diff --git a/.changeset/config.json b/.changeset/config.json index 363ee484fcd..91294d70aac 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -7,9 +7,9 @@ "commit": false, "linked": [], "access": "public", - "baseBranch": "main", + "baseBranch": "origin/main", "updateInternalDependencies": "patch", - "ignore": ["starlight-docs", "@example/*", "docs-i18n-tracker"], + "ignore": ["starlight-docs", "@example/*", "starlight-file-icons-generator", "@e2e/*"], "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { "onlyUpdatePeerDependentsWhenOutOfRange": true } diff --git a/.changeset/fifty-meals-explain.md b/.changeset/fifty-meals-explain.md deleted file mode 100644 index 01a52c762a7..00000000000 --- a/.changeset/fifty-meals-explain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@astrojs/starlight': patch ---- - -Update bundled version of `@astrojs/mdx` to v1.1.0 diff --git a/.changeset/hip-experts-crash.md b/.changeset/hip-experts-crash.md new file mode 100644 index 00000000000..56de22112e8 --- /dev/null +++ b/.changeset/hip-experts-crash.md @@ -0,0 +1,5 @@ +--- +'@astrojs/starlight': patch +--- + +Fixes an issue using components containing scripts inside Starlight’s steps component in versions of Astro >= 5.16.9 diff --git a/.changeset/tall-seals-act.md b/.changeset/tall-seals-act.md deleted file mode 100644 index 69c0d7884d3..00000000000 --- a/.changeset/tall-seals-act.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@astrojs/starlight": patch ---- - -Improve Arabic UI translations diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index f3d56a54842..207f5d818bb 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,7 +1,8 @@ # Based on https://github.com/withastro/astro/blob/main/.devcontainer/Dockerfile FROM mcr.microsoft.com/devcontainers/javascript-node:0-18 -# Install latest pnpm -RUN npm install -g pnpm +# We uninstall pnpm here, since we enable the corepack version in the postCreateCommand +# This ensures we respect the "packageManager" version in package.json +RUN npm uninstall -g pnpm COPY welcome-message.txt /usr/local/etc/vscode-dev-containers/first-run-notice.txt \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 2b192ec94fd..477989322e4 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,7 +3,7 @@ "build": { "dockerfile": "Dockerfile" }, - "postCreateCommand": "pnpm install", + "postCreateCommand": "sudo corepack enable pnpm && pnpm config set store-dir /home/node/.pnpm-store && PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 pnpm install", "waitFor": "postCreateCommand", "customizations": { "codespaces": { diff --git a/.github/DISCUSSION_TEMPLATE/docs-suggestions.yml b/.github/DISCUSSION_TEMPLATE/docs-suggestions.yml new file mode 100644 index 00000000000..4c0494e4a11 --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/docs-suggestions.yml @@ -0,0 +1,39 @@ +body: + - type: markdown + attributes: + value: | + Thank you for getting in touch! Please fill out this form as completely as possible. + + Want to report a problem with the Starlight docs? [Open a new issue](https://github.com/withastro/starlight/issues/new?assignees=&labels=&projects=&template=---02-docs-issue.yml) + Want to chat before posting? [Join us in the `#starlight` channel on Discord](https://astro.build/chat) + - type: textarea + id: summary + attributes: + label: What is your idea? + description: A brief, one or two sentence description of your idea for how to improve the Starlight docs. + validations: + required: true + - type: textarea + id: background + attributes: + label: Why is this important? + description: Explain why this idea is valuable. What problems would it solve? Which users would it help? + validations: + required: true + - type: textarea + id: prior-art + attributes: + label: How does your idea relate to existing docs content? + description: Are there specific pages you would like to change? Or existing pages that are related to your proposal? + placeholder: | + - Example + - Example + - Example + - type: checkboxes + id: will-pr + attributes: + label: Participation + description: Let us know if your interested in contributing this feature yourself. + options: + - label: I am willing to submit a pull request for this feature. + required: false diff --git a/.github/ISSUE_TEMPLATE/---02-feature-request.yml b/.github/DISCUSSION_TEMPLATE/feature-requests.yml similarity index 92% rename from .github/ISSUE_TEMPLATE/---02-feature-request.yml rename to .github/DISCUSSION_TEMPLATE/feature-requests.yml index 59e98328f57..54fdcf82ed3 100644 --- a/.github/ISSUE_TEMPLATE/---02-feature-request.yml +++ b/.github/DISCUSSION_TEMPLATE/feature-requests.yml @@ -1,7 +1,3 @@ -name: Feature Request -description: Suggest an improvement you’d like to see added to Starlight -labels: [] -assignees: [] body: - type: markdown attributes: @@ -46,5 +42,5 @@ body: label: Participation description: Let us know if your interested in contributing this feature yourself. options: - - label: I am willing to submit a pull request for this issue. + - label: I am willing to submit a pull request for this feature. required: false diff --git a/.github/ISSUE_TEMPLATE/---02-docs-issue.yml b/.github/ISSUE_TEMPLATE/---02-docs-issue.yml new file mode 100644 index 00000000000..c49db9c7db0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---02-docs-issue.yml @@ -0,0 +1,45 @@ +name: "\U0001F4DA Docs Issue" +description: Report an issue with the Starlight documentation +labels: [] +assignees: [] +body: + - type: markdown + attributes: + value: | + Thank you for taking the time to let us know something is wrong! Please fill out this form as completely as possible. + - type: input + id: docs-page + attributes: + label: What page of the docs did you find an issue on? + description: If this issue applies to multiple pages, include additional pages in your bug description. + placeholder: https://starlight.astro.build/... + validations: + required: true + - type: textarea + id: bug-description + attributes: + label: Describe the issue + description: A clear and concise description of what the issue is. + validations: + required: true + - type: input + id: os + attributes: + label: What operating system are you using? + placeholder: Mac, Windows, Linux + validations: + required: true + - type: input + id: browser + attributes: + label: What browser are you using? + placeholder: Chrome, Firefox, Safari + validations: + required: true + - type: checkboxes + id: will-pr + attributes: + label: Participation + options: + - label: I am willing to submit a pull request for this issue. + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 92864ff9433..4a25318af8e 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,8 @@ blank_issues_enabled: false contact_links: + - name: 💡 Feature Request + url: https://github.com/withastro/starlight/discussions/new?category=feature-requests + about: Suggest an improvement you’d like to see added to Starlight - name: 👾 Chat url: https://astro.build/chat about: Our Discord server is active, come join us! diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 9e046d1fd7b..a64e9d947a5 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,23 +1,15 @@ -#### What kind of changes does this PR include? - - - -- Minor content fixes (broken links, typos, etc.) -- Changes or translations of Starlight docs site content -- Changes to Starlight code -- Something else! - #### Description + + + + - Closes # - What does this PR change? Give us a brief description. - Did you change something visual? A before/after screenshot can be helpful. - - - "1 broken link" / "2 broken links" - * - If `count` is undefined, it capitalizes the first letter. - * - Example: "broken link(s)" --> "Broken link" - * - * Supported template syntax: - * - Use `(s)` to add a plural-only "s", e.g. "broken link(s)" - * - Use `|` to provide separate templates, e.g. "issue was|issues were" - * - * @param {number} count - * @param {string} template - */ -export function formatCount(count, template) { - /** @param {string} text */ - const wrapWithCount = (text) => { - // If no count was given, we're outputting a single issue in annotations, - // so omit count and capitalize the first letter of the issue type description - if (count === undefined) return text[0].toUpperCase() + text.slice(1); - - // Otherwise, prefix the issue type description with count - return `${count} ${text}`; - }; - - const usePlural = count !== undefined && count !== 1; - const templateParts = template.split('|'); - const usedTemplate = templateParts.length === 2 ? templateParts[usePlural ? 1 : 0] : template; - return wrapWithCount(usedTemplate.replace(/\(s\)/g, usePlural ? 's' : '')); -} - -export default { - debug, - warning, - error, - dedentMd, - formatCount, - isCi, -}; diff --git a/docs-i18n-tracker/lib/translation-status/builder.ts b/docs-i18n-tracker/lib/translation-status/builder.ts deleted file mode 100644 index 630c58dbff1..00000000000 --- a/docs-i18n-tracker/lib/translation-status/builder.ts +++ /dev/null @@ -1,463 +0,0 @@ -import dedent from 'dedent-js'; -import glob from 'fast-glob'; -import fs from 'fs'; -import { escape } from 'html-escaper'; -import os from 'os'; -import path from 'path'; -import simpleGit from 'simple-git'; -import { fileURLToPath } from 'url'; -import { githubGet } from '../github-get.mjs'; -import output from '../output.mjs'; -import type { PageData, PageIndex, PageTranslationStatus } from './types'; - -export const COMMIT_IGNORE = /(en-only|typo|broken link|i18nReady|i18nIgnore)/i; - -interface PullRequest { - html_url: string; - title: string; - labels: { - name: string; - }[]; -} - -/** - * Uses the git commit history to build an HTML-based overview of - * the current Astro Docs translation status. - * - * This code is designed to be run on every push to the `main` branch. - */ -export class TranslationStatusBuilder { - constructor(config: { - pageSourceDir: string; - /** - * Full path & file name of the HTML file that the translation status should be written to. - * If the parent path does not exist yet, it will be created. - * */ - htmlOutputFilePath: string; - sourceLanguage: string; - targetLanguages: string[]; - languageLabels: { [key: string]: string }; - githubRepo: string; - githubToken?: string | undefined; - }) { - this.pageSourceDir = config.pageSourceDir; - this.htmlOutputFilePath = path.resolve(config.htmlOutputFilePath); - this.sourceLanguage = config.sourceLanguage; - this.targetLanguages = config.targetLanguages; - this.languageLabels = config.languageLabels; - this.githubRepo = config.githubRepo; - this.githubToken = config.githubToken ?? ''; - this.git = simpleGit({ - maxConcurrentProcesses: Math.max(2, Math.min(32, os.cpus().length)), - }); - } - - readonly pageSourceDir; - readonly htmlOutputFilePath; - readonly sourceLanguage; - readonly targetLanguages; - readonly languageLabels; - readonly githubRepo; - readonly githubToken; - readonly git; - - async run() { - // Before we start, validate that this is not a shallow clone of the repo - const isShallowRepo = await this.git.revparse(['--is-shallow-repository']); - if (isShallowRepo !== 'false') { - output.error(dedent`This script cannot operate on a shallow clone of the git repository. - Please add the checkout setting "fetch-depth: 0" to your GitHub workflow: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - `); - process.exit(1); - } - - output.debug(`*** Building translation status`); - - // Ensure that the output directory exists before continuing - output.debug(`- Output file path: ${this.htmlOutputFilePath}`); - const outputDir = path.dirname(this.htmlOutputFilePath); - if (!fs.existsSync(outputDir)) { - fs.mkdirSync(outputDir, { recursive: true }); - } - - // Create an index of all Markdown/MDX pages grouped by language, - // with information about the last minor & major commit per page - output.debug(`- Generating page index...`); - const pages = await this.createPageIndex(); - - // Determine translation status by source page - const statusByPage = this.getTranslationStatusByPage(pages); - - // Fetch all pull requests - const pullRequests = await this.getPullRequests(); - - // Render a human-friendly summary - output.debug(`- Building HTML file...`); - const html = this.renderHtmlStatusPage(statusByPage, pullRequests); - - // Write HTML output to file - fs.writeFileSync(this.htmlOutputFilePath, html); - - output.debug(''); - output.debug('*** Success!'); - output.debug(''); - } - - /** Get all pull requests with the `i18n` tag */ - async getPullRequests() { - const pullRequests: PullRequest[] = await githubGet({ - url: `https://api.github.com/repos/${this.githubRepo}/pulls?state=open&per_page=100`, - githubToken: this.githubToken, - }); - - return pullRequests.filter((pr) => pr.labels.find((label) => label.name === 'i18n')); - } - - async createPageIndex(): Promise { - // Initialize a new page index with a stable key order - const pages: PageIndex = { - [this.sourceLanguage]: {}, - }; - this.targetLanguages.forEach((lang) => (pages[lang.toLowerCase()] = {})); - // Enumerate all markdown pages with supported languages in pageSourceDir, - // retrieve their page data and update them - const pagePaths = await glob(`**/*.{md,mdx}`, { - cwd: this.pageSourceDir, - }); - const updatedPages = await Promise.all( - pagePaths.sort().map(async (pagePath) => { - const pathParts = pagePath.split('/'); - const isLanguageSubpathIncluded = this.targetLanguages - .map((el) => el.toLowerCase()) - .includes(pathParts[0]!); - - // If the first path of a file does not belong to a language, it will be by default a page of the original language set. - const lang = isLanguageSubpathIncluded ? pathParts[0] : this.sourceLanguage; - const subpath = pathParts.splice(1).join('/'); - - // Create or update page data for the page - return { - lang, - subpath: isLanguageSubpathIncluded ? subpath : pagePath, - pageData: await this.getSinglePageData(pagePath), - }; - }) - ); - - // Write the updated pages to the index - updatedPages.forEach((page) => { - if (!page) return; - const { lang, subpath, pageData } = page; - pages[lang!]![subpath] = pageData; - }); - - return pages; - } - - /** - * Processes the markdown page located in the pageSourceDir subpath `pagePath` - * and creates a new page data object based on its frontmatter and git history. - */ - async getSinglePageData(pagePath: string): Promise { - const fullFilePath = `${this.pageSourceDir}/${pagePath}`; - - // Retrieve git history for the current page - const gitHistory = await this.getGitHistory(fullFilePath); - - return { - lastChange: gitHistory.lastCommitDate, - lastCommitMsg: gitHistory.lastCommitMessage, - lastMajorChange: gitHistory.lastMajorCommitDate, - lastMajorCommitMsg: gitHistory.lastMajorCommitMessage, - }; - } - - async getGitHistory(filePath: string) { - const gitLog = await this.git.log({ - file: filePath, - strictDate: true, - }); - - const lastCommit = gitLog.latest; - if (!lastCommit) { - throw new Error(dedent`Failed to retrieve last commit information for file - "${filePath}". Your working copy should not contain uncommitted new pages - when running this script.`); - } - - // Attempt to find the last "major" commit, ignoring any commits that - // usually do not require translations to be updated - const lastMajorCommit = - gitLog.all.find((logEntry) => { - return !logEntry.message.match(COMMIT_IGNORE); - }) || lastCommit; - - return { - lastCommitMessage: lastCommit.message, - lastCommitDate: toUtcString(lastCommit.date), - lastMajorCommitMessage: lastMajorCommit.message, - lastMajorCommitDate: toUtcString(lastMajorCommit.date), - }; - } - - getTranslationStatusByPage(pages: PageIndex): PageTranslationStatus[] { - const sourcePages = pages[this.sourceLanguage]; - const arrContent: PageTranslationStatus[] = []; - - Object.keys(sourcePages!).forEach((subpath) => { - const sourcePage = sourcePages![subpath]!; - - const content: PageTranslationStatus = { - subpath, - sourcePage, - githubUrl: this.getPageUrl({ lang: this.sourceLanguage, subpath }), - translations: {}, - }; - - this.targetLanguages.forEach((lang) => { - const i18nPage = pages[lang.toLowerCase()]![subpath]!; - content.translations[lang] = { - page: i18nPage, - isMissing: !i18nPage, - isOutdated: i18nPage && sourcePage.lastMajorChange > i18nPage.lastMajorChange, - githubUrl: this.getPageUrl({ lang, subpath }), - sourceHistoryUrl: this.getPageUrl({ - lang: 'en', - subpath, - type: 'commits', - query: i18nPage ? `?since=${i18nPage.lastMajorChange}` : '', - }), - }; - }); - - arrContent.push(content); - }); - - return arrContent; - } - - getPageUrl({ - type = 'blob', - refName = 'main', - lang, - subpath, - query = '', - }: { - type?: string; - refName?: string; - lang: string; - subpath: string; - query?: string; - }) { - const noDotSrcDir = this.pageSourceDir.replace(/^\.+\//, ''); - const isSrcLang = lang === this.sourceLanguage; - return `https://github.com/${this.githubRepo}/${type}/${refName}/${noDotSrcDir}${ - isSrcLang ? '' : `/${lang}` - }/${subpath}${query}`; - } - - /** - * Renders the primary HTML output of this script by loading a template from disk, - * rendering the individual views to HTML, and inserting them into the template. - */ - renderHtmlStatusPage(statusByPage: PageTranslationStatus[], prs: PullRequest[]) { - // Load HTML template - const templateFilePath = path.join( - path.dirname(fileURLToPath(import.meta.url)), - 'template.html' - ); - const html = fs.readFileSync(templateFilePath, { encoding: 'utf8' }); - - // Replace placeholders in the template with the rendered views - // and return the resulting HTML page - return html - .replace( - '', - this.renderTranslationStatusByLanguage(statusByPage) - ) - .replace('', this.renderTranslationNeedsReview(prs)) - .replace( - '', - this.renderTranslationStatusByPage(statusByPage) - ); - } - - renderTranslationStatusByLanguage(statusByPage: PageTranslationStatus[]) { - const lines: string[] = []; - - this.targetLanguages.forEach((lang) => { - const missing = statusByPage.filter((content) => content.translations[lang]!.isMissing); - const outdated = statusByPage.filter((content) => content.translations[lang]!.isOutdated); - lines.push('
'); - lines.push( - `` + - `${this.languageLabels[lang]} (${lang})` + - `
` + - `` + - `${statusByPage.length - outdated.length - missing.length} done, ` + - `${outdated.length} need${outdated.length === 1 ? 's' : ''} updating, ` + - `${missing.length} missing` + - `` + - '
' + - this.renderProgressBar(statusByPage.length, outdated.length, missing.length) + - `
` - ); - lines.push(``); - if (outdated.length > 0) { - lines.push(`
🔄  Needs updating
`); - lines.push(`
    `); - lines.push( - ...outdated.map( - (content) => - `
  • ` + - `${this.renderLink(content.githubUrl, content.subpath)} ` + - `(${this.renderLink( - content.translations[lang]!.githubUrl, - 'outdated translation' - )}, ${this.renderLink( - content.translations[lang]!.sourceHistoryUrl, - 'source change history' - )})` + - `
  • ` - ) - ); - lines.push(`
`); - } - if (missing.length > 0) { - lines.push(`
❌  Missing
`); - lines.push(`
    `); - lines.push( - ...missing.map( - (content) => - `
  • ` + - `${this.renderLink( - content.githubUrl, - content.subpath - )}   ${this.renderCreatePageButton(lang, content.subpath)}` + - `
  • ` - ) - ); - lines.push(`
`); - } - lines.push(`
`); - lines.push(``); - }); - - return lines.join('\n'); - } - - renderTranslationNeedsReview(prs: PullRequest[]) { - const lines: string[] = []; - - if (prs.length > 0) { - lines.push(``); - } - lines.push(``); - - return lines.join('\n'); - } - - renderTranslationStatusByPage(statusByPage: PageTranslationStatus[]) { - const lines: string[] = []; - - lines.push('
'); - lines.push(''); - - lines.push(''); - lines.push(['Page', ...this.targetLanguages].map((col) => ``).join('')); - lines.push(''); - - lines.push(''); - const spacer = `\n${this.targetLanguages - .map(() => ``) - .join('\n')}\n`; - lines.push(spacer); - statusByPage.forEach((content) => { - const cols = []; - cols.push(this.renderLink(content.githubUrl, content.subpath)); - cols.push( - ...this.targetLanguages.map((lang) => { - const translation = content.translations[lang]!; - if (translation.isMissing) - return ``; - if (translation.isOutdated) - return ``; - return ``; - }) - ); - lines.push(`\n${cols.map((col) => ``).join('\n')}\n`); - }); - lines.push(spacer); - lines.push(''); - - lines.push('
${col}
${col}
'); - - lines.push(`\n❌ Missing   🔄 Needs updating   ✔ Completed`); - lines.push('
'); - - return lines.join('\n'); - } - - /** - * Render a link to a pre-filled GitHub UI for creating a new file. - * - * @param lang Language tag to create page for - * @param filename Subpath of page to create - */ - renderCreatePageButton(lang: string, filename: string): string { - // We include `lang` twice because GitHub eats the last path segment when setting filename. - const createUrl = new URL( - `https://github.com/${this.githubRepo}/new/main/docs/src/content/docs` - ); - createUrl.searchParams.set('filename', lang + '/' + filename); - createUrl.searchParams.set('value', '---\ntitle:\ndescription:\n---\n'); - return this.renderLink(createUrl.href, `Create\xa0page\xa0+`, 'create-button'); - } - - /** - * Render a progress bar with emoji. - */ - renderProgressBar( - total: number, - outdated: number, - missing: number, - { size = 20 }: { size?: number } = {} - ) { - const outdatedLength = Math.round((outdated / total) * size); - const missingLength = Math.round((missing / total) * size); - const doneLength = size - outdatedLength - missingLength; - return ( - '' - ); - } - - renderLink(href: string, text: string, className = ''): string { - return `${escape(text)}`; - } -} - -function toUtcString(date: string) { - return new Date(date).toISOString(); -} diff --git a/docs-i18n-tracker/lib/translation-status/template.html b/docs-i18n-tracker/lib/translation-status/template.html deleted file mode 100644 index 965068e2416..00000000000 --- a/docs-i18n-tracker/lib/translation-status/template.html +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - - - Starlight Docs Translation Status - - - - - - - - - - - -
-
-

Starlight Docs Translation Status

- -

- If you're interested in helping us translate - starlight.astro.build into one of the - languages listed below, you've come to the right place! This auto-updating page always - lists all the content that could use your help right now. -

- -

- Before starting a new translation, be sure to check the - existing Starlight PRs to see if this page has already been - translated, and consider reviewing any open PRs in your language! -

- -

- Translation progress by language -

- - -

- Translations that need reviews -

- - -

- Translation status by content -

-
- - -
- - diff --git a/docs-i18n-tracker/lib/translation-status/types.ts b/docs-i18n-tracker/lib/translation-status/types.ts deleted file mode 100644 index 3a1a0b1cd4c..00000000000 --- a/docs-i18n-tracker/lib/translation-status/types.ts +++ /dev/null @@ -1,27 +0,0 @@ -export type PageIndex = { - [language: string]: { - [pagePath: string]: PageData; - }; -}; - -export type PageData = { - lastChange: string; - lastCommitMsg: string; - lastMajorChange: string; - lastMajorCommitMsg: string; -}; - -export type PageTranslationStatus = { - subpath: string; - sourcePage: PageData; - githubUrl: string; - translations: { - [language: string]: { - page: PageData; - isMissing: boolean; - isOutdated: boolean; - githubUrl: string; - sourceHistoryUrl: string; - }; - }; -}; diff --git a/docs-i18n-tracker/package.json b/docs-i18n-tracker/package.json deleted file mode 100644 index 6320ec6a180..00000000000 --- a/docs-i18n-tracker/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "docs-i18n-tracker", - "private": true, - "version": "1.0.0", - "description": "A single-page dashboard that tracks translation status across Starlight docs pages", - "scripts": { - "build": "tsm --require=./lib/filter-warnings.cjs ./build.ts" - }, - "devDependencies": { - "@types/html-escaper": "^3.0.0", - "dedent-js": "^1.0.1", - "fast-glob": "^3.2.12", - "html-escaper": "^3.0.3", - "kleur": "^4.1.5", - "node-fetch": "^3.3.1", - "p-retry": "^5.1.2", - "simple-git": "^3.19.0", - "tsm": "^2.3.0" - } -} diff --git a/docs/.pa11yci b/docs/.pa11yci deleted file mode 100644 index 76751c3ea3d..00000000000 --- a/docs/.pa11yci +++ /dev/null @@ -1,7 +0,0 @@ -{ - "defaults": { - "runners": [ - "axe" - ] - } -} diff --git a/docs/.vscode/extensions.json b/docs/.vscode/extensions.json deleted file mode 100644 index 22a15055d63..00000000000 --- a/docs/.vscode/extensions.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "recommendations": ["astro-build.astro-vscode"], - "unwantedRecommendations": [] -} diff --git a/docs/__a11y__/docs.test.ts b/docs/__a11y__/docs.test.ts new file mode 100644 index 00000000000..32713e76fb8 --- /dev/null +++ b/docs/__a11y__/docs.test.ts @@ -0,0 +1,22 @@ +import { expect, test } from './test-utils'; + +test('does not report accessibility violations on the docs site', async ({ docsSite }) => { + let violationsCount = 0; + + const urls = await docsSite.getAllUrls(); + + for (const url of urls) { + const violations = await docsSite.testPage(url); + + if (violations.length > 0) { + violationsCount += violations.length; + } + + await docsSite.reportPageViolations(violations); + } + + expect( + violationsCount, + `Found ${violationsCount} accessibility violations. Check the errors above for more details.` + ).toBe(0); +}); diff --git a/docs/__a11y__/test-utils.ts b/docs/__a11y__/test-utils.ts new file mode 100644 index 00000000000..60a1941744e --- /dev/null +++ b/docs/__a11y__/test-utils.ts @@ -0,0 +1,181 @@ +import { test as baseTest, type Page } from '@playwright/test'; +import { + DefaultTerminalReporter, + getViolations, + injectAxe, + reportViolations, +} from 'axe-playwright'; +import Sitemapper from 'sitemapper'; + +// We use the Lunaria config to get the list of languages rather than the Astro config as importing +// the latter does not play well with Playwright. +import lunariaConfig from '../lunaria.config.json' assert { type: 'json' }; + +export { expect, type Locator } from '@playwright/test'; + +const config: Config = { + axe: { + // https://www.deque.com/axe/core-documentation/api-documentation/#axecore-tags + runOnly: { + type: 'tag', + values: ['wcag2a', 'wcag21a', 'wcag2aa', 'wcag21aa', 'wcag22aa', 'best-practice'], + }, + }, + // i18n specific configuration. + i18n: { + // A list of slugs to exclude from the sitemap for the default locale. + // By default, all slugs for the default locale are included. + exclude: [ + 'components/using-components', + 'getting-started', + 'guides/customization', + 'guides/i18n', + 'guides/overriding-components', + 'guides/pages', + 'guides/project-structure', + 'guides/route-data', + 'guides/site-search', + 'manual-setup', + 'reference/frontmatter', + 'reference/overrides', + 'reference/plugins', + 'reference/route-data', + ], + // Locale-specific included slugs (non-default locale slugs are excluded by default). + locales: { + // N.B. If adding more locales here, also update the changed files filters in + // `.github/workflows/ci.yml` to ensure tests run when files for those locales change. + ja: ['guides/route-data', 'reference/frontmatter'], + }, + }, + // A list of violation to ignore. + ignore: [{ id: 'landmark-unique', nodeMatcher: landmarkUniqueNodeMatcher }], + sitemap: { + url: 'http://localhost:4321/sitemap-index.xml', + replace: { + query: 'https://starlight.astro.build', + value: 'http://localhost:4321', + }, + }, +}; + +process.env.ASTRO_TELEMETRY_DISABLED = 'true'; +process.env.ASTRO_DISABLE_UPDATE_CHECK = 'true'; + +const locales = lunariaConfig.locales.map((locale) => locale.lang); + +export const test = baseTest.extend<{ + docsSite: DocsSite; +}>({ + docsSite: async ({ page }, use) => use(new DocsSite(page)), +}); + +// A Playwright test fixture accessible from within all tests. +class DocsSite { + constructor(private readonly page: Page) {} + + async getAllUrls() { + const sitemap = new Sitemapper({ url: config.sitemap.url }); + const { sites } = await sitemap.fetch(); + + if (sites.length === 0) { + throw new Error('No URLs found in sitemap.'); + } + + const urls: string[] = []; + + for (const site of sites) { + const slug = site.replace(config.sitemap.replace.query, ''); + const url = config.sitemap.replace.value + slug; + + // Default locale + if (!locales.some((locale) => slug.startsWith(`/${locale}/`))) { + // Skip default locale excluded slugs + if (config.i18n.exclude.some((excludedSlug) => slug.endsWith(`/${excludedSlug}/`))) + continue; + } else { + // Get locale-specific config + const locale = slug.split('/')[1]!; + const localeConfig = config.i18n.locales[locale]; + // Skip non-configured locales + if (!localeConfig) continue; + // Skip locale-specific non-included slugs + if (!localeConfig.some((includedSlug) => slug.endsWith(`/${includedSlug}/`))) continue; + } + + urls.push(url); + } + + return urls; + } + + async testPage(url: string) { + await this.page.goto(url); + await injectAxe(this.page); + await this.page.waitForLoadState('networkidle'); + const violations = await getViolations(this.page, undefined, config.axe); + return this.#filterViolations(violations); + } + + async reportPageViolations(violations: Awaited>) { + const url = this.page.url().replace(config.sitemap.replace.value, ''); + + if (violations.length > 0) { + console.error(`> Found ${violations.length} violations on ${url}\n`); + await reportViolations(violations, new DefaultTerminalReporter(true, true, false)); + console.error('\n'); + } else { + console.log(`> Found no violations on ${url}`); + } + } + + #filterViolations(violations: Awaited>) { + return violations.filter((violation) => { + return !config.ignore.some((ignore) => { + if (typeof ignore === 'string') return violation.id === ignore; + if (violation.id !== ignore.id) return false; + if (!ignore.nodeMatcher) return true; + return !violation.nodes.some(ignore.nodeMatcher); + }); + }); + } +} + +function landmarkUniqueNodeMatcher(node: ViolationNode) { + /** + * Ignore the `landmark-unique` violation only if the node HTML is an aside. + * + * The best action to fix this violation would be to remove the landmark altogether as it's not + * necessary in this case and switch to the `note` role. Although, this is not possible at the + * moment due to an issue with NVDA not announcing it and also skipping the associated label for + * a role not supported. + * + * @see https://github.com/nvaccess/nvda/issues/10439 + * @see https://github.com/withastro/starlight/pull/2503 + */ + return !/^]* class="starlight-aside[^>]*>$/.test(node.html); +} + +interface Config { + axe: Parameters[2]; + i18n: { exclude: string[]; locales: Record }; + ignore: Array< + | string + | { + id: string; + // A function called for each node to evaluate if it should be ignored or not. + // Return `true` if the node should be considered for the violation, `false` otherwise. + nodeMatcher?: (node: ViolationNode) => boolean; + } + >; + sitemap: { + url: string; + replace: { + query: string; + value: string; + }; + }; +} + +type Violations = Awaited>; +type ViolationNode = Violations[number]['nodes'][number]; diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 72141ee858b..a059280810c 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -1,5 +1,8 @@ +// @ts-check import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; +import starlightLinksValidator from 'starlight-links-validator'; +import markdocGrammar from './grammars/markdoc.tmLanguage.json'; export const locales = { root: { label: 'English', lang: 'en' }, @@ -9,15 +12,27 @@ export const locales = { fr: { label: 'Français', lang: 'fr' }, it: { label: 'Italiano', lang: 'it' }, id: { label: 'Bahasa Indonesia', lang: 'id' }, - zh: { label: '简体中文', lang: 'zh' }, + 'zh-cn': { label: '简体中文', lang: 'zh-CN' }, 'pt-br': { label: 'Português do Brasil', lang: 'pt-BR' }, + 'pt-pt': { label: 'Português', lang: 'pt-PT' }, ko: { label: '한국어', lang: 'ko' }, + tr: { label: 'Türkçe', lang: 'tr' }, + ru: { label: 'Русский', lang: 'ru' }, + hi: { label: 'हिंदी', lang: 'hi' }, + da: { label: 'Dansk', lang: 'da' }, + uk: { label: 'Українська', lang: 'uk' }, }; -const site = 'https://starlight.astro.build/'; +/* https://docs.netlify.com/configure-builds/environment-variables/#read-only-variables */ +const NETLIFY_PREVIEW_SITE = process.env.CONTEXT !== 'production' && process.env.DEPLOY_PRIME_URL; + +const site = NETLIFY_PREVIEW_SITE || 'https://starlight.astro.build/'; +const ogUrl = new URL('og.jpg?v=1', site).href; +const ogImageAlt = 'Make your docs shine with Starlight'; export default defineConfig({ site, + trailingSlash: 'always', integrations: [ starlight({ title: 'Starlight', @@ -26,13 +41,14 @@ export default defineConfig({ dark: '/src/assets/logo-dark.svg', replacesTitle: true, }, + lastUpdated: true, editLink: { baseUrl: 'https://github.com/withastro/starlight/edit/main/docs/', }, - social: { - github: 'https://github.com/withastro/starlight', - discord: 'https://astro.build/chat', - }, + social: [ + { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' }, + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + ], head: [ { tag: 'script', @@ -44,14 +60,14 @@ export default defineConfig({ }, { tag: 'meta', - attrs: { property: 'og:image', content: site + 'og.jpg?v=1' }, + attrs: { property: 'og:image', content: ogUrl }, }, { tag: 'meta', - attrs: { property: 'twitter:image', content: site + 'og.jpg?v=1' }, + attrs: { property: 'og:image:alt', content: ogImageAlt }, }, ], - customCss: process.env.NO_GRADIENTS ? [] : ['./src/assets/landing.css'], + customCss: ['./src/assets/landing.css'], locales, sidebar: [ { @@ -63,67 +79,36 @@ export default defineConfig({ fr: 'Commencez ici', it: 'Inizia qui', id: 'Mulai dari sini', - zh: '从这里开始', + 'zh-CN': '从这里开始', 'pt-BR': 'Comece Aqui', - ko: '여기서부터', + 'pt-PT': 'Comece Aqui', + ko: '시작 안내', + tr: 'Buradan Başlayın', + ru: 'Первые шаги', + hi: 'यहाँ से शुरू करे', + uk: 'Почніть звідси', }, items: [ - { - label: 'Getting Started', - link: 'getting-started', - translations: { - de: 'Erste Schritte', - es: 'Empezando', - ja: '入門', - fr: 'Mise en route', - it: 'Iniziamo', - id: 'Memulai', - zh: '开始使用', - 'pt-BR': 'Introdução', - ko: '시작하기', - }, - }, - { - label: 'Manual Setup', - link: 'manual-setup', - translations: { - de: 'Manuelle Einrichtung', - es: 'Configuración Manual', - ja: '手動セットアップ', - fr: 'Installation manuelle', - // it: 'Manual Setup', - id: 'Instalasi Manual', - zh: '手动配置', - 'pt-BR': 'Instalação Manual', - ko: '수동으로 설정하기', - }, - }, + 'getting-started', + 'manual-setup', { label: 'Environmental Impact', - link: 'environmental-impact', + slug: 'environmental-impact', translations: { - // de: '', + de: 'Umweltbelastung', es: 'Documentación ecológica', ja: '環境への負荷', fr: 'Impact environnemental', it: 'Impatto ambientale', id: 'Dampak terhadap lingkungan', - zh: '环境影响', + 'zh-CN': '环境影响', 'pt-BR': 'Impacto Ambiental', + 'pt-PT': 'Impacto Ambiental', ko: '환경적 영향', - }, - }, - { - label: 'Showcase', - link: 'showcase', - translations: { - // de: '', - // es: '', - ja: 'ショーケース', - fr: 'Vitrine', - // it: '', - id: 'Galeri', - ko: '쇼케이스', + tr: 'Çevre Etkisi', + ru: 'Влияние на окружающую среду', + hi: 'पर्यावरणीय प्रभाव', + uk: 'Вплив на довкілля', }, }, ], @@ -136,30 +121,75 @@ export default defineConfig({ ja: 'ガイド', fr: 'Guides', it: 'Guide', - id: 'Petunjuk Penggunaan', - zh: '指南', + id: 'Panduan', + 'zh-CN': '指南', 'pt-BR': 'Guias', + 'pt-PT': 'Guias', ko: '가이드', + tr: 'Rehber', + ru: 'Руководства', + hi: 'गाइड', + uk: 'Ґайди', }, autogenerate: { directory: 'guides' }, }, + { + label: 'Components', + translations: { + de: 'Komponenten', + fr: 'Composants', + ru: 'Компоненты', + ko: '컴포넌트', + ja: 'コンポーネント', + 'zh-CN': '组件', + uk: 'Компоненти', + }, + autogenerate: { directory: 'components' }, + }, { label: 'Reference', translations: { - de: 'Referenz', + de: 'Referenzen', es: 'Referencias', ja: 'リファレンス', fr: 'Référence', it: 'Riferimenti', id: 'Referensi', - zh: '参考', + 'zh-CN': '参考', 'pt-BR': 'Referência', ko: '참조', + tr: 'Referanslar', + ru: 'Справочник', + hi: 'संदर्भ', + uk: 'Довідник', }, autogenerate: { directory: 'reference' }, }, + { + label: 'Resources', + translations: { + de: 'Ressourcen', + 'zh-CN': '资源', + fr: 'Ressources', + 'pt-BR': 'Recursos', + 'pt-PT': 'Recursos', + ja: 'リソース', + ru: 'Ресурсы', + ko: '리소스', + uk: 'Ресурси', + }, + autogenerate: { directory: 'resources' }, + }, ], - lastUpdated: true, + expressiveCode: { shiki: { langs: [markdocGrammar] } }, + plugins: process.env.CHECK_LINKS + ? [ + starlightLinksValidator({ + errorOnFallbackPages: false, + errorOnInconsistentLocale: true, + }), + ] + : [], }), ], }); diff --git a/docs/grammars/README.md b/docs/grammars/README.md new file mode 100644 index 00000000000..8a74cb94474 --- /dev/null +++ b/docs/grammars/README.md @@ -0,0 +1,34 @@ +# Starlight Docs Grammars + +This directory contains additional grammars for the Starlight documentation website. + +## Grammars + +The following additional grammars are generated and available for use: + +- [Markdoc](https://github.com/markdoc/language-server) + +## Usage + +To generate the grammars from their source files, run: + +```sh +pnpm grammars +``` + +To include the grammars in the Starlight documentation website, update the `expressiveCode.shiki.langs` array in the `astro.config.mjs` file: + +```diff +starlight({ + expressiveCode: { + shiki: { + langs: [ + JSON.parse( + fs.readFileSync('./grammars/existing.tmLanguage.json', 'utf-8'), ++ fs.readFileSync('./grammars/new.tmLanguage.json', 'utf-8'), + ), + ], + }, + }, +}); +``` diff --git a/docs/grammars/generate.mjs b/docs/grammars/generate.mjs new file mode 100644 index 00000000000..aee8d7096c1 --- /dev/null +++ b/docs/grammars/generate.mjs @@ -0,0 +1,74 @@ +// @ts-check + +import fs from 'node:fs/promises'; + +const markdown = { + repo: 'shikijs/textmate-grammars-themes', + tmLanguagePath: 'packages/tm-grammars/grammars/markdown.json', +}; + +const markdoc = { + repo: 'markdoc/language-server', + // We don't need the Markdoc grammar, only the Markdoc Markdown grammar. + // tmLanguagePath: 'syntaxes/markdoc.tmLanguage.json', + markdownTmLanguagePath: 'syntaxes/markdoc.markdown.tmLanguage.json', +}; + +/** + * Download a TextMate grammar file from a GitHub repository. + * @param {string} repo + * @param {string} path + */ +async function fetchTmLanguage(repo, path) { + const url = `https://raw.githubusercontent.com/${repo}/main/${path}`; + const response = await fetch(url); + const data = await response.json(); + return data; +} + +// Download the TextMate grammar files for Markdown. +const markdownTmLanguage = await fetchTmLanguage(markdown.repo, markdown.tmLanguagePath); + +// Download the TextMate grammar files for Markdoc Markdown. +const markdocMarkdownTmLanguage = await fetchTmLanguage( + markdoc.repo, + markdoc.markdownTmLanguagePath +); + +// Reference: https://macromates.com/manual/en/language_grammars + +// Update the name and scope name for the Markdoc grammar. +markdownTmLanguage.name = 'markdoc'; +markdownTmLanguage.scopeName = 'text.html.markdoc'; + +// Merge the Markdown and Markdoc Markdown grammar repositories. +markdownTmLanguage.repository = { + ...markdownTmLanguage.repository, + ...markdocMarkdownTmLanguage.repository, +}; + +// Include the Markdoc Markdown grammar rules at the beginning of the Markdown grammar. +for (const rule of Object.keys(markdocMarkdownTmLanguage.repository)) { + // Skip shortcut rules as they break syntax highlighting of child content that includes dots in + // words and we don't ever use them. + if (rule === 'shortcut') continue; + + markdownTmLanguage.repository.block.patterns.unshift({ include: `#${rule}` }); + markdownTmLanguage.repository.inline.patterns.unshift({ include: `#${rule}` }); +} + +// Write the grammar to a file. +await fs.writeFile( + './grammars/markdoc.tmLanguage.json', + JSON.stringify( + markdownTmLanguage, + (key, value) => { + // The `applyEndPatternLast` property should be a boolean and not a number. + if (key === 'applyEndPatternLast') return Boolean(value); + return value; + }, + 2 + ) +); + +console.log('Markdoc grammar generated successfully.'); diff --git a/docs/grammars/markdoc.tmLanguage.json b/docs/grammars/markdoc.tmLanguage.json new file mode 100644 index 00000000000..7089fd499b6 --- /dev/null +++ b/docs/grammars/markdoc.tmLanguage.json @@ -0,0 +1,3142 @@ +{ + "displayName": "Markdown", + "name": "markdoc", + "patterns": [ + { + "include": "#frontMatter" + }, + { + "include": "#block" + } + ], + "repository": { + "ampersand": { + "comment": "Markdown will convert this for us. We match it so that the HTML grammar will not mark it up as invalid.", + "match": "&(?!([a-zA-Z0-9]+|#\\d+|#x[0-9a-fA-F]+);)", + "name": "meta.other.valid-ampersand.markdown" + }, + "block": { + "patterns": [ + { + "include": "#tag" + }, + { + "include": "#attribute" + }, + { + "include": "#separator" + }, + { + "include": "#heading" + }, + { + "include": "#blockquote" + }, + { + "include": "#lists" + }, + { + "include": "#fenced_code_block" + }, + { + "include": "#raw_block" + }, + { + "include": "#link-def" + }, + { + "include": "#html" + }, + { + "include": "#table" + }, + { + "include": "#paragraph" + } + ] + }, + "blockquote": { + "begin": "(^|\\G)[ ]{0,3}(>) ?", + "captures": { + "2": { + "name": "punctuation.definition.quote.begin.markdown" + } + }, + "name": "markup.quote.markdown", + "patterns": [ + { + "include": "#block" + } + ], + "while": "(^|\\G)\\s*(>) ?" + }, + "bold": { + "begin": "(?(\\*\\*(?=\\w)|(?]*+>|(?`+)([^`]|(?!(?(?!`))`)*+\\k|\\\\[\\\\`*_{}\\[\\]()#.!+\\->]?+|\\[((?[^\\[\\]\\\\]|\\\\.|\\[\\g*+\\])*+\\](([ ]?\\[[^\\]]*+\\])|(\\([ \\t]*+?[ \\t]*+((?['\"])(.*?)\\k<title>)?\\))))|(?!(?<=\\S)\\k<open>).)++(?<=\\S)(?=__\\b|\\*\\*)\\k<open>)", + "captures": { + "1": { + "name": "punctuation.definition.bold.markdown" + } + }, + "end": "(?<=\\S)(\\1)", + "name": "markup.bold.markdown", + "patterns": [ + { + "applyEndPatternLast": true, + "begin": "(?=<[^>]*?>)", + "end": "(?<=>)", + "patterns": [ + { + "include": "text.html.derivative" + } + ] + }, + { + "include": "#escape" + }, + { + "include": "#ampersand" + }, + { + "include": "#bracket" + }, + { + "include": "#raw" + }, + { + "include": "#bold" + }, + { + "include": "#italic" + }, + { + "include": "#image-inline" + }, + { + "include": "#link-inline" + }, + { + "include": "#link-inet" + }, + { + "include": "#link-email" + }, + { + "include": "#image-ref" + }, + { + "include": "#link-ref-literal" + }, + { + "include": "#link-ref" + }, + { + "include": "#link-ref-shortcut" + }, + { + "include": "#strikethrough" + } + ] + }, + "bracket": { + "comment": "Markdown will convert this for us. We match it so that the HTML grammar will not mark it up as invalid.", + "match": "<(?![a-zA-Z/?$!])", + "name": "meta.other.valid-bracket.markdown" + }, + "escape": { + "match": "\\\\[-`*_#+.!(){}\\[\\]\\\\>]", + "name": "constant.character.escape.markdown" + }, + "fenced_code_block": { + "patterns": [ + { + "include": "#fenced_code_block_css" + }, + { + "include": "#fenced_code_block_basic" + }, + { + "include": "#fenced_code_block_ini" + }, + { + "include": "#fenced_code_block_java" + }, + { + "include": "#fenced_code_block_lua" + }, + { + "include": "#fenced_code_block_makefile" + }, + { + "include": "#fenced_code_block_perl" + }, + { + "include": "#fenced_code_block_r" + }, + { + "include": "#fenced_code_block_ruby" + }, + { + "include": "#fenced_code_block_php" + }, + { + "include": "#fenced_code_block_sql" + }, + { + "include": "#fenced_code_block_vs_net" + }, + { + "include": "#fenced_code_block_xml" + }, + { + "include": "#fenced_code_block_xsl" + }, + { + "include": "#fenced_code_block_yaml" + }, + { + "include": "#fenced_code_block_dosbatch" + }, + { + "include": "#fenced_code_block_clojure" + }, + { + "include": "#fenced_code_block_coffee" + }, + { + "include": "#fenced_code_block_c" + }, + { + "include": "#fenced_code_block_cpp" + }, + { + "include": "#fenced_code_block_diff" + }, + { + "include": "#fenced_code_block_dockerfile" + }, + { + "include": "#fenced_code_block_git_commit" + }, + { + "include": "#fenced_code_block_git_rebase" + }, + { + "include": "#fenced_code_block_go" + }, + { + "include": "#fenced_code_block_groovy" + }, + { + "include": "#fenced_code_block_pug" + }, + { + "include": "#fenced_code_block_js" + }, + { + "include": "#fenced_code_block_js_regexp" + }, + { + "include": "#fenced_code_block_json" + }, + { + "include": "#fenced_code_block_jsonc" + }, + { + "include": "#fenced_code_block_less" + }, + { + "include": "#fenced_code_block_objc" + }, + { + "include": "#fenced_code_block_swift" + }, + { + "include": "#fenced_code_block_scss" + }, + { + "include": "#fenced_code_block_perl6" + }, + { + "include": "#fenced_code_block_powershell" + }, + { + "include": "#fenced_code_block_python" + }, + { + "include": "#fenced_code_block_julia" + }, + { + "include": "#fenced_code_block_regexp_python" + }, + { + "include": "#fenced_code_block_rust" + }, + { + "include": "#fenced_code_block_scala" + }, + { + "include": "#fenced_code_block_shell" + }, + { + "include": "#fenced_code_block_ts" + }, + { + "include": "#fenced_code_block_tsx" + }, + { + "include": "#fenced_code_block_csharp" + }, + { + "include": "#fenced_code_block_fsharp" + }, + { + "include": "#fenced_code_block_dart" + }, + { + "include": "#fenced_code_block_handlebars" + }, + { + "include": "#fenced_code_block_markdown" + }, + { + "include": "#fenced_code_block_log" + }, + { + "include": "#fenced_code_block_erlang" + }, + { + "include": "#fenced_code_block_elixir" + }, + { + "include": "#fenced_code_block_latex" + }, + { + "include": "#fenced_code_block_bibtex" + }, + { + "include": "#fenced_code_block_twig" + }, + { + "include": "#fenced_code_block_unknown" + } + ] + }, + "fenced_code_block_basic": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(html|htm|shtml|xhtml|inc|tmpl|tpl)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.html", + "patterns": [ + { + "include": "text.html.basic" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_bibtex": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(bibtex)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.bibtex", + "patterns": [ + { + "include": "text.bibtex" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_c": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(c|h)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.c", + "patterns": [ + { + "include": "source.c" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_clojure": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(clj|cljs|clojure)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.clojure", + "patterns": [ + { + "include": "source.clojure" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_coffee": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(coffee|Cakefile|coffee.erb)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.coffee", + "patterns": [ + { + "include": "source.coffee" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_cpp": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(cpp|c\\+\\+|cxx)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.cpp source.cpp", + "patterns": [ + { + "include": "source.cpp" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_csharp": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(cs|csharp|c#)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.csharp", + "patterns": [ + { + "include": "source.cs" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_css": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(css|css.erb)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.css", + "patterns": [ + { + "include": "source.css" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_dart": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(dart)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.dart", + "patterns": [ + { + "include": "source.dart" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_diff": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(patch|diff|rej)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.diff", + "patterns": [ + { + "include": "source.diff" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_dockerfile": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(dockerfile|Dockerfile)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.dockerfile", + "patterns": [ + { + "include": "source.dockerfile" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_dosbatch": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(bat|batch)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.dosbatch", + "patterns": [ + { + "include": "source.batchfile" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_elixir": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(elixir)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.elixir", + "patterns": [ + { + "include": "source.elixir" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_erlang": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(erlang)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.erlang", + "patterns": [ + { + "include": "source.erlang" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_fsharp": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(fs|fsharp|f#)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.fsharp", + "patterns": [ + { + "include": "source.fsharp" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_git_commit": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(COMMIT_EDITMSG|MERGE_MSG)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.git_commit", + "patterns": [ + { + "include": "text.git-commit" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_git_rebase": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(git-rebase-todo)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.git_rebase", + "patterns": [ + { + "include": "text.git-rebase" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_go": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(go|golang)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.go", + "patterns": [ + { + "include": "source.go" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_groovy": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(groovy|gvy)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.groovy", + "patterns": [ + { + "include": "source.groovy" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_handlebars": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(handlebars|hbs)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.handlebars", + "patterns": [ + { + "include": "text.html.handlebars" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_ini": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(ini|conf)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.ini", + "patterns": [ + { + "include": "source.ini" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_java": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(java|bsh)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.java", + "patterns": [ + { + "include": "source.java" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_js": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(js|jsx|javascript|es6|mjs|cjs|dataviewjs|\\{\\.js.+?\\})((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.javascript", + "patterns": [ + { + "include": "source.js" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_js_regexp": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(regexp)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.js_regexp", + "patterns": [ + { + "include": "source.js.regexp" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_json": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(json|json5|sublime-settings|sublime-menu|sublime-keymap|sublime-mousemap|sublime-theme|sublime-build|sublime-project|sublime-completions)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.json", + "patterns": [ + { + "include": "source.json" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_jsonc": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(jsonc)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.jsonc", + "patterns": [ + { + "include": "source.json.comments" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_julia": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(julia|\\{\\.julia.+?\\})((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.julia", + "patterns": [ + { + "include": "source.julia" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_latex": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(latex|tex)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.latex", + "patterns": [ + { + "include": "text.tex.latex" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_less": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(less)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.less", + "patterns": [ + { + "include": "source.css.less" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_log": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(log)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.log", + "patterns": [ + { + "include": "text.log" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_lua": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(lua)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.lua", + "patterns": [ + { + "include": "source.lua" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_makefile": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(Makefile|makefile|GNUmakefile|OCamlMakefile)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.makefile", + "patterns": [ + { + "include": "source.makefile" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_markdown": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(markdown|md)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.markdown", + "patterns": [ + { + "include": "text.html.markdown" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_objc": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(objectivec|objective-c|mm|objc|obj-c|m|h)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.objc", + "patterns": [ + { + "include": "source.objc" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_perl": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(perl|pl|pm|pod|t|PL|psgi|vcl)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.perl", + "patterns": [ + { + "include": "source.perl" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_perl6": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(perl6|p6|pl6|pm6|nqp)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.perl6", + "patterns": [ + { + "include": "source.perl.6" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_php": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(php|php3|php4|php5|phpt|phtml|aw|ctp)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.php", + "patterns": [ + { + "include": "text.html.basic" + }, + { + "include": "source.php" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_powershell": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(powershell|ps1|psm1|psd1|pwsh)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.powershell", + "patterns": [ + { + "include": "source.powershell" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_pug": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(jade|pug)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.pug", + "patterns": [ + { + "include": "text.pug" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_python": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(python|py|py3|rpy|pyw|cpy|SConstruct|Sconstruct|sconstruct|SConscript|gyp|gypi|\\{\\.python.+?\\})((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.python", + "patterns": [ + { + "include": "source.python" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_r": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(R|r|s|S|Rprofile|\\{\\.r.+?\\})((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.r", + "patterns": [ + { + "include": "source.r" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_regexp_python": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(re)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.regexp_python", + "patterns": [ + { + "include": "source.regexp.python" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_ruby": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(ruby|rb|rbx|rjs|Rakefile|rake|cgi|fcgi|gemspec|irbrc|Capfile|ru|prawn|Cheffile|Gemfile|Guardfile|Hobofile|Vagrantfile|Appraisals|Rantfile|Berksfile|Berksfile.lock|Thorfile|Puppetfile)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.ruby", + "patterns": [ + { + "include": "source.ruby" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_rust": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(rust|rs|\\{\\.rust.+?\\})((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.rust", + "patterns": [ + { + "include": "source.rust" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_scala": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(scala|sbt)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.scala", + "patterns": [ + { + "include": "source.scala" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_scss": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(scss)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.scss", + "patterns": [ + { + "include": "source.css.scss" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_shell": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(shell|sh|bash|zsh|bashrc|bash_profile|bash_login|profile|bash_logout|.textmate_init|\\{\\.bash.+?\\})((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.shellscript", + "patterns": [ + { + "include": "source.shell" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_sql": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(sql|ddl|dml)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.sql", + "patterns": [ + { + "include": "source.sql" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_swift": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(swift)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.swift", + "patterns": [ + { + "include": "source.swift" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_ts": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(typescript|ts)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.typescript", + "patterns": [ + { + "include": "source.ts" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_tsx": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(tsx)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.typescriptreact", + "patterns": [ + { + "include": "source.tsx" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_twig": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(twig)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.twig", + "patterns": [ + { + "include": "source.twig" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_unknown": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?=([^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown" + }, + "fenced_code_block_vs_net": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(vb)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.vs_net", + "patterns": [ + { + "include": "source.asp.vb.net" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_xml": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(xml|xsd|tld|jsp|pt|cpt|dtml|rss|opml)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.xml", + "patterns": [ + { + "include": "text.xml" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_xsl": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(xsl|xslt)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.xsl", + "patterns": [ + { + "include": "text.xml.xsl" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "fenced_code_block_yaml": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(yaml|yml)((\\s+|:|,|\\{|\\?)[^`]*)?$)", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "name": "markup.fenced_code.block.markdown", + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "contentName": "meta.embedded.block.yaml", + "patterns": [ + { + "include": "source.yaml" + } + ], + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" + } + ] + }, + "frontMatter": { + "applyEndPatternLast": true, + "begin": "\\A(?=(-{3,}))", + "end": "^ {,3}\\1-*[ \\t]*$|^[ \\t]*\\.{3}$", + "endCaptures": { + "0": { + "name": "punctuation.definition.end.frontmatter" + } + }, + "patterns": [ + { + "begin": "\\A(-{3,})(.*)$", + "beginCaptures": { + "1": { + "name": "punctuation.definition.begin.frontmatter" + }, + "2": { + "name": "comment.frontmatter" + } + }, + "contentName": "meta.embedded.block.frontmatter", + "patterns": [ + { + "include": "source.yaml" + } + ], + "while": "^(?! {,3}\\1-*[ \\t]*$|[ \\t]*\\.{3}$)" + } + ] + }, + "heading": { + "captures": { + "1": { + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.definition.heading.markdown" + }, + "2": { + "name": "entity.name.section.markdown", + "patterns": [ + { + "include": "#inline" + }, + { + "include": "text.html.derivative" + } + ] + }, + "3": { + "name": "punctuation.definition.heading.markdown" + } + }, + "match": "(#{6})\\s+(.*?)(?:\\s+(#+))?\\s*$", + "name": "heading.6.markdown" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.heading.markdown" + }, + "2": { + "name": "entity.name.section.markdown", + "patterns": [ + { + "include": "#inline" + }, + { + "include": "text.html.derivative" + } + ] + }, + "3": { + "name": "punctuation.definition.heading.markdown" + } + }, + "match": "(#{5})\\s+(.*?)(?:\\s+(#+))?\\s*$", + "name": "heading.5.markdown" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.heading.markdown" + }, + "2": { + "name": "entity.name.section.markdown", + "patterns": [ + { + "include": "#inline" + }, + { + "include": "text.html.derivative" + } + ] + }, + "3": { + "name": "punctuation.definition.heading.markdown" + } + }, + "match": "(#{4})\\s+(.*?)(?:\\s+(#+))?\\s*$", + "name": "heading.4.markdown" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.heading.markdown" + }, + "2": { + "name": "entity.name.section.markdown", + "patterns": [ + { + "include": "#inline" + }, + { + "include": "text.html.derivative" + } + ] + }, + "3": { + "name": "punctuation.definition.heading.markdown" + } + }, + "match": "(#{3})\\s+(.*?)(?:\\s+(#+))?\\s*$", + "name": "heading.3.markdown" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.heading.markdown" + }, + "2": { + "name": "entity.name.section.markdown", + "patterns": [ + { + "include": "#inline" + }, + { + "include": "text.html.derivative" + } + ] + }, + "3": { + "name": "punctuation.definition.heading.markdown" + } + }, + "match": "(#{2})\\s+(.*?)(?:\\s+(#+))?\\s*$", + "name": "heading.2.markdown" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.heading.markdown" + }, + "2": { + "name": "entity.name.section.markdown", + "patterns": [ + { + "include": "#inline" + }, + { + "include": "text.html.derivative" + } + ] + }, + "3": { + "name": "punctuation.definition.heading.markdown" + } + }, + "match": "(#{1})\\s+(.*?)(?:\\s+(#+))?\\s*$", + "name": "heading.1.markdown" + } + ] + } + }, + "match": "(?:^|\\G)[ ]{0,3}(#{1,6}\\s+(.*?)(\\s+#{1,6})?\\s*)$", + "name": "markup.heading.markdown" + }, + "heading-setext": { + "patterns": [ + { + "match": "^(={3,})(?=[ \\t]*$\\n?)", + "name": "markup.heading.setext.1.markdown" + }, + { + "match": "^(-{3,})(?=[ \\t]*$\\n?)", + "name": "markup.heading.setext.2.markdown" + } + ] + }, + "html": { + "patterns": [ + { + "begin": "(^|\\G)\\s*(<!--)", + "captures": { + "1": { + "name": "punctuation.definition.comment.html" + }, + "2": { + "name": "punctuation.definition.comment.html" + } + }, + "end": "(-->)", + "name": "comment.block.html" + }, + { + "begin": "(?i)(^|\\G)\\s*(?=<(script|style|pre)(\\s|$|>)(?!.*?</(script|style|pre)>))", + "end": "(?i)(.*)((</)(script|style|pre)(>))", + "endCaptures": { + "1": { + "patterns": [ + { + "include": "text.html.derivative" + } + ] + }, + "2": { + "name": "meta.tag.structure.$4.end.html" + }, + "3": { + "name": "punctuation.definition.tag.begin.html" + }, + "4": { + "name": "entity.name.tag.html" + }, + "5": { + "name": "punctuation.definition.tag.end.html" + } + }, + "patterns": [ + { + "begin": "(\\s*|$)", + "patterns": [ + { + "include": "text.html.derivative" + } + ], + "while": "(?i)^(?!.*</(script|style|pre)>)" + } + ] + }, + { + "begin": "(?i)(^|\\G)\\s*(?=</?[a-zA-Z]+[^\\s/>]*(\\s|$|/?>))", + "patterns": [ + { + "include": "text.html.derivative" + } + ], + "while": "^(?!\\s*$)" + }, + { + "begin": "(^|\\G)\\s*(?=(<[a-zA-Z0-9\\-](/?>|\\s.*?>)|</[a-zA-Z0-9\\-]>)\\s*$)", + "patterns": [ + { + "include": "text.html.derivative" + } + ], + "while": "^(?!\\s*$)" + } + ] + }, + "image-inline": { + "captures": { + "1": { + "name": "punctuation.definition.link.description.begin.markdown" + }, + "2": { + "name": "string.other.link.description.markdown" + }, + "4": { + "name": "punctuation.definition.link.description.end.markdown" + }, + "5": { + "name": "punctuation.definition.metadata.markdown" + }, + "7": { + "name": "punctuation.definition.link.markdown" + }, + "8": { + "name": "markup.underline.link.image.markdown" + }, + "9": { + "name": "punctuation.definition.link.markdown" + }, + "10": { + "name": "markup.underline.link.image.markdown" + }, + "12": { + "name": "string.other.link.description.title.markdown" + }, + "13": { + "name": "punctuation.definition.string.begin.markdown" + }, + "14": { + "name": "punctuation.definition.string.end.markdown" + }, + "15": { + "name": "string.other.link.description.title.markdown" + }, + "16": { + "name": "punctuation.definition.string.begin.markdown" + }, + "17": { + "name": "punctuation.definition.string.end.markdown" + }, + "18": { + "name": "string.other.link.description.title.markdown" + }, + "19": { + "name": "punctuation.definition.string.begin.markdown" + }, + "20": { + "name": "punctuation.definition.string.end.markdown" + }, + "21": { + "name": "punctuation.definition.metadata.markdown" + } + }, + "match": "(!\\[)((?<square>[^\\[\\]\\\\]|\\\\.|\\[\\g<square>*+\\])*+)(\\])(\\()[ \\t]*((<)((?:\\\\[<>]|[^<>\\n])*)(>)|((?<url>(?>[^\\s()]+)|\\(\\g<url>*\\))*))[ \\t]*(?:((\\().+?(\\)))|((\").+?(\"))|((').+?(')))?\\s*(\\))", + "name": "meta.image.inline.markdown" + }, + "image-ref": { + "captures": { + "1": { + "name": "punctuation.definition.link.description.begin.markdown" + }, + "2": { + "name": "string.other.link.description.markdown" + }, + "4": { + "name": "punctuation.definition.link.description.end.markdown" + }, + "5": { + "name": "punctuation.definition.constant.markdown" + }, + "6": { + "name": "constant.other.reference.link.markdown" + }, + "7": { + "name": "punctuation.definition.constant.markdown" + } + }, + "match": "(!\\[)((?<square>[^\\[\\]\\\\]|\\\\.|\\[\\g<square>*+\\])*+)(\\])[ ]?(\\[)(.*?)(\\])", + "name": "meta.image.reference.markdown" + }, + "inline": { + "patterns": [ + { + "include": "#tag" + }, + { + "include": "#attribute" + }, + { + "include": "#ampersand" + }, + { + "include": "#bracket" + }, + { + "include": "#bold" + }, + { + "include": "#italic" + }, + { + "include": "#raw" + }, + { + "include": "#strikethrough" + }, + { + "include": "#escape" + }, + { + "include": "#image-inline" + }, + { + "include": "#image-ref" + }, + { + "include": "#link-email" + }, + { + "include": "#link-inet" + }, + { + "include": "#link-inline" + }, + { + "include": "#link-ref" + }, + { + "include": "#link-ref-literal" + }, + { + "include": "#link-ref-shortcut" + } + ] + }, + "italic": { + "begin": "(?<open>(\\*(?=\\w)|(?<!\\w)\\*|(?<!\\w)\\b_))(?=\\S)(?=(<[^>]*+>|(?<raw>`+)([^`]|(?!(?<!`)\\k<raw>(?!`))`)*+\\k<raw>|\\\\[\\\\`*_{}\\[\\]()#.!+\\->]?+|\\[((?<square>[^\\[\\]\\\\]|\\\\.|\\[\\g<square>*+\\])*+\\](([ ]?\\[[^\\]]*+\\])|(\\([ \\t]*+<?(.*?)>?[ \\t]*+((?<title>['\"])(.*?)\\k<title>)?\\))))|\\k<open>\\k<open>|(?!(?<=\\S)\\k<open>).)++(?<=\\S)(?=_\\b|\\*)\\k<open>)", + "captures": { + "1": { + "name": "punctuation.definition.italic.markdown" + } + }, + "end": "(?<=\\S)(\\1)((?!\\1)|(?=\\1\\1))", + "name": "markup.italic.markdown", + "patterns": [ + { + "applyEndPatternLast": true, + "begin": "(?=<[^>]*?>)", + "end": "(?<=>)", + "patterns": [ + { + "include": "text.html.derivative" + } + ] + }, + { + "include": "#escape" + }, + { + "include": "#ampersand" + }, + { + "include": "#bracket" + }, + { + "include": "#raw" + }, + { + "include": "#bold" + }, + { + "include": "#image-inline" + }, + { + "include": "#link-inline" + }, + { + "include": "#link-inet" + }, + { + "include": "#link-email" + }, + { + "include": "#image-ref" + }, + { + "include": "#link-ref-literal" + }, + { + "include": "#link-ref" + }, + { + "include": "#link-ref-shortcut" + }, + { + "include": "#strikethrough" + } + ] + }, + "link-def": { + "captures": { + "1": { + "name": "punctuation.definition.constant.markdown" + }, + "2": { + "name": "constant.other.reference.link.markdown" + }, + "3": { + "name": "punctuation.definition.constant.markdown" + }, + "4": { + "name": "punctuation.separator.key-value.markdown" + }, + "5": { + "name": "punctuation.definition.link.markdown" + }, + "6": { + "name": "markup.underline.link.markdown" + }, + "7": { + "name": "punctuation.definition.link.markdown" + }, + "8": { + "name": "markup.underline.link.markdown" + }, + "9": { + "name": "string.other.link.description.title.markdown" + }, + "10": { + "name": "punctuation.definition.string.begin.markdown" + }, + "11": { + "name": "punctuation.definition.string.end.markdown" + }, + "12": { + "name": "string.other.link.description.title.markdown" + }, + "13": { + "name": "punctuation.definition.string.begin.markdown" + }, + "14": { + "name": "punctuation.definition.string.end.markdown" + }, + "15": { + "name": "string.other.link.description.title.markdown" + }, + "16": { + "name": "punctuation.definition.string.begin.markdown" + }, + "17": { + "name": "punctuation.definition.string.end.markdown" + } + }, + "match": "\\s*(\\[)([^]]+?)(\\])(:)[ \\t]*(?:(<)((?:\\\\[<>]|[^<>\\n])*)(>)|(\\S+?))[ \\t]*(?:((\\().+?(\\)))|((\").+?(\"))|((').+?(')))?\\s*$", + "name": "meta.link.reference.def.markdown" + }, + "link-email": { + "captures": { + "1": { + "name": "punctuation.definition.link.markdown" + }, + "2": { + "name": "markup.underline.link.markdown" + }, + "4": { + "name": "punctuation.definition.link.markdown" + } + }, + "match": "(<)((?:mailto:)?[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)(>)", + "name": "meta.link.email.lt-gt.markdown" + }, + "link-inet": { + "captures": { + "1": { + "name": "punctuation.definition.link.markdown" + }, + "2": { + "name": "markup.underline.link.markdown" + }, + "3": { + "name": "punctuation.definition.link.markdown" + } + }, + "match": "(<)((?:https?|ftp)://.*?)(>)", + "name": "meta.link.inet.markdown" + }, + "link-inline": { + "captures": { + "1": { + "name": "punctuation.definition.link.title.begin.markdown" + }, + "2": { + "name": "string.other.link.title.markdown", + "patterns": [ + { + "include": "#raw" + }, + { + "include": "#bold" + }, + { + "include": "#italic" + }, + { + "include": "#strikethrough" + }, + { + "include": "#image-inline" + } + ] + }, + "4": { + "name": "punctuation.definition.link.title.end.markdown" + }, + "5": { + "name": "punctuation.definition.metadata.markdown" + }, + "7": { + "name": "punctuation.definition.link.markdown" + }, + "8": { + "name": "markup.underline.link.markdown" + }, + "9": { + "name": "punctuation.definition.link.markdown" + }, + "10": { + "name": "markup.underline.link.markdown" + }, + "12": { + "name": "string.other.link.description.title.markdown" + }, + "13": { + "name": "punctuation.definition.string.begin.markdown" + }, + "14": { + "name": "punctuation.definition.string.end.markdown" + }, + "15": { + "name": "string.other.link.description.title.markdown" + }, + "16": { + "name": "punctuation.definition.string.begin.markdown" + }, + "17": { + "name": "punctuation.definition.string.end.markdown" + }, + "18": { + "name": "string.other.link.description.title.markdown" + }, + "19": { + "name": "punctuation.definition.string.begin.markdown" + }, + "20": { + "name": "punctuation.definition.string.end.markdown" + }, + "21": { + "name": "punctuation.definition.metadata.markdown" + } + }, + "match": "(\\[)((?<square>[^\\[\\]\\\\]|\\\\.|\\[\\g<square>*+\\])*+)(\\])(\\()[ \\t]*((<)((?:\\\\[<>]|[^<>\\n])*)(>)|((?<url>(?>[^\\s()]+)|\\(\\g<url>*\\))*))[ \\t]*(?:((\\()[^()]*(\\)))|((\")[^\"]*(\"))|((')[^']*(')))?\\s*(\\))", + "name": "meta.link.inline.markdown" + }, + "link-ref": { + "captures": { + "1": { + "name": "punctuation.definition.link.title.begin.markdown" + }, + "2": { + "name": "string.other.link.title.markdown", + "patterns": [ + { + "include": "#raw" + }, + { + "include": "#bold" + }, + { + "include": "#italic" + }, + { + "include": "#strikethrough" + }, + { + "include": "#image-inline" + } + ] + }, + "4": { + "name": "punctuation.definition.link.title.end.markdown" + }, + "5": { + "name": "punctuation.definition.constant.begin.markdown" + }, + "6": { + "name": "constant.other.reference.link.markdown" + }, + "7": { + "name": "punctuation.definition.constant.end.markdown" + } + }, + "match": "(?<![\\]\\\\])(\\[)((?<square>[^\\[\\]\\\\]|\\\\.|\\[\\g<square>*+\\])*+)(\\])(\\[)([^\\]]*+)(\\])", + "name": "meta.link.reference.markdown" + }, + "link-ref-literal": { + "captures": { + "1": { + "name": "punctuation.definition.link.title.begin.markdown" + }, + "2": { + "name": "string.other.link.title.markdown" + }, + "4": { + "name": "punctuation.definition.link.title.end.markdown" + }, + "5": { + "name": "punctuation.definition.constant.begin.markdown" + }, + "6": { + "name": "punctuation.definition.constant.end.markdown" + } + }, + "match": "(?<![\\]\\\\])(\\[)((?<square>[^\\[\\]\\\\]|\\\\.|\\[\\g<square>*+\\])*+)(\\])[ ]?(\\[)(\\])", + "name": "meta.link.reference.literal.markdown" + }, + "link-ref-shortcut": { + "captures": { + "1": { + "name": "punctuation.definition.link.title.begin.markdown" + }, + "2": { + "name": "string.other.link.title.markdown" + }, + "3": { + "name": "punctuation.definition.link.title.end.markdown" + } + }, + "match": "(?<![\\]\\\\])(\\[)((?:[^\\s\\[\\]\\\\]|\\\\[\\[\\]])+?)((?<!\\\\)\\])", + "name": "meta.link.reference.markdown" + }, + "list_paragraph": { + "begin": "(^|\\G)(?=\\S)(?![*+->]\\s|\\d+\\.\\s)", + "name": "meta.paragraph.markdown", + "patterns": [ + { + "include": "#inline" + }, + { + "include": "text.html.derivative" + }, + { + "include": "#heading-setext" + } + ], + "while": "(^|\\G)(?!\\s*$|#|[ ]{0,3}([-*_>][ ]{2,}){3,}[ \\t]*$\\n?|[ ]{0,3}[*+->]|[ ]{0,3}\\d+\\.)" + }, + "lists": { + "patterns": [ + { + "begin": "(^|\\G)([ ]{0,3})([*+-])([ \\t])", + "beginCaptures": { + "3": { + "name": "punctuation.definition.list.begin.markdown" + } + }, + "comment": "Currently does not support un-indented second lines.", + "name": "markup.list.unnumbered.markdown", + "patterns": [ + { + "include": "#block" + }, + { + "include": "#list_paragraph" + } + ], + "while": "((^|\\G)([ ]{2,4}|\\t))|(^[ \\t]*$)" + }, + { + "begin": "(^|\\G)([ ]{0,3})(\\d+[\\.)])([ \\t])", + "beginCaptures": { + "3": { + "name": "punctuation.definition.list.begin.markdown" + } + }, + "name": "markup.list.numbered.markdown", + "patterns": [ + { + "include": "#block" + }, + { + "include": "#list_paragraph" + } + ], + "while": "((^|\\G)([ ]{2,4}|\\t))|(^[ \\t]*$)" + } + ] + }, + "paragraph": { + "begin": "(^|\\G)[ ]{0,3}(?=[^ \\t\\n])", + "name": "meta.paragraph.markdown", + "patterns": [ + { + "include": "#inline" + }, + { + "include": "text.html.derivative" + }, + { + "include": "#heading-setext" + } + ], + "while": "(^|\\G)((?=\\s*[-=]{3,}\\s*$)|[ ]{4,}(?=[^ \\t\\n]))" + }, + "raw": { + "captures": { + "1": { + "name": "punctuation.definition.raw.markdown" + }, + "3": { + "name": "punctuation.definition.raw.markdown" + } + }, + "match": "(`+)((?:[^`]|(?!(?<!`)\\1(?!`))`)*+)(\\1)", + "name": "markup.inline.raw.string.markdown" + }, + "raw_block": { + "begin": "(^|\\G)([ ]{4}|\\t)", + "name": "markup.raw.block.markdown", + "while": "(^|\\G)([ ]{4}|\\t)" + }, + "separator": { + "match": "(^|\\G)[ ]{0,3}([\\*\\-_])([ ]{0,2}\\2){2,}[ \\t]*$\\n?", + "name": "meta.separator.markdown" + }, + "strikethrough": { + "captures": { + "1": { + "name": "punctuation.definition.strikethrough.markdown" + }, + "2": { + "patterns": [ + { + "applyEndPatternLast": true, + "begin": "(?=<[^>]*?>)", + "end": "(?<=>)", + "patterns": [ + { + "include": "text.html.derivative" + } + ] + }, + { + "include": "#escape" + }, + { + "include": "#ampersand" + }, + { + "include": "#bracket" + }, + { + "include": "#raw" + }, + { + "include": "#bold" + }, + { + "include": "#italic" + }, + { + "include": "#image-inline" + }, + { + "include": "#link-inline" + }, + { + "include": "#link-inet" + }, + { + "include": "#link-email" + }, + { + "include": "#image-ref" + }, + { + "include": "#link-ref-literal" + }, + { + "include": "#link-ref" + }, + { + "include": "#link-ref-shortcut" + } + ] + }, + "3": { + "name": "punctuation.definition.strikethrough.markdown" + } + }, + "match": "(?<!\\\\)(~{2,})((?:[^~]|(?!(?<![~\\\\])\\1(?!~))~)*+)(\\1)", + "name": "markup.strikethrough.markdown" + }, + "table": { + "begin": "(^|\\G)(\\|)(?=[^|].+\\|\\s*$)", + "beginCaptures": { + "2": { + "name": "punctuation.definition.table.markdown" + } + }, + "name": "markup.table.markdown", + "patterns": [ + { + "match": "\\|", + "name": "punctuation.definition.table.markdown" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.table.markdown" + } + }, + "match": "(?<=\\|)\\s*(:?-+:?)\\s*(?=\\|)" + }, + { + "captures": { + "1": { + "patterns": [ + { + "include": "#inline" + } + ] + } + }, + "match": "(?<=\\|)\\s*(?=\\S)((\\\\\\||[^|])+)(?<=\\S)\\s*(?=\\|)" + } + ], + "while": "(^|\\G)(?=\\|)" + }, + "shortcut": { + "match": "(\\$|\\.|#)([-_:a-zA-Z0-9]+)", + "name": "string.other.markdoc-shortcut" + }, + "attribute": { + "match": "([-_a-zA-Z0-9]+)(=)", + "captures": { + "1": { + "name": "entity.other.attribute-name" + }, + "2": { + "name": "punctuation.definition.tag.equal.markdoc" + } + } + }, + "tag": { + "name": "punctuation.definition.tag", + "begin": "({%)\\s*/?([-_a-zA-Z0-9]+)?", + "end": "\\s*/?\\s*%}", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.markdoc" + }, + "2": { + "name": "entity.name.tag" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.markdoc" + } + }, + "patterns": [ + { + "include": "#attribute" + }, + { + "include": "#shortcut" + }, + { + "include": "source.json" + } + ] + } + }, + "scopeName": "text.html.markdoc" +} diff --git a/docs/lunaria.config.json b/docs/lunaria.config.json new file mode 100644 index 00000000000..029acfc0370 --- /dev/null +++ b/docs/lunaria.config.json @@ -0,0 +1,103 @@ +{ + "$schema": "./node_modules/@lunariajs/core/config.schema.json", + "repository": { + "name": "withastro/starlight", + "rootDir": "docs" + }, + "defaultLocale": { + "label": "English", + "lang": "en" + }, + "locales": [ + { + "label": "Dansk", + "lang": "da" + }, + { + "label": "Deutsch", + "lang": "de" + }, + { + "label": "Español", + "lang": "es" + }, + { + "label": "Français", + "lang": "fr" + }, + { + "label": "हिंदी", + "lang": "hi" + }, + { + "label": "Bahasa Indonesia", + "lang": "id" + }, + { + "label": "Italiano", + "lang": "it" + }, + { + "label": "日本語", + "lang": "ja" + }, + { + "label": "한국어", + "lang": "ko" + }, + { + "label": "Português do Brasil", + "lang": "pt-br" + }, + { + "label": "Português", + "lang": "pt-pt" + }, + { + "label": "Русский", + "lang": "ru" + }, + { + "label": "Türkçe", + "lang": "tr" + }, + { + "label": "Українська", + "lang": "uk" + }, + { + "label": "简体中文", + "lang": "zh-cn" + } + ], + "files": [ + { + "location": "src/content/docs/**/*.{md,mdx}", + "pattern": "src/content/docs/@lang/@path", + "type": "universal" + } + ], + "dashboard": { + "title": "Starlight Docs Translation Status", + "description": "Translation progress tracker for the Starlight Docs site. See how much has been translated in your language and get involved!", + "favicon": { + "external": [ + { + "link": "https://starlight.astro.build/favicon.svg", + "type": "image/svg+xml" + } + ] + }, + "customCss": ["./lunaria/styles.css"], + "basesToHide": ["src/content/docs/"], + "ui": { + "statusByLocale.heading": "Translation progress by locale", + "statusByLocale.incompleteLocalizationLink": "incomplete translation", + "statusByLocale.outdatedLocalizationLink": "outdated translation", + "statusByLocale.completeLocalization": "This translation is complete, amazing job! 🎉", + "statusByFile.heading": "Translation status by file" + } + }, + "ignoreKeywords": ["lunaria-ignore", "typo", "en-only", "broken link", "i18nReady", "i18nIgnore"], + "renderer": "./lunaria/renderer.config.ts" +} diff --git a/docs/lunaria/components.ts b/docs/lunaria/components.ts new file mode 100644 index 00000000000..a7bf83b9658 --- /dev/null +++ b/docs/lunaria/components.ts @@ -0,0 +1,18 @@ +import { html } from '@lunariajs/core'; + +export const TitleParagraph = () => html` + <p> + If you're interested in helping us translate + <a href="https://starlight.astro.build/">starlight.astro.build</a> into one of the languages + listed below, you've come to the right place! This auto-updating page always lists all the + content that could use your help right now. + </p> + <p> + Before starting a new translation, please read our + <a + href="https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#translating-starlights-docs" + >translation guide</a + > + to learn about our translation process and how you can get involved. + </p> +`; diff --git a/docs/lunaria/renderer.config.ts b/docs/lunaria/renderer.config.ts new file mode 100644 index 00000000000..c5cdf506039 --- /dev/null +++ b/docs/lunaria/renderer.config.ts @@ -0,0 +1,8 @@ +import { defineRendererConfig } from '@lunariajs/core'; +import { TitleParagraph } from './components'; + +export default defineRendererConfig({ + slots: { + afterTitle: TitleParagraph, + }, +}); diff --git a/docs/lunaria/styles.css b/docs/lunaria/styles.css new file mode 100644 index 00000000000..43ce528008d --- /dev/null +++ b/docs/lunaria/styles.css @@ -0,0 +1,47 @@ +:root { + --theme-accent: hsl(234, 100%, 87%); + --theme-bg: hsl(223, 13%, 10%); + --theme-table-header: hsl(222, 13%, 16%); + --theme-table-hover: hsl(222, 13%, 16%); + --theme-text: hsl(228, 8%, 77%); + --theme-text-bright: hsl(0, 0%, 100%); + --overlay-blurple: hsla(255, 60%, 60%, 0.2); + + --ln-color-background: linear-gradient(215deg, var(--overlay-blurple), transparent 40%), + radial-gradient(var(--overlay-blurple), transparent 40%) no-repeat -60vw -40vh / 105vw 200vh, + radial-gradient(var(--overlay-blurple), transparent 65%) no-repeat 50% calc(100% + 20rem) / + 60rem 30rem, + var(--theme-bg); + --ln-color-link: var(--theme-accent); + --ln-color-black: var(--theme-text); + --ln-color-done: var(--ln-color-blue); + --ln-color-outdated: #ea580c; + --ln-color-missing: var(--theme-text-bright); + --ln-color-table-background: var(--theme-table-header); + --ln-color-table-border: var(--theme-table-header); + + color-scheme: dark; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + color: var(--theme-text-bright); +} + +p a { + text-decoration: underline; +} + +.create-button { + background-color: hsl(213deg 89% 64% / 20%); + border-radius: 0.5em; +} + +sup { + display: flex; + justify-content: center; +} diff --git a/docs/package.json b/docs/package.json index 90159bff6ce..2059be1dc02 100644 --- a/docs/package.json +++ b/docs/package.json @@ -4,28 +4,30 @@ "type": "module", "version": "0.0.1", "scripts": { - "test": "start-server-and-test 'pnpm preview' http://localhost:4321 'pnpm pa11y'", - "pa11y": "pa11y-ci --sitemap 'http://localhost:4321/sitemap-0.xml' --sitemap-find 'https://starlight.astro.build' --sitemap-replace 'http://localhost:4321' --sitemap-exclude '/(de|zh|fr|es|pt-br|it|id|ko)/.*'", + "test": "playwright install --with-deps chromium && playwright test", "dev": "astro dev", "start": "astro dev", "build": "astro build", "preview": "astro preview", - "astro": "astro" + "typecheck": "tsc --noEmit", + "linkcheck": "CHECK_LINKS=true pnpm build", + "astro": "astro", + "lunaria:build": "lunaria build", + "grammars": "node grammars/generate.mjs" }, "dependencies": { + "@astro-community/astro-embed-youtube": "^0.5.6", "@astrojs/starlight": "workspace:*", - "@types/culori": "^2.0.0", - "astro": "^3.2.1", - "culori": "^3.2.0", - "sharp": "^0.32.5" + "@lunariajs/core": "^0.1.1", + "@types/culori": "^2.1.1", + "astro": "^5.6.1", + "culori": "^4.0.1", + "sharp": "^0.34.2" }, "devDependencies": { - "hast-util-from-html": "^1.0.2", - "hast-util-to-string": "^2.0.0", - "hastscript": "^7.2.0", - "pa11y-ci": "^3.0.1", - "rehype": "^12.0.1", - "start-server-and-test": "^2.0.0", - "unist-util-visit": "^4.1.2" + "@playwright/test": "^1.45.0", + "axe-playwright": "^2.0.3", + "sitemapper": "^3.2.12", + "starlight-links-validator": "^0.14.0" } } diff --git a/docs/playwright.config.ts b/docs/playwright.config.ts new file mode 100644 index 00000000000..b763858ca80 --- /dev/null +++ b/docs/playwright.config.ts @@ -0,0 +1,28 @@ +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + forbidOnly: !!process.env['CI'], + projects: [ + { + name: 'Chrome Stable', + use: { + ...devices['Desktop Chrome'], + headless: true, + }, + }, + ], + testMatch: '__a11y__/*.test.ts', + // The timeout for the accessibility tests only. + timeout: 180 * 1_000, + webServer: [ + { + command: 'pnpm run build && pnpm run preview', + reuseExistingServer: !process.env['CI'], + stdout: 'pipe', + // The timeout of the single build step ran before the accessibility tests. + timeout: 120 * 1_000, + url: 'http://localhost:4321', + }, + ], + workers: 1, +}); diff --git a/docs/public/_headers b/docs/public/_headers index aaa51ef2a6e..929480eeb9f 100644 --- a/docs/public/_headers +++ b/docs/public/_headers @@ -1,4 +1,4 @@ /_astro/* Cache-Control: public - Cache-Control: max-age=604800 + Cache-Control: max-age=31536000 Cache-Control: immutable diff --git a/docs/public/_redirects b/docs/public/_redirects index 3d094687795..1e26cc68622 100644 --- a/docs/public/_redirects +++ b/docs/public/_redirects @@ -1,2 +1,15 @@ -/ph/* https://astro-houston-ph.pages.dev/ph/:splat 200 -/:lang/* /:lang/404/ 404 +# Proxy to Phat Houston from our Product Hunt launch — site operated by Otterlord +/ph/* https://astro-houston-ph.pages.dev/ph/:splat 200 + +# Moved content +/zh/* /zh-cn/:splat +/showcase/ /resources/showcase/ +/:lang/showcase/ /:lang/resources/showcase/ + +# Component docs +/guides/components/ /components/using-components/ +/:lang/guides/components/ /:lang/components/using-components/ + +# Translated 404s +/:lang/* /:lang/404/ 404 +/* /404/ 404 diff --git a/docs/public/ph-houston.svg b/docs/public/ph-houston.svg deleted file mode 100644 index 1e6733528f9..00000000000 --- a/docs/public/ph-houston.svg +++ /dev/null @@ -1,87 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" viewBox="0 0 75 75"> - <defs> - <path id="e" fill="#79E399" fill-opacity=".8" d="M20.2 37.63h10.24v3.88a.7.7 0 0 1-.7.7H20.2v-4.58Z"/> - </defs> - <circle cx="37.66" cy="37.78" r="31.76" fill="url(#a)" fill-opacity=".25"/> - <circle cx="37.66" cy="37.78" r="36.42" stroke="url(#b)" stroke-opacity=".25" stroke-width=".85"/> - <path fill="#7F7F7F" d="m30.09 43.3-14.22-6.25-2.2 5.13 14.15 6.28 2.27-5.17Zm15.88-1.44 14.36-6.31.91 2.07-14.36 6.3z"/> - <clipPath id="c"> - <path d="M14.91 26.71c0-3.33 2.7-6.02 6.03-6.02h33.12c3.33 0 6.03 2.7 6.03 6.02v21.83c0 3.33-2.7 6.03-6.03 6.03H20.94a6.02 6.02 0 0 1-6.03-6.03V26.71Z"/> - </clipPath> - <foreignObject width="100%" height="100%" clip-path="url(#c)"> - <div xmlns="http://www.w3.org/1999/xhtml" style="width:100%;height:100%;background:conic-gradient(from 0deg at 50% 50%,#3245ff 0deg,#bc52ee 103.12500357627869deg,#4af2c8 149.1623318195343deg,#4af2c8 199.67810153961182deg,#3245ff 360deg)"/> - </foreignObject> - <path fill="url(#d)" d="M16.68 27.26a4.82 4.82 0 0 1 4.83-4.8H53.5a4.82 4.82 0 0 1 4.83 4.8V48a4.82 4.82 0 0 1-4.83 4.81h-32a4.82 4.82 0 0 1-4.83-4.8V27.25Z"/> - <path fill="#fff" d="M29.13 41.16a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Zm8.25 2.24c1.24 0 2.24-1 2.24-2.24h1.5a3.75 3.75 0 1 1-7.5 0h1.5a2.26 2.26 0 0 0 2.26 2.25Zm15.74-2.24a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z"/> - <mask id="f" width="11" height="6" x="20" y="37" maskUnits="userSpaceOnUse" style="mask-type:alpha"> - <use xlink:href="#e" fill-opacity=".8"/> - </mask> - <g mask="url(#f)"> - <g filter="url(#g)"> - <mask id="h" fill="#fff"> - <path d="M20.2 37.63h10.24v3.88a.7.7 0 0 1-.7.7H20.2v-4.58Z"/> - </mask> - <use xlink:href="#e" fill-opacity=".8"/> - <path fill="#000" fill-opacity=".6" d="M20.2 37.63h10.24-10.23Zm10.6 3.88c0 .58-.48 1.06-1.06 1.06h-9.89l.71-.7h9.18c.2 0 .35-.17.35-.36h.7Zm-10.95 1.06v-4.94h.71v4.23l-.7.7Zm10.94-4.94v3.88c0 .58-.47 1.06-1.05 1.06v-.7c.2 0 .35-.17.35-.36v-3.88h.7Z" mask="url(#h)" style="mix-blend-mode:overlay"/> - </g> - <g filter="url(#i)" opacity=".6" style="mix-blend-mode:overlay"> - <path fill="#fff" d="m30.72 31.26 1.5 1.5-15.47 15.47-1.5-1.5z"/> - </g> - <g filter="url(#j)" opacity=".6" style="mix-blend-mode:overlay"> - <path fill="#fff" d="m36.37 31.26.75.75-15.47 15.47-.75-.75z"/> - </g> - </g> - <mask id="k" width="49" height="8" x="13" y="35" maskUnits="userSpaceOnUse" style="mask-type:alpha"> - <path fill="#D9D9D9" d="M13.86 35.16a.7.7 0 0 0-.71.7v5.65c0 .39.32.7.7.7h6.71v-4.58h40.59a.7.7 0 0 0 .7-.7v-1.07a.7.7 0 0 0-.7-.7h-47.3Z"/> - </mask> - <g mask="url(#k)"> - <path fill="#D9D9D9" d="M13.15 35.16a.7.7 0 0 0-.7.7v5.65c0 .39.3.7.7.7h8.12v-4.58h40.58a.7.7 0 0 0 .7-.7v-1.07a.7.7 0 0 0-.7-.7h-48.7Z"/> - <path fill="url(#l)" fill-opacity=".2" d="M13.15 35.16a.7.7 0 0 0-.7.7v5.65c0 .39.3.7.7.7h8.12v-4.58h40.58a.7.7 0 0 0 .7-.7v-1.07a.7.7 0 0 0-.7-.7h-48.7Z" style="mix-blend-mode:overlay"/> - <path fill="#7F7F7F" d="M13.86 34.1h.35v10.23h-.35zm6.7 3.53v-.35h44.11v.35z"/> - <path fill="#7F7F7F" d="M12.09 42.22v-.35h43.4v.35z"/> - <path fill="#fff" d="M8.91 32.69h55.76v2.82H8.91z" style="mix-blend-mode:overlay"/> - </g> - <circle cx="17.74" cy="39.04" r="1.41" fill="#373941"/> - <circle cx="17.74" cy="39.04" r="1.06" fill="#0F1119"/> - <circle cx="17.74" cy="39.04" r=".64" fill="url(#m)"/> - <circle cx="17.74" cy="39.04" r=".64" stroke="#fff" stroke-width=".14" style="mix-blend-mode:overlay"/> - <defs> - <linearGradient id="a" x1="37.66" x2="37.66" y1="6.02" y2="69.55" gradientUnits="userSpaceOnUse"> - <stop stop-color="#12101E"/> - <stop offset="1" stop-color="#12101E" stop-opacity=".25"/> - </linearGradient> - <linearGradient id="b" x1="37.66" x2="37.66" y1=".94" y2="74.63" gradientUnits="userSpaceOnUse"> - <stop stop-color="#12101E"/> - <stop offset="1" stop-color="#12101E" stop-opacity=".25"/> - </linearGradient> - <linearGradient id="l" x1="37.5" x2="37.5" y1="35.16" y2="42.21" gradientUnits="userSpaceOnUse"> - <stop/> - <stop offset="1" stop-color="#fff"/> - </linearGradient> - <linearGradient id="m" x1="17.74" x2="18.09" y1="38.33" y2="39.74" gradientUnits="userSpaceOnUse"> - <stop stop-color="#BBE970" stop-opacity="0"/> - <stop offset="1" stop-color="#E9B170"/> - </linearGradient> - <filter id="g" width="10.94" height="5.29" x="19.85" y="37.27" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"> - <feFlood flood-opacity="0" result="BackgroundImageFix"/> - <feGaussianBlur in="BackgroundImageFix" stdDeviation=".18"/> - <feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_1518_22944"/> - <feBlend in="SourceGraphic" in2="effect1_backgroundBlur_1518_22944" result="shape"/> - </filter> - <filter id="i" width="19.09" height="19.09" x="14.19" y="30.2" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"> - <feFlood flood-opacity="0" result="BackgroundImageFix"/> - <feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/> - <feGaussianBlur result="effect1_foregroundBlur_1518_22944" stdDeviation=".53"/> - </filter> - <filter id="j" width="18.34" height="18.34" x="19.84" y="30.2" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"> - <feFlood flood-opacity="0" result="BackgroundImageFix"/> - <feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/> - <feGaussianBlur result="effect1_foregroundBlur_1518_22944" stdDeviation=".53"/> - </filter> - <radialGradient id="d" cx="0" cy="0" r="1" gradientTransform="matrix(0 25 -34 0 37.5 33.83)" gradientUnits="userSpaceOnUse"> - <stop offset=".37" stop-color="#191C24"/> - <stop offset=".66" stop-color="#111218"/> - <stop offset="1" stop-color="#040506"/> - </radialGradient> - </defs> -</svg> diff --git a/docs/src/assets/landing.css b/docs/src/assets/landing.css index ef753eca07a..88f6c63525b 100644 --- a/docs/src/assets/landing.css +++ b/docs/src/assets/landing.css @@ -25,63 +25,3 @@ [data-has-hero] .hero > img { filter: drop-shadow(0 0 3rem var(--overlay-blurple)); } - -/* Product Hunt launch banner — can be removed on 30 August 2023. */ -[data-has-hero] .sl-banner { - --sl-color-banner-bg: #d73f37; - --sl-color-banner-text: #fff; - border-block: 1px solid #fff8; - padding-block: 0; - overflow: hidden; -} - -[data-has-hero] .sl-banner a { - text-decoration: 1px underline; - text-underline-offset: 0.1em; -} - -.ph-banner { - display: flex; - align-items: center; - gap: 1rem; - font-size: clamp(1rem, calc(0.75rem + 1vw), 1.65rem); -} -.ph-houston { - padding-block: 0.25rem; -} -.ph-text { - display: flex; - flex-direction: column; - gap: 0.25rem 1rem; - text-align: start; - padding-block: var(--sl-nav-pad-y); -} -.ph-text strong { - font-weight: 600; -} - -@media (min-width: 23em) { - .ph-banner { - justify-content: center; - } - - .ph-houston img { - vertical-align: middle; - } -} - -@media (min-width: 40em) { - .ph-banner { - gap: 3.5rem; - } - .ph-houston { - padding: 0; - } - .ph-houston img { - scale: 1.75; - } - .ph-text { - flex-direction: row; - flex-wrap: wrap; - } -} diff --git a/docs/src/assets/robots.txt b/docs/src/assets/robots.txt new file mode 100644 index 00000000000..0081d7a6fdf --- /dev/null +++ b/docs/src/assets/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://starlight.astro.build/sitemap-index.xml diff --git a/docs/src/assets/showcase/academeez.com.png b/docs/src/assets/showcase/academeez.com.png new file mode 100644 index 00000000000..145a02b2ae3 Binary files /dev/null and b/docs/src/assets/showcase/academeez.com.png differ diff --git a/docs/src/assets/showcase/accessible-astro.incluud.dev.png b/docs/src/assets/showcase/accessible-astro.incluud.dev.png new file mode 100644 index 00000000000..16797111cff Binary files /dev/null and b/docs/src/assets/showcase/accessible-astro.incluud.dev.png differ diff --git a/docs/src/assets/showcase/actionbase.io.png b/docs/src/assets/showcase/actionbase.io.png new file mode 100644 index 00000000000..2ed5ec651bd Binary files /dev/null and b/docs/src/assets/showcase/actionbase.io.png differ diff --git a/docs/src/assets/showcase/ai-prompt-snippets.png b/docs/src/assets/showcase/ai-prompt-snippets.png new file mode 100644 index 00000000000..9e779636f03 Binary files /dev/null and b/docs/src/assets/showcase/ai-prompt-snippets.png differ diff --git a/docs/src/assets/showcase/api.dipsway.com.png b/docs/src/assets/showcase/api.dipsway.com.png new file mode 100644 index 00000000000..4ae45ff83e2 Binary files /dev/null and b/docs/src/assets/showcase/api.dipsway.com.png differ diff --git a/docs/src/assets/showcase/aptos.dev.png b/docs/src/assets/showcase/aptos.dev.png new file mode 100644 index 00000000000..a9095cfa075 Binary files /dev/null and b/docs/src/assets/showcase/aptos.dev.png differ diff --git a/docs/src/assets/showcase/aspire.dev.png b/docs/src/assets/showcase/aspire.dev.png new file mode 100644 index 00000000000..918c3c1bb48 Binary files /dev/null and b/docs/src/assets/showcase/aspire.dev.png differ diff --git a/docs/src/assets/showcase/astro-error-page-documentation.vercel.app.png b/docs/src/assets/showcase/astro-error-page-documentation.vercel.app.png deleted file mode 100644 index 3f184992911..00000000000 Binary files a/docs/src/assets/showcase/astro-error-page-documentation.vercel.app.png and /dev/null differ diff --git a/docs/src/assets/showcase/astro-snipcart.png b/docs/src/assets/showcase/astro-snipcart.png new file mode 100644 index 00000000000..24f2df33a2d Binary files /dev/null and b/docs/src/assets/showcase/astro-snipcart.png differ diff --git a/docs/src/assets/showcase/bettercap.org.png b/docs/src/assets/showcase/bettercap.org.png new file mode 100644 index 00000000000..3751dab9a2f Binary files /dev/null and b/docs/src/assets/showcase/bettercap.org.png differ diff --git a/docs/src/assets/showcase/biomejs.dev.png b/docs/src/assets/showcase/biomejs.dev.png new file mode 100644 index 00000000000..477734e5767 Binary files /dev/null and b/docs/src/assets/showcase/biomejs.dev.png differ diff --git a/docs/src/assets/showcase/capgo.app.png b/docs/src/assets/showcase/capgo.app.png new file mode 100644 index 00000000000..876d9faccb9 Binary files /dev/null and b/docs/src/assets/showcase/capgo.app.png differ diff --git a/docs/src/assets/showcase/catchintent.com.png b/docs/src/assets/showcase/catchintent.com.png new file mode 100644 index 00000000000..a6b628105c0 Binary files /dev/null and b/docs/src/assets/showcase/catchintent.com.png differ diff --git a/docs/src/assets/showcase/codesweetly.com.png b/docs/src/assets/showcase/codesweetly.com.png new file mode 100644 index 00000000000..64dae43de13 Binary files /dev/null and b/docs/src/assets/showcase/codesweetly.com.png differ diff --git a/docs/src/assets/showcase/contribute.freecodecamp.org.png b/docs/src/assets/showcase/contribute.freecodecamp.org.png new file mode 100644 index 00000000000..3d6abdafb87 Binary files /dev/null and b/docs/src/assets/showcase/contribute.freecodecamp.org.png differ diff --git a/docs/src/assets/showcase/crawler.siteone.io.png b/docs/src/assets/showcase/crawler.siteone.io.png new file mode 100644 index 00000000000..e764a8928b8 Binary files /dev/null and b/docs/src/assets/showcase/crawler.siteone.io.png differ diff --git a/docs/src/assets/showcase/create.bingo.png b/docs/src/assets/showcase/create.bingo.png new file mode 100644 index 00000000000..9220e9ed235 Binary files /dev/null and b/docs/src/assets/showcase/create.bingo.png differ diff --git a/docs/src/assets/showcase/dev.vrchatfrance.fr.png b/docs/src/assets/showcase/dev.vrchatfrance.fr.png deleted file mode 100644 index 55286154441..00000000000 Binary files a/docs/src/assets/showcase/dev.vrchatfrance.fr.png and /dev/null differ diff --git a/docs/src/assets/showcase/developers.cloudflare.com.png b/docs/src/assets/showcase/developers.cloudflare.com.png new file mode 100644 index 00000000000..f3150109713 Binary files /dev/null and b/docs/src/assets/showcase/developers.cloudflare.com.png differ diff --git a/docs/src/assets/showcase/dmno.dev.png b/docs/src/assets/showcase/dmno.dev.png new file mode 100644 index 00000000000..b1e9961ed5b Binary files /dev/null and b/docs/src/assets/showcase/dmno.dev.png differ diff --git a/docs/src/assets/showcase/docs.astronvim.com.png b/docs/src/assets/showcase/docs.astronvim.com.png new file mode 100644 index 00000000000..38c3ea0679f Binary files /dev/null and b/docs/src/assets/showcase/docs.astronvim.com.png differ diff --git a/docs/src/assets/showcase/docs.cookie-api.com.png b/docs/src/assets/showcase/docs.cookie-api.com.png new file mode 100644 index 00000000000..186c98a8165 Binary files /dev/null and b/docs/src/assets/showcase/docs.cookie-api.com.png differ diff --git a/docs/src/assets/showcase/docs.emojiblast.dev.png b/docs/src/assets/showcase/docs.emojiblast.dev.png new file mode 100644 index 00000000000..545c031aeef Binary files /dev/null and b/docs/src/assets/showcase/docs.emojiblast.dev.png differ diff --git a/docs/src/assets/showcase/docs.ethfollow.xyz.png b/docs/src/assets/showcase/docs.ethfollow.xyz.png new file mode 100644 index 00000000000..c62f659b0b4 Binary files /dev/null and b/docs/src/assets/showcase/docs.ethfollow.xyz.png differ diff --git a/docs/src/assets/showcase/docs.flojoy.ai.png b/docs/src/assets/showcase/docs.flojoy.ai.png new file mode 100644 index 00000000000..de0ce40acac Binary files /dev/null and b/docs/src/assets/showcase/docs.flojoy.ai.png differ diff --git a/docs/src/assets/showcase/docs.fontawesome.com.png b/docs/src/assets/showcase/docs.fontawesome.com.png new file mode 100644 index 00000000000..f63c9cb5370 Binary files /dev/null and b/docs/src/assets/showcase/docs.fontawesome.com.png differ diff --git a/docs/src/assets/showcase/docs.mrrobot.app.png b/docs/src/assets/showcase/docs.mrrobot.app.png new file mode 100644 index 00000000000..79419392b0f Binary files /dev/null and b/docs/src/assets/showcase/docs.mrrobot.app.png differ diff --git a/docs/src/assets/showcase/docs.netlify.com.png b/docs/src/assets/showcase/docs.netlify.com.png new file mode 100644 index 00000000000..21bab1bba32 Binary files /dev/null and b/docs/src/assets/showcase/docs.netlify.com.png differ diff --git a/docs/src/assets/showcase/docs.papermc.io.png b/docs/src/assets/showcase/docs.papermc.io.png new file mode 100644 index 00000000000..4aa70ed7cc1 Binary files /dev/null and b/docs/src/assets/showcase/docs.papermc.io.png differ diff --git a/docs/src/assets/showcase/docs.pubindexapi.com.png b/docs/src/assets/showcase/docs.pubindexapi.com.png deleted file mode 100644 index 26f687e7a17..00000000000 Binary files a/docs/src/assets/showcase/docs.pubindexapi.com.png and /dev/null differ diff --git a/docs/src/assets/showcase/docs.reactbricks.com.png b/docs/src/assets/showcase/docs.reactbricks.com.png new file mode 100644 index 00000000000..d6fb7f12498 Binary files /dev/null and b/docs/src/assets/showcase/docs.reactbricks.com.png differ diff --git a/docs/src/assets/showcase/docs.scalekit.com.png b/docs/src/assets/showcase/docs.scalekit.com.png new file mode 100644 index 00000000000..118220682fc Binary files /dev/null and b/docs/src/assets/showcase/docs.scalekit.com.png differ diff --git a/docs/src/assets/showcase/docs.stackit.cloud.png b/docs/src/assets/showcase/docs.stackit.cloud.png new file mode 100644 index 00000000000..45a874fee6c Binary files /dev/null and b/docs/src/assets/showcase/docs.stackit.cloud.png differ diff --git a/docs/src/assets/showcase/docs.vlt.sh.png b/docs/src/assets/showcase/docs.vlt.sh.png new file mode 100644 index 00000000000..ba14b22839a Binary files /dev/null and b/docs/src/assets/showcase/docs.vlt.sh.png differ diff --git a/docs/src/assets/showcase/document.saasfly.io.png b/docs/src/assets/showcase/document.saasfly.io.png new file mode 100644 index 00000000000..4036e7eb9a9 Binary files /dev/null and b/docs/src/assets/showcase/document.saasfly.io.png differ diff --git a/docs/src/assets/showcase/drops-of-php.hi-folks.dev.png b/docs/src/assets/showcase/drops-of-php.hi-folks.dev.png new file mode 100644 index 00000000000..ea597b1c1e7 Binary files /dev/null and b/docs/src/assets/showcase/drops-of-php.hi-folks.dev.png differ diff --git a/docs/src/assets/showcase/ee.qqv.com.au.png b/docs/src/assets/showcase/ee.qqv.com.au.png new file mode 100644 index 00000000000..2dff3d94bcf Binary files /dev/null and b/docs/src/assets/showcase/ee.qqv.com.au.png differ diff --git a/docs/src/assets/showcase/events-3bg.pages.dev.png b/docs/src/assets/showcase/events-3bg.pages.dev.png new file mode 100755 index 00000000000..3fcc17d7ec6 Binary files /dev/null and b/docs/src/assets/showcase/events-3bg.pages.dev.png differ diff --git a/docs/src/assets/showcase/feedbackspark.com.png b/docs/src/assets/showcase/feedbackspark.com.png new file mode 100644 index 00000000000..e751db31631 Binary files /dev/null and b/docs/src/assets/showcase/feedbackspark.com.png differ diff --git a/docs/src/assets/showcase/fluid-dnd.png b/docs/src/assets/showcase/fluid-dnd.png new file mode 100644 index 00000000000..9e301c51c01 Binary files /dev/null and b/docs/src/assets/showcase/fluid-dnd.png differ diff --git a/docs/src/assets/showcase/folksrouter.io.png b/docs/src/assets/showcase/folksrouter.io.png new file mode 100644 index 00000000000..0a0a2f89b6a Binary files /dev/null and b/docs/src/assets/showcase/folksrouter.io.png differ diff --git a/docs/src/assets/showcase/fomr.io.png b/docs/src/assets/showcase/fomr.io.png new file mode 100644 index 00000000000..fb20adb4374 Binary files /dev/null and b/docs/src/assets/showcase/fomr.io.png differ diff --git a/docs/src/assets/showcase/formware.io.png b/docs/src/assets/showcase/formware.io.png new file mode 100644 index 00000000000..58643e3e865 Binary files /dev/null and b/docs/src/assets/showcase/formware.io.png differ diff --git a/docs/src/assets/showcase/grpc.md.png b/docs/src/assets/showcase/grpc.md.png new file mode 100644 index 00000000000..ce0ab614b91 Binary files /dev/null and b/docs/src/assets/showcase/grpc.md.png differ diff --git a/docs/src/assets/showcase/ion.sst.dev.png b/docs/src/assets/showcase/ion.sst.dev.png new file mode 100644 index 00000000000..67908448fd6 Binary files /dev/null and b/docs/src/assets/showcase/ion.sst.dev.png differ diff --git a/docs/src/assets/showcase/itihon.github.io-isomorphic-validation.png b/docs/src/assets/showcase/itihon.github.io-isomorphic-validation.png new file mode 100644 index 00000000000..596f4aeae38 Binary files /dev/null and b/docs/src/assets/showcase/itihon.github.io-isomorphic-validation.png differ diff --git a/docs/src/assets/showcase/kinde.com.png b/docs/src/assets/showcase/kinde.com.png new file mode 100644 index 00000000000..8b84c896c51 Binary files /dev/null and b/docs/src/assets/showcase/kinde.com.png differ diff --git a/docs/src/assets/showcase/knip.dev.png b/docs/src/assets/showcase/knip.dev.png new file mode 100644 index 00000000000..3c4ba4c502f Binary files /dev/null and b/docs/src/assets/showcase/knip.dev.png differ diff --git a/docs/src/assets/showcase/launchfa.st.png b/docs/src/assets/showcase/launchfa.st.png new file mode 100644 index 00000000000..2573d05885b Binary files /dev/null and b/docs/src/assets/showcase/launchfa.st.png differ diff --git a/docs/src/assets/showcase/lavamoat.github.io.png b/docs/src/assets/showcase/lavamoat.github.io.png new file mode 100644 index 00000000000..77579b4405b Binary files /dev/null and b/docs/src/assets/showcase/lavamoat.github.io.png differ diff --git a/docs/src/assets/showcase/learnaiso.com.png b/docs/src/assets/showcase/learnaiso.com.png new file mode 100644 index 00000000000..9fff6748ae6 Binary files /dev/null and b/docs/src/assets/showcase/learnaiso.com.png differ diff --git a/docs/src/assets/showcase/lychee.cli.rs.png b/docs/src/assets/showcase/lychee.cli.rs.png new file mode 100644 index 00000000000..d6d5b77b455 Binary files /dev/null and b/docs/src/assets/showcase/lychee.cli.rs.png differ diff --git a/docs/src/assets/showcase/modestbench.dev.png b/docs/src/assets/showcase/modestbench.dev.png new file mode 100644 index 00000000000..54bacff9318 Binary files /dev/null and b/docs/src/assets/showcase/modestbench.dev.png differ diff --git a/docs/src/assets/showcase/nostalgist.js.org.png b/docs/src/assets/showcase/nostalgist.js.org.png new file mode 100644 index 00000000000..35a5f54bf96 Binary files /dev/null and b/docs/src/assets/showcase/nostalgist.js.org.png differ diff --git a/docs/src/assets/showcase/octo.guide.png b/docs/src/assets/showcase/octo.guide.png new file mode 100644 index 00000000000..2373af58c9a Binary files /dev/null and b/docs/src/assets/showcase/octo.guide.png differ diff --git a/docs/src/assets/showcase/omni-byte.com.png b/docs/src/assets/showcase/omni-byte.com.png new file mode 100644 index 00000000000..7e40c894145 Binary files /dev/null and b/docs/src/assets/showcase/omni-byte.com.png differ diff --git a/docs/src/assets/showcase/onerepo.tools.png b/docs/src/assets/showcase/onerepo.tools.png new file mode 100644 index 00000000000..72bc27c5de8 Binary files /dev/null and b/docs/src/assets/showcase/onerepo.tools.png differ diff --git a/docs/src/assets/showcase/openai.github.io.png b/docs/src/assets/showcase/openai.github.io.png new file mode 100644 index 00000000000..a70deb423fe Binary files /dev/null and b/docs/src/assets/showcase/openai.github.io.png differ diff --git a/docs/src/assets/showcase/opencode.ai.png b/docs/src/assets/showcase/opencode.ai.png new file mode 100644 index 00000000000..7db36235fad Binary files /dev/null and b/docs/src/assets/showcase/opencode.ai.png differ diff --git a/docs/src/assets/showcase/openresource.dev.png b/docs/src/assets/showcase/openresource.dev.png new file mode 100644 index 00000000000..f611966fdfb Binary files /dev/null and b/docs/src/assets/showcase/openresource.dev.png differ diff --git a/docs/src/assets/showcase/opensaas.sh.png b/docs/src/assets/showcase/opensaas.sh.png new file mode 100644 index 00000000000..14e6c94dbc5 Binary files /dev/null and b/docs/src/assets/showcase/opensaas.sh.png differ diff --git a/docs/src/assets/showcase/openstatus.dev.png b/docs/src/assets/showcase/openstatus.dev.png new file mode 100644 index 00000000000..2431ea402e0 Binary files /dev/null and b/docs/src/assets/showcase/openstatus.dev.png differ diff --git a/docs/src/assets/showcase/dhruvkb.github.io-pls.png b/docs/src/assets/showcase/pls.cli.rs.png similarity index 100% rename from docs/src/assets/showcase/dhruvkb.github.io-pls.png rename to docs/src/assets/showcase/pls.cli.rs.png diff --git a/docs/src/assets/showcase/pokemon-siace.netlify.app.png b/docs/src/assets/showcase/pokemon-siace.netlify.app.png new file mode 100644 index 00000000000..8b0078df84b Binary files /dev/null and b/docs/src/assets/showcase/pokemon-siace.netlify.app.png differ diff --git a/docs/src/assets/showcase/quotesdomain.com.png b/docs/src/assets/showcase/quotesdomain.com.png new file mode 100644 index 00000000000..d9d1f0ed372 Binary files /dev/null and b/docs/src/assets/showcase/quotesdomain.com.png differ diff --git a/docs/src/assets/showcase/react-awesome-reveal.morello.dev.png b/docs/src/assets/showcase/react-awesome-reveal.morello.dev.png new file mode 100644 index 00000000000..9ab91ba49e4 Binary files /dev/null and b/docs/src/assets/showcase/react-awesome-reveal.morello.dev.png differ diff --git a/docs/src/assets/showcase/runs-on.com.png b/docs/src/assets/showcase/runs-on.com.png new file mode 100644 index 00000000000..5a29eeb8787 Binary files /dev/null and b/docs/src/assets/showcase/runs-on.com.png differ diff --git a/docs/src/assets/showcase/saucer.app.png b/docs/src/assets/showcase/saucer.app.png new file mode 100644 index 00000000000..c777e37cb46 Binary files /dev/null and b/docs/src/assets/showcase/saucer.app.png differ diff --git a/docs/src/assets/showcase/screenshotone.com.png b/docs/src/assets/showcase/screenshotone.com.png new file mode 100644 index 00000000000..9a6bb80bdb2 Binary files /dev/null and b/docs/src/assets/showcase/screenshotone.com.png differ diff --git a/docs/src/assets/showcase/secco.lekoarts.de.png b/docs/src/assets/showcase/secco.lekoarts.de.png new file mode 100644 index 00000000000..5ee9249f47b Binary files /dev/null and b/docs/src/assets/showcase/secco.lekoarts.de.png differ diff --git a/docs/src/assets/showcase/sharp.pixelplumbing.com.png b/docs/src/assets/showcase/sharp.pixelplumbing.com.png new file mode 100644 index 00000000000..6b417f294ce Binary files /dev/null and b/docs/src/assets/showcase/sharp.pixelplumbing.com.png differ diff --git a/docs/src/assets/showcase/simple.arciniega.one.png b/docs/src/assets/showcase/simple.arciniega.one.png deleted file mode 100644 index 1156e14e07c..00000000000 Binary files a/docs/src/assets/showcase/simple.arciniega.one.png and /dev/null differ diff --git a/docs/src/assets/showcase/sonar-team.github.io.png b/docs/src/assets/showcase/sonar-team.github.io.png new file mode 100644 index 00000000000..c494d0a390a Binary files /dev/null and b/docs/src/assets/showcase/sonar-team.github.io.png differ diff --git a/docs/src/assets/showcase/styledictionary.com.png b/docs/src/assets/showcase/styledictionary.com.png new file mode 100644 index 00000000000..c8d04e0a876 Binary files /dev/null and b/docs/src/assets/showcase/styledictionary.com.png differ diff --git a/docs/src/assets/showcase/texttotableconverter.com.png b/docs/src/assets/showcase/texttotableconverter.com.png new file mode 100644 index 00000000000..62a6e8e0325 Binary files /dev/null and b/docs/src/assets/showcase/texttotableconverter.com.png differ diff --git a/docs/src/assets/showcase/truecharts.org.png b/docs/src/assets/showcase/truecharts.org.png new file mode 100644 index 00000000000..e75c2d99edf Binary files /dev/null and b/docs/src/assets/showcase/truecharts.org.png differ diff --git a/docs/src/assets/showcase/tutorialkit.dev.png b/docs/src/assets/showcase/tutorialkit.dev.png new file mode 100644 index 00000000000..a69751b3ed1 Binary files /dev/null and b/docs/src/assets/showcase/tutorialkit.dev.png differ diff --git a/docs/src/assets/showcase/vtbag.dev.png b/docs/src/assets/showcase/vtbag.dev.png new file mode 100755 index 00000000000..a30edec0a51 Binary files /dev/null and b/docs/src/assets/showcase/vtbag.dev.png differ diff --git a/docs/src/assets/showcase/www.devhealthos.com.png b/docs/src/assets/showcase/www.devhealthos.com.png new file mode 100644 index 00000000000..d9318fab008 Binary files /dev/null and b/docs/src/assets/showcase/www.devhealthos.com.png differ diff --git a/docs/src/assets/showcase/www.pydocs.site.png b/docs/src/assets/showcase/www.pydocs.site.png new file mode 100644 index 00000000000..f0b8a6b2133 Binary files /dev/null and b/docs/src/assets/showcase/www.pydocs.site.png differ diff --git a/docs/src/assets/showcase/zumerlab.github.io.orbit-docs.png b/docs/src/assets/showcase/zumerlab.github.io.orbit-docs.png new file mode 100644 index 00000000000..53e96874081 Binary files /dev/null and b/docs/src/assets/showcase/zumerlab.github.io.orbit-docs.png differ diff --git a/docs/src/assets/testimonials/BowTiedWebReapr.jpg b/docs/src/assets/testimonials/BowTiedWebReapr.jpg new file mode 100644 index 00000000000..1280ca5d723 Binary files /dev/null and b/docs/src/assets/testimonials/BowTiedWebReapr.jpg differ diff --git a/docs/src/assets/testimonials/J_Everhart383.jpg b/docs/src/assets/testimonials/J_Everhart383.jpg new file mode 100644 index 00000000000..165a032e38b Binary files /dev/null and b/docs/src/assets/testimonials/J_Everhart383.jpg differ diff --git a/docs/src/assets/testimonials/RmeetsH.jpg b/docs/src/assets/testimonials/RmeetsH.jpg new file mode 100644 index 00000000000..fc2e0e17ffd Binary files /dev/null and b/docs/src/assets/testimonials/RmeetsH.jpg differ diff --git a/docs/src/assets/testimonials/SylwiaVargas.jpg b/docs/src/assets/testimonials/SylwiaVargas.jpg new file mode 100644 index 00000000000..860d2f4e3ca Binary files /dev/null and b/docs/src/assets/testimonials/SylwiaVargas.jpg differ diff --git a/docs/src/assets/testimonials/beaussan.jpg b/docs/src/assets/testimonials/beaussan.jpg new file mode 100644 index 00000000000..9eeb270ddcd Binary files /dev/null and b/docs/src/assets/testimonials/beaussan.jpg differ diff --git a/docs/src/assets/testimonials/flaviocopes.jpg b/docs/src/assets/testimonials/flaviocopes.jpg new file mode 100644 index 00000000000..fed48386838 Binary files /dev/null and b/docs/src/assets/testimonials/flaviocopes.jpg differ diff --git a/docs/src/assets/testimonials/jhooks.jpg b/docs/src/assets/testimonials/jhooks.jpg new file mode 100644 index 00000000000..ab5c7e32665 Binary files /dev/null and b/docs/src/assets/testimonials/jhooks.jpg differ diff --git a/docs/src/assets/testimonials/loucyx.jpg b/docs/src/assets/testimonials/loucyx.jpg new file mode 100644 index 00000000000..ea89003744d Binary files /dev/null and b/docs/src/assets/testimonials/loucyx.jpg differ diff --git a/docs/src/assets/testimonials/rachelnabors.jpg b/docs/src/assets/testimonials/rachelnabors.jpg new file mode 100644 index 00000000000..14a1563930d Binary files /dev/null and b/docs/src/assets/testimonials/rachelnabors.jpg differ diff --git a/docs/src/assets/testimonials/rick_viscomi.jpg b/docs/src/assets/testimonials/rick_viscomi.jpg new file mode 100644 index 00000000000..685b997c0b0 Binary files /dev/null and b/docs/src/assets/testimonials/rick_viscomi.jpg differ diff --git a/docs/src/assets/testimonials/solelychloe.jpg b/docs/src/assets/testimonials/solelychloe.jpg new file mode 100644 index 00000000000..79e83c2eed3 Binary files /dev/null and b/docs/src/assets/testimonials/solelychloe.jpg differ diff --git a/docs/src/assets/testimonials/sulco.jpg b/docs/src/assets/testimonials/sulco.jpg new file mode 100644 index 00000000000..c346a086a0c Binary files /dev/null and b/docs/src/assets/testimonials/sulco.jpg differ diff --git a/docs/src/assets/themes/black-dark.png b/docs/src/assets/themes/black-dark.png new file mode 100644 index 00000000000..7bc9c091941 Binary files /dev/null and b/docs/src/assets/themes/black-dark.png differ diff --git a/docs/src/assets/themes/black-light.png b/docs/src/assets/themes/black-light.png new file mode 100644 index 00000000000..4b216d254a0 Binary files /dev/null and b/docs/src/assets/themes/black-light.png differ diff --git a/docs/src/assets/themes/catppuccin-dark.png b/docs/src/assets/themes/catppuccin-dark.png new file mode 100644 index 00000000000..45539e5bf30 Binary files /dev/null and b/docs/src/assets/themes/catppuccin-dark.png differ diff --git a/docs/src/assets/themes/catppuccin-light.png b/docs/src/assets/themes/catppuccin-light.png new file mode 100644 index 00000000000..ffcbec68373 Binary files /dev/null and b/docs/src/assets/themes/catppuccin-light.png differ diff --git a/docs/src/assets/themes/flexoki-dark.png b/docs/src/assets/themes/flexoki-dark.png new file mode 100644 index 00000000000..01e44078f3c Binary files /dev/null and b/docs/src/assets/themes/flexoki-dark.png differ diff --git a/docs/src/assets/themes/flexoki-light.png b/docs/src/assets/themes/flexoki-light.png new file mode 100644 index 00000000000..660a185a1f0 Binary files /dev/null and b/docs/src/assets/themes/flexoki-light.png differ diff --git a/docs/src/assets/themes/galaxy-dark.png b/docs/src/assets/themes/galaxy-dark.png new file mode 100644 index 00000000000..ded5ffd319f Binary files /dev/null and b/docs/src/assets/themes/galaxy-dark.png differ diff --git a/docs/src/assets/themes/galaxy-light.png b/docs/src/assets/themes/galaxy-light.png new file mode 100644 index 00000000000..6c79dfd02af Binary files /dev/null and b/docs/src/assets/themes/galaxy-light.png differ diff --git a/docs/src/assets/themes/gruvbox-dark.png b/docs/src/assets/themes/gruvbox-dark.png new file mode 100644 index 00000000000..981828b492e Binary files /dev/null and b/docs/src/assets/themes/gruvbox-dark.png differ diff --git a/docs/src/assets/themes/gruvbox-light.png b/docs/src/assets/themes/gruvbox-light.png new file mode 100644 index 00000000000..c48b1593244 Binary files /dev/null and b/docs/src/assets/themes/gruvbox-light.png differ diff --git a/docs/src/assets/themes/ion-dark.png b/docs/src/assets/themes/ion-dark.png new file mode 100644 index 00000000000..455ece2da4f Binary files /dev/null and b/docs/src/assets/themes/ion-dark.png differ diff --git a/docs/src/assets/themes/ion-light.png b/docs/src/assets/themes/ion-light.png new file mode 100644 index 00000000000..718745e73fa Binary files /dev/null and b/docs/src/assets/themes/ion-light.png differ diff --git a/docs/src/assets/themes/nextjs-dark.png b/docs/src/assets/themes/nextjs-dark.png new file mode 100644 index 00000000000..c3d06d95009 Binary files /dev/null and b/docs/src/assets/themes/nextjs-dark.png differ diff --git a/docs/src/assets/themes/nextjs-light.png b/docs/src/assets/themes/nextjs-light.png new file mode 100644 index 00000000000..30fa8e3b223 Binary files /dev/null and b/docs/src/assets/themes/nextjs-light.png differ diff --git a/docs/src/assets/themes/nova-dark.png b/docs/src/assets/themes/nova-dark.png new file mode 100644 index 00000000000..fbfc35a6eea Binary files /dev/null and b/docs/src/assets/themes/nova-dark.png differ diff --git a/docs/src/assets/themes/nova-light.png b/docs/src/assets/themes/nova-light.png new file mode 100644 index 00000000000..c43a6709717 Binary files /dev/null and b/docs/src/assets/themes/nova-light.png differ diff --git a/docs/src/assets/themes/obsidian-dark.png b/docs/src/assets/themes/obsidian-dark.png new file mode 100644 index 00000000000..d317d9c8a32 Binary files /dev/null and b/docs/src/assets/themes/obsidian-dark.png differ diff --git a/docs/src/assets/themes/obsidian-light.png b/docs/src/assets/themes/obsidian-light.png new file mode 100644 index 00000000000..be84b2999b1 Binary files /dev/null and b/docs/src/assets/themes/obsidian-light.png differ diff --git a/docs/src/assets/themes/page-dark.png b/docs/src/assets/themes/page-dark.png new file mode 100644 index 00000000000..171a08c3edb Binary files /dev/null and b/docs/src/assets/themes/page-dark.png differ diff --git a/docs/src/assets/themes/page-light.png b/docs/src/assets/themes/page-light.png new file mode 100644 index 00000000000..66b01ff27d2 Binary files /dev/null and b/docs/src/assets/themes/page-light.png differ diff --git a/docs/src/assets/themes/rapide-dark.png b/docs/src/assets/themes/rapide-dark.png new file mode 100644 index 00000000000..854eb23dc63 Binary files /dev/null and b/docs/src/assets/themes/rapide-dark.png differ diff --git a/docs/src/assets/themes/rapide-light.png b/docs/src/assets/themes/rapide-light.png new file mode 100644 index 00000000000..c2bdcec52b2 Binary files /dev/null and b/docs/src/assets/themes/rapide-light.png differ diff --git a/docs/src/assets/themes/rose-pine-dark.png b/docs/src/assets/themes/rose-pine-dark.png new file mode 100644 index 00000000000..44930c36641 Binary files /dev/null and b/docs/src/assets/themes/rose-pine-dark.png differ diff --git a/docs/src/assets/themes/rose-pine-light.png b/docs/src/assets/themes/rose-pine-light.png new file mode 100644 index 00000000000..97fc3805a27 Binary files /dev/null and b/docs/src/assets/themes/rose-pine-light.png differ diff --git a/docs/src/assets/themes/six-dark.png b/docs/src/assets/themes/six-dark.png new file mode 100644 index 00000000000..f1832a5c7f9 Binary files /dev/null and b/docs/src/assets/themes/six-dark.png differ diff --git a/docs/src/assets/themes/six-light.png b/docs/src/assets/themes/six-light.png new file mode 100644 index 00000000000..79c08fda8e1 Binary files /dev/null and b/docs/src/assets/themes/six-light.png differ diff --git a/docs/src/assets/themes/vintage-dark.png b/docs/src/assets/themes/vintage-dark.png new file mode 100644 index 00000000000..1e0cb9bc2c9 Binary files /dev/null and b/docs/src/assets/themes/vintage-dark.png differ diff --git a/docs/src/assets/themes/vintage-light.png b/docs/src/assets/themes/vintage-light.png new file mode 100644 index 00000000000..7b8a020bc00 Binary files /dev/null and b/docs/src/assets/themes/vintage-light.png differ diff --git a/docs/src/components/about-astro.astro b/docs/src/components/about-astro.astro index 964a40ea30f..665d11258a6 100644 --- a/docs/src/components/about-astro.astro +++ b/docs/src/components/about-astro.astro @@ -6,7 +6,7 @@ interface Props { const { title } = Astro.props; --- -<article class="sl-flex not-content" aria-labelledby="about-astro-heading"> +<article class="sl-flex" aria-labelledby="about-astro-heading"> <small id="about-astro-heading"> {title} <span class="sr-only">Astro</span> @@ -37,6 +37,7 @@ const { title } = Astro.props; } article > :global(*) { max-width: 50ch; + margin-top: 0 !important; } small { color: var(--sl-color-gray-3); diff --git a/docs/src/components/component-preview.astro b/docs/src/components/component-preview.astro new file mode 100644 index 00000000000..41d71815f25 --- /dev/null +++ b/docs/src/components/component-preview.astro @@ -0,0 +1,49 @@ +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +const showContentTypeTabs = Astro.slots.has('markdoc'); +--- + +<figure> + { + showContentTypeTabs ? ( + <Tabs syncKey="content-type"> + <TabItem label="MDX"> + <slot /> + </TabItem> + <TabItem label="Markdoc"> + <slot name="markdoc" /> + </TabItem> + </Tabs> + ) : ( + <slot /> + ) + } + <div class="preview"> + <figcaption>{Astro.locals.t('component.preview')}</figcaption> + <div class="preview-content"><slot name="preview" /></div> + </div> +</figure> + +<style> + :global(.sl-markdown-content) .preview { + border: 1px solid var(--sl-color-gray-5); + border-top: none; + margin-top: 0; + } + + .preview:only-child { + border-top: 1px solid var(--sl-color-gray-5); + } + + figcaption { + font-size: var(--sl-text-sm); + font-weight: 600; + padding: 0.5rem 1rem 0; + } + + :global(.sl-markdown-content) .preview-content { + margin-top: 0; + padding: 1rem; + } +</style> diff --git a/docs/src/components/file-tree.astro b/docs/src/components/file-tree.astro deleted file mode 100644 index db0a27e8a26..00000000000 --- a/docs/src/components/file-tree.astro +++ /dev/null @@ -1,146 +0,0 @@ ---- -import { fileTreeProcessor } from './internal/rehype-file-tree'; - -const content = await Astro.slots.render('default'); -if (!/^\s*<ul>/.test(content)) { - throw new Error( - `<FileTree> component expects its content to be an unordered list but found HTML starting with “${content.slice( - 0, - 20 - )}...”` - ); -} - -const processedContent = await fileTreeProcessor.process({ - value: content, - data: { directoryLabel: 'Directory' }, -}); ---- - -<file-tree set:html={processedContent} class="not-content" data-pagefind-ignore /> - -<style is:global> - file-tree { - --x-space: 1.5rem; - --y-pad: 0; - - display: block; - border: 1px solid var(--sl-color-gray-5); - padding: 1rem; - background-color: var(--sl-color-gray-6); - font-size: var(--sl-text-xs); - font-family: var(--__sl-font-mono); - overflow-x: auto; - } - - file-tree .directory > details, - file-tree .directory > details:hover, - file-tree .directory > details[open] { - border: 0; - padding: 0; - padding-inline-start: var(--x-space); - background: transparent; - } - - file-tree .directory > details > summary, - file-tree .directory > details[open] > summary { - margin-inline-start: calc(-1 * var(--x-space)); - border: 0; - padding: var(--y-pad) 0.625rem; - font-weight: normal; - color: var(--sl-color-white); - max-width: 100%; - } - - file-tree .directory > details > summary::marker, - file-tree .directory > details > summary::-webkit-details-marker { - color: var(--sl-color-gray-3); - } - - file-tree .directory > details > summary:hover .tree-icon, - file-tree .directory > details > summary:hover { - cursor: pointer; - color: var(--sl-color-text-accent); - fill: var(--sl-color-text-accent); - } - - file-tree ul, - file-tree .directory > details ul { - margin-inline-start: 0.6875rem; - border-inline-start: 1px solid var(--sl-color-gray-5); - padding: 0; - padding-inline-start: 0.125rem; - list-style: none; - } - - file-tree .directory > details > summary:hover ~ ul { - border-color: var(--sl-color-gray-4); - } - - file-tree .directory > details > summary:hover .highlight .tree-icon { - fill: var(--sl-color-text-invert); - } - - file-tree > ul { - margin: 0; - border: 0; - padding: 0; - } - - file-tree li { - padding: var(--y-pad) 0; - } - - file-tree .file { - margin-inline-start: calc(var(--x-space) - 0.125rem); - color: var(--sl-color-white); - } - - file-tree .tree-entry { - display: inline-flex; - align-items: flex-start; - flex-wrap: wrap; - max-width: calc(100% - 1rem); - } - @media (min-width: 30em) { - file-tree .tree-entry { - flex-wrap: nowrap; - } - } - - file-tree .tree-entry > :first-child { - flex-shrink: 0; - } - - file-tree .empty { - color: var(--sl-color-gray-3); - padding-inline-start: 0.375rem; - } - - file-tree .comment { - color: var(--sl-color-gray-3); - padding-inline-start: 1.625rem; - max-width: 24rem; - min-width: 12rem; - } - - file-tree .highlight { - display: inline-block; - border-radius: 0.25rem; - padding-inline-end: 0.5rem; - color: var(--sl-color-text-invert); - background-color: var(--sl-color-text-accent); - } - - file-tree svg.tree-icon { - display: inline; - fill: var(--sl-color-gray-3); - vertical-align: middle; - margin-inline: 0.125rem; - width: 1.25rem; - height: 1.25rem; - } - file-tree .highlight svg.tree-icon { - fill: var(--sl-color-text-invert); - } -</style> diff --git a/docs/src/components/fluid-grid.astro b/docs/src/components/fluid-grid.astro index 0d8130bf948..2be8b70e4d7 100644 --- a/docs/src/components/fluid-grid.astro +++ b/docs/src/components/fluid-grid.astro @@ -1,10 +1,18 @@ +--- +interface Props { + minColumnWidth?: string; + gap?: string; +} +const { minColumnWidth, gap } = Astro.props; +--- + <ul class="fluid-grid"><slot /></ul> -<style> +<style define:vars={{ minColumnWidth, gap }}> .fluid-grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); - gap: 1rem; + grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--minColumnWidth, 11rem)), 1fr)); + gap: var(--gap, 1rem); list-style: none; padding: 0; } diff --git a/docs/src/components/icons-list.astro b/docs/src/components/icons-list.astro index ee1146c03f4..e0e37a98207 100644 --- a/docs/src/components/icons-list.astro +++ b/docs/src/components/icons-list.astro @@ -1,11 +1,19 @@ --- import { Icon } from '@astrojs/starlight/components'; -import { Icons } from '../../../packages/starlight/components/Icons'; +import { Icons, type StarlightIcon } from '../../../packages/starlight/components/Icons'; -const icons = Object.keys(Icons) as (keyof typeof Icons)[]; +interface Props { + labels?: { + copied?: string; + }; +} + +const { copied = 'Copied!' } = Astro.props.labels ?? {}; + +const icons = Object.keys(Icons) as StarlightIcon[]; --- -<div class="icons-grid"> +<div class="icons-grid" data-label-copied={copied}> { icons.map((icon) => { return ( @@ -19,21 +27,22 @@ const icons = Object.keys(Icons) as (keyof typeof Icons)[]; </div> <script> - const icons = document.querySelectorAll<HTMLButtonElement>('.icon-preview'); - icons.forEach((icon) => { - icon.addEventListener('click', () => { - const iconName = icon.dataset.name!; - const copiedValue = `<Icon name="${iconName}" />`; - navigator.clipboard.writeText(copiedValue); + const iconGrid = document.querySelector<HTMLDivElement>('.icons-grid'); + const copiedLabel = document.querySelector<HTMLDivElement>('.icons-grid')?.dataset.labelCopied!; + iconGrid?.addEventListener('click', (event) => { + if (!(event.target instanceof Element)) return; + const icon = event.target.closest('.icon-preview'); + if (!(icon instanceof HTMLButtonElement)) return; + const iconName = icon.dataset.name!; + navigator.clipboard.writeText(iconName); - const iconLabel = icon.querySelector('[aria-live]'); - if (iconLabel) { - iconLabel.textContent = 'Copied!'; - setTimeout(() => { - iconLabel.textContent = iconName; - }, 1000); - } - }); + const iconLabel = icon.querySelector('[aria-live]'); + if (iconLabel) { + iconLabel.textContent = copiedLabel; + setTimeout(() => { + iconLabel.textContent = iconName; + }, 1000); + } }); </script> @@ -54,6 +63,7 @@ const icons = Object.keys(Icons) as (keyof typeof Icons)[]; font-size: var(--sl-text-sm); gap: 0.25rem; margin: 0; + overflow-wrap: anywhere; padding: 0.75rem; background: none; } diff --git a/docs/src/components/internal/file-tree-icons.ts b/docs/src/components/internal/file-tree-icons.ts deleted file mode 100644 index 478c30b128d..00000000000 --- a/docs/src/components/internal/file-tree-icons.ts +++ /dev/null @@ -1,754 +0,0 @@ -/** - * Based on https://github.com/elviswolcott/seti-icons which - * is derived from https://github.com/jesseweed/seti-ui/ - * - * Copyright (c) 2014 Jesse Weed - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -const rawDefinitions = { - files: { - COMMIT_EDITMSG: ['git', 'ignore'], - MERGE_MSG: ['git', 'ignore'], - 'karma.conf.js': ['karma', 'green'], - 'karma.conf.coffee': ['karma', 'green'], - 'README.md': ['info', 'blue'], - 'README.txt': ['info', 'blue'], - README: ['info', 'blue'], - 'CHANGELOG.md': ['clock', 'blue'], - 'CHANGELOG.txt': ['clock', 'blue'], - CHANGELOG: ['clock', 'blue'], - 'CHANGES.md': ['clock', 'blue'], - 'CHANGES.txt': ['clock', 'blue'], - CHANGES: ['clock', 'blue'], - 'VERSION.md': ['clock', 'blue'], - 'VERSION.txt': ['clock', 'blue'], - VERSION: ['clock', 'blue'], - mvnw: ['maven', 'red'], - 'tsconfig.json': ['tsconfig', 'blue'], - 'swagger.json': ['json', 'green'], - 'swagger.yml': ['json', 'green'], - 'swagger.yaml': ['json', 'green'], - 'mime.types': ['config', 'grey-light'], - Jenkinsfile: ['jenkins', 'red'], - 'babel.config.js': ['babel', 'yellow'], - 'babel.config.json': ['babel', 'yellow'], - 'babel.config.cjs': ['babel', 'yellow'], - BUILD: ['bazel', 'green'], - 'BUILD.bazel': ['bazel', 'green'], - WORKSPACE: ['bazel', 'green'], - 'WORKSPACE.bazel': ['bazel', 'green'], - 'bower.json': ['bower', 'orange'], - 'Bower.json': ['bower', 'orange'], - 'firebase.json': ['firebase', 'orange'], - geckodriver: ['firefox', 'orange'], - 'Gruntfile.js': ['grunt', 'orange'], - 'gruntfile.babel.js': ['grunt', 'orange'], - 'Gruntfile.babel.js': ['grunt', 'orange'], - 'gruntfile.js': ['grunt', 'orange'], - 'Gruntfile.coffee': ['grunt', 'orange'], - 'gruntfile.coffee': ['grunt', 'orange'], - 'ionic.config.json': ['ionic', 'blue'], - 'Ionic.config.json': ['ionic', 'blue'], - 'ionic.project': ['ionic', 'blue'], - 'Ionic.project': ['ionic', 'blue'], - 'platformio.ini': ['platformio', 'orange'], - 'rollup.config.js': ['rollup', 'red'], - 'sass-lint.yml': ['sass', 'pink'], - 'stylelint.config.js': ['stylelint', 'white'], - 'stylelint.config.cjs': ['stylelint', 'white'], - 'yarn.clean': ['yarn', 'blue'], - 'yarn.lock': ['yarn', 'blue'], - 'webpack.config.js': ['webpack', 'blue'], - 'webpack.config.cjs': ['webpack', 'blue'], - 'webpack.config.ts': ['webpack', 'blue'], - 'webpack.config.build.js': ['webpack', 'blue'], - 'webpack.config.build.cjs': ['webpack', 'blue'], - 'webpack.config.build.ts': ['webpack', 'blue'], - 'webpack.common.js': ['webpack', 'blue'], - 'webpack.common.cjs': ['webpack', 'blue'], - 'webpack.common.ts': ['webpack', 'blue'], - 'webpack.dev.js': ['webpack', 'blue'], - 'webpack.dev.cjs': ['webpack', 'blue'], - 'webpack.dev.ts': ['webpack', 'blue'], - 'webpack.prod.js': ['webpack', 'blue'], - 'webpack.prod.cjs': ['webpack', 'blue'], - 'webpack.prod.ts': ['webpack', 'blue'], - 'npm-debug.log': ['npm_ignored', 'ignore'], - }, - extensions: { - '.astro': ['astro', 'red'], - '.bsl': ['bsl', 'red'], - '.mdo': ['mdo', 'red'], - '.cls': ['salesforce', 'blue'], - '.apex': ['salesforce', 'blue'], - '.asm': ['asm', 'red'], - '.s': ['asm', 'red'], - '.bicep': ['bicep', 'blue'], - '.bzl': ['bazel', 'green'], - '.bazel': ['bazel', 'green'], - '.BUILD': ['bazel', 'green'], - '.WORKSPACE': ['bazel', 'green'], - '.bazelignore': ['bazel', 'green'], - '.bazelversion': ['bazel', 'green'], - '.c': ['c', 'blue'], - '.h': ['c', 'purple'], - '.m': ['c', 'yellow'], - '.cs': ['c-sharp', 'blue'], - '.cshtml': ['html', 'blue'], - '.aspx': ['html', 'blue'], - '.ascx': ['html', 'green'], - '.asax': ['html', 'yellow'], - '.master': ['html', 'yellow'], - '.cc': ['cpp', 'blue'], - '.cpp': ['cpp', 'blue'], - '.cxx': ['cpp', 'blue'], - '.c++': ['cpp', 'blue'], - '.hh': ['cpp', 'purple'], - '.hpp': ['cpp', 'purple'], - '.hxx': ['cpp', 'purple'], - '.h++': ['cpp', 'purple'], - '.mm': ['cpp', 'yellow'], - '.clj': ['clojure', 'green'], - '.cljs': ['clojure', 'green'], - '.cljc': ['clojure', 'green'], - '.edn': ['clojure', 'blue'], - '.cfc': ['coldfusion', 'blue'], - '.cfm': ['coldfusion', 'blue'], - '.coffee': ['coffee', 'yellow'], - '.litcoffee': ['coffee', 'yellow'], - '.config': ['config', 'grey-light'], - '.cfg': ['config', 'grey-light'], - '.conf': ['config', 'grey-light'], - '.cr': ['crystal', 'white'], - '.ecr': ['crystal_embedded', 'white'], - '.slang': ['crystal_embedded', 'white'], - '.cson': ['json', 'yellow'], - '.css': ['css', 'blue'], - '.css.map': ['css', 'blue'], - '.sss': ['css', 'blue'], - '.csv': ['csv', 'green'], - '.xls': ['xls', 'green'], - '.xlsx': ['xls', 'green'], - '.cu': ['cu', 'green'], - '.cuh': ['cu', 'purple'], - '.hu': ['cu', 'purple'], - '.cake': ['cake', 'red'], - '.ctp': ['cake_php', 'red'], - '.d': ['d', 'red'], - '.doc': ['word', 'blue'], - '.docx': ['word', 'blue'], - '.ejs': ['ejs', 'yellow'], - '.ex': ['elixir', 'purple'], - '.exs': ['elixir_script', 'purple'], - '.elm': ['elm', 'blue'], - '.ico': ['favicon', 'yellow'], - '.fs': ['f-sharp', 'blue'], - '.fsx': ['f-sharp', 'blue'], - '.gitignore': ['git', 'ignore'], - '.gitconfig': ['git', 'ignore'], - '.gitkeep': ['git', 'ignore'], - '.gitattributes': ['git', 'ignore'], - '.gitmodules': ['git', 'ignore'], - '.go': ['go2', 'blue'], - '.slide': ['go', 'blue'], - '.article': ['go', 'blue'], - '.gd': ['godot', 'blue'], - '.godot': ['godot', 'red'], - '.tres': ['godot', 'yellow'], - '.tscn': ['godot', 'purple'], - '.gradle': ['gradle', 'blue'], - '.groovy': ['grails', 'green'], - '.gsp': ['grails', 'green'], - '.gql': ['graphql', 'pink'], - '.graphql': ['graphql', 'pink'], - '.graphqls': ['graphql', 'pink'], - '.hack': ['hacklang', 'orange'], - '.haml': ['haml', 'red'], - '.handlebars': ['mustache', 'orange'], - '.hbs': ['mustache', 'orange'], - '.hjs': ['mustache', 'orange'], - '.hs': ['haskell', 'purple'], - '.lhs': ['haskell', 'purple'], - '.hx': ['haxe', 'orange'], - '.hxs': ['haxe', 'yellow'], - '.hxp': ['haxe', 'blue'], - '.hxml': ['haxe', 'purple'], - '.html': ['html', 'orange'], - '.jade': ['jade', 'red'], - '.java': ['java', 'red'], - '.class': ['java', 'blue'], - '.classpath': ['java', 'red'], - '.properties': ['java', 'red'], - '.js': ['javascript', 'yellow'], - '.js.map': ['javascript', 'yellow'], - '.spec.js': ['javascript', 'orange'], - '.test.js': ['javascript', 'orange'], - '.es': ['javascript', 'yellow'], - '.es5': ['javascript', 'yellow'], - '.es6': ['javascript', 'yellow'], - '.es7': ['javascript', 'yellow'], - '.cjs': ['javascript', 'yellow'], - '.mjs': ['javascript', 'yellow'], - '.jinja': ['jinja', 'red'], - '.jinja2': ['jinja', 'red'], - '.json': ['json', 'yellow'], - '.jl': ['julia', 'purple'], - '.kt': ['kotlin', 'orange'], - '.kts': ['kotlin', 'orange'], - '.dart': ['dart', 'blue'], - '.less': ['less', 'blue'], - '.liquid': ['liquid', 'green'], - '.ls': ['livescript', 'blue'], - '.lua': ['lua', 'blue'], - '.markdown': ['markdown', 'blue'], - '.md': ['markdown', 'blue'], - '.mdx': ['markdown', 'blue'], - '.argdown': ['argdown', 'blue'], - '.ad': ['argdown', 'blue'], - '.mustache': ['mustache', 'orange'], - '.stache': ['mustache', 'orange'], - '.nim': ['nim', 'yellow'], - '.nims': ['nim', 'yellow'], - '.github-issues': ['github', 'white'], - '.ipynb': ['notebook', 'blue'], - '.njk': ['nunjucks', 'green'], - '.nunjucks': ['nunjucks', 'green'], - '.nunjs': ['nunjucks', 'green'], - '.nunj': ['nunjucks', 'green'], - '.njs': ['nunjucks', 'green'], - '.nj': ['nunjucks', 'green'], - '.npm-debug.log': ['npm', 'ignore'], - '.npmignore': ['npm', 'red'], - '.npmrc': ['npm', 'red'], - '.ml': ['ocaml', 'orange'], - '.mli': ['ocaml', 'orange'], - '.cmx': ['ocaml', 'orange'], - '.cmxa': ['ocaml', 'orange'], - '.odata': ['odata', 'orange'], - '.pl': ['perl', 'blue'], - '.php': ['php', 'purple'], - '.php.inc': ['php', 'purple'], - '.pipeline': ['pipeline', 'orange'], - '.pddl': ['pddl', 'purple'], - '.plan': ['plan', 'green'], - '.happenings': ['happenings', 'blue'], - '.ps1': ['powershell', 'blue'], - '.psd1': ['powershell', 'blue'], - '.psm1': ['powershell', 'blue'], - '.prisma': ['prisma', 'blue'], - '.pug': ['pug', 'red'], - '.pp': ['puppet', 'yellow'], - '.epp': ['puppet', 'yellow'], - '.purs': ['purescript', 'white'], - '.py': ['python', 'blue'], - '.jsx': ['react', 'blue'], - '.spec.jsx': ['react', 'orange'], - '.test.jsx': ['react', 'orange'], - '.cjsx': ['react', 'blue'], - '.spec.tsx': ['react', 'orange'], - '.test.tsx': ['react', 'orange'], - '.re': ['reasonml', 'red'], - '.res': ['rescript', 'red'], - '.resi': ['rescript', 'pink'], - '.R': ['R', 'blue'], - '.rmd': ['R', 'blue'], - '.rb': ['ruby', 'red'], - '.erb': ['html_erb', 'red'], - '.erb.html': ['html_erb', 'red'], - '.html.erb': ['html_erb', 'red'], - '.rs': ['rust', 'grey-light'], - '.sass': ['sass', 'pink'], - '.scss': ['sass', 'pink'], - '.springBeans': ['spring', 'green'], - '.slim': ['slim', 'orange'], - '.smarty.tpl': ['smarty', 'yellow'], - '.tpl': ['smarty', 'yellow'], - '.sbt': ['sbt', 'blue'], - '.scala': ['scala', 'red'], - '.sol': ['ethereum', 'blue'], - '.styl': ['stylus', 'green'], - '.svelte': ['svelte', 'red'], - '.swift': ['swift', 'orange'], - '.sql': ['db', 'pink'], - '.soql': ['db', 'blue'], - '.tf': ['terraform', 'purple'], - '.tf.json': ['terraform', 'purple'], - '.tfvars': ['terraform', 'purple'], - '.tfvars.json': ['terraform', 'purple'], - '.tex': ['tex', 'blue'], - '.sty': ['tex', 'yellow'], - '.dtx': ['tex', 'orange'], - '.ins': ['tex', 'white'], - '.txt': ['default', 'white'], - '.toml': ['config', 'grey-light'], - '.twig': ['twig', 'green'], - '.ts': ['typescript', 'blue'], - '.tsx': ['typescript', 'blue'], - '.spec.ts': ['typescript', 'orange'], - '.test.ts': ['typescript', 'orange'], - '.vala': ['vala', 'grey-light'], - '.vapi': ['vala', 'grey-light'], - '.component': ['html', 'orange'], - '.vue': ['vue', 'green'], - '.wasm': ['wasm', 'purple'], - '.wat': ['wat', 'purple'], - '.xml': ['xml', 'orange'], - '.yml': ['yml', 'purple'], - '.yaml': ['yml', 'purple'], - '.pro': ['prolog', 'orange'], - '.zig': ['zig', 'orange'], - '.jar': ['zip', 'red'], - '.zip': ['zip', 'grey-light'], - '.wgt': ['wgt', 'blue'], - '.ai': ['illustrator', 'yellow'], - '.psd': ['photoshop', 'blue'], - '.pdf': ['pdf', 'red'], - '.eot': ['font', 'red'], - '.ttf': ['font', 'red'], - '.woff': ['font', 'red'], - '.woff2': ['font', 'red'], - '.avif': ['image', 'purple'], - '.gif': ['image', 'purple'], - '.jpg': ['image', 'purple'], - '.jpeg': ['image', 'purple'], - '.png': ['image', 'purple'], - '.pxm': ['image', 'purple'], - '.svg': ['svg', 'purple'], - '.svgx': ['image', 'purple'], - '.tiff': ['image', 'purple'], - '.webp': ['image', 'purple'], - '.sublime-project': ['sublime', 'orange'], - '.sublime-workspace': ['sublime', 'orange'], - '.code-search': ['code-search', 'purple'], - '.sh': ['shell', 'green'], - '.zsh': ['shell', 'green'], - '.fish': ['shell', 'green'], - '.zshrc': ['shell', 'green'], - '.bashrc': ['shell', 'green'], - '.mov': ['video', 'pink'], - '.ogv': ['video', 'pink'], - '.webm': ['video', 'pink'], - '.avi': ['video', 'pink'], - '.mpg': ['video', 'pink'], - '.mp4': ['video', 'pink'], - '.mp3': ['audio', 'purple'], - '.ogg': ['audio', 'purple'], - '.wav': ['audio', 'purple'], - '.flac': ['audio', 'purple'], - '.3ds': ['svg', 'blue'], - '.3dm': ['svg', 'blue'], - '.stl': ['svg', 'blue'], - '.obj': ['svg', 'blue'], - '.dae': ['svg', 'blue'], - '.bat': ['windows', 'blue'], - '.cmd': ['windows', 'blue'], - '.babelrc': ['babel', 'yellow'], - '.babelrc.js': ['babel', 'yellow'], - '.babelrc.cjs': ['babel', 'yellow'], - '.bazelrc': ['bazel', 'grey'], - '.bowerrc': ['bower', 'orange'], - '.codeclimate.yml': ['code-climate', 'green'], - '.eslintrc': ['eslint', 'purple'], - '.eslintrc.js': ['eslint', 'purple'], - '.eslintrc.cjs': ['eslint', 'purple'], - '.eslintrc.yaml': ['eslint', 'purple'], - '.eslintrc.yml': ['eslint', 'purple'], - '.eslintrc.json': ['eslint', 'purple'], - '.eslintignore': ['eslint', 'grey'], - '.firebaserc': ['firebase', 'orange'], - '.gitlab-ci.yml': ['gitlab', 'orange'], - '.jshintrc': ['javascript', 'blue'], - '.jscsrc': ['javascript', 'blue'], - '.stylelintrc': ['stylelint', 'white'], - '.stylelintrc.json': ['stylelint', 'white'], - '.stylelintrc.yaml': ['stylelint', 'white'], - '.stylelintrc.yml': ['stylelint', 'white'], - '.stylelintrc.js': ['stylelint', 'white'], - '.stylelintignore': ['stylelint', 'grey'], - '.direnv': ['config', 'grey-light'], - '.env': ['config', 'grey-light'], - '.static': ['config', 'grey-light'], - '.editorconfig': ['config', 'grey-light'], - '.slugignore': ['config', 'grey-light'], - '.tmp': ['clock', 'grey-light'], - '.htaccess': ['config', 'grey-light'], - '.key': ['lock', 'green'], - '.cert': ['lock', 'green'], - '.cer': ['lock', 'green'], - '.crt': ['lock', 'green'], - '.pem': ['lock', 'green'], - '.DS_Store': ['ignored', 'ignore'], - }, - partials: [ - ['TODO.md', ['todo', 'blue']], - ['TODO.txt', ['todo', 'blue']], - ['TODO', ['todo', 'blue']], - ['Procfile', ['heroku', 'purple']], - ['cmakelists.txt', ['makefile', 'blue']], - ['CMakeLists.txt', ['makefile', 'blue']], - ['CMAKELISTS.txt', ['makefile', 'blue']], - ['CMAKELISTS.TXT', ['makefile', 'blue']], - ['omakefile', ['makefile', 'grey-light']], - ['OMakefile', ['makefile', 'grey-light']], - ['OMAKEFILE', ['makefile', 'grey-light']], - ['qmakefile', ['makefile', 'purple']], - ['QMakefile', ['makefile', 'purple']], - ['QMAKEFILE', ['makefile', 'purple']], - ['makefile', ['makefile', 'orange']], - ['Makefile', ['makefile', 'orange']], - ['MAKEFILE', ['makefile', 'orange']], - ['CONTRIBUTING.md', ['license', 'red']], - ['CONTRIBUTING.txt', ['license', 'red']], - ['CONTRIBUTING', ['license', 'red']], - ['COMPILING.md', ['license', 'orange']], - ['COMPILING.txt', ['license', 'orange']], - ['COMPILING', ['license', 'orange']], - ['COPYING.md', ['license', 'yellow']], - ['COPYING.txt', ['license', 'yellow']], - ['COPYING', ['license', 'yellow']], - ['LICENCE.md', ['license', 'yellow']], - ['LICENSE.md', ['license', 'yellow']], - ['LICENCE.txt', ['license', 'yellow']], - ['LICENSE.txt', ['license', 'yellow']], - ['LICENCE', ['license', 'yellow']], - ['LICENSE', ['license', 'yellow']], - ['gulpfile.js', ['gulp', 'red']], - ['gulpfile', ['gulp', 'red']], - ['Gulpfile', ['gulp', 'red']], - ['GULPFILE', ['gulp', 'red']], - ['docker-compose.override.yaml', ['docker', 'pink']], - ['docker-compose.override.yml', ['docker', 'pink']], - ['docker-compose.yaml', ['docker', 'pink']], - ['docker-compose.yml', ['docker', 'pink']], - ['docker-healthcheck', ['docker', 'green']], - ['.dockerignore', ['docker', 'grey']], - ['DOCKERFILE', ['docker', 'blue']], - ['Dockerfile', ['docker', 'blue']], - ['dockerfile', ['docker', 'blue']], - ['gemfile', ['ruby', 'red']], - ['Gemfile', ['ruby', 'red']], - ['mix', ['hex', 'red']], - ], - default: ['default', 'white'], -}; - -const rawIcons = { - astro: - '<svg viewBox="-4 -4 40 40"><path fill-rule="evenodd" d="M5.9 18.847a7.507 7.507 0 0 0-.572 2.624a3.265 3.265 0 0 0 .551 1.553a7.427 7.427 0 0 0 2.093 1.681l5.128 3.414a7.332 7.332 0 0 0 2.1 1.168a3.239 3.239 0 0 0 1.5 0a7.381 7.381 0 0 0 2.117-1.16L24 24.711a7.512 7.512 0 0 0 2.117-1.688a3.241 3.241 0 0 0 .55-1.563a7.515 7.515 0 0 0-.587-2.643L21.547 4.551a3.973 3.973 0 0 0-.54-1.3a1.733 1.733 0 0 0-.7-.51a3.972 3.972 0 0 0-1.4-.122h-5.902a3.932 3.932 0 0 0-1.4.125a1.713 1.713 0 0 0-.7.512a3.94 3.94 0 0 0-.535 1.3L5.9 18.848Zm13.24-13.2a3.329 3.329 0 0 1 .441 1.093l3.892 12.784a16.168 16.168 0 0 0-4.653-1.573l-2.529-8.56a.331.331 0 0 0-.513-.169a.323.323 0 0 0-.119.169l-2.5 8.557a16.14 16.14 0 0 0-4.674 1.579l3.908-12.784a3.281 3.281 0 0 1 .442-1.094a1.458 1.458 0 0 1 .582-.43a3.31 3.31 0 0 1 1.175-.1h2.793a3.314 3.314 0 0 1 1.176.1a1.454 1.454 0 0 1 .583.432ZM16.127 21.06a5.551 5.551 0 0 0 3.4-.923a2.8 2.8 0 0 1-.207 2.182a3.938 3.938 0 0 1-1.547 1.481c-.674.428-1.254.8-1.254 1.787a2.079 2.079 0 0 0 .209.914a2.49 2.49 0 0 1-1.535-2.3v-.061c0-.683 0-1.524-.962-1.524a1.028 1.028 0 0 0-.391.077a1.021 1.021 0 0 0-.552.551a1.03 1.03 0 0 0-.079.391a3.769 3.769 0 0 1-.988-2.644a4.206 4.206 0 0 1 .175-1.248c.4.757 1.92 1.32 3.731 1.32Z"/></svg>', - bsl: '<svg viewBox="0 0 32 32"><path d="M16.8 19v3H27v-3H16.8zM7 10h3v12H7V10zm-2 1h2v3H5v-3z"/><path d="M14 16c0-1.7 1.3-3 3-3 1.3 0 2.4.8 2.8 2h3.1c-.5-2.8-2.9-5-5.9-5-3.3 0-6 2.7-6 6s2.7 6 6 6c2.2 0 4.2-1.2 5.2-3H17c-1.7 0-3-1.3-3-3z"/></svg>', - mdo: '<svg viewBox="0 0 32 32"><path d="M18 17.7c-1 0-1.8-.8-1.8-1.8s.8-1.8 1.8-1.8c.7 0 1.4.4 1.7 1.1h1.5c-.4-1.5-1.7-2.5-3.2-2.5-1.8 0-3.3 1.5-3.3 3.3s1.5 3.3 3.3 3.3h4.7v-1.5H18zm-5.5-5H14v6.5h-1.5v-6.5zm-1.4 1.1h1.5v1.5h-1.5v-1.5z"/><path d="M22.9 9.1H9.4L6 16s3.4 6.8 3.4 6.9h13.5c1.7 0 3.1-1.4 3.1-3.1v-7.7c0-1.6-1.3-3-3.1-3zm1.6 10.8c0 .9-.7 1.5-1.5 1.5H10.6s-3.1-4.9-3.1-5.2l3.1-5.5H23c.9 0 1.5.7 1.5 1.5v7.7z"/></svg>', - salesforce: - '<svg viewBox="0 0 32 32"><path d="M12.4 10.4c.6.1 1.2.3 1.7.7.2.2.4.3.5.5h.1c.2-.2.4-.3.6-.5.2-.1.5-.2.7-.3.1 0 .2 0 .4-.1h.6c.4 0 .7.1 1 .3.5.3.8.6 1.1 1.1 0 .1.1.1.1 0 .3-.1.5-.2.8-.2h.8c.4 0 .9.2 1.3.4.3.2.6.3.8.6.3.3.5.6.7 1 .2.3.3.7.3 1.1v.8c0 .5-.2.9-.4 1.3s-.5.8-.8 1.1c-.2.2-.5.4-.8.5l-.9.3h-1.3c-.2.4-.5.6-.8.9-.3.2-.6.3-1 .4h-.6c-.3 0-.5-.1-.8-.2h-.1c-.1.3-.3.5-.5.8-.2.3-.5.5-.8.6-1.2.6-2.7.3-3.6-.9-.2-.2-.3-.4-.4-.7 0-.1-.1 0-.1 0h-.7c-.3 0-.5-.1-.7-.1-.3-.1-.5-.2-.8-.4-.3-.3-.6-.6-.8-1 .1-.4.1-.7 0-.9v-.6c0-.3.1-.6.2-.8.1-.2.2-.4.4-.6.1-.1.2-.2.2-.3.2-.2.3-.3.5-.4 0 0 .1 0 0-.1-.1-.2-.2-.4-.2-.7v-.9c.2-1.5 1.4-2.7 2.9-2.8h.2c.1.1.2.1.2.1z"/></svg>', - asm: '<svg viewBox="0 0 32 32"><path d="M5.998 19.625l2.623-7.28h1.37l2.623 7.28h-1.43l-.716-1.95H7.727l-.715 1.95H5.998zm2.027-2.86h2.086L9.098 13.84l-1.073 2.925zm4.947 2.795v-1.235c.953.325 1.728.52 2.384.52.536 0 .894-.13 1.132-.26.298-.195.417-.39.417-.715 0-.26-.06-.455-.238-.585-.179-.195-.477-.39-.954-.585l-.596-.26c-.775-.39-1.311-.78-1.669-1.105-.298-.325-.476-.715-.476-1.17 0-.585.238-1.105.774-1.43.537-.39 1.252-.585 2.146-.585.715 0 1.49.065 2.324.26v1.17c-.894-.26-1.609-.39-2.145-.39-.417 0-.715.065-.954.195-.238.195-.357.39-.357.585 0 .195.06.39.238.52.179.13.477.325.954.585l.596.26c.834.39 1.43.78 1.728 1.105.298.325.477.715.477 1.235 0 .65-.298 1.235-.894 1.56-.537.39-1.371.585-2.444.585-.655 0-1.49-.065-2.443-.26zm6.318.065V12.41h1.847l1.609 5.135 1.669-5.135h1.609v7.215h-1.311V14.1l-1.61 5.005h-1.132l-1.609-5.07v5.59h-1.073z"/></svg>', - bicep: - '<svg viewBox="0 0 32 32"><path d="M21.5 18H13l2-5h3.3l.7-1.5h-3L15 10l1-1.5h3L18.3 7H15l-2.2 3 .9 1.5-6 7.5c-.4.5-.7 1.3-.7 2 0 1.5 1.1 2.8 2.5 3 0 0 10.5 1 12 1 1.9 0 3.5-1.6 3.5-3.5S23.4 18 21.5 18zM10 22.5c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5zm11.5 1c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></svg>', - bazel: - '<svg viewBox="0 0 512 512"><path d="M184 112l72 72 72-72 72 72v72L256 400 112 256v-72z"/></svg>', - c: '<svg viewBox="0 0 32 32"><path d="M22.3 22.9q-1.07.572-2.22.863-1.14.292-2.39.292-3.73 0-5.91-2.16-2.18-2.17-2.18-5.89 0-3.72 2.18-5.89 2.18-2.18 5.91-2.18 1.24 0 2.39.292 1.16.291 2.22.863v3.22q-1.08-.76-2.12-1.11-1.03-.353-2.18-.353-2.07 0-3.24 1.37-1.18 1.37-1.18 3.79 0 2.4 1.18 3.78 1.18 1.37 3.24 1.37 1.14 0 2.18-.354 1.04-.354 2.12-1.11z" font-size="22" font-stretch="semi-condensed" font-weight="700" letter-spacing="0" word-spacing="0"/></svg>', - 'c-sharp': - '<svg viewBox="0 0 32 32"><g><path d="M7.1 15.9c0-1.3.2-2.4.6-3.4.4-1 .9-1.8 1.6-2.5.7-.7 1.5-1.2 2.4-1.6s1.9-.5 2.9-.5 1.9.2 2.7.6c.8.4 1.5.9 2 1.4l-2.2 2.5c-.4-.3-.7-.6-1.1-.7-.4-.1-.8-.3-1.4-.3-.5 0-.9.1-1.3.3-.4.2-.8.5-1.1.9s-.5.8-.7 1.4c-.2.6-.3 1.2-.3 1.9 0 1.5.3 2.6 1 3.3.7.8 1.5 1.2 2.6 1.2.5 0 1-.1 1.4-.3.4-.2.8-.5 1.1-.9l2.2 2.5c-.7.8-1.4 1.3-2.2 1.7-.8.4-1.7.6-2.7.6s-2-.2-2.9-.5-1.7-.8-2.4-1.5-1.1-1.7-1.5-2.7c-.5-.9-.7-2.1-.7-3.4z"/><path d="M21.8 17.1h-1l-.4 2.4h-1.2l.4-2.4h-1.2V16h1.5l.2-1.6h-1.3v-1.1h1.5l.4-2.4h1.2l-.4 2.4h1l.4-2.4h1.2l-.4 2.4H25v1.1h-1.6l-.2 1.6h1.3v1.1h-1.6l-.4 2.4h-1.2c0 .1.5-2.4.5-2.4zm-.8-1h1l.2-1.6h-1l-.2 1.6z"/></g></svg>', - html: '<svg viewBox="0 0 32 32"><path d="M8 15l6-5.6V12l-4.5 4 4.5 4v2.6L8 17v-2zm16 2.1l-6 5.6V20l4.6-4-4.6-4V9.3l6 5.6v2.2z"/></svg>', - cpp: '<svg viewBox="0 0 32 32"><path d="M8.3 15.5c0-1.3.2-2.4.6-3.4.4-1 .9-1.8 1.6-2.5.7-.7 1.5-1.2 2.4-1.6s1.9-.5 2.9-.5 1.9.2 2.7.6c.8.4 1.5.9 2 1.4L18.3 12c-.4-.3-.7-.6-1.1-.7s-.8-.3-1.4-.3c-.5 0-.9.1-1.3.3-.4.2-.8.5-1.1.9s-.5.8-.7 1.4c-.2.6-.3 1.2-.3 1.9 0 1.5.3 2.6 1 3.3.7.8 1.5 1.2 2.6 1.2.5 0 1-.1 1.4-.3.4-.2.8-.5 1.1-.9l2.2 2.5c-.7.8-1.4 1.3-2.2 1.7-.8.4-1.7.6-2.7.6s-2-.2-2.9-.5-1.7-.8-2.4-1.5-1.1-1.7-1.5-2.7c-.5-1-.7-2.1-.7-3.4z"/><path d="M18.2 12.9h-1.4v1.7h-1.6V16h1.6v1.8h1.4V16h1.6v-1.4h-1.6v-1.7zm6 1.6v-2h-1.7v2h-1.9v1.7h1.9v2.1h1.7v-2.1h1.9v-1.7h-1.9z"/></svg>', - clojure: - '<svg id="svg2" viewBox="0 0 32 32"><style>.st0{fill:#231f20}</style><path id="path10" d="M15.7 16.4l-.3.6c-.4.8-.8 1.8-.9 2.5-.1.2-.1.5-.1.8v.4c.5.2 1.1.3 1.6.3s1-.1 1.5-.2l-.3-.3c-.5-.9-.9-2.1-1.5-4.1" class="st0"/><path id="path12" d="M13.4 12.3c-1.2.9-2 2.3-2 3.9s.8 3 2 3.9c.3-1.2 1-2.3 2.1-4.6-.1-.2-.1-.4-.2-.6-.3-.8-.7-1.6-1.1-2.1-.3-.1-.6-.3-.8-.5" class="st0"/><path id="path14" d="M20.3 21.7c-.6-.1-1.2-.2-1.6-.3-.8.4-1.6.6-2.5.6-3.2 0-5.7-2.6-5.7-5.7 0-1.7.8-3.2 1.9-4.3-.3-.1-.7-.1-1-.1-1.7 0-3.4.9-4.2 3.5-.1.4-.1.6-.1 1 0 5 4 9 9 9 3 0 5.7-1.5 7.4-3.8-.9.2-1.7.3-2.5.3-.3-.2-.5-.2-.7-.2" class="st0"/><path id="path18" d="M16.1 7.2c-3 0-5.7 1.5-7.3 3.8.8-.5 1.7-.7 2.5-.7 1 0 1.9.3 2.3.5.1.1.2.1.3.2.7-.3 1.5-.5 2.3-.5 3.2 0 5.7 2.6 5.7 5.7 0 1.6-.7 3-1.7 4.1h.8c1 0 2.1-.2 2.9-.9.5-.4 1-1.1 1.2-2.1 0-.4.1-.8.1-1.1-.1-5-4.1-9-9.1-9" class="st0"/></svg>', - coldfusion: - '<svg viewBox="0 0 32 32"><path d="M10.8 14.5c-.4 0-.9-.1-1.3 0-1.6.2-3.2.3-4.2 1.7C3.9 18 3.6 20 4.6 22s2.7 2.9 4.9 3h4c2.5-.1 4.5-1.2 6-3.2.8-1 1.4-2.1 1.8-3.3.3-.8.7-1.1 1.5-1.1.8.1 1.5 0 2.3 0 .3 0 .7 0 .7-.4.1-.8.3-1.6-.1-2.3-.3-.6-1-.2-1.5-.3h-.5c-.5 0-.7-.1-.5-.7.6-1.4 1.6-2.5 3.1-3 .5-.2 1.3 0 1.5-.6.3-.4.2-1.1.2-1.7v-.9c0-.3-.2-.5-.6-.5-1.9.2-3.7.7-4.9 2.2-1.3 1.7-2.2 3.6-3 5.6-.7 1.9-1.3 3.8-2.6 5.3-.6.7-1.4 1.2-2.3 1.4-1.9.3-3.8.2-5.7-.2-1-.2-1.5-.9-1.5-1.8 0-1 .6-1.7 1.7-2 1-.2 2-.1 3-.2.6 0 .8-.2.8-.8 0-2.5.2-2.1-2-2.1.1.1 0 .1-.1.1z"/></svg>', - coffee: - '<svg viewBox="0 0 32 32"><path d="M16.8 9.1c-.5.1-.8.3-2.3 1-.8.4-1.9.5-2.2.2-.3-.4.1-.6 1-.6.8 0 1-.1.7-.3-.6-.4-2-.1-2.3.4-.1.3-.1.4.1.7.5.5.9.7 2 .6.8 0 1.2-.1 2-.6 1.2-.6 2.5-.9 3.3-.8.8.1 1 .4.5.7-.4.3-1.4.4-1.8 0-.4-.2-.9-.2-.9.2 0 .5 1.5.9 2.8.6 1.5-.3 1.5-1.6 0-2.1-.6-.1-2.1-.2-2.9 0zm-8.5 1.3c-.3.2-.5.5-.5.6-.1.4.7 1 1.9 1.4 1.1.3 1.5.4 3.2.6 1.1.1 6.1.1 7.1 0 .4-.1 1-.1 1.2-.2.7-.1 2.6-.6 3-.9.6-.3.9-.8.7-1.1-.3-.6-1-1-.8-.4.2.8-2.1 1.6-5.1 1.8-1.1.1-4.4.1-5 0-.2 0-.9-.1-1.4-.1-1.7-.1-3.6-.8-3.7-1.3 0-.1 0-.4.1-.5.1-.3-.1-.3-.7.1zM8 13.1c0 .4.2 1 .3 1.5l.3.8-.4.3c-.2.2-.6.6-.8.9-.3.6-.4.8-.4 1.7 0 1.2.2 1.7 1.2 2.4.5.4.7.4 1.5.4 1.2 0 1.6-.3.7-.4-.7-.1-1.7-1-2-1.8-.3-.7-.2-1.8.1-2.3.1-.2.3-.4.3-.4l.4.6c.2.3.8 1.2 1.3 2 .6.8 1.1 1.7 1.2 2.1.6 1.6 1.7 2.1 4.7 2.1s4.2-.6 4.8-2.2c.1-.4.7-1.3 1.2-2s1.2-1.7 1.4-2.3c.5-1.1 1.2-3.3 1.2-3.8 0-.3 0-.3-.3 0-.5.5-2.2 1-4.4 1.2-1.8.2-7.5.1-8.9-.2-.2 0-.5-.1-.8-.1-.7-.1-2.2-.8-2.5-1-.1-.1-.2-.1-.1.5z"/></svg>', - config: - '<svg viewBox="0 0 32 32"><path d="M24.5 17.3c-.4-.1-.8-.3-1.1-.4 0-.7-.1-1.3-.1-2 0-.1.1-.1.1-.2.4-.2.7-.3 1.1-.5.4-.2.5-.6.4-1-.3-.7-.6-1.3-.9-2-.2-.4-.6-.6-1-.4-.4.2-.7.3-1.1.5-.1 0-.2 0-.2-.1-.2-.3-.5-.5-.7-.7-.2-.2-.5-.4-.7-.6.2-.4.3-.8.5-1.2.2-.5 0-.9-.5-1.1-.6-.1-1.3-.4-1.9-.6-.5-.2-.9 0-1.1.5-.1.4-.3.8-.4 1.1-.7 0-1.3.1-2 .1-.1 0-.1-.1-.2-.1-.2-.4-.3-.7-.5-1.1-.2-.4-.6-.5-1-.4-.7.3-1.3.6-2 .9-.4.2-.6.6-.4 1 .2.4.3.7.5 1.1 0 .1 0 .2-.1.2-.2.2-.4.3-.5.5-.3.3-.5.6-.8.9-.4-.1-.8-.3-1.1-.4-.5-.2-.9 0-1.1.5-.2.5-.5 1.2-.7 1.8-.2.6-.1.9.5 1.1.4.1.8.3 1.1.4 0 .7.1 1.3.1 2 0 .1-.1.1-.1.2-.4.2-.7.3-1.1.5-.4.2-.5.6-.4 1 .3.7.6 1.3.9 2 .2.4.6.6 1 .4.4-.2.7-.3 1.1-.5.1 0 .2 0 .2.1.2.3.5.5.7.7.2.2.5.4.7.6-.2.4-.3.8-.5 1.2-.2.5 0 .9.5 1.1.6.2 1.2.5 1.9.7.6.2.9.1 1.1-.5.1-.4.3-.8.4-1.1.7 0 1.3-.1 2-.1.1 0 .1.1.2.1.2.4.3.7.5 1.1.2.4.6.5 1 .4.7-.3 1.3-.6 2-.9.4-.2.6-.6.4-1-.2-.4-.3-.7-.5-1.1 0-.1 0-.2.1-.2.3-.2.5-.5.7-.7.2-.2.4-.5.6-.7.4.1.8.3 1.1.4.5.2.9 0 1.1-.5.2-.6.5-1.2.7-1.9.2-.5.1-.9-.5-1.1zm-7 2.1c-1.9.8-4 0-4.9-1.9-.8-1.9 0-4 1.9-4.9 1.9-.8 4 0 4.9 1.9.8 1.9 0 4-1.9 4.9z"/></svg>', - crystal: - '<svg viewBox="0 0 32 32"><path d="M16 3.851l-5.26 3.037-5.261 3.038v12.148l5.26 3.037L16 28.15l5.26-3.038 5.261-3.037V9.926l-5.26-3.038z"/><path d="M13.244 20.697l-2.748-4.76-2.749-4.76h10.994l-2.749 4.76z"/></svg>', - crystal_embedded: - '<svg viewBox="0 0 32 32"><path d="M16 3.851l-5.26 3.037-5.261 3.038v12.148l5.26 3.037L16 28.15l5.26-3.038 5.261-3.037V9.926l-5.26-3.038z"/><path d="M14.077 21.025l-5.646-4.758 5.646-4.75 1.307 1.324-4.155 3.41 4.155 3.45zm3.846-9.508l5.646 4.75-5.646 4.757-1.298-1.323 4.146-3.418-4.146-3.443z"/></svg>', - json: '<svg viewBox="0 0 32 32"><path d="M7.5 15.1c1.5 0 1.7-.8 1.7-1.5 0-.6-.1-1.1-.1-1.7S9 10.7 9 10.2c0-2.1 1.3-3 3.4-3h.8v1.9h-.4c-1 0-1.3.6-1.3 1.6 0 .4.1.8.1 1.3 0 .4.1.9.1 1.5 0 1.7-.7 2.3-1.9 2.6 1.2.3 1.9.9 1.9 2.6 0 .6-.1 1.1-.1 1.5 0 .4-.1.9-.1 1.2 0 1 .3 1.6 1.3 1.6h.4v1.9h-.8c-2 0-3.3-.8-3.3-3 0-.6 0-1.1.1-1.7.1-.6.1-1.2.1-1.7 0-.6-.2-1.5-1.7-1.5l-.1-1.9zm17 1.7c-1.5 0-1.7.9-1.7 1.5s.1 1.1.1 1.7c.1.6.1 1.2.1 1.7 0 2.2-1.4 3-3.4 3h-.8V23h.4c1 0 1.3-.6 1.3-1.6 0-.4 0-.8-.1-1.2 0-.5-.1-1-.1-1.5 0-1.7.7-2.3 1.9-2.6-1.2-.3-1.9-.9-1.9-2.6 0-.6.1-1.1.1-1.5.1-.5.1-.9.1-1.3 0-1-.4-1.5-1.3-1.6h-.4V7.2h.8c2.1 0 3.4.9 3.4 3 0 .6-.1 1.1-.1 1.7-.1.6-.1 1.2-.1 1.7 0 .7.2 1.5 1.7 1.5v1.7z"/></svg>', - css: '<svg viewBox="0 0 32 32"><path d="M10.3 23.3l.8-4H8.6v-2.1h3l.5-2.5H9.5v-2.1h3.1l.8-3.9h2.8l-.8 3.9h2.8l.8-3.9h2.8l-.8 3.9h2.5v2.1h-2.9l-.6 2.5h2.6v2.1h-3l-.8 4H16l.8-4H14l-.8 4h-2.9zm6.9-6.1l.5-2.5h-2.8l-.5 2.5h2.8z"/></svg>', - csv: '<svg viewBox="0 0 32 32"><path d="M7 7.1v17.8h18V7.1H7zm2.9 3.7H15v1.3H9.9v-1.3zm7 0H22v1.3h-5.1v-1.3zm-7 3H15v1.3H9.9v-1.3zm7 0H22v1.3h-5.1v-1.3zm-7 3H15v1.3H9.9v-1.3zm7 0H22v1.3h-5.1v-1.3zm-7 3H15v1.3H9.9v-1.3zm7 0H22v1.3h-5.1v-1.3z"/></svg>', - xls: '<svg viewBox="0 0 32 32"><path d="M26 9.3v13.6c0 .1-.1.2-.1.3-.2.3-.5.5-.8.5h-7.7v2c-.3-.1-.7-.1-1-.2-.7-.1-1.5-.3-2.2-.4-.8-.1-1.6-.3-2.4-.4-.8-.1-1.6-.3-2.4-.4-.7-.1-1.5-.3-2.2-.4-.4-.1-.7-.1-1.1-.2V9c.1 0 .3-.1.4-.1.7-.5 1.5-.7 2.3-.8.7-.1 1.4-.3 2-.4.6-.1 1.3-.2 1.9-.4.7-.1 1.5-.3 2.2-.4.8-.1 1.5-.3 2.3-.4h.1v1.9h7.8c.4 0 .8.3.9.7v.2zm-.8-.1h-7.9v1.2H20v1.7h-2.7v.6H20v1.7h-2.7v.6H20v1.7h-2.7v.7h2.8v1.7h-2.8v.6H20v1.7h-2.7v1.2h7.9V9.2zM14.7 20.7s0-.1-.1-.1c-.7-1.4-1.5-2.8-2.2-4.2v-.2c.7-1.4 1.4-2.7 2.2-4.1V12h-.1c-.2 0-.5 0-.7.1-.3 0-.6 0-1 .1-.1 0-.1 0-.1.1-.3.6-.5 1.1-.8 1.7-.2.5-.4.9-.6 1.4-.1-.2-.1-.5-.2-.7-.3-.7-.6-1.5-.9-2.2-.1-.2-.1-.2-.3-.2-.4 0-.8.1-1.2.1h-.4v.1c.1.2.2.5.3.7l1.5 3v.1c-.6 1.2-1.3 2.4-1.9 3.6 0 .1-.1.1-.1.2h.6c.4 0 .7.1 1.1.1.1 0 .1 0 .1-.1.3-.6.6-1.2.9-1.9.1-.3.3-.6.4-.9 0-.1 0-.2.1-.3v.1c.1.2.1.4.2.5.4.8.7 1.6 1.1 2.5.1.1.1.2.3.2.5 0 1 .1 1.5.1.1.3.2.3.3.3z"/><path d="M23.9 10.4v1.7h-3.1v-1.7h3.1zm-3.1 11.2v-1.7h3.1v1.7h-3.1zm0-4.7v-1.7h3.1v1.7h-3.1zm3.1-4.1v1.7h-3.1v-1.7h3.1zm0 4.8v1.7h-3.1v-1.7h3.1z"/></svg>', - cu: '<svg viewBox="0 0 32 32"><path d="M8.3 15.5c0-6.5 7.6-10.7 12.2-6L18.3 12c-8.1-5.4-7.4 13 .2 6.8l2.2 2.5c-4.6 5.3-12.4.9-12.4-5.8zm17.8 2.3h-.8l-.3-1h-1.4l-.3 1h-.8l1.4-4.3h.8l1.4 4.3zm-1.3-1.7l-.5-1.6-.5 1.6h1z"/><path d="M15.76 13.51h.71v2.33c0 .36.01.6.03.71.03.19.11.34.22.44.12.1.27.15.47.15a.7.7 0 00.4-.11c.1-.07.17-.17.21-.3s.06-.41.06-.84v-2.38h.71v2.26c0 .58-.03.99-.09 1.25s-.2.46-.42.62-.5.24-.85.24c-.37 0-.65-.07-.86-.2s-.36-.32-.45-.56-.14-.68-.14-1.32v-2.29zm3.55 0h1.3c.33 0 .58.04.74.11.17.07.32.2.46.37s.25.4.33.68.12.62.12 1.03c0 .37-.04.69-.13.97s-.19.49-.32.65-.29.28-.47.36c-.18.08-.42.12-.7.12h-1.33v-4.29zm.71.72v2.84h.53c.23 0 .39-.02.5-.06.1-.04.19-.11.25-.19.07-.09.12-.22.16-.41.04-.19.06-.43.06-.74 0-.32-.02-.57-.07-.75a.87.87 0 00-.21-.43.676.676 0 00-.34-.21c-.1-.03-.29-.04-.58-.04h-.3z"/></svg>', - cake: '<svg id="Layer_1" viewBox="0 0 32 32"><style/><path d="M21.1 17c.5 1.7 1.7 6.3 1.7 6.3l4.1-.5v-6.5l-5.8.7zm-7 .7l-7.4.8v6.8l8.7-1.1zm6.2-6.6c-.2.4-.4.8-.7 1.1.2.7.4 1.3.6 2l6.6-.8s-1.6-2.7-3.8-4.1c-.8-.5-1.7-.9-2.4-1.1.2.7.2 1.7-.3 2.9zm-7.2 3.2c-1.2-.1-2.1-.6-2.8-1.4l-3.6 2.8 6.6-.8c-.1-.2-.1-.4-.2-.6zm4.7-2c-.1-.3-.1-.5.1-.7.2-.3.4-.6.6-1 .4-.9.5-1.9-.1-2.8-.6-1-1.5-1.3-2.6-1.1-.3 0-.4.3-.2.6l.9 1.8c0 .1.1.2-.1.2-.6.4-1.2.8-1.7 1.1-.1.1-.2.1-.3 0-.4-.4-.7-.8-1-1.2-.2-.2-.5-.4-.5-.4s-.3-.1-.4.1c-.5.8-.8 2.2-.2 3.1.5.8 1.2 1.2 2.1 1.2.2 0 .4 0 .5.3.2.9 2.3 9.6 2.5 10.9.1.6.5 1.1 1 1 .7-.1 1.5-.1 2.1-.7.4-.4.5-.8.4-1.3-.3-.6-2.7-9.7-3.1-11.1z"/></svg>', - cake_php: - '<svg viewBox="0 0 32 32"><path d="M16 14.5v3.1h-1.2c-1.7-.1-3.3-.2-4.9-.7-.8-.2-1.5-.5-2.2-.8-.4-.1-.7-.3-1-.5-.5-.4-.7-.8-.7-1.4v-2.6c0-.4.2-.8.5-1.1.5-.5 1.2-.8 1.9-1 1.4-.5 2.9-.8 4.3-.9 1.4-.1 2.7-.2 4.1-.2 2.3 0 4.5.3 6.7 1 .6.2 1.2.6 1.8.9.5.3.8.8.8 1.5v2.5c0 .6-.2 1.1-.7 1.4-.4.3-.9.5-1.3.7-.1.1-.3 0-.4 0-2.4-.6-4.8-1.2-7.3-1.8-.2-.1-.3-.1-.4-.1zm0 9.2h-2c-1.7-.1-3.4-.3-5-.8-.7-.2-1.4-.6-2.1-.9-.6-.4-.9-1-.9-1.7V18c.9 1.2 2.2 1.6 3.5 2 2 .5 4 .7 6.1.7.3 0 .4.1.4.4v2.6zm10-5.8v2.8c0 .4-.2.7-.6 1-.5.3-1 .6-1.5.8-.1.1-.3 0-.5 0l-6-1.5-1.2-.3c-.1 0-.2-.2-.2-.2v-2.8c.7.2 1.3.3 2 .5 1.9.5 3.7.9 5.6 1.4h.4c.8-.5 1.5-.8 2-1.7z"/></svg>', - d: '<svg viewBox="0 0 32 32"><path d="M23.5 15.8c0 2.6-.8 4.7-2.5 6.1-1.7 1.4-4.1 2.1-7.4 2.1H8.5V8h5.7c3 0 5.3.7 6.9 2.1 1.6 1.3 2.4 3.3 2.4 5.7zm-4 .1c0-3.4-1.7-5.2-5.2-5.2h-2v10.5H14c3.7 0 5.5-1.7 5.5-5.3z"/></svg>', - word: '<svg viewBox="0 0 32 32"><path d="M26 11.4V8.8c0-.4-.3-.8-.8-.8h-7.3V6.2h-1.4c-.2 0-.3.1-.5.1-.7.1-1.4.3-2.1.4-.7.1-1.4.2-2 .4-.7.1-1.4.2-2.2.4-.8.1-1.5.2-2.2.3-.5.1-1 .2-1.4.2H6v15.9c.8.1 1.6.3 2.4.4.8.1 1.7.3 2.5.4.8.1 1.6.3 2.4.4.8.1 1.7.3 2.5.5.3.1.7.1 1 .1h.9V24c0-.1 0-.1.1-.1h7.3c.1 0 .3 0 .4-.1.2 0 .3-.1.3-.3 0-.2.1-.3.1-.5V11.4c.1.1.1.1.1 0zm-11 1.5l-.9 3.9c-.2.7-.3 1.4-.5 2.2 0 .1-.1.1-.1.1-.2.1-.4 0-.6 0h-.6c-.1 0-.1 0-.1-.1-.1-.6-.3-1.3-.4-1.9-.2-.8-.3-1.6-.5-2.4 0 .2-.1.4-.1.6l-.6 3c0 .2-.1.5-.1.7 0 .1 0 .1-.1.1-.4 0-.8-.1-1.2-.1-.1 0-.1 0-.1-.1-.3-1.6-.6-3.2-1-4.9-.1-.3-.1-.7-.2-1v-.1h1.2c.2 1.4.5 2.8.7 4.3 0-.2.1-.4.1-.6.3-1.2.5-2.5.8-3.7 0-.1 0-.1.1-.1h1c.2 0 .2 0 .3.2.3 1.4.6 2.8.9 4.3v.1c.1-.8.3-1.6.4-2.4.1-.7.3-1.5.4-2.2 0 0 0-.1.1-.1.4 0 .8 0 1.3-.1h.1c-.2 0-.3.2-.3.3zm10.3-4.1s0 .1 0 0v14.5h-7.5v-1.8h5.9v-.9H18c-.1 0-.1 0-.1-.1v-.9c0-.1 0-.1.1-.1h5.8v-.9h-5.9v-1.1h5.8c.1 0 .1 0 .1-.1v-.7c0-.1 0-.1-.1-.1H18c-.1 0-.1 0-.1-.1v-1h5.9v-.9h-5.7c-.1 0-.1 0-.1-.1v-.9c0-.1 0-.1.1-.1h5.7v-.9h-5.9v-1.2h5.8c.1 0 .1 0 .1-.1v-.7c0-.1 0-.1-.1-.1h-5.9V9c0-.1 0-.1.1-.1h7.3c.1-.2.1-.2.1-.1z"/></svg>', - ejs: '<svg viewBox="0 0 32 32"><path d="M7.5 14.9L13.9 9v2.8L9.1 16l4.8 4.2V23l-6.4-5.9v-2.2zm17 2.3l-6.4 5.9v-2.8l4.9-4.2V16l-4.9-4.2V8.9l6.4 5.9v2.4z"/></svg>', - elixir: - '<svg viewBox="0 0 32 32"><path d="M17.314 10.006c1.644 3.531 5.925 5.006 5.538 9.601-.456 5.412-4.305 6.772-6.433 6.868-2.128.097-6.191-.653-7.304-5.755-1.249-5.731 4.208-14.534 7.352-15.792-.121 1.427.184 3.656.847 5.078zm-2.799 14.61c1.439.299 2.542.507 2.673-.072.197-.873-3.159-1.365-5.402-1.608.673.71 2.032 1.535 2.729 1.68z"/></svg>', - elixir_script: - '<svg viewBox="0 0 32 32"><path d="M19.182 12.632c1.828 1.993 3.947 3.683 3.67 6.975-.456 5.412-4.305 6.772-6.433 6.868-2.128.097-6.191-.653-7.304-5.755-1.249-5.731 4.208-14.534 7.352-15.792-.116 1.373.162 3.491.774 4.916a7.65 7.65 0 00-.663-.028c-1.339 0-2.428.364-3.27 1.094-.841.729-1.261 1.666-1.261 2.812 0 .656.161 1.18.484 1.57.323.391.984.795 1.984 1.211l.93.391c.359.151.63.345.813.582.182.237.273.517.273.84 0 .521-.198.934-.594 1.238-.396.305-.94.457-1.633.457-.557 0-1.112-.11-1.664-.332a5.906 5.906 0 01-1.586-.965l-.46 2.383a10.82 10.82 0 001.863.617 7.869 7.869 0 001.754.203c1.427 0 2.56-.356 3.398-1.07.839-.713 1.258-1.669 1.258-2.867 0-.693-.176-1.277-.527-1.754-.352-.476-.908-.884-1.668-1.223l-.907-.398-.054-.023c-.959-.433-1.438-.868-1.438-1.305 0-.458.193-.835.578-1.129.386-.294.886-.441 1.5-.441.578 0 1.105.082 1.578.246.474.164.888.407 1.243.73l.01-.051zm-4.667 11.984c1.439.299 2.542.507 2.673-.072.197-.873-3.159-1.365-5.402-1.608.673.71 2.032 1.535 2.729 1.68z"/></svg>', - hex: '<svg viewBox="0 0 32 32"><path d="M20.994 24.65h-9.988L6.012 16l4.994-8.65h9.988L25.988 16l-4.994 8.65zm-2.467-4.272L21.055 16l-2.528-4.378h-5.054L10.945 16l2.528 4.378h5.054z"/></svg>', - elm: '<svg preserveAspectRatio="xMidYMid" viewBox="0 0 32 32"><rect width="100%" height="100%"/><g class="currentLayer"><path d="M16 16.533l-9.181 9.181H25.18z"/><path d="M21.641 21.108l4.073 4.073v-8.146z"/><path d="M15.467 16L6.286 6.819V25.18z"/><path d="M25.714 14.923V6.286h-8.637z"/><path d="M21.13 11.403l4.575 4.576-4.597 4.596L16.533 16zM6.819 6.286l4.229 4.229h9.193l-4.23-4.23z"/><path d="M16 15.467l4.199-4.198H11.8z"/></g></svg>', - favicon: - '<svg viewBox="0 0 32 32"><path d="M16 5.5l3.1 6.3 6.9 1-5 4.8 1.2 6.9-6.2-3.2-6.2 3.2 1.2-6.9-5-4.8 6.9-1z"/></svg>', - 'f-sharp': - '<svg id="Layer_1" viewBox="0 0 32 32"><style>.st0{fill:#231f20}</style><path d="M7 15l8.5-8.5v4.3L11.3 15l4.3 4.3v4.3L7 15z" class="st0"/><path d="M12.5 15l3.1-3.1V18l-3.1-3zM25 15l-8.8-8.5v4.3l4.3 4.3-4.3 4.3v4.3L25 15z" class="st0"/></svg>', - git: '<svg viewBox="0 0 32 32"><path d="M7 16.2v-.3c.1-.5.4-.7.7-1.1l4.8-4.8.2-.2s.1 0 .1.1l1.8 1.8c.1.1.1.2 0 .3-.1.6.1 1.2.6 1.5.2.1.2.2.2.4v4.4c0 .2-.1.3-.2.4-.5.3-.8.9-.6 1.5.2.6.7 1 1.3 1 .6 0 1.1-.4 1.3-.9.2-.6 0-1.2-.5-1.6-.2-.1-.2-.2-.2-.4v-4.5h.1l1.6 1.6c.1.1.1.2.1.2v.6c.1.8.8 1.3 1.6 1.2.8-.1 1.4-.9 1.2-1.7-.1-.7-.9-1.2-1.6-1.1-.1 0-.2 0-.4-.1l-1.7-1.7c-.1-.1-.1-.2-.1-.3.2-.9-.7-1.8-1.6-1.6-.1 0-.3 0-.3-.1-.6-.6-1.2-1.2-1.8-1.7-.1-.1-.1-.2 0-.3.5-.4.9-.9 1.3-1.3.6-.6 1.2-.6 1.8 0l7.6 7.6c.6.6.6 1.2 0 1.8L17 24.2c-.3.3-.6.7-1.1.8h-.2c-.2-.1-.5-.2-.7-.4-.6-.6-1.3-1.2-1.9-1.9l-5.5-5.5c-.1-.3-.5-.6-.6-1z"/></svg>', - go2: '<svg id="Layer_1" viewBox="0 0 254.5 225"><style id="style74">.st4{fill:#00acd7}</style><path id="path76" d="M20.2 103.1c-.4 0-.5-.2-.3-.5l2.1-2.7c.2-.3.7-.5 1.1-.5h35.7c.4 0 .5.3.3.6l-1.7 2.6c-.2.3-.7.6-1 .6zm-15.1 9.2c-.4 0-.5-.2-.3-.5l2.1-2.7c.2-.3.7-.5 1.1-.5h45.6c.4 0 .6.3.5.6l-.8 2.4c-.1.4-.5.6-.9.6zm24.2 9.2c-.4 0-.5-.3-.3-.6l1.4-2.5c.2-.3.6-.6 1-.6h20c.4 0 .6.3.6.7l-.2 2.4c0 .4-.4.7-.7.7z" class="st4"/><g id="CXHf1q_3_" transform="translate(-20 2)"><path id="path78" d="M153.1 99.3c-6.3 1.6-10.6 2.8-16.8 4.4-1.5.4-1.6.5-2.9-1-1.5-1.7-2.6-2.8-4.7-3.8-6.3-3.1-12.4-2.2-18.1 1.5-6.8 4.4-10.3 10.9-10.2 19 .1 8 5.6 14.6 13.5 15.7 6.8.9 12.5-1.5 17-6.6.9-1.1 1.7-2.3 2.7-3.7h-19.3c-2.1 0-2.6-1.3-1.9-3 1.3-3.1 3.7-8.3 5.1-10.9.3-.6 1-1.6 2.5-1.6h36.4c-.2 2.7-.2 5.4-.6 8.1-1.1 7.2-3.8 13.8-8.2 19.6-7.2 9.5-16.6 15.4-28.5 17-9.8 1.3-18.9-.6-26.9-6.6-7.4-5.6-11.6-13-12.7-22.2-1.3-10.9 1.9-20.7 8.5-29.3 7.1-9.3 16.5-15.2 28-17.3 9.4-1.7 18.4-.6 26.5 4.9 5.3 3.5 9.1 8.3 11.6 14.1.6.9.2 1.4-1 1.7z" class="st4"/><path id="path80" d="M186.2 154.6c-9.1-.2-17.4-2.8-24.4-8.8-5.9-5.1-9.6-11.6-10.8-19.3-1.8-11.3 1.3-21.3 8.1-30.2 7.3-9.6 16.1-14.6 28-16.7 10.2-1.8 19.8-.8 28.5 5.1 7.9 5.4 12.8 12.7 14.1 22.3 1.7 13.5-2.2 24.5-11.5 33.9-6.6 6.7-14.7 10.9-24 12.8-2.7.5-5.4.6-8 .9zm23.8-40.4c-.1-1.3-.1-2.3-.3-3.3-1.8-9.9-10.9-15.5-20.4-13.3-9.3 2.1-15.3 8-17.5 17.4-1.8 7.8 2 15.7 9.2 18.9 5.5 2.4 11 2.1 16.3-.6 7.9-4.1 12.2-10.5 12.7-19.1z" class="st4"/></g></svg>', - go: '<svg viewBox="0 0 32 32"><path d="M18.3 10c-1.1 0-1.9-.6-2.1-1.6-.1-.6.1-1.1.5-1.5.6-.7 1.6-.9 2.5-.6.8.3 1.3 1 1.2 1.9 0 .8-.5 1.4-1.4 1.7-.3.1-.5.1-.7.1zm-1.7-1.8c0 .4.3.7.6.7s.6-.3.6-.7c0-.4-.3-.7-.6-.7-.3.1-.6.4-.6.7zm-3.5-1.8C15 6.4 15.5 8 15 9.1c-.3.7-.9 1-1.7 1.1-1 .2-1.9-.4-2.2-1.3-.4-1.1.3-2.2 1.5-2.5h.5zm-.4 2c0-.4-.3-.7-.6-.7s-.6.3-.6.7c0 .4.3.7.6.7s.6-.3.6-.7zm3.2 1c.2 0 .4 0 .6.1.3.1.4.4.3.6 0 .1 0 .1.1.2.2.1.3.2.5.4s.2.4.1.6c-.1.2-.4.3-.6.2-.1 0-.3-.1-.4-.2-.3-.1-.6-.1-.9 0-.2.1-.4.2-.6.2-.4 0-.6-.2-.5-.6 0-.3.2-.5.4-.6 0 0 .1 0 .1-.1-.1-.4.2-.5.4-.7.1-.1.3-.1.5-.1zm-.1 1.1c.3 0 .6-.1.8-.2.3-.2.3-.4.1-.6-.1-.1-.3-.2-.4-.2-.3-.1-.7 0-.9.2-.3.3-.2.6.2.7-.1.1 0 .1.2.1z"/><path d="M16.7 12.1v.2c0 .2-.1.4-.3.4-.2 0-.4-.2-.4-.3-.1-.3 0-.6 0-1 0-.1 0-.1.1-.1.2 0 .4.1.5.2.1 0 .1.1.1.1v.5zm-.9-.2v.3c0 .2-.1.3-.2.4-.2.2-.4.1-.5-.1-.1-.2-.1-.5-.1-.8 0-.1 0-.1.1-.1.2-.1.4-.1.6-.2.1 0 .1 0 .1.1v.4z"/><g><path d="M10.5 27h-.2c-.1-.1-.3-.2-.4-.4-.2-.2-.2-.5.1-.8.2-.3.6-.5.9-.7-.8-.7-1.2-1.5-1.4-2.5-.2-.7-.2-1.5-.2-2.3 0-1.2.2-2.3.2-3.5-.3.2-.6.4-1 .5h-.2c-.2-.2-.3-.4-.3-.6 0-.2.2-.4.3-.5.3-.2.6-.3 1-.3.2 0 .2-.1.2-.2-.1-1-.2-2-.2-3-.1-1-.1-2.1.1-3.1.1-.5.1-.5-.3-.6-.5-.3-.8-.9-.7-1.4.2-1.1 1.4-1.6 2.4-1.1.1.1.2.1.3 0 .5-.4 1-.7 1.6-.9 1.7-.6 3.5-.7 5.2-.4.9.1 1.8.4 2.5 1 .2.2.4.2.6.1.8-.4 1.7-.1 2.1.7.4.8.1 1.5-.8 1.9-.1.1-.1.1-.1.2.3 1 .4 2 .4 3.1 0 1.2 0 2.3.1 3.5 0 .2 0 .2.2.3.4 0 .7.2 1 .5.2.2.2.3 0 .6v.1c0 .2-.2.3-.4.3s-.4-.1-.5-.2c-.1 0-.2-.1-.3-.1v.1c0 .6.1 1.2.1 1.9 0 1.1 0 2.1-.2 3.2-.2 1-.6 2-1.3 2.8-.1.1-.1.2 0 .3.3.2.6.5.8.9.1.3 0 .5-.3.7-.2.2-.4.1-.6 0l-.4-.4c-.2-.2-.3-.4-.5-.5-.1-.1-.2-.1-.3 0-1.1.6-2.3.8-3.5.8-1.4.1-2.9-.1-4.2-.7h-.1c-.2.2-.6.3-.8.5-.3-.2-.6 0-.9.2zm7.8-17c.2 0 .5 0 .7-.1.8-.3 1.3-.9 1.4-1.7 0-.9-.5-1.6-1.2-1.9-.8-.3-1.9 0-2.5.6-.4.4-.6.9-.5 1.5.2 1 1 1.6 2.1 1.6zm-5.2-3.6h-.5c-1.2.2-1.9 1.3-1.5 2.5.3.9 1.2 1.4 2.2 1.3.7-.1 1.3-.4 1.7-1.1.5-1.1 0-2.7-1.9-2.7zm2.8 3c-.2 0-.4 0-.6.1-.3.2-.5.3-.4.7 0 .1-.1.1-.1.1-.2.1-.4.3-.4.6-.1.4.2.6.5.6.2 0 .4-.1.6-.2.3-.1.6-.1.9 0 .1.1.3.1.4.2.3.1.5 0 .6-.2.1-.2.1-.4-.1-.6-.1-.2-.3-.3-.5-.4-.1 0-.1-.1-.1-.2.1-.3 0-.5-.3-.6-.1-.1-.3-.1-.5-.1zm.8 2.7v-.5c0-.1 0-.1-.1-.1-.2-.1-.4-.1-.5-.2-.1 0-.1 0-.1.1 0 .3-.1.6 0 1 0 .2.2.4.4.3.2 0 .3-.2.3-.4v-.2zm-.9-.2v-.4c0-.1 0-.1-.1-.1-.2.1-.4.1-.6.2-.1 0-.1.1-.1.1 0 .3 0 .5.1.8.1.2.3.3.5.1.1-.1.2-.2.2-.4-.1-.1 0-.2 0-.3z"/><path d="M16.6 8.2c0-.4.3-.7.6-.7s.6.3.6.7c0 .4-.3.7-.6.7s-.6-.3-.6-.7zm1.1.2c0-.1 0-.2-.1-.2s-.1.1-.1.2 0 .2.1.2c0 0 0-.1.1-.2zm-5 0c0 .4-.3.7-.6.7s-.6-.3-.6-.7c0-.4.3-.7.6-.7s.6.3.6.7zm-.3.3c.1 0 .1-.1.1-.1 0-.1 0-.2-.1-.2s-.1.1-.1.1c-.1.1 0 .2.1.2zm3.4 1.8c-.1 0-.3 0-.4-.1-.4-.1-.4-.4-.2-.7.3-.2.6-.3.9-.2.2 0 .3.1.4.2.2.2.2.5-.1.6-.1.1-.3.2-.6.2z"/></g><path d="M17.7 8.4c0 .1 0 .2-.1.2s-.1-.1-.1-.2 0-.2.1-.2c0 0 0 .1.1.2zm-5.3.3c-.1 0-.1-.1-.1-.2s0-.2.1-.1c.1 0 .1.1.1.2s0 .1-.1.1z"/></svg>', - godot: - '<svg viewBox="0 0 32 32"><g stroke-width=".32"><path d="M14.17 7.512c-.823.183-1.636.437-2.399.82.018.674.06 1.32.149 1.975-.297.19-.607.352-.883.574-.281.216-.57.423-.824.676a15.73 15.73 0 00-1.6-.932c-.597.644-1.157 1.339-1.613 2.116.359.563.743 1.129 1.1 1.57v4.765l.025.002 2.923.281a.314.314 0 01.284.291l.09 1.291 2.548.182.176-1.191a.315.315 0 01.312-.268h3.082c.156 0 .29.113.313.268l.176 1.191 2.548-.182.09-1.29a.314.314 0 01.283-.292l2.922-.28a.115.115 0 01.026-.003v-.38h.002V14.31c.411-.518.8-1.09 1.1-1.57-.457-.777-1.017-1.473-1.614-2.116a15.75 15.75 0 00-1.6.932c-.254-.253-.542-.46-.824-.676-.276-.222-.587-.384-.883-.574a18.37 18.37 0 00.149-1.975c-.763-.383-1.576-.637-2.399-.82a17.044 17.044 0 00-.89 1.733 6.085 6.085 0 00-.934-.075h-.011a6.08 6.08 0 00-.934.075 16.914 16.914 0 00-.89-1.733zm-2.313 6.973a1.76 1.76 0 11-1.762 1.76c0-.973.79-1.76 1.762-1.76zm8.285 0a1.76 1.76 0 11.002 3.521 1.76 1.76 0 01-.002-3.521zM16 15.514c.313 0 .566.231.566.516v1.62c0 .285-.253.516-.566.516s-.567-.23-.567-.515V16.03c0-.285.253-.516.567-.516z"/><path d="M21.277 19.96l-.09 1.297a.315.315 0 01-.292.292l-3.113.222h-.023a.315.315 0 01-.31-.268l-.18-1.21h-2.54l-.178 1.21a.314.314 0 01-.333.268l-3.113-.222a.315.315 0 01-.292-.292l-.09-1.297-2.628-.253c.001.282.005.591.005.653 0 2.775 3.52 4.11 7.894 4.125h.011c4.374-.016 7.894-1.35 7.894-4.125 0-.063.004-.37.005-.653zm-8.082-3.61a1.169 1.169 0 11-2.337 0 1.169 1.169 0 012.337 0m5.611 0a1.168 1.168 0 102.337 0 1.168 1.168 0 00-2.337 0"/></g></svg>', - gradle: - '<svg xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 43 43"><defs><path id="a" d="M27.22 20.842l-1.571-.791v-.004c0-.546.441-.988.986-.988a.987.987 0 01.584 1.783m8.404-9.334a5.124 5.124 0 00-7.137-.12.49.49 0 00-.011.705l.647.648a.488.488 0 00.639.046 2.921 2.921 0 011.762-.588 2.947 2.947 0 012.943 2.95c0 .815-.33 1.553-.862 2.087-4.075 4.088-9.518-7.367-21.864-1.474a1.68 1.68 0 00-.732 2.358l2.118 3.672a1.672 1.672 0 002.268.625l.053-.03-.042.03.939-.527s1.614-.98 2.957-2.212a.517.517 0 01.674-.021l.003.001.003.003a.486.486 0 01.022.738 22.053 22.053 0 01-3.137 2.352l-.031.018-.94.527a2.688 2.688 0 01-3.628-1l-2.003-3.465C6.42 21.553 4.088 26.799 5.34 33.435a.49.49 0 00.48.399h2.278a.489.489 0 00.484-.428 3.344 3.344 0 013.314-2.923c1.7 0 3.104 1.274 3.313 2.923a.49.49 0 00.485.428h2.221a.488.488 0 00.484-.428 3.345 3.345 0 013.314-2.923c1.7 0 3.104 1.274 3.314 2.923a.489.489 0 00.484.428h2.193a.489.489 0 00.488-.482c.052-3.105.885-6.67 3.265-8.455 8.238-6.181 6.07-11.478 4.166-13.389"/></defs><use fill-rule="evenodd" xlink:href="#a"/></svg>', - grails: - '<svg viewBox="0 0 32 32"><path d="M15.5 22.8h-.3c-.1-.1-.3-.1-.4-.1-.3-.1-.7-.2-1-.3-.3-.2-.4-.4-.2-.7.2-.3.3-.6.4-.9.5-1.1.9-2.2.7-3.5-.1-1-.6-1.8-1.6-2.2-.8-.3-1.6-.7-2.2-1.3-1.4-1.3-2.4-2.7-2.3-4.7h14.8c0 1-.2 1.9-.7 2.7-.9 1.6-2.2 2.6-3.8 3.3-1 .5-1.6 1.3-1.7 2.4-.1 1.4.5 2.7 1.1 3.9.3.6.2.7-.4 1-.2.1-.3.1-.5.2-.3.1-.7.1-1 .2H16c-.1-.1-.3-.1-.5 0zM28 13.9c-.2.2-.2.5-.3.7-.5 1.1-1.3 1.9-2.4 2.2-.8.2-1 .8-1 1.5-.1.8.2 1.5.5 2.2.3.6.2.8-.5.9-.7.1-1.3.1-2-.1-.3-.1-.4-.3-.2-.6.4-.7.7-1.4.6-2.3-.1-1-.3-1.3-1-1.4-.2 0-.4-.1-.5-.3.1 0 .1-.1.2-.1 1.6-.6 2.7-1.7 3.5-3.1.1-.2.3-.2.5-.2H28v.6zm-24-.7h2.5c.2 0 .3 0 .4.2.9 1.5 2.2 2.5 3.8 3.2-.1.1-.2.1-.3.2-.8.3-1.1.8-1.1 1.7 0 .6.2 1.2.5 1.8.1.2.2.4.3.5.1.2.1.4-.1.4-.9.4-1.8.4-2.7 0-.3 0-.3-.2-.2-.5.4-.8.8-1.6.7-2.5-.1-.8-.3-1-1-1.2-1.3-.4-2.1-1.4-2.6-2.6-.1-.1 0-.3-.2-.3v-.9z"/></svg>', - graphql: - '<svg viewBox="0 0 32 32"><path d="M24.8 18.8c-.2-.1-.3-.2-.5-.2v-5.2c.2 0 .4-.1.5-.2.9-.5 1.3-1.7.7-2.7-.5-.9-1.7-1.3-2.7-.7-.2.1-.3.2-.4.4l-4.5-2.6c0-.3.1-.4.1-.6 0-1.1-.9-2-2-2s-2 .9-2 2c0 .2 0 .4.1.6l-4.5 2.6c-.1-.2-.3-.3-.4-.4-1-.6-2.2-.2-2.7.7-.5.9-.2 2.1.7 2.7.2.1.3.2.5.2v5.2c-.2 0-.4.1-.5.2-.9.5-1.3 1.7-.7 2.7.5.9 1.7 1.3 2.7.7.2-.1.3-.2.4-.4l4.5 2.6c0 .3-.1.4-.1.6 0 1.1.9 2 2 2s2-.9 2-2c0-.2 0-.4-.1-.6l4.5-2.6c.1.2.3.3.5.4.9.5 2.1.2 2.7-.7.5-.9.1-2.1-.8-2.7zm-14.7 1.3c0-.2-.1-.4-.2-.5-.1-.2-.2-.3-.3-.4l5.9-10.3c.2 0 .4.1.5.1.2 0 .4 0 .5-.1l5.9 10.3c-.1.1-.3.3-.3.4-.1.2-.2.3-.2.5H10.1zm11.8-9.2c-.1.5-.1 1 .2 1.5.3.5.7.8 1.2.9v5.2h-.1L17.4 8.4l.1-.1 4.4 2.6zm-7.3-2.6s0 .1 0 0L8.7 18.6h-.1v-5.2c.5-.1.9-.4 1.2-.9.3-.5.3-1 .2-1.5l4.6-2.7zm2.8 15.4c-.4-.4-.9-.6-1.4-.6-.6 0-1.1.2-1.4.6l-4.5-2.6V21h11.8v.1l-4.5 2.6z"/></svg>', - hacklang: - '<svg viewBox="0 0 32 32"><path d="M15.8 5v6.3c0 .1 0 .2-.1.3L9.3 18s0 .1-.1.1v-6.4c0-.1 0-.1.1-.1 2.2-2.2 4.3-4.4 6.5-6.6zm8 9.2v6.4c0 .1 0 .1-.1.1l-6.5 6.5h-.1v-6.4c0-.1 0-.1.1-.1 2.2-2.1 4.3-4.3 6.6-6.5-.1 0-.1 0 0 0zm-.3-1.5l-6.4 6.4v-6.3c0-.1 0-.1.1-.1h6.3zm-7.6.3v6.3c0 .1 0 .1-.1.1H9.5c2.1-2.2 4.2-4.3 6.4-6.4zM9.2 27s0-.1 0 0v-6.3c0-.1 0-.1.1-.1h6.3c-2.1 2.1-4.2 4.3-6.4 6.4z"/></svg>', - haml: '<svg viewBox="0 0 32 32"><path d="M20 15c-1-.4-.3-2-.3-2l1.1-1s.3.1.6-.1c.4-.2.3-.7.3-.7l.8-.9s.3-.1-.9-1-1.6-.4-1.6-.4l-.9.7s-.3 0-.5.1 0 .5 0 .5l-4.1 3.4-2.1-4.8s.2-.2.1-.5c0-.3-.3-.3-.3-.3-.5-.9-.7-.9-.7-.9-1.7-.4-2.4.7-2.4.7-.1.1.1.7.1.7s-.2.1-.1.6c.2.7.6.4.6.4l2.7 6c0 .5-2.1 8.4-2.1 8.4 1.6 1.7 4 .9 4 .9 0-1 1.2-6.8 1.2-6.8 1.3 1.2 2.7 1.4 3.2 1.4 0 .4.1.7.1.7s1.9.7 2.9-.8c.1-.1.1-.2.1-.3 0 0 1.1-.4 1.1-1.4 0-1.4-1.9-2.2-2.9-2.6zm2 3.6c.2-.7-.2-1.1-.2-1.1s-.1.6-1.2.9c-1.1.3-1.4-.2-1.4-.2s-.2.3-.4.7c-2.3-.4-3-1.6-3.2-1.9-.1-.3.1-1 .1-1l3-2.2c-.2 1.4 1.4 1.9 1.4 1.9s2.3.8 2.3 2c.1.5-.2.8-.4.9z"/></svg>', - mustache: - '<svg viewBox="0 0 32 32"><path d="M7.4 15.7c0-.2 0-.4-.1-.5-.2-.2-.6-.2-.7.1-.3.5 0 1 .6 1.2.4.1.7.1 1-.2.5-.4 1-.8 1.5-1.3.7-.6 1.3-1.2 2.2-1.5 1.2-.4 2.4-.4 3.4.5l.6.6.2.2c.1-.2.2-.3.3-.4.6-.7 1.4-1.1 2.4-1.1 1.1 0 2.1.4 2.9 1.1.6.5 1.1 1 1.7 1.5.3.3.6.5 1 .6.5.1 1-.2 1.2-.6.1-.3 0-.5-.2-.7-.2-.2-.4-.2-.6-.1-.2.1-.3.3-.2.5v.1c-.3-.2-.4-.5-.4-.8 0-.4.3-.6.6-.7.9-.3 1.8.2 2 1.2.1.6.1 1.3-.2 1.9-.3.7-.9 1-1.6 1.2-1.4.4-2.7.1-4-.4l-2.7-1.2c-1.1-.5-2.3-.7-3.5-.4-.7.2-1.5.5-2.2.8-.9.4-1.7.8-2.6 1.1-1.1.4-2.2.5-3.3.1-1.1-.4-1.9-1.2-1.8-2.7.1-.7.3-1.3 1-1.5.4-.2.9-.2 1.3 0 .7.3.7 1 .2 1.4z"/></svg>', - haskell: - '<svg viewBox="0 0 32 32"><path d="M14.2 8.9c1.2 1.7 2.3 3.5 3.5 5.2 2 3 4 5.9 5.9 8.9h-3.5l-.1-.1c-.9-1.4-1.9-2.8-2.8-4.2-.1-.1 0-.1-.1 0-.9 1.4-1.9 2.8-2.8 4.2l-.1.1h-3.5v-.1c1.5-2.3 3.1-4.6 4.6-6.9v-.1c-1.5-2.3-3.1-4.6-4.6-6.9v-.1h3.5z"/><path d="M9.5 23.1H6V23c.4-.6.8-1.3 1.3-1.9 1.1-1.7 2.2-3.3 3.3-5V16c-1.5-2.4-3-4.7-4.6-7h3.5l.1.1c.8 1.1 1.5 2.3 2.3 3.4.8 1.2 1.6 2.3 2.3 3.5v.1c-1.5 2.3-3.1 4.6-4.7 7 .1-.1.1-.1 0 0zM26 15.4h-6.3c-.5-.8-1-1.5-1.5-2.3V13H26v2.4zm0 3.6s0-.1 0 0h-4c-.5-.8-1-1.5-1.5-2.3v-.1H26V19z"/></svg>', - haxe: '<svg viewBox="0 0 32 32"><path d="M24.9 20l-2-4 2-4 .1-.1V7h-4.9l-.1.1-4 2-4-2-.1-.1H7v4.9l.1.1 2 4-2 4-.1.1V25h4.9l.1-.1 4-2 4 2 .1.1H25v-4.9l-.1-.1zM22 15.6L16.4 10l7.5-1.9-1.9 7.5zm-12 0L8.1 8.1l7.5 1.9-5.6 5.6zm0 .8l5.6 5.6-7.5 1.9 1.9-7.5zm12 0l1.9 7.5-7.5-1.9 5.6-5.6z"/></svg>', - jade: '<svg viewBox="0 0 32 32"><path d="M26 19.9c-.2-1.1-.2-2.3-.1-3.4.1-.6.2-1.2 0-1.9-.2-.6-.3-1.2-.4-1.8-.2-1.3-.4-2.7-.9-4-.2-.4-.4-.7-.9-.7-.4 0-.6.2-.6.6.1.9.3 1.9.4 2.8.1.7.3 1.3.4 2v.4c-.1 0-.3 0-.4-.1-.4-.3-.8-.5-1.1-.9-.5-.7-.9-1.4-1.2-2.1-.6-1.4-1.1-2.8-1.8-4-.6-1-1.4-1.2-2.4-1.2-.3 0-.4.2-.4.4.1.3.1.6.3.9.9 1.6 1.7 3.3 2.6 4.9.3.5.7 1 1 1.4.4.6.3.8-.3 1.1-.1 0-.1 0-.2.1-.8.2-1.4-.1-1.9-.6-.5-.4-1.1-.7-1.8-.8-.3 0-.7-.1-1-.1-1.4-.1-2.7-.1-4.1.4-2 .7-3.1 2.3-3.8 4.2-.2.6-.4 1.3-.6 2-.1-.2-.1-.2-.2-.3-.1-.1-.2-.2-.2-.4-.1.1-.3.2-.4.4v.5c0 .3.1.6.2.8.7 1.7 1.4 3.5 2 5.2.2.4.5.6.9.6 1 .1 2 .1 2.9-.1l1.8-.3c-.2-.2-.4-.4-.6-.5 0-.1.1-.1.1-.2.5.1.9.2 1.4.3 1.6.6 3.2.9 4.9.8.3 0 .6-.1.7-.4l.3-.6c.2-.8.6-1.5 1-2.1.7-1 .6-.9 1.7-.6 1.2.4 2.3-.2 2.6-1.4.1-.4.1-.9.1-1.3zm-1.1-1.2c-.1.1-.3.3-.4.3-.9.1-1.8.1-2.6-.3-.3-.1-.5-.4-.8-.7.3-.1.6-.2.8-.3.9-.1 1.7.1 2.5.5.1 0 .2.1.2.1.1.1.3.3.3.4z"/></svg>', - java: '<svg viewBox="0 0 32 32"><path d="M22.003 18.236c-.023.764.018 1.78-.282 2.64a5.76 5.76 0 01-1.348 2.304 6.607 6.607 0 01-2.19 1.46c-.825.3-1.453.36-2.585.36s-2.135-.116-3.146-.528a6.873 6.873 0 01-2.472-1.91l2.022-2.584a4.42 4.42 0 001.517 1.236c.6.3 1.255.449 1.967.449.936 0 1.666-.3 2.19-.899.525-.637.787-1.573.787-2.809V7h3.54v11.236z"/></svg>', - javascript: - '<svg viewBox="0 0 32 32"><path d="M11.4 10h2.7v7.6c0 3.4-1.6 4.6-4.3 4.6-.6 0-1.5-.1-2-.3l.3-2.2c.4.2.9.3 1.4.3 1.1 0 1.9-.5 1.9-2.4V10zm5.1 9.2c.7.4 1.9.8 3 .8 1.3 0 1.9-.5 1.9-1.3s-.6-1.2-2-1.7c-2-.7-3.3-1.8-3.3-3.6 0-2.1 1.7-3.6 4.6-3.6 1.4 0 2.4.3 3.1.6l-.6 2.2c-.5-.2-1.3-.6-2.5-.6s-1.8.5-1.8 1.2c0 .8.7 1.1 2.2 1.7 2.1.8 3.1 1.9 3.1 3.6 0 2-1.6 3.7-4.9 3.7-1.4 0-2.7-.4-3.4-.7l.6-2.3z"/></svg>', - jinja: - '<svg viewBox="0 0 1200 1000"><path d="M843.3 275.4c0-1.8-3.4-3.6-5.2-5.4h-2.7c-14.2 6.5-28.3 13.3-42.6 19.4-62 26.5-127.2 38.7-194.2 43-27.9 1.8-55.7 3.9-83.6 5.5-48.6 2.8-97.3 6.7-145-16.2 8.6 18.7 3.1 30.5-13.6 37.6v2.7c5.2 2.6 10.2 6 15.8 7.7 8.4 2.6 15.9 4 24.1 10 9.4 6.8 14.8 12.9 18.1 23 .6 1.8 5.2 3.1 8.1 3.3 11.7.9 23.5 2.3 35.1 1.5 11.2-.8 22.8 3.1 21.4 12.5-1.1 7.3-13.8 15.4-22.9 18.3-9.3 3-20.5.2-30.8-.4-8.6-.5-13.1 1.1-9.6 11.3 2.2 6.2 2.3 13.1 3.4 19.9h58.4c-1.5 27.2-3 53.9-4.6 81.6-15.8-.9-30-1.7-45.3-2.5-.5-4.7-1-9-1.4-12.6 8.3-6.1 15.9-11.7 23.6-17.3-16.4-12.6-44.2-13.6-73.8-1.3 5.6 4.6 10 8.7 14.9 12 12.4 8.7 12 14.2-3.6 21.9 13.6 25 13.5 52.5 12 79.9-.2 4.5-5.6 8.5-6.7 13.2-1.7 7.3-5.4 18.3-2 21.7 9 9.2 5 19.1 5.8 28.7.3 4 .2 8.2-.3 12.2-1.2 8.9 2.6 12.3 11.4 11.7 7.5-.5 15.1-.1 23.3-.1-1.9-15.5-3.6-29.7-5.5-45.8h40.2c-1.9 13-3.9 26.5-5.9 40.7h50.6v-44.8c9.7-.9 17.6-1.6 26.7-2.4v44.5h30.4c0-3.9-.2-8.2 0-12.4.9-12.9 2.7-25.7 2.7-38.6 0-8.8-3.1-17.5-3.8-26.4-1.5-19.6-7.6-39.2 2.3-58.9 2.6-5.2 5.8-15.1-3.8-21.4-2.1-1.4-1-11.1 1.7-15 4-5.8 10.6-9.9 16.9-15.4-22.6-9.3-44.1-9.3-66.2 0 7.2 8.8 14.2 17.3 21.1 25.7-1 1.2-2.1 2.3-3.1 3.5h-28.6v-84.4c52.7-2.9 103.7-5.8 157.9-8.8-1.7 29.8-3.3 58.1-5 87.3h-26.6V528c8.3-6.2 16-12 25-18.8-26.8-12.4-51.8-12.2-78.6-1.6 5.1 5.6 10.1 10.9 14.9 16.5 2.9 3.4 7.5 7.3 7.4 10.9-.1 3.8-4.9 7.5-9 13.1 5.4 6.3-3.8 20 8.9 27.7 1.5.9.8 6 .8 9.1-.1 16.2.3 32.5-.8 48.7-.4 6.3-4.2 12.5-8.3 18.3 3.2 21.3 9.9 42.8 4.7 65.7-.8 3.6 2.9 8.2 4.4 12.4h37.9c-1.6-17.3-3.3-34.6-5-53h26.6v45.5h54.5c-2-17.2-3.7-32.3-5.6-48.6h24.2v42.7c2.3.9 3.8 1.9 5.5 2.1 29.1 3.1 28.8 2.7 27.3-25.6-.7-12.9 2.2-26.1 3.5-39.1.3-2.6 1.7-5.9.7-7.8-13.1-23.9-8-48.2-3.4-72.9 1.5-7.8-2-16.5-3.1-24.8-.6-4.4-.9-8.9-1.2-12.2 8-7 15.2-13.3 23.1-20.2-24.9-9.1-48.7-9.8-73.1.2 5.2 12.6 27.8 12 22.9 32.8-8.8 0-18.1.3-27.4-.2-2.4-.1-6.3-2.8-6.6-4.8-4.2-28.3-7.9-56.7-11.9-86.4 29.1-2.5 54.5-4.6 79.6-6.7 1.7-10.3 4-19.8 4.4-29.3.1-2.3-6-7.2-9.1-7-12.5.8-25.4 1.6-37.4 5.2-15.2 4.6-24-4.4-34.3-11.2 2-4.6 3.2-8.8 5.6-12.1 2.2-3 5.4-6.7 8.7-7.2 18.6-3.3 37.4-5.6 56-8.7 3.7-.6 9.7-2.4 10.3-4.7 7-27.2 31.4-28.3 51.8-35.3 5.5-1.9 10.9-3.7 16.4-5.5v-5.4c.4-18.3.6-36.4.2-54.4zM468.4 640.2c-13.8.9-26.6 1.7-41.4 2.6v-66.5c14.2.8 28.2 1.6 41.4 2.4v61.5zm68.7-61.5c0 18.5.5 36.4-.2 54.3-.4 11.1-9.9 6.6-15.7 7.1-6.2.6-14.6 2.9-14.7-8-.2-17.4-.1-34.9-.1-53.4h30.7zm-16.5-146.5c-16.7-4-11.6-15.9-4.6-27.5 10.5-.9 22-1.8 36.4-3 1.6 10.6 3.1 20.5 4.6 30.5-12.2.1-25 2.7-36.4 0zm138.9 214.1h-24.7v-70.4h24.7v70.4zm77.9-70.1v67c-8.2.6-16.1 1.2-25.4 1.8-1.4-23.4-2.6-44.7-3.9-67.5 9.8-.4 19-.8 29.3-1.3zM611.7 427.4c-1.7-29 .5-30.8 42.4-33.9 3.6 4.5 7.1 8.9 11.3 14.2-13.2 20.1-32.8 21.9-53.7 19.7z"/></svg>', - julia: - '<svg viewBox="0 0 32 32"><g><circle cx="11.3" cy="20.3" r="3.9"/><circle cx="20.7" cy="20.3" r="3.9"/><circle cx="16" cy="11.7" r="3.9"/></g></svg>', - karma: - '<svg viewBox="0 0 32 32"><path d="M9 7.4v4.8l3.3 12.5h1.5v-5h.8l3.4 5h5l-5.9-8.9v-.5l5.5-8h-5.3l-2.7 4.4h-.8V7.4z"/></svg>', - kotlin: - '<svg viewBox="-25 -25 110 110"><linearGradient id="a" x1="15.959" x2="44.307" y1="-13.014" y2="15.333" gradientTransform="matrix(1 0 0 -1 0 61)" gradientUnits="userSpaceOnUse"><stop offset=".097" stop-color="#0095d5"/><stop offset=".301" stop-color="#238ad9"/><stop offset=".621" stop-color="#557bde"/><stop offset=".864" stop-color="#7472e2"/><stop offset="1" stop-color="#806ee3"/></linearGradient><path d="M0 60l30.1-30.1L60 60z"/><linearGradient id="b" x1="4.209" x2="20.673" y1="48.941" y2="65.405" gradientTransform="matrix(1 0 0 -1 0 61)" gradientUnits="userSpaceOnUse"><stop offset=".118" stop-color="#0095d5"/><stop offset=".418" stop-color="#3c83dc"/><stop offset=".696" stop-color="#6d74e1"/><stop offset=".833" stop-color="#806ee3"/></linearGradient><path d="M0 0h30.1L0 32.5z"/><linearGradient id="c" x1="-10.102" x2="45.731" y1="5.836" y2="61.669" gradientTransform="matrix(1 0 0 -1 0 61)" gradientUnits="userSpaceOnUse"><stop offset=".107" stop-color="#c757bc"/><stop offset=".214" stop-color="#d0609a"/><stop offset=".425" stop-color="#e1725c"/><stop offset=".605" stop-color="#ee7e2f"/><stop offset=".743" stop-color="#f58613"/><stop offset=".823" stop-color="#f88909"/></linearGradient><path d="M30.1 0L0 31.7V60l30.1-30.1L60 0z"/></svg>', - dart: '<svg data-name="Layer 1" viewBox="-60 -60 320 320"><path d="M194.42 83.82L154.8 44.2l-.08-.09-31.63-31.62c-3.25-3.25-9.56-6.71-14.87-6.71-4.75 0-9.13 1-11.91 2.66L40.77 36.22l-3.68 2-1.65 3.41-27.86 58c-.27.57-2.64 5.7-2.64 9.41a23.64 23.64 0 006.7 16.09l31.71 31.71 38.4 38.41h79.75v-32.91h32.92zM98.29 12.06c2.26-1.35 6-2.15 9.93-2.15s9.32 2.85 12 5.49l22.44 22.44h-.76a48.2 48.2 0 00-5.59-.31H47.43zm59.08 179.08H83.46l-37.2-37.2c-4.52-4.53-5.49-6.38-5.49-15.61v-93.8l116.6 116.6z"/></svg>', - less: '<svg viewBox="0 0 32 32"><path d="M7.5 15.1c1.5 0 1.7-.8 1.7-1.5 0-.6-.1-1.1-.1-1.7S9 10.7 9 10.2c0-2.1 1.3-3 3.4-3h.8v1.9h-.4c-1 0-1.3.6-1.3 1.6 0 .4.1.8.1 1.3 0 .4.1.9.1 1.5 0 1.7-.7 2.3-1.9 2.6 1.2.3 1.9.9 1.9 2.6 0 .6-.1 1.1-.1 1.5 0 .4-.1.9-.1 1.2 0 1 .3 1.6 1.3 1.6h.4v1.9h-.8c-2 0-3.3-.8-3.3-3 0-.6 0-1.1.1-1.7.1-.6.1-1.2.1-1.7 0-.6-.2-1.5-1.7-1.5l-.1-1.9zm17 1.7c-1.5 0-1.7.9-1.7 1.5s.1 1.1.1 1.7c.1.6.1 1.2.1 1.7 0 2.2-1.4 3-3.4 3h-.8V23h.4c1 0 1.3-.6 1.3-1.6 0-.4 0-.8-.1-1.2 0-.5-.1-1-.1-1.5 0-1.7.7-2.3 1.9-2.6-1.2-.3-1.9-.9-1.9-2.6 0-.6.1-1.1.1-1.5.1-.5.1-.9.1-1.3 0-1-.4-1.5-1.3-1.6h-.4V7.2h.8c2.1 0 3.4.9 3.4 3 0 .6-.1 1.1-.1 1.7-.1.6-.1 1.2-.1 1.7 0 .7.2 1.5 1.7 1.5v1.7z"/></svg>', - liquid: - '<svg viewBox="0 0 32 32"><path d="M18.1 18.8c0 .5-.1 1.1-.1 1.6-.1 1.6-.2 3.2-.2 4.8v.7c0 .1 0 .1-.1.1l-3-.6c-.5-.1-.9-.1-1.4-.2-.5-.1-.9-.2-1.3-.2-1.3-.2-2.6-.5-3.9-.7-.5-.2-1.1-.3-1.6-.4-.1 0-.1-.1-.1-.2.2-1.1.3-2.3.4-3.4 0-.2.1-.5.1-.7.1-.1 0-.2.1-.4.1-.5.1-1 .2-1.6.1-.5.2-1 .2-1.6.2-1.3.4-2.7.5-4 0-.3.2-.5.4-.6l1.8-.6c.1 0 .2-.1.2-.3.2-1.1.7-2.1 1.3-3 .4-.6.9-1.1 1.5-1.4.4 0 .7-.1 1.1-.1.5 0 .9.1 1.2.5.1.1.1.1.2.1.5 0 1 .2 1.3.6.3.4.5.8.7 1.2 0 .1.1.1.2.1.2-.1.3-.1.5-.2.2 0 .2 0 .2.2 0 .9-.1 1.7-.1 2.6-.1 1.1-.1 2.3-.2 3.4-.1 1.4-.1 2.7-.2 4.1.1.1.1.1.1.2zm-7.4-.5c.2.2.4.4.7.6.3.2.6.5.7.9.1.5-.1.9-.6 1H11c-.6-.1-1.1-.4-1.5-.7-.1-.1-.1-.1-.2.1-.1.4-.2.8-.4 1.2-.1.3 0 .5.2.6.9.7 1.9 1 2.9.9 1.1-.1 1.9-.7 2.3-1.7.2-.5.3-1 .3-1.5s-.2-1-.5-1.4c0-.1-.1-.1-.1-.2-.3-.5-.8-.8-1.3-1.1-.2-.1-.4-.3-.6-.5-.3-.5-.1-1.3.6-1.5.7-.1 1.3 0 1.9.2.1.1.2 0 .2-.1l.6-1.8c.1-.3.1-.3-.2-.4-.7-.2-1.4-.2-2.1-.1-1.6.3-3 1.4-3.1 3.2-.2.9.1 1.7.7 2.3zm4-11.5c-.1-.1-.1-.1-.2-.1-.2-.1-.4 0-.7 0-.6.2-1 .5-1.4 1-.7.8-1.1 1.8-1.4 2.8 0 .1 0 .1.1.1.5-.1.9-.3 1.4-.4.1 0 .1-.1.1-.1 0-.2.1-.4.1-.6.4-1.1.9-2.1 2-2.7zm.7 2.1c0-.4-.1-.9-.2-1.3-.1-.2-.1-.2-.2-.1-.2.1-.5.3-.6.5-.4.5-.7 1.1-.9 1.7v.1h.1c.5-.1 1-.3 1.4-.4.4-.1.4-.1.4-.5zm.8.2c.2-.1.5-.2.8-.3v-.1c-.1-.4-.3-.8-.6-1.1-.1-.1-.2-.2-.4-.3h-.1v.1c0 .1.1.3.1.4.1.3.1.7.1 1.1 0 .1 0 .2.1.2zm9.2 13.3l.3 2.1c0 .1 0 .1-.1.2-1.2.2-2.3.5-3.5.7-.8.2-1.7.4-2.5.5-.1 0-.2.1-.1-.1 0-.3 0-.7.1-1 .1-1.4.1-2.7.2-4.1v-1c0-.3 0-.7.1-1V18c.1-1.8.2-3.5.3-5.3v-1c.1-.8.1-1.5.1-2.3v-1c.1 0 .1 0 .1.1l.4.4c.2.2.4.3.5.5.1.2.3.2.5.2.4 0 .9.1 1.3.1.1 0 .2.1.2.2.1.4.1.8.2 1.2.1.7.2 1.3.3 2 .2 1 .3 2.1.5 3.1.3 1.7.5 3.4.8 5.1.1.4.2.7.3 1.1z"/></svg>', - livescript: - '<svg viewBox="0 0 32 32"><path d="M16 7.5V15c.1 0 .1 0 .1-.1 0 0 .1 0 .1-.1 0 0 .1 0 .1-.1.1 0 .1 0 .1-.1.1 0 .1 0 .1-.1.1 0 .1-.1.1-.2V8.2c0-.2.1-.3.3-.3h.6c.3 0 .3 0 .3.3v5h.1c.1 0 .1 0 .1-.1V13l.2-.2c.1-.1 0-.2 0-.2V8.8h1.1v2.8c.1 0 .1-.1.2-.1l1.1-1.1c.1 0 .1-.1.1-.2V8.7c.2-.1.4 0 .6 0 .2 0 .5-.1.6 0 .1.1 0 .4 0 .6v.5c0 .1 0 .1.1.2 0 0-.1 0 0 0h.9c.1 0 .2 0 .2.2v1h-.3c.1-.1.2 0 .3-.1h-1.4c-.1 0-.1 0-.1.1-.4.4-.9.8-1.3 1.3 0 .1.1.1.2.1h2.4c.2 0 .2 0 .2.2v.7c0 .2 0 .3-.3.3h-3.6c-.1 0-.2-.1-.2.1l-1.2 1.2h5.3v.9c0 .2-.1.2-.3.2h-6.3c-.1 0-.1 0-.1.1-.1 0-.1 0-.1.1-.1 0-.1 0-.1.1-.1 0-.1 0-.1.1-.1 0-.1 0-.1.1-.1 0-.1 0-.1.1-.1 0-.1 0-.1.1.1.1.2 0 .2 0h7.5c.1 0 .1 0 .1.1v.7c0 .3 0 .3-.3.3h-8.9l-.1.1c-.1.2-.3.3-.4.5.1.1.2 0 .3 0h9.9c.1 0 .2 0 .2.2v1H12.9c-.1 0-.2 0-.3.1L11.5 21c0 .1.2.1.2.1h13.6c.2 0 .2 0 .2.2v1.9c0 .3 0 .3-.3.3H10.5c-.1.1 0 .2 0 .2V26H8.2c-.2 0-.2-.1-.2-.2v-2.3c-.1-.1-.1 0-.2 0h-2c-.2 0-.2 0-.2-.2v-2c0-.2.1-.2.2-.2H8 5.6c.1-.1.1 0 .2 0h2.3c.1-.1 0-.2 0-.2V6.4c0-.2 0-.2.2-.2h1.9c.3 0 .3 0 .3.3v13.8c.2-.1.3-.3.4-.4.3-.3.5-.6.8-.8.1 0 .1-.1.1-.2V7.5c.2-.1.5 0 .7 0 .2 0 .4-.1.5 0 .1.1 0 .3 0 .5v9.7c.4-.4.8-.8 1.3-1.2.1-.1.1-.2.1-.2V7.5h1.1c.1 0 .1 0 .1.1.3-.2.3-.1.4-.1-.1 2.5-.1 4.9-.1 7.3v.2c.1-.1 0-.2 0-.3v-7c.1 0 0-.1.1-.2z"/><path d="M11 23.5c.1-.1.2 0 .3 0h14.4c.3 0 .3 0 .3-.3v-1.9c0-.2 0-.2-.2-.2H12.2c-.1 0-.2.1-.2-.1h13.9c.1 0 .1 0 .1.2v2.1c0 .2 0 .2-.2.2H11zm0-3.4c-.1-.1 0-.2 0-.3V6.3c0-.3 0-.3-.3-.3H8.8c-.2 0-.2 0-.2.2v-.1c-.1-.1-.1-.1.1-.1h2.1c.1 0 .2 0 .2.2v13.9zm7.5-7.6c-.1-.1 0-.2 0-.2V7.5c0-.3 0-.3-.3-.3h-.6c-.2 0-.3.1-.3.3v6.1c0 .1 0 .2-.1.2.1-.1.1-.2.1-.3V7.3c0-.2 0-.2.2-.2h.9c.1 0 .2 0 .2.2v4.8c-.1.2-.1.3-.1.4zm-2.9 4.7c.1-.1.2 0 .3 0h8.6c.3 0 .3 0 .3-.3v-.7c0-.1 0-.2-.1-.1H17h7.7c.2 0 .2 0 .2.2v.8c0 .1 0 .2-.2.2h-8.8c-.2-.1-.2-.1-.3-.1zm-3.3-9.9c.1.1 0 .1 0 .2v11.2c0 .1 0 .2-.1.2V7.5c.1-.1.1-.2.1-.2zm12.4 12.4v-1c0-.1 0-.2-.2-.2H14.3h10c.3 0 .3 0 .3.3v.8c.1 0 .2.1.1.1zM14.8 7.3v8.8c0 .1 0 .2-.1.2V7.4c.1 0 0-.1.1-.1zm5.8 5c0-.1.1-.1.2-.1h3.6c.2 0 .3-.1.3-.3v-.7c0-.2 0-.2-.2-.2h-2.4c-.1 0-.2 0-.2-.1h2.9c.1 0 .1.1.1.1v1.2h-3.8c-.3 0-.4 0-.5.1 0-.1 0-.1 0 0zM16 7.5c-.1.1 0 .2 0 .2v7.1c-.1-2.4-.1-4.8 0-7.3-.1 0-.1-.1 0-.2v.2zm2.1 7.2c.1-.1.2 0 .2 0h6.1c.2 0 .3 0 .3-.2v-.9c.1 0 .1.1.1.2v.9c0 .1 0 .2-.2.2-2.2-.2-4.3-.2-6.5-.2zM6 21h2.4-2.2c-.2 0-.2 0-.2.2v2c0 .2 0 .2.2.2h2.2-2.3c-.1 0-.1 0-.1-.1V21zM19.8 7.3v.1c0-.1-.1-.2 0-.1zm.9 4.9h4-4zM21 10c-.1 0 0-.1 0-.2V7.2c.1 0 0 .1 0 .1V10zm2.1-.3c0-.1.1-.1.1-.1h1.4c-.1.1-.2 0-.3.1h-1.2zm1.6 1.3h-2.8 2.8zM10.9 26v-2.5 2.3c.1.1.1.1 0 .2zM24.7 9.7v-1c0-.1 0-.2-.2-.2h-.9c-.1 0 0 0 0 0h1.1c.1.4 0 .8 0 1.2zm-2.4-2.4c.1 0 0 .1 0 .2v1.3c0 .1 0 .1-.1.2 0-.7.1-1.2.1-1.7zm-4.5 7.8c0-.1 0-.1.1-.1 0 0-.1 0-.1.1zm-.7.6c0-.1 0-.1.1-.1 0 0 0 .1-.1.1zm.6-.5c0-.1 0-.1 0 0 0-.1 0 0 0 0zm-1.6-.2c0 .1 0 .1 0 0-.1.1 0 0 0 0zm1.8-.1c0-.1.1-.1 0 0 .1-.1.1 0 0 0zm-.5.5c0-.1.1-.1 0 0 .1-.1.1 0 0 0zm-.7-1c0 .1-.1.1 0 0-.1.1-.1.1 0 0zm.2-.2c0 .1-.1.1 0 0-.1.1-.1.1 0 0zm.1 1.6zm-.1.2c0-.1 0-.1 0 0 0-.1 0-.1 0 0zm2.1-3.9c0 .1-.1.1 0 0-.1.1-.1.1 0 0zm-2.8 2.8zm.1-.1s0 .1 0 0c-.1 0 0 0 0 0zm-1.5-7.3c-.1 0-.1 0 0 0zm9.9 1zM14.8 18zm2.8-2.8zm0 .1s0-.1 0 0c0-.1 0 0 0 0zM14.9 18zm2.6-2.7s.1 0 0 0c.1 0 0 0 0 0zm-2.6 2.6zm2.5-2.5zm0 .1s0-.1 0 0c0-.1 0 0 0 0zm-.1 0s.1 0 0 0c.1 0 0 0 0 0zm-2.4 2.4c.1 0 .1 0 0 0 .1 0 .1 0 0 0zm2.4-2.3c0-.1 0-.1 0 0 0-.1 0-.1 0 0zm-.1 0c.1 0 .1 0 0 0 .1 0 .1 0 0 0zM15 17.9c0-.1 0-.1 0 0 0-.1 0-.1 0 0zm0-.1s.1 0 0 0c.1 0 0 0 0 0zm2.1-2c0-.1 0-.1 0 0 0-.1 0-.1 0 0zm-2 1.9c.1 0 .1 0 0 0 .1 0 .1 0 0 0zm4.6-6.4c0 .1 0 .1 0 0 0 .1 0 .1 0 0zm-4.1 6zm-.1 0zm0 .1s0-.1 0 0c0-.1 0 0 0 0zm-.1 0zm-.1.1c.1 0 .1 0 0 0 .1 0 .1 0 0 0zm0 0zm0 .1s0-.1 0 0c0-.1 0 0 0 0zm-.1 0s.1 0 0 0c.1 0 0 0 0 0zm3.4-5.1zm.1-.1s-.1.1 0 0c-.1.1 0 0 0 0zm.1-.1c-.1.1-.1.1 0 0-.1.1-.1.1 0 0zm0 0zm0 0zm.7-.7zm-.6.6zm.1-.1zm0-.1c0 .1 0 .1 0 0 0 .1 0 .1 0 0zm.1 0zm.1-.1s-.1.1 0 0c-.1.1 0 0 0 0zm0 0zm.1-.1c-.1.1-.1.1 0 0-.1.1-.1.1 0 0zm0 0zm.1-.1s-.1.1 0 0c-.1.1 0 0 0 0zm0 0zm.1-.1c-.1.1-.1.1 0 0-.1.1-.1.1 0 0zm-1.8 3.5s.1 0 0 0c.1 0 0 0 0 0zm-1.5-.2s-.1.1 0 0c-.1.1 0 0 0 0zm1.7 0zm.1-.1zm-1.6-.1s-.1.1 0 0c-.1.1 0 0 0 0zm0 0zm.1-.1zm.1-.1s0 .1 0 0c0 .1 0 0 0 0zm.1-.1zm0 0zm.2-.2zm.1-.1c-.1.1-.1.1 0 0-.1.1-.1.1 0 0zm0 0zm.1-.1s-.1.1 0 0c-.1.1 0 0 0 0zm0 0zm.1-.1zm2.5-2.5z"/></svg>', - lua: '<svg viewBox="0 0 32 32"><path d="M14.7 26C9.9 26 6 22.1 6 17.3c0-4.8 3.9-8.8 8.9-8.7 4.7.1 8.5 3.9 8.5 8.7 0 4.8-3.9 8.7-8.7 8.7zm3.6-14.9c-1.4 0-2.6 1.2-2.6 2.6 0 1.4 1.1 2.6 2.6 2.6 1.4 0 2.6-1.1 2.6-2.6 0-1.4-1.1-2.6-2.6-2.6zm5.1 0c-1.4 0-2.6-1.1-2.5-2.6C20.9 7.1 22 6 23.5 6 24.9 6 26 7.2 26 8.6c0 1.4-1.2 2.5-2.6 2.5z"/></svg>', - markdown: - '<svg viewBox="0 0 32 32"><path d="M20.7 6.7v9.9h3.8c-2.9 3-5.8 5.9-8.7 8.8-2.7-2.8-5.6-5.8-8.4-8.7h3.5V6.6c1.3.9 4.4 3.1 5 3.1.6 0 3.6-2.2 4.8-3z"/></svg>', - argdown: - '<svg fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" clip-rule="evenodd" viewBox="0 0 32 32"><path d="M20.451 16.65h3.55l-8 8.975-8-8.975h3.56V6.375l3 1.875v11.765l1.44 1.615 1.45-1.628V8.25l3-1.875V16.65z"/></svg>', - info: '<svg viewBox="0 0 32 32"><path d="M26 15.1c-.1-1.7-.7-3.2-1.6-4.6C23 8.4 21 7 18.6 6.4c-.7-.2-1.4-.3-2-.3H15c-2 .2-3.7.9-5.3 2.1-1.8 1.5-3 3.3-3.5 5.6-.1.5-.2 1.1-.2 1.6V17c.2 1.7.7 3.3 1.7 4.7 1.1 1.6 2.6 2.9 4.4 3.6 1.1.4 2.2.7 3.3.8H17c2.4-.2 4.5-1.2 6.2-3 1.4-1.4 2.3-3.1 2.7-5 .1-.5.1-.9.2-1.4v-1.1c-.1-.2-.1-.3-.1-.5zm-10 9.4c-4.7 0-8.4-3.8-8.4-8.5s3.8-8.5 8.6-8.5c4.6.1 8.4 3.8 8.4 8.5-.1 4.7-3.9 8.5-8.6 8.5z"/><path d="M18.4 21.4c-.2 0-.3 0-.5-.1-.2 0-.2-.2-.3-.3v-6.5c-1.6.1-3.1.1-4.7.2v.8h1c.4 0 .6.3.6.7v4.6c0 .4-.2.6-.6.6H13v.8h6v-.8h-.6zm-2.6-8.1c1 0 1.7-.8 1.7-1.7 0-.9-.8-1.7-1.7-1.7-1 0-1.7.8-1.7 1.7 0 .9.8 1.7 1.7 1.7z"/></svg>', - clock: - '<svg viewBox="0 0 32 32"><path d="M15.5 7h1.2c.5.1.9.1 1.4.2 1.2.3 2.3.8 3.3 1.5.8.6 1.4 1.2 1.9 2 .9 1.2 1.4 2.5 1.6 4 0 .2.1.4.1.7v1.3c-.1.4-.1.8-.2 1.1-.3 1.2-.8 2.4-1.5 3.4s-1.6 1.8-2.7 2.5c-1.1.6-2.2 1.1-3.5 1.2-.2 0-.4.1-.6.1h-1.3c-.4-.1-.8-.1-1.1-.2-1.2-.3-2.4-.8-3.4-1.5s-1.8-1.6-2.5-2.7c-.6-1.1-1.1-2.2-1.2-3.5.1-.1 0-.3 0-.6v-1.2c.1-.5.1-.9.2-1.4.3-1.2.8-2.3 1.5-3.3s1.7-1.8 2.7-2.4c1-.6 2.1-1 3.3-1.1.3 0 .5-.1.8-.1zm-7 9.2c.1 4.1 3.5 7.4 7.6 7.4 4.2 0 7.6-3.5 7.5-7.8-.1-4-3.5-7.4-7.8-7.3-4 .1-7.4 3.4-7.3 7.7z"/><path d="M16.4 16c.2-.2.5-.3.7-.5.9-.6 1.8-1.2 2.6-1.8.1-.1.2-.1.2-.2.2-.2.5-.1.7.1.2.2.1.5-.1.7-.3.2-.7.5-1 .7-.7.5-1.5 1-2.2 1.6-.4.3-.7.5-1.1.8-.3.2-.7 0-.7-.3v-6.5c0-.3.1-.5.4-.5.2-.1.5.1.5.4V16c0-.1 0 0 0 0z"/></svg>', - maven: - '<svg viewBox="0 0 32 32"><path d="M16.2 5.6c-2 1.6-2.7 2-3.7 3.4s-1 5.4 1 6.9c-.5 0-2.5-1.2-2.5-1.2s2.7 3.8 3.8 4.9c1.6 2.3 2.6 4.8 3 7.4.3-2.2-.1-4.3-1.2-6.3v-.1c-.1-.5 0-.9.5-1.3.5-.3 2.6-2.3 2.6-2.3s-2.2 1.3-2.8 1.4c.9-.9 1.5-1.7 2.4-2.3 1.5-1.2 1.8-2.7 1.6-4.2 0-.4-.1-.7-.2-1.1-.5-2.2-1.7-4.1-3.6-5.9-.3.4-.6.5-.9.7z"/></svg>', - nim: '<svg viewBox="0 0 32 32"><g fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"><path d="M15.932 10l-1.371 1.069c-.712-.023-2.11.137-2.866.412-.697-.442-1.31-.93-1.31-.93l-.853 1.43c-.488.26-.979.552-1.415.938L7 12.464c.673 1.356 1.122 2.713 2.356 3.533 1.96-3.094 11.064-2.806 13.064-.018 1.293-.673 1.796-2.12 2.304-3.463-.4.134-.8.274-1.196.421-.267-.291-.898-.74-1.257-.956-.34-.623-.835-1.464-.835-1.464s-.586.436-1.266.912c-.918-.17-2.029-.375-2.963-.324-.635-.523-1.274-1.105-1.274-1.105z"/><path d="M7.696 15.348l1.616 3.915c2.807 3.703 9.975 3.958 13.1.072l1.737-4.008c-.802 1.187-2.106 2.007-2.91 2.451-.57.313-1.888.502-1.888.502l-3.456-1.792-3.479 1.756s-1.3-.209-1.888-.484c-1.188-.636-1.987-1.383-2.83-2.409l-.002-.002z"/></g></svg>', - github: - '<svg viewBox="0 0 32 32"><path d="M17.8 20.6c.4-.1.8-.1 1.2-.2 1.2-.3 2.2-.9 2.7-2 .6-1.2.7-2.4.4-3.7-.1-.6-.4-1-.8-1.5-.1-.1-.1-.2-.1-.3.2-.8.2-1.5-.1-2.3 0-.1-.1-.2-.3-.2-.5 0-.9.2-1.3.4s-.7.4-1 .6c-.1.1-.2.1-.3.1-1.6-.4-3.1-.4-4.7 0-.1 0-.2 0-.3-.1-.7-.4-1.3-.8-2.1-.9-.5-.1-.5-.1-.6.4-.2.7-.2 1.4 0 2.1v.2c-.9 1-1.1 2.3-.9 3.5.1.4.1.7.2 1.1.5 1.4 1.5 2.2 3 2.6.4.1.8.2 1.3.3-.3.3-.5.8-.6 1.2 0 .1-.1.1-.1.1-1 .4-2.1.3-2.8-.8-.3-.5-.7-.9-1.4-1h-.5c-.2 0-.2.2-.1.3l.2.2c.5.3.9.8 1.1 1.4.4.9 1.1 1.3 2.1 1.4.4 0 .9 0 1.4-.1v1.9c0 .3-.3.5-.7.4-.8-.3-1.6-.7-2.4-1.2-3-2.1-4.6-5-4.4-8.7.2-4.6 3.6-8.3 8.1-9.2 5.2-1 10.2 2.2 11.6 7.3 1.3 5-1.6 10.2-6.4 11.8-.5.2-.8 0-.8-.6v-2.4c.1-.8 0-1.5-.6-2.1z"/></svg>', - notebook: - '<svg viewBox="0 0 32 32"><path d="M19.474 7c1.118 0 2.025.907 2.025 2.025v13.95A2.025 2.025 0 0119.474 25h-9.449A2.025 2.025 0 018 22.975V9.025C8 7.907 8.907 7 10.025 7h9.449zM22.4 18.702h.675c.342 0 .624.254.669.583l.006.092v1.348a.675.675 0 01-.583.669l-.092.006H22.4v-2.698h.675-.675zm0-3.6h.675c.342 0 .624.254.669.583l.006.092v1.348a.675.675 0 01-.583.669l-.092.006H22.4v-2.698h.675-.675zm0-3.6h.675c.342 0 .624.254.669.583l.006.092v1.348a.675.675 0 01-.583.669l-.092.006H22.4v-2.698h.675-.675zm-4.722-1.354h-5.852a.675.675 0 00-.669.583l-.006.092v1.353c0 .342.254.624.584.669l.091.006h5.852a.675.675 0 00.67-.584l.005-.091v-1.353a.675.675 0 00-.675-.675z"/></svg>', - nunjucks: - '<svg viewBox="0 0 32 32"><path d="M20.7 12.6l-1.2.4c-.3-1-1.4-4.1-3.4-4.1s-3.2 3.2-3.5 4.1l-1.4-.4L8.3 22l3.6 1.1 2.9-9.4-1.3-.4c.3-1.1 1.4-3.4 2.5-3.4s2.1 2.3 2.4 3.4l-1.5.5 2.9 9.4 3.6-1.1-2.7-9.5z"/></svg>', - npm: '<svg viewBox="0 0 32 32"><path d="M4 11.3v8h6.8v1.4h5.3v-1.3H28v-8.1H4zm6.6 6.7H9.3v-3.9H8V18H5.3v-5.3h5.3V18zm6.6 0h-2.7v1.4h-2.7v-6.6h5.3c.1 1.6.1 3.4.1 5.2zm9.4 0h-1.3v-3.9H24V18h-1.4v-3.9h-1.3V18h-2.7v-5.3h8V18zm-10.7-3.9h-1.3v2.6h1.3v-2.6z"/></svg>', - ocaml: - '<svg viewBox="0 0 32 32"><path d="M26 23.9V10.4c0-.4 0-.8-.1-1.2-.1-.6-.5-1.1-1-1.5-.3-.2-.6-.4-1-.4-.1 0-.1 0-.1-.1H8.1c0 .2-.3.2-.4.2-.8.3-1.3.9-1.6 1.7-.1.2-.1.4-.1.6v4.6c0 .3 0 .3.3.2.2-.1.3-.1.5-.2.4-.1.5-.5.7-.7.2-.3.3-.5.6-.7.2-.2.4-.2.7 0 .2.1.4.3.7.4.3.1.7.2 1 .1.3 0 .4-.3.5-.5.1-.2.2-.4.3-.5.2-.1.3-.1.6-.1.6.1 1 .6 1.4 1.1.1.2.2.3.4.4.2.1.4.3.6.5.5.6 1.2 1 1.7 1.5.3.3.7.6 1.2.8.6.2 1.1.3 1.6-.4.4-.5.7-1.1.8-1.7.1-.3.3-.5.5-.8h.1c.5-.1 1 0 1.4.1.2 0 .3 0 .5.1.4.1.8.1 1.2.3.4.2.5.6.4 1-.1.4-.2.2-.4.2H23c-.4.1-.8.3-1.2.5-.2.1-.4.3-.4.5-.1.4-.3.7-.6.9-.1.1-.2.1-.2.3-.2.1-.2.3-.4.4-.7.7-1.6 1-2.6 1.1H16c-.2 0-.2.1-.2.2.1.4 0 .8.1 1.2.1.2.1.4.1.6 0 .4.2.8.5 1.1.1.1.1.2.1.3 0 .3 0 .7.1 1 .1.4.2.9.4 1.3.1.1.2.2.3.1.2-.1.4-.1.6-.2.5-.2 1.1-.2 1.7-.2 1.2 0 2.3-.2 3.5.1.4.1.7.1 1.1.2.6.2 1.1.2 1.7.2.2 0 .4-.1.4-.4-.5-.4-.4-.5-.4-.7z"/><path d="M10.7 21.1l.1-.1c.1-.5.3-1 .7-1.4h-.1c-.7 0-1.3-.1-2-.3-.5-.1-1.1-.3-1.5-.7-.3-.3-.7-.2-.9.2 0 .1-.1.3-.1.4-.2.4-.4.7-.7 1-.1.2-.2.4-.2.7v1.9c0 .2.1.3.3.3.5.1.9.3 1.3.4.6.2 1.2.5 1.8.5.4 0 .4 0 .5-.4 0-.1.1-.1.1-.2h-.1.1v-.2.1c0-.1.1-.1.1-.2V23c.1-.2.1-.4.1-.5 0-.2 0-.4.1-.5v-.1c.2-.1.3-.4.4-.6v-.2zm5 1.9c-.2-.2-.3-.4-.4-.7 0-.1 0-.3-.1-.3 0-.3-.1-.5-.2-.8-.2-.7-.6-1.3-1.2-1.8-.5-.3-.7-.3-1.1.1-.1.1-.1.2-.2.3-.3.5-.6 1-.9 1.6-.1.2-.2.3-.2.6-.1.1-.1.3-.2.5-.3.3-.5.8-.7 1.2 0 .1-.1.1 0 .2h.2c.4-.1.8-.2 1.2-.4.6-.3 1.3-.3 1.9-.1.6.2 1 .5 1.5.9.3.2.6.3.9.4h.2v-.1c-.3-.6-.4-1.1-.7-1.6z"/></svg>', - odata: - '<svg viewBox="0 0 32 32"><path d="M22.5 7.1h-13C8.1 7.1 7 8.2 7 9.6v12.8c0 1.4 1.1 2.5 2.5 2.5h12.9c1.4 0 2.5-1.1 2.5-2.5V9.6c.1-1.4-1-2.5-2.4-2.5zM11.9 22.9c-1.4 0-2.6-1.2-2.6-2.6s1.2-2.6 2.6-2.6 2.6 1.2 2.6 2.6-1.1 2.6-2.6 2.6zm3.9-6.5H9.4v-1.7h6.3v1.7zm0-2.5H9.4v-1.7h6.3v1.7zm0-2.5H9.4V9.8h6.3v1.6zm6.8 7.3h-6.3V17h6.3v1.7zm0-2.4h-6.3v-1.7h6.3v1.7zm0-2.5h-6.3v-1.7h6.3v1.7zm0-2.4h-6.3V9.7h6.3v1.7z"/></svg>', - perl: '<svg viewBox="0 0 32 32"><path d="M13.4 26h-1.5c.1-.3.1-.7.2-.8 1-.4.7-1.2.7-2V17c-1-.2-2-.1-2.7-.5-2.2-1.4-2.8-3.7-1.8-6.1.3-.7.2-1.2-.7-1.3-.2 0-.5-.1-.8-.2v-.2c.6-.3 1.1-.7 1.7-1 .2-.1.6 0 .8-.2 1.6-.8 1.9-.7 2.8.9.5 1 .4 1.9-.1 2.9-.3.5-.7 1.2.1 1.5 2-2.8 3.7-5.7 7.2-6.8h.7c.5.7 1.2 1.2 1.6 2 1.1 1.8 1.9 3.7 3 5.4.8 1.2.7 3.6-.3 4.4v-3.5h-.4c-.9 1.3-.4 2.8-.4 4.3 0 2.5-.1 5-.1 7.4h-.7c0-.3-.1-.5 0-.8.4-3.1 0-6.2-1.1-9.2-.9.8-1.3 1.8-1.4 3-.1.9-.4 1.8-.7 2.7-.3.8-1.1 1.5-.1 2.3.1.1-.1.6-.1 1.1-.4-.5-.6-.8-.8-1v.3c-.7.2-1.5.3-2.2.5 0-.1-.1-.3-.1-.4.2-.1.4-.2.6-.4 1-.6 1.1-1.2.3-1.9-1.3-1-1.7-2.2-1.1-3.7.2-.4.1-.9.2-1.7-.7.4-1.3.6-1.4.9-.4 1.5-.6 3.1-.8 4.6-.3 1.4-.4 2.5-.6 3.7zm4.6-3.8c1.4-1.8 1.6-3.8.6-5.2-.6 1.2-1.2 2.4-1.8 3.7l1.2 1.5z"/></svg>', - php: '<svg viewBox="0 0 32 32"><path d="M12.7 19.7c-.1-.6-.4-1.1-1-1.3-.2-.1-.5-.3-.7-.4-.3-.1-.6-.2-.8-.3-.2-.1-.4 0-.6.2-.1.2 0 .4.1.5.1.2.2.3.4.5.2.3.4.5.7.8.2.3.4.5.3.9-.1.7-.4 1.4-.9 1.9-.1.1-.2.1-.2.1-.3 0-.7-.2-.9-.4-.3-.3-.2-.6.1-.8.1 0 .2-.1.2-.2.2-.2.3-.4.2-.7-.1-.1-.1-.2-.2-.3-.4-.4-.9-.8-1.4-1.2-1.3-1-1.9-2.2-2-3.6-.1-1.6.3-3.1 1.1-4.5.3-.5.7-1 1.3-1.3.4-.2.8-.3 1.2-.4 1.1-.3 2.3-.5 3.5-.3 1 .2 1.8.7 2.1 1.7.2.7.3 1.3.2 2-.1 1.4-1.2 2.6-2.5 3-.6.2-.9.1-1.2-.4-.2-.3-.5-.7-.7-1.1V14c0-.1-.1-.1-.1-.2.1.6.2 1.2.5 1.7.2.3.4.5.8.5 1.3.1 2.3-.3 3.1-1.3.8-1.1 1-2.4.8-3.8 0-.3-.1-.5-.2-.8 0-.2 0-.3.2-.4.1 0 .2 0 .2-.1 1-.2 2.1-.3 3.1-.2 1.2.1 2.3.4 3.3 1.1 1.6 1 2.6 2.5 3.1 4.3.1.3.1.5.1.8 0 .2-.1.2-.3.1-.2-.1-.3-.3-.4-.4-.1-.1-.2-.3-.3-.4-.1-.1-.2-.1-.2 0s-.1.2-.1.3c-.3 1-.7 1.9-1.4 2.6-.1.1-.2.3-.2.4 0 .4-.1.8 0 1.2.1.8.2 1.7.3 2.5.1.5-.1.7-.5.9-.3.1-.6.2-1 .2h-1.6c0-.6 0-1.2-.5-1.5.1-.4.2-.8.3-1.3.1-.4 0-.7-.2-1-.2-.3-.5-.3-.8-.2-.8.5-1.6.5-2.5.2-.4-.1-.7-.1-.9.3-.2.4-.3.8-.3 1.2 0 .5.1 1.1.2 1.6 0 .3 0 .4-.3.5-.7.2-1.4.2-2 .1h-.1c0-.6 0-1.2-.7-1.5.4-.4.4-1.1.3-1.7zm-4.1-2.3c.1-.1.2-.2.2-.4.1-.3-.2-.8-.5-.9-.2-.1-.3 0-.4.1-.3.3-.5.6-.8.9 0 .1-.1.1-.1.2-.1.2 0 .4.2.4.1 0 .3 0 .4.1.4 0 .7-.1 1-.4zm0-3.3c0-.2-.2-.4-.4-.4s-.5.2-.4.5c0 .2.2.4.5.4.1-.1.3-.3.3-.5z"/></svg>', - pipeline: - '<svg viewBox="0 0 32 32"><path d="M19 21.25h-6.1a3.111 3.111 0 00-.322-.75l7.922-7.927A2.883 2.883 0 0022 13a3 3 0 10-2.9-3.75h-6.2a3 3 0 100 1.5h6.2a3.111 3.111 0 00.322.75l-7.919 7.927a2.883 2.883 0 00-1.5-.427 3 3 0 102.897 3.75H19V25h5.99v-6H19zm-8.99-9.75a1.5 1.5 0 111.059-.439 1.5 1.5 0 01-1.062.439zm11.986-3A1.5 1.5 0 1120.5 10a1.5 1.5 0 011.493-1.5zm-11.986 15a1.5 1.5 0 111.5-1.5 1.5 1.5 0 01-1.503 1.5zm10.488-3h3v3h-3z"/></svg>', - pddl: '<svg viewBox="0 0 32 32"><g><path d="M7.39 27.464H4.968q-.56-1.15-1.016-2.368-.455-1.218-.785-2.618-.31-1.309-.488-2.902-.172-1.593-.172-3.312 0-1.878.178-3.403.185-1.525.475-2.789.317-1.377.772-2.595.462-1.23 1.036-2.413H7.39v.33q-.535.831-1.023 1.89-.482 1.047-.897 2.458-.396 1.355-.647 3.005-.244 1.65-.244 3.517 0 1.946.237 3.528.244 1.582.654 2.994.395 1.343.89 2.435.502 1.104 1.03 1.913zm21.78-11.2q0 1.719-.179 3.312-.171 1.582-.482 2.902-.33 1.4-.785 2.618t-1.016 2.368h-2.421v-.33q.528-.809 1.03-1.901.5-1.093.89-2.447.409-1.412.646-2.994.245-1.582.245-3.528 0-1.867-.251-3.517-.244-1.65-.64-3.005-.416-1.411-.904-2.458-.482-1.059-1.016-1.89v-.33h2.421q.574 1.184 1.03 2.413.461 1.218.778 2.595.29 1.264.469 2.789.184 1.525.184 3.403z"/><path d="M9.29 14.05q-.894 0-1.49-.622-.595-.636-.595-1.562 0-.953.607-1.561.618-.61 1.534-.61.928 0 1.512.623.596.609.596 1.548 0 .966-.607 1.575-.596.609-1.558.609zm0 9.686q-.894 0-1.49-.635-.595-.635-.595-1.561 0-.953.607-1.562.618-.609 1.534-.609.928 0 1.512.622.596.609.596 1.549 0 .966-.607 1.588-.596.608-1.558.608zm14.51-.331h-3.424V21.46h-.046q-1.18 2.276-3.493 2.276-1.707 0-2.692-1.111-.973-1.125-.973-2.991 0-3.943 4.043-4.552l3.184-.49q0-2.223-2.085-2.223-2.096 0-3.985 1.442v-3.15q.756-.449 2.061-.793 1.317-.344 2.394-.344 5.017 0 5.017 5.783zM20.4 17.9v-.913l-2.13.318q-1.764.265-1.764 1.84 0 .714.424 1.177.435.45 1.168.45 1.02 0 1.66-.807.642-.82.642-2.065z"/></g></svg>', - plan: '<svg viewBox="0 0 32 32"><path d="M4.178 4.956h17.37v6.45H4.178zm7.145 8.538h17.37v6.45h-17.37zm10.334 8.539h7.036v6.45h-7.036z"/></svg>', - happenings: - '<svg viewBox="0 0 32 32"><g><g transform="translate(.147 -44.7)"><path d="M11.213 48.85h17.37v6.45h-17.37z"/><ellipse cx="5.717" cy="52.075" rx="2.638" ry="2.785"/></g><g transform="translate(.22 -35.905)"><path d="M11.213 48.85h17.37v6.45h-17.37z"/><ellipse cx="5.717" cy="52.075" rx="2.638" ry="2.785"/></g><g transform="translate(.22 -27.11)"><path d="M11.213 48.85h17.37v6.45h-17.37z"/><ellipse cx="5.717" cy="52.075" rx="2.638" ry="2.785"/></g></g></svg>', - powershell: - '<svg viewBox="0 0 32 32"><path d="M7.205 19.83l7.286-3.933-7.27-4.419.008-4.668 12.29 7.931-.005 2.685-12.317 7.041.008-4.636zm18.594 5.205H15.137v-2.662h10.662v2.662z"/></svg>', - prisma: - '<svg viewBox="0 0 32 32"><path fill-rule="evenodd" d="M23.208 22.209l-9.76 2.812c-.299.086-.584-.165-.522-.458l3.487-16.27c.065-.304.497-.352.633-.07l6.456 13.356a.451.451 0 01-.294.63zm1.674-.663L17.407 6.08a1.2 1.2 0 00-1.023-.666 1.195 1.195 0 00-1.092.552L7.185 18.759a1.17 1.17 0 00.014 1.284l3.963 5.982c.236.357.645.563 1.07.563a1.3 1.3 0 00.362-.05l11.504-3.315c.352-.102.64-.345.791-.667.15-.322.148-.69-.007-1.01z" clip-rule="evenodd"/></svg>', - pug: '<svg viewBox="0 0 1200 1000"><path d="M715.8 310.8h-.1c0 .1-.1.1-.1.2h.2v-.2zm-75 196.8c-5.8-2.7-10.9-5.6-14.9-11.6-5.3-8-18.2-11.9-30.5-11.1-12.3-.7-25.2 3.2-30.5 11.1-4 6-9.1 8.9-14.9 11.6-41.5 19.2-67.1 61.6-65.3 107.4-.7.6 6.3 61.6 17.2 69.9 4.3 2.2 55.2 14.9 93.5 14.9s91.6-12.8 95.9-14.9c10.9-8.3 15.6-69.4 14.9-69.9 1.7-45.8-23.8-88.2-65.4-107.4zm257-122.2c-18.7-17.9-36-37.8-57.6-51.8-26.7-17.3-58.2-20.5-89.4-22.4-3.3 5.2.7 8.4 3.5 11.6 4.7 5.4 10 10.2 14.9 15.4 27.9 28.6 48.4 61.3 55.4 101.3.8 4.5 12 91.8 14.7 94.1 5 15 9.1 15.9 19.9 4.6 2.9-3 19.2-45 31.1-60.2 11.9-15.2 45.2-37 47.1-42.1 1.6-5-25.6-37.1-39.6-50.5zm-472-62.6c2.8-3.2 6.8-6.4 3.5-11.6-31.2 2-62.7 5.1-89.4 22.4-21.7 14-38.9 33.9-57.6 51.8-14 13.4-41.3 45.4-39.4 50.5 1.9 5.1 35.2 26.9 47.1 42.1 11.9 15.2 28.2 57.2 31.1 60.2 10.7 11.3 14.9 10.3 19.9-4.6 2.7-2.3 13.9-89.6 14.7-94.1 7-40 27.5-72.7 55.4-101.3 4.7-5.2 10-10 14.7-15.4zm378.4 211.1v-.3c0 .1-.1.1-.1.2s.1.1.1.1z"/><path d="M734.1 338.3c-4.9-5.2-10.2-10.3-14.9-15.7-2.8-3.2-6.7-6.2-3.6-11.6-27.7-2.8-55.2-7.7-83.2-9.6-51.3-3.5-101.9-.2-152.2 9.7-5 1-9.7 2.7-14.6.2 0 .7-.1 1.3-.2 1.9 1.2 4-2.1 6.7-4.5 9.5-4.7 5.4-10 10.2-14.9 15.4-27.9 28.6-48.4 61.3-55.4 101.3-.3 1.6-2 14.6-4.2 30.4 0 1.5-.1 3-.2 4.3l-.3-.6c-2.5 18.3-5 52.1-3.7 60.3 1.8 11.6 3.1 23.4 10.9 33.1 6.9 13.4 20.4 23 23.2 38.8 5.3 30.6 23.8 48.1 50.2 57.7-10.3-18.8-14.8-69-14-69.5-2.3-49.5 30.2-95.3 83.1-116 7.4-2.9 13.9-6.1 19-12.6 6.8-8.6 23.1-12.8 38.8-12 15.7-.8 32 3.4 38.8 12 5.1 6.5 11.6 9.7 19 12.6 52.9 20.7 85.4 66.5 83.1 116 .7.5-3.5 48.4-13.3 68.1 23.2-9.9 39.9-26 44.9-51.8 1.9-9.8 5.5-18.5 11.7-26.3 3.4-4.3 7.7-8.2 8-14.2 4.9-2.5 6.5-7.3 8.2-11.9 3.1-8.2 4.5-17.3 10.4-24.2-2.8-4.7-13.8-89.7-14.6-94.1-7.1-39.8-27.6-72.6-55.5-101.2zm-297.7 46.1c-.5-.5-1-1-1.5-1.3 1.1.1 1.5.6 1.5 1.3zm27.9 105c-24.1 0-43.6-19.5-43.6-43.6s19.5-43.6 43.6-43.6 43.6 19.5 43.6 43.6-19.5 43.6-43.6 43.6zm223.2-17.2s.1 0 .2-.1c0 .1 0 .1.1.2-.1 0-.2-.1-.3-.1zm38.3 17.2c-24.1 0-43.6-19.5-43.6-43.6s19.5-43.6 43.6-43.6 43.6 19.5 43.6 43.6-19.5 43.6-43.6 43.6zm46.3-26.6c0-.6-.1-1-.2-1.4.1-1 .1-1.9.2-2.9.2 1.5.4 2.9 0 4.3zm.3-10.2c-.2.4-.3.7-.4 1.1v-.9c.3-.3.5-.4.4-.2z"/></svg>', - puppet: - '<svg viewBox="0 0 32 32"><path d="M7.239 2.865h7.972c.004 2.03-.007 4.06.005 6.09 1.088 1.071 2.16 2.16 3.244 3.235l.034.015c2.02.006 4.04 0 6.06.003l-.001 7.971h-6.014c-.103-.008-.154.103-.224.16-1.034 1.03-2.06 2.068-3.099 3.094-.012 2.029-.001 4.06-.005 6.089H7.239V21.55c2.033-.002 4.066.003 6.099-.002 1.083-1.09 2.172-2.174 3.258-3.26v-4.186c-1.086-1.09-2.176-2.176-3.262-3.265H7.239V2.866z"/><path d="M9.91 5.536h2.643v2.642H9.91V5.536zm0 18.686h2.643v2.642H9.91v-2.642z"/></svg>', - purescript: - '<svg fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" clip-rule="evenodd" viewBox="0 0 32 32"><path fill-rule="nonzero" d="M18.786 19.079h-7.217l1.644 1.535h7.218l-1.645-1.535zm-7.217-2.312h7.217l1.644-1.534h-7.218l-1.643 1.534zm7.217-5.381h-7.217l1.643 1.535h7.218l-1.644-1.535zm-7.977 3.054l-1.086-1.086-4.026 4.026a.766.766 0 000 1.086l4.026 4.027 1.086-1.086-3.483-3.487 3.483-3.48zm15.493-.906l-4.025-4.027-1.085 1.086 3.481 3.487-3.481 3.483 1.085 1.086 4.025-4.025a.77.77 0 000-1.09"/></svg>', - python: - '<svg viewBox="0 0 32 32"><path d="M15.6 15.5h-2c-1.4 0-2.3.9-2.3 2.3v1.8c0 .2-.1.3-.3.3h-.9c-.9 0-1.6-.4-2-1.2-.3-.6-.5-1.2-.5-1.8-.1-1.1-.1-2.2.3-3.3.3-.9.9-1.6 1.9-1.8h5.8c.1 0 .3 0 .3-.1v-.5s-.2-.1-.3-.1h-3.4c-.3 0-.4-.1-.4-.4V9.4c0-.7.3-1.2.9-1.4.5-.2 1-.4 1.5-.5 1.2-.2 2.4-.2 3.6.1.5.1 1 .3 1.4.6.4.4.7.8.6 1.4v3.6c0 1.4-.8 2.2-2.2 2.2-.7.1-1.4.1-2 .1zm-2.8-6c0 .4.3.8.8.8.4 0 .8-.4.8-.8s-.4-.7-.8-.8c-.5 0-.8.4-.8.8zm3.6 7h2c1.4 0 2.3-.9 2.3-2.3v-1.8c0-.2.1-.3.3-.3h.9c.9 0 1.6.4 2 1.2.3.6.5 1.2.5 1.8.1 1.1.1 2.2-.3 3.3-.3.9-.9 1.6-1.9 1.8h-5.8c-.1 0-.3 0-.3.1v.5s.2.1.3.1h3.4c.3 0 .4.1.4.4v1.3c0 .7-.3 1.2-.9 1.4-.5.2-1 .4-1.5.5-1.2.2-2.4.2-3.6-.1-.5-.1-1-.3-1.4-.6-.4-.4-.7-.8-.6-1.4v-3.6c0-1.4.8-2.2 2.2-2.2.7-.1 1.4-.1 2-.1zm2.8 6c0-.4-.3-.8-.8-.8-.4 0-.8.4-.8.8s.4.7.8.8c.5 0 .8-.4.8-.8z"/></svg>', - react: - '<svg viewBox="0 0 32 32"><path d="M22 19.4c.1 1.1.2 2.1.2 3.2 0 1.3-.7 2.2-1.7 2.3-.5.1-1.1 0-1.6-.2-1-.5-1.9-1.2-2.9-1.8-.5.4-1 .8-1.6 1.2-.3.2-.7.4-1 .5-1.8.8-3.3-.1-3.4-2.1 0-1 .1-2.1.2-3.2-.6-.2-1.2-.4-1.8-.8-.6-.3-1.1-.7-1.6-1.2-.9-.9-.8-2 .1-2.9.8-.9 1.9-1.3 3-1.7.1 0 .3-.1.4-.1-.1-.7-.2-1.5-.3-2.2 0-.6.1-1.3.2-1.9.3-1.1 1.3-1.6 2.5-1.3 1.2.3 2.1 1 2.9 1.7.2.1.3.3.4.4.8-.6 1.6-1.2 2.5-1.7.6-.4 1.3-.6 2-.4 1 .2 1.6 1.1 1.7 2.4v1.6c0 .5-.2 1-.3 1.6.6.2 1.1.4 1.7.7.8.4 1.6.8 2.1 1.6.5.7.5 1.5 0 2.2-.5.8-1.3 1.2-2.1 1.6-.6.1-1.1.3-1.6.5zm-5.8-.1c.3 0 .8-.1 1.2-.1.3 0 .5-.1.7-.4.5-.8 1-1.6 1.4-2.5.1-.2.1-.5 0-.6-.5-.9-1-1.7-1.5-2.5-.1-.2-.3-.3-.5-.3-.9 0-1.7 0-2.6-.1-.5 0-.9.2-1.2.7-.2.3-.4.6-.6 1-1.1 2-1.1 1.2 0 3.2 1.2 1.9.6 1.5 3.1 1.6zm-5.8-.8c.3-.8.6-1.6.9-2.3v-.4c-.3-.8-.6-1.5-.9-2.3-1 .3-2 .7-2.8 1.3-.9.7-.9 1.6 0 2.3.8.8 1.8 1.1 2.8 1.4zm11.3-5.1c-.4.9-.7 1.7-1 2.5 0 .1-.1.2 0 .2.3.8.6 1.6 1 2.6.9-.5 1.9-.9 2.7-1.4 1.1-.7 1.1-1.7 0-2.4-.8-.7-1.8-1-2.7-1.5zm-10.7-1c.9-.1 1.7-.2 2.5-.4.1 0 .2-.1.2-.1.5-.7 1-1.3 1.6-2-.8-.7-1.6-1.4-2.6-1.8-1.1-.4-1.8 0-2 1.2-.1 1 .1 2 .3 3.1zm10 0c0-.1.1-.3.1-.4.2-1 .4-2.1 0-3.1-.2-.7-.7-1-1.3-.9-1.3.2-2.2 1.1-3.1 1.9.5.7 1 1.3 1.5 1.9l.3.3c.8.1 1.6.2 2.5.3zm-10 7.2c-.2 1.1-.5 2.1-.2 3.2.2 1 .9 1.4 1.9 1.1 1.1-.3 1.9-1.1 2.7-1.8-.5-.7-1-1.3-1.6-2-.1-.1-.2-.2-.3-.2-.8 0-1.6-.1-2.5-.3zm5.6 2.5c.6.8 1.8 1.6 2.6 1.9 1 .3 1.7 0 1.9-1.1.2-1.1 0-2.1-.2-3.2-.9.1-1.8.1-2.6.4-.6.3-.9 1-1.3 1.5-.1.2-.2.3-.4.5zm.6-10.2c-.4-.5-.8-.9-1.2-1.4-.4.5-.7.9-1.2 1.4h2.4zm0 8.2h-2.3c.4.5.8.9 1.2 1.4.3-.5.7-.9 1.1-1.4zm-4.1-1c-.4-.7-.8-1.3-1.2-2.1-.2.6-.4 1.1-.6 1.7.5.2 1.1.3 1.8.4zm7-2.1l-1.2 2.1c.7-.1 1.2-.2 1.8-.3-.1-.6-.3-1.1-.6-1.8zm-8.2-2l1.2-2.1c-.7.1-1.2.2-1.8.3.2.7.3 1.2.6 1.8zm7-2.1c.2.4.4.7.6 1 .2.3.4.6.6 1 .2-.6.4-1.2.6-1.7-.6 0-1.1-.1-1.8-.3z"/></svg>', - reasonml: - '<svg viewBox="0 0 32 32"><path fill-rule="evenodd" d="M6 6h20v20H6zm7.002 12.177v2.349h1.453c.808 0 1.278-.415 1.278-1.191 0-.754-.47-1.158-1.278-1.158zm5.911-1.595h6.042v1.595h-4.043v1.431h3.649v1.584l-3.649.011v1.443h4.152v1.595h-6.151zm-1.049 7.659h-2.262l-1.114-2.12h-1.486v2.12h-2v-7.659h3.442c2.032 0 3.19.983 3.19 2.687 0 1.159-.48 2.011-1.365 2.47z"/></svg>', - rescript: - '<svg viewBox="0 0 32 32"><path d="M25.3 11.1c0 2.1-1.7 3.9-3.9 3.9s-3.9-1.7-3.9-3.9 1.7-3.9 3.9-3.9c2.1 0 3.9 1.7 3.9 3.9zm-10.8-4v14.3c0 1 0 1.5-.2 2s-.7 1-1.2 1.2c-.4.2-.9.2-2 .2-1 0-1.5 0-2-.2s-1-.7-1.2-1.2c-.2-.4-.2-.9-.2-2V10.6c0-1.2 0-1.9.2-2.3s.6-.8 1-1c.5-.2 1.1-.2 2.3-.2h3.3z"/></svg>', - R: '<svg preserveAspectRatio="xMidYMid" viewBox="0 0 32 32"><defs><linearGradient id="a" x1="7.1" x2="25" y1="10.197" y2="22.185" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#CBCED0"/><stop offset="1" stop-color="#84838B"/></linearGradient><linearGradient id="b" x1="14.475" x2="24.355" y1="13.919" y2="24" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#276DC3"/><stop offset="1" stop-color="#165CAA"/></linearGradient></defs><g fill-rule="evenodd"><path d="M16.05 22.185c-4.943 0-8.95-2.684-8.95-5.994s4.007-5.994 8.95-5.994S25 12.88 25 16.19s-4.007 5.994-8.95 5.994zm1.37-9.645c-3.757 0-6.803 1.835-6.803 4.098s3.046 4.098 6.803 4.098 6.53-1.254 6.53-4.098-2.773-4.098-6.53-4.098z" transform="translate(-.05 -1.098)"/><path d="M20.73 19.48s.542.163.856.323c.109.055.298.166.434.3s.199.285.199.285l2.135 3.599-3.45.002-1.614-3.03s-.33-.568-.534-.732c-.17-.137-.242-.186-.4-.186h-.82v3.957l-3.053.001v-10.08h6.13s2.793.05 2.793 2.707-2.67 2.855-2.67 2.855zm-1.328-3.375l-1.848-.001-.001 1.714 1.849-.001s.856-.003.856-.872c0-.887-.856-.84-.856-.84z" transform="translate(-.05 -1.098)"/></g></svg>', - ruby: '<svg viewBox="0 0 32 32"><path d="M17.8 7.5h4.1c.1 0 .2.1.3.1 1.2.3 2 1 2.2 2.2 0 .2.1.4.1.6v.8c0 .2-.1.4-.1.6-.1 1.4-.2 2.9-.3 4.3-.2 2.4-.4 4.7-.5 7.1 0 .4-.1.5-.5.5-1.1.1-2.1.1-3.2.2-2.2.1-4.4.3-6.6.4-.6 0-1.2.1-1.8.2h-1c-.1 0-.2-.1-.3-.1-1.2-.2-2.1-.9-2.4-2.1-.1-.3-.1-.6-.2-.9v-.5c0-.1.1-.2.1-.4 0-.8.1-1.7.1-2.5 0-.5 0-.9.1-1.3.7-1.8 1.5-3.5 2.9-4.9 1.7-1.8 3.6-3.2 6-3.8.3-.2.6-.3 1-.5z"/></svg>', - html_erb: - '<svg viewBox="0 0 32 32"><path d="M7.5 14.9L13.9 9v2.8L9.1 16l4.8 4.2V23l-6.4-5.9v-2.2zm17 2.3l-6.4 5.9v-2.8l4.9-4.2V16l-4.9-4.2V8.9l6.4 5.9v2.4z"/></svg>', - rust: '<svg viewBox="0 0 32 32"><path d="M21.7 8.4V9l.1.1h.1c.3-.1.6-.1.9-.2.2-.1.4.1.3.3-.1.3-.1.6-.2.9v.1l.1.1c0 .1.1.1.2.1h.9c.2 0 .3.1.3.3v.2c-.1.3-.3.6-.4.8v.1s.1.1.1.2h.1c.3.1.6.1.9.2.2 0 .3.3.2.5-.2.3-.4.5-.5.7v.2c0 .1.1.1.2.2.3.1.5.2.8.3.2.1.3.3.1.5-.2.2-.4.4-.7.6v.3s.1.1.2.1c.2.1.4.3.7.4.2.1.2.4 0 .5-.3.2-.5.3-.8.5v.1c0 .2 0 .2.1.3.2.2.4.4.6.5.2.2.1.4-.1.5-.3.1-.6.2-.8.3 0 0-.1 0-.1.1-.1.1 0 .2 0 .3.2.2.3.4.5.7.1.1.1.3-.1.4-.1 0-.1 0-.2.1-.3 0-.5.1-.8.1h-.1c0 .1-.1.1-.1.2s0 .1.1.2c.1.2.2.5.3.7.1.1 0 .3-.1.4h-1.2c-.1.1-.1.2-.1.3.1.3.1.5.2.8.1.2-.1.4-.4.4-.3-.1-.6-.1-.9-.2H22l-.1.1s-.1.1 0 .1v.9c0 .2-.1.3-.3.3h-.2c-.3-.1-.5-.2-.8-.4h-.1c-.1 0-.2.1-.2.2 0 .3-.1.5-.1.8 0 .2-.3.3-.5.2-.2-.2-.5-.4-.7-.5h-.1c-.1 0-.2.1-.2.2-.1.3-.2.5-.3.8-.1.2-.2.2-.3.2-.1 0-.1-.1-.1-.1-.2-.2-.4-.4-.6-.7h-.2c-.1 0-.2.1-.2.2-.1.2-.3.5-.4.7-.1.2-.4.2-.5 0-.2-.3-.3-.5-.5-.8h-.2c-.1 0-.1 0-.2.1l-.6.6c-.1.1-.2.1-.4.1-.1 0-.1-.1-.1-.2l-.3-.9s0-.1-.1-.1h-.3c-.2.2-.4.3-.7.5-.4-.2-.7-.3-.7-.5-.1-.3-.1-.6-.1-.9 0 0 0-.1-.1-.1s-.1-.1-.2-.1-.1 0-.2.1c-.2.1-.5.2-.7.3-.2.1-.4 0-.4-.2V23l-.1-.1h-.1c-.3.1-.6.1-.9.2-.2.1-.4-.1-.3-.3.1-.3.1-.6.2-.9v-.1l-.1-.1H8c-.2 0-.3-.1-.3-.3v-.2c.1-.3.3-.6.4-.8v-.1s0-.1-.1-.1c0-.1-.1-.1-.1-.1-.3 0-.6-.1-.9-.1-.2 0-.3-.3-.2-.5.2-.2.4-.5.5-.7v-.1c0-.1 0-.1-.1-.2 0 0-.1-.1-.2-.1-.2-.1-.5-.2-.7-.3-.2-.1-.3-.3-.1-.5.3-.1.5-.4.8-.6v-.2c0-.1 0-.2-.1-.2-.2-.1-.5-.3-.7-.4-.2-.1-.2-.4 0-.5.3-.2.5-.3.8-.5V15l-.1-.1-.6-.6c-.1-.1-.1-.3 0-.4 0 0 .1 0 .1-.1l.9-.3v-.1c.1-.1 0-.2 0-.3-.2-.2-.3-.4-.5-.6-.1-.2 0-.5.2-.5.3-.1.6-.1.9-.2H8c0-.1.1-.1.1-.2s0-.1-.1-.2c-.1-.2-.2-.5-.3-.7-.1-.2 0-.4.2-.4H9s0-.1.1-.1v-.1c-.1-.3-.2-.6-.2-.9-.1-.2.1-.4.3-.3.3 0 .6.1.9.2h.1l.1-.1s.1-.1 0-.1V8c0-.2.1-.3.3-.3h.2c.3.1.6.3.8.4h.1s.1 0 .1-.1c.1 0 .1-.1.1-.1 0-.3.1-.6.1-.9 0-.2.3-.3.5-.2.2.2.5.4.7.5h.1c.1 0 .1 0 .2-.1 0 0 0-.1.1-.2.1-.2.2-.5.3-.7.1-.2.2-.2.4-.2l.1.1c.1.3.4.5.6.8h.1c.1 0 .2-.1.2-.1.1-.2.3-.5.4-.7.2-.2.4-.2.5-.1l.1.1c.2.3.3.5.5.8h.3c.1 0 .1-.1.1-.1.2-.2.4-.4.5-.6.1-.1.3-.1.4 0v.1c.1.3.2.6.3.8l.1.1h.2c.3-.1.6-.3.8-.5.2-.1.5 0 .5.2 0 .3.1.6.1.9 0 0 0 .1.1.1h.1c.1.1.2.1.2 0 .2-.1.5-.2.8-.3.2-.1.4 0 .4.3v.4zm-11.1 2.7h7.6c.3 0 .6 0 .9.1.6.2 1.1.5 1.4.9.3.3.5.7.5 1.2 0 .4-.1.8-.3 1.2-.2.3-.5.6-.8.8-.1.1-.2.2-.3.2.1.1.2.1.3.2.2.2.5.4.6.7.2.3.3.7.3 1 0 .1.1.2.2.3.2.2.5.2.8.2.2 0 .4-.1.5-.2.2-.2.2-.4.3-.6v-.5c0-.1 0-.1.1-.1h.7v-1.3c-.3-.1-.6-.3-.9-.4-.1-.1-.3-.1-.4-.2-.3-.1-.4-.4-.3-.8.2-.5.4-1 .7-1.5v-.1c-.4-.6-.8-1.2-1.4-1.7-1-.9-2.2-1.5-3.6-1.8h-.1c-.3.3-.6.6-1 .9-.2.2-.6.2-.8 0l-.9-.9h-.1c-.4.1-.7.2-1 .3-1.1.4-2 1-2.8 1.8-.1.1-.2.2-.2.3zm11.3 9.2h-3c-.2 0-.3 0-.4-.1-.4-.2-.6-.6-.7-1-.1-.4-.2-.7-.2-1.1 0-.2-.1-.4-.2-.6-.2-.5-.6-.8-1.1-.8h-1.8V18h1.8c.1 0 .1 0 .1.1v2c0 .1 0 .1-.1.1h-6c.2.3.4.5.6.7h.1c.4-.1.8-.2 1.2-.2.3-.1.6.1.7.4.1.4.2.9.3 1.3v.1c.8.3 1.6.6 2.4.6.7.1 1.4 0 2.1-.1.5-.1 1-.3 1.5-.5v-.1c.1-.4.2-.9.3-1.3.1-.3.3-.5.7-.4l1.2.3h.1c0-.2.2-.5.4-.7zm-11.9-7l.3.6c0 .1.1.2 0 .3 0 .2-.2.3-.3.4-.4.2-.8.4-1.2.5 0 0-.1 0-.1.1v.5c0 .7.1 1.4.3 2.2 0 0 0 .1.1.1h2.1v-4.7H10zm4.3 1.4c.1 0 .1 0 0 0h2.3c.2 0 .4 0 .6-.1.1-.1.2-.1.3-.3.1-.2.1-.5-.1-.7-.2-.2-.5-.3-.7-.3h-2.5c.1.5.1.9.1 1.4zm-6-1c0 .3.3.6.6.6s.6-.3.6-.6-.3-.6-.6-.6-.6.3-.6.6zM21 22.1c0-.3-.3-.6-.6-.6s-.6.3-.6.6.3.6.6.6.6-.2.6-.6zm-9.4-.6c-.3 0-.6.3-.6.6s.3.6.6.6.6-.3.6-.6-.3-.6-.6-.6zm5-13.1c0-.3-.2-.6-.6-.6-.3 0-.6.2-.6.6 0 .3.2.6.6.6.3 0 .5-.3.6-.6zm6.5 6c.3 0 .6-.3.6-.6s-.3-.6-.6-.6-.6.3-.6.6.2.6.6.6z"/></svg>', - sass: '<svg viewBox="0 0 32 32"><path d="M18 17.3c-1.1.7-2.4 1.5-3.5 2.2.4.9.4 1.8.1 2.7-.5 1.6-1.7 2.5-3.2 2.7-.4.1-.8 0-1.1-.1-.4-.1-.6-.4-.7-.7-.4-.9-.3-1.7.3-2.4.4-.4.8-.9 1.3-1.2.5-.4 1.2-.7 1.8-1.1.1-.1.2-.1.4-.2-.3-.2-.4-.4-.6-.4-.8-.5-1.6-1.1-2.3-1.8-.4-.4-.8-.8-1.1-1.3-.9-.7-1-1.7-.5-2.6.4-1 1.1-1.8 1.8-2.5 1.6-1.4 3.4-2.4 5.4-3.1 1.4-.5 2.8-.7 4.2-.5.4.2 1 .3 1.4.5 1.5.6 2.1 1.8 1.6 3.4-.4 1.3-1.2 2.4-2.4 3.1-1.6 1-3.2 1.4-5.1 1.1-.6-.1-1.1-.4-1.6-.9-.1-.2-.2-.4-.3-.5 0 0 0-.1.1-.2 0 0 .1 0 .2.1.8.8 1.7.9 2.6.7 1.7-.3 3.2-.9 4.3-2.2.4-.5.8-1.1 1-1.8.2-.8-.2-1.4-.9-1.8-.8-.4-1.6-.4-2.4-.3-2 .3-3.8 1.1-5.4 2.1-.9.5-1.7 1.1-2.3 1.9-.3.4-.5.8-.7 1.2-.3.8-.2 1.6.4 2.2.4.4.8.8 1.2 1.1.6.5 1.3 1.1 1.9 1.6.1 0 .2.1.3 0 .3-.2.5-.3.8-.4.9-.5 1.8-.9 2.8-1.1 0 .4.1.4.2.5 0-.1 0-.1 0 0zm-4.3 2.5c-.9.5-1.6 1-2.3 1.7-.4.4-.6.8-.7 1.3-.1.6.3.9.9.8.8-.2 1.4-.7 1.8-1.3.5-.8.5-1.5.3-2.5z"/></svg>', - spring: - '<svg viewBox="0 0 32 32"><path d="M23.4 8.1c1.1 3 1.9 5.9 1.5 9.1-.3 2.3-1.3 4.2-3.1 5.8-1.8 1.4-3.9 2.2-6.1 2.1C13.2 25 11 24 9.3 22c-1.7-2-2.4-4.2-2.2-6.7.1-1.9.8-3.6 2.1-5C10.6 8.4 12.7 7.4 15 7c2.4-.3 4.6.4 6.5 1.8 1.1.9 1.1.9 1.7-.4.1 0 .1-.1.2-.3zm-.8 5.8c-.5 2.2-1.9 4-3.7 5.5-1.3 1.1-2.9 1.6-4.5 2.2-.4.1-.8.3-1.2.4 0 .1 0 .2.1.3 2.2-.1 4.5 0 6.7-.4 2.7-.4 4-1.9 4.5-4.6.3-1.8.1-3.5-.4-5.3-.3-.9-.5-1.8-.8-2.8-.2.3-.3.4-.4.4-.9 1.4-2.2 2.3-3.7 3-1.3.6-2.9.6-4.3.7-1.3.1-2.5.4-3.5 1.2-1.6 1.2-2.2 3.7-1.3 5.3.5 1 1.1 1.2 2.1 1 .5-.1 1-.3 1.5-.4 3.9-1 7-2.8 8.9-6.5zm-12.1 7.3c-.4 0-.7.4-.7.8s.4.7.8.7.7-.4.7-.8c0-.5-.2-.7-.8-.7z"/></svg>', - slim: '<svg viewBox="0 0 32 32"><path d="M7 22.4V9.6c0-.1.1-.1.1-.2.2-.7.6-1.4 1.3-1.8L9.6 7h12.8c.1 0 .1.1.2.1.9.3 1.6.9 2.1 1.7.1.3.2.5.4.7v12.8c0 .1-.1.1-.1.2-.2.7-.6 1.3-1.3 1.8-.4.3-.8.5-1.3.6H9.6c-.1 0-.1-.1-.2-.1-.9-.3-1.6-.9-2.1-1.7-.1-.1-.2-.4-.3-.7zm2.8-10.5c.9 1.1 1.7 2.2 2.6 3.2.1.1.3.2.4.2h6.4c.1 0 .3-.1.4-.1.9-1.1 1.7-2.2 2.6-3.2-3-3.6-9.1-3.9-12.4-.1z"/><path d="M18.3 10.4c-.4 1.3-.6 2.8-1 4.1h-1.9c1.1-1.4 2-2.8 2.9-4.1z"/></svg>', - smarty: - '<svg viewBox="0 0 32 32"><path d="M16 19.7h-2.1c-.7 0-.8 0-.9-.7-.3-1.5-.8-2.9-1.5-4.2-.4-.7-.7-1.4-1-2.2-.4-1.1-.5-2.2-.3-3.4.2-1.6 1.2-2.8 2.6-3.4 2.2-1 4.5-1 6.7.1 2 .9 2.9 3 2.5 5.3-.2 1.5-.8 2.7-1.5 4-.6 1.2-1.1 2.4-1.3 3.7-.2.9-.2.9-1.1.9-.8-.1-1.5-.1-2.1-.1zm-.1 7.3h-2.4c-.4 0-.6-.1-.6-.6 0-1.3-.2-1.2 1.2-1.2h4.3c.5 0 .6.2.6.6 0 1.1 0 1.1-1.1 1.1-.6.1-1.3.1-2 .1zm.1-3.6h-2.5c-.4 0-.5-.1-.5-.5 0-1.3-.1-1.2 1.1-1.2h4.3c.4 0 .6.2.6.6 0 1.2.1 1.1-1.1 1.1H16z"/></svg>', - sbt: '<svg viewBox="0 0 32 32"><path d="M26 17c0 .5-.1.9-.2 1.4H12.6c-.9 0-1.3.5-1.3 1.3 0 .7.5 1.1 1.4 1.1h12.2c-1.6 3-4.2 4.8-7.6 5.2-5.3.6-10.2-3-11.1-8.1-1-5.3 2.3-10.3 7.4-11.6 4.2-1.1 8.8.8 11 4.5-.2.1-.5.1-.8.1h-6.5c-.7 0-1.2.5-1.2 1.2s.4 1.1 1.1 1.1h8.4c.2.5.3 1 .3 1.5H15c-.9 0-1.4.4-1.4 1.2 0 .7.5 1.1 1.4 1.1h10.1c.3-.1.6-.1.9 0z"/></svg>', - scala: - '<svg viewBox="0 0 32 32"><path d="M21.6 7v4.2c-.1.1-.1.2-.2.2-.3.3-.7.5-1.1.6-.9.3-1.9.5-2.8.7-1.6.3-3.1.5-4.7.7-.8.1-1.6.2-2.4.4V9.6c.1-.1.2-.1.4-.1 1.2-.2 2.5-.4 3.8-.5 1.9-.3 3.8-.5 5.6-1.1.5-.2 1.1-.4 1.4-.9zm0 5.6v4.2l-.2.2c-.5.4-1.1.6-1.6.8-.8.2-1.6.4-2.4.5-1 .2-1.9.3-2.9.5-1.4.2-2.7.3-4.1.6v-4.2c.1-.1.2-.1.3-.1 1.7-.2 3.4-.5 5.1-.7 1.4-.2 2.9-.5 4.3-.9.6-.2 1.1-.4 1.5-.9zM10.5 25h-.1v-4.2c.1-.1.2-.1.3-.1 1.2-.2 2.3-.3 3.5-.5 2-.3 3.9-.5 5.8-1.1.6-.2 1.2-.4 1.6-.9v4.2c-.1.2-.3.3-.5.5-.6.3-1.2.5-1.9.7-1.2.3-2.5.5-3.7.7-1.3.2-2.6.4-3.9.5-.4 0-.7.1-1.1.2z"/></svg>', - ethereum: - '<svg id="Layer_1" viewBox="0 0 32 32"><style>.st1{fill:#231f20}</style><path d="M12.4 16.8l3.6 2.1h.1c1.8-1.1 3.6-2.2 5.5-3.2v-.1c-.5-.9-1-1.7-1.6-2.6-1.3-2.2-2.6-4.3-3.9-6.5-.1.2-.2.3-.3.5-.6 1-1.2 1.9-1.7 2.9-.5.9-1.1 1.8-1.6 2.7-.6 1-1.2 2-1.8 2.9v.1c.4.5 1.1.8 1.7 1.2z" class="st1"/><path d="M16.7 20.6c-.2.1-.5.3-.7.4-.8-.5-1.6-.9-2.4-1.4-.9-.5-1.8-1.1-2.7-1.6-.1-.1-.2-.1-.4-.2.3.4.5.7.8 1.1.7 1 1.4 2 2.2 3 .8 1.2 1.7 2.3 2.5 3.5 0 0 0 .1.1.1 1.2-1.7 2.5-3.5 3.7-5.2.6-.8 1.2-1.7 1.8-2.5-1.7.9-3.3 1.8-4.9 2.8z" class="st1"/></svg>', - stylus: - '<svg viewBox="0 0 32 32"><path d="M25.1 3.2c-.2 0-.5.1-.7.2-.9.3-1.5 1-2.1 1.7-1.2 1.3-2.2 2.8-3 4.4-1.1 1.9-1.9 3.9-2.5 6-.2.8-.4 1.7-.4 2.6 0 .5.4.8.8.7.9-.1 1.4-.8 1.9-1.4v-.3c-.3.3-.6.6-.9.8-.3.2-.5.1-.5-.2v-1c0-1.2.3-2.4.7-3.5.4-1.1.8-2.2 1.3-3.2.7-1.5 1.6-3 2.8-4.2.5-.8 1.2-1.3 2.2-1.4.5 0 .8.1.9.5 0 .1.1.1.1.1s.1-.1.2-.1c.1-.3.2-.6.2-.9 0-.4-.5-.9-1-.8zm-10 10.1c-.7 0-1.8.8-2.1 1.4v.2c.1 0 .1 0 .2-.1s.2-.3.4-.4c.2-.2.4-.4.7-.3.3.1.3.5.2.7-.1 1.2-.3 2.2-.5 3.3-.4 1.5-.9 3-1.6 4.3-.8 1.6-1.7 3-3 4.2-.6.5-1.3 1-2.1 1-.5 0-.7-.1-.8-.6 0-.1-.1-.1-.2-.2-.3.4-.4.8-.3 1.3.1.4.3.7.6.7.4 0 .8-.1 1.1-.2.7-.2 1.2-.8 1.7-1.3 1.2-1.2 2.2-2.6 3-4.1 1.3-2.2 2.3-4.5 3-7 .2-.8.4-1.5.3-2.3 0-.3-.3-.6-.6-.6z"/></svg>', - svelte: - '<svg viewBox="0 0 32 32"><path d="M10.617 10.473L14.809 7.8c2.387-1.52 5.688-.812 7.359 1.58a5.123 5.123 0 01.876 3.876 4.821 4.821 0 01-.72 1.798c.524.998.7 2.142.5 3.251a4.808 4.808 0 01-1.963 3.081l-.21.14-4.192 2.672c-2.386 1.52-5.688.812-7.36-1.58a5.125 5.125 0 01-.875-3.876c.116-.642.36-1.253.72-1.798a5.065 5.065 0 01-.5-3.251 4.81 4.81 0 011.962-3.081l.21-.14L14.81 7.8l-4.192 2.672zm9.825.008a3.33 3.33 0 00-3.573-1.324c-.226.06-.444.146-.65.256l-.202.118-4.192 2.671a2.891 2.891 0 00-1.306 1.937 3.081 3.081 0 00.526 2.33 3.33 3.33 0 003.574 1.326c.226-.06.444-.147.65-.256l.201-.118 1.6-1.02a.923.923 0 01.257-.113c.407-.105.837.054 1.077.4a.931.931 0 01.158.702.873.873 0 01-.295.512l-.099.072-4.192 2.671a.923.923 0 01-.257.113 1.003 1.003 0 01-1.076-.4.94.94 0 01-.171-.49l.002-.132.014-.156-.156-.047a5.407 5.407 0 01-1.387-.645l-.252-.174-.215-.158-.08.24a2.923 2.923 0 00-.1.392 3.082 3.082 0 00.527 2.33 3.33 3.33 0 003.38 1.37l.194-.045c.226-.06.444-.146.65-.256l.202-.118 4.192-2.671a2.892 2.892 0 001.306-1.937 3.081 3.081 0 00-.526-2.331 3.33 3.33 0 00-3.574-1.325 3.05 3.05 0 00-.65.257l-.201.117-1.6 1.02a.927.927 0 01-.257.113 1.003 1.003 0 01-1.077-.4.93.93 0 01-.158-.702.871.871 0 01.295-.512l.098-.072 4.192-2.671a.923.923 0 01.258-.113c.407-.106.836.053 1.076.399a.942.942 0 01.171.49l-.002.133-.014.156.155.047c.492.148.959.365 1.388.645l.252.175.215.157.079-.24c.042-.129.076-.26.1-.392a3.082 3.082 0 00-.526-2.33z"/></svg>', - swift: - '<svg viewBox="0 0 32 32"><path d="M9.6 11c0-.1-.1-.1-.1-.2-.2-.3-.5-.6-.7-.9-.4-.4-.7-.7-.9-1.1.3.3.7.6 1 .8.2.1.3.3.5.4.4.3.7.6 1.1.9.4.4.9.7 1.3 1 .5.4 1 .8 1.5 1.1.8.6 1.6 1.1 2.4 1.7v-.1c-.6-.7-1.2-1.4-1.9-2.1-.4-.5-.8-1-1.2-1.4-.3-.4-.7-.9-1-1.3 0-.1-.1-.1-.1-.2l-.9-1.2c-.1-.2-.3-.4-.4-.7.5.4.9.9 1.4 1.3.5.5 1.1 1 1.6 1.5.4.3.8.7 1.2 1l1.2.9c.3.2.5.4.8.6 1.1.8 2.2 1.6 3.4 2.4.1.1.2.1.2-.1.4-1 .5-2 .5-3.1 0-.9-.2-1.9-.5-2.7 0-.2-.1-.5-.2-.8-.2-.4-.4-.9-.7-1.3-.1-.4-.4-.8-.7-1.1 0-.1-.1-.1-.1-.2.4.2.7.4 1 .6 1.5 1.1 2.7 2.4 3.7 3.9.3.6.7 1.3.9 1.9.4 1 .7 2.1.7 3.2v.1c0 .4 0 .9-.1 1.3s-.1.8-.2 1.2c0 .1 0 .2.1.3.8 1 1.3 2.1 1.5 3.3.1.3.1.6.1 1 0 .3 0 .5-.1.8 0 .1 0 .1-.1.1s-.1-.1-.1-.1c-.4-.8-1-1.4-1.9-1.5-.8-.2-1.5 0-2.2.3-.5.2-.9.5-1.3.6-1.4.6-2.9.8-4.4.6-1-.1-2-.3-3-.7h-.1c-.6-.3-1.2-.5-1.8-.8-2-1.1-3.6-2.6-4.9-4.5l-.1-.1c.1 0 .1 0 .2.1.3.2.6.4 1 .6.4.2.8.5 1.2.6.5.3 1.1.5 1.7.6.1.1.1 0 .2.1 1 .3 2.1.4 3.2.4 1.3-.1 2.5-.4 3.6-1 .2-.1.2-.1 0-.2-.7-.5-1.3-1.1-2-1.7-.5-.4-.9-.9-1.4-1.3-.4-.3-.7-.7-1-1.1-.2-.3-.5-.5-.7-.8-.4-.4-.8-.9-1.2-1.3-.3-.4-.6-.7-.9-1.1 0-.2-.2-.4-.3-.5z"/></svg>', - db: '<svg viewBox="0 0 32 32"><path d="M16.4 14c-2.4 0-4.7-.1-7-.6-.6-.1-1.1-.4-1.7-.6-.3-.1-.4-.3-.4-.6V8.7c0-.2.1-.4.3-.4.7-.3 1.3-.6 2-.7C12.1 7 14.5 7 17 7c2 0 4.1.2 6 .7.4.1.9.3 1.3.5.3.1.4.3.4.6v3.5c0 .2-.2.4-.3.5-.4.2-.8.4-1.2.5-1.4.2-2.8.5-4.2.6-.9.1-1.8 0-2.6.1zm8.3.2v3.6c0 .2-.3.5-.5.5-.6.2-1.3.5-1.9.6-2.8.5-5.7.6-8.6.5-1.6-.1-3.3-.2-4.9-.7-.4-.1-.8-.3-1.2-.5-.2-.1-.3-.3-.3-.5v-3.5c2.9 1 5.8 1.1 8.7 1.1 2.9.1 5.8-.1 8.7-1.1zm0 5.6v3.5c0 .2-.3.5-.5.6-.8.3-1.6.6-2.4.7-4 .6-8 .6-12.1-.1-.7-.1-1.4-.4-2-.6-.3-.1-.4-.3-.4-.7v-3.4c2.8 1 5.7 1.1 8.7 1.1 2.9 0 5.8-.1 8.7-1.1z"/></svg>', - terraform: - '<svg viewBox="0 0 32 32"><path fill-rule="evenodd" d="M12.507 8.015l6.73 4.092v8.182l-6.73-4.09V8.015zM20.03 12.107v8.182l7.126-4.09V8.015l-7.127 4.092zM4.588 3.66v7.919l7.127 3.96v-7.92L4.588 3.66zM12.507 25.04l6.73 3.96v-7.918l-6.73-3.96v7.918z" clip-rule="evenodd"/></svg>', - tex: '<svg viewBox="0 0 32 32"><path d="M8.7 18.8H6.5 11 8.7zm15.5-1.3l-1.4-2.2-1.5 2.2.4.1v1.1h2.2v-1.2z"/><path d="M7.9 17.5H6.5v1.3h4.4v-1.3H9.6V11h.4c1.2 0 1.4.1 1.6 1h1.2l-.2-2.3H4.8l-.3 3.6h1.2v-.5c.2-1.7.3-1.8 1.8-1.8h.4v6.5z"/><path d="M15.8 21.1h-1.7v-2.8h.6c.7 0 .7 0 .7.9v.5h1.2v-4.1h-1.2v.5c0 .9 0 .9-.7.9h-.6v-2.4h1.6c1.5 0 1.6.4 1.7 1.8h1.2l-.3-3.2h-7v1.3h1v6.4h-1v1.3h7.1l.4-2.6h-1.3c0 1.1-.4 1.5-1.7 1.5z"/><path d="M21.7 17.6h-.5l1.5-2.2 1.5 2.2h-.3v1.1h3.6v-1.2H27c-.6 0-.6 0-.7-.2l-2.4-3.5 1.6-2.3c.2-.2.4-.6 1.1-.6h.5V9.6H24v1.2h.5l-.1.1-1.2 1.7-1.3-1.6h.3V9.6h-3.6V11h.5c.6 0 .6 0 .7.2l2.1 3.1-1.8 2.7-.3.3c-.2.2-.5.3-.8.3h-.5v1.2h3.2v-1.2z"/></svg>', - default: - '<svg viewBox="0 0 1200 1000"><path d="M394.1 537.8h411.7v54.7H394.1v-54.7zm0-130.3H624v54.7H394.1v-54.7zm0-130.3h411.7v54.7H394.1v-54.7zm0 390.9H700v54.7H394.1v-54.7z"/></svg>', - twig: '<svg viewBox="0 0 32 32"><rect width="100%" height="100%"/><g class="currentLayer"><path d="M20.505 6.481c.122 0 .246-.005.368.001l.001.027a22.9 22.9 0 01-.37 0V6.48z"/><path d="M19.48 6.964c.296-.22.644-.43 1.024-.455h.37c.041.014.142-.031.143.028-.095 0-.186 0-.279.005-.379-.022-.71.206-.998.424l-.26-.002z"/><path d="M19.74 6.966c.287-.218.62-.446.998-.424-.256.079-.51.185-.712.367-.175.137-.32.305-.48.459a.32.32 0 00-.271.074c.13-.18.294-.336.465-.476z"/><path d="M20.738 6.542c.093-.005.184-.005.279-.005.415.073.76.372 1.026.683l-.024.065c-.282-.283-.626-.527-1.032-.59-.069-.024-.137-.037-.199-.002-.168.04-.332.1-.483.186-.121.07-.21.18-.319.264-.088-.082-.004-.155.04-.234.201-.182.456-.288.712-.367z"/><path d="M20.788 6.693c.062-.035.13-.022.2.001a.21.21 0 01-.2-.001z"/><path d="M19.546 7.368c.16-.154.305-.322.48-.459-.044.079-.128.152-.04.234-.317.4-.56.864-.797 1.319-.036.068-.044.163-.107.21.008-.048.02-.095.028-.143a9.271 9.271 0 00-.281-.002c0-.014.003-.04.004-.054.125-.207.243-.419.368-.626.105-.167.24-.313.345-.48z"/><path d="M18.777 7.623c.238-.216.438-.476.703-.66.087 0 .172.003.26.003a2.62 2.62 0 00-.465.476c-.075.077-.14.162-.213.242-.084.045-.149-.024-.222-.057-.027.034-.049.077-.098.08l.035-.084z"/><path d="M22.043 7.22c.053.06.104.124.14.197l-.018.032c-.04-.057-.134-.1-.146-.164l.024-.065z"/><path d="M19.275 7.442a.32.32 0 01.271-.074c-.106.166-.24.312-.345.48-.043.03-.083.066-.125.098-.054-.015-.105-.037-.16-.048l.146-.214c.072-.08.138-.165.213-.242z"/><path d="M22.183 7.417a.413.413 0 01.114.203.403.403 0 01-.132-.171l.018-.032z"/><path d="M18.84 7.627c.073.033.138.102.222.057l-.146.214a9.259 9.259 0 00-.552.91c-.106.198-.205.4-.3.603-.135 0-.266-.018-.399-.031-.04.038-.072.083-.118.113a9.299 9.299 0 011.042-1.629c.046-.055.083-.131.153-.158.049-.002.071-.045.098-.079z"/><path d="M19.076 7.946c.042-.032.082-.068.125-.099-.125.207-.243.419-.368.626-.034.023-.065.048-.098.07-.045-.012-.086-.036-.132-.043-.113.066-.104.278-.24.308.167-.313.352-.618.553-.91.055.011.106.033.16.048z"/><path d="M18.735 8.543c.033-.022.064-.047.098-.07l-.004.054c-.225.39-.384.817-.557 1.233-.099.29-.24.568-.297.87l-.03.08c-.127.098-.121.308-.23.431-.163.014-.117-.207-.25-.235.027-.093.06-.185.084-.28.169-.405.33-.815.514-1.215.096-.203.195-.405.3-.603.136-.03.127-.242.24-.308.046.007.087.031.132.043z"/><path d="M18.829 8.527c.094 0 .186 0 .28.002-.007.048-.019.095-.027.142a20.237 20.237 0 00-.772 2.008l-.02-.002c-.105-.011-.212-.017-.315-.046.057-.303.198-.581.297-.871.173-.416.332-.842.557-1.233z"/><path d="M17.547 9.493c.046-.03.079-.075.118-.113.133.013.264.032.398.031-.184.4-.345.81-.514 1.215-.084.032-.051.174-.14.175-.067-.095-.147-.19-.153-.31-.056-.013-.113 0-.127.062-.096.13-.077.317-.2.426.01-.13.078-.246.121-.367.15-.38.296-.767.497-1.119z"/><path d="M17.129 10.553c.014-.062.07-.075.127-.063.006.122.086.216.153.311.089-.001.056-.143.14-.175-.024.095-.057.187-.085.28-.174.487-.344.98-.462 1.484-.145.434-.222.888-.336 1.331-.07.04-.135.09-.216.107-.143.074-.275.2-.315.362a.354.354 0 01.002-.141c.188-1 .422-1.992.738-2.96l.055-.11c.122-.11.103-.297.199-.426z"/><path d="M17.975 10.63c.103.03.21.036.316.047-.074.034-.06.115-.062.182-.062.32-.189.629-.27.946a40.74 40.74 0 00-.312 1.25c-.022.03.01.112-.043.106-.094 0-.186-.008-.278-.023a.875.875 0 00-.149.194c.091-.474.243-.935.37-1.4.116-.413.266-.815.398-1.223l.03-.078z"/><path d="M18.23 10.86c.001-.068-.013-.15.06-.183-.015.057-.004.155-.06.182z"/><path d="M17.714 11.141c.11-.123.104-.333.231-.432-.132.408-.282.81-.399 1.222-.062.064-.104.143-.15.218a.523.523 0 01-.154.013c-.047-.048.027-.148-.084-.106-.036.118-.064.245-.156.334.118-.505.288-.997.462-1.484.134.028.088.249.25.235z"/><path d="M17.396 12.149c.046-.075.088-.154.15-.218-.126.466-.278.927-.369 1.401-.055.144-.066.3-.114.447-.109.171-.118.383-.205.564-.09.02-.2.03-.267.104-.031.103-.05.21-.089.311a.878.878 0 01.02-.211c.02-.28.135-.545.144-.826.114-.443.19-.897.336-1.331.092-.09.12-.216.156-.334.111-.042.037.058.084.106a.523.523 0 00.154-.013z"/><path d="M17.326 13.138c.092.015.184.022.278.023-.104.664-.265 1.318-.343 1.986l-.026.003c-.01-.144.021-.284.048-.423-.131-.072-.249.057-.379.063-.034.027-.044.071-.063.109.039-.379.165-.744.222-1.12.048-.146.06-.303.114-.447a.875.875 0 01.149-.194z"/><path d="M16.45 13.828c.081-.017.146-.067.216-.107-.009.28-.124.546-.144.826a1.312 1.312 0 00-.447 0c-.025-.124.064-.232.06-.357.04-.161.172-.288.315-.362z"/><path d="M16.858 14.343c.087-.18.096-.393.205-.564-.057.376-.183.741-.222 1.12a.97.97 0 01-.02.143l-.012-.093c-.053.01-.011.093-.05.123-.05.093-.165.026-.25.03-.02.047-.04.093-.065.136l-.004-.202c.018-.093.029-.189.062-.278.039-.101.058-.208.09-.311.066-.073.177-.084.266-.104z"/><path d="M16.075 14.548c.147-.022.299-.03.447-.001a.878.878 0 00-.02.211c-.033.09-.044.185-.062.278-.129.044-.265-.014-.39.036-.066.041-.072.124-.092.195a2.395 2.395 0 01.117-.72z"/><path d="M16.904 14.79c.13-.006.248-.135.379-.063-.027.14-.059.279-.048.423-.01.2-.036.397-.062.595l-.032.003a.205.205 0 00-.053-.199h-.303c-.043.069-.051.153-.09.225.005-.097.029-.193.026-.29.038-.147.069-.294.1-.442a.97.97 0 00.02-.143c.02-.038.029-.082.063-.11z"/><path d="M16.76 15.072c.038-.03-.004-.112.05-.123l.011.093a9.378 9.378 0 01-.1.441c-.04.064-.062.135-.09.203-.063-.012-.123-.04-.186-.052-.038.053-.06.115-.085.175-.001-.067.003-.133.006-.2.032-.12.017-.258.078-.37a1.41 1.41 0 00.065-.136c.085-.005.2.062.25-.031z"/><path d="M16.05 15.072c.125-.05.261.008.39-.036l.004.202c-.06.113-.046.25-.078.371-.102.097-.25.008-.374.008-.048.069-.076.148-.11.223a1.56 1.56 0 01.076-.573c.02-.07.026-.154.093-.195z"/><path d="M19.198 15.207c.084-.04.157-.126.258-.115-.953 1.021-1.415 2.395-1.657 3.746l-.024-.006a1.373 1.373 0 00-.286-.051c.227-.943.447-1.916.976-2.744.033-.058.102-.114.062-.186.001-.055.057-.103.094-.141.182-.18.353-.375.577-.503z"/><path d="M16.631 15.686c.028-.068.05-.14.09-.203.003.098-.02.194-.025.291-.057.116-.08.244-.122.366-.064-.011-.126-.032-.189-.046-.042.068-.053.15-.083.223l-.008-.034a4.22 4.22 0 01.066-.474c.025-.06.047-.122.085-.175.063.012.123.04.186.052z"/><path d="M16.785 15.549h.303a.205.205 0 01.053.199.356.356 0 00-.019.192c.015.25-.065.493-.058.743h-.026c-.02-.096.048-.246-.067-.301-.1.027-.315-.126-.326.055l-.03-.008-.012-.121c.027-.179.093-.352.093-.534.038-.072.046-.156.09-.225z"/><path d="M15.992 15.617c.124 0 .272.089.374-.008-.003.067-.007.133-.006.2a4.22 4.22 0 00-.066.474c-.02.057-.037.115-.06.17-.137.05-.33-.138-.406.04a1.12 1.12 0 01-.06.313c-.014-.224.033-.45.058-.672.008-.1.018-.2.055-.294.035-.075.063-.154.11-.223z"/><path d="M17.122 15.94a.356.356 0 01.019-.192c.02.052.046.172-.019.192z"/><path d="M16.574 16.14c.041-.122.065-.25.122-.366 0 .182-.066.355-.093.534-.025.085-.055.168-.085.252-.053-.011-.106-.027-.16-.038-.053.04-.064.108-.083.168.005-.125.016-.249.027-.373.03-.073.041-.155.083-.223.063.014.125.035.19.046z"/><path d="M18.23 16.229c.093-.127.165-.292.297-.378.04.072-.03.128-.062.186-.53.828-.749 1.801-.976 2.744-.11.206-.092.462-.144.688-.113.004-.157-.128-.23-.194-.054-.015-.106.01-.157.024.069-.404.224-.786.353-1.175.247-.658.524-1.31.92-1.895z"/><path d="M16.233 16.454c.024-.056.04-.114.061-.17l.008.033c-.01.124-.022.248-.027.373-.03.236-.041.473-.057.71-.017.423-.058.844-.068 1.267-.042.296-.02.596-.015.894-.014.35-.003.701-.01 1.052l-.044-.02c-.133-.222-.21-.476-.364-.685-.053-.032-.168-.131-.06.09.073.417.268.81.27 1.24a9.059 9.059 0 00-.045-.184 6.103 6.103 0 00-.288-.966 4.114 4.114 0 01-.063-.18c.016-.09.031-.178.029-.268 0-.055.002-.11.006-.165a2.41 2.41 0 00.021-.407 43.3 43.3 0 01-.001-.191c-.012-.18.022-.359.038-.537l.027-.238.006-.027a.45.45 0 00.017-.197l-.003-.195a2.34 2.34 0 01.067-.565 2.12 2.12 0 00.022-.264l.007-.048a1.02 1.02 0 00.06-.312c.078-.179.27.008.406-.04z"/><path d="M16.518 16.56c.03-.084.06-.167.085-.252l.012.12c-.057.226-.079.46-.154.68-.053-.004-.104-.02-.156-.025-.011.11-.051.214-.087.317.016-.237.027-.474.057-.71.019-.06.03-.127.083-.168.054.011.107.027.16.038z"/><path d="M16.645 16.437c.01-.18.227-.028.326-.055.115.055.047.205.067.302a3.39 3.39 0 01-.066.703c-.014.074-.019.152-.027.228a1.686 1.686 0 00-.023.291c0 .076 0 .151.002.227.003.074 0 .147-.007.22-.013.075-.021.153-.03.229a1.98 1.98 0 00-.019.35l-.003.191-.003.025c-.01.185-.042.37-.046.556-.02.11-.064.213-.066.327-.067 0-.05.07-.059.115a.997.997 0 00-.135.15c.032-.332-.032-.664-.035-.997-.083-.693-.018-1.388 0-2.082.024-.262.074-.521.124-.78z"/><path d="M16.615 16.429l.03.008c-.05.259-.1.518-.124.78a10.894 10.894 0 00-.034 2.395c-.06.412-.192.812-.275 1.22-.003.04-.054.047-.08.066-.003-.097-.003-.19-.007-.285.007-.35-.004-.702.01-1.052.04-.296.018-.596.015-.894.01-.423.05-.844.068-1.267.036-.103.076-.207.087-.317.052.005.103.02.156.024.075-.22.097-.453.154-.678z"/><path d="M10.7 16.54c.047.014.041.093.046.137l-.018.177-.028.001v-.315z"/><path d="M10.728 16.854l.018-.177c.065.262.107.53.168.792a.245.245 0 01.004.117c-.075.385.158.804-.022 1.173-.028-.018-.055-.039-.082-.06v-.082c-.002-.09.01-.18-.021-.264a9.89 9.89 0 01-.01-.222l.002-.196a.385.385 0 00-.014-.2.98.98 0 01-.015-.227c-.002-.117.006-.235-.017-.35a1.886 1.886 0 01-.011-.304z"/><path d="M15.738 17.118c.019-.072-.053-.237.022-.264a2.115 2.115 0 01-.022.264z"/><path d="M10.739 17.159c.023.114.015.232.017.35h-.028a1.965 1.965 0 01.01-.35z"/><path d="M16.487 19.612a10.897 10.897 0 01.034-2.395c-.018.694-.083 1.39 0 2.082.003.333.067.665.035.997a.997.997 0 01.135-.15l.013.068c-.059.26-.114.52-.161.783-.012.048-.02.096-.028.144l-.027.184-.021-.007c-.023-.02-.041-.074-.08-.053-.085.039-.2.028-.258.11a8.04 8.04 0 00-.006-.321l.008-.156c.027-.02.078-.025.081-.066.083-.408.214-.808.275-1.22z"/><path d="M16.945 17.615c.008-.076.013-.154.027-.228a.98.98 0 01.004.236l-.031-.008z"/><path d="M12.537 17.637c-.085.08-.322-.197-.02-.072.367-.025.732.036 1.078.15l.01.024c-.076.079-.15.158-.232.23-.275-.118-.533-.29-.836-.332z"/><path d="M10.896 18.759c.18-.369-.053-.788.022-1.173.069.239.101.498.15.745-.077-.071-.13.081-.081.143.044.264.002.527-.008.791-.018.04-.035.082-.057.121-.07-.034-.084-.111-.102-.179l-.007-.078v-.257l.001-.172.082.059z"/><path d="M16.922 17.906a1.686 1.686 0 01.023-.29c.004.095.011.193.005.29h-.028z"/><path d="M15.66 17.878c-.026-.053-.043-.165.011-.195l.003.195h-.015z"/><path d="M10.77 17.736a.385.385 0 01.015.199h-.014a.218.218 0 010-.2z"/><path d="M13.605 17.74a.864.864 0 01.36.162 1.387 1.387 0 00-.08.068c.079.08.19.123.254.22.171.129.069.38.214.522-.025.086.03.164.019.249-.106-.07-.153-.217-.24-.31-.221-.215-.425-.451-.687-.619-.022-.022-.07-.027-.072-.063.082-.072.156-.151.232-.23z"/><path d="M15.66 17.878h.014a.45.45 0 01-.017.197c-.028-.059-.034-.14.002-.197z"/><path d="M13.885 17.97a.87.87 0 01.08-.068c.548.304.946.822 1.247 1.363a.698.698 0 00-.162.125c0 .139.05.27.104.396a1.55 1.55 0 01-.039.905c.005.114.018.226.018.341l-.026-.001c-.08-.734-.373-1.44-.735-2.07.01-.085-.044-.163-.02-.25-.144-.14-.042-.392-.213-.521-.064-.097-.175-.14-.254-.22z"/><path d="M16.922 17.906h.028c-.011.068.037.202-.026.227a8.664 8.664 0 01-.002-.227z"/><path d="M10.771 17.935h.014l-.002.196h-.017a.257.257 0 01.005-.196z"/><path d="M15.624 18.34c.007-.072-.048-.214.027-.238-.008.08-.018.157-.027.238z"/><path d="M10.766 18.13h.017c.002.074.006.148.01.223l-.032.009a.786.786 0 01.005-.231z"/><path d="M10.987 18.474c-.05-.062.004-.214.08-.143.022.16.055.318.08.476-.06.037-.16.056-.079.179-.03.162.07.33.006.487-.016.048-.036.096-.054.145-.012-.118-.032-.235-.041-.353.01-.264.052-.527.008-.791z"/><path d="M10.793 18.353c.03.084.02.174.02.264h-.027a1.413 1.413 0 01.007-.264z"/><path d="M16.887 18.582c.009-.076.017-.154.03-.228.003.086.01.176.005.264l-.032-.006-.003-.03z"/><path d="M16.868 18.933c0-.118 0-.236.02-.351l.002.03c.003.105.016.215-.005.32h-.017z"/><path d="M10.786 18.617h.027l.001.083-.001.172h-.027a2.953 2.953 0 010-.255z"/><path d="M16.135 19.56c-.004-.297-.027-.597.015-.893.003.298.025.598-.015.894z"/><path d="M17.345 19.47c.052-.227.034-.483.144-.69.098.006.192.026.286.052-.049.101-.052.214-.057.325-.005.105-.019.21-.04.313a.4.4 0 00-.015.194c.005.057-.02.111-.037.166a2.48 2.48 0 00-.024.033c-.046.003-.089.016-.115.056-.04.057-.115.072-.157.127-.102.342-.068.72-.24 1.042-.07.012-.122-.042-.18-.068-.096-.02-.339.019-.242-.187.026-.37.1-.737.186-1.098a.192.192 0 00.007-.159l.012-.072a.56.56 0 00.085-.205c.05-.014.103-.04.157-.024.073.066.117.198.23.194z"/><path d="M11.068 18.986c-.081-.123.018-.142.079-.179.033.24.08.477.12.716-.046-.036-.08.001-.107.04-.004.147-.007.296-.008.444-.03.06-.093.102-.091.177a.7.7 0 00-.078-.23c.014-.112.026-.224.037-.336.018-.049.038-.097.054-.145.064-.157-.036-.325-.006-.487z"/><path d="M17.718 19.157c.005-.11.008-.224.057-.325-.04.08.032.285-.057.325z"/><path d="M10.786 18.873h.027v.256l-.027-.001a2.832 2.832 0 010-.255z"/><path d="M15.57 19.068c-.02-.053-.037-.162.016-.191l.001.191h-.017z"/><path d="M16.868 18.933h.017a.277.277 0 01-.002.19h-.018l.003-.19z"/><path d="M15.57 19.068h.017c.002.136 0 .272-.021.407l-.007-.12c0-.096-.01-.192.01-.287z"/><path d="M10.786 19.128h.027l.007.08-.007.204c-.084-.02-.008-.204-.027-.284z"/><path d="M16.865 19.123h.018l.012.206c.002.08.03-.042.063-.03a.56.56 0 01-.085.205 14.099 14.099 0 01-.01-.356l.002-.025z"/><path d="M16.816 19.704c.004-.186.036-.37.046-.556l.01.356a6.316 6.316 0 01-.011.072c-.016.042-.03.085-.045.128z"/><path d="M10.82 19.207c.018.068.033.145.102.18.022-.04.039-.081.057-.122.01.118.029.235.04.353-.01.112-.022.224-.036.336a.492.492 0 01-.14-.027c-.005-.082.003-.161-.02-.239-.017-.092-.01-.184-.01-.276l.007-.205z"/><path d="M15.05 19.39a.698.698 0 01.162-.125c.09.154.162.318.228.484-.035.031-.07.062-.102.097.047.248.176.49.126.75-.097.246-.223.485-.277.746l-.024.004c.009-.108-.037-.207-.03-.314 0-.115-.013-.227-.018-.34a1.55 1.55 0 00.039-.906 1.008 1.008 0 01-.104-.396z"/><path d="M15.532 19.64c.029-.072-.046-.25.027-.285l.007.12c-.004.055-.005.11-.006.165h-.028z"/><path d="M17.663 19.664a.4.4 0 01.014-.194c.024.051.049.17-.014.194z"/><path d="M11.16 19.563c.027-.039.06-.076.107-.04-.004.142.075.283.047.421a.187.187 0 00-.046.179 5.99 5.99 0 00.068 1.006c.03.165.015.34.073.5l.007.019c-.023.028-.044.058-.068.085-.076-.01-.163-.067-.221.01l-.022-.177c-.006-.12-.008-.238-.013-.357.025-.343-.038-.683-.031-1.025-.002-.075.06-.118.09-.177.002-.148.005-.297.01-.444z"/><path d="M16.816 19.704l.045-.128a.192.192 0 01-.007.16 6.67 6.67 0 00-.186 1.097c-.097.206.146.168.242.187.058.026.11.08.18.068.172-.323.138-.7.24-1.042.042-.055.117-.07.157-.127.026-.04.07-.053.115-.056l.004.203c.003.131-.019.26-.036.39-.015.094-.02.19-.028.285-.01.029-.018.057-.026.087-.047.076-.122.103-.212.101-.126.139-.119.334-.187.499-.172-.007-.264-.241-.459-.215-.116-.002-.13-.117-.115-.216.047-.262.102-.523.16-.783.02-.06.038-.12.047-.183.002-.114.046-.217.066-.327z"/><path d="M15.532 19.64h.028c.002.09-.013.178-.029.268-.001-.091-.003-.179.001-.268z"/><path d="M10.824 19.688c.022.078.014.157.018.239v.053l-.028.002c-.003-.1-.008-.197.01-.294z"/><path d="M15.338 19.846c.032-.035.067-.066.102-.097.031.053.04.118.091.159.02.06.04.12.063.18a6.63 6.63 0 00-.003.107c-.108.05-.023.178-.023.258.02.183.06.364.047.549-.106.217-.27.41-.311.655-.06.152.03.31-.023.464l-.03-.008a9.016 9.016 0 01-.004-.231.392.392 0 00-.014-.196c-.049-.108-.043-.229-.046-.344.054-.261.18-.5.277-.747.05-.26-.079-.501-.126-.749z"/><path d="M17.602 19.863a2.48 2.48 0 01.024-.033c-.006.07.044.209-.02.236l-.004-.203z"/><path d="M15.658 19.998c-.109-.221.006-.122.06-.09.154.209.23.463.363.685l.044.02c.004.095.004.188.006.285l-.008.156a.929.929 0 01-.157.187l-.016.193a3.701 3.701 0 00-.11-.009c.054-.05.106-.108.087-.188-.002-.428-.197-.822-.27-1.239z"/><path d="M10.842 19.927a.492.492 0 00.14.027.7.7 0 01.079.23c-.007.342.056.682.03 1.025-.026-.133-.014-.283-.083-.404-.08.001-.1.103-.157.147-.01-.106-.01-.211-.01-.318v-.654l.001-.053z"/><path d="M11.268 20.123a.187.187 0 01.046-.179c.092.445.129.903.193 1.354-.01.125.063.241.04.366a1.21 1.21 0 00-.056-.089c-.028.016-.055.035-.082.054-.058-.16-.043-.335-.073-.5a5.99 5.99 0 01-.068-1.006z"/><path d="M10.814 19.982l.028-.002v.313h-.028a4.958 4.958 0 010-.311z"/><path d="M16.691 20.146c.009-.046-.008-.115.059-.115a1.079 1.079 0 01-.046.183l-.013-.068z"/><path d="M15.594 20.088c.125.313.216.638.288.966l-.03-.006-.036-.013a1.47 1.47 0 00-.023-.101 4.345 4.345 0 00-.202-.739l.003-.107z"/><path d="M15.568 20.453c0-.08-.085-.208.023-.258.086.241.16.486.202.739a.925.925 0 00-.073.072c-.06.048.007.149-.038.206-.085.116-.211.21-.237.36-.13.342.155.657.072 1.001-.01.114-.07.214-.118.316-.058.116-.045.257-.117.367l-.003-.03c-.008-.286-.002-.572-.004-.858 0-.084 0-.165.006-.247.053-.155-.037-.312.023-.464.04-.245.205-.438.31-.655.014-.185-.026-.366-.046-.549z"/><path d="M10.814 20.293h.028v.341h-.029a5.684 5.684 0 01.001-.34z"/><path d="M17.542 20.741c.008-.095.013-.191.028-.285.004.097.013.196.003.293l-.031-.008z"/><path d="M17.516 20.828l.026-.087c.005.124.011.25.006.376h-.027c-.002-.097-.001-.192-.005-.29z"/><path d="M10.85 20.952c.057-.044.078-.146.158-.147.069.121.057.271.084.404.005.119.007.237.013.357.002.09.029.216-.09.175-.077-.037-.085-.164-.14-.232a43.324 43.324 0 01-.004-.192c-.002-.117 0-.233-.018-.348l-.002-.017z"/><path d="M17.304 20.93c.09 0 .165-.026.212-.102.004.097.003.192.005.29l-.003.193c-.135.01-.15.2-.307.156-.076.099-.09.226-.134.34-.003-.228-.161-.46-.39-.506-.097.001-.154-.072-.172-.16.007-.048.016-.096.028-.144-.014.1-.001.214.115.216.195-.026.287.208.459.215.068-.165.061-.36.187-.499z"/><path d="M15.72 21.006a.925.925 0 01.073-.072l.023.101a1.505 1.505 0 01-.096-.029z"/><path d="M10.853 20.969c.018.115.016.231.018.348h-.029a2.403 2.403 0 01.01-.348z"/><path d="M15.682 21.212c.045-.057-.021-.158.038-.206l.096.03.036.012c-.115.065-.113.215-.202.302-.143.14-.215.366-.141.558.044.158.155.278.242.413.05.372-.175.697-.237 1.052 0 .393-.004.794.105 1.175a2.939 2.939 0 00-.146-.027c-.026-.019-.075-.017-.082-.054-.067-.202-.114-.41-.167-.616.05-.048.026-.115.023-.175a.545.545 0 01.007-.107c.013-.104.022-.208.028-.313.072-.11.059-.251.117-.367.048-.102.107-.202.118-.316.083-.344-.202-.66-.072-1.001.026-.15.152-.244.237-.36z"/><path d="M15.65 21.35c.089-.087.087-.237.202-.302l.03.006c.009.088-.045.141-.11.189-.041.146-.196.225-.224.376-.079.232.086.454.272.575.06.03.055.1.066.157.036.32.009.645-.03.965 0 .364-.022.732.022 1.095a.609.609 0 01-.005.189c-.085-.016-.169-.035-.254-.052-.11-.38-.106-.782-.105-1.175.062-.355.286-.68.237-1.052-.087-.135-.198-.255-.242-.413-.074-.192-.002-.418.141-.558z"/><path d="M15.882 21.054l.045.183c.02.08-.033.138-.087.188-.13.062-.226.185-.21.34-.053.174.17.27.26.383.088.254.062.525.09.789.037.559.039 1.118.034 1.679-.047-.004-.095-.006-.14-.016a.609.609 0 00.004-.189c-.044-.363-.021-.731-.022-1.095.039-.32.066-.644.03-.965-.01-.057-.007-.127-.066-.157-.186-.121-.35-.343-.272-.575.028-.151.183-.23.224-.376.065-.048.119-.1.11-.189z"/><path d="M15.966 21.241a.929.929 0 00.157-.187c.005.107.006.213.006.321l-.06.113c-.04-.019-.08-.035-.119-.054l.016-.193z"/><path d="M17.52 21.118h.028c0 .141.006.285-.002.427l-.027-.008v-.226l.002-.193z"/><path d="M16.488 21.325l.027-.184c.018.088.075.161.171.16.23.046.388.278.391.506.043-.114.058-.241.134-.34.156.045.172-.147.307-.156v.226a3.257 3.257 0 01-.03.032.622.622 0 00-.174.22c-.04-.03-.077-.072-.13-.078-.011.104-.035.21-.018.316-.009.326-.102.645-.096.972l-.009.046c-.02.074-.037.153-.061.228-.17-.049-.325.048-.493.025a.45.45 0 01-.094-.253c.03.047.057.097.089.144.086-.04.155-.156.26-.125.084.001.161-.05.238-.08.062-.248.061-.505.091-.758a.916.916 0 00-.03-.343c-.057.082-.11.168-.176.245-.113.034-.23.087-.35.057-.062-.02-.126-.005-.188.007l.007-.022c.11-.12.316-.024.447-.123.184-.127.198-.415.046-.57-.083-.114-.239-.102-.359-.152z"/><path d="M9.703 21.172c.18.087.32.245.456.39a.124.124 0 00-.093.093l-.02-.002c-.083-.182-.22-.327-.343-.48z"/><path d="M16.13 21.375c.057-.082.172-.071.257-.11.039-.021.057.032.08.053l.006.14c-.159.077-.196.292-.087.427a.816.816 0 01-.03.197c-.052.057-.167.098-.194-.004-.034-.064-.073-.125-.099-.193a.266.266 0 00.005-.397l.061-.113z"/><path d="M10.842 21.316h.029c0 .049.003.145.004.193a7.292 7.292 0 00-.006.177h-.027c-.002-.124-.005-.247 0-.37z"/><path d="M16.467 21.318l.021.007c.12.05.276.038.36.153.151.154.137.442-.047.569-.131.1-.338.004-.447.123l.003-.088a.816.816 0 00.03-.197c.12.133.367.09.424-.084.116-.199-.146-.406-.338-.344l-.006-.139z"/><path d="M15.63 21.764c-.016-.154.08-.277.21-.339l.11.01c.04.018.08.034.118.053a.266.266 0 01-.005.397l-.078.058c-.151.045-.29-.05-.355-.179z"/><path d="M16.473 21.457c.192-.062.454.145.338.344-.057.175-.304.217-.425.084-.109-.135-.072-.35.087-.428z"/><path d="M10.875 21.509c.055.068.063.195.14.232.119.041.092-.085.09-.175l.022.178c-.001.095 0 .193-.003.29a1.538 1.538 0 01-.16-.044c-.05-.043-.062-.111-.09-.168a4.374 4.374 0 01-.005-.136c.001-.06.004-.118.006-.177z"/><path d="M17.487 21.569l.032-.032c0 .086.004.175 0 .263h-.027l-.005-.231z"/><path d="M10.066 21.655a.124.124 0 01.093-.093c.203.192.357.438.478.689-.08.08-.177.149-.23.25l-.015.011c-.064-.3-.206-.577-.326-.857z"/><path d="M11.41 21.629a1.02 1.02 0 01.08-.054c.02.029.039.058.056.089.01.097.055.2.026.297-.16.067-.06.28-.132.408-.043.11-.199.069-.285.116l.003-.2c.04-.132.2-.041.276-.123a5.48 5.48 0 00.005-.222c-.004-.098.017-.2-.023-.292l-.007-.02z"/><path d="M17.314 21.79a.622.622 0 01.173-.221l.005.23c0 .22 0 .439.002.658a1.647 1.647 0 00-.005.14c-.148-.112-.22.124-.354.155-.026.081-.044.163-.065.247-.006-.327.087-.646.096-.972-.017-.105.007-.212.018-.316.053.006.09.048.13.078z"/><path d="M11.348 21.733c.024-.027.045-.057.068-.085.04.092.02.194.023.292-.082.11-.256-.037-.315.094.003-.097.002-.195.003-.29.058-.078.145-.022.221-.011z"/><path d="M10.842 21.686h.027l.005.136-.005.262h-.027c-.001-.134-.004-.266 0-.398z"/><path d="M15.233 21.686a.392.392 0 01.014.196h-.019a.238.238 0 01.005-.196z"/><path d="M15.89 22.148c-.09-.113-.313-.21-.26-.384.065.129.204.224.355.179-.031.025-.075.024-.112.036.03.09.14.097.189.17.032.093.038.195.086.283.026.128.038.259.037.39a.641.641 0 00-.08-.029c-.01.088-.057.175-.047.267.044.526-.027 1.059.038 1.583h-.081l-.001-.027c.005-.56.003-1.12-.035-1.68-.027-.263-.001-.534-.09-.788z"/><path d="M17.492 21.8h.027c-.004.218.016.438-.008.656h-.017a35.863 35.863 0 01-.002-.656z"/><path d="M10.874 21.822c.028.057.04.125.09.168.052.018.106.032.16.044a2.5 2.5 0 00.014.1c-.023.088-.016.261-.179.174-.05-.006-.053-.082-.083-.117a.434.434 0 01-.007-.107l.005-.262z"/><path d="M15.228 21.883l.019-.001c0 .076.001.153.004.23-.069-.019-.024-.162-.023-.23z"/><path d="M15.985 21.943c.026-.02.052-.04.078-.058.026.068.065.129.099.193l-.014.354c-.048-.088-.054-.19-.086-.283-.05-.073-.16-.08-.189-.17.037-.012.08-.011.112-.036z"/><path d="M16.885 22.128c.065-.077.12-.163.177-.245.038.11.034.228.03.343-.03.253-.03.51-.092.759-.077.03-.154.08-.238.079-.105-.03-.174.085-.26.125-.032-.047-.059-.097-.09-.144-.064-.212-.068-.437-.094-.655a.559.559 0 01.03-.198c.061-.012.125-.026.187-.007.12.03.237-.023.35-.057z"/><path d="M11.124 22.034c.059-.13.233.017.315-.094 0 .074-.002.148-.005.222-.076.082-.235-.01-.276.124a1.125 1.125 0 00-.02-.152 2.5 2.5 0 01-.014-.1z"/><path d="M11.44 22.37c.072-.128-.027-.342.132-.409.021.094.05.192.032.289-.034.024-.082.038-.085.087-.037.174-.012.365-.093.53-.082.07-.161.144-.241.216-.008-.173-.03-.346-.033-.519l.003-.08c.086-.046.242-.005.285-.115z"/><path d="M16.162 22.078c.027.102.142.061.195.004l-.003.088-.007.022a.559.559 0 00-.029.198c-.03.174-.038.352-.083.523a3.62 3.62 0 01-.05-.092 1.897 1.897 0 00-.037-.389l.014-.354z"/><path d="M15.25 22.113l.03.008a4.437 4.437 0 00-.005.247h-.027a1.826 1.826 0 01.003-.255z"/><path d="M11.138 22.134c.01.05.016.1.02.152l-.003.199-.003.08c-.083.01-.166.029-.25.032a1.276 1.276 0 00-.021-.123 1.027 1.027 0 01-.005-.283c.03.035.032.11.083.117.163.087.156-.086.179-.174z"/><path d="M10.407 22.502c.053-.102.15-.171.23-.251.085.147.16.3.214.462.011.03.024.06.037.089.054.146.114.29.144.443-.174.037-.007.286-.1.378-.102.06-.272.11-.263.25l-.026.002c.002-.467-.138-.922-.236-1.373z"/><path d="M11.52 22.337c.002-.05.05-.063.084-.087.039.216.05.439.062.658-.004.117.054.255-.058.337-.077.054-.112.145-.145.23-.044.09-.059.189-.08.285-.022.028-.044.054-.063.083-.025.127-.033.264-.06.394l-.021.015a2.051 2.051 0 01-.031-.297c-.001-.045-.013-.088-.022-.132.055-.245-.03-.493-.001-.74l.24-.216c.082-.165.057-.356.094-.53z"/><path d="M15.248 22.368h.027c.002.286-.004.572.004.858l-.03-.007a35.34 35.34 0 01-.001-.85z"/><path d="M16.235 22.913c.045-.171.054-.35.083-.523.026.218.03.443.095.655a.45.45 0 00.094.253c.168.023.324-.074.493-.025.024-.075.04-.154.061-.228.001.056.002.113 0 .17-.024.141-.039.284-.057.426-.16-.068-.298.153-.442.084-.037-.098-.066-.198-.105-.296-.04-.067-.128-.078-.19-.12-.01-.117.02-.24-.018-.351l-.014-.045z"/><path d="M17.494 22.457l.017-.001c.026.053.013.118.008.176l-.01.018a10.44 10.44 0 01-.02-.053c0-.047.001-.094.005-.14z"/><path d="M10.88 22.474c.01.04.017.082.022.123l-.014.205c-.013-.03-.026-.06-.037-.09a3.58 3.58 0 01.03-.238z"/><path d="M10.902 22.597c.084-.003.167-.022.25-.033.002.173.025.346.033.519-.03.247.056.495.001.74l-.092-.059c.06-.173-.03-.349-.062-.52-.03-.152-.09-.296-.144-.442l.014-.205z"/><path d="M17.135 22.752c.134-.031.206-.267.354-.155l.02.053.002.022a.765.765 0 00.004.299l.002.025v.117c-.019-.05-.031-.102-.057-.149-.162.073-.405.113-.39.347a11.116 11.116 0 00-.01-.096 3.38 3.38 0 00.001-.17l.009-.046c.021-.084.04-.166.065-.247z"/><path d="M17.519 22.632l.026-.011c.002.123.01.248.001.371l-.029.004-.002-.025c0-.101.007-.2-.004-.299l-.001-.022.009-.018z"/><path d="M17.515 22.97a.765.765 0 01-.004-.298c.01.1.005.198.004.299z"/><path d="M12.461 22.71h.313v.027c-.104 0-.208.002-.312 0v-.028z"/><path d="M11.696 23.11c.197-.21.471-.371.766-.373.104.002.208 0 .312 0 .037.013.152-.028.136.028a.388.388 0 00-.193.013.857.857 0 00-.592.446c-.021.075-.072.136-.11.203-.063.201-.099.41-.123.618l-.023-.003a1.346 1.346 0 00-.128-.329c-.1-.063-.283-.08-.251-.237.043-.075.091-.148.118-.231.112-.082.054-.22.058-.337h.027l.003.202z"/><path d="M12.717 22.778a.388.388 0 01.193-.013c-.022.063-.143.04-.193.013z"/><path d="M16.106 22.793a.641.641 0 01.08.028l.049.092.014.045c.016.122-.048.265.017.38.03.048.033.105.038.161 0 .14-.015.284 0 .425.032.2.018.408.076.603-.067-.013-.093.02-.082.085.001.039-.017.06-.055.065-.049-.01-.098-.023-.147-.034-.065-.524.006-1.057-.038-1.583-.01-.092.038-.179.048-.267z"/><path d="M16.25 22.958c.038.111.006.234.017.35v.03c-.066-.115-.002-.258-.018-.38z"/><path d="M17.07 23.311c-.015-.234.228-.274.39-.347.026.047.038.099.056.15.002.041.002.083.003.126-.13.089-.28.161-.396.266-.077.304-.062.629-.051.943l-.007.078-.026.002c-.004-.406-.013-.813.031-1.218z"/><path d="M17.517 22.996l.03-.004c.002.085.006.174-.002.26l-.026-.012a2.66 2.66 0 00-.003-.127l.001-.117z"/><path d="M15.021 23.217c.033.018.066.04.046.082a.859.859 0 00-.012.255l-.003.03-.03.008c-.003-.126-.007-.25 0-.375z"/><path d="M15.249 23.219l.03.007.003.03a4.471 4.471 0 01-.028.313 3.43 3.43 0 01-.005-.35z"/><path d="M17.004 23.641c.018-.142.033-.285.057-.426l.01.096c-.045.405-.036.812-.032 1.218l-.024.004a1.876 1.876 0 00-.17 0 4.072 4.072 0 00-.228 0c-.052-.292-.051-.597-.158-.878-.077-.025-.14-.068-.155-.156-.005-.056-.009-.113-.038-.162l.001-.029c.062.043.15.054.19.121.039.098.068.198.105.296.144.069.283-.152.442-.084z"/><path d="M10.933 23.623c.092-.092-.075-.34.1-.378.032.17.12.346.061.52-.108-.033-.2.034-.223.14.002.109.104.18.201.206l-.084.027a.401.401 0 01.116.129c-.006.103.011.218-.041.314-.111.003-.222.004-.333.004a1.85 1.85 0 00-.02-.093c-.003-.208-.04-.413-.041-.62-.01-.14.161-.189.264-.249z"/><path d="M11.463 23.475c.033-.085.068-.176.145-.23-.027.083-.075.156-.118.23h-.027z"/><path d="M17.123 23.506c.117-.105.265-.177.396-.266 0 .099-.01.204.021.3l.01.106v.025l-.047-.008c-.102.117-.231.224-.262.384 0 .064-.069.05-.11.065 0 .115-.028.227-.06.337-.01-.314-.025-.64.052-.943z"/><path d="M17.519 23.24l.026.013c.006.055.006.11.004.166l-.009.122c-.032-.097-.02-.202-.021-.301z"/><path d="M15.055 23.554a.859.859 0 01.012-.255c.034.163.08.324.13.483.06.032-.021-.13.05-.106.003.06.026.127-.023.175.053.206.1.414.167.616.007.037.056.035.082.054-.08-.01-.057.08-.038.126l.031.085.01.079c-.128-.033-.288.017-.399-.06-.015-.399.026-.801-.022-1.197z"/><path d="M17.549 23.42c.063.024.015.158.027.227l-.027-.001a4.11 4.11 0 00-.009-.105l.009-.122z"/><path d="M11.463 23.475h.027c-.032.158.152.175.251.238.056.104.1.214.128.329a1.263 1.263 0 01-.012.138 2.333 2.333 0 00-.022.233c-.066 0-.134 0-.19.037-.031.088-.03.181-.035.274l-.002.02c-.022.057-.037.118-.064.174a1.68 1.68 0 01-.274.037 4.757 4.757 0 01-.036-.38c.032.027.052.071.092.088.073-.02.146-.043.22-.06a1.66 1.66 0 00.092-.415c-.123.016-.28-.052-.379.05.028-.131.036-.268.061-.395-.108.196.222.327.29.146.101-.131-.1-.305-.228-.229.022-.096.037-.195.08-.285z"/><path d="M16.304 23.5c.015.087.078.13.155.155.107.28.106.586.158.878l-.033-.001c-.039-.119-.05-.244-.09-.362-.148.057-.092-.183-.19-.246-.015-.141 0-.284 0-.425z"/><path d="M15.055 23.554c.048.396.007.798.022 1.197l-.027.005-.003-.056v-.056l-.002-.053c.001-.11.004-.216.002-.324v-.109c.005-.192-.008-.383.005-.574l.003-.03z"/><path d="M17.503 23.663l.046.008c0 .088-.01.182.017.269.017.072.041.142.041.217.007.123.02.245.025.368-.19.003-.378.003-.567.002l.007-.078c.031-.11.058-.222.058-.337.042-.015.111-.001.11-.065.032-.16.161-.267.263-.384z"/><path d="M17.55 23.646l.026.001c.002.096.009.197-.01.293-.027-.087-.016-.181-.017-.27v-.024z"/><path d="M11.382 23.76c.128-.076.33.098.229.23-.069.18-.4.05-.29-.147.018-.03.04-.055.061-.083z"/><path d="M10.87 23.905c.024-.106.116-.173.224-.14l.092.058c.01.044.02.087.022.132a.671.671 0 01-.136.156c-.097-.025-.2-.097-.201-.206z"/><path d="M17.888 24.303c.103-.182.187-.383.316-.546-.048.266-.175.518-.247.78-.03.083-.044.174-.1.244a2.13 2.13 0 01-.226.001.185.185 0 01.038-.08c.023-.036.043-.074.061-.112.048-.098.114-.187.158-.287z"/><path d="M16.304 23.924c.098.063.042.303.19.246.04.118.051.243.09.362a48.88 48.88 0 00-.204-.005c-.058-.195-.044-.404-.076-.603z"/><path d="M11.072 24.111a.671.671 0 00.136-.156c.004.1.012.199.03.297 0 .107 0 .215-.004.323-.036.154-.027.313.004.467a.607.607 0 00-.088-.088c-.07-.223.026-.47-.046-.687a.401.401 0 00-.116-.13.9.9 0 00.084-.026z"/><path d="M14.193 24.014c.096.052.142.163.223.235.064.071.12.148.178.224-.17.076-.207-.085-.277-.182-.042-.092-.102-.178-.124-.277z"/><path d="M18.752 24.14l.02-.012a2.295 2.295 0 01-.176.397l-.196.002c.084-.154.226-.267.352-.387z"/><path d="M14.416 24.25c.214.055.415-.107.631-.092v.053a.66.66 0 00-.283.09c-.056.035-.137.085-.111.164.108.1.253.145.393.18l.001.055c-.27-.05-.546-.108-.793-.233-.01-.062.003-.146.063-.176.07.097.106.258.277.182-.058-.076-.114-.153-.178-.224z"/><path d="M17.607 24.157c.055-.004 0 .091.057.087.075.02.15.034.224.06-.044.099-.11.188-.158.286.006-.073-.05-.053-.097-.042v-.023c-.005-.123-.019-.245-.026-.368z"/><path d="M11.26 24.237c.098-.1.255-.033.378-.05a1.7 1.7 0 01-.091.416c-.075.017-.148.04-.221.06-.04-.017-.06-.061-.092-.088.003-.108.005-.216.005-.323l.02-.015z"/><path d="M11.835 24.413c.003-.077.01-.158.022-.233.003.096.019.198-.001.295h-.017l-.004-.062z"/><path d="M14.764 24.301a.66.66 0 01.283-.09v.056c-.09.007-.18.052-.197.147.023.095.106.153.195.177l.001.053c-.14-.034-.285-.078-.393-.179-.026-.08.055-.129.111-.164z"/><path d="M11.104 24.267c.072.217-.023.464.046.687.004.13.002.262.008.393a.676.676 0 00-.17.007 4.53 4.53 0 00-.2-.035 2.912 2.912 0 01-.069-.215c.002-.09.008-.176.009-.263l.002-.256c.111 0 .222 0 .333-.004.052-.096.035-.21.041-.314z"/><path d="M14.85 24.414c.017-.095.107-.14.197-.147.002.108 0 .215-.002.324-.089-.024-.172-.082-.195-.177z"/><path d="M10.444 24.356c.047.003.034.075.04.11l-.014.117c-.097.018-.006-.167-.026-.227z"/><path d="M11.645 24.45c.056-.038.124-.037.19-.037 0 .016.003.046.004.062-.003.055-.004.11-.006.166-.08.002-.172.015-.223.083.005-.093.004-.186.035-.274z"/><path d="M10.47 24.583c.004-.04.009-.078.015-.117.09.208.143.43.234.638.02.072.044.144.07.215l.022.062.023.062.011.03a.663.663 0 01-.115.025c-.056 0-.113-.002-.17-.006l-.002-.027-.003-.051a9.343 9.343 0 00-.043-.41c-.012-.14-.044-.28-.042-.42z"/><path d="M11.84 24.475h.016a.336.336 0 010 .191l-.017-.002-.006-.023c.002-.056.003-.111.006-.166z"/><path d="M10.71 24.492l.02.093-.002.256h-.029a2.232 2.232 0 01.01-.35z"/><path d="M15.435 24.647c-.02-.047-.042-.136.038-.126l.039.056a1.934 1.934 0 00.584.066c.05.01.098.023.147.034l-.002.023c-.272.03-.536-.049-.806-.053z"/><path d="M15.473 24.521c.049.008.098.017.146.027.085.017.17.036.254.052.046.01.094.012.14.016l.002.027a1.934 1.934 0 01-.503-.066l-.04-.056z"/><path d="M16.298 24.612c-.011-.065.015-.098.082-.085l.204.005.033.001c-.087.063-.2.037-.297.073l-.022.006z"/><path d="M16.617 24.533c.075-.002.152-.002.228 0-.163.075-.348.09-.525.073.097-.036.21-.01.297-.073z"/><path d="M16.845 24.533c.056-.003.113-.002.17 0-.11.086-.255.058-.379.103l-.299.011-.008.025-.009.027-.08.001.003-.023c.038-.005.056-.026.055-.065l.022-.006c.177.016.362.002.525-.073z"/><path d="M17.015 24.533l.024-.004.026-.002c.19.001.378.001.567-.002l.001.023-.106.016-.2-.002c-.224-.02-.43.095-.656.086l-.035-.012c.124-.045.27-.017.379-.103z"/><path d="M17.633 24.548c.047-.011.103-.031.097.042a1.064 1.064 0 01-.061.112l-.012-.059a9.815 9.815 0 01-2.19.09 1.456 1.456 0 01-.032-.086c.27.004.534.083.806.053l.08-.001c.199.004.399.003.595-.037a1.15 1.15 0 00.611-.098l.106-.016z"/><path d="M12.525 24.562l.024-.007c-.029.287-.104.568-.15.853l-.172-.004c.02-.073.05-.142.073-.213.069-.212.166-.414.225-.629z"/><path d="M16.671 24.648c.225.009.432-.107.657-.086-.129.065-.273.076-.412.1a2.7 2.7 0 01-.596.037l.009-.027c.111-.015.234.017.342-.024z"/><path d="M17.328 24.562l.2.002a1.15 1.15 0 01-.612.098c.14-.024.283-.035.412-.1z"/><path d="M11.238 25.042a1.082 1.082 0 01-.004-.467c.008.127.018.253.036.38a1.68 1.68 0 00.274-.037c.027-.056.042-.117.064-.175.021.12.018.24.027.36v.05c-.131.03-.262.061-.393.089l-.004-.2z"/><path d="M11.61 24.724c.051-.068.143-.081.223-.083l.006.023c0 .097-.017.203.018.299l.006.107c-.04-.032-.082-.072-.137-.06-.034.028-.06.062-.091.093-.01-.12-.006-.24-.027-.36l.002-.019z"/><path d="M16.337 24.647l.3-.01.034.01c-.108.042-.23.01-.342.025l.008-.025z"/><path d="M11.84 24.664l.017.002a1.18 1.18 0 010 .297c-.035-.096-.018-.202-.018-.3z"/><path d="M12.895 24.905l.023-.01c-.004.099-.062.186-.065.285h-.14c.048-.1.115-.188.182-.275z"/><path d="M9.928 24.927c.103.046.143.163.226.234.047.04.151.143.026.15-.076-.043-.11-.125-.155-.195-.033-.062-.084-.118-.097-.19z"/><path d="M11.15 24.954a.607.607 0 01.088.088l.004.2-.004.14-.057-.002a2.375 2.375 0 00-.023-.033c-.006-.131-.004-.263-.008-.393z"/><path d="M11.857 24.963c.066-.03.025.096.037.134l-.002.054-.008.066c-.016-.048-.018-.098-.021-.147a4.232 4.232 0 00-.006-.107z"/><path d="M10.512 25.003c.017.136.032.274.043.41-.095-.001-.2-.093-.163-.195.04-.039.117-.054.108-.122l.012-.093z"/><path d="M11.635 25.103c.03-.03.057-.065.09-.093.056-.012.098.028.138.06.003.049.005.1.021.147.012.044.027.087.036.131-.075.048-.17.052-.256.063a3.656 3.656 0 01-.03-.259v-.049z"/><path d="M10.154 25.16c.117-.01.229-.056.346-.064.01.068-.069.083-.108.122-.037.102.068.194.163.196l.003.05c-.132-.032-.278-.051-.378-.154.125-.006.021-.11-.026-.15z"/><path d="M11.894 25.097c.134.028.286.022.406.094-.022.071-.054.14-.073.213-.288.06-.587.086-.881.083.106-.022.212-.048.32-.05.14-.02.318-.006.422-.12.033-.117-.114-.145-.196-.166l.002-.054z"/><path d="M9.873 25.206c.058-.017.104-.055.152-.09.044.07.079.152.155.194.1.103.246.122.378.155l.002.027c-.177.024-.343-.05-.514-.083a.41.41 0 01-.252-.12c-.026-.056.039-.07.079-.083z"/><path d="M11.242 25.242c.131-.028.262-.06.393-.09.007.086.016.173.03.259l.002.025c-.109.003-.215.029-.321.051a.435.435 0 01-.105.006l-.002-.027v-.027l-.001-.028v-.03l.004-.14z"/><path d="M11.892 25.151c.082.021.229.05.196.166-.104.114-.282.1-.421.12l-.003-.026c.087-.01.181-.015.256-.063-.009-.044-.024-.087-.036-.131l.008-.066z"/><path d="M10.788 25.319c.067.01.133.022.2.035a.23.23 0 00.193.026l.057.001v.03c-.144-.002-.285-.018-.427-.03l-.023-.062z"/><path d="M10.988 25.354a.676.676 0 01.17-.007l.023.033a.23.23 0 01-.193-.026z"/><path d="M10.81 25.38c.143.013.284.029.428.03v.029c-.13.018-.282-.042-.404.004l-.023-.062z"/><path d="M10.834 25.443c.122-.046.274.014.404-.004l.001.027c-.131 0-.263-.003-.394.006l-.011-.03z"/><path d="M10.845 25.472c.131-.009.263-.006.394-.006l.002.027c-.172 0-.345-.003-.515.03l.004-.025a.663.663 0 00.115-.026z"/></g></svg>', - typescript: - '<svg viewBox="0 0 32 32"><path d="M15.6 11.8h-3.4V22H9.7V11.8H6.3V10h9.2v1.8zm7.7 7.1c0-.5-.2-.8-.5-1.1-.3-.3-.9-.5-1.7-.8-1.4-.4-2.5-.9-3.3-1.5-.7-.6-1.1-1.3-1.1-2.3 0-1 .4-1.8 1.3-2.4.8-.6 1.9-.9 3.2-.9 1.3 0 2.4.4 3.2 1.1.8.7 1.2 1.6 1.2 2.6h-2.3c0-.6-.2-1-.6-1.4-.4-.3-.9-.5-1.6-.5-.6 0-1.1.1-1.5.4-.4.3-.5.7-.5 1.1 0 .4.2.7.6 1 .4.3 1 .5 2 .8 1.3.4 2.3.9 3 1.5.7.6 1 1.4 1 2.4s-.4 1.9-1.2 2.4c-.8.6-1.9.9-3.2.9-1.3 0-2.5-.3-3.4-1s-1.5-1.6-1.4-2.9h2.4c0 .7.2 1.2.7 1.6.4.3 1.1.5 1.8.5s1.2-.1 1.5-.4c.2-.3.4-.7.4-1.1z"/></svg>', - tsconfig: - '<svg viewBox="0 0 32 32"><path d="M8.125 7h15.75C24.496 7 25 7.504 25 8.125v15.75c0 .621-.504 1.125-1.125 1.125H8.125A1.125 1.125 0 017 23.875V8.125C7 7.504 7.504 7 8.125 7zm9 9.422v-1.547h-6.188v1.547h2.21v6.89h1.758v-6.89h2.22zm.597 6.968a3.71 3.71 0 001.054.364c.407.08.834.121 1.284.121.438 0 .855-.045 1.249-.133.394-.089.74-.237 1.038-.44.297-.206.54-.48.706-.802.173-.33.26-.737.26-1.223 0-.351-.05-.66-.149-.925-.097-.26-.242-.5-.429-.707a3.174 3.174 0 00-.672-.555 7.037 7.037 0 00-.883-.464c-.24-.105-.456-.208-.646-.307a3.24 3.24 0 01-.486-.304 1.288 1.288 0 01-.309-.327.72.72 0 01-.108-.391c0-.134.033-.255.097-.362a.868.868 0 01.275-.276c.118-.077.262-.136.434-.179.172-.042.362-.064.572-.064a3.623 3.623 0 011.495.34c.162.077.311.166.449.267V15.21a4.256 4.256 0 00-.912-.252 7.003 7.003 0 00-1.135-.082c-.435 0-.846.05-1.235.149-.388.1-.73.254-1.026.464a2.272 2.272 0 00-.7.805c-.172.325-.257.714-.257 1.167 0 .58.157 1.072.47 1.481.316.409.793.755 1.433 1.038.251.11.486.216.703.321.217.106.405.215.563.328.158.113.283.237.375.37a.786.786 0 01.137.456.73.73 0 01-.346.628c-.116.079-.26.14-.434.185a2.472 2.472 0 01-.61.067 3.293 3.293 0 01-1.177-.222 3.472 3.472 0 01-1.08-.665v1.943z"/></svg>', - vala: '<svg viewBox="0 0 32 32"><path d="M17.2 12.8c.9 0 1.7.1 2.5.3.2.1.3.1.5.2 1.2.6 1.3 1.7.9 2.6-.2.6-.7 1-1.1 1.4-.8.7-1.7 1.2-2.6 1.8-.7.5-1.5.9-2.1 1.5-.2.2-.3.4-.5.6-.2.3-.2.7-.1 1 .3.6.9 1.1 1.6 1.3.8.2 1.4-.3 1.5-1.1V22c0-.3.1-.5.3-.7.3-.2.7-.4 1.1-.5.5-.1 1.1-.2 1.6-.1.1 0 .2 0 .3.1.5.2.6.5.5 1-.3 1.2-.9 2.1-1.8 2.9-.8.7-1.7 1.1-2.7 1.2-.8.1-1.6 0-2.4-.3-2.6-1-4.4-2.9-5.3-5.6-.6-2 0-3.8 1.6-5.1 1.1-1 2.5-1.5 3.9-1.8.4-.1.8-.2 1.2-.2.5-.1.9-.1 1.1-.1zm1.3-2.9c.1-1.4.7-2.7 2.1-3.5.8-.4 1.6-.5 2.4-.3.9.2 1.2.7 1.1 1.6-.1.6-.4 1.1-.7 1.5-.6.8-1.2 1.6-2.1 2.1-.4.3-.8.5-1.3.6-.6.1-1.1-.1-1.3-.7-.1-.3-.2-.7-.2-1.3zm-1.4-1.7c0 .9-.2 1.7-.7 2.4-.1.2-.2.3-.4.4-.3.3-.7.3-1 0-.3-.3-.4-.6-.5-.9-.2-.7-.3-1.4-.1-2.2.2-.7.7-1.1 1.5-1.1.5 0 .9.2 1 .6.1.1.1.2.1.3 0 .2 0 .3.1.5zM13 10.3c0 .5 0 1-.3 1.4-.2.5-.6.6-1.1.2-.6-.5-.9-1.1-1-1.8v-.7c.1-.6.6-1.1 1.2-1.1.3 0 .6.1.8.4.3.4.4.8.4 1.3v.3zm-2.8 2.9c0 .2-.1.5-.2.7-.1.3-.3.4-.6.3-.1 0-.1 0-.2-.1-.8-.3-1.4-1.4-1.4-2.2 0-.5.4-.9.8-1.1.3-.1.6 0 .9.3.4.4.5 1 .6 1.5.1.3.1.4.1.6z"/></svg>', - vue: '<svg viewBox="0 0 1200 1000"><path d="M600 495.9l159.1-275.4h-84.4L600 349.7l-74.6-129.2h-84.5z"/><path d="M793.7 220.5L600 555.9 406.3 220.5H277l323 559 323-559z"/></svg>', - wasm: '<svg viewBox="0 0 32 32"><path d="M7 7v18h18V7h-7c0 1-1 2-2 2s-2-1-2-2zm5.2 10h1.2l.9 3.45.9-3.45h.9l.9 3.45.9-3.45h1.2l-1.5 6h-1.05l-.9-3.9c-.3 1.41-.5 2.52-.9 3.9H13.7zm7.95 0h1.8l1.5 6H22.1l-.3-1.5h-1.5L20 23h-1.35l1.5-6m1.05 1.2h-.3l-.45 2.25h1.2z"/></svg>', - wat: '<svg viewBox="0 0 32 32"><path d="M13.5 22l-2-8-2 8h-2L5 10h2.1l1.4 7 2-7h2l2 7 1.4-7H18l-2.5 12zM24 10h-4l-2.47 12H20l.5-3h3l.5 3h2.54zm-3.25 7l.75-4.5h1l.75 4.5z"/></svg>', - xml: '<svg viewBox="0 0 32 32"><path d="M9.7 9.6c7.2-.1 12.9 6.2 12.7 12.7h-2.6c-.1-2.8-1-5.1-2.9-7.1s-4.4-2.9-7.1-2.9c-.1-.9-.1-1.8-.1-2.7zm8.6 12.8h-2.6c-.1-.5-.2-1.1-.3-1.6-.8-2.4-2.3-3.8-4.8-4.3-.2-.1-.4-.1-.7-.1-.2 0-.2-.1-.2-.2v-2.5c2.1 0 3.9.7 5.5 2 2 1.8 3 4 3.1 6.7zm-5.1-1.8c0 1-.8 1.8-1.8 1.8s-1.7-.8-1.8-1.8c0-1 .8-1.8 1.8-1.8s1.8.8 1.8 1.8z"/></svg>', - yml: '<svg viewBox="0 0 32 32"><path fill-rule="evenodd" d="M17.1 19.3c-.5 0-.8.1-1.1.1h-1.8c.4-4.3.7-8.5 1.1-12.8 1.2 0 2.2-.1 3.2 0 .3 0 .7.5.6.8-.3 2.3-.8 4.7-1.2 7-.2 1.6-.5 3.2-.8 4.9zm.4 4c.1 1.1-.8 2.1-2.1 2.2-1.3.1-2.5-.7-2.6-1.8-.1-1.2.8-2.1 2.2-2.2 1.4-.1 2.4.6 2.5 1.8z" clip-rule="evenodd"/></svg>', - prolog: - '<svg viewBox="0 0 32 32"><g transform="translate(8 7)"><path d="M14.532 0s-2.227 2.676-6.23 2.676C4.3 2.676 2.08 0 2.08 0S-.194 3.535.013 6.975c.13 2.167.693 4.453 2.783 6.803 1.232 1.386 2.99 2.79 5.507 4.21 6.797-3.83 8.082-7.573 8.29-11.013C16.8 3.535 14.531 0 14.531 0zM2.404 1.886c.39.294.8.559 1.23.792a4.57 4.57 0 00-2.095 1.478c.223-.78.513-1.539.865-2.27zm11.521 9.805c-.547.843-1.258 1.656-2.144 2.445v-1.069h-1.184v2.035c-.522.391-1.09.778-1.703 1.16v-1.734H7.71v1.732a23.887 23.887 0 01-1.7-1.16v-2.033H4.825v1.065a13.957 13.957 0 01-1.144-1.14c-.843-.95-1.399-1.87-1.767-2.747a4.555 4.555 0 004.53 1.106l1.859 1.858 1.858-1.858a4.554 4.554 0 004.53-1.105 8.91 8.91 0 01-.766 1.445zm-6.34-.874a4.5 4.5 0 00.718-.578c.219.216.46.41.717.578l-.717.718-.718-.718zm3.915-.45a3.381 3.381 0 01-3.197-2.293 3.37 3.37 0 110-2.162 3.375 3.375 0 113.197 4.456zm1.474-7.689c.43-.233.84-.498 1.23-.792.353.731.641 1.491.864 2.271a4.576 4.576 0 00-2.094-1.479z"/><circle cx="5.105" cy="6.993" r="1.688"/><circle cx="11.5" cy="6.993" r="1.688"/></g></svg>', - zig: '<svg viewBox="-43 -50 240 240"><g><path d="M46 22L28 44l-9-14z"/><path d="M46 22L33 33l-5 11h-6v51h9l-11 5-8 17H0V22z"/><path d="M31 95l-19 22-8-11zm25-73l6 14-25 8z"/><path d="M56 22h55v22H37l19-12zm60 73l-19 22-7-13z"/><path d="M116 95l-16 9-3 13H42V95z"/><path d="M150 0L52 117 3 140l98-118zm-9 22l-1 18-18 5z"/><path d="M153 22v95h-47l14-12 5-10h6V45h-9l10-9 9-14z"/><path d="M125 95l5 15-24 7z"/></g></svg>', - zip: '<svg viewBox="0 0 1200 1000"><path d="M846.4 813.2H353.6c-8.2 0-15-6.8-15-15v-595c0-8.2 6.8-15 15-15h492.7c8.2 0 15 6.8 15 15v595c.1 8.3-6.7 15-14.9 15z"/><g><path d="M589.5 186.8h20.9v380.3h-20.9z"/><path d="M594.7 210h61.6v20.8h-61.6zm0 43.4h61.6v20.8h-61.6zm0 43.4h61.6v20.8h-61.6zm0 43.4h61.6V361h-61.6zm0 44.1h61.6v20.8h-61.6zm0 43.4h61.6v20.8h-61.6zm0 43.4h61.6v20.8h-61.6zm0 43.4h61.6v20.8h-61.6z"/><path d="M542 230.2h61.6V251H542zm0 43.4h61.6v20.8H542zm0 43.3h61.6v20.8H542zm0 44.2h61.6v20.8H542zm0 43.4h61.6v20.8H542zm0 43.4h61.6v20.8H542zm0 43.4h61.6v20.8H542zm0-304.5h61.6v20.8H542zm0 347.8h61.6v20.8H542zm132.3 160.8c-3.5-26.4-8.8-52.7-13.3-79-.2-1-.5-1.9-.9-2.9-6.7-14.5-24.6-20.7-60-20.5-35.5-.3-53.4 6-60 20.5-.4.9-.8 1.9-.9 2.9-4.5 26.3-9.8 52.6-13.3 79-2.5 18.8 13.7 30.7 41.1 31.8 10.8.4 21.7-.3 32.5 0h1.2c10.8-.2 21.7.5 32.5 0 27.4-1.1 43.6-13 41.1-31.8zM601 666.2h-2c-19.6.1-33.2-9.9-33.6-24.7-.4-15.4 13.8-26.3 34-26v.1h1.2v-.1c20.2-.3 34.4 10.5 34 26-.4 14.8-14 24.8-33.6 24.7z"/></g></svg>', - wgt: '<svg viewBox="0 0 512 512"><path d="M252.245 87.27a2.687 2.687 0 00-1.285.276c-21.947 13.49-53.976 32.266-61.563 55.249-2.373 7.61-1.323 10.427-.029 16.561 2.146 7.381 6.63 17.058 11.62 25.1 3.234 5.208 13.882 18.953 14.685 18.953 14.75-9.362 30.539-20.182 42.413-31.898v-39.379c0-33.305-.35-39.883-2.254-42.6-.715-1.363-2.221-2.241-3.587-2.263zm-68.639 66.305c-.776.016-1.998 2.942-2.717 6.503-1.866 9.233-10.172 42.115-13.864 54.902-2.998 10.381-4.059 21.53-2.322 24.339 1.287 2.082 23.115 9.977 54.349 19.655 15.156 4.696 17.55 4.603 20.603-.761 4.651-8.172 5.375-6.754-23.805-46.602-23.032-31.454-26.088-36.773-29.22-50.842-.885-3.975-2.247-7.21-3.024-7.194zm159.185 9.645a28.373 28.373 0 00-3.745.198c-9.359 1.078-43.192 3.334-56.494 3.774-10.8.357-21.738 2.797-23.874 5.317-1.583 1.867-2.345 25.063-1.898 57.758.217 15.866 1.05 18.113 7.096 19.359 9.209 1.898 8.086 3.028 36.967-37.037 22.797-31.625 26.907-36.174 39.32-43.5 3.506-2.07 6.165-4.365 5.909-5.098-.16-.459-1.452-.732-3.281-.771zm15.326 2.945c-7.971.095-10.326 1.963-15.761 5.089-6.357 4.322-14.182 11.573-20.287 18.805-3.955 4.684-13.727 19.059-13.479 19.822 13.461 11.135 28.628 22.813 43.44 30.485l37.452-12.174c31.675-10.292 37.817-12.657 39.813-15.307 1.076-1.102 1.45-2.805 1.048-4.11a2.72 2.72 0 00-.662-1.137c-19.612-16.704-47.361-41.36-71.564-41.473zM86.727 215.74c-.737 0-1.304.085-1.8.237-1.517.26-2.818 1.426-3.26 2.718-.148.43-.207.87-.139 1.304 6.048 25.042 14.006 61.307 33.52 75.625 6.504 4.608 9.507 4.483 15.74 5.148 7.684.24 18.272-1.038 27.462-3.3 5.953-1.465 22.322-7.34 22.57-8.103-4.346-16.92-9.76-35.286-17.234-50.2l-37.452-12.164C99.41 218.323 90.7 215.75 86.726 215.741zm264.019 25.584c-4.43-.018-25.841 6.256-54.864 16.127-15.022 5.11-16.899 6.594-16.216 12.728 1.04 9.345-.377 8.62 46.652 23.706 37.122 11.908 42.717 14.422 53.52 23.963 3.052 2.696 6.051 4.512 6.67 4.042.618-.47-.11-3.555-1.621-6.858-3.918-8.567-16.53-40.056-21.058-52.57-3.677-10.161-9.365-19.797-12.421-21.05-.142-.057-.367-.087-.662-.088zm-117.978 37.62c-5.473-.013-16.236 3.62-44.092 12.786-37.032 12.186-43.036 13.445-57.383 12.076-4.055-.387-7.553-.091-7.777.652-.224.744 2.181 2.81 5.346 4.595 8.205 4.628 36.906 22.686 47.926 30.15 8.947 6.058 19.222 10.516 22.431 9.733 2.379-.58 16.63-18.9 35.486-45.614 9.15-12.963 9.8-15.272 5.642-19.833-2.573-2.823-3.835-4.536-7.58-4.545zm35.88 11.354c-1.126.034-2.3.43-3.705 1.067-8.567 3.877-8.318 2.302-8.133 51.691.146 38.985-.51 45.09-6.245 58.312-1.62 3.736-2.427 7.147-1.789 7.59.638.442 3.353-1.199 6.028-3.657 6.937-6.373 32.976-28.101 43.48-36.276 8.527-6.636 15.939-15.026 16.186-18.32.183-2.442-12.832-21.66-32.412-47.848-7.126-9.53-10.032-12.663-13.41-12.56zm62.74 10.089c-.052.01-.089.015-.11.029-6.43 16.243-12.843 34.285-15.563 50.743l23.143 31.858c19.576 26.944 23.732 32.054 26.868 33.134 1.38.682 3.112.508 4.23-.277a2.72 2.72 0 00.88-.978c9.826-23.814 24.702-57.83 17.332-80.882-2.554-7.552-5.062-9.217-9.714-13.42-6.075-4.71-15.386-9.897-24.151-13.468-5.5-2.242-21.34-6.882-22.916-6.74zm-106.14 48.5c-9.025.043-17.93.538-26.177 1.788l-23.153 31.859c-19.576 26.944-23.154 32.474-23.212 35.791-.222 1.524.479 3.113 1.571 3.933.364.274.773.465 1.206.534 25.685 1.986 62.628 5.625 82.275-8.508 6.393-4.763 7.204-7.667 9.763-13.39 2.603-7.233 4.658-17.696 5.346-27.135.446-6.115-.092-23.492-.74-23.964-8.718-.547-17.855-.952-26.88-.909z"/></svg>', - illustrator: - '<svg viewBox="0 0 32 32"><path d="M25 8H7v17h18V8zm-7.6 12.3h-1c-.2 0-.2 0-.3-.2-.2-.7-.5-1.5-.7-2.2 0-.1-.1-.2-.3-.2H13c-.2 0-.2.1-.3.2-.2.7-.4 1.5-.6 2.2 0 .1-.1.2-.2.2h-1.1c-.2 0-.2-.1-.2-.2.4-1.3.7-2.6 1.1-3.9.4-1.5.9-3.1 1.3-4.6.1-.2.1-.3.3-.2h1.5c.1 0 .2 0 .2.2.5 1.5.9 3.1 1.4 4.6l1.2 3.9c.1.2.1.2-.2.2zm3-.5c0 .5 0 .5-.5.5h-.7c-.2 0-.2 0-.2-.2v-6.5c0-.2.1-.3.2-.2h.9c.2 0 .2.1.2.2.1 2.1.1 4.2.1 6.2zm-.7-7.1c-.4 0-.8-.3-.8-.7 0-.4.3-.8.8-.8.4 0 .8.3.8.7 0 .5-.3.8-.8.8z"/><path d="M14.2 13.3c0-.1-.1-.1-.2 0 0 .1-.1.2-.1.3-.2.9-.4 1.8-.7 2.6 0 .1 0 .2.1.2h1.4c.2 0 .2-.1.1-.2-.1-1-.3-2-.6-2.9z"/></svg>', - photoshop: - '<svg viewBox="0 0 32 32"><path d="M25 7.4V7H7v18h17.5c.4 0 .5-.1.5-.5V7.4zm-10.6 9.7c-.8.2-1.4.2-2.4.3V21h-1.8c-.1 0-.2-.3-.2-.5V11c0-.1 1-.2 1.5-.2.9 0 1.8 0 2.6.1 1.7.2 2.6 1.3 2.7 2.8.1 1.7-.8 3-2.4 3.4zm7.7 2c-.1.9-.6 1.5-1.4 1.8-1.2.5-2.4.4-3.6-.1-.1 0-.2-.2-.2-.3.1-.4.2-.8.3-1.1.7.1 1.4.3 2 .4.4.1.8-.1.9-.6.1-.4-.1-.7-.6-1-.3-.2-.7-.3-1-.4-1.1-.5-1.6-1.2-1.5-2.3.1-.9.8-1.6 1.9-1.9.9-.2 1.8-.1 2.6.2.1 0 .3.3.2.4-.1.4-.2.7-.3 1.1-.5-.1-1-.2-1.4-.3-.2 0-.5 0-.7.1-.5.2-.6.8-.2 1.1.2.2.4.2.7.4.3.2.7.3 1.1.5.8.3 1.2 1 1.2 2z"/><path d="M13.9 12.5c-.6-.1-.9-.1-1.9-.2v3.4c1 .1 1.4.1 2.1-.2.7-.3.8-1 .8-1.6 0-.7-.4-1.2-1-1.4z"/></svg>', - pdf: '<svg viewBox="0 0 32 32"><path d="M7 22.9c.1-.6.5-1 .9-1.4.5-.5 1.1-.8 1.8-1.2.7-.4 1.4-.7 2.1-1 .1 0 .2-.1.2-.2.6-1.2 1.2-2.4 1.7-3.6.3-.7.5-1.4.8-2.1v-.1c-.3-.7-.6-1.5-.7-2.3-.2-.8-.2-1.6-.1-2.4.1-.5.4-.9.8-1.3.1-.1.3-.1.5-.1h.8c.2 0 .4.1.5.3.3.2.5.5.7.8.2.4.2.8.3 1.2 0 1.2-.2 2.3-.4 3.4-.1.4-.2.7-.3 1.1v.1c.6 1.1 1.4 2.1 2.2 3 .1.1.1.1.3.1 1.1-.2 2.2-.2 3.2-.2.6 0 1.3.1 1.9.4.3.2.6.4.8.7.1.2.2.4.2.6v.7c0 .2-.1.4-.3.5-.2.2-.4.5-.8.5-.2 0-.5.1-.7.1-1.6.1-2.9-.4-4.2-1.3-.2-.2-.5-.4-.7-.6-.1 0-.1-.1-.2-.1-.6.1-1.2.2-1.8.4-.8.2-1.6.5-2.4.7-.1 0-.1.1-.2.1-.5.9-1.1 1.8-1.7 2.6-.5.6-1.1 1.2-1.7 1.7-.3.2-.7.4-1.1.5h-.8c-.2 0-.3 0-.5-.1-.5-.2-.9-.6-1-1.1-.1 0-.1-.2-.1-.4zm8.8-7c-.3.8-.7 1.6-1 2.4l2.4-.6c-.5-.6-1-1.3-1.4-1.8zm4.3 2.6c.6.4 1.3.7 2 .9.3.1.5 0 .7-.1.2-.1.3-.4.1-.5 0-.1-.1-.1-.2-.1-.2-.1-.5-.1-.8-.2-.6-.1-1.2-.1-1.8 0zm-9.4 2.8s-.1 0 0 0c-.6.3-1.2.7-1.7 1.1-.3.2-.5.5-.7.8v.2c.1.1.1.1.2.1.3-.2.5-.4.7-.5.6-.5 1-1.1 1.5-1.7zM15 11.2c.1 0 .1 0 0 0 .2-.6.3-1.2.3-1.7 0-.3 0-.6-.1-.9 0-.1-.1-.1-.2-.1s-.1.1-.2.1c-.2.3-.2.6-.2 1 0 .3 0 .5.1.8.2.2.2.5.3.8z"/></svg>', - font: '<svg viewBox="0 0 32 32"><path d="M21.1 18.3h-3.3l-.4.9c-.1.3-.2.5-.2.7 0 .3.1.5.3.6.1.1.4.1.9.2v.3h-3.1v-.3c.3-.1.6-.2.8-.4s.5-.7.8-1.4l3.3-7.4h.1l3.3 7.6c.3.7.6 1.2.8 1.4.2.1.4.2.7.2v.3h-4.5v-.3h.4c.4 0 .6-.1.8-.2.1-.1.2-.2.2-.3v-.3s-.1-.2-.2-.5l-.7-1.1zm-.2-.6l-1.4-3.2-1.4 3.2h2.8z" opacity=".6"/><path d="M6.7 22.4c.5 0 .9-.3 1.2-.7.2-.3.5-.8.8-1.7l4.4-10.9h.6l4.5 10.5c.5 1.2.9 1.9 1.1 2.3s.6.5 1.1.5v.5h-6.5v-.5c.7 0 1.1-.1 1.3-.2.2-.1.3-.3.3-.6 0-.2-.1-.4-.2-.7-.1-.2-.2-.4-.3-.7l-.5-1.2H10c-.3.8-.5 1.3-.6 1.6-.2.5-.3.9-.3 1.1 0 .3.2.5.6.6.2.1.6.1 1 .1v.5h-4v-.5zm7.5-4.2l-1.9-4.6h-.2l-1.8 4.6h3.9z"/></svg>', - image: - '<svg viewBox="0 0 32 32"><path d="M21.3 17.2c1 0 1.8-.8 1.8-1.8s-.8-1.8-1.8-1.8-1.8.8-1.8 1.8.8 1.8 1.8 1.8zm-11.1-5.5v12.4h15.3V11.7H10.2zm.7.7h13.9v10.8l-3.6-4.1-2.2 2.6-4.4-4.7-3.7 4.6v-9.2zm9.8-4.5H6.5v10.8h1.9V9.6h12.3V7.9z"/></svg>', - svg: '<svg viewBox="0 0 32 32"><path d="M11.5 11.4H17c0-2-2.3-4.9-5.1-4.9s-5.3 2.4-5.3 5.2 2.9 5.2 4.9 5.2v-5.5z" opacity=".5"/><path d="M13.6 13.7h11.8v11.8H13.6z"/></svg>', - sublime: - '<svg viewBox="0 0 32 32"><path d="M25 15.4v-.5c-.2-1.2-.6-2.4-1.2-3.5-.6-.9-1.3-1.7-2.1-2.4-.7-.6-1.4-1-2.2-1.3-2.6-1-5.2-.9-7.7.4-1.4.8-2.5 1.8-3.4 3.2-.9 1.4-1.4 2.8-1.4 4.5v1.1c.2 1.5.6 2.8 1.4 4.1.7 1 1.5 1.9 2.6 2.6.6.4 1.3.8 2.1 1 1.3.4 2.7.6 4 .4 3.3-.5 5.7-2.3 7.1-5.3.7-1.4.9-2.8.8-4.3zm-6.8 4.8c-.8.4-1.6.4-2.4.4-1.2 0-2.2-.4-3.2-1-.2-.1-.2-.2-.1-.3l.6-1.2c.1-.1.1-.1.2-.1.8.6 1.7.9 2.7 1 .3 0 .6 0 .9-.1.4-.1.6-.4.7-.7 0-.3-.1-.6-.5-.8-.6-.3-1.2-.5-1.8-.7-.7-.2-1.5-.4-2-1-.4-.4-.5-1-.5-1.6.1-1.6 1.2-2.4 2.5-2.6 1.4-.2 2.6.1 3.7.8.1.1.1.2.1.3-.2.4-.4.7-.6 1.1-.1.2-.1.1-.3.1-.8-.5-1.6-.8-2.6-.7-.2 0-.4.1-.6.1-.3.2-.5.4-.5.8 0 .3.1.6.4.8.3.2.6.3.9.3.6.2 1.2.3 1.9.5.1-.1.2-.1.4-.1-.1 0-.3 0-.4.1.2.1.5.2.7.3 0 0 .1 0 .1.1 0 0 .1 0 .1.1.1.1.2.1.2.2l.1.1c.9.8 1 3-.7 3.8z"/></svg>', - 'code-search': - '<svg viewBox="0 0 32 32"><g class="layer"><path d="M18.381 5.225c-1.371 0-2.714.4-3.866 1.153a7.18 7.18 0 00-2.628 3.093 7.282 7.282 0 00-.547 4.04 7.241 7.241 0 001.709 3.694l-6.963 7.999.966.873 6.946-7.964a7.08 7.08 0 003.055 1.402 7.038 7.038 0 003.35-.17 7.1 7.1 0 002.901-1.703 7.214 7.214 0 001.809-2.858 7.285 7.285 0 00-.936-6.53 7.143 7.143 0 00-2.536-2.22 7.05 7.05 0 00-3.26-.8v-.009zm0 13.098a5.775 5.775 0 01-3.235-.993A5.88 5.88 0 0113 14.685a5.96 5.96 0 01-.331-3.406 5.916 5.916 0 011.594-3.018 5.803 5.803 0 012.982-1.613 5.76 5.76 0 013.365.336 5.84 5.84 0 012.614 2.17c.64.97.982 2.11.982 3.275a5.93 5.93 0 01-1.706 4.168 5.79 5.79 0 01-4.119 1.726z"/><path d="M18.404 6.514c-1.138 0-2.251.33-3.207.95a5.93 5.93 0 00-2.179 2.55 5.974 5.974 0 00.963 6.379l-5.774 6.595.801.72 5.76-6.566a5.869 5.869 0 007.717-.389 5.944 5.944 0 001.5-2.357 5.975 5.975 0 00-.775-5.384 5.914 5.914 0 00-2.103-1.832 5.874 5.874 0 00-2.703-.659v-.007zm0 10.8c-.956 0-1.89-.285-2.684-.819a4.854 4.854 0 01-1.779-2.18 4.888 4.888 0 011.047-5.297 4.802 4.802 0 015.264-1.054c.883.368 1.637.99 2.168 1.79a4.882 4.882 0 01-.601 6.137 4.815 4.815 0 01-3.415 1.423z"/><path stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" d="M5.64 24.78l7.88-8.967 2.261 1.988-7.88 8.967z"/></g></svg>', - shell: - '<svg viewBox="0 0 32 32"><path d="M14.42 9.31c-.26.1-.67.3-.91.44-.14.08-.26.17-.38.26-.22.17-.54.49-.71.71-.08.1-.15.2-.22.3-.15.23-.36.64-.43.91-.04.14-.07.29-.09.44-.04.28-.04.74-.01 1.01.02.22.06.43.12.64.07.27.26.69.41.92.07.1.14.2.22.3.17.22.51.52.74.68.15.11.31.23.48.34.23.16.63.36.89.47.25.11.51.23.78.34.26.1.69.23.94.35a.3.3 0 01.08.04c.67.2 1.16.58 1.46 1.11.06.11.2.42.2.7 0 .12.07.48-.05.72-.57 1.16-1.27 1.14-2.35 1.1-.97-.22-1.35-.8-1.64-1.68-.01-.04-.02-.08-.02-.12-.05-.28-.27-.51-.55-.51h-1.61c-.28 0-.5.23-.49.51.02.33.07.65.14.94.06.27.23.7.36.95.1.18.21.35.33.51.18.22.54.49.76.65.14.1.29.2.45.29.24.14.66.31.92.41.08.03.16.05.24.07.27.06.5.28.5.56v.81c0 .28.22.51.5.51h1.11c.28 0 .5-.23.5-.51v-.81c0-.28.22-.54.49-.61.13-.03.24-.07.35-.11.26-.1.67-.28.91-.43.55-.34.93-.77 1.29-1.27.16-.23.39-.62.46-.89.05-.17.08-.35.1-.54.03-.28.03-.74 0-1.02-.02-.19-.05-.37-.1-.54a3.83 3.83 0 00-.42-.92c-.38-.6-.92-1.02-1.46-1.4-.23-.16-.62-.39-.87-.51-.61-.28-1.18-.46-1.8-.71-.26-.1-.68-.26-.89-.44-.16-.13-.45-.4-.6-.64a1.41 1.41 0 01-.17-.62c0-.06-.02-.35.03-.62.02-.12.15-.42.31-.65.03-.04.21-.27.47-.34.1-.03.4-.11.68-.12.17-.01.54-.03.82.03.12.02.42.16.64.33.1.08.34.31.46.56.07.16.19.52.2.8v.01c.02.28.23.51.51.51h1.61c.28 0 .51-.23.48-.51-.02-.25-.06-.5-.12-.74-.07-.27-.24-.7-.35-.95a3.55 3.55 0 00-.23-.43c-.14-.24-.41-.61-.62-.8-.11-.1-.22-.19-.34-.28-.23-.16-.63-.37-.87-.51-.09-.05-.18-.09-.28-.13-.26-.1-.49-.36-.49-.64V7.52c0-.28-.22-.51-.5-.51h-1.11c-.28 0-.5.23-.5.51v1.12c0 .28-.2.44-.45.56-.1.05-.21.08-.31.11z"/></svg>', - video: - '<svg viewBox="0 0 32 32"><path d="M16 25c-4.9 0-9.1-4.1-9-9.2C7.1 11 11 7 16.1 7c4.9 0 9 4.1 8.9 9.2-.1 4.8-4.1 8.8-9 8.8zm-3.2-14.6v11.1h.1l8.1-5.4c.1-.1.1-.1 0-.1-2.7-1.8-5.4-3.6-8.2-5.4.1-.1.1-.2 0-.2z"/></svg>', - audio: - '<svg viewBox="0 0 32 32"><path d="M16.3 23.8c-.2 0-.4-.2-.6-.3-1.5-1.3-3-2.6-4.6-3.9-.1-.1-.1-.1-.2-.1H6.7c-.4 0-.6-.2-.7-.5v-5.7c0-.5.3-.8.8-.8H11c.1 0 .2 0 .2-.1 1.5-1.3 3.1-2.7 4.6-4 .4-.3.8-.3 1.1.1.1.1.1.3.1.4V23c0 .3-.1.6-.4.7-.1 0-.1 0-.2.1h-.1zm9.7-7.7c0 .3 0 .6-.1.9-.1 1.2-.4 2.4-.9 3.6-.4 1-.9 1.9-1.6 2.7-.1.2-.3.3-.6.4-.3 0-.5-.1-.7-.3-.2-.2-.2-.5 0-.7.1-.2.3-.4.4-.6 1-1.4 1.6-2.9 1.8-4.5.4-3-.3-5.7-2.2-8.1-.2-.3-.3-.6 0-.9.3-.4.8-.4 1.2 0 .7.9 1.3 1.8 1.7 2.9.5 1.2.8 2.5.9 3.8v.7c.1 0 .1.1.1.1z"/><path d="M23.3 15.9c0 2.1-.6 3.9-1.7 5.5-.1.2-.3.3-.6.4-.3 0-.5-.1-.7-.3-.2-.2-.2-.5 0-.8 0-.1.1-.1.1-.2.8-1.1 1.2-2.2 1.4-3.5.3-2.1-.2-4-1.5-5.8-.1-.2-.2-.4-.2-.6.1-.3.2-.5.5-.6.3-.1.6 0 .8.3.3.4.6.9.9 1.4.5 1.1.9 2.3.9 3.5.1.4.1.6.1.7z"/><path d="M20.5 16c0 1.2-.3 2.4-1 3.4-.2.4-.6.5-1 .3-.3-.2-.5-.6-.2-1 .4-.6.6-1.3.7-2 .2-1.2-.1-2.4-.7-3.4-.2-.4-.1-.8.2-1 .3-.2.8-.1 1 .2.4.6.6 1.2.8 1.9.1.6.2 1.1.2 1.6z"/></svg>', - windows: - '<svg preserveAspectRatio="xMidYMid" viewBox="0 0 32 32"><path d="M6 8.81l8.173-1.114.004 7.884-8.17.047L6 8.81zm8.17 7.68l.006 7.89-8.17-1.124v-6.82l8.163.053zm.99-8.94l10.837-1.58v9.51l-10.837.086V7.55zM26 16.564l-.003 9.468L15.16 24.5l-.015-7.955L26 16.563z"/></svg>', - jenkins: - '<svg viewBox="0 0 1200 1000"><path d="M637.9 394c1.9 0 3.7-.2 5.6-.3 21.2-1.1 39.2-10.7 56.4-22 1.1-.7 1.9-2.3 2.4-3.6 1.1-3 1.6-6.2 2.8-9.2 2.7-6.6.5-11.2-4.6-16-15.2-14.3-28.3-30.5-39.2-48.2-3.4-5.5-5.4-11.9-8.3-17.8-.8-1.6-2.8-2.7-4.2-4-.5 1.6-1.5 3.2-1.5 4.8 0 2.7.4 5.4 1 8 3.1 15.1 11.2 27.8 20.6 39.7 6.4 8.1 13 16 19.9 23.7 6 6.7 4.5 18.4-4.6 21.3-5.1 1.6-9.8 4.6-14.8 6.7-8.9 3.7-17.7 7.6-27.7 7.4-7.7-.2-10.8-2.5-12.7-9.8-.7-2.8-1.5-5.5-2.4-8.5-5.1 5.8-5.3 12.8-2 21.2 2.6 6.6 7.8 6.7 13.3 6.6zm-47.5 21.7c6.2 6.9 14.2 10.6 22.9 13.3 14.2 4.3 28.7 6 44 5 0-4.2-.1-7.7 0-11.3.1-4.7-1.8-6.3-6.7-6.4-12.5-.2-25.1-.5-37.5-1.8-9.1-1-17.9-3.7-27.5-5.7 1.6 2.4 3 4.9 4.8 6.9zM573.1 305c-4.7-.4-7.7 2.2-6.1 6.7.9 2.4 3.1 5.1 5.4 6.2 9.6 4.3 19.8 5.4 29.6 1.4 11.8-4.7 12.4-14.3 9.7-24.5-2.6-10.2-18.8-32-22.6-30.5-6.4 3.3 9.4 34 7.3 39.6-.2 3.3-15.6 1.8-23.3 1.1zm-30-43.9c.9-1.9 1.7-3.5 2.5-5.1 8.3-15.7 20.9-28.6 42.5-24.5 3.5.7 4.6-1 4.8-4 .3-4.7-4-9.6-9.7-10.8-8.5-1.9-16.1.4-23.1 5.2-11.2 7.7-20.1 17-21.7 31.3-.2 3.2-.2 6.5 4.7 7.9zm123.1 154.1c-1 .1-2.4 2-2.5 3.1-.3 4.7-.1 9.4-.1 14.3 20.9.7 38.8-14.8 47.5-35.2-1.2.3-2.2.4-3 .8-13.4 6.9-26.3 15.2-41.9 17zm32-101.9c10.2 1.2 18.9-2.2 26.4-9 2.6-2.3 2.7-4.4 1-7.5-4.4-8-12.7-34.6-17.3-33.5s.8 17.8 4.2 25.9c3.3 7.8 2.6 9-6 9.7-2.4.2-15.5-2.3-17.3 2.1-2 4.5 2.6 11.5 9 12.3z"/><path d="M827 655.2c-7.8-26.9-23.9-34.2-50.6-27.9-11.4 2.7-22.2 8.1-33.3 12.3-1.7.6-3.4 1.3-6 2.4 1.1-3.1 1.8-5.3 2.6-7.5 11.8-35.5 23.7-70.9 35.4-106.4 5.2-15.6 1.7-28.6-11.6-38.7-7.8-6-15.3-12.3-22.9-18.6-2.9-2.4-5.8-4.8-8.4-7.4-9.4-9.2-9.7-10.8-3.1-22 12.9-22.2 19.1-46.6 23.3-71.5 4.9-28.6 7.4-57.5 6.2-86.6-1.3-33-8.2-64.5-28.3-91.7-26.4-35.6-61-57.4-105.5-62.4-3.2-.4-6.3-.8-9.5-1.2h-22.4c-8.7 1.3-17.4 2.5-26 3.9-31.6 5.4-60.6 17.8-87.8 34.5-4 2.5-8 5.1-12 7.5-15.1 9.2-26.1 21.8-32.3 38.6-1 2.7-3.4 5.3-5.9 7-14.6 9.8-20.3 24.3-20.9 40.8-.6 13.9.6 27.8.6 41.7 0 2.8-1.4 5.7-2.3 8.4-2.4 6.8-6.1 13.4-7 20.4-3.2 25.2 2.8 48.1 20.1 67.3 6.1 6.8 14.4 10.6 23.1 13.3 3.3 1 5.1 2.6 5.6 6.1 1.8 11.9 6.4 22.7 13.2 32.7 1.7 2.6 3 5.8 3.5 8.8.9 5.2-1 8.9-6.1 12-23.3 14.1-46.4 28.7-69.5 43.1-2.3 1.4-4.7 2.6-7.3 3.5-8.9 3.1-16.1 7.8-18.9 17.4v7.1c8.6 23.3 17.9 46.3 25.5 69.8 9 27.5 12.3 56.1 14.1 84.9.9 13.9 1.3 27.7 1.8 41.6.2 6.7 3.6 11.4 9.3 13.9 20.4 9.1 40.8 18.1 61.3 26.8 11.2 4.7 23 6.9 35.2 6 3.4-.2 4.5 1 5.5 4.2 7.3 23.2 14.9 46.3 22.3 69.5 1 3.1 2.6 4.7 5.9 5.3 13.2 2.2 26.3 4.5 39.4 6.8 1.5.3 2.9.6 4.4.9h41.7c7.6-.7 15.2-1 22.7-2.2 7.4-1.2 15-2.8 22-5.4 8.2-3.1 11.5-9.6 10.2-18.7-1.4-10.2-1.1-10.2 8.7-12.8 18.1-4.8 22-11.3 18.2-29.4-2.2-10.8-4-21.6-5.9-32.4-.4-2.5-.2-5.1-.2-7.6 0-3.6 1.4-5.8 5.1-6.9 4.1-1.2 6.7-4.3 7.6-8.7.3-1.4 1.4-3.2 2.6-3.8 10.7-4.9 22-6.4 33.7-5.3.8.1 2 .4 2.2.9 2.9 8.1 10.3 8.3 16.8 8.7 10.4.7 21 1.1 31.3.1 17.5-1.7 25-14.4 29.4-29.5 1.3-4.5 2.1-9.2 3.1-13.8v-12.2c-3.1-12.5-6.3-25.1-9.9-37.6zM480.5 463.5c-7.7-16-14.3-32.4-17.5-50.1-.9-5.1.4-8.8 3.9-12.4 2.3-2.4 4.7-5 6.1-7.9.8-1.8.1-4.6-.8-6.6-.3-.6-3.7-.2-5.4.5-2.3.9-4.4 2.5-6.5 3.9-9.2 6.4-16.8 6.7-26.1.4-11.9-8-17.9-19.9-21.4-33.4-3-11.5-2.7-22.6 4.4-32.6 7.3-10.3 17.3-15.6 30.1-14 8.2 1 13.2 6.6 16.3 13.7 2 4.5 3.2 9.3 4.4 14 .7 2.8 2 4 4.9 3.6 3.7-.5 7.5-.5 11.1-1.4 8-2 10-5.5 8.2-13.7-1.8-7.9-4-15.8-5.5-23.7-2.1-10.7-.1-21.2 1.8-31.7 2.2-11.8 4.4-23.6 5.4-35.6.5-6.2-1.9-12.6-2.7-18.9-.3-2.4-.3-5.4.8-7.4 7.1-13.7 17.8-24.4 30.3-32.9 14.2-9.7 29-18.6 44.2-26.6 14.7-7.8 31.1-7.8 47.3-6.2 22.2 2.2 43.3 8.9 63.2 19.1 13.3 6.8 23.1 17.5 32.4 28.8 4.6 5.6 8.9 11.4 14.1 18-10.4-1.2-20-2-26.4 6.6-2.2 3-2.9 7.1-3.6 11.3 10-6.4 19.8-5.9 29.5-1.1 9.3 4.5 16.6 11.2 20 21.2 1.9 5.7 3.5 11.8 4 17.8 2.4 24.7 3.9 49.4 1.4 74.1-3.4 32.4-11 63.8-28.4 91.8-7.5 12.1-15.4 24.7-25.7 34.2-13.8 12.8-31.5 19.8-50.1 24.3-14.1 3.4-27.9 3.7-41.6-.8-15.2-5-28.9-12.9-41-23.7-14.1-12.6-25-27.9-36.1-43-.5-.7-1-1.3-1.6-2.1-.9 4.5.8 11.1 3.9 16.8 7.9 14.2 19.1 25.8 30.6 37 5.5 5.4 11.8 10 18.5 15.5-4.7 0-54.8 4.3-67.6 1.1-14.6-3.5-22.6-15.1-28.8-27.9zm134.4 107c13.5 12.4 33.1 52.6 40.2 69.9-6.4-1.8-12.3-2.9-17.8-5.1-17.9-7.2-35.5-14.7-53.3-22.1-2.9-1.2-3.6-3.3-2.3-5.6 3.6-6.4 6.7-13.4 11.6-18.7 6.3-6.9 14.2-12.3 21.6-18.4zm37.7 33.1c-6.1-12.4-13.1-24.3-19.6-36.5-1-1.8-2.1-4.4-1.5-6 1.1-2.6 2.8-5.1 7-4 2.2.6 5.3-.8 7.6-2 6.1-3.3 11.3-2.4 16.9 1.7 4 2.9 8.8 4.7 14 7.3.3 15.7-2.1 65.6-8.6 74.7-5.3-12.1-10.1-23.8-15.8-35.2zM636.1 850c-19.9 2.4-39.8 1.8-59.5-1.6-7.5-1.3-14.9-3.1-22.2-5-1.6-.4-3.6-2-4-3.5-6.3-23.4-13.4-46.7-18.2-70.4-5.2-25.5-8.3-51.5-12.2-77.3-.2-1.3-.2-2.7-.3-4.8 7.4-1.3 14.4-2.8 21.4-3.8 27.6-3.9 55.3-6.3 83.2-4.8 8.3.4 16.6 1.9 24.9 2.8 2.7.3 3.1 1.9 3.3 4 1 15.5 2.2 30.9 3.1 46.4 1.7 29.4 3.1 58.9 4.9 88.3.5 8 2 15.9 3.2 24.8-9.2 1.7-18.3 3.8-27.6 4.9zm55.4-31.6c-4.7 1.1-9.5 2.1-15.2 3.4-.9-19.8-1.7-38.6-2.6-57.7 5.3-1.3 9.4-2.5 13.5-3.1 1.3-.2 3.9 1.2 4 2.1 2.7 14.9 5.5 29.9 7.4 44.9 1.1 8.9 1.2 8.5-7.1 10.4zm-10-180.9c-.1.2-.6.3-.3.2 2.2-18 4.6-36.3 6.7-54.5.6-5 .8-10.1.8-15.2-.1-4 2.3-5.3 5.4-6.1 8.7-2.2 20.5 2.8 25.1 10.6.6 1 .8 3 .2 4-12.6 20.4-25.2 40.7-37.9 61zm110 90.2c-7.2.3-14.3.9-21.4-.7-.1-.5-.1-1.1-.2-1.6 8.1-1.8 16.1-3.6 24.2-5.4 0-.4 0-.7.1-1.1-2.9-.5-5.8-1.5-8.6-1.5-9.8.2-19.5.7-29.3 1.1-5.9.2-5.7 0-6.5-5.9-2-15.1-4.3-30.1-6.3-45.1-.2-1.2.8-3.4 1.9-3.9 7.2-3.5 14.6-6.8 21.9-10 4.8-2.1 10-3.6 14.6-6 9.5-4.9 20.4-1.9 23.7 8.3 4.4 13.7 8.8 27.8 10.6 42 1.7 15.2-8 29.1-24.7 29.8z"/><path d="M710.4 223.7s12.9 2.2 24.7 20.6 12.3 50.9 12.3 50.9.5 28.9-3.1 58.1c-8.7 67.3-61.4 122.8-61.4 122.8l35.7-29.9 25.7-51.3 9.2-60.6v-60.6l-8.4-50.2-32-7.8-2.7 8z"/></svg>', - babel: - '<svg viewBox="0 0 32 32"><path d="M22.36 12.38l1.876-1.687A4.99 4.99 0 0025 8.023v-.211c0-.211-.07-.422-.139-.563-.347-.703-.973-1.195-1.737-1.476-.695-.492-1.946-.703-3.753-.773-2.016.281-3.962.773-5.769 1.546-.695.492-1.46.984-2.224 1.406v.14c.07 0 .14-.07.209-.07s.139 0 .139.07l.139-.07h.07v.07s-.07.141-.348.282c-.278.14-.695.492-1.251.914l.208.14-.139-.07c0 .07-.07.07-.208.07v.07l.139.211c-.07 0-.14 0-.209-.07-.417.07-.764.351-.973.703v.281c.14-.14.278-.281.487-.422v.211h-.07l-.139.07v.07l.14.212v.07a.97.97 0 01.208-.281l.208-.211.14-.14.138-.141.07-.07.347-.211c.209.07.278.14.278.21h.14c1.042-.773 2.154-1.405 3.335-1.827v.14c-.07.141-.208.282-.278.352s-.07.07-.139.07c0 .07.07.211.14.281-.418 1.336-.904 2.601-1.53 3.796A97.162 97.162 0 017 25.032c0 .07.07.14.07.21l.208-.07c.208-.07.347-.14.486-.21h.07v.14h.139l.139-.07h.139v.281c-.07.14-.139.352-.209.492-.208.352-.417.703-.486 1.125V27h.208l.209-.281c.486-.562.903-1.125 1.181-1.757l.695-.211c.487-.14.904-.281 1.251-.422l.14-.07c.694-.281 1.39-.563 2.084-.914.765 0 1.599-.281 2.224-.773v-.07l-.347.14h-.07v-.14c.556-.07 1.043-.211 1.46-.492a130.306 130.306 0 013.127-2.32c2.155-1.617 3.197-3.163 3.128-4.639-.348-.562-.765-1.124-1.251-1.546l-.209-.281c0-.14.278-.422.973-.844zm-3.337 5.342l-1.946 1.546c-.764.492-1.529.984-2.293 1.406a20.566 20.566 0 01-3.962 1.898c-.07 0-.208.07-.278.07h-.07c.07-.281 1.113-2.32 3.059-6.255a15.72 15.72 0 004.03-1.195l.487-.07c.765-.141 1.53.07 2.085.562v.28c-.347.985-.695 1.547-1.112 1.758zm1.182-6.396a7.49 7.49 0 01-1.668 1.265c-1.112.351-2.224.773-3.267 1.336-.07 0-.07 0-.139-.07h-.208v-.141c0-.352.139-.774.347-1.055.14-.773.278-1.265.487-1.335l1.598-3.585c0-.21.348-.422 1.043-.492h.208v.211c.695-.14 1.112-.14 1.251-.14 1.182-.141 1.807.14 1.946.632v.14h.14v-.491h.138c.278.14.487.351.556.632v.14c0 .282-.139.563-.347.774-.07 0-.14-.07-.14-.21h-.138v.42c-.626.985-1.112 1.477-1.39 1.477a4.194 4.194 0 01-.417.492z"/></svg>', - bower: - '<svg viewBox="0 0 32 32"><path d="M25.1 15.5c-.3-.1-.6-.3-1-.4-1.8-.5-3.6-.7-5.4-1-.3 0-.6-.1-1-.1.1-.5.3-.7 1-.8.1.1.1.3.2.4 0 .1.1.2.2.1h.7c1.2-.2 2-.8 2.5-2 .1-.4.2-.8.3-1.1.1-.8.4-1.6 1-2.2l.2-.2c-1.4-.4-3.9.5-4.9 2.6-.2-.1-.5-.1-.7-.2-.1 0-.2-.1-.2-.2-.4-1.1-1.1-2-2.2-2.7-.8-.5-1.9-.6-2.8-.5-2.1.3-3.8 1.3-5.1 2.9S6 13.7 6.1 15.7c.1 2.1.8 4.1 2 5.9.4.6 1.1 1.2 1.6 1.7.7.4 1.6.4 2.2-.2.1-.1.2-.3.3-.4 0 .1.1.1.1.2.2.4.3 1 .5 1.3.2.4.9.7 1.4.5.1-.1.2-.1.3 0 .4.2.8.2 1.2 0 .2-.1.3-.3.5-.3.2-.1.4 0 .6 0 .5-.1 1-.3 1-1 0 0 0-.1.1-.1.2-.1.4-.3.4-.5.1-.3.1-.6 0-1-.3-.5-.6-1.2-1-1.7l-.1-.1c.3.1.6.2 1 .3.5.1 1 .1 1.4-.3.1 0 .1.1.2.1.8.5 1.9.3 2.5-.4h.2c.6.1 1.1 0 1.6-.4.2-.2.4-.4.4-.7v-.1c1-.1 1.5-.5 1.5-1.5-.1-.7-.3-1.2-.9-1.5zm-4.4-2.7c-.4.2-.8.3-1.4.3 0 0-.1 0-.1-.1-.1-.2-.1-.4-.2-.6 0-.1 0-.1.1-.1.3 0 .4 0 .4.4.2-.3.2-.3.5-.2.2.1.4.1.6.2.2.1.2.1.1.1zm-1.3-2.1c.4-.7 1-1.2 1.5-1.6.5-.3 1-.5 1.6-.5-.1.1-.2.2-.3.4-.3.4-.3 1-.4 1.4-.1.5-.2 1-.4 1.5 0 .2-.2.3-.2.4-.3-.3-.6-.5-1-.8v-.2c.4-.7.8-1.5 1.5-2-1 .4-1.4 1.1-1.9 2-.2-.1-.3-.2-.5-.3 0-.1.1-.2.1-.3zm-2.7 1.7c0-.5.1-1 .4-1.4 0-.1.2-.1.2-.1 1 .1 1.8.4 2.6 1 .2.1.3.3.5.4-.2-.1-.5-.1-.7-.2-.5-.1-1.1-.1-1.6.1-.4.3-.9.3-1.4.2.3.3.6.3 1 .2.3 0 .5-.1.8-.2 0 .1-.1.2-.1.2-.4.3-1 .5-1.5.7h-.1c-.1-.3-.1-.6-.1-.9zm-3-2.4c.9 0 1.8.8 1.8 1.8s-.8 1.8-1.8 1.8-1.8-.8-1.8-1.8c0-1.1.8-1.8 1.8-1.8zm4.6 6.1c.4.1 1 .2 1.4.2.6.1 1.1.2 1.8.3.2 0 .3.1.1.3-.2.3-.7.5-1.1.4h-.2c.1.2 0 .5-.2.6-.3.3-.6.4-1 .4-.2 0-.5-.1-.7-.1-.1.6-1.2.8-1.9.3.1.3.2.6.3 1v.3c-.2 1.5-1.4 2.6-2.9 2.7-1.4.1-2.8-.3-4-1.2-1.1-.7-1.9-1.7-2.4-2.8 0-.1-.1-.1-.1-.2.4.1.8.2 1.1.3.7.1 1.4.1 2.1-.4h.2c.7.2 1.4.3 2.2.2 1.1-.2 1.9-.8 2.7-1.7.3-.3.5-.7.7-1.1.2-.3.4-.5.6-.7h.2c.8.1 1.6.2 2.5.3 1.1.2 2.1.4 3.3.6 0 0 .1 0 .1.1-1.5.1-3.2.3-4.8.2zm-4.6-3.3c.6 0 1.1-.4 1.1-1s-.5-1-1.1-1c-.6 0-1.1.5-1.1 1s.4 1 1.1 1zm-.6-1.8c.1-.1.3-.1.5-.2.2.1.3.1.5.2s.2.3 0 .5-.7.2-1.1 0c-.1-.2-.1-.4.1-.5z"/></svg>', - docker: - '<svg viewBox="0 0 32 32"><g><path d="M14.5 8.6h2v2h-2zm0 2.3h2v2h-2zm0 2.4h2v2h-2zm-2.3-2.4h2v2h-2zm0 2.4h2v2h-2zm-2.4-2.4h2v2h-2zm0 2.4h2v2h-2zm-2.3 0h2v2h-2zm9.4 0h2v2h-2z"/><path d="M27.1 13.6c-.4-.1-.9-.2-1.3-.2-.5.1-.8-.1-1-.6-.2-.5-.5-.9-.9-1.2-.6-.7-1.2-.5-1.5.3-.2.7-.2 1.5-.1 2.2.2.9.1 1.1-.8 1.3-1.1.3-16.3.2-16.3.2-.2 0-.3.5-.3 1s.1 2 .4 2.7c1 2.2 2.7 3.8 5.2 4H15c2.9-.1 5.2-1.5 7.2-3.6.8-.9 1.5-1.9 2-3 .2-.4.5-.6.9-.7.7-.1 1.3-.2 1.8-.6.1-.2.3-.4.4-.5.7-.5.6-1.1-.2-1.3zm-14.9 5.1c.4 0 .8.3.8.8s-.3.8-.8.8c-.4 0-.8-.3-.8-.8s.4-.8.8-.8zm-4.9 2.2c.8-.1 1.6.1 2.3-.1.9-.3 1.6-.2 2.1.8.3.6 1 .9 1.7 1.3-2.2.3-4.6-.5-6.1-2z"/></g></svg>', - 'code-climate': - '<svg viewBox="0 0 1200 1000"><path d="M723.4 621.3c-26.8 25.7-53 50.8-79 76.1-6.3 6.1-9.5 1.7-13.6-2.3-48.1-46.2-96.3-92.4-144.4-138.6-3.7-3.5-7.4-6.9-11.9-11.2-20.9 19.9-41.3 39.2-61.6 58.7-31.1 29.9-62.4 59.8-93.2 90-6.9 6.8-11.4 7.4-18.7.1-24.5-24.4-49.7-48.1-79-76.3 6.7-4.7 13.7-8.2 19.2-13.4 75.1-71.7 150.1-143.6 224.9-215.8 6.3-6 10-6.7 16.6-.3 77.8 75.1 155.9 149.9 233.9 224.9 2.4 2.3 4.3 5 6.8 8.1zm4.9-321.7C812.1 380 894.7 459.2 978 539.2c-28.6 27.6-56.6 54.4-85.4 82.2-55-52.6-109.5-104.8-164.3-157.4-19.5 18.6-38.2 36.5-57.9 55.3-28.8-27.6-56.7-54.3-85.5-81.9 48.2-46.4 95.2-91.6 143.4-137.8z"/></svg>', - eslint: - '<svg viewBox="0 0 32 32"><path d="M21.8 7H10.5l-5.1 9 5.1 9h11.3l4.7-9-4.7-9zM16 23.3l-6.3-3.6v-7.1L16 8.7l6.3 3.9v7.1L16 23.3z"/><path d="M11.8 13.7v4.8l4.2 2.4 4.2-2.4v-4.8L16 11.1z"/></svg>', - firebase: - '<svg baseProfile="tiny" version="1.2" viewBox="0 0 512 512"><path d="M297.036 205.578l-36.334 33.809-33.716-68.005 17.446-39.108c4.416-7.84 11.621-7.855 16.037 0l36.567 73.304z"/><path d="M260.702 239.386L124.924 365.697l102.062-194.316z"/><path d="M336.776 153.901c6.491-6.239 13.202-4.111 14.912 4.729l35.342 205.375-117.157 70.215c-4.1 2.264-14.957 3.246-14.957 3.246s-9.91-1.185-13.687-3.281L124.92 365.69l211.856-211.789z"/><path d="M226.986 171.381L124.924 365.697l45.46-283.998c1.674-8.847 6.71-9.699 11.203-1.89l45.399 91.572z"/></svg>', - firefox: - '<svg viewBox="0 0 1200 1000"><path d="M883 466.6c-2.1-12.2-4.2-24.4-6.4-37.6-3.6 8.1-6.5 14.7-9.4 21.3-.7 0-1.3-.1-2-.1 5.8-56.6-7.8-106-52.1-144.9-.8 2.3-1.2 3.5-1.7 5-9.8-12.7-22-21.6-34.5-30.6-2.2 7.7.1 12.3 5.1 17 17.9 16.6 33.7 35.1 46.1 56.3 1 1.7 1.8 3.6 2.7 5.4-12.9-18.2-29.1-33-44.4-48.7-20.5-21.2-45.2-34.6-72.9-43.4-4.9-1.6-9.9-3.1-13.8-4.3 13.8 11.4 28.6 22.8 42.3 35.4 16.8 15.5 33.1 37.5 34.1 44-13.8-11.5-28.4-21.1-48.4-22.4 41.2 37 59.9 81.7 55.7 136.7-5.7-10.6-12.5-19-23.5-25.3.9 8.8 1.7 16.1 2.3 23.4 1.7 19.5 6.1 38.9 1.8 58.7-1.9 8.8-3.6 17.7-5.5 26.6-2.5-4.9-4.8-9.2-7.1-13.7-4.2 16.4-7.7 31.7-12.2 46.7-4.5 15.1-11.9 28.8-23.6 39.7-2.7 2.5-5.8 4.6-8.9 6.5-1.3.8-3.2.4-4.8.6-.1-1.4-.2-2.9-.2-4.3 0-.7.1-1.4.3-3.1-2.5.6-4.9.6-6.3 1.7-2.8 2.3-5.3 5.1-7.4 8.1-5 7-11.4 12.3-19.6 16.5.9-3.3 1.5-5.6 2.1-8.1-6.6 1.7-12.4 3.6-18.3 4.7-18.3 3.6-36.5 8.5-55.4 5.3-9.4-1.6-18.3-4.2-25.4-11.7h17.4c-1.9-1.9-4-3.3-6.3-3.9-9.4-2.4-19-4.1-28.3-6.8-7.3-2.1-15.1-4.2-21.4-8.3-7.4-4.8-13.7-11.4-20-17.7-22.2-22.1-28.2-49.5-24.1-79.5 2-14.6 4.2-29.5 17.1-39.8-6.5-4.7-13.5-7.2-21.2-7.5-20.6-.7-41.7 14.7-49.2 36.6-9.4 27.6-2 52 14.9 74.5 1.2 1.6 2.4 3.2 3.7 4.9-22.9-19.8-35.8-57.3-21.5-89.4 17.5-39.3 62.3-47.8 92.7-17.6 1.5 1.5 2.5 3.3 4.1 5.4 5.2-11.7 3.6-29.5-2.9-38.5-15.6-21.4-22.9-44.7-17.4-71.4 5.4-26.3 18.4-48.1 37.3-66.7 1.4-1.4 2.8-2.8 4.5-4.6-28.7-6-59.7 13.1-89 53.3 1.3-7.7 2.6-15.4 3.9-23.7-2.7-.6-5.5-1.5-8.3-1.8-30.3-3.8-57.4 3.7-81.1 23.3-24.4 20.2-39.1 46.6-48.2 76.3-4.3 14.1-8.3 28.4-12.4 42.6.4.1.7.2 1.1.3 2.2-3.4 4.4-6.9 7.6-11.7-5.2 29.4-8.1 69.7-6.4 86.2 1.9-5.9 3.8-11.7 5.7-17.5 8.3 61.3 30.9 115 73.5 159.6 40.7 42.5 122 88.5 151.9 86.5-3.5-2.4-7.3-5-11-7.6 9.2 1.6 17.6 4.7 26.2 6.9 11.1 2.8 22.3 4.8 33.5 7.2h17.5c-2.7-2.3-5.4-4.7-9-7.7 11.4-.6 21.6-.8 31.8-1.6 30.9-2.5 61.1-9 90.5-18.9 19.9-6.7 32.3-21.5 43.8-37.7 2.4-3.3 5.7-6.4 9.2-8.3 29.8-16.7 52.7-40.2 69.5-69.8 8.6-15.2 9.5-31.3 5.7-48-.7-3-.4-6.6.7-9.4 4.9-12 11-23.6 15.4-35.9 4.2-11.6 6.8-23.8 10.2-35.7.3-.9.6-1.8 1-2.7v-28c-.6-2.8-1-5-1.4-7.3z"/><path d="M500.1 517.4c-5.7 28.1 9.6 62 35.2 76.4 1.3.7 2.9 1 4.3 1.1 29.3 2.2 56-4.2 79-23.5 2.5-2.1 5.6-3.6 7.9-5.9 6.4-6.3 13.8-7.9 22.5-6.2 6.9 1.3 10.3-2.8 8.9-9.7-1.5-7.3-5.9-12.8-12.4-16.2-19.8-10.4-39.6-11.4-59.6-.1-4.8 2.8-10.1 5.2-15.5 6.5-14.2 3.5-28.1.9-40.9-5.3-10.1-4.8-19.7-11.4-29.4-17.1zM408.6 312c1.1-1.1 2.2-2.2 3.4-3.2 67.8-63 147.4-86.3 238-67.8 32.2 6.5 63.5 17.5 93.2 25.9-106.4-72.2-258.3-53.3-343.9 39 2.6 2.4 5.3 4.9 7.8 7.2.9-.6 1.2-.8 1.5-1.1zm183.6 74.8c.5-7.2-1.3-9.9-8.5-10.5-11.4-1-22.9-1.2-34.3-1.5-9.8-.3-19.6-.3-26.9-8.6-8.8 19-.4 54.9 14.8 67.8 13.4-7.5 26.1-15.3 39.5-21.9 11-5.4 14.7-14.3 15.4-25.3zM400.5 320c-13.3-11.3-19.6-25.3-21-43.1-20.8 23.3-26.4 50-28 78.5 14.1-14.8 29.7-27.2 49-35.4z"/></svg>', - gitlab: - '<svg class="footer-logo" viewBox="0 0 125.785 125.785"><path stroke-width=".369" d="M62.892 105.624L75.92 57.573H49.865z" class="logo-svg-shape logo-dark-orange-shape"/><path stroke-width=".369" d="M62.892 105.624L49.865 57.573H31.606z" class="logo-svg-shape logo-orange-shape"/><path stroke-width=".369" d="M31.607 57.573l-3.96 14.602c-.36 1.332.035 2.791.98 3.614l34.265 29.835z" class="logo-svg-shape logo-light-orange-shape"/><path stroke-width=".369" d="M31.607 57.573h18.258l-7.847-28.94c-.404-1.49-2.162-1.49-2.565 0z" class="logo-svg-shape logo-dark-orange-shape"/><path stroke-width=".369" d="M62.892 105.624L75.92 57.573h18.258z" class="logo-svg-shape logo-orange-shape"/><path stroke-width=".369" d="M94.178 57.573l3.959 14.602c.361 1.332-.034 2.791-.98 3.614l-34.265 29.835z" class="logo-svg-shape logo-light-orange-shape"/><path stroke-width=".369" d="M94.178 57.573H75.92l7.847-28.94c.403-1.49 2.161-1.49 2.565 0z" class="logo-svg-shape logo-dark-orange-shape"/></svg>', - grunt: - '<svg viewBox="0 0 32 32"><path d="M22.5 16.4c.4-.2.9-.4 1.3-.7.9-.6.9-1.7 0-2.1-.2-.1-.3-.3-.4-.6-.1-.6 0-1.1.3-1.6.7-1 .2-1.8-1.1-1.9h-.1l-.1-.1c-.1-.5-.2-.9.4-1.3.2-.1.5-.2.8-.3.2-.1.4-.1.5-.1 0-.1-.1-.1-.1-.1-.7-.8-1.7-1-2.6-.9-1.2.1-1.9.7-2.6 1.5-.1.2-.3.2-.5.1s-.2-.2-.2-.3c0-.2.1-.4.1-.6l.3-.6c-.6 0-1 .3-1.5.6-.3-.5-.3-.9-.1-1.4-.9.3-1.5.7-1.7 1.6-.3-.3-.2-.7-.2-1.1h-.1c-.1 0-.1.1-.2.1-.5.4-.8.9-.9 1.4 0 .1-.1.2-.1.3-.1-.1-.2-.1-.3-.2-.4-.3-.8-.7-1.2-1-1.2-.7-2.3-.7-3.5-.1l-.8.8c.4.2.8.2 1.2.4.7.2.9.6.6 1.4-.2 0-.4.1-.6.1-.7.2-1 .7-.9 1.3.1.3.3.6.4.9 0 .1.1.2.1.3v1c0 .2-.2.4-.4.6-.2.2-.5.4-.6.7-.3.5 0 1.1.5 1.5.4.3.8.5 1.3.7.6.3.8.7.8 1.2 0 .6 0 1.1-.1 1.7 0 .2-.1.5-.1.8-.6-.5-1-1-1.1-1.7-.6.5-.9 1-.9 1.6-.2 1.3.3 2.6 1.9 3.2.1 0 .2.1.3.2.6 1 1.5 1.6 2.7 1.8.1 0 .2 0 .2.1 1.1.7 2.2.8 3.4.7.7-.1 1.3-.2 1.8-.6.1-.1.3-.1.4-.2 1.2-.2 2-.8 2.6-1.7l.3-.3c.6-.2 1.1-.5 1.4-1 .5-.7.6-1.6.5-2.3-.1-.6-.4-1-.9-1.5-.2.7-.5 1.2-1.1 1.7-.1-.9-.1-1.8-.1-2.6.2-.8.5-1.2 1-1.4zm-8.4 5.3h4.5-4.5z"/></svg>', - gulp: '<svg viewBox="0 0 32 32"><path d="M20.1 22.8c-.2.3-.3.5-.4.7-.1.2-.2.5-.2.7-.1 1-.2 2.1-.3 3.1 0 .4-.2.6-.5.7-.7.2-1.5.5-2.2.7h-1.1c-.1 0-.3-.1-.4-.1-.6-.2-1.2-.4-1.7-.7-.1-.1-.3-.3-.3-.5-.1-.8-.1-1.5-.1-2.3 0-.8 0-1.6-.6-2.2v-.1c2.5.7 5.1.7 7.8 0zm1.5-12.7c-.1 1.4-.3 2.8-.4 4.2l-.4 4.1c-.1 1-.2 2.1-.3 3.2 0 .7-.4 1-1 1.1-1 .2-1.9.3-2.9.4-1.4.1-2.8 0-4.2-.4-.5-.1-.6-.5-.7-.9 0-.5-.1-1-.2-1.4-.1-.9-.2-1.8-.3-2.8l-.1-.9c0-.1-.1-.2-.1-.3-.1-1.6-.4-3.1-.6-4.7-.1-.5-.1-1-.1-1.5 3.8.8 7.6.8 11.3-.1zm-11.3-.6c.2-.1.4-.2.6-.2.9-.1 1.9-.2 2.8-.3.1 0 .4-.2.4-.2-.3-.9-.3-1.8-1-2.5-.8-.8-1.5-1.7-2.3-2.5.6-.6.6-.6 1.1-.1.4.4.7.8 1.1 1.1 1.1.9 1.8 2.1 2 3.5.2.6.5.7 1 .7 1.7.1 3.3.2 5 .3.2 0 .4.1.7.2-1.7 1.3-10.4 1.2-11.4 0z"/></svg>', - ionic: - '<svg viewBox="0 0 32 32"><path d="M24.9 11.6c.4-.4.6-1 .6-1.7 0-1.4-1.1-2.6-2.6-2.6-.5 0-1 .2-1.4.4C20 6.6 18.1 6 16 6 10.5 6 6 10.5 6 16s4.5 10 10 10 10-4.5 10-10c0-1.6-.4-3.1-1.1-4.4zM16 24.4c-4.7 0-8.4-3.8-8.4-8.4s3.8-8.4 8.4-8.4c1.7 0 3.3.5 4.6 1.4-.1.3-.2.6-.2.9 0 1.4 1.1 2.6 2.6 2.6.2 0 .4 0 .6-.1.5 1.1.8 2.3.8 3.6 0 4.7-3.7 8.4-8.4 8.4z"/><path d="M16 11.9c-2.3 0-4.1 1.8-4.2 4.1 0 2.3 1.8 4.1 4.1 4.2 2.3 0 4.1-1.8 4.2-4.1 0-2.3-1.8-4.2-4.1-4.2z"/></svg>', - platformio: - '<svg preserveAspectRatio="xMidYMid" viewBox="0 0 32 32"><g><path d="M20.155 10.313l.625-2.183c.64-.055 1.142-.575 1.142-1.21 0-.671-.562-1.215-1.255-1.215-.693 0-1.254.544-1.254 1.215 0 .442.244.828.609 1.04l-.614 2.144c-1.755-.432-3.237-.4-3.237-.4l-.274.12v16.592l.274.089c1.655 0 8.896-4.845 8.913-10.044 0-3.724-2.555-5.397-4.93-6.148zm-1.743 10.688c-1.412-2.186-.815-7.273 2.874-8 1.011-.158 2.25.486 2.615 1.917.921 3.034-4.5 7.284-5.49 6.083zm2.214-4.682c-.63 0-1.142.495-1.142 1.107 0 .611.511 1.107 1.142 1.107.631 0 1.143-.496 1.143-1.107 0-.612-.512-1.107-1.143-1.107zm.342 1.021a.284.284 0 01-.289-.28c0-.154.13-.28.289-.28.16 0 .288.126.288.28 0 .155-.129.28-.288.28z"/><path d="M12.922 10.154l-.61-2.226c.349-.216.581-.594.581-1.025 0-.671-.561-1.216-1.254-1.216s-1.254.545-1.254 1.216c0 .67.558 1.212 1.248 1.215l.612 2.233c-2.384.766-4.97 2.443-4.97 6.11.053 5.301 7.241 10.043 8.896 10.043v-16.8s-1.489-.007-3.249.45zm1.264 10.847c-.99 1.2-6.41-3.049-5.489-6.083.365-1.43 1.603-2.075 2.615-1.918 3.689.728 4.286 5.815 2.874 8zm-2.288-4.648c-.63 0-1.142.495-1.142 1.107 0 .611.511 1.107 1.142 1.107.631 0 1.143-.496 1.143-1.107 0-.612-.512-1.107-1.143-1.107zm-.341 1.021a.284.284 0 01-.29-.28c0-.154.13-.279.29-.279.159 0 .288.125.288.28 0 .154-.13.28-.288.28z"/></g></svg>', - rollup: - '<svg viewBox="0 0 32 32"><path d="M22.3 23.9l-2.7-5.4c-.1-.2-.1-.3.1-.4.6-.3 1.1-.7 1.5-1.2 1.1-1.3 1.6-2.9 1.4-4.6-.1-.8-.3-1.5-.7-2.2-.1-.1-.1-.2-.2-.3-.4-.4-.9-.6-1.5-.8-.6-.1-1.2-.2-1.8 0-.4.1-.7.2-.9.5-.5.6-.6 1.2-.4 1.9.2.8.7 1.3 1.3 1.8.2.1.4.2.7.3.2 0 .4 0 .5-.3.1-.1.1-.3.1-.4 0-.4-.1-.7-.2-1-.1-.2-.2-.4-.2-.6.2.5.5 1 .7 1.4.1.3.1.7-.1 1l-.2.2c-.5.4-1 .9-1.5 1.3-.7.6-1.3 1.2-1.8 1.8-.8 1-1.5 2-2.2 3-.5.7-.9 1.4-1.4 2.2-.4.6-.7 1.2-1.1 1.8-.2.4-.5.8-.7 1.1h11.6c.3 0 .4-.2.3-.5-.4-.2-.5-.4-.6-.6z"/><path d="M12.7 15.1c.8-1.4 1.5-2.8 2.4-4.1.4-.6.8-1.2 1.2-1.7.4-.4.8-.7 1.3-.9.5-.1 1.1-.2 1.7-.1.8.1 1.5.4 2.1 1l.1.1.1.1v-.1C20.4 7.9 18.8 7 16.8 7H9.6c-.2 0-.3.1-.3.4v14.4c.5-1.3 1.2-2.6 1.9-3.9.5-1 1-1.9 1.5-2.8z"/></svg>', - stylelint: - '<svg viewBox="0 0 32 32"><path d="M14.482 9.308h2.399v1.46h-2.4zm5.266 3.157l-2.534-1.572c-.093-.096-.046-1.76-.046-1.76L19.7 7.708l.047 4.758zm-8.152-.048l2.55-1.572c.094-.096.046-1.76.046-1.76l-2.55-1.426-.046 4.758zm3.392.485c0-.36.285-.653.637-.653.352 0 .637.292.637.653a.645.645 0 01-.637.654.645.645 0 01-.637-.654zm0 3.99c0-.362.285-.655.637-.655.352 0 .637.293.637.654a.645.645 0 01-.637.654.645.645 0 01-.637-.654zm0 3.988c0-.361.285-.654.637-.654.352 0 .637.293.637.654a.645.645 0 01-.637.653.645.645 0 01-.637-.653zM25.226 9.75L22.46 7.203h-1.546l-.796 2.835-.047 3.028-.75-.433-3.466 13.12 8.854-12.976-1.218-1.441 1.734-1.586zM6.11 9.702l2.764-2.547h1.546l.796 2.835.047 3.028.75-.433 3.467 13.12-8.855-12.976 1.218-1.441L6.11 9.702zm5.786 3.1"/></svg>', - yarn: '<svg viewBox="0 0 32 32"><path d="M12 24.2c-.2-.1-.3-.2-.4-.4-.1-.1-.1-.1-.2 0-.1.2-.1.4-.2.6-.3 1-.8 1.3-1.8 1.1-.2 0-.4-.1-.6-.2-.4-.2-.5-.5-.3-.9 0-.1.1-.2.1-.3-.4 0-.6-.2-.7-.5-.5-1.3-.4-2.3.6-3.3.1-.2.2-.3.2-.5 0-1.3.2-2.5 1.1-3.6.3-.4.7-.8 1.2-1.1.2-.1.2-.2.1-.4-.4-.5-.6-1-.7-1.6-.1-.5.2-1 .4-1.5.1-.1.2-.2.3-.2.4-.1.7-.4 1-.6.7-.7 1.5-1 2.5-1 .2 0 .3-.1.3-.2.1-.4.3-.8.6-1.2l.3-.3c.2-.2.5-.2.6.1.3.5.5 1 .7 1.4.1.2.2.2.3.1.7-.3.7-.3.9.4.5 2.1.2 4.1-1 6-.1.2-.3.4-.4.6-.1.2-.1.3.1.5.9.8 1.5 1.9 1.7 3.1.1.7.1 1.5 0 2.2-.1.4 0 .4.3.3.7-.2 1.4-.5 2-.9.7-.4 1.3-.8 2.1-.9.3 0 .5-.1.8 0 .3.1.5.4.5.7 0 .3-.2.5-.5.6-1 .2-1.9.7-2.7 1.3-1 .7-2.2 1.2-3.3 1.5-.1 0-.3.1-.4.2-.4.3-.8.3-1.3.4-1.1.1-2.1.2-3.2.2-.3 0-.6 0-1-.1-.3-.1-.6-.3-.7-.6-.1-.4 0-.7.3-.9.2 0 .3-.1.4-.1z"/></svg>', - webpack: - '<svg viewBox="0 0 32 32"><path d="M24 21.4L16 26v-3.6l5-2.8 3 1.8zm.6-.5v-9.6l-3 1.7v6.2l3 1.7zm-17.4.5l8.1 4.6v-3.6l-5-2.8-3.1 1.8zm-.6-.5v-9.6l3 1.7v6.2l-3 1.7zm.3-10.2L15.2 6v3.4l-5.3 2.9-3-1.6zm17.4 0L16 6v3.4l5.3 2.9 3-1.6zm-9.1 10.9l-5-2.7v-5.4l5 2.9v5.2zm.8 0l5-2.7v-5.4l-5 2.9v5.2zm-5.4-8.8l5-2.7 5 2.7-5 2.9-5-2.9z"/></svg>', - lock: '<svg viewBox="0 0 1200 1000"><path d="M818.5 463.8v290.9h-437V463.8h73.4v-6.2c0-22-.1-44 .1-66 .1-7.1.6-14.3 1.6-21.4 11.3-80 87.2-136 166.9-123.1C694 258.5 746.2 319.7 746.2 391v72.7c24.4.1 48.4.1 72.3.1zm-145.2-.1c.1-1.6.2-2.6.2-3.5 0-23.7.1-47.3-.1-71 0-4.1-.6-8.3-1.4-12.4-8-38.7-41-62.2-81.3-58.2-35.6 3.6-63.3 35.5-63.3 73.1v72h145.9z"/></svg>', - license: - '<svg viewBox="0 0 32 32"><path d="M18.7 12.8c-.2-2.2-1.9-3.7-4.2-3.8H13c-.1-1.3.4-3.1 2.5-3.3.9-.1 1.7.1 2.4.8.6.7.8 1.5.8 2.4 0 .1 0 .3.1.4l.9.9c.3-.9.3-1.8.1-2.7-.5-1.8-2-2.9-3.9-3-1.1 0-2.1.2-2.9 1-1.4 1.3-1.9 4.2.1 6.1.3.3.7.5 1.1.7.5.2.9-.2.9-.6 0-.4-.2-.7-.7-.8-.1 0-.2-.1-.3-.2v-.1c.4-.1.9 0 1.2.3.3.3.4.7.3 1.2-.2.7-.8 1-1.6.8-1.1-.3-1.8-1-2.3-2-.1-.3-.3-.6-.4-.9-.7.7-1.3 1.4-1.5 2.4-.4 1.8.1 3.3 1.4 4.5.1.1.2.2.1.4-.1.8-.2 1.5-.4 2.3-.3 1.7-.5 3.3-.8 5-.1.5-.1 1.1 0 1.6.1.4.3.7.8.9.1-.4.1-.8.2-1.2.3-1.7.5-3.3.8-5 .2-1 .3-2.1.5-3.1 0-.2.1-.3.3-.3.2 0 .2.2.2.4-.1 1-.3 2-.5 2.9-.3 2.1-.7 4.2-1 6.3 0 .1.1.2.1.2.5 0 .9.1 1.4.1.5 0 .9-.4 1.2-.8.3-.3.3-.7.1-1.1-.1-.1-.2-.2-.2-.3-.3-.4-.2-.7.2-.9.1-.1.3-.1.4-.2.2-.1.3-.4.1-.6-.3-.3-.5-.6-.8-.8-.2-.2-.1-.6.1-.7.3-.2.7-.3 1-.5.2-.1.3-.3.1-.5-.1-.1-.2-.2-.3-.4-.3-.3-.2-.8.1-1 .1-.1.2-.2.4-.2.2-.1.3-.2.3-.4 0-.3.1-.6.1-.9 0-.1.1-.3.2-.4.3-.3.7-.5 1.1-.7 1.4-1 1.9-2.5 1.7-4.2zm3.6 11.4c0-.2-.1-.4-.4-.4-.2 0-.5 0-.6-.3-.1-.3-.1-.6 0-.9.2-.4.1-.7-.4-.8-.2 0-.4-.1-.7-.1-.2 0-.3-.1-.3-.3 0-.2-.1-.4-.1-.6 0-.3.2-.5.4-.7.2-.3.2-.4-.1-.6-.1-.1-.3-.2-.4-.3-.4-.2-.4-.4-.2-.8.1-.1.2-.2.2-.3.2-.2.2-.4.1-.6-.1-.2-.2-.5-.4-.7-.1-.2-.1-.4 0-.6.8-1.6 1-3.2.3-4.9-.5-1.1-1.4-1.8-2.6-2.1l-.1.1c.1.1.2.3.3.4 1.2 1 1.9 2.3 1.9 3.9 0 1.7-.7 3.1-2.2 4.2-.2.1-.3.3-.2.5.4 1 .7 1.9 1.1 2.9.8 1.9 1.6 3.7 2.4 5.6.1.1.1.2.3.2 1.2-.6 1.9-1.7 1.7-2.8zm-6-5.9c-.1.4-.1.7-.2 1 0 .2-.1.4 0 .6.7 1.7 1.4 3.5 2.1 5.2.2.5.5 1 1 1.4.2.1.4.2.5.3l.1-.1c-1.1-2.8-2.3-5.6-3.5-8.4z"/></svg>', - makefile: - '<svg viewBox="0 0 32 32"><path d="M10.2 7L7 7.8v16h4.2v-9.9l3.6 3.9h2.4l3.6-3.9v9.9H25v-16L21.8 7 16 13.3 10.2 7z"/></svg>', - heroku: - '<svg viewBox="0 0 32 32"><path d="M9 26v-5.714l3.25 2.857L9 26zm11.742-11.58c1.243 1.242 1.26 2.826 1.258 3.009V26h-2.889v-8.532C19.097 16.8 18.772 16 17.306 16c-2.938 0-6.233 1.461-6.265 1.476L9 18.39V6h2.889v8.111c1.442-.464 3.458-.968 5.417-.968 1.785 0 2.854.694 3.436 1.277zm-3.798-3.777C18.08 9.17 18.793 7.619 19.111 6H22c-.195 1.623-.86 3.179-2.167 4.643h-2.889z"/></svg>', - todo: '<svg viewBox="0 0 32 32"><path d="M16 7h5.7c1.6 0 2.9 1.1 3.2 2.6.1.2.1.5.1.6v11.4c0 1.6-1.1 3-2.7 3.2-.2 0-.4.1-.6.1H10.4c-2 0-3.4-1.4-3.4-3.3V10.3c0-1.7 1.1-3 2.7-3.3H16zm-6.3 9v5.7c0 .4.2.6.7.6h11.2c.4 0 .7-.3.7-.7V10.4c-.1-.5-.3-.7-.8-.7H10.3c-.5 0-.7.2-.7.7.1 1.8.1 3.7.1 5.6z"/><path d="M12.1 14.7c.2.1.3.1.5.2.7.3 1.4.7 2.1 1 .2.1.2.1.3 0 1.5-1.1 2.9-2.2 4.4-3.2.2-.2.4-.2.5-.3.3-.1.5.2.5.5-.1.2-.2.3-.2.4-.7.9-1.3 1.8-2 2.8-.8 1.1-1.5 2.1-2.3 3.1-.5.8-1.3.7-1.8-.1-.8-1.2-1.5-2.2-2.3-3.4-.1-.1-.2-.2-.2-.3-.1-.4.1-.7.5-.7z"/></svg>', - npm_ignored: - '<svg viewBox="0 0 32 32"><path d="M4 11.3v8h6.8v1.4h5.3v-1.3H28v-8.1H4zm6.6 6.7H9.3v-3.9H8V18H5.3v-5.3h5.3V18zm6.7 0h-2.7v1.4h-2.7v-6.6h5.3c.1 1.6.1 3.4.1 5.2zm9.3 0h-1.3v-3.9H24V18h-1.4v-3.9h-1.3V18h-2.7v-5.3h8V18zm-10.7-3.9h-1.3v2.6h1.3v-2.6z"/></svg>', - ignored: - '<svg viewBox="0 0 32 32"><path d="M22.9 10.3c.1-.2.2-.4.2-.6-.1-.4-.3-.6-.6-.7-.3-.1-.6 0-.9.2l-2 2c-.1.1-.2.1-.4.1-2.3-.9-4.5-.9-6.8.1s-4 2.7-5.3 4.7c-.2.4-.2.7.1 1 .5.6 1.1 1.2 1.7 1.7.6.5 1.2.9 1.8 1.3-.1 0-.1.1-.2.1-.5.5-1 .9-1.4 1.4-.2.2-.3.5-.2.9.1.3.3.5.7.6.3 0 .6-.1.8-.3l12.4-12.4.1-.1zm-10.8 8.4h-.2c-1.1-.6-2.1-1.3-3-2.3 1-1.3 2.2-2.5 3.7-3.3-1 1.7-.9 3.3.2 4.9l-.7.7zm4.5-5.5c-.1.3-.3.5-.7.5-.9 0-1.6.6-1.7 1.5v.3c0 .4-.3.6-.6.6-.4 0-.6-.3-.6-.7 0-1.6 1.3-3 2.9-3 .5 0 .8.4.7.8zm8.2 2.8c-.5-.6-1-1.3-1.5-1.9-.4-.5-1-.9-1.4-1.4l-1.2 1.2c.9.7 1.7 1.5 2.4 2.5-.1.1-.2.2-.3.2-.3.3-.6.6-.9.8-2 1.6-4.2 2.4-6.7 2.1-.2 0-.3 0-.4.1-.2.2-.4.4-.6.7l-.6.6h.1c1.4.3 2.9.4 4.3.1 2.8-.5 5-2 6.8-4.1.3-.2.3-.5 0-.9z"/></svg>', -}; - -type IconDetails = [string, string]; - -interface SetiTheme { - blue: string; - grey: string; - 'grey-light': string; - green: string; - orange: string; - pink: string; - purple: string; - red: string; - white: string; - yellow: string; - ignore: string; -} - -type Color = keyof SetiTheme; - -interface Icon { - svg: string; - color: Color; -} - -const definitions = rawDefinitions as unknown as { - default: IconDetails; - extensions: { [extension: string]: IconDetails }; - files: { [file: string]: IconDetails }; - partials: [string, IconDetails][]; -}; -const icons = rawIcons as unknown as { - [icon: string]: string; -}; - -const getDetails = (fileName: string): IconDetails => { - const details = definitions.files[fileName]; - if (details) return details; - let extension = fileName.slice(fileName.indexOf('.')); - while (extension !== '') { - const details = definitions.extensions[extension]; - if (details) return details; - // look for next "." - extension = extension.slice(1); - extension = extension.slice(extension.indexOf('.')); - } - for (const partial of definitions.partials) { - if (fileName.indexOf(partial[0]) > -1) { - return partial[1]; - } - } - return definitions.default; -}; - -export const getIcon = (fileName: string): Icon => { - const [icon, color] = getDetails(fileName); - return { svg: icons[icon], color } as Icon; -}; diff --git a/docs/src/components/internal/rehype-file-tree.ts b/docs/src/components/internal/rehype-file-tree.ts deleted file mode 100644 index b61dde3cadb..00000000000 --- a/docs/src/components/internal/rehype-file-tree.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { fromHtml } from 'hast-util-from-html'; -import { toString } from 'hast-util-to-string'; -import { h } from 'hastscript'; -import type { Element, HChild } from 'hastscript/lib/core'; -import { rehype } from 'rehype'; -import { CONTINUE, SKIP, visit } from 'unist-util-visit'; -import { getIcon } from './file-tree-icons'; - -/** Make a text node with the pass string as its contents. */ -const Text = (value = ''): { type: 'text'; value: string } => ({ - type: 'text', - value, -}); - -/** Convert an HTML string containing an SVG into a HAST element node. */ -const makeSVGIcon = (svgString: string) => { - const root = fromHtml(svgString, { fragment: true }); - const svg = root.children[0] as Element; - svg.properties = { - ...svg.properties, - width: 16, - height: 16, - class: 'tree-icon', - 'aria-hidden': 'true', - }; - return svg; -}; - -const FileIcon = (filename: string) => { - const { svg } = getIcon(filename); - return makeSVGIcon(svg); -}; - -const FolderIcon = makeSVGIcon( - '<svg viewBox="0 0 20 20"><path d="M14.77 6.45H9.8v-.47A.97.97 0 0 0 8.83 5H3.75v10H15.7V7.42a.91.91 0 0 0-.93-.97Z"/></svg>' -); - -export const fileTreeProcessor = rehype().use(() => (tree, file) => { - const { directoryLabel } = file.data as { directoryLabel: string }; - visit(tree, 'element', (node) => { - // Strip nodes that only contain newlines - node.children = node.children.filter( - (child) => child.type === 'comment' || child.type !== 'text' || !/^\n+$/.test(child.value) - ); - - if (node.tagName !== 'li') return CONTINUE; - - // Ensure node has properties so we can assign classes later. - if (!node.properties) node.properties = {}; - - const [firstChild, ...otherChildren] = node.children; - - const comment: HChild[] = []; - if (firstChild?.type === 'text') { - const [filename, ...fragments] = firstChild.value.split(' '); - firstChild.value = filename || ''; - comment.push(fragments.join(' ')); - } - const subTreeIndex = otherChildren.findIndex( - (child) => child.type === 'element' && child.tagName === 'ul' - ); - const commentNodes = - subTreeIndex > -1 ? otherChildren.slice(0, subTreeIndex) : [...otherChildren]; - otherChildren.splice(0, subTreeIndex > -1 ? subTreeIndex : otherChildren.length); - comment.push(...commentNodes); - - const firstChildTextContent = toString(firstChild); - - // Decide a node is a directory if it ends in a `/` or contains another list. - const isDirectory = - /\/\s*$/.test(firstChildTextContent) || - otherChildren.some((child) => child.type === 'element' && child.tagName === 'ul'); - const isPlaceholder = /^\s*(\.{3}|…)\s*$/.test(firstChildTextContent); - const isHighlighted = firstChild.type === 'element' && firstChild.tagName === 'strong'; - const hasContents = otherChildren.length > 0; - - const fileExtension = isDirectory ? 'dir' : firstChildTextContent.trim().split('.').pop() || ''; - - const icon = h('span', isDirectory ? FolderIcon : FileIcon(firstChildTextContent)); - if (!icon.properties) icon.properties = {}; - if (isDirectory) { - icon.children.unshift(h('span', { class: 'sr-only' }, directoryLabel)); - } - - node.properties.class = isDirectory ? 'directory' : 'file'; - if (isPlaceholder) node.properties.class += ' empty'; - node.properties['data-filetype'] = fileExtension; - - const treeEntry = h( - 'span', - { class: 'tree-entry' }, - h('span', { class: isHighlighted ? 'highlight' : '' }, [ - isPlaceholder ? null : icon, - firstChild, - ]), - Text(comment.length > 0 ? ' ' : ''), - comment.length > 0 ? h('span', { class: 'comment' }, ...comment) : Text() - ); - - if (isDirectory) { - node.children = [ - h('details', { open: hasContents }, [ - h('summary', treeEntry), - ...(hasContents ? otherChildren : [h('ul', h('li', '…'))]), - ]), - ]; - // Continue down the tree. - return CONTINUE; - } - - node.children = [treeEntry, ...otherChildren]; - - // Files can’t contain further files or directories, so skip iterating children. - return SKIP; - }); -}); diff --git a/docs/src/components/languages-list.astro b/docs/src/components/languages-list.astro new file mode 100644 index 00000000000..03a0b40dd70 --- /dev/null +++ b/docs/src/components/languages-list.astro @@ -0,0 +1,40 @@ +--- +import { getEntry } from 'astro:content'; +import translations from '../../../packages/starlight/translations'; + +interface Props { + startsSentence?: boolean; +} + +// The current page's slug. +const slug = Astro.url.pathname.replace(/^\//, '').replace(/\/$/, ''); +// The docs entry for the current page, or `undefined` if the page is using fallback content. +const entry = await getEntry('docs', slug); +// The BCP-47 tag for the current page or fallback content's language. +const pageLang = entry && Astro.currentLocale ? Astro.currentLocale : 'en'; +// The BCP-47 tags for all supported languages in Starlight. +const supportedLangs = Object.keys(translations); +// An i18n helper that returns the language name for a given BCP-47 tag configured for the current page's language. +const langNames = new Intl.DisplayNames([pageLang], { type: 'language' }); + +// A list of the language names for all supported languages sorted alphabetically. +const supportedLangNames = supportedLangs + .map((supportedLang) => { + const langName = langNames.of(supportedLang); + if (!langName) throw new Error(`Failed to get the language name for '${supportedLang}'.`); + return langName; + }) + .sort((a, b) => a.localeCompare(b, pageLang)); + +// The list of language names for all supported languages formatted according to the current page's language. +const langList = new Intl.ListFormat(pageLang, { + style: 'long', + type: 'conjunction', +}).format(supportedLangNames); +--- + +{ + Astro.props.startsSentence + ? langList[0]?.toLocaleUpperCase(pageLang) + langList.slice(1) + : langList +} diff --git a/docs/src/components/media-card.astro b/docs/src/components/media-card.astro new file mode 100644 index 00000000000..a9395f03f57 --- /dev/null +++ b/docs/src/components/media-card.astro @@ -0,0 +1,48 @@ +--- +interface Props { + href?: string | undefined; +} +const { href } = Astro.props; +const El = href ? 'a' : 'span'; +--- + +<li class="not-content sl-flex"> + <El class="media-card sl-flex" {href}> + <div class="media"><slot name="media" /></div> + <slot /> + </El> +</li> + +<style> + .media-card { + flex-direction: column; + border: 1px solid var(--sl-color-gray-5); + border-radius: 0.5rem; + overflow: hidden; + text-decoration: none; + box-shadow: var(--sl-shadow-sm); + width: 100%; + } + a:hover { + border-color: var(--sl-color-gray-2); + background-color: var(--sl-color-gray-7, var(--sl-color-gray-6)); + } + + .media { + border-bottom: 1px solid var(--sl-color-gray-5); + } + + .media :global(img) { + display: block; + width: 100%; + height: auto; + aspect-ratio: 16 / 9; + object-fit: cover; + } + + .media-card :global(.title) { + color: var(--sl-color-white); + font-weight: 600; + line-height: var(--sl-line-height-headings); + } +</style> diff --git a/docs/src/components/showcase-card.astro b/docs/src/components/showcase-card.astro index c940251a11d..2ca38fdb434 100644 --- a/docs/src/components/showcase-card.astro +++ b/docs/src/components/showcase-card.astro @@ -1,6 +1,8 @@ --- import type { ImageMetadata } from 'astro'; import { Image } from 'astro:assets'; +import MediaCard from './media-card.astro'; +import { AstroError } from 'astro/errors'; interface Props { href: string; @@ -17,44 +19,31 @@ if (!thumbnail) { throw new Error(`Could not resolve showcase thumbnail: ${Astro.props.thumbnail}`); } const src = (await thumbnail()).default; + +if (src.width !== 800 || src.height !== 450) { + let fileName = src.src.split('/').pop(); + const queryIndex = fileName?.indexOf('?'); + if (queryIndex !== undefined && queryIndex > -1) { + fileName = fileName?.slice(0, queryIndex); + } + throw new AstroError( + 'Showcase images must be **800×450px**', + `Dimensions of **${src.width}×${src.height}px** found for showcase image \`${fileName || src.src}\`\n\n` + + `For best results:\n\n` + + `1. Take a screenshot of the site using a browser resized to **1280×720px**. The responsive view in dev tools can be helpful for this.\n\n` + + `2. Resize the screenshot to **800×450px** and make sure it is saved as a PNG. An online tool like [Squoosh](https://squoosh.app/) can help here.\n\n` + + `See more details in the [Starlight contributing guide](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#showcase)\n` + ); +} --- -<li> - <a class="showcase-card" {href}> - <span class="image"><Image {src} alt="" width="560" /></span> - <span class="title">{title}</span> - </a> -</li> +<MediaCard {href}> + <Image slot="media" {src} alt="" width="560" /> + <p class="title">{title}</p> +</MediaCard> <style> - li { - display: flex; - } - .showcase-card { - display: flex; - flex-direction: column; - border: 1px solid var(--sl-color-gray-5); - border-radius: 0.5rem; - overflow: hidden; - text-decoration: none; - box-shadow: var(--sl-shadow-sm); - } - .showcase-card:hover { - border-color: var(--sl-color-gray-2); - background-color: var(--sl-color-gray-7, var(--sl-color-gray-6)); - } .title { - color: var(--sl-color-white); padding: 0.75rem 1rem; - font-weight: 600; - line-height: var(--sl-line-height-headings); - } - .image { - border-bottom: 1px solid var(--sl-color-gray-5); - } - - .image img { - aspect-ratio: 16 / 9; - object-fit: cover; } </style> diff --git a/docs/src/components/showcase-sites.astro b/docs/src/components/showcase-sites.astro index 4661828aae0..08351ff6ecf 100644 --- a/docs/src/components/showcase-sites.astro +++ b/docs/src/components/showcase-sites.astro @@ -5,16 +5,11 @@ import FluidGrid from './fluid-grid.astro'; <FluidGrid> <Card title="Athena OS" href="https://athenaos.org" thumbnail="www.athenaos.org.png" /> - <Card - title="PubIndexAPI Docs" - href="https://docs.pubindexapi.com/" - thumbnail="docs.pubindexapi.com.png" - /> - <Card title="pls" href="https://dhruvkb.github.io/pls" thumbnail="dhruvkb.github.io-pls.png" /> + <Card title="pls" href="https://pls.cli.rs/" thumbnail="pls.cli.rs.png" /> <Card title="capo.js" href="https://rviscomi.github.io/capo.js/" thumbnail="capo.js.png" /> <Card title="Web Monetization API" - href="https://webmonetization.org/" + href="https://webmonetization.org/docs/" thumbnail="webmonetization.org.png" /> <Card @@ -30,27 +25,196 @@ import FluidGrid from './fluid-grid.astro'; href="https://sibiraj-s.github.io/ngx-editor/" thumbnail="sibiraj-s.github.io-ngx-editor.png" /> - <Card - title="Astro Error Pages" - href="https://astro-error-page-documentation.vercel.app/" - thumbnail="astro-error-page-documentation.vercel.app.png" - /> <Card title="Terrateam Docs" href="https://terrateam.io/docs" thumbnail="terrateam.io-docs.png" /> - <Card - title="simple-fm" - href="https://simple.arciniega.one" - thumbnail="simple.arciniega.one.png" - /> <Card title="Obytes Starter" href="https://starter.obytes.com" thumbnail="starter.obytes.com.jpg" /> - <Card title="Kanri" href="https://kanriapp.com" thumbnail="kanriapp.com.png" /> <Card - title="VRCFR Creator" - href="https://dev.vrchatfrance.fr" - thumbnail="dev.vrchatfrance.fr.png" + title="Kanri" + href="https://www.kanriapp.com/getting-started/what-is-kanri/" + thumbnail="kanriapp.com.png" /> <Card title="Refact" href="https://docs.refact.ai/" thumbnail="refact.ai.png" /> + <Card + title="Some drops of PHP Book" + href="https://drops-of-php.hi-folks.dev/" + thumbnail="drops-of-php.hi-folks.dev.png" + /> + <Card title="Nostalgist.js" href="https://nostalgist.js.org/" thumbnail="nostalgist.js.org.png" /> + <Card + title="AI Prompt Snippets" + href="https://ai-prompt-snippets.vercel.app/" + thumbnail="ai-prompt-snippets.png" + /> + <Card + title="Folks Router" + href="https://folksrouter.io/docs/introduction" + thumbnail="folksrouter.io.png" + /> + <Card + title="React Awesome Reveal" + href="https://react-awesome-reveal.morello.dev/" + thumbnail="react-awesome-reveal.morello.dev.png" + /> + <Card + title="Ethereum Follow Protocol" + href="https://docs.ethfollow.xyz/" + thumbnail="docs.ethfollow.xyz.png" + /> + <Card title="Knip" href="https://knip.dev" thumbnail="knip.dev.png" /> + <Card title="secco" href="https://secco.lekoarts.de" thumbnail="secco.lekoarts.de.png" /> + <Card + title="SiteOne Crawler" + href="https://crawler.siteone.io/?utm_source=starlight-docs" + thumbnail="crawler.siteone.io.png" + /> + <Card title="Mr. Robøt" href="https://docs.mrrobot.app" thumbnail="docs.mrrobot.app.png" /> + <Card title="Open SaaS Docs" href="https://docs.opensaas.sh/" thumbnail="opensaas.sh.png" /> + <Card + title="Astro Snipcart" + href="https://astro-snipcart.vercel.app/" + thumbnail="astro-snipcart.png" + /> + <Card title="oneRepo" href="https://onerepo.tools" thumbnail="onerepo.tools.png" /> + <Card title="Flojoy" href="https://docs.flojoy.ai" thumbnail="docs.flojoy.ai.png" /> + <Card title="AstroNvim" href="https://docs.astronvim.com" thumbnail="docs.astronvim.com.png" /> + <Card + title="ScreenshotOne Docs" + href="https://screenshotone.com/docs/" + thumbnail="screenshotone.com.png" + /> + <Card title="DipSway" href="https://api.dipsway.com" thumbnail="api.dipsway.com.png" /> + <Card title="RunsOn" href="https://runs-on.com" thumbnail="runs-on.com.png" /> + <Card title="SST Ion" href="https://ion.sst.dev/" thumbnail="ion.sst.dev.png" /> + <Card + title="Font Awesome" + href="https://docs.fontawesome.com/" + thumbnail="docs.fontawesome.com.png" + /> + <Card title="TrueCharts" href="https://truecharts.org/" thumbnail="truecharts.org.png" /> + <Card title="Kinde" href="https://docs.kinde.com/" thumbnail="kinde.com.png" /> + <Card title="DMNO" href="https://dmno.dev" thumbnail="dmno.dev.png" /> + <Card title="EspansoEdit" href="https://ee.qqv.com.au" thumbnail="ee.qqv.com.au.png" /> + <Card title="TutorialKit" href="https://tutorialkit.dev/" thumbnail="tutorialkit.dev.png" /> + <Card + title="The Dev Health OS" + href="https://www.devhealthos.com/" + thumbnail="www.devhealthos.com.png" + /> + <Card + title="FeedbackSpark" + href="https://feedbackspark.com/docs/" + thumbnail="feedbackspark.com.png" + /> + <Card + title="QuotesDomain" + href="https://www.quotesdomain.com/" + thumbnail="quotesdomain.com.png" + /> + <Card title="Saasfly" href="https://document.saasfly.io/" thumbnail="document.saasfly.io.png" /> + <Card + title="freeCodeCamp" + href="https://contribute.freecodecamp.org/intro/" + thumbnail="contribute.freecodecamp.org.png" + /> + <Card + title="Style Dictionary" + href="https://styledictionary.com/" + thumbnail="styledictionary.com.png" + /> + <Card title="CodeSweetly" href="https://codesweetly.com/" thumbnail="codesweetly.com.png" /> + <Card title="grpcmd" href="https://grpc.md/docs/" thumbnail="grpc.md.png" /> + <Card + title="Pokemon Database" + href="https://pokemon-siace.netlify.app/" + thumbnail="pokemon-siace.netlify.app.png" + /> + <Card + title="Cloudflare Docs" + href="https://developers.cloudflare.com/" + thumbnail="developers.cloudflare.com.png" + /> + <Card title="Open {re}Source" href="https://openresource.dev" thumbnail="openresource.dev.png" /> + <Card + title="Orbit CSS" + href="https://zumerlab.github.io/orbit-docs/" + thumbnail="zumerlab.github.io.orbit-docs.png" + /> + <Card + title="LaunchFast" + href="https://www.launchfa.st/documentation" + thumbnail="launchfa.st.png" + /> + <Card title="Capgo" href="https://capgo.app/docs" thumbnail="capgo.app.png" /> + <Card + title="React Bricks" + href="https://docs.reactbricks.com" + thumbnail="docs.reactbricks.com.png" + /> + <Card title="emoji-blast" href="https://emojiblast.dev" thumbnail="docs.emojiblast.dev.png" /> + <Card + title="Text To Table Converter" + href="https://texttotableconverter.com" + thumbnail="texttotableconverter.com.png" + /> + <Card + title="Isomorphic Validation" + href="https://itihon.github.io/isomorphic-validation/" + thumbnail="itihon.github.io-isomorphic-validation.png" + /> + <Card + title="Accessible Astro" + href="https://accessible-astro.incluud.dev" + thumbnail="accessible-astro.incluud.dev.png" + /> + <Card title="Learn AISO" href="https://learnaiso.com" thumbnail="learnaiso.com.png" /> + <Card title="PaperMC Docs" href="https://docs.papermc.io" thumbnail="docs.papermc.io.png" /> + <Card title="Bingo" href="https://create.bingo" thumbnail="create.bingo.png" /> + <Card title="OctoGuide" href="https://octo.guide" thumbnail="octo.guide.png" /> + <Card + title="Sonar" + href="https://sonar-team.github.io/doc/" + thumbnail="sonar-team.github.io.png" + /> + <Card title="Cookie API" href="https://docs.cookie-api.com" thumbnail="docs.cookie-api.com.png" /> + <Card title="Fluid DnD" href="https://fluid-dnd.netlify.app/" thumbnail="fluid-dnd.png" /> + <Card title="PyDocs" href="https://www.pydocs.site/en" thumbnail="www.pydocs.site.png" /> + <Card title="Fomr" href="https://fomr.io/help" thumbnail="fomr.io.png" /> + <Card + title="The Jotter | Bag of Tricks" + href="https://events-3bg.pages.dev/jotter" + thumbnail="events-3bg.pages.dev.png" + /> + <Card title="@vtbag" href="https://vtbag.dev" thumbnail="vtbag.dev.png" /> + <Card title="vlt docs" href="https://docs.vlt.sh/" thumbnail="docs.vlt.sh.png" /> + <Card + title="sharp" + href="https://sharp.pixelplumbing.com/" + thumbnail="sharp.pixelplumbing.com.png" + /> + <Card title="Netlify Docs" href="https://docs.netlify.com" thumbnail="docs.netlify.com.png" /> + <Card + title="Open AI Agents SDK" + href="https://openai.github.io/openai-agents-js/" + thumbnail="openai.github.io.png" + /> + <Card title="opencode" href="https://opencode.ai/docs" thumbnail="opencode.ai.png" /> + <Card title="Scalekit Docs" href="https://docs.scalekit.com/" thumbnail="docs.scalekit.com.png" /> + <Card title="Aptos Docs" href="https://aptos.dev" thumbnail="aptos.dev.png" /> + <Card title="OmniPrint Docs" href="https://omni-byte.com/docs/" thumbnail="omni-byte.com.png" /> + <Card title="Academeez" href="https://www.academeez.com/" thumbnail="academeez.com.png" /> + <Card title="openstatus Docs" href="https://docs.openstatus.dev" thumbnail="openstatus.dev.png" /> + <Card title="Saucer" href="https://saucer.app" thumbnail="saucer.app.png" /> + <Card title="lychee" href="https://lychee.cli.rs/" thumbnail="lychee.cli.rs.png" /> + <Card title="Biome" href="https://biomejs.dev/" thumbnail="biomejs.dev.png" /> + <Card title="aspire.dev" href="https://aspire.dev/" thumbnail="aspire.dev.png" /> + <Card title="bettercap" href="https://www.bettercap.org/" thumbnail="bettercap.org.png" /> + <Card title="modestbench" href="https://modestbench.dev/" thumbnail="modestbench.dev.png" /> + <Card title="LavaMoat" href="https://lavamoat.github.io/" thumbnail="lavamoat.github.io.png" /> + <Card title="STACKIT Docs" href="https://docs.stackit.cloud" thumbnail="docs.stackit.cloud.png" /> + <Card title="CatchIntent" href="https://catchintent.com/docs" thumbnail="catchintent.com.png" /> + <Card title="Actionbase" href="https://actionbase.io/" thumbnail="actionbase.io.png" /> + <Card title="Formware Help Center" href="https://formware.io/help/" thumbnail="formware.io.png" /> </FluidGrid> diff --git a/docs/src/components/sidebar-preview.astro b/docs/src/components/sidebar-preview.astro index 0865d2f6315..2ecdd9d32d5 100644 --- a/docs/src/components/sidebar-preview.astro +++ b/docs/src/components/sidebar-preview.astro @@ -1,13 +1,20 @@ --- -import type { AutoSidebarGroup, SidebarItem } from '../../../packages/starlight/utils/user-config'; +import type { + AutoSidebarGroup, + SidebarItem, + InternalSidebarLinkItem, +} from '../../../packages/starlight/schemas/sidebar'; import SidebarSublist from '../../../packages/starlight/components/SidebarSublist.astro'; -import type { SidebarEntry } from '../../../packages/starlight/utils/navigation'; +import type { Badge } from '../../../packages/starlight/schemas/badge'; +import type { SidebarEntry } from '../../../packages/starlight/utils/routing/types'; interface Props { config: SidebarConfig; } -type SidebarConfig = Exclude<SidebarItem, AutoSidebarGroup>[]; +type SidebarConfig = (Exclude<SidebarItem, AutoSidebarGroup | InternalSidebarLinkItem> & { + badge?: Badge; +})[]; const { config } = Astro.props; @@ -17,19 +24,22 @@ function makeEntries(items: SidebarConfig): SidebarEntry[] { return { type: 'link', label: item.label, - href: item.link, + // Empty hrefs are used to represent internal links that do not exist in the Starlight + // docs. Using a non-existing anchor link like `#_` will not trigger a page reload or any + // scrolling. + href: item.link.length > 0 ? item.link : '#_', isCurrent: false, badge: item.badge, + attrs: item.attrs ?? {}, }; } - item; - return { type: 'group', label: item.label, entries: makeEntries(item.items as SidebarConfig), collapsed: item.collapsed, + badge: item.badge, }; }); } @@ -44,6 +54,7 @@ function makeEntries(items: SidebarConfig): SidebarEntry[] { background-color: var(--sl-color-bg-sidebar); border: 1px solid var(--sl-color-gray-5); padding: 1rem var(--sl-sidebar-pad-x); - max-width: var(--sl-sidebar-width); + /* Matches `var(--sl-sidebar-width)`, but hardcoded to avoid being overridden when printing the page. */ + max-width: 18.75rem; } </style> diff --git a/docs/src/components/social-links-type.astro b/docs/src/components/social-links-type.astro new file mode 100644 index 00000000000..d60e2071639 --- /dev/null +++ b/docs/src/components/social-links-type.astro @@ -0,0 +1,10 @@ +--- +import { getRelativeLocaleUrl } from 'astro:i18n'; +const href = getRelativeLocaleUrl(Astro.currentLocale ?? 'en', '/reference/icons/'); +--- + +<code> + <Fragment set:text="Array<{" /> + label: string; icon: <a {href}>StarlightIcon</a>; href: string + <Fragment set:text="}>" /> +</code> diff --git a/docs/src/components/testimonial-grid.astro b/docs/src/components/testimonial-grid.astro new file mode 100644 index 00000000000..d8fc4ea8457 --- /dev/null +++ b/docs/src/components/testimonial-grid.astro @@ -0,0 +1,39 @@ +--- +interface Props { + title: string; +} + +const { title } = Astro.props; +--- + +<div class="testimonial-wrapper not-content" data-pagefind-ignore> + <h2 class="testimonial-grid-title">{title}</h2> + <ul class="testimonial-grid"> + <slot /> + </ul> +</div> + +<style> + .testimonial-wrapper { + margin-block: 7rem 2.5rem !important; + font-size: clamp(var(--sl-text-sm), calc(0.5rem + 1vw), var(--sl-text-body)); + } + .testimonial-grid-title { + text-align: center; + font-size: var(--sl-text-h3); + font-weight: 600; + color: var(--sl-color-white); + line-height: var(--sl-line-height-headings); + } + .testimonial-grid { + margin-top: 2.5rem; + display: grid; + gap: 5em; + padding-inline-start: 0; + } + @media (min-width: 50rem) { + .testimonial-grid { + grid-template-columns: 1fr 1fr; + } + } +</style> diff --git a/docs/src/components/testimonial.astro b/docs/src/components/testimonial.astro new file mode 100644 index 00000000000..4ba4fd00b9a --- /dev/null +++ b/docs/src/components/testimonial.astro @@ -0,0 +1,90 @@ +--- +import type { ImageMetadata } from 'astro'; +import { Image } from 'astro:assets'; + +interface Props { + handle: string; + name: string; + cite: string; +} + +const { name, handle, cite } = Astro.props; + +const avatars = import.meta.glob<{ default: ImageMetadata }>('../assets/testimonials/*.jpg'); +const avatar = avatars[`../assets/testimonials/${handle}.jpg`]; +if (!avatar) { + throw new Error(`Could not resolve testimonial avatar for @${handle}`); +} +const src = (await avatar()).default; +--- + +<li class="testimonial"> + <blockquote class="quote" cite={cite}> + <slot /> + </blockquote> + <div class="footer"> + <Image class="avatar" height="96" width="96" {src} alt="" /> + <div> + <p class="name">{name}</p> + <a href={cite} class="handle">@{handle}</a> + </div> + </div> +</li> + +<style> + .testimonial { + display: flex; + flex-direction: column; + gap: 1.5em; + } + @media (min-width: 50rem) { + .testimonial { + gap: 2em; + } + } + .quote { + position: relative; + padding-inline-start: 1.5em; + } + .quote::before { + position: absolute; + content: ''; + inset-block: 0.5em; + inset-inline-start: 0; + border-inline-start: 1px solid var(--sl-color-text-accent); + } + .quote > :global(* + *) { + margin-top: 0.75em; + } + + .footer { + display: flex; + gap: 1rem; + align-items: center; + } + .avatar { + --outline-color: rgba(255, 255, 255, 0.33); + outline: 1px solid var(--outline-color); + outline-offset: -1px; + border-radius: 99rem; + width: 4em; + height: 4em; + } + :global([data-theme='light']) .avatar { + --outline-color: rgba(23, 25, 30, 0.33); + } + + .name { + font-weight: 600; + font-size: var(--sl-text-h4); + color: var(--sl-color-white); + line-height: var(--sl-line-height-headings); + } + .handle { + text-underline-offset: 4px; + color: var(--sl-color-text-accent); + } + .handle:hover { + color: var(--sl-color-white); + } +</style> diff --git a/docs/src/components/theme-designer.astro b/docs/src/components/theme-designer.astro index a59c2890e0b..ed13418ed00 100644 --- a/docs/src/components/theme-designer.astro +++ b/docs/src/components/theme-designer.astro @@ -1,12 +1,16 @@ --- import { TabItem, Tabs } from '@astrojs/starlight/components'; -import ColorEditor, { Props as EditorProps } from './theme-designer/color-editor.astro'; -import Presets, { Props as PresetsProps } from './theme-designer/presets.astro'; +import ColorEditor, { type Props as EditorProps } from './theme-designer/color-editor.astro'; +import ContrastLevel, { + type Props as ContrastLevelProps, +} from './theme-designer/contrast-level.astro'; +import Presets, { type Props as PresetsProps } from './theme-designer/presets.astro'; import Preview from './theme-designer/preview.astro'; interface Props { labels: { presets: PresetsProps['labels']; + contrast: ContrastLevelProps['labels']; editor: EditorProps['labels'] & { accentColor: string; grayColor: string }; preview: Record< 'darkMode' | 'lightMode' | 'bodyText' | 'linkText' | 'dimText' | 'inlineCode', @@ -15,12 +19,14 @@ interface Props { }; } const { - labels: { presets, editor, preview }, + labels: { presets, contrast, editor, preview }, } = Astro.props; --- <Presets labels={presets} /> +<ContrastLevel labels={contrast} /> + <div> <theme-designer> <div class="sl-flex controls not-content"> @@ -52,7 +58,7 @@ const { <script> import { getPalettes } from './theme-designer/color-lib'; - import { store } from './theme-designer/store'; + import { store, minimumContrast } from './theme-designer/store'; class ThemeDesigner extends HTMLElement { #stylesheet = new CSSStyleSheet(); @@ -65,10 +71,15 @@ const { const onInput = () => this.#update(); store.accent.subscribe(onInput); store.gray.subscribe(onInput); + minimumContrast.subscribe(onInput); } #update() { - const palettes = getPalettes({ accent: store.accent.get(), gray: store.gray.get() }); + const palettes = getPalettes({ + accent: store.accent.get(), + gray: store.gray.get(), + minimumContrast: minimumContrast.get(), + }); this.#updatePreview(palettes); this.#updateStylesheet(palettes); this.#updateTailwindConfig(palettes); @@ -104,22 +115,20 @@ const { } #updateTailwindConfig({ dark, light }: ReturnType<typeof getPalettes>) { - const config = `const starlightPlugin = require('@astrojs/starlight-tailwind'); - -// Generated color palettes -const accent = { 200: '${dark['accent-high']}', 600: '${light.accent}', 900: '${light['accent-high']}', 950: '${dark['accent-low']}' }; -const gray = { 100: '${light['gray-7']}', 200: '${light['gray-6']}', 300: '${light['gray-5']}', 400: '${light['gray-4']}', 500: '${light['gray-3']}', 700: '${light['gray-2']}', 800: '${light['gray-1']}', 900: '${light.white}' }; - -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: { - colors: { accent, gray }, - }, - }, - plugins: [starlightPlugin()], -};`; + const config = `/* Generated accent color palettes. */ +--color-accent-200: ${dark['accent-high']}; +--color-accent-600: ${light.accent}; +--color-accent-900: ${light['accent-high']}; +--color-accent-950: ${dark['accent-low']}; +/* Generated gray color palettes. */ +--color-gray-100: ${light['gray-7']}; +--color-gray-200: ${light['gray-6']}; +--color-gray-300: ${light['gray-5']}; +--color-gray-400: ${light['gray-4']}; +--color-gray-500: ${light['gray-3']}; +--color-gray-700: ${light['gray-2']}; +--color-gray-800: ${light['gray-1']}; +--color-gray-900: ${light.white};`; const codePreview = this.querySelector('[data-theme-tailwind]'); if (codePreview) codePreview.innerHTML = config; } diff --git a/docs/src/components/theme-designer/atom.ts b/docs/src/components/theme-designer/atom.ts index e1f2518c4fc..140542f88c5 100644 --- a/docs/src/components/theme-designer/atom.ts +++ b/docs/src/components/theme-designer/atom.ts @@ -29,3 +29,7 @@ export function map<T extends Record<string, unknown>>(value: T): MapStore<T> { }; return atom; } + +export function atom<T>(value: T): Atom<T> { + return new Atom(value); +} diff --git a/docs/src/components/theme-designer/color-lib.ts b/docs/src/components/theme-designer/color-lib.ts index 27b52b52771..3ad21985f81 100644 --- a/docs/src/components/theme-designer/color-lib.ts +++ b/docs/src/components/theme-designer/color-lib.ts @@ -1,57 +1,121 @@ -import { useMode, modeOklch, modeRgb, formatHex, clampChroma } from 'culori/fn'; +import { + clampChroma, + formatHex, + modeLrgb, + modeOklch, + modeRgb, + useMode, + wcagContrast, + type Oklch, +} from 'culori/fn'; const rgb = useMode(modeRgb); export const oklch = useMode(modeOklch); +// We need to initialise LRGB support for culori’s `wcagContrast()` method. +useMode(modeLrgb); -/** Convert an OKLCH color to an RGB hex code. */ -export const oklchToHex = (l: number, c: number, h: number) => { - const okLchColor = oklch(`oklch(${l}% ${c} ${h})`)!; +/** Convert a culori OKLCH color object to an RGB hex code. */ +const oklchColorToHex = (okLchColor: Oklch) => { const rgbColor = rgb(clampChroma(okLchColor, 'oklch')); return formatHex(rgbColor); }; +/** Construct a culori OKLCH color object from LCH parameters. */ +const oklchColorFromParts = (l: number, c: number, h: number) => oklch(`oklch(${l}% ${c} ${h})`)!; +/** Convert OKLCH parameters to an RGB hex code. */ +export const oklchToHex = (l: number, c: number, h: number) => + oklchColorToHex(oklchColorFromParts(l, c, h)); + +/** + * Ensure a text colour passes a contrast threshold against a specific background colour. + * If necessary, colours will be darkened/lightened to increase contrast until the threshold is passed. + * + * @param text The text colour to adjust if necessary. + * @param bg The background colour to test contrast against. + * @param threshold The minimum contrast ratio required. Defaults to `4.5` to meet WCAG AA standards. + * @returns The adjusted text colour as a culori OKLCH color object. + */ +const contrastColor = (text: Oklch, bg: Oklch, threshold = 4.5): Oklch => { + /** Clone of the input foreground colour to mutate. */ + const fgColor = { ...text }; + // Brighten text in dark mode, darken text in light mode. + const increment = fgColor.l > bg.l ? 0.005 : -0.005; + while (wcagContrast(fgColor, bg) < threshold && fgColor.l < 100 && fgColor.l > 0) { + fgColor.l += increment; + } + return fgColor; +}; /** Generate dark and light palettes based on user-selected hue and chroma values. */ export function getPalettes(config: { accent: { hue: number; chroma: number }; gray: { hue: number; chroma: number }; + minimumContrast?: number; }) { const { accent: { hue: ah, chroma: ac }, gray: { hue: gh, chroma: gc }, + minimumContrast: mc, } = config; - return { + + const palettes = { dark: { // Accents - 'accent-low': oklchToHex(25.94, ac / 3, ah), - accent: oklchToHex(52.28, ac, ah), - 'accent-high': oklchToHex(83.38, ac / 3, ah), + 'accent-low': oklchColorFromParts(25.94, ac / 3, ah), + accent: oklchColorFromParts(52.28, ac, ah), + 'accent-high': oklchColorFromParts(83.38, ac / 3, ah), // Grays - white: oklchToHex(100, 0, 0), - 'gray-1': oklchToHex(94.77, gc / 2.5, gh), - 'gray-2': oklchToHex(81.34, gc / 2, gh), - 'gray-3': oklchToHex(63.78, gc, gh), - 'gray-4': oklchToHex(46.01, gc, gh), - 'gray-5': oklchToHex(34.09, gc, gh), - 'gray-6': oklchToHex(27.14, gc, gh), - black: oklchToHex(20.94, gc / 2, gh), + white: oklchColorFromParts(100, 0, 0), + 'gray-1': oklchColorFromParts(94.77, gc / 2.5, gh), + 'gray-2': oklchColorFromParts(81.34, gc / 2, gh), + 'gray-3': oklchColorFromParts(63.78, gc, gh), + 'gray-4': oklchColorFromParts(46.01, gc, gh), + 'gray-5': oklchColorFromParts(34.09, gc, gh), + 'gray-6': oklchColorFromParts(27.14, gc, gh), + black: oklchColorFromParts(20.94, gc / 2, gh), }, light: { // Accents - 'accent-low': oklchToHex(87.81, ac / 4, ah), - accent: oklchToHex(52.95, ac, ah), - 'accent-high': oklchToHex(31.77, ac / 2, ah), + 'accent-low': oklchColorFromParts(87.81, ac / 4, ah), + accent: oklchColorFromParts(52.95, ac, ah), + 'accent-high': oklchColorFromParts(31.77, ac / 2, ah), // Grays - white: oklchToHex(20.94, gc / 2, gh), - 'gray-1': oklchToHex(27.14, gc, gh), - 'gray-2': oklchToHex(34.09, gc, gh), - 'gray-3': oklchToHex(46.01, gc, gh), - 'gray-4': oklchToHex(63.78, gc, gh), - 'gray-5': oklchToHex(81.34, gc / 2, gh), - 'gray-6': oklchToHex(94.77, gc / 2.5, gh), - 'gray-7': oklchToHex(97.35, gc / 5, gh), - black: oklchToHex(100, 0, 0), + white: oklchColorFromParts(20.94, gc / 2, gh), + 'gray-1': oklchColorFromParts(27.14, gc, gh), + 'gray-2': oklchColorFromParts(34.09, gc, gh), + 'gray-3': oklchColorFromParts(46.01, gc, gh), + 'gray-4': oklchColorFromParts(63.78, gc, gh), + 'gray-5': oklchColorFromParts(81.34, gc / 2, gh), + 'gray-6': oklchColorFromParts(94.77, gc / 2.5, gh), + 'gray-7': oklchColorFromParts(97.35, gc / 5, gh), + black: oklchColorFromParts(100, 0, 0), }, }; + + // Ensure text shades have sufficient contrast against common background colours. + + // Dark mode: + // `gray-2` is used against `gray-5` in inline code snippets. + palettes.dark['gray-2'] = contrastColor(palettes.dark['gray-2'], palettes.dark['gray-5'], mc); + // `gray-3` is used in the table of contents. + palettes.dark['gray-3'] = contrastColor(palettes.dark['gray-3'], palettes.dark.black, mc); + + // Light mode: + // `accent` is used for links and link buttons and can be slightly under 7:1 for some hues. + palettes.light.accent = contrastColor(palettes.light.accent, palettes.light['gray-6'], mc); + // `gray-2` is used against `gray-6` in inline code snippets. + palettes.light['gray-2'] = contrastColor(palettes.light['gray-2'], palettes.light['gray-6'], mc); + // `gray-3` is used in the table of contents. + palettes.light['gray-3'] = contrastColor(palettes.light['gray-3'], palettes.light.black, mc); + + // Convert the palette from OKLCH to RGB hex codes. + return { + dark: Object.fromEntries( + Object.entries(palettes.dark).map(([key, color]) => [key, oklchColorToHex(color)]) + ) as Record<keyof typeof palettes.dark, string>, + light: Object.fromEntries( + Object.entries(palettes.light).map(([key, color]) => [key, oklchColorToHex(color)]) + ) as Record<keyof typeof palettes.light, string>, + }; } /* diff --git a/docs/src/components/theme-designer/contrast-level.astro b/docs/src/components/theme-designer/contrast-level.astro new file mode 100644 index 00000000000..6d89eb50c58 --- /dev/null +++ b/docs/src/components/theme-designer/contrast-level.astro @@ -0,0 +1,86 @@ +--- +export interface Props { + labels: { + label: string; + }; +} +const { labels = { label: 'WCAG Contrast Level' } } = Astro.props; +--- + +<contrast-level-toggle class="sl-flex"> + <fieldset class="not-content"> + <legend>{labels.label}</legend> + <div class="sl-flex"> + <label class="sl-flex"> + <input type="radio" name="contrast-level" value="4.5" checked /> + AA + </label> + <label class="sl-flex"> + <input type="radio" name="contrast-level" value="7" /> + AAA + </label> + </div> + </fieldset> +</contrast-level-toggle> + +<script> + import { minimumContrast } from './store'; + + class ContrastLevelToggle extends HTMLElement { + #fieldset = this.querySelector('fieldset')!; + constructor() { + super(); + this.#fieldset.addEventListener('input', (e) => { + if (e.target instanceof HTMLInputElement) { + const contrast = parseFloat(e.target.value); + minimumContrast.set(contrast); + } + }); + } + } + + customElements.define('contrast-level-toggle', ContrastLevelToggle); +</script> + +<style> + fieldset { + border: 0; + padding: 0; + } + fieldset > * { + float: left; + float: inline-start; + vertical-align: middle; + } + legend { + color: var(--sl-color-white); + margin-inline-end: 0.75rem; + } + label { + align-items: center; + padding: 0.25rem 0.75rem; + gap: 0.375rem; + background-color: var(--sl-color-gray-6); + font-size: var(--sl-text-xs); + cursor: pointer; + } + label:has(:focus-visible) { + outline: 2px solid; + outline-offset: -4px; + } + label:first-child { + border-start-start-radius: 99rem; + border-end-start-radius: 99rem; + } + label:last-child { + border-start-end-radius: 99rem; + border-end-end-radius: 99rem; + } + label:has(:checked) { + color: var(--sl-color-black); + background-color: var(--sl-color-text-accent); + } + input:focus-visible { + outline: none; + } +</style> diff --git a/docs/src/components/theme-designer/presets.astro b/docs/src/components/theme-designer/presets.astro index 140cf1ae4d8..b0c8d73d2a2 100644 --- a/docs/src/components/theme-designer/presets.astro +++ b/docs/src/components/theme-designer/presets.astro @@ -64,6 +64,10 @@ const resolvedPresets = Object.entries(presets).map(([key, preset]) => { font-size: var(--sl-text-xs); cursor: pointer; } + button:focus-visible { + outline: 2px solid; + outline-offset: -4px; + } :global([data-theme='light']) [data-preset] { background-color: var(--light-bg); color: var(--light-text); diff --git a/docs/src/components/theme-designer/preview.astro b/docs/src/components/theme-designer/preview.astro index 7dbfb7d86a9..d5bfdb7d237 100644 --- a/docs/src/components/theme-designer/preview.astro +++ b/docs/src/components/theme-designer/preview.astro @@ -21,9 +21,9 @@ const codeBg = light ? '--sl-color-gray-6' : '--sl-color-gray-5'; <div class="preview-card" {...attrs}> <h4>{light ? labels.lightMode : labels.darkMode}</h4> <p> - {labels.bodyText} - <span class="link" style={`color:var(${linkColor})`}>{labels.linkText}</span> - <span class="dim">{labels.dimText}</span> + {labels.bodyText}{' '} + <span class="link" style={`color:var(${linkColor})`}>{labels.linkText}</span>{' '} + <span class="dim">{labels.dimText}</span>{' '} <code style={`--sl-color-bg-inline-code:var(${codeBg})`}>{labels.inlineCode}</code> </p> <Palette {light} /> diff --git a/docs/src/components/theme-designer/store.ts b/docs/src/components/theme-designer/store.ts index 6eb1aa8249d..6466a845814 100644 --- a/docs/src/components/theme-designer/store.ts +++ b/docs/src/components/theme-designer/store.ts @@ -1,4 +1,4 @@ -import { map } from './atom'; +import { atom, map } from './atom'; export const presets = { ocean: { @@ -27,6 +27,7 @@ export const store = { accent: map(presets.default.accent), gray: map(presets.default.gray), }; +export const minimumContrast = atom(4.5); export const usePreset = (name: string) => { if (name in presets) { diff --git a/docs/src/components/theme-grid.astro b/docs/src/components/theme-grid.astro new file mode 100644 index 00000000000..64f4f9d3387 --- /dev/null +++ b/docs/src/components/theme-grid.astro @@ -0,0 +1,221 @@ +--- +import { Icon } from '@astrojs/starlight/components'; +import FluidGrid from './fluid-grid.astro'; +import MediaCard from './media-card.astro'; +import ThemeImage from './theme-image.astro'; + +interface Props { + labels: { + /** Accessible label for the theme toggle. */ + legend: string; + /** Accessible label for the dark color scheme variant. */ + dark: string; + /** Accessible label for the light color scheme variant. */ + light: string; + }; + themes: Array<{ + /** The name of this theme. */ + title: string; + /** A short description of this theme. */ + description: string; + /** URL for this theme’s website. Ideally should link to a demo site showing off the theme. */ + href: string; + previews: { + /** Image filename as found in `src/assets/themes/`, e.g. `ion-light.png`. */ + light: string; + /** Image filename as found in `src/assets/themes/`, e.g. `ion-dark.png`. */ + dark: string; + }; + }>; +} + +const { labels, themes } = Astro.props; +--- + +<starlight-theme-preview data-theme-preview="dark"> + <fieldset class="not-content sl-flex"> + { + /* `<legend>` is a pain to position, so we visually hide it and use an `aria-hidden` duplicate + for the visual representation. See https://adrianroselli.com/2022/07/use-legend-and-fieldset.html */ + } + <legend class="sr-only">{labels.legend}</legend> + <strong aria-hidden="true">{labels.legend}</strong> + { + (['dark', 'light'] as const).map((variant) => ( + <label class:list={['sl-flex', variant]} for={`${variant}-input`}> + <span class="radio"> + <Icon name="approve-check" /> + </span> + <span>{labels[variant]}</span> + <input + id={`${variant}-input`} + class="sr-only" + name="preview-theme" + value={variant} + type="radio" + checked={variant === 'dark'} + /> + </label> + )) + } + {/* If the currently active theme is light mode, default to showing the light mode previews. */} + <script is:inline> + // @ts-nocheck + const theme = document.documentElement.dataset.theme || 'dark'; + const input = document.querySelector(`input[value="${theme}"]`); + if (input) input.checked = true; + const customEl = document.querySelector('starlight-theme-preview'); + if (customEl) customEl.dataset.themePreview = theme; + </script> + </fieldset> + + <FluidGrid minColumnWidth="25rem" gap="clamp(1rem, calc(0.75rem + 1vw), 1.5rem)"> + { + themes.map( + async ({ title, description, href, previews }) => + previews && ( + <MediaCard {href}> + <div class="preview-images" slot="media" aria-hidden="true"> + <ThemeImage src={previews.light} class="light" /> + <ThemeImage src={previews.dark} class="dark" /> + </div> + <div class="meta sl-flex"> + <p class="title">{title}</p> + <p class="description" set:html={description} /> + </div> + </MediaCard> + ) + ) + } + </FluidGrid> +</starlight-theme-preview> + +<script> + customElements.define( + 'starlight-theme-preview', + class ThemePreview extends HTMLElement { + constructor() { + super(); + this.querySelector('fieldset')?.addEventListener('change', ({ target }) => { + if (target instanceof HTMLInputElement) { + this.dataset.themePreview = target.value; + } + }); + } + } + ); +</script> + +<style> + starlight-theme-preview { + --transition-time: 0.25s; + display: block; + } + + fieldset { + /* Snappier transitions for the form controls. */ + --transition-time: 0.15s; + + /* Stick the control bar to bottom of the nav bar on scroll. */ + position: sticky; + top: var(--sl-nav-height); + z-index: var(--sl-z-index-toc); + /* Pull the bar out so it is full width on small screens. */ + margin-inline: calc(-1 * var(--sl-nav-pad-x)); + padding: var(--sl-nav-pad-y) var(--sl-nav-pad-x); + /* Internal layout and styles. */ + gap: 1rem; + align-items: center; + justify-content: end; + border: 1px solid var(--sl-color-hairline); + font-size: var(--sl-text-sm); + background-color: var(--sl-color-bg-nav); + box-shadow: var(--sl-shadow-md); + } + @media (min-width: 50rem) and (max-width: 72rem) { + /* Medium-width screens need a custom value to avoid x-axis overflow. */ + fieldset { + margin-inline: -1rem; + } + } + + label { + align-items: center; + gap: 0.375rem; + color: var(--sl-color-gray-3); + transition: color var(--transition-time) ease-in-out; + } + label:hover, + label:has(:checked) { + color: var(--sl-color-white); + } + + .radio { + display: grid; + place-content: center; + border: 1px solid var(--sl-color-gray-5); + border-radius: 100%; + width: 1.5rem; + height: 1.5rem; + background-color: #000; + color: #fff; + transition: transform var(--transition-time) ease-in-out; + } + label:not(:has(:checked)):hover .radio { + transform: scale(1.15); + } + .light .radio { + background-color: #fff; + color: #000; + } + + /* Show the input’s focus ring on the label. */ + label:has(:focus-visible) { + outline: auto; + outline-offset: 2px; + } + + /* Show check mark icon only when input is checked. */ + label svg { + opacity: 0; + transition: opacity var(--transition-time) ease-in-out; + } + label:has(:checked) svg { + opacity: 1; + } + + /* Stack light/dark images in the same grid row and column. */ + .preview-images { + display: grid; + grid-template-columns: 1fr; + } + .preview-images > * { + grid-area: 1 / 1; + } + + /* Fade out the preview image that isn’t currently selected. */ + img { + transition: opacity var(--transition-time) ease-in-out; + } + [data-theme-preview='dark'] img.light { + opacity: 0; + } + [data-theme-preview='light'] img.dark { + opacity: 0; + } + + .meta { + padding: 1rem; + flex-direction: column; + gap: 0.5rem; + } + + .title { + font-size: var(--sl-text-lg); + } + + .description { + color: var(--sl-color-gray-3); + line-height: 1.5; + } +</style> diff --git a/docs/src/components/theme-image.astro b/docs/src/components/theme-image.astro new file mode 100644 index 00000000000..8cb10289f15 --- /dev/null +++ b/docs/src/components/theme-image.astro @@ -0,0 +1,37 @@ +--- +import { AstroError } from 'astro/errors'; +import { Image } from 'astro:assets'; + +interface Props { + src: string; + class: 'light' | 'dark'; +} + +const thumbnails = import.meta.glob<{ default: ImageMetadata }>( + '../assets/themes/*{.png,.jpg,.jpeg,.webp,.avif}' +); + +const thumbnail = thumbnails[`../assets/themes/${Astro.props.src}`]; +if (!thumbnail) { + throw new Error(`Could not resolve showcase thumbnail: ${Astro.props.src}`); +} +const src = (await thumbnail()).default; + +if (src.width !== 1280 || src.height !== 720) { + let fileName = src.src.split('/').pop(); + const queryIndex = fileName?.indexOf('?'); + if (queryIndex !== undefined && queryIndex > -1) { + fileName = fileName?.slice(0, queryIndex); + } + throw new AstroError( + 'Theme screenshots must be **1280×720px**', + `Dimensions of **${src.width}×${src.height}px** found for theme image \`${fileName || src.src}\`\n\n` + + `For best results:\n\n` + + `1. Take a screenshot of the site using a browser resized to **1280×720px**. The responsive view in dev tools can be helpful for this.\n\n` + + `2. Resize the screenshot to **1280×720px** if necessary and make sure it is saved as a PNG. An online tool like [Squoosh](https://squoosh.app/) can help here.\n\n` + + `See more details in the [Starlight contributing guide](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#themes)\n` + ); +} +--- + +<Image {src} alt="" width="960" class={Astro.props.class} /> diff --git a/docs/src/components/ui-strings-list.astro b/docs/src/components/ui-strings-list.astro new file mode 100644 index 00000000000..4684be73d64 --- /dev/null +++ b/docs/src/components/ui-strings-list.astro @@ -0,0 +1,6 @@ +--- +import { Code } from '@astrojs/starlight/components'; +import uiStrings from '../../../packages/starlight/translations/en.json?raw'; +--- + +<Code code={uiStrings} lang="json" /> diff --git a/docs/src/components/youtube-card.astro b/docs/src/components/youtube-card.astro new file mode 100644 index 00000000000..cc751f3bf62 --- /dev/null +++ b/docs/src/components/youtube-card.astro @@ -0,0 +1,34 @@ +--- +import { YouTube } from '@astro-community/astro-embed-youtube'; +import MediaCard from './media-card.astro'; + +export interface Props { + href: string; + title: string; + description?: string; +} +const { href, title, description } = Astro.props; +--- + +<MediaCard> + <YouTube slot="media" id={href} /> + <div class="meta sl-flex"> + <p class="title">{title}</p> + {description && <p class="description" set:html={description} />} + </div> +</MediaCard> + +<style> + .meta { + padding: 1rem; + flex-direction: column; + gap: 0.5rem; + } + .title { + font-size: var(--sl-text-lg); + } + .description { + color: var(--sl-color-gray-3); + line-height: 1.5; + } +</style> diff --git a/docs/src/components/youtube-grid.astro b/docs/src/components/youtube-grid.astro new file mode 100644 index 00000000000..27c8f961cff --- /dev/null +++ b/docs/src/components/youtube-grid.astro @@ -0,0 +1,12 @@ +--- +import FluidGrid from './fluid-grid.astro'; +import YoutubeCard, { type Props as CardProps } from './youtube-card.astro'; + +interface Props { + videos: CardProps[]; +} +--- + +<FluidGrid minColumnWidth="16rem"> + {Astro.props.videos.map((video) => <YoutubeCard {...video} />)} +</FluidGrid> diff --git a/docs/src/content.config.ts b/docs/src/content.config.ts new file mode 100644 index 00000000000..e47e819f524 --- /dev/null +++ b/docs/src/content.config.ts @@ -0,0 +1,18 @@ +import { defineCollection, z } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema(), + }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ + extend: z.object({ + 'component.preview': z.string().optional(), + }), + }), + }), +}; diff --git a/docs/src/content/config.ts b/docs/src/content/config.ts deleted file mode 100644 index 9df91b60444..00000000000 --- a/docs/src/content/config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineCollection } from 'astro:content'; -import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; - -export const collections = { - docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), -}; diff --git a/docs/src/content/docs/404.md b/docs/src/content/docs/404.md index 6772acfb8b4..5938da5874c 100644 --- a/docs/src/content/docs/404.md +++ b/docs/src/content/docs/404.md @@ -2,6 +2,7 @@ title: Not found template: splash editUrl: false +lastUpdated: false hero: title: '404' tagline: <strong>Houston, we have a problem.</strong> We couldn’t find that page.<br>Check the URL or try using the search bar. diff --git a/docs/src/content/docs/components/asides.mdx b/docs/src/content/docs/components/asides.mdx new file mode 100644 index 00000000000..329f3170958 --- /dev/null +++ b/docs/src/content/docs/components/asides.mdx @@ -0,0 +1,194 @@ +--- +title: Asides +description: Learn how to use asides in Starlight to display secondary information alongside a page’s main content. +--- + +import { Aside } from '@astrojs/starlight/components'; + +To display secondary information alongside a page’s main content, use the `<Aside>` component. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Aside slot="preview"> + Include nonessential, supplementary information in an `<Aside>`. +</Aside> + +</Preview> + +## Import + +```tsx +import { Aside } from '@astrojs/starlight/components'; +``` + +## Usage + +Display an aside (also known as “admonitions” or “callouts”) using the `<Aside>` component. + +An `<Aside>` can have an optional [`type`](#type) attribute, which controls the aside’s color, icon, and default title. + +<Preview> + +````mdx +import { Aside } from '@astrojs/starlight/components'; + +<Aside>Some content in an aside.</Aside> + +<Aside type="caution">Some cautionary content.</Aside> + +<Aside type="tip"> + +Other content is also supported in asides. + +```js +// A code snippet, for example. +``` + +</Aside> + +<Aside type="danger">Do not give your password to anyone.</Aside> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% aside %} +Some content in an aside. +{% /aside %} + +{% aside type="caution" %} +Some cautionary content. +{% /aside %} + +{% aside type="tip" %} +Other content is also supported in asides. + +```js +// A code snippet, for example. +``` +{% /aside %} + +{% aside type="danger" %} +Do not give your password to anyone. +{% /aside %} +```` + +</Fragment> + +<Fragment slot="preview"> + + <Aside>Some content in an aside.</Aside> + + <Aside type="caution">Some cautionary content.</Aside> + + <Aside type="tip"> + + Other content is also supported in asides. + + ```js + // A code snippet, for example. + ``` + + </Aside> + + <Aside type="danger">Do not give your password to anyone.</Aside> + +</Fragment> + +</Preview> + +Starlight also provides a custom syntax for rendering asides in Markdown and MDX as an alternative to the `<Aside>` component. +See the [“Authoring Content in Markdown”](/guides/authoring-content/#asides) guide for details of the custom syntax. + +### Use custom titles + +Override the default aside titles by using the [`title`](#title) attribute. + +<Preview> + +```mdx 'title="Watch out!"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="caution" title="Watch out!"> + A warning aside *with* a custom title. +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'title="Watch out!"' +{% aside type="caution" title="Watch out!" %} +A warning aside *with* a custom title. +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="caution" title="Watch out!"> + A warning aside *with* a custom title. +</Aside> + +</Preview> + +### Use custom icons + +Override the default aside icons by using the [`icon`](#icon) attribute set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons). + +<Preview> + +```mdx 'icon="starlight"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="tip" icon="starlight"> + A tip aside *with* a custom icon. +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="starlight"' +{% aside type="tip" icon="starlight" %} +A tip aside *with* a custom icon. +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="tip" icon="starlight"> + A tip aside *with* a custom icon. +</Aside> + +</Preview> + +## `<Aside>` Props + +**Implementation:** [`Aside.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Aside.astro) + +The `<Aside>` component accepts the following props: + +### `type` + +**type:** `'note' | 'tip' | 'caution' | 'danger'` +**default:** `'note'` + +The type of aside to display: + +- `note` asides (the default) are blue and display an information icon. +- `tip` asides are purple and display a rocket icon. +- `caution` asides are yellow and display a triangular warning icon. +- `danger` asides are red and display an octagonal warning icon. + +### `title` + +**type:** `string` + +The title of the aside to display. +If `title` is not set, the default title for the current aside `type` will be used. + +### `icon` + +**type:** [`StarlightIcon`](/reference/icons/#starlighticon-type) + +An aside can include an `icon` attribute set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons). diff --git a/docs/src/content/docs/components/badges.mdx b/docs/src/content/docs/components/badges.mdx new file mode 100644 index 00000000000..a247edd6063 --- /dev/null +++ b/docs/src/content/docs/components/badges.mdx @@ -0,0 +1,150 @@ +--- +title: Badges +description: Learn how to use badges in Starlight to display additional pieces of information. +--- + +import { Badge } from '@astrojs/starlight/components'; + +To display small pieces of information, such as a status or category, use the `<Badge>` component. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Badge slot="preview" text="New" /> + +</Preview> + +## Import + +```tsx +import { Badge } from '@astrojs/starlight/components'; +``` + +## Usage + +Display a badge using the `<Badge>` component and pass the content you want to display to the [`text`](#text) attribute of the `<Badge>` component. + +By default, the badge will use the theme accent color of your site. +To use a built-in badge color, set the [`variant`](#variant) attribute to one of the supported values. + +<Preview> + +```mdx +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="Note" variant="note" /> +- <Badge text="Success" variant="success" /> +- <Badge text="Tip" variant="tip" /> +- <Badge text="Caution" variant="caution" /> +- <Badge text="Danger" variant="danger" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +- {% badge text="Note" variant="note" /%} +- {% badge text="Success" variant="success" /%} +- {% badge text="Tip" variant="tip" /%} +- {% badge text="Caution" variant="caution" /%} +- {% badge text="Danger" variant="danger" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="Note" variant="note" /> + - <Badge text="Success" variant="success" /> + - <Badge text="Tip" variant="tip" /> + - <Badge text="Caution" variant="caution" /> + - <Badge text="Danger" variant="danger" /> +</Fragment> + +</Preview> + +### Use different sizes + +Use the [`size`](#size) attribute to control the size of the badge text. + +<Preview> + +```mdx /size="\w+"/ +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="New" size="small" /> +- <Badge text="New and improved" size="medium" /> +- <Badge text="New, improved, and bigger" size="large" /> +``` + +<Fragment slot="markdoc"> + +```markdoc /size="\w+"/ +- {% badge text="New" size="small" /%} +- {% badge text="New and improved" size="medium" /%} +- {% badge text="New, improved, and bigger" size="large" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="New" size="small" /> + - <Badge text="New and improved" size="medium" /> + - <Badge text="New, improved, and bigger" size="large" /> +</Fragment> + +</Preview> + +### Customize badges + +Customize badges by using any other `<span>` attributes such as `class` or `style` with custom CSS. + +<Preview> + +```mdx "style={{ fontStyle: 'italic' }}" +import { Badge } from '@astrojs/starlight/components'; + +<Badge text="Custom" variant="success" style={{ fontStyle: 'italic' }} /> +``` + +<Fragment slot="markdoc"> + +```markdoc 'style="font-style: italic;"' +{% badge text="Custom" variant="success" style="font-style: italic;" /%} +``` + +</Fragment> + +<Badge + slot="preview" + text="Custom" + variant="success" + style={{ fontStyle: 'italic' }} +/> + +</Preview> + +## `<Badge>` Props + +**Implementation:** [`Badge.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Badge.astro) + +The `<Badge>` component accepts the following props and also any [other `<span>` attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes): + +### `text` + +**required** +**type:** `string` + +The text content to display in the badge. + +### `variant` + +**type:** `'note' | 'danger' | 'success' | 'caution' | 'tip' | 'default'` +**default:** `'default'` + +The badge color variant to use: `note` (blue), `tip` (purple), `danger` (red), `caution` (orange), `success` (green), or `default` (theme accent color). + +### `size` + +**type:** `'small' | 'medium' | 'large'` + +Defines the size of the badge to display. diff --git a/docs/src/content/docs/components/card-grids.mdx b/docs/src/content/docs/components/card-grids.mdx new file mode 100644 index 00000000000..1485174e285 --- /dev/null +++ b/docs/src/content/docs/components/card-grids.mdx @@ -0,0 +1,173 @@ +--- +title: Card Grids +description: Learn how to wrap multiple cards in a grid in Starlight. +sidebar: + order: 4 +--- + +import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; + +To wrap multiple [`<Card>`](/components/cards/) or [`<LinkCard>`](/components/link-cards/) components in a grid, use the`<CardGrid>` component. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<CardGrid slot="preview"> + <Card title="Stars" icon="star"> + Sirius, Vega, Betelgeuse + </Card> + <Card title="Moons" icon="moon"> + Io, Europa, Ganymede + </Card> +</CardGrid> + +</Preview> + +## Import + +```tsx +import { CardGrid } from '@astrojs/starlight/components'; +``` + +## Usage + +### Group cards + +Display multiple [`<Card>`](/components/cards/) components side-by-side when there’s enough space by grouping them using the `<CardGrid>` component. + +<Preview> + +```mdx {3,10} +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <Card title="Check this out" icon="open-book"> + Interesting content you want to highlight. + </Card> + <Card title="Other feature" icon="information"> + More information you want to share. + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,9} +{% cardgrid %} +{% card title="Check this out" icon="open-book" %} +Interesting content you want to highlight. +{% /card %} + +{% card title="Other feature" icon="information" %} +More information you want to share. +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <Card title="Check this out" icon="open-book"> + Interesting content you want to highlight. + </Card> + <Card title="Other feature" icon="information"> + More information you want to share. + </Card> +</CardGrid> + +</Preview> + +### Group link cards + +Display multiple [`<LinkCard>`](/components/link-cards/) components side-by-side when there’s enough space by grouping them using the `<CardGrid>` component. + +<Preview> + +```mdx {3,6} +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <LinkCard title="Authoring Markdown" href="/guides/authoring-content/" /> + <LinkCard title="Components" href="/components/using-components/" /> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,5} +{% cardgrid %} +{% linkcard title="Authoring Markdown" href="/guides/authoring-content/" /%} + +{% linkcard title="Components" href="/components/using-components/" /%} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <LinkCard title="Authoring Markdown" href="/guides/authoring-content/" /> + <LinkCard title="Components" href="/components/using-components/" /> +</CardGrid> + +</Preview> + +### Stagger cards + +Shift the second column of the grid vertically to add visual interest by adding the [`stagger`](#stagger) attribute to the `<CardGrid>` component. + +This attribute is useful on your home page to display your project’s key features. + +<Preview> + +```mdx "stagger" +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid stagger> + <Card title="Check this out" icon="open-book"> + Interesting content you want to highlight. + </Card> + <Card title="Other feature" icon="information"> + More information you want to share. + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc "stagger=true" +{% cardgrid stagger=true %} +{% card title="Check this out" icon="open-book" %} +Interesting content you want to highlight. +{% /card %} + +{% card title="Other feature" icon="information" %} +More information you want to share. +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview" stagger> + <Card title="Check this out" icon="open-book"> + Interesting content you want to highlight. + </Card> + <Card title="Other feature" icon="information"> + More information you want to share. + </Card> +</CardGrid> + +</Preview> + +## `<CardGrid>` Props + +**Implementation:** [`CardGrid.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/CardGrid.astro) + +The `<CardGrid>` component accepts the following props: + +### `stagger` + +**type:** `boolean` + +Defines whether to stagger the cards in the grid or not. diff --git a/docs/src/content/docs/components/cards.mdx b/docs/src/content/docs/components/cards.mdx new file mode 100644 index 00000000000..0749d4e5f44 --- /dev/null +++ b/docs/src/content/docs/components/cards.mdx @@ -0,0 +1,108 @@ +--- +title: Cards +description: Learn how to use cards in Starlight to display content in a box. +sidebar: + order: 2 +--- + +import { Card } from '@astrojs/starlight/components'; + +To display content in a box matching Starlight’s styles, use the `<Card>` component. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Card slot="preview" title="Moons" icon="moon"> + Io, Europa, Ganymede +</Card> + +</Preview> + +## Import + +```tsx +import { Card } from '@astrojs/starlight/components'; +``` + +## Usage + +Display a card using the `<Card>` component and provide a [`title`](#title) for the card. + +<Preview> + +```mdx +import { Card } from '@astrojs/starlight/components'; + +<Card title="Check this out">Interesting content you want to highlight.</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% card title="Check this out" %} +Interesting content you want to highlight. +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="Check this out"> + Interesting content you want to highlight. +</Card> + +</Preview> + +### Add icons to cards + +Include an icon in a card using the [`icon`](#icon) attribute set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons). + +<Preview> + +```mdx 'icon="star"' +import { Card } from '@astrojs/starlight/components'; + +<Card title="Stars" icon="star"> + Sirius, Vega, Betelgeuse +</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="star"' +{% card title="Stars" icon="star" %} +Sirius, Vega, Betelgeuse +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="Stars" icon="star"> + Sirius, Vega, Betelgeuse +</Card> + +</Preview> + +### Group cards + +Display multiple cards side-by-side when there’s enough space by grouping them using the [`<CardGrid>`](/components/card-grids/) component. +See the [“Group cards”](/components/card-grids/#group-cards) guide for an example. + +## `<Card>` Props + +**Implementation:** [`Card.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Card.astro) + +The `<Card>` component accepts the following props: + +### `title` + +**required** +**type:** `string` + +The title of the card to display. + +### `icon` + +**type:** `string` + +A card can include an `icon` attribute set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons). diff --git a/docs/src/content/docs/components/code.mdx b/docs/src/content/docs/components/code.mdx new file mode 100644 index 00000000000..acd50b9479e --- /dev/null +++ b/docs/src/content/docs/components/code.mdx @@ -0,0 +1,103 @@ +--- +title: Code +description: Learn how to display syntax highlighted code in Starlight without Markdown code blocks. +--- + +import { Code } from '@astrojs/starlight/components'; + +The `<Code>` component renders syntax highlighted code. +It is useful when using a [Markdown code block](/guides/authoring-content/#code-blocks) is not possible, for example, to render data coming from external sources like files, databases, or APIs. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Code + slot="preview" + code={`## Welcome + +Hello from **space**!`} +lang="md" +title="example.md" +ins={3} +/> + +</Preview> + +## Import + +```tsx +import { Code } from '@astrojs/starlight/components'; +``` + +## Usage + +Use the `<Code>` component to render syntax highlighted code, for example when displaying code fetched from external sources. + +See the [Expressive Code “Code Component” docs](https://expressive-code.com/key-features/code-component/) for full details on how to use the `<Code>` component and the list of available props. + +<Preview> + +```mdx +import { Code } from '@astrojs/starlight/components'; + +export const exampleCode = `console.log('This could come from a file or CMS!');`; +export const fileName = 'example.js'; +export const highlights = ['file', 'CMS']; + +<Code code={exampleCode} lang="js" title={fileName} mark={highlights} /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% code + code="console.log('This could come from a file or CMS!');" + lang="js" + title="example.js" + meta="'file' 'CMS'" /%} +``` + +</Fragment> + +export const exampleCode = `console.log('This could come from a file or CMS!');`; +export const fileName = 'example.js'; +export const highlights = ['file', 'CMS']; + +<Code + slot="preview" + code={exampleCode} + lang="js" + title={fileName} + mark={highlights} +/> + +</Preview> + +### Display imported code + +In MDX files and Astro components, use [Vite’s `?raw` import suffix](https://vite.dev/guide/assets#importing-asset-as-string) to import any code file as a string. +You can then pass this imported string to the `<Code>` component to include it on your page. + +<Preview> + +```mdx "?raw" +# src/content/docs/example.mdx + +import { Code } from '@astrojs/starlight/components'; +import importedCode from '/tsconfig.json?raw'; + +<Code code={importedCode} lang="json" title="tsconfig.json" /> +``` + +import importedCode from '../../../../../examples/basics/tsconfig.json?raw'; + +<Code slot="preview" code={importedCode} lang="json" title="tsconfig.json" /> + +</Preview> + +## `<Code>` Props + +**Implementation:** [`Code.astro`](https://github.com/expressive-code/expressive-code/blob/main/packages/astro-expressive-code/components/Code.astro) + +The `<Code>` component accepts all the props documented in the [Expressive Code “Code Component” docs](https://expressive-code.com/key-features/code-component/#available-props). diff --git a/docs/src/content/docs/components/file-tree.mdx b/docs/src/content/docs/components/file-tree.mdx new file mode 100644 index 00000000000..82108e1d52d --- /dev/null +++ b/docs/src/content/docs/components/file-tree.mdx @@ -0,0 +1,265 @@ +--- +title: File Tree +description: Learn how to display the structure of a directory with file icons and collapsible sub-directories in Starlight. +--- + +import { FileTree } from '@astrojs/starlight/components'; + +To display the structure of a directory with file icons and collapsible sub-directories, use the `<FileTree>` component. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<FileTree slot="preview"> + +- astro.config.mjs an **important** file +- package.json +- README.md +- src + - components + - **Header.astro** + - … +- pages/ + +</FileTree> + +</Preview> + +## Import + +```tsx +import { FileTree } from '@astrojs/starlight/components'; +``` + +## Usage + +Display a file tree with file icons and collapsible sub-directories using the `<FileTree>` component. + +Specify the structure of your files and directories with an [unordered Markdown list](https://www.markdownguide.org/basic-syntax/#unordered-lists) inside `<FileTree>`. +Create a sub-directory using a nested list or add a `/` to the end of a list item to render it as a directory without specific content. + +<Preview> + +```mdx +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% filetree %} +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> + +</Preview> + +### Highlight entries + +Make a file or directory stand out by making its name bold, e.g. `**README.md**`. + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - **Header.astro** + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> + +</Preview> + +### Add comments + +Add a comment to a file or directory by adding more text after the name. +Inline Markdown formatting such as bold and italics is supported in comments. + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro an **important** file + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - Header.astro an **important** file + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro an **important** file + - Title.astro + +</FileTree> + +</Preview> + +### Add placeholders + +Add placeholder files and directories by using either `...` or `…` as the name. +This can be useful to indicate to a reader that a folder is expected to contain more items without specifying them all explicitly. + +<Preview> + +```mdx {8} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro + - … + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {5} +{% filetree %} +- src + - components + - Header.astro + - … +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro + - … + +</FileTree> + +</Preview> + +### Escape special characters + +Escape special characters such as underscores or spaces in filenames by wrapping the filename in code backticks. + +<Preview> + +```mdx +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- `__init__.py` +- `Hello world.txt` +- **`READ ME FIRST.md`** + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% filetree %} +- `__init__.py` +- `Hello world.txt` +- **`READ ME FIRST.md`** +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- `__init__.py` +- `Hello world.txt` +- **`READ ME FIRST.md`** + +</FileTree> + +</Preview> + +## `<FileTree>` Props + +**Implementation:** [`FileTree.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/FileTree.astro) + +The `<FileTree>` component does not accept any props. diff --git a/docs/src/content/docs/components/icons.mdx b/docs/src/content/docs/components/icons.mdx new file mode 100644 index 00000000000..745f4f7e395 --- /dev/null +++ b/docs/src/content/docs/components/icons.mdx @@ -0,0 +1,128 @@ +--- +title: Icons +description: Learn how to display icons in Starlight. +--- + +import { Icon } from '@astrojs/starlight/components'; + +To display icons from Starlight’s [built-in icon set](/reference/icons/#all-icons), use the `<Icon>` component. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Icon + slot="preview" + name="open-book" + color="var(--sl-color-text-accent)" + size="4rem" +/> + +</Preview> + +## Import + +```tsx +import { Icon } from '@astrojs/starlight/components'; +``` + +## Usage + +Display an icon using the `<Icon>` component. +An icon requires a [`name`](#name) set to [one of Starlight’s built-in icons](/reference/icons/#all-icons) and can optionally include a [`label`](#label) to provide context for screen readers. + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" /> +<Icon name="starlight" label="The Starlight logo" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" /%} +{% icon name="starlight" label="The Starlight logo" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" /> + <Icon name="starlight" label="The Starlight logo" /> +</Fragment> + +</Preview> + +### Customize icons + +The [`size`](#size) and [`color`](#color) attributes can be used to adjust the icon’s appearance using CSS units and color values. +The [`class`](#class) attribute can be used to add custom CSS classes to the icon. + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" color="goldenrod" size="2rem" /> +<Icon name="rocket" color="var(--sl-color-text-accent)" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" color="goldenrod" size="2rem" /%} +{% icon name="rocket" color="var(--sl-color-text-accent)" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" color="goldenrod" size="2rem" /> + <Icon name="rocket" color="var(--sl-color-text-accent)" /> +</Fragment> + +</Preview> + +## `<Icon>` Props + +**Implementation:** [`Icon.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Icon.astro) + +The `<Icon>` component accepts the following props: + +### `name` + +**required** +**type:** [`StarlightIcon`](/reference/icons/#starlighticon-type) + +The name of the icon to display set to [one of Starlight’s built-in icons](/reference/icons/#all-icons). + +### `label` + +**type:** `string` + +An optional label to provide context for assistive technologies, such as screen readers. + +When `label` is not set, the icon will be completely hidden from assistive technologies. +In this case, make sure the context is still understandable without the icon. +For example, a link containing only the icon **must** include the `label` attribute in order to be accessible, but if a link contains text and the icon is purely decorative, omitting the `label` may make sense. + +### `size` + +**type:** `string` + +The size of the icon using CSS units. + +### `color` + +**type:** `string` + +The color of the icon using a CSS color value. + +### `class` + +**type:** `string` + +Custom CSS classes to add to the icon. diff --git a/docs/src/content/docs/components/link-buttons.mdx b/docs/src/content/docs/components/link-buttons.mdx new file mode 100644 index 00000000000..008adc22c54 --- /dev/null +++ b/docs/src/content/docs/components/link-buttons.mdx @@ -0,0 +1,145 @@ +--- +title: Link Buttons +description: Learn how to create link buttons in Starlight for visually distinct call-to-action links. +--- + +import { LinkButton } from '@astrojs/starlight/components'; + +To display visually distinct call-to-action links, use the `<LinkButton>` component. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkButton slot="preview" href="/getting-started/"> + Read the docs +</LinkButton> + +</Preview> + +## Import + +```tsx +import { LinkButton } from '@astrojs/starlight/components'; +``` + +## Usage + +Use the `<LinkButton>` component to display a visually distinct call-to-action link. +A link button is useful for directing users to the most relevant or actionable content and is often used on landing pages. + +A `<LinkButton>` requires an [`href`](#href) attribute. +Optionally, customize the appearance of the link button using the [`variant`](#variant) attribute, which can be set to `primary` (the default), `secondary`, or `minimal`. + +<Preview> + +```mdx +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton href="/getting-started/">Get started</LinkButton> +<LinkButton href="/reference/configuration/" variant="secondary"> + Configuration Reference +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkbutton href="/getting-started/" %}Get started{% /linkbutton %} + +{% linkbutton href="/reference/configuration/" variant="secondary" %} +Configuration Reference +{% /linkbutton %} +``` + +</Fragment> + +<Fragment slot="preview"> + <LinkButton href="/getting-started/">Get started</LinkButton> + <LinkButton href="/reference/configuration/" variant="secondary"> + Configuration Reference + </LinkButton> +</Fragment> + +</Preview> + +### Add icons to link buttons + +Include an icon in a link button using the [`icon`](#icon) attribute set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons). + +The [`iconPlacement`](#iconplacement) attribute can be used to place the icon before the text by setting it to `start` (defaults to `end`). + +<Preview> + +```mdx {6-7} +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" +> + Related: Astro +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc {4-5} +{% linkbutton + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" %} +Related: Astro +{% /linkbutton %} +``` + +</Fragment> + +<LinkButton + slot="preview" + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" +> + Related: Astro +</LinkButton> + +</Preview> + +## `<LinkButton>` Props + +**Implementation:** [`LinkButton.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkButton.astro) + +The `<LinkButton>` component accepts the following props and also any [other `<a>` attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a): + +### `href` + +**required** +**type:** `string` + +The URL that the link button points to. + +### `variant` + +**type:** `'primary' | 'secondary' | 'minimal'` +**default:** `'primary'` + +The appearance of the link button. +Set to `primary` for a prominent call-to-action link using the theme’s accent color, `secondary` for a less prominent link, or `minimal` for a link with minimal styling. + +### `icon` + +**type:** `string` + +A link button can include an `icon` attribute set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons). + +### `iconPlacement` + +**type:** `'start' | 'end'` +**default:** `'end'` + +Determines the placement of the icon in relation to the link button text. diff --git a/docs/src/content/docs/components/link-cards.mdx b/docs/src/content/docs/components/link-cards.mdx new file mode 100644 index 00000000000..3cc394acd16 --- /dev/null +++ b/docs/src/content/docs/components/link-cards.mdx @@ -0,0 +1,125 @@ +--- +title: Link Cards +description: Learn how to display links prominently as cards in Starlight. +sidebar: + order: 3 +--- + +import { LinkCard } from '@astrojs/starlight/components'; + +To display links to different pages prominently, use the `<LinkCard>` component. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkCard + slot="preview" + title="Customizing Starlight" + description="Learn how to make your Starlight site your own with custom styles, fonts, and more." + href="/guides/customization/" +/> + +</Preview> + +## Import + +```tsx +import { LinkCard } from '@astrojs/starlight/components'; +``` + +## Usage + +Display a link prominently using the `<LinkCard>` component. +Each `<LinkCard>` requires a [`title`](#title) and an [`href`](#href) attribute. + +<Preview> + +```mdx +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard title="Authoring Markdown" href="/guides/authoring-content/" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkcard title="Authoring Markdown" href="/guides/authoring-content/" /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="Authoring Markdown" + href="/guides/authoring-content/" +/> + +</Preview> + +### Add a link description + +Add a short description to a link card using the [`description`](#description) attribute. + +<Preview> + +```mdx {6} +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard + title="Internationalization" + href="/guides/i18n/" + description="Configure Starlight to support multiple languages." +/> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% linkcard + title="Internationalization" + href="/guides/i18n/" + description="Configure Starlight to support multiple languages." /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="Internationalization" + href="/guides/i18n/" + description="Configure Starlight to support multiple languages." +/> + +</Preview> + +### Group link cards + +Display multiple link cards side-by-side when there’s enough space by grouping them using the [`<CardGrid>`](/components/card-grids/) component. +See the [“Group link cards”](/components/card-grids/#group-link-cards) guide for an example. + +## `<LinkCard>` Props + +**Implementation:** [`LinkCard.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkCard.astro) + +The `<LinkCard>` component accepts the following props, as well as all other [`<a>` element attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a): + +### `title` + +**required** +**type:** `string` + +The title of the link card to display. + +### `href` + +**required** +**type:** `string` + +The URL to link to when the card is interacted with. + +### `description` + +**type:** `string` + +An optional description to display below the title. diff --git a/docs/src/content/docs/components/steps.mdx b/docs/src/content/docs/components/steps.mdx new file mode 100644 index 00000000000..4f30b7ffdf9 --- /dev/null +++ b/docs/src/content/docs/components/steps.mdx @@ -0,0 +1,120 @@ +--- +title: Steps +description: Learn how to style numbered lists of tasks to create step-by-step guides in Starlight. +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +To style a numbered list of tasks to create step-by-step guides, use the `<Steps>` component. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Steps slot="preview"> + +1. Create a new Starlight project: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm create astro@latest -- --template starlight + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm create astro --template starlight + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn create astro --template starlight + ``` + + </TabItem> + + </Tabs> + +2. Write your first documentation page. + +</Steps> + +</Preview> + +## Import + +```tsx +import { Steps } from '@astrojs/starlight/components'; +``` + +## Usage + +Use the `<Steps>` component to style numbered lists of tasks. +This is useful for more complex step-by-step guides where each step needs to be clearly highlighted. + +Wrap `<Steps>` around a standard Markdown ordered list. +All the usual Markdown syntax is applicable inside `<Steps>`. + +<Preview> + +````mdx +import { Steps } from '@astrojs/starlight/components'; + +<Steps> + +1. Import the component into your MDX file: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Wrap `<Steps>` around your ordered list items. + +</Steps> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% steps %} + +1. Import the component into your MDX file: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Wrap `<Steps>` around your ordered list items. + +{% /steps %} +```` + +</Fragment> + +<Steps slot="preview"> + +1. Import the component into your MDX file: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Wrap `<Steps>` around your ordered list items. + +</Steps> + +</Preview> + +## `<Steps>` Props + +**Implementation:** [`Steps.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Steps.astro) + +The `<Steps>` component does not accept any props. diff --git a/docs/src/content/docs/components/tabs.mdx b/docs/src/content/docs/components/tabs.mdx new file mode 100644 index 00000000000..c530e2c8447 --- /dev/null +++ b/docs/src/content/docs/components/tabs.mdx @@ -0,0 +1,221 @@ +--- +title: Tabs +description: Learn how to create tabbed interfaces in Starlight to group equivalent information. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +To create a tabbed interface use the `<Tabs>` and `<TabItem>` components. +Tabs are useful for grouping equivalent information where a user only needs to see one of several options. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Tabs slot="preview"> + <TabItem label="Stars">Sirius, Vega, Betelgeuse</TabItem> + <TabItem label="Moons">Io, Europa, Ganymede</TabItem> +</Tabs> + +</Preview> + +## Import + +```tsx +import { Tabs, TabItem } from '@astrojs/starlight/components'; +``` + +## Usage + +Display a tabbed interface using the `<Tabs>` and `<TabItem>` components. +Each `<TabItem>` must have a [`label`](#label) to display to users. + +<Preview> + +```mdx +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="Stars">Sirius, Vega, Betelgeuse</TabItem> + <TabItem label="Moons">Io, Europa, Ganymede</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% tabs %} +{% tabitem label="Stars" %} +Sirius, Vega, Betelgeuse +{% /tabitem %} + +{% tabitem label="Moons" %} +Io, Europa, Ganymede +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="Stars">Sirius, Vega, Betelgeuse</TabItem> + <TabItem label="Moons">Io, Europa, Ganymede</TabItem> +</Tabs> + +</Preview> + +### Sync tabs + +Keep multiple tab groups synchronized by adding the [`syncKey`](#synckey) attribute. + +All `<Tabs>` on a page with the same `syncKey` value will display the same active label. +This allows your reader to choose once (e.g. their operating system or package manager), and see their choice persisted across page navigations. + +To synchronize related tabs, add an identical `syncKey` property to each `<Tabs>` component and ensure that they all use the same `<TabItem>` labels: + +<Preview> + +```mdx 'syncKey="constellations"' +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +_Some stars:_ + +<Tabs syncKey="constellations"> + <TabItem label="Orion">Bellatrix, Rigel, Betelgeuse</TabItem> + <TabItem label="Gemini">Pollux, Castor A, Castor B</TabItem> +</Tabs> + +_Some exoplanets:_ + +<Tabs syncKey="constellations"> + <TabItem label="Orion">HD 34445 b, Gliese 179 b, Wasp-82 b</TabItem> + <TabItem label="Gemini">Pollux b, HAT-P-24b, HD 50554 b</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc 'syncKey="constellations"' +_Some stars:_ + +{% tabs syncKey="constellations" %} +{% tabitem label="Orion" %} +Bellatrix, Rigel, Betelgeuse +{% /tabitem %} + +{% tabitem label="Gemini" %} +Pollux, Castor A, Castor B +{% /tabitem %} +{% /tabs %} + +_Some exoplanets:_ + +{% tabs syncKey="constellations" %} +{% tabitem label="Orion" %} +HD 34445 b, Gliese 179 b, Wasp-82 b +{% /tabitem %} + +{% tabitem label="Gemini" %} +Pollux b, HAT-P-24b, HD 50554 b +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Fragment slot="preview"> + +_Some stars:_ + +<Tabs syncKey="constellations"> + <TabItem label="Orion">Bellatrix, Rigel, Betelgeuse</TabItem> + <TabItem label="Gemini">Pollux, Castor A, Castor B</TabItem> +</Tabs> + +_Some exoplanets:_ + +<Tabs syncKey="constellations"> + <TabItem label="Orion">HD 34445 b, Gliese 179 b, Wasp-82 b</TabItem> + <TabItem label="Gemini">Pollux b, HAT-P-24b, HD 50554 b</TabItem> +</Tabs> + +</Fragment> + +</Preview> + +### Add icons to tabs + +Include an icon in a tab item using the [`icon`](#icon) attribute set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons) to display an icon next to the label. + +<Preview> + +```mdx /icon="\w+"/ +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="Stars" icon="star"> + Sirius, Vega, Betelgeuse + </TabItem> + <TabItem label="Moons" icon="moon"> + Io, Europa, Ganymede + </TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc /icon="\w+"/ +{% tabs %} +{% tabitem label="Stars" icon="star" %} +Sirius, Vega, Betelgeuse +{% /tabitem %} + +{% tabitem label="Moons" icon="moon" %} +Io, Europa, Ganymede +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="Stars" icon="star"> + Sirius, Vega, Betelgeuse + </TabItem> + <TabItem label="Moons" icon="moon"> + Io, Europa, Ganymede + </TabItem> +</Tabs> + +</Preview> + +## `<Tabs>` Props + +**Implementation:** [`Tabs.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Tabs.astro) + +The `<Tabs>` component groups multiple `<TabItem>` components together and accepts the following props: + +### `syncKey` + +**type:** `string` + +A key used to keep multiple tab groups synchronized across multiple pages. + +## `<TabItem>` Props + +**Implementation:** [`TabItem.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/TabItem.astro) + +A set of tabs is composed of tab items, each with the following props: + +### `label` + +**required** +**type:** `string` + +A tab item must include a `label` attribute set to the text that will be displayed in the tab. + +### `icon` + +**type:** `string` + +Each tab item can include an `icon` attribute set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons) to display an icon next to the label. diff --git a/docs/src/content/docs/components/using-components.mdx b/docs/src/content/docs/components/using-components.mdx new file mode 100644 index 00000000000..354d0d35624 --- /dev/null +++ b/docs/src/content/docs/components/using-components.mdx @@ -0,0 +1,94 @@ +--- +title: Using Components +description: Using components in MDX and Markdoc with Starlight. +sidebar: + order: 1 +--- + +Components let you easily reuse a piece of UI or styling consistently. +Examples might include a link card or a YouTube embed. +Starlight supports the use of components in [MDX](https://mdxjs.com/) and [Markdoc](https://markdoc.dev/) files and provides some common components for you to use. + +[Learn more about building components in the Astro Docs](https://docs.astro.build/en/basics/astro-components/). + +## Using a component in MDX + +You can use a component by importing it into your MDX file and then rendering it as a JSX tag. +These look like HTML tags but start with an uppercase letter matching the name in your `import` statement: + +```mdx +--- +# src/content/docs/example.mdx +title: Welcome to my docs +--- + +import { Icon } from '@astrojs/starlight/components'; +import CustomCard from '../../components/CustomCard.astro'; + +<Icon name="open-book" /> + +<CustomCard>Components can also contain **nested content**.</CustomCard> +``` + +Because Starlight is powered by Astro, you can add support for components built with any [supported UI framework (React, Preact, Svelte, Vue, Solid, and Alpine)](https://docs.astro.build/en/guides/framework-components/) in your MDX files. +Learn more about [using components in MDX](https://docs.astro.build/en/guides/integrations-guide/mdx/#using-components-in-mdx) in the Astro docs. + +## Using a component in Markdoc + +Add support for authoring content in Markdoc by following our [Markdoc set-up guide](/guides/authoring-content/#markdoc). + +Using the Starlight Markdoc preset, you can use Starlight’s built-in components with Markdoc’s `{% %}` tag syntax. +Unlike MDX, components in Markdoc do not need to be imported. +The following example renders Starlight’s [card component](/components/cards/) in a Markdoc file: + +```markdoc +--- +# src/content/docs/example.mdoc +title: Welcome to my docs +--- + +{% card title="Stars" icon="star" %} +Sirius, Vega, Betelgeuse +{% /card %} +``` + +See the [Astro Markdoc integration documentation](https://docs.astro.build/en/guides/integrations-guide/markdoc/#render-components) for more information on how to use components in Markdoc files. + +## Built-in components + +Starlight provides built-in components for common documentation use cases. +These components are available from the `@astrojs/starlight/components` package in MDX files and from the [Starlight Markdoc preset](/guides/authoring-content/#markdoc) in Markdoc files. + +See the sidebar for a list of available components and how to use them. + +## Compatibility with Starlight’s styles + +Starlight applies default styling to your Markdown content, for example, adding margin between elements. +If these styles conflict with your component’s appearance, set the `not-content` class on your component to disable them. + +```astro 'class="not-content"' +--- +// src/components/Example.astro +--- + +<div class="not-content"> + <p>Not impacted by Starlight’s default content styling.</p> +</div> +``` + +## Component props + +Use the [`ComponentProps`](https://docs.astro.build/en/guides/typescript/#componentprops-type) type from `astro/types` to reference the `Props` accepted by a component even if they are not exported by the component itself. +This can be helpful when wrapping or extending an existing component. + +The following example uses `ComponentProps` to get the type of the props accepted by Starlight’s built-in `Badge` component: + +```astro +--- +// src/components/Example.astro +import type { ComponentProps } from 'astro/types'; +import { Badge } from '@astrojs/starlight/components'; + +type BadgeProps = ComponentProps<typeof Badge>; +--- +``` diff --git a/docs/src/content/docs/da/404.md b/docs/src/content/docs/da/404.md new file mode 100644 index 00000000000..35f4b501a27 --- /dev/null +++ b/docs/src/content/docs/da/404.md @@ -0,0 +1,14 @@ +--- +title: Ikke Fundet +template: splash +editUrl: false +lastUpdated: false +hero: + title: '404' + tagline: <strong>Houston, vi har et problem.</strong> Vi kunne ikke finde den side.<br>Check URL'en eller prøv at bruge søgefeltet. + actions: + - text: Gå til hjem + icon: right-arrow + link: /da/ + variant: primary +--- diff --git a/docs/src/content/docs/da/index.mdx b/docs/src/content/docs/da/index.mdx new file mode 100644 index 00000000000..eddf756641e --- /dev/null +++ b/docs/src/content/docs/da/index.mdx @@ -0,0 +1,52 @@ +--- +title: Starlight 🌟 Byg dokumentationssider med Astro +description: Starlight hjælper dig med at bygge smukke og hurtige dokumentationssider med Astro. +template: splash +editUrl: false +lastUpdated: false +hero: + title: Få din dokumentation til at skinne med Starlight + tagline: Alt du har brug for, for at bygge en skindende dokumentationsside. Hurtig, tilgængelig og nem at bruge. + image: + file: ~/assets/hero-star.webp + actions: + - text: Kom igang + icon: right-arrow + link: /da/getting-started/ + - text: Se på GitHub + icon: external + variant: minimal + link: https://github.com/withastro/starlight +--- + +import { CardGrid, Card } from '@astrojs/starlight/components'; +import AboutAstro from '~/components/about-astro.astro'; + +<CardGrid stagger> + <Card title="Documentation, der begejstrer" icon="open-book"> + Inkluderer: Sidenavigation, søg, internationalisering, SEO, nem at læse + typografi, kodefremhævning, mørk tilstand og mere. + </Card> + <Card title="Drevet af Astro" icon="rocket"> + Udnyt den fulde kraft og udevne af Astro. Udvid Starlight med dine yndlings + Astro integrationer og biblioteker + </Card> + <Card title="Markdown, Markdoc og MDX" icon="document"> + Anvend dit yndlings markup sprog. Starlight giver dig indbygget + Frontmatter-validering med TypeScript type-sikkerhed. + </Card> + <Card title="Anvend dine egne UI-komponenter" icon="puzzle"> + Starlight ships as a framework-agnostic, complete docs solution. Extend with + React, Vue, Svelte, Solid, and more. Starlight bliver leveret som en fuldent + dokumentations-løsning, der er ligeglad, med hvilket framework du bruger. + Udvid med React, Vue, Svelte, Solid, og mere. + </Card> +</CardGrid> + +<AboutAstro title="Bragt til dig af"> +Astro er et all-in-one web framework, der er bygget til udevne. +Hiv dit indhold ned fra hvor som helst og indsæt det hvor som helst, alt sammen drevet af dine yndlings UI-komponenter og biblioteker. + +[Lær mere om Astro](https://astro.build/) + +</AboutAstro> diff --git a/docs/src/content/docs/de/404.md b/docs/src/content/docs/de/404.md index 6a86c88979b..a1013c93647 100644 --- a/docs/src/content/docs/de/404.md +++ b/docs/src/content/docs/de/404.md @@ -2,6 +2,7 @@ title: Nicht gefunden template: splash editUrl: false +lastUpdated: false hero: title: '404' tagline: <strong>Houston, wir haben ein Problem.</strong> Wir konnten diese Seite nicht finden.<br>Prüfe die URL oder verwende die Suchleiste. diff --git a/docs/src/content/docs/de/components/asides.mdx b/docs/src/content/docs/de/components/asides.mdx new file mode 100644 index 00000000000..d93df4a1893 --- /dev/null +++ b/docs/src/content/docs/de/components/asides.mdx @@ -0,0 +1,194 @@ +--- +title: Nebenbemerkungen +description: Lerne, wie du in Starlight zusätzliche Informationen neben dem Hauptinhalt einer Seite anzeigen kannst. +--- + +import { Aside } from '@astrojs/starlight/components'; + +Um sekundäre Informationen neben dem Hauptinhalt einer Seite anzuzeigen, verwende die Komponente `<Aside>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Aside slot="preview"> + Füge nicht wesentliche, ergänzende Informationen in ein `<Aside>`. +</Aside> + +</Preview> + +## Import + +```tsx +import { Aside } from '@astrojs/starlight/components'; +``` + +## Verwendung + +Zeige eine Nebenbemerkung (auch bekannt als „Hinweise“, „Ermahnungen“ oder „Aufrufe“) mit Hilfe der Komponente `<Aside>`. + +Ein `<Aside>` kann ein optionales [`type`](#type) Attribute haben, welches die Farbe, das Symbol und den Standardtitel der Nebenbemerkung steuert. + +<Preview> + +````mdx +import { Aside } from '@astrojs/starlight/components'; + +<Aside>Einige Inhalte am Rande.</Aside> + +<Aside type="caution">Einige warnende Inhalte.</Aside> + +<Aside type="tip"> + +Auch andere Inhalte werden durch Nebenbemerkungen unterstützt. + +```js +// Ein Codeschnipsel zum Beispiel. +``` + +</Aside> + +<Aside type="danger">Gib dein Passwort nie an Dritte weiter!</Aside> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% aside %} +Einige Inhalte am Rande. +{% /aside %} + +{% aside type="caution" %} +Einige warnende Inhalte. +{% /aside %} + +{% aside type="tip" %} +Auch andere Inhalte werden durch Nebenbemerkungen unterstützt. + +```js +// Ein Codeschnipsel zum Beispiel. +``` +{% /aside %} + +{% aside type="danger" %} +Gib dein Passwort nie an Dritte weiter! +{% /aside %} +```` + +</Fragment> + +<Fragment slot="preview"> + + <Aside>Einige Inhalte am Rande.</Aside> + + <Aside type="caution">Einige warnende Inhalte.</Aside> + + <Aside type="tip"> + + Auch andere Inhalte werden durch Nebenbemerkungen unterstützt. + + ```js + // Ein Codeschnipsel zum Beispiel. + ``` + + </Aside> + + <Aside type="danger">Gib dein Passwort nie an Dritte weiter!</Aside> + +</Fragment> + +</Preview> + +Starlight bietet auch eine benutzerdefinierte Syntax für die Darstellung von Nebenbemerkungen in Markdown und MDX als Alternative zur `<Aside>` Komponente. +Siehe den Leitfaden [„Inhalte in Markdown verfassen“](/de/guides/authoring-content/#nebenbemerkungen) für Details zu dieser Syntax. + +### Benutzerdefinierte Titel verwenden + +Überschreibe die voreingestellten Überschriften der Nebenbemerkungen mit dem Attribut [`title`](#title). + +<Preview> + +```mdx 'title="Aufgepasst!"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="caution" title="Aufgepasst!"> + Ein Warnhinweis *mit* einem benutzerdefinierten Titel. +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'title="Aufgepasst!"' +{% aside type="caution" title="Aufgepasst!" %} +Ein Warnhinweis *mit* einem benutzerdefinierten Titel. +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="caution" title="Aufgepasst!"> + Ein Warnhinweis *mit* einem benutzerdefinierten Titel. +</Aside> + +</Preview> + +### Benutzerdefinierte Symbole verwenden + +Überschreibe die Standard-Symbole der Nebenbemerkungen, indem du das Attribut [`icon`](#icon) auf den Namen [eines der in Starlight integrierten Symbole](/de/reference/icons/#alle-symbole) setzt. + +<Preview> + +```mdx 'icon="starlight"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="tip" icon="starlight"> + Ein Hinweis *mit* einem benutzerdefinierten Symbol. +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="starlight"' +{% aside type="tip" icon="starlight" %} +Ein Hinweis *mit* einem benutzerdefinierten Symbol. +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="tip" icon="starlight"> + Ein Hinweis *mit* einem benutzerdefinierten Symbol. +</Aside> + +</Preview> + +## `<Aside>`-Eigenschaften + +**Implementation:** [`Aside.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Aside.astro) + +Die Komponente `<Aside>` akzeptiert die folgenden Eigenschaften: + +### `type` + +**Typ:** `'note' | 'tip' | 'caution' | 'danger'` +**Standard:** `'note'` + +Die Art der Nebenbemerkung, die angezeigt werden soll: + +- `note`-Hinweise (die Standardeinstellung) sind blau und zeigen ein Informationssymbol an. +- `tip`-Hinweise sind violett und zeigen ein Raketensymbol an. +- `caution`-Hinweise sind gelb und zeigen ein dreieckiges Warnsymbol an. +- `danger`-Hinweise sind rot und zeigen ein achteckiges Warnsymbol an. + +### `title` + +**Typ:** `string` + +Die Überschrift der anzuzeigenden Nebenbemerkung. +Wenn `title` nicht gesetzt ist, wird der Standardtitel für den aktuellen `type` der Nebenbemerkung verwendet. + +### `icon` + +**Typ:** [`StarlightIcon`](/de/reference/icons/#starlighticon-typ) + +Eine Nebenbemerkung kann ein `icon`-Attribut enthalten, das auf den Namen [eines der in Starlight integrierten Symbole](/de/reference/icons/#alle-symbole) gesetzt ist. diff --git a/docs/src/content/docs/de/components/badges.mdx b/docs/src/content/docs/de/components/badges.mdx new file mode 100644 index 00000000000..4e106811b84 --- /dev/null +++ b/docs/src/content/docs/de/components/badges.mdx @@ -0,0 +1,150 @@ +--- +title: Abzeichen +description: Lerne, wie du in Starlight Abzeichen verwenden kannst, um zusätzliche Informationen anzuzeigen. +--- + +import { Badge } from '@astrojs/starlight/components'; + +Um wenige Informationen, wie z. B. einen Status oder eine Kategorie, anzuzeigen, verwende die Komponente `<Badge>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Badge slot="preview" text="Neu" /> + +</Preview> + +## Import + +```tsx +import { Badge } from '@astrojs/starlight/components'; +``` + +## Verwendung + +Zeige ein Abzeichen mit der Komponente `<Badge>` an und übergib den Inhalt, den du anzeigen möchtest, an das Attribut [`text`](#text) der Komponente `<Badge>`. + +Standardmäßig wird für das Abzeichen die Akzentfarbe des Themes deiner Website verwendet. +Um eine eingebaute Abzeichen-Farbe zu verwenden, setze das Attribut [`variant`](#variant) auf einen der unterstützten Werte. + +<Preview> + +```mdx +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="Hinweis" variant="note" /> +- <Badge text="Erfolg" variant="success" /> +- <Badge text="Tipp" variant="tip" /> +- <Badge text="Warnung" variant="caution" /> +- <Badge text="Gefahr" variant="danger" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +- {% badge text="Hinweis" variant="note" /%} +- {% badge text="Erfolg" variant="success" /%} +- {% badge text="Tipp" variant="tip" /%} +- {% badge text="Warnung" variant="caution" /%} +- {% badge text="Gefahr" variant="danger" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="Hinweis" variant="note" /> + - <Badge text="Erfolg" variant="success" /> + - <Badge text="Tipp" variant="tip" /> + - <Badge text="Warnung" variant="caution" /> + - <Badge text="Gefahr" variant="danger" /> +</Fragment> + +</Preview> + +### Verschiedene Größen verwenden + +Verwende das Attribut [`size`](#size), um die Größe des Abzeichentextes zu steuern. + +<Preview> + +```mdx /size="\w+"/ +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="Neu" size="small" /> +- <Badge text="Neu und verbessert" size="medium" /> +- <Badge text="Neu, verbessert und größer" size="large" /> +``` + +<Fragment slot="markdoc"> + +```markdoc /size="\w+"/ +- {% badge text="Neu" size="small" /%} +- {% badge text="Neu und verbessert" size="medium" /%} +- {% badge text="Neu, verbessert und größer" size="large" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="Neu" size="small" /> + - <Badge text="Neu und verbessert" size="medium" /> + - <Badge text="Neu, verbessert und größer" size="large" /> +</Fragment> + +</Preview> + +### Abzeichen anpassen + +Passe Abzeichen an, indem du andere `<span>`-Attribute wie `class` oder `style` mit benutzerdefiniertem CSS verwendest. + +<Preview> + +```mdx "style={{ fontStyle: 'italic' }}" +import { Badge } from '@astrojs/starlight/components'; + +<Badge text="Individuell" variant="success" style={{ fontStyle: 'italic' }} /> +``` + +<Fragment slot="markdoc"> + +```markdoc 'style="font-style: italic;"' +{% badge text="Individuell" variant="success" style="font-style: italic;" /%} +``` + +</Fragment> + +<Badge + slot="preview" + text="Individuell" + variant="success" + style={{ fontStyle: 'italic' }} +/> + +</Preview> + +## `<Badge>`-Eigenschaften + +**Implementation:** [`Badge.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Badge.astro) + +Die `<Badge>`-Komponente akzeptiert die folgenden Eigenschaften und auch alle [anderen `<span>`-Attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes): + +### `text` + +**Erforderlich** +**Typ:** `string` + +Der Textinhalt, der in dem Abzeichen angezeigt werden soll. + +### `variant` + +**Typ:** `'note' | 'danger' | 'success' | 'caution' | 'tip' | 'default'` +**Standard:** `'default'` + +Die zu verwendende Farbvariante des Abzeichens: `note` (blau), `tip` (lila), `danger` (rot), `caution` (orange), `success` (grün) oder `default` (Akzentfarbe des Themes). + +### `size` + +**Typ:** `'small' | 'medium' | 'large'` + +Bestimmt die Größe des anzuzeigenden Abzeichens. diff --git a/docs/src/content/docs/de/components/card-grids.mdx b/docs/src/content/docs/de/components/card-grids.mdx new file mode 100644 index 00000000000..2b0859ba5f4 --- /dev/null +++ b/docs/src/content/docs/de/components/card-grids.mdx @@ -0,0 +1,173 @@ +--- +title: Kartenraster +description: Erfahre, wie du in Starlight mehrere Karten in ein Raster packen kannst. +sidebar: + order: 4 +--- + +import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; + +Um mehrere [`<Card>`](/de/components/cards/) oder [`<LinkCard>`](/de/components/link-cards/) Komponenten in einem Raster zu verpacken, verwende die Komponente `<CardGrid>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<CardGrid slot="preview"> + <Card title="Sterne" icon="star"> + Sirius, Wega, Betelgeuse + </Card> + <Card title="Monde" icon="moon"> + Io, Europa, Ganymed + </Card> +</CardGrid> + +</Preview> + +## Import + +```tsx +import { CardGrid } from '@astrojs/starlight/components'; +``` + +## Verwendung + +### Karten gruppieren + +Zeige mehrere [`<Card>`](/de/components/cards/) Komponenten nebeneinander an, wenn genügend Platz vorhanden ist, indem du sie mit der `<CardGrid>` Komponente gruppierst. + +<Preview> + +```mdx {3,10} +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <Card title="Schau dir das an" icon="open-book"> + Interessante Inhalte, die du hervorheben möchtest. + </Card> + <Card title="Anderer Inhalt" icon="information"> + Weitere Informationen, die du weitergeben möchtest. + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,9} +{% cardgrid %} +{% card title="Schau dir das an" icon="open-book" %} +Interessante Inhalte, die du hervorheben möchtest. +{% /card %} + +{% card title="Anderer Inhalt" icon="information" %} +Weitere Informationen, die du weitergeben möchtest. +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <Card title="Schau dir das an" icon="open-book"> + Interessante Inhalte, die du hervorheben möchtest. + </Card> + <Card title="Anderer Inhalt" icon="information"> + Weitere Informationen, die du weitergeben möchtest. + </Card> +</CardGrid> + +</Preview> + +### Link-Karten gruppieren + +Zeige mehrere [`<LinkCard>`](/de/components/link-cards/) Komponenten nebeneinander an, wenn genügend Platz vorhanden ist, indem du sie mit der `<CardGrid>` Komponente gruppierst. + +<Preview> + +```mdx {3,6} +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <LinkCard title="Markdown verfassen" href="/de/guides/authoring-content/" /> + <LinkCard title="Komponenten" href="/de/components/using-components/" /> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,5} +{% cardgrid %} +{% linkcard title="Markdown verfassen" href="/de/guides/authoring-content/" /%} + +{% linkcard title="Komponenten" href="/de/components/using-components/" /%} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <LinkCard title="Markdown verfassen" href="/de/guides/authoring-content/" /> + <LinkCard title="Komponenten" href="/de/components/using-components/" /> +</CardGrid> + +</Preview> + +### Karten staffeln + +Verschiebe die zweite Spalte des Rasters vertikal, um es optisch interessanter zu gestalten, indem du das Attribut [`stagger`](#stagger) zur Komponente `<CardGrid>` hinzufügst. + +Dieses Attribut ist auf deiner Homepage nützlich, um die wichtigsten Merkmale deines Projekts anzuzeigen. + +<Preview> + +```mdx "stagger" +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid stagger> + <Card title="Schau dir das an" icon="open-book"> + Interessante Inhalte, die du hervorheben möchtest. + </Card> + <Card title="Anderer Inhalt" icon="information"> + Weitere Informationen, die du weitergeben möchtest. + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc "stagger=true" +{% cardgrid stagger=true %} +{% card title="Schau dir das an" icon="open-book" %} +Interessante Inhalte, die du hervorheben möchtest. +{% /card %} + +{% card title="Anderer Inhalt" icon="information" %} +Weitere Informationen, die du weitergeben möchtest. +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview" stagger> + <Card title="Schau dir das an" icon="open-book"> + Interessante Inhalte, die du hervorheben möchtest. + </Card> + <Card title="Anderer Inhalt" icon="information"> + Weitere Informationen, die du weitergeben möchtest. + </Card> +</CardGrid> + +</Preview> + +## `<CardGrid>`-Eigenschaften + +**Implementation:** [`CardGrid.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/CardGrid.astro) + +Die Komponente `<CardGrid>` akzeptiert die folgenden Eigenschaften: + +### `stagger` + +**Typ:** `boolean` + +Legt fest, ob die Karten im Raster gestaffelt werden sollen oder nicht. diff --git a/docs/src/content/docs/de/components/cards.mdx b/docs/src/content/docs/de/components/cards.mdx new file mode 100644 index 00000000000..6480545bf7a --- /dev/null +++ b/docs/src/content/docs/de/components/cards.mdx @@ -0,0 +1,110 @@ +--- +title: Karten +description: Lerne, wie du in Starlight Karten verwenden kannst, um Inhalte in einer Box anzuzeigen. +sidebar: + order: 2 +--- + +import { Card } from '@astrojs/starlight/components'; + +Um Inhalte in einer Box anzuzeigen, die den Stilen von Starlight entspricht, verwende die Komponente `<Card>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Card slot="preview" title="Monde" icon="moon"> + Io, Europa, Ganymed +</Card> + +</Preview> + +## Import + +```tsx +import { Card } from '@astrojs/starlight/components'; +``` + +## Verwendung + +Zeige eine Karte an, indem du die Komponente `<Card>` verwendest und einen [`title`](#title) für die Karte angibst. + +<Preview> + +```mdx +import { Card } from '@astrojs/starlight/components'; + +<Card title="Schau dir das an"> + Interessante Inhalte, die du hervorheben möchtest. +</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% card title="Schau dir das an" %} +Interessante Inhalte, die du hervorheben möchtest. +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="Schau dir das an"> + Interessante Inhalte, die du hervorheben möchtest. +</Card> + +</Preview> + +### Hinzufügen von Symbolen zu Karten + +Füge ein Symbol in eine Karte ein, indem du das Attribut [`icon`](#icon) auf den Namen [eines von Starlights eingebauten Symbolen](/de/reference/icons/#alle-symbole) setzt. + +<Preview> + +```mdx 'icon="star"' +import { Card } from '@astrojs/starlight/components'; + +<Card title="Sterne" icon="star"> + Sirius, Wega, Betelgeuse +</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="star"' +{% card title="Sterne" icon="star" %} +Sirius, Wega, Betelgeuse +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="Sterne" icon="star"> + Sirius, Wega, Betelgeuse +</Card> + +</Preview> + +### Karten gruppieren + +Zeige mehrere Karten nebeneinander an, wenn genügend Platz vorhanden ist, indem du sie mit der Komponente [`<CardGrid>`](/de/components/card-grids/) gruppierst. +Siehe die Anleitung [„Karten gruppieren“](/de/components/card-grids/#karten-gruppieren) für ein Beispiel. + +## `<Card>`-Eigenschaften + +**Implementation:** [`Card.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Card.astro) + +Die Komponente `<Card>` akzeptiert die folgenden Eigenschaften: + +### `title` + +**Erforderlich** +**Typ:** `string` + +Der Titel der anzuzeigenden Karte. + +### `icon` + +**Typ:** `string` + +Eine Karte kann ein `icon`-Attribut enthalten, das auf den Namen [eines von Starlights eingebauten Symbolen](/de/reference/icons/#alle-symbole) gesetzt ist. diff --git a/docs/src/content/docs/de/components/code.mdx b/docs/src/content/docs/de/components/code.mdx new file mode 100644 index 00000000000..43ea00bdeb8 --- /dev/null +++ b/docs/src/content/docs/de/components/code.mdx @@ -0,0 +1,103 @@ +--- +title: Code +description: Erfahre, wie du syntaxmarkierten Code in Starlight ohne Markdown-Codeblöcke anzeigen kannst. +--- + +import { Code } from '@astrojs/starlight/components'; + +Die Komponente `<Code>` gibt syntaktisch hervorgehobenen Code wieder. +Sie ist nützlich, wenn die Verwendung eines [Markdown-Codeblocks](/de/guides/authoring-content/#codeblöcke) nicht möglich ist, zum Beispiel, um Daten aus externen Quellen wie Dateien, Datenbanken oder APIs darzustellen. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Code + slot="preview" + code={`## Willkommen + +Hallo aus dem **Weltraum**!`} +lang="md" +title="example.md" +ins={3} +/> + +</Preview> + +## Import + +```tsx +import { Code } from '@astrojs/starlight/components'; +``` + +## Verwendung + +Verwende die Komponente `<Code>`, um Code mit hervorgehobener Syntax darzustellen, z. B. bei der Anzeige von Code aus externen Quellen. + +Siehe die [Ausdrucksstarker Code „Code Komponente“ Dokumentation](https://expressive-code.com/key-features/code-component/) für alle Details über die Verwendung der `<Code>` Komponente und die Liste der verfügbaren Eigenschaften. + +<Preview> + +```mdx +import { Code } from '@astrojs/starlight/components'; + +export const exampleCode = `console.log('Dies könnte aus einer Datei oder einem CMS stammen!');`; +export const fileName = 'example.js'; +export const highlights = ['Datei', 'CMS']; + +<Code code={exampleCode} lang="js" title={fileName} mark={highlights} /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% code + code="console.log('Dies könnte aus einer Datei oder einem CMS stammen!');" + lang="js" + title="example.js" + meta="'Datei' 'CMS'" /%} +``` + +</Fragment> + +export const exampleCode = `console.log('Dies könnte aus einer Datei oder einem CMS stammen!');`; +export const fileName = 'example.js'; +export const highlights = ['Datei', 'CMS']; + +<Code + slot="preview" + code={exampleCode} + lang="js" + title={fileName} + mark={highlights} +/> + +</Preview> + +### Importierten Code anzeigen + +Verwende in MDX-Dateien und Astro-Komponenten [Vites Importsuffix `?raw`](https://de.vite.dev/guide/assets#importieren-von-assets-als-zeichenfolge), um jede Codedatei als Zeichenfolge zu importieren. +Du kannst diese importierte Zeichenfolge dann an die Komponente `<Code>` übergeben, um sie auf deiner Seite einzubinden. + +<Preview> + +```mdx "?raw" +# src/content/docs/example.mdx + +import { Code } from '@astrojs/starlight/components'; +import importedCode from '/tsconfig.json?raw'; + +<Code code={importedCode} lang="json" title="tsconfig.json" /> +``` + +import importedCode from '../../../../../../examples/basics/tsconfig.json?raw'; + +<Code slot="preview" code={importedCode} lang="json" title="tsconfig.json" /> + +</Preview> + +## `<Code>`-Eigenschaften + +**Implementation:** [`Code.astro`](https://github.com/expressive-code/expressive-code/blob/main/packages/astro-expressive-code/components/Code.astro) + +Die `<Code>`-Komponente akzeptiert alle in der [Ausdrucksstarker Code Dokumentation „Code Komponente“](https://expressive-code.com/key-features/code-component/#available-props) dokumentierten Eigenschaften. diff --git a/docs/src/content/docs/de/components/file-tree.mdx b/docs/src/content/docs/de/components/file-tree.mdx new file mode 100644 index 00000000000..10f39e02c95 --- /dev/null +++ b/docs/src/content/docs/de/components/file-tree.mdx @@ -0,0 +1,265 @@ +--- +title: Verzeichnisbaum +description: Lerne, wie du die Struktur eines Verzeichnisses mit Dateisymbolen und einklappbaren Unterverzeichnissen in Starlight anzeigen kannst. +--- + +import { FileTree } from '@astrojs/starlight/components'; + +Um die Struktur eines Verzeichnisses mit Dateisymbolen und einklappbaren Unterverzeichnissen anzuzeigen, verwende die Komponente `<FileTree>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<FileTree slot="preview"> + +- astro.config.mjs eine **wichtige** Datei +- package.json +- README.md +- src + - components + - **Header.astro** + - … +- pages/ + +</FileTree> + +</Preview> + +## Import + +```tsx +import { FileTree } from '@astrojs/starlight/components'; +``` + +## Verwendung + +Zeige einen Dateibaum mit Dateisymbolen und zusammenklappbaren Unterverzeichnissen unter Verwendung der Komponente `<FileTree>` an. + +Gib die Struktur deiner Dateien und Verzeichnisse mit einer [ungeordneten Markdown-Liste](https://www.markdownguide.org/basic-syntax/#unordered-lists) innerhalb von `<FileTree>` an. +Erstelle ein Unterverzeichnis mit einer verschachtelten Liste oder füge ein `/` am Ende eines Listenelements hinzu, um es als Verzeichnis ohne spezifischen Inhalt darzustellen. + +<Preview> + +```mdx +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% filetree %} +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> + +</Preview> + +### Einträge hervorheben + +Hebe eine Datei oder ein Verzeichnis hervor, indem du seinen Namen fett druckst, z. B. `**README.md**`. + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - **Header.astro** + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> + +</Preview> + +### Kommentare hinzufügen + +Füge einen Kommentar zu einer Datei oder einem Verzeichnis hinzu, indem du nach dem Namen weiteren Text hinzufügst. +Inline-Markdown-Formatierung wie Fett- und Kursivdruck wird in Kommentaren unterstützt. + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro eine **wichtige** Datei + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - Header.astro eine **wichtige** Datei + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro eine **wichtige** Datei + - Title.astro + +</FileTree> + +</Preview> + +### Platzhalter hinzufügen + +Füge Platzhalterdateien und Verzeichnisse hinzu, indem du entweder `...` oder `…` als Namen verwendest. +Dies kann nützlich sein, um einem Leser zu zeigen, dass ein Ordner mehr Elemente enthalten soll, ohne sie alle explizit anzugeben. + +<Preview> + +```mdx {8} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro + - … + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {5} +{% filetree %} +- src + - components + - Header.astro + - … +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro + - … + +</FileTree> + +</Preview> + +### Sonderzeichen umgehen + +Sichere Sonderzeichen wie Unterstriche oder Leerzeichen in Dateinamen, indem du den Dateinamen in Code-Backticks einschließt. + +<Preview> + +```mdx +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- `__init__.py` +- `Hallo Welt.txt` +- **`LIES MICH ZUERST.md`** + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% filetree %} +- `__init__.py` +- `Hallo Welt.txt` +- **`LIES MICH ZUERST.md`** +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- `__init__.py` +- `Hallo Welt.txt` +- **`LIES MICH ZUERST.md`** + +</FileTree> + +</Preview> + +## `<FileTree>`-Eigenschaften + +**Implementation:** [`FileTree.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/FileTree.astro) + +Die Komponente `<FileTree>` akzeptiert keine Eigenschaften. diff --git a/docs/src/content/docs/de/components/icons.mdx b/docs/src/content/docs/de/components/icons.mdx new file mode 100644 index 00000000000..f65772e5223 --- /dev/null +++ b/docs/src/content/docs/de/components/icons.mdx @@ -0,0 +1,128 @@ +--- +title: Symbole +description: Erfahre, wie du Symbole in Starlight anzeigen kannst. +--- + +import { Icon } from '@astrojs/starlight/components'; + +Um Symbole aus Starlights [eingebautem Symbol-Set](/de/reference/icons/#alle-symbole) anzuzeigen, verwende die `<Icon>` Komponente. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Icon + slot="preview" + name="open-book" + color="var(--sl-color-text-accent)" + size="4rem" +/> + +</Preview> + +## Import + +```tsx +import { Icon } from '@astrojs/starlight/components'; +``` + +## Verwendung + +Zeigt ein Symbol mit der Komponente `<Icon>` an. +Ein Symbole benötigt einen [`name`](#name), der auf [eines der in Starlight eingebauten Symbolen](/de/reference/icons/#alle-symbole) gesetzt ist, und kann optional ein [`label`](#label) enthalten, um Kontext für Screenreader zu liefern. + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" /> +<Icon name="starlight" label="Das Starlight-Logo" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" /%} +{% icon name="starlight" label="Das Starlight-Logo" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" /> + <Icon name="starlight" label="Das Starlight-Logo" /> +</Fragment> + +</Preview> + +### Anpassen von Symbolen + +Die Attribute [`size`](#size) und [`color`](#color) können verwendet werden, um das Aussehen des Symbols mit CSS-Einheiten und Farbwerten anzupassen. +Das Attribut [`class`](#class) kann verwendet werden, um dem Symbol eigene CSS-Klassen hinzuzufügen. + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" color="goldenrod" size="2rem" /> +<Icon name="rocket" color="var(--sl-color-text-accent)" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" color="goldenrod" size="2rem" /%} +{% icon name="rocket" color="var(--sl-color-text-accent)" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" color="goldenrod" size="2rem" /> + <Icon name="rocket" color="var(--sl-color-text-accent)" /> +</Fragment> + +</Preview> + +## `<Icon>`-Eigenschaften + +**Implementation:** [`Icon.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Icon.astro) + +Die Komponente `<Icon>` akzeptiert die folgenden Eigenschaften: + +### `name` + +**Erforderlich** +**Typ:** [`StarlightIcon`](/de/reference/icons/#starlighticon-typ) + +Der Name des anzuzeigenden Symbols wird auf [eines der in Starlight integrierten Symbole](/de/reference/icons/#alle-symbole) gesetzt. + +### `label` + +**Typ:** `string` + +Eine optionale Beschriftung, die den Kontext für unterstützende Technologien wie Bildschirm­lesegeräte liefert. + +Wenn `label` nicht gesetzt ist, wird das Symbol von assistiven Technologien vollständig ausgeblendet. +In diesem Fall ist darauf zu achten, dass der Kontext auch ohne das Symbol verständlich ist. +Ein Link, der nur das Symbol enthält, **muss** das Attribut `label` enthalten, um zugänglich zu sein, aber wenn ein Link Text enthält und das Symbol rein dekorativ ist, kann es sinnvoll sein, das `label` wegzulassen. + +### `size` + +**Typ:** `string` + +Die Größe des Symbols in CSS-Einheiten. + +### `color` + +**Typ:** `string` + +Die Farbe des Symbols unter Verwendung eines CSS-Farbwerts. + +### `class` + +**Typ:** `string` + +Benutzerdefinierte CSS-Klassen, die dem Symbol hinzugefügt werden können. diff --git a/docs/src/content/docs/de/components/link-buttons.mdx b/docs/src/content/docs/de/components/link-buttons.mdx new file mode 100644 index 00000000000..7463833990b --- /dev/null +++ b/docs/src/content/docs/de/components/link-buttons.mdx @@ -0,0 +1,145 @@ +--- +title: Link-Buttons +description: Erfahre, wie du in Starlight Link-Buttons für visuell eindeutige Call-to-Action-Links erstellen. +--- + +import { LinkButton } from '@astrojs/starlight/components'; + +Um visuell eindeutige Call-to-Action-Links anzuzeigen, verwende die Komponente `<LinkButton>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkButton slot="preview" href="/de/getting-started/"> + Lies die Dokumentationen +</LinkButton> + +</Preview> + +## Import + +```tsx +import { LinkButton } from '@astrojs/starlight/components'; +``` + +## Verwendung + +Verwende die Komponente `<LinkButton>`, um einen visuell eindeutigen Call-to-Action-Link anzuzeigen. +Ein Link-Button ist nützlich, um Nutzer zu den relevantesten oder handlungsrelevanten Inhalten zu leiten und wird häufig auf Landing Pages verwendet. + +Ein `<LinkButton>` benötigt ein [`href`](#href) Attribut. +Optional kann das Aussehen des Link-Buttons mit dem Attribut [`variant`](#variant) angepasst werden, das auf `primary` (Standard), `secondary` oder `minimal` gesetzt werden kann. + +<Preview> + +```mdx +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton href="/de/getting-started/">Los geht's</LinkButton> +<LinkButton href="/de/reference/configuration/" variant="secondary"> + Konfiguration Referenz +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkbutton href="/de/getting-started/" %}Los geht's{% /linkbutton %} + +{% linkbutton href="/de/reference/configuration/" variant="secondary" %} +Konfiguration Referenz +{% /linkbutton %} +``` + +</Fragment> + +<Fragment slot="preview"> + <LinkButton href="/de/getting-started/">Los geht's</LinkButton> + <LinkButton href="/de/reference/configuration/" variant="secondary"> + Konfiguration Referenz + </LinkButton> +</Fragment> + +</Preview> + +### Hinzufügen von Symbolen zu Link-Buttons + +Füge ein Symbol in einen Link-Button ein, indem du das Attribut [`icon`](#icon) auf den Namen [eines von Starlights eingebauten Symbolen](/de/reference/icons/#alle-symbole) setzt. + +Das Attribut [`iconPlacement`](#iconplacement) kann verwendet werden, um das Symbol vor dem Text zu platzieren, indem man es auf `start` setzt (Standardwert ist `end`). + +<Preview> + +```mdx {6-7} +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" +> + Verwandt: Astro +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc {4-5} +{% linkbutton + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" %} +Verwandt: Astro +{% /linkbutton %} +``` + +</Fragment> + +<LinkButton + slot="preview" + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" +> + Verwandt: Astro +</LinkButton> + +</Preview> + +## `<LinkButton>`-Eigenschaften + +**Implementation:** [`LinkButton.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkButton.astro) + +Die `<LinkButton>`-Komponente akzeptiert die folgenden Eigenschaften und auch alle [anderen `<a>`-Attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a): + +### `href` + +**Erforderlich** +**Typ:** `string` + +Die URL, auf die der Link-Button zeigt. + +### `variant` + +**Typ:** `'primary' | 'secondary' | 'minimal'` +**Standard:** `'primary'` + +Das Aussehen des Link-Button. +Setze auf `primary` für einen auffälligen Call-to-Action-Link mit der Akzentfarbe des Themas, auf `secondary` für einen weniger auffälligen Link oder auf `minimal` für einen Link mit minimalem Styling. + +### `icon` + +**Typ:** `string` + +Ein Link-Button kann ein `icon`-Attribut enthalten, das auf den Namen [eines von Starlights eingebauten Symbolen](/de/reference/icons/#alle-symbole) gesetzt ist. + +### `iconPlacement` + +**Typ:** `'start' | 'end'` +**Standard:** `'end'` + +Bestimmt die Platzierung des Symbols im Verhältnis zum Text des Link-Buttons. diff --git a/docs/src/content/docs/de/components/link-cards.mdx b/docs/src/content/docs/de/components/link-cards.mdx new file mode 100644 index 00000000000..f3642fa8ba9 --- /dev/null +++ b/docs/src/content/docs/de/components/link-cards.mdx @@ -0,0 +1,128 @@ +--- +title: Link-Karten +description: Erfahre, wie du in Starlight Links prominent als Karten anzeigst. +sidebar: + order: 3 +--- + +import { LinkCard } from '@astrojs/starlight/components'; + +Um Links zu verschiedenen Seiten prominent anzuzeigen, verwende die Komponente `<LinkCard>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkCard + slot="preview" + title="Starlight anpassen" + description="Lerne, wie du deine Starlight-Website mit deinem Logo, eigenen Schriftarten, Landing-Page-Design und vielem mehr zu deiner eigenen machen kannst." + href="/de/guides/customization/" +/> + +</Preview> + +## Import + +```tsx +import { LinkCard } from '@astrojs/starlight/components'; +``` + +## Verwendung + +Zeige einen Link mithilfe der Komponente `<LinkCard>` deutlich sichtbar an. +Jede `<LinkCard>` erfodert ein [`title`](#title) und ein [`href`](#href)-Attribut. + +<Preview> + +```mdx +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard + title="Inhalte in Markdown verfassen" + href="/de/guides/authoring-content/" +/> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkcard title="Inhalte in Markdown verfassen" href="/de/guides/authoring-content/" /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="Inhalte in Markdown verfassen" + href="/de/guides/authoring-content/" +/> + +</Preview> + +### Füge eine Linkbeschreibung hinzu + +Füge einer Link-Karte mit dem Attribut [`description`](#description) eine kurze Beschreibung hinzu. + +<Preview> + +```mdx {6} +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard + title="Internationalisierung" + href="/de/guides/i18n/" + description="Konfiguriere Starlight zur Unterstützung mehrerer Sprachen." +/> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% linkcard + title="Internationalisierung" + href="/de/guides/i18n/" + description="Konfiguriere Starlight zur Unterstützung mehrerer Sprachen." /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="Internationalisierung" + href="/de/guides/i18n/" + description="Konfiguriere Starlight zur Unterstützung mehrerer Sprachen." +/> + +</Preview> + +### Gruppiere Link-Karten + +Zeige mehrere Link-Karten nebeneinander an, wenn genügend Platz vorhanden ist, indem du sie mit der Komponente [`<CardGrid>`](/de/components/card-grids/) gruppierst. +Ein Beispiel findest du im Handbuch [“Gruppiere Link-Karten”](/de/components/card-grids/#link-karten-gruppieren). + +## `<LinkCard>`-Eigenschaften + +**Implementation:** [`LinkCard.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkCard.astro) + +Die Komponente `<LinkCard>` akzeptiert die folgenden Eigenschaften sowie alle anderen [`<a>`-Elementattribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a): + +### `title` + +**Erforderlich** +**Typ:** `string` + +Der Titel der anzuzeigenden Link-Karte. + +### `href` + +**Erforderlich** +**Typ:** `string` + +Die URL, auf die bei Interaktion mit der Karte verwiesen werden soll. + +### `description` + +**Typ:** `string` + +Eine optionale Beschreibung, welche unter dem Titel angezeigt wird. diff --git a/docs/src/content/docs/de/components/steps.mdx b/docs/src/content/docs/de/components/steps.mdx new file mode 100644 index 00000000000..abc520ce21e --- /dev/null +++ b/docs/src/content/docs/de/components/steps.mdx @@ -0,0 +1,120 @@ +--- +title: Schritte +description: Hier erfährst du, wie du nummerierte Listen mit Aufgaben erstellen kannst, um Schritt-für-Schritt-Anleitungen in Starlight zu erstellen. +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +Um eine nummerierte Liste von Aufgaben zu gestalten und Schritt-für-Schritt-Anleitungen zu erstellen, verwendest du die Komponente `<Steps>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Steps slot="preview"> + +1. Erstelle ein neues Starlight-Projekt: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm create astro@latest -- --template starlight + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm create astro --template starlight + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn create astro --template starlight + ``` + + </TabItem> + + </Tabs> + +2. Schreibe deine erste Dokumentationsseite. + +</Steps> + +</Preview> + +## Import + +```tsx +import { Steps } from '@astrojs/starlight/components'; +``` + +## Verwendung + +Verwende die Komponente `<Steps>`, um nummerierte Listen von Aufgaben zu gestalten. +Dies ist nützlich für komplexere Schritt-für-Schritt-Anleitungen, bei denen jeder Schritt deutlich hervorgehoben werden muss. + +Wickle `<Steps>` um eine geordnete Standard-Markdown-Liste. +Die übliche Markdown-Syntax ist innerhalb von `<Steps>` anwendbar. + +<Preview> + +````mdx +import { Steps } from '@astrojs/starlight/components'; + +<Steps> + +1. Importiere die Komponente in deine MDX-Datei: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Wickle `<Steps>` um deine geordneten Listenelemente. + +</Steps> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% steps %} + +1. Importiere die Komponente in deine MDX-Datei: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Wickle `<Steps>` um deine geordneten Listenelemente. + +{% /steps %} +```` + +</Fragment> + +<Steps slot="preview"> + +1. Importiere die Komponente in deine MDX-Datei: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Wickle `<Steps>` um deine geordneten Listenelemente. + +</Steps> + +</Preview> + +## `<Steps>`-Eigenschaften + +**Implementation:** [`Steps.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Steps.astro) + +Die Komponente `<Steps>` akzeptiert keine Eigenschaften. diff --git a/docs/src/content/docs/de/components/tabs.mdx b/docs/src/content/docs/de/components/tabs.mdx new file mode 100644 index 00000000000..66f959d1018 --- /dev/null +++ b/docs/src/content/docs/de/components/tabs.mdx @@ -0,0 +1,221 @@ +--- +title: Registerkarten +description: Lerne, wie du in Starlight Oberflächen mit Registerkarten erstellst, um gleichwertige Informationen zu gruppieren. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +Um eine Oberfläche mit Registerkarten zu erstellen, verwende die Komponenten `<Tabs>` und `<TabItem>`. +Registerkarten sind nützlich, um gleichwertige Informationen zu gruppieren, wenn ein Nutzer nur eine von mehreren Optionen sehen muss. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Tabs slot="preview"> + <TabItem label="Sterne">Sirius, Wega, Betelgeuse</TabItem> + <TabItem label="Monde">Io, Europa, Ganymed</TabItem> +</Tabs> + +</Preview> + +## Import + +```tsx +import { Tabs, TabItem } from '@astrojs/starlight/components'; +``` + +## Verwendung + +Zeige eine Oberfläche mit Registerkarten an, indem du die Komponenten `<Tabs>` und `<TabItem>` benutzt. +Jedes `<TabItem>` muss ein [`label`](#label) haben, um es den Benutzern anzuzeigen. + +<Preview> + +```mdx +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="Sterne">Sirius, Wega, Betelgeuse</TabItem> + <TabItem label="Monde">Io, Europa, Ganymed</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% tabs %} +{% tabitem label="Sterne" %} +Sirius, Wega, Betelgeuse +{% /tabitem %} + +{% tabitem label="Monde" %} +Io, Europa, Ganymed +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="Sterne">Sirius, Wega, Betelgeuse</TabItem> + <TabItem label="Monde">Io, Europa, Ganymed</TabItem> +</Tabs> + +</Preview> + +### Registerkarten synchronisieren + +Halte mehrere Registerkarten­gruppen synchron, indem du das Attribut [`syncKey`](#synckey) hinzufügst. + +Alle `<Tabs>` auf einer Seite mit demselben Wert für `syncKey` zeigen dasselbe aktive Label an. +Auf diese Weise kann dein Leser eine Auswahl treffen (z. B. sein Betriebssystem oder den Paketmanager), die dann beim Navigieren durch die Seiten beibehalten wird. + +Um zusammenhängende Tabs zu synchronisieren, füge eine identische `syncKey`-Eigenschaft zu jeder `<Tabs>`-Komponente hinzu und stelle sicher, dass sie alle die gleichen `<TabItem>`-Beschriftungen verwenden: + +<Preview> + +```mdx 'syncKey="constellations"' +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +_Ein paar Sterne:_ + +<Tabs syncKey="constellations"> + <TabItem label="Orion">Bellatrix, Rigel, Betelgeuse</TabItem> + <TabItem label="Zwillinge">Pollux, Castor A, Castor B</TabItem> +</Tabs> + +_Ein paar Exoplaneten:_ + +<Tabs syncKey="constellations"> + <TabItem label="Orion">HD 34445 b, Gliese 179 b, Wasp-82 b</TabItem> + <TabItem label="Zwillinge">Pollux b, HAT-P-24b, HD 50554 b</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc 'syncKey="constellations"' +_Ein paar Sterne:_ + +{% tabs syncKey="constellations" %} +{% tabitem label="Orion" %} +Bellatrix, Rigel, Betelgeuse +{% /tabitem %} + +{% tabitem label="Zwillinge" %} +Pollux, Castor A, Castor B +{% /tabitem %} +{% /tabs %} + +_Ein paar Exoplaneten:_ + +{% tabs syncKey="constellations" %} +{% tabitem label="Orion" %} +HD 34445 b, Gliese 179 b, Wasp-82 b +{% /tabitem %} + +{% tabitem label="Zwillinge" %} +Pollux b, HAT-P-24b, HD 50554 b +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Fragment slot="preview"> + +_Ein paar Sterne:_ + +<Tabs syncKey="constellations"> + <TabItem label="Orion">Bellatrix, Rigel, Betelgeuse</TabItem> + <TabItem label="Zwillinge">Pollux, Castor A, Castor B</TabItem> +</Tabs> + +_Ein paar Exoplaneten:_ + +<Tabs syncKey="constellations"> + <TabItem label="Orion">HD 34445 b, Gliese 179 b, Wasp-82 b</TabItem> + <TabItem label="Zwillinge">Pollux b, HAT-P-24b, HD 50554 b</TabItem> +</Tabs> + +</Fragment> + +</Preview> + +### Hinzufügen von Symbolen zu Registerkarten + +Füge ein Symbol in ein Tab-Element ein, indem du das Attribut [`icon`](#icon) auf den Namen [eines der in Starlight eingebauten Symbole](/de/reference/icons/#alle-symbole) setzt, um ein Symbol neben dem Label anzuzeigen. + +<Preview> + +```mdx /icon="\w+"/ +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="Sterne" icon="star"> + Sirius, Wega, Betelgeuse + </TabItem> + <TabItem label="Monde" icon="moon"> + Io, Europa, Ganymed + </TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc /icon="\w+"/ +{% tabs %} +{% tabitem label="Sterne" icon="star" %} +Sirius, Wega, Betelgeuse +{% /tabitem %} + +{% tabitem label="Monde" icon="moon" %} +Io, Europa, Ganymed +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="Sterne" icon="star"> + Sirius, Wega, Betelgeuse + </TabItem> + <TabItem label="Monde" icon="moon"> + Io, Europa, Ganymed + </TabItem> +</Tabs> + +</Preview> + +## `<Tabs>`-Eigenschaften + +**Implementation:** [`Tabs.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Tabs.astro) + +Die Komponente `<Tabs>` fasst mehrere `<TabItem>`-Komponenten zusammen und akzeptiert die folgenden Eigenschaften: + +### `syncKey` + +**Typ:** `string` + +Ein Schlüssel, der verwendet wird, um mehrere Registerkarten­gruppen über mehrere Seiten hinweg zu synchronisieren. + +## `<TabItem>`-Eigenschaften + +**Implementation:** [`TabItem.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/TabItem.astro) + +Ein Satz von Tabs besteht aus Tab-Elementen, die jeweils die folgenden Eigenschaften haben: + +### `label` + +**Erforderlich** +**Typ:** `string` + +Eine Registerkarte muss ein Attribut `label` enthalten, das auf den Text gesetzt ist, der in der Registerkarte angezeigt werden soll. + +### `icon` + +**Typ:** `string` + +Jedes Tab-Element kann ein `icon`-Attribut enthalten, das auf den Namen [eines von Starlights eingebauten Symbolen](/de/reference/icons/#alle-symbole) gesetzt ist, um ein Symbol neben dem Label anzuzeigen. diff --git a/docs/src/content/docs/de/components/using-components.mdx b/docs/src/content/docs/de/components/using-components.mdx new file mode 100644 index 00000000000..17c7f447936 --- /dev/null +++ b/docs/src/content/docs/de/components/using-components.mdx @@ -0,0 +1,96 @@ +--- +title: Verwendung von Komponenten +description: Verwendung von Komponenten in MDX und Markdoc mit Starlight. +sidebar: + order: 1 +--- + +Mit Komponenten kannst du auf einfache Weise einen Teil der Benutzeroberfläche oder ein Styling konsistent wiederverwendem. +Beispiele könnten eine Link-Karte oder eine YouTube-Einbettung sein. +Starlight unterstützt die Verwendung von Komponenten in [MDX](https://mdxjs.com/)- und [Markdoc](https://markdoc.dev/)-Dateien und stellt dir einige gängige Komponenten zur Verfügung, die du verwenden kannst. + +[Erfahre mehr über die Erstellung von Komponenten in den Astro Docs](https://docs.astro.build/de/basics/astro-components/). + +## Verwendung einer Komponente in MDX + +Du kannst eine Komponente verwenden, indem du sie in deine MDX-Datei importierst und sie dann als JSX-Tag wiedergibst. +Diese sehen wie HTML-Tags aus, beginnen aber mit einem Großbuchstaben, der dem Namen in der `Import`-Anweisung entspricht: + +```mdx +--- +# src/content/docs/example.mdx +title: Willkommen bei meiner Dokumentation +--- + +import { Icon } from '@astrojs/starlight/components'; +import CustomCard from '../../components/CustomCard.astro'; + +<Icon name="open-book" /> + +<CustomCard> + Komponenten können auch **verschachtelte Inhalte** enthalten. +</CustomCard> +``` + +Da Starlight von Astro unterstützt wird, kannst du in deinen MDX-Dateien Unterstützung für Komponenten hinzufügen, die mit einem beliebigen [unterstützten UI-Framework (React, Preact, Svelte, Vue, Solid und Alpine)](https://docs.astro.build/de/guides/framework-components/) erstellt wurden. +Weitere Informationen über [Verwendung von Komponenten in MDX](https://docs.astro.build/de/guides/integrations-guide/mdx/#using-components-in-mdx) findest du in der Astro-Dokumentation. + +## Verwendung einer Komponente in Markdoc + +Füge Unterstützung für das Verfassen von Inhalten in Markdoc hinzu, indem du unsere [Markdoc-Einrichtungs­anleitung](/de/guides/authoring-content/#markdoc) befolgst. + +Mit der Starlight-Markdoc-Voreinstellung kannst du die in Starlight eingebauten Komponenten mit der Markdoc-Tag-Syntax `{% %}` verwenden. +Im Gegensatz zu MDX müssen die Komponenten in Markdoc nicht importiert werden. +Das folgende Beispiel stellt Starlights [Kartenkomponente](/de/components/cards/) in einer Markdoc-Datei dar: + +```markdoc +--- +# src/content/docs/example.mdoc +title: Willkommen bei meiner Dokumentation +--- + +{% card title="Stars" icon="star" %} +Sirius, Wega, Betelgeuse +{% /card %} +``` + +Weitere Informationen zur Verwendung von Komponenten in Markdoc-Dateien findst du in der [Astro Markdoc Integrations­dokumentation](https://docs.astro.build/de/guides/integrations-guide/markdoc/#render-components). + +## Integrierte Komponenten + +Starlight bietet eingebaute Komponenten für gängige Dokumentations­anwendungen. +Diese Komponenten sind aus dem Paket `@astrojs/starlight/components` in MDX-Dateien und aus der [Starlight-Markdoc-Voreinstellung](/de/guides/authoring-content/#markdoc) in Markdoc-Dateien verfügbar. + +In der Seitenleiste findst du eine Liste der verfügbaren Komponenten und deren Verwendung. + +## Kompatibilität mit den Stilen von Starlight + +Starlight wendet Standardstile auf deinen Markdown-Inhalt an, z. B. fügt es einen Rand zwischen den Elementen hinzu. +Wenn diese Stile mit dem Erscheinungsbild deiner Komponente in Konflikt stehen, setze die Klasse `not-content` für deine Komponente, um sie zu deaktivieren. + +```astro 'class="not-content"' +--- +// src/components/Example.astro +--- + +<div class="not-content"> + <p>Die Standard-Inhaltsgestaltung von Starlight wirkt sich nicht aus.</p> +</div> +``` + +## Komponenten­eigenschaften + +Verwende den Typ [`ComponentProps`](https://docs.astro.build/de/guides/typescript/#componentprops-type) aus `astro/types`, um auf die von einer Komponente akzeptierten `Props` zu verweisen, auch wenn sie nicht von der Komponente selbst exportiert werden. +Dies kann hilfreich sein, wenn man eine existierende Komponente verpackt oder erweitert. + +Das folgende Beispiel benutzt `ComponentProps`, um den Typ der Eigenschaften zu ermitteln, die von Starlights eingebauter Komponente `Badge` akzeptiert werden: + +```astro +--- +// src/components/Example.astro +import type { ComponentProps } from 'astro/types'; +import { Badge } from '@astrojs/starlight/components'; + +type BadgeProps = ComponentProps<typeof Badge>; +--- +``` diff --git a/docs/src/content/docs/de/environmental-impact.md b/docs/src/content/docs/de/environmental-impact.md new file mode 100644 index 00000000000..674b59af34c --- /dev/null +++ b/docs/src/content/docs/de/environmental-impact.md @@ -0,0 +1,146 @@ +--- +title: Umweltfreundliche Dokumentation +description: Erfahre, wie Starlight dir helfen kann, umweltfreundlichere Dokumentationen zu erstellen und deinen ökologischen Fußabdruck zu verringern. +--- + +Schätzungen über die Auswirkungen der Webindustrie auf das Klima liegen zwischen [2%][sf] und [4% der weltweiten Kohlenstoff­emissionen][bbc], was in etwa den Emissionen der Luftfahrtindustrie entspricht. +Es gibt viele komplexe Faktoren bei der Berechnung der ökologischen Auswirkungen einer Website, aber dieser Leitfaden enthält einige Tipps, wie du den ökologischen Fußabdruck deiner Docs-Website verringern kannst. + +Die gute Nachricht ist, dass die Wahl von Starlight ein guter Anfang ist. +Laut dem Website Carbon Calculator ist diese Website [sauberer als 98% der getesteten Websites][sl-carbon] und erzeugt 0,01g CO₂ pro Seitenbesuch. + +## Seitengewicht + +Je mehr Daten eine Website überträgt, desto mehr Energieressourcen benötigt sie. +Im April 2023 musste ein Nutzer laut [Daten aus dem HTTP-Archiv][http] für die durchschnittliche Website mehr als 2.000 KB herunterladen. + +Starlight erstellt Seiten, die so leicht wie möglich sind. +So lädt ein Benutzer beim ersten Besuch weniger als 50 KB an komprimierten Daten herunter - nur 2,5% des Medianwerts des HTTP-Archivs. +Mit einer guten Caching-Strategie können nachfolgende Besuche sogar nur 10 KB herunterladen. + +### Bilder + +Während Starlight eine gute Grundlage bietet, können Bilder, die du deinen Dokumentationsseiten hinzufügst, das Seitengewicht schnell erhöhen. +Starlight nutzt die [optimierte Asset-Unterstützung][Assets] von Astro, um lokale Bilder in deinen Markdown- und MDX-Dateien zu optimieren. + +### UI-Komponenten + +Komponenten, die mit UI-Frameworks wie React oder Vue erstellt wurden, können leicht große Mengen an JavaScript zu einer Website hinzufügen. +Da Starlight auf Astro aufbaut, laden Komponenten wie diese dank [Astro Islands][islands] standardmäßig **kein clientseitiges JavaScript**. + +### Caching + +Caching wird verwendet, um zu kontrollieren, wie lange ein Browser Daten speichert und wiederverwendet, die er bereits heruntergeladen hat. +Eine gute Caching-Strategie stellt sicher, dass ein Benutzer neue Inhalte so schnell wie möglich erhält, wenn sich diese ändern, vermeidet aber auch, dass derselbe Inhalt unnötigerweise immer wieder heruntergeladen wird, wenn er sich nicht geändert hat. + +Die gebräuchlichste Art, das Zwischenspeichern zu konfigurieren, ist der [`Cache-Control` HTTP-Header][cache]. +Wenn du Starlight verwendest, kannst du eine lange Cache-Zeit für alles im Verzeichnis `/_astro/` einstellen. +Dieses Verzeichnis enthält CSS, JavaScript und andere gebündelte Inhalte, die sicher für immer zwischengespeichert werden können, wodurch unnötige Downloads vermieden werden: + +``` +Cache-Control: public, max-age=604800, immutable +``` + +Wie du das Caching konfigurierst, hängt von deinem Webhost ab. Zum Beispiel wendet Vercel diese Caching-Strategie für dich an, ohne dass eine Konfiguration erforderlich ist, während du [benutzerdefinierte Header für Netlify][ntl-headers] einstellen kannst, indem du eine `public/_headers`-Datei zu deinem Projekt hinzufügst: + +``` +/_astro/* + Cache-Control: public + Cache-Control: max-age=604800 + Cache-Control: immutable +``` + +[cache]: https://csswizardry.com/2019/03/cache-control-for-civilians/ +[ntl-headers]: https://docs.netlify.com/routing/headers/ + +## Stromverbrauch + +Die Art und Weise, wie eine Website aufgebaut ist, kann sich auf den Stromverbrauch auswirken, den sie auf dem Gerät des Benutzers benötigt. +Durch die Verwendung von minimalem JavaScript reduziert Starlight die Rechenleistung, die das Telefon, Tablet oder der Computer eines Nutzers zum Laden und Rendern von Seiten benötigt. + +Sei jedoch vorsichtig, wenn du Funktionen wie analytische Tracking-Skripte oder JavaScript-lastige Inhalte wie Videoeinbettungen hinzufügst, da diese den Stromverbrauch der Seite erhöhen können. +Wenn du Analysen benötigst, solltest du eine schlanke Option wie [Cabin][cabin], [Fathom][fathom] oder [Plausible][plausible] wählen. +Einbettungen wie YouTube- und Vimeo-Videos können verbessert werden, indem man auf [Laden des Videos bei Benutzerinteraktion][lazy-video] wartet. +Pakete wie [`astro-embed`][embed] können bei gängigen Diensten helfen. + +:::tip[Wusstest du schon?] +Das Analysieren und Kompilieren von JavaScript ist eine der aufwändigsten Aufgaben, die ein Browser zu erledigen hat. +Verglichen mit dem Rendern eines JPEG-Bildes derselben Größe kann die [Verarbeitung von JavaScript mehr als 30 Mal so lange dauern][cost-of-js]. +::: + +[cabin]: https://withcabin.com/ +[fathom]: https://usefathom.com/ +[plausible]: https://plausible.io/ +[lazy-video]: https://web.dev/iframe-lazy-loading/ +[embed]: https://www.npmjs.com/package/astro-embed +[cost-of-js]: https://medium.com/dev-channel/the-cost-of-javascript-84009f51e99e + +## Hosting + +Wo eine Website gehostet wird, kann einen großen Einfluss darauf haben, wie umweltfreundlich deine Dokumentationswebsite ist. +Rechenzentren und Serveranlagen können große ökologische Auswirkungen haben, einschließlich eines hohen Stromverbrauchs und eines intensiven Wasserverbrauchs. + +Wenn du dich für einen Hoster entscheidest, der erneuerbare Energien einsetzt, wird deine Website weniger Kohlenstoff­emissionen verursachen. Das [Green Web Directory][gwb] ist ein Tool, das dir helfen kann, Hosting-Unternehmen zu finden. + +[gwb]: https://www.thegreenwebfoundation.org/directory/ + +## Gegenüberstellungen + +Bist du neugierig, wie andere Dokumentations-Frameworks im Vergleich abschneiden? +Diese Tests mit dem [Website Carbon Calculator][wcc] vergleichen ähnliche Seiten, die mit verschiedenen Tools erstellt wurden. + +| Framework | CO₂ pro Seitenaufruf | Bewertung | +| --------------------------- | -------------------- | :-------: | +| [Starlight][sl-carbon] | 0.01g | A+ | +| [Sphinx][sx-carbon] | 0.01g | A+ | +| [Read the Docs][rtd-carbon] | 0.03g | A+ | +| [VitePress][vp-carbon] | 0.04g | A | +| [docsify][dy-carbon] | 0.05g | A | +| [mdBook][md-carbon] | 0.05g | A | +| [Nextra][nx-carbon] | 0.05g | A | +| [MkDocs][mk-carbon] | 0.07g | A | +| [Fumadocs][fs-carbon] | 0.07g | A | +| [Docusaurus][ds-carbon] | 0.10g | B | +| [Docus][dc-carbon] | 0.11g | B | +| [GitBook][gb-carbon] | 0.42g | F | +| [Mintlify][mt-carbon] | 0.48g | F | + +<small>Daten erhoben am 7. August 2025. Klicke auf einen Link, um aktuelle Zahlen zu sehen.</small> + +[sl-carbon]: https://www.websitecarbon.com/website/starlight-astro-build-getting-started/ +[vp-carbon]: https://www.websitecarbon.com/website/vitepress-dev-guide-what-is-vitepress/ +[dc-carbon]: https://www.websitecarbon.com/website/docus-dev-en-getting-started-project-structure/ +[sx-carbon]: https://www.websitecarbon.com/website/sphinx-doc-org-en-master-usage-quickstart-html/ +[mk-carbon]: https://www.websitecarbon.com/website/mkdocs-org-getting-started/ +[md-carbon]: https://www.websitecarbon.com/website/rust-lang-github-io-mdbook/ +[nx-carbon]: https://www.websitecarbon.com/website/nextra-site-docs-docs-theme-start/ +[fs-carbon]: https://www.websitecarbon.com/website/fumadocs-dev-docs-ui/ +[dy-carbon]: https://www.websitecarbon.com/website/docsify-js-org/ +[ds-carbon]: https://www.websitecarbon.com/website/docusaurus-io-docs/ +[rtd-carbon]: https://www.websitecarbon.com/website/docs-readthedocs-io-en-stable-index-html/ +[gb-carbon]: https://www.websitecarbon.com/website/gitbook-com-docs/ +[mt-carbon]: https://www.websitecarbon.com/website/mintlify-com-docs-quickstart/ + +## Weitere Ressourcen + +### Werkzeuge + +- [Website Carbon Calculator][wcc] +- [GreenFrame](https://greenframe.io/) +- [Ecograder](https://ecograder.com/) +- [WebPageTest Kohlenstoff­kontrolle](https://www.webpagetest.org/carbon-control/) +- [Ecoping](https://ecoping.earth/) + +### Artikel und Vorträge + +- [„Building a greener web“](https://youtu.be/EfPoOt7T5lg), Vortrag von Michelle Barker +- [„Sustainable Web Development Strategies Within An Organization“](https://www.smashingmagazine.com/2022/10/sustainable-web-development-strategies-organization/), Artikel von Michelle Barker +- [„A sustainable web for everyone“](https://2021.stateofthebrowser.com/speakers/tom-greenwood/), Vortrag von Tom Greenwood +- [„How Web Content Can Affect Power Usage“](https://webkit.org/blog/8970/how-web-content-can-affect-power-usage/), Artikel von Benjamin Poulain und Simon Fraser + +[sf]: https://www.sciencefocus.com/science/what-is-the-carbon-footprint-of-the-internet/ +[bbc]: https://www.bbc.com/future/article/20200305-why-your-internet-habits-are-not-as-clean-as-you-think +[http]: https://httparchive.org/reports/state-of-the-web +[assets]: https://docs.astro.build/de/guides/images/ +[islands]: https://docs.astro.build/de/concepts/islands/ +[wcc]: https://www.websitecarbon.com/ diff --git a/docs/src/content/docs/de/getting-started.mdx b/docs/src/content/docs/de/getting-started.mdx index 1a98025ad80..66020b9a2b1 100644 --- a/docs/src/content/docs/de/getting-started.mdx +++ b/docs/src/content/docs/de/getting-started.mdx @@ -1,21 +1,24 @@ --- title: Erste Schritte -description: Lerne wie du deine nächste Dokumentationsseite mit Starlight und Astro erstellst. +description: Lerne, wie du deine nächste Dokumentations­website mit Starlight und Astro erstellst. --- import { Tabs, TabItem } from '@astrojs/starlight/components'; -## Erstelle ein neues Projekt +Starlight ist ein voll funktionsfähiges Dokumentations­framework, welches auf [Astro](https://astro.build) aufbaut. +Diese Anleitung wird dir helfen, mit einem neuen Projekt zu beginnen. +Sieh dir die [manuellen Einrichtungs­anweisungen](/de/manual-setup/) an, um Starlight zu einem bestehenden Astro-Projekt hinzuzufügen. -Starlight ist ein voll ausgestattetes Dokumentations-Theme, das auf dem [Astro](https://astro.build) Framework aufbaut. +## Schnellstart + +### Erstelle ein neues Projekt Du kannst ein neues Astro + Starlight Projekt mit dem folgenden Befehl erstellen: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# Erstelle ein neues Projekt mit npm npm create astro@latest -- --template starlight ``` @@ -23,7 +26,6 @@ npm create astro@latest -- --template starlight <TabItem label="pnpm"> ```sh -# Erstelle ein neues Projekt mit pnpm pnpm create astro --template starlight ``` @@ -31,86 +33,95 @@ pnpm create astro --template starlight <TabItem label="Yarn"> ```sh -# Erstelle ein neues Projekt mit yarn yarn create astro --template starlight ``` </TabItem> </Tabs> -Damit wird ein neues [Projektverzeichnis](/de/guides/project-structure/) mit allen erforderlichen Dateien und Konfigurationen für deine Webseite erstellt. +Damit wird ein neues [Projektverzeichnis](/de/guides/project-structure/) mit allen erforderlichen Dateien und Konfigurationen für deine Website erstellt. :::tip[In Aktion sehen] Probiere Starlight in deinem Browser aus: [öffne die Vorlage in StackBlitz](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). ::: -## Inhalte mit Starlight erstellen +### Starte den Entwicklungsserver -Starlight ist bereit für dich, neuen Inhalt hinzuzufügen oder deine vorhandenen Dateien mitzubringen! +Wenn du lokal arbeitest, kannst du mit dem [Astro-Entwicklungsserver](https://docs.astro.build/de/reference/cli-reference/#astro-dev) eine Vorschau deiner Arbeit angezeigt bekommen und dein Browser wird automatisch aktualisiert, wenn du Änderungen vornimmst. -### Dateiformate +Führe in deinem Projektverzeichnis den folgenden Befehl aus, um den Entwicklungsserver zu starten: -Starlight unterstützt das Erstellen von Inhalten in Markdown und MDX. (Du kannst die experimentelle [Astro Markdoc Integration](https://docs.astro.build/de/guides/integrations-guide/markdoc/) installieren, um Markdoc zu unterstützen.) +<Tabs syncKey="pkg"> +<TabItem label="npm"> -### Seiten hinzufügen +```sh +npm run dev +``` -Füge neue Seiten zu deiner Webseite automatisch hinzu, indem du `.md` oder `.mdx` Dateien in `src/content/docs/` erstellst. Erstelle Unterordner, um deine Dateien zu organisieren und mehrere Pfadsegmente zu erstellen: +</TabItem> +<TabItem label="pnpm"> +```sh +pnpm dev ``` -src/content/docs/hello-world.md => your-site.com/hello-world -src/content/docs/guides/faq.md => your-site.com/guides/faq + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev ``` -### Typsichere Frontmatter +</TabItem> +</Tabs> -Alle Starlight Seiten teilen sich anpassbare [Frontmatter-Eigenschaften](/de/reference/frontmatter/), mit denen das Erscheinungsbild der Seite gesteuert wird: +Daraufhin wird eine Meldung mit der URL deiner lokalen Vorschau in deinem Terminal angezeigt. +Öffne diese URL, um deine Website zu betrachten. -```md ---- -title: Hello, World! -description: This is a page in my Starlight-powered site ---- -``` +### Inhalt hinzufügen -Wenn du etwas Wichtiges vergisst, wird Starlight dich daran erinnern. +Starlight ist bereit für dich, neuen Inhalt hinzuzufügen oder deine vorhandenen Dateien mitzubringen! -## Veröffentlichung deiner Starlight Webseite +Füge neue Seiten zu deiner Website hinzu, indem du Markdown-Dateien im Verzeichnis `src/content/docs/` erstellst. -Sobald du deine Starlight Webseite erstellt und angepasst hast, kannst du sie auf einen Webserver oder Hosting-Plattform deiner Wahl veröffentlichen, einschließlich Netlify, Vercel, GitHub Pages und vielen mehr. +Lies mehr über dateibasiertes Routing und Unterstützung für MDX- und Markdoc-Dateien in der Anleitung [„Seiten“](/de/guides/pages/). -[Lerne mehr über die Veröffentlichung einer Astro Webseite in der Astro Dokumentation.](https://docs.astro.build/de/guides/deploy/) +### Nächste Schritte + +- **Konfigurieren:** Erfahre mehr über die allgemeinen Optionen in [„Starlight anpassen“](/de/guides/customization/). +- **Navigieren:** Richte dir deine Seitenleiste mit der Anleitung [„Seitenleisten-Navigation“](/de/guides/sidebar/) ein. +- **Komponenten:** Entdecke die eingebauten Karten, Registerkarten und mehr in der Anleitung [„Komponenten“](/de/components/using-components/). +- **Erweitern:** Schau dir die Community-Erweiterungen in unseren Katalogen [„Plugins“](/de/resources/plugins/) und [„Themes“](/de/resources/themes/) an. +- **Veröffentlichen:** Veröffentliche deine Arbeit mit der Anleitung [„Bereitstellen deiner Website“](https://docs.astro.build/de/guides/deploy/) in der Astro-Dokumentation. ## Starlight aktualisieren -:::tip +:::tip[Tipp] Da es sich bei Starlight um eine Beta-Software handelt, wird es regelmäßig Updates und Verbesserungen geben. Achte darauf Starlight regelmäßig zu aktualisieren! ::: -Starlight ist eine Astro-Integration und wird wie jede `@astrojs/*`-Integration aktualisiert: +Starlight ist eine Astro-Integration. Dieses und andere Astro-Pakete kannst du aktualisieren, indem du den folgenden Befehl in deinem Terminal ausführst: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# Starlight mit npm aktualisieren -npm install @astrojs/starlight@latest +npx @astrojs/upgrade ``` </TabItem> <TabItem label="pnpm"> ```sh -# Starlight mit pnpm aktualisieren -pnpm upgrade @astrojs/starlight --latest +pnpm dlx @astrojs/upgrade ``` </TabItem> <TabItem label="Yarn"> ```sh -# Starlight mit yarn aktualisieren -yarn upgrade @astrojs/starlight --latest +yarn dlx @astrojs/upgrade ``` </TabItem> @@ -118,12 +129,12 @@ yarn upgrade @astrojs/starlight --latest Eine vollständige Liste der Änderungen findest du im [Starlight Changelog](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md). -## Fehlerbehebung - -Sowohl die Starlight [Projektkonfiguration](/reference/configuration/) als auch die [Konfiguration einzelner Seiten](/reference/frontmatter/) findest du im Referenzbereich dieser Website. Nutze diese Seiten, um sicherzustellen, dass deine Starlight-Site richtig konfiguriert ist und funktioniert. +## Fehlerbehebung Starlight -In der wachsenden Liste der Anleitungen in der Seitenleiste findest du Hilfe beim Hinzufügen von Inhalten und beim Anpassen deiner Starlight-Website. +Benutze die Referenzseiten [Projekt­konfiguration](/de/reference/configuration/) und [Individuelle Seitenfrontmatter-Konfiguration](/de/reference/frontmatter/), um sicherzustellen, dass deine Starlight-Website richtig konfiguriert ist und funktioniert. +In den Anleitungen in der Seitenleiste findest du Hilfe beim Hinzufügen von Inhalten und Anpassen deiner Starlight-Website. -Wenn du keine Antwort in dieser Dokumentation finden kannst, besuche bitte die [Astro Docs](https://docs.astro.build) für die vollständige Astro-Dokumentation. Deine Frage kann vielleicht beantwortet werden, wenn du verstehst, wie Astro im Allgemeinen funktioniert. +Wenn du deine Antwort nicht in dieser Dokumentation finden kannst, besuche bitte die [Astro-Dokumentation](https://docs.astro.build) für eine vollständige Dokumentation des darunterliegenden Frameworks. +Deine Frage lässt sich vielleicht beantworten, wenn du verstehst, wie Astro im Allgemeinen funktioniert, da Astro das Framework ist, auf dem Starlight basiert. -Du kannst auch im [Astro Discord](https://astro.build/chat/) Hilfe von unserer aktiven, freundlichen Community bekommen. Du kannst Fragen in unserem `#Support`-Forum stellen oder unseren speziellen `#starlight`-Channel besuchen, um aktuelle Entwicklungen und mehr zu diskutieren. +Du kannst auch nach bekannten [Starlight-Problemen auf GitHub](https://github.com/withastro/starlight/issues) suchen und im [Astro Discord](https://astro.build/chat/) Hilfe von unserer aktiven, freundlichen Community erhalten! Poste Fragen in unserem `#support` Forum mit dem „starlight“ Tag oder besuche unseren speziellen `#starlight`-Kanal, um über die aktuelle Entwicklung und mehr zu diskutieren! diff --git a/docs/src/content/docs/de/guides/authoring-content.mdx b/docs/src/content/docs/de/guides/authoring-content.mdx new file mode 100644 index 00000000000..47ad4b4944e --- /dev/null +++ b/docs/src/content/docs/de/guides/authoring-content.mdx @@ -0,0 +1,698 @@ +--- +title: Inhalte in Markdown verfassen +description: Ein Überblick über die von Starlight unterstützte Markdown-Syntax. +--- + +Starlight unterstützt die gesamte Bandbreite der [Markdown](https://daringfireball.net/projects/markdown/) Syntax in `.md` Dateien sowie Frontmatter [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) um Metadaten wie Titel und Beschreibung zu definieren. + +Bitte prüfe die [MDX-Dokumentation](https://mdxjs.com/docs/what-is-mdx/#markdown) oder [Markdoc-Dokumentation](https://markdoc.dev/docs/syntax), wenn du diese Dateiformate verwendest, da die Unterstützung und Verwendung von Markdown unterschiedlich sein kann. + +## Frontmatter + +Du kannst einzelne Seiten in Starlight anpassen, indem du Werte in deinen Frontmatter festlegst. +Frontmatter wird oben in deinen Dateien zwischen `---`-Trennzeichen festgelegt: + +```md title="src/content/docs/example.md" +--- +title: Mein Seitentitel +--- + +Nach dem zweiten `---` folgt der Seiteninhalt. +``` + +Jede Seite muss mindestens einen `title` enthalten. +Alle verfügbaren Felder und Informationen zum Hinzufügen benutzerdefinierter Felder findst du in der [Frontmatter-Referenz](/de/reference/frontmatter/). + +## Inline-Stile + +Text kann **fett**, _italic_, oder ~~durchgestrichen~~ sein. + +```md +Text kann **fett**, _italic_, oder ~~durchgestrichen~~ sein. +``` + +Du kannst [auf eine andere Seite](/de/getting-started/) verlinken. + +```md +Du kannst [auf eine andere Seite](/de/getting-started/) verlinken. +``` + +Du kannst `inline code` mit Backticks hervorheben. + +```md +Du kannst `inline code` mit Backticks hervorheben. +``` + +## Bilder + +Bilder in Starlight verwenden [Astros eingebaute optimierte Asset-Unterstützung](https://docs.astro.build/de/guides/images/). + +Markdown und MDX unterstützen die Markdown-Syntax für die Anzeige von Bildern, einschließlich Alt-Text für Bildschirmleser und unterstützende Technologien. + +![Eine Illustration von Planeten und Sternen mit dem Wort "Astro"](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) + +```md +![Eine Illustration von Planeten und Sternen mit dem Wort "astro"](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) +``` + +Relative Bildpfade werden auch für in deinem Projekt lokal gespeicherte Bilder unterstützt. + +```md +// src/content/docs/page-1.md + +![Ein Raketenschiff im Weltraum](../../assets/images/rocket.svg) +``` + +## Überschriften + +Mit einer Überschrift kannst du den Inhalt strukturieren. Überschriften in Markdown werden durch eine Reihe von `#` am Anfang der Zeile gekennzeichnet. + +### Wie du Seiteninhalte in Starlight strukturierst + +Starlight ist so konfiguriert, dass es automatisch den Seitentitel als Überschrift verwendet und eine "Übersicht"-Überschrift an den Anfang des Inhalts­verzeichnisses jeder Seite setzt. Wir empfehlen, jede Seite mit normalem Text zu beginnen und die Seitenüberschriften ab `<h2>` zu verwenden: + +```md +--- +title: Markdown Anleitung +description: Wie man Markdown in Starlight benutzt +--- + +Diese Seite beschreibt, wie man Markdown in Starlight benutzt. + +## Inline-Stile + +## Überschriften +``` + +### Automatische Überschriften-Ankerlinks + +Wenn du Überschriften in Markdown verwendst, erhaltst du automatisch Ankerlinks, sodass du direkt auf bestimmte Abschnitte deiner Seite verlinken kannst: + +```md +--- +title: Meine Seite mit Inhalt +description: Wie man Starlights eingebaute Ankerlinks benutzt +--- + +## Einleitung + +Ich kann auf [meine Schlussfolgerung](#schlussfolgerung) weiter unten auf derselben Seite verlinken. + +## Schlussfolgerung + +`https://meine-site.com/seite1/#einleitung` navigiert direkt zu meiner Einleitung. +``` + +Überschriften der Ebene 2 (`<h2>`) und der Ebene 3 (`<h3>`) werden automatisch im Inhaltsverzeichnis der Seite angezeigt. + +Erfahre mehr darüber, wie Astro Kopfzeilen-IDs verarbeitet, in [der Astro-Dokumentation](https://docs.astro.build/de/guides/markdown-content/#%C3%BCberschriften-ids). + +## Nebenbemerkungen + +Nebenbemerkungen (auch bekannt als "Ermahnungen" oder "Callouts") sind nützlich, um sekundäre Informationen neben dem Hauptinhalt einer Seite anzuzeigen. + +Starlight bietet eine eigene Markdown-Syntax für die Darstellung von Nebeninformationen. Seitenblöcke werden mit einem Paar dreifacher Doppelpunkte `:::` angezeigt, um den Inhalt zu umschließen, und können vom Typ `note`, `tip`, `caution` oder `danger` sein. + +Du kannst alle anderen Markdown-Inhaltstypen innerhalb einer Nebenbemerkung verschachteln, allerdings eignen sich diese am besten für kurze und prägnante Inhaltsstücke. + +### Nebenbemerkung `note` + +:::note +Starlight ist ein Toolkit für Dokumentations-Websites, das mit [Astro](https://astro.build/de) erstellt wurde. Du kannst mit diesem Befehl beginnen: + +```sh +npm create astro@latest -- --template starlight +``` + +::: + +````md +:::note +Starlight ist ein Toolkit für Dokumentations-Websites, das mit [Astro](https://astro.build/de) erstellt wurde. Du kannst mit diesem Befehl beginnen: + +```sh +npm create astro@latest -- --template starlight +``` + +::: +```` + +### Benutzerdefinierte Nebenbemerkungs­titel + +Du kannst einen benutzerdefinierten Titel für die Nebenbemerkung in eckigen Klammern nach dem Typen angeben, z. B. `:::tip[Wusstest du schon?]`. + +:::tip[Wusstest du schon?] +Astro hilft dir, schnellere Websites mit ["Inselarchitektur"](https://docs.astro.build/de/concepts/islands/) zu erstellen. +::: + +```md +:::tip[Wusstest du schon?] +Astro hilft dir, schnellere Websites mit ["Inselarchitektur"](https://docs.astro.build/de/concepts/islands/) zu erstellen. +::: +``` + +### Benutzerdefinierte Symbole für Nebenbemerkungen + +Du kannst ein benutzerdefiniertes Symbol für die Nebenbemerkungen in geschweiften Klammern nach dem Typ der Nebeninformation oder dem [benutzerdefinierten Titel](#benutzerdefinierte-nebenbemerkungstitel) angeben, z. B. `:::tip{icon="heart"}` oder `:::tip[Wusstest du schon?]{icon="heart"}`. +Der Name des Symbols muss dem Namen [eines der in Starlight integrierten Symbole](/de/reference/icons/#alle-symbole) entsprechen. + +:::tip{icon="heart"} +Astro hilft dir, schnellere Websites mit ["Inselarchitektur"](https://docs.astro.build/de/concepts/islands/) zu erstellen. +::: + +```md +:::tip{icon="heart"} +Astro hilft dir, schnellere Websites mit ["Inselarchitektur"](https://docs.astro.build/de/concepts/islands/) zu erstellen. +::: +``` + +### Weitere Typen + +Vorsichts- und Gefahrenhinweise sind hilfreich, um die Aufmerksamkeit des Benutzers auf Details zu lenken, über die er stolpern könnte. +Wenn du diese häufig verwenden, kann das auch ein Zeichen dafür sein, dass die Sache, die du dokumentierst, von einem neuen Design profitieren könnte. + +:::caution +Wenn du nicht sicher bist, ob du eine großartige Dokumentationswebsite willst, überlege es dir zweimal, bevor du [Starlight](/de/) verwendest. +::: + +:::danger +Deine Benutzer können dank hilfreicher Starlight-Funktionen produktiver sein und dein Produkt einfacher nutzen. + +- Übersichtliche Navigation +- Benutzer-konfigurierbares Farben-Theme +- [i18n-Unterstützung](/de/guides/i18n/) + +::: + +```md +:::caution +Wenn du nicht sicher bist, ob du eine großartige Dokumentationswebsite willst, überlege es dir zweimal, bevor du [Starlight](/de/) verwendest. +::: + +:::danger +Deine Benutzer können dank hilfreicher Starlight-Funktionen produktiver sein und dein Produkt einfacher nutzen. + +- Übersichtliche Navigation +- Benutzer-konfigurierbares Farben-Theme +- [i18n-Unterstützung](/de/guides/i18n/) + +::: +``` + +## Blockzitate + +> Dies ist ein Blockzitat, das üblicherweise verwendet wird, wenn eine andere Person oder ein Dokument zitiert wird. +> +> Blockzitate werden durch ein ">" am Anfang jeder Zeile gekennzeichnet. + +```md +> Dies ist ein Blockzitat, das üblicherweise verwendet wird, wenn eine andere Person oder ein Dokument zitiert wird. +> +> Blockzitate werden durch ein ">" am Anfang jeder Zeile gekennzeichnet. +``` + +## Codeblöcke + +Ein Codeblock wird durch einen Block mit drei Backticks <code>```</code> am Anfang und Ende gekennzeichnet. Du kannst die verwendete Programmiersprache nach den ersten drei Backticks angeben. + +```js +// Javascript-Code mit Syntaxhervorhebung. +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` + +````md +```js +// Javascript-Code mit Syntaxhervorhebung. +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` +```` + +### Expressive Code-Merkmale + +Starlight verwendet [Expressive Code](https://expressive-code.com/), um die Formatierungs­möglichkeiten für Codeblöcke zu erweitern. +Die Textmarker und Fensterrahmen-Plugins von Expressive Code sind standardmäßig aktiviert. +Die Darstellung von Codeblöcken kann mit Starlights [`expressiveCode` Konfigurations­option](/de/reference/configuration/#expressivecode) konfiguriert werden. + +#### Textmarkierungen + +Du kannst bestimmte Zeilen oder Teile deiner Codeblöcke hervorheben, indem du [Expressive Code Textmarkierungen](https://expressive-code.com/key-features/text-markers/) in der ersten Zeile deines Codeblocks verwendest. +Verwende geschweifte Klammern (`{ }`), um ganze Zeilen hervorzuheben, und Anführungszeichen, um Textabschnitte zu markieren. + +Es gibt drei Hervorhebungsstile: neutral, um auf den Code aufmerksam zu machen, grün, um eingefügten Code zu kennzeichnen, und rot, um gelöschten Code zu kennzeichnen. +Sowohl Text als auch ganze Zeilen können mit der Standardmarkierung oder in Kombination mit `ins=` und `del=` markiert werden, um die gewünschte Hervorhebung zu erzielen. + +Expressive Code bietet mehrere Optionen zur Anpassung des visuellen Erscheinungsbildes deiner Codebeispiele. +Viele dieser Optionen können kombiniert werden, um sehr anschauliche Codebeispiele zu erstellen. +Bitte schaue dir die [Expressive Code Dokumentation](https://expressive-code.com/key-features/text-markers/#configuration) an, um dich über die umfangreichen Optionen zu informieren. +Einige der gebräuchlichsten Beispiele sind unten aufgeführt: + +- [Markiere ganze Zeilen und Zeilenbereiche mit dem Marker `{ }`](https://expressive-code.com/key-features/text-markers/#marking-full-lines--line-ranges): + + ```js {2-3} + function demo() { + // Diese Zeile (#2) und die nächste Zeile sind hervorgehoben + return 'Dies ist Zeile #3 dieses Ausschnittes'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js {2-3} + function demo() { + // Diese Zeile (#2) und die nächste Zeile sind hervorgehoben + return 'Dies ist Zeile #3 dieses Ausschnittes'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="{2-3}" %} + function demo() { + // Diese Zeile (#2) und die nächste Zeile sind hervorgehoben + return 'Dies ist Zeile #3 dieses Ausschnittes'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [Markieren von Textabschnitten mit der Markierung `" "` oder regulären Ausdrücken](https://expressive-code.com/key-features/text-markers/#marking-individual-text-inside-lines): + + ```js "einzelne Begriffe" /Auch.*unterstützt/ + // Auch einzelne Begriffe können hervorgehoben werden + function demo() { + return 'Auch reguläre Ausdrücke (RegEx) werden unterstützt'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "einzelne Begriffe" /Auch.*unterstützt/ + // Auch einzelne Begriffe können hervorgehoben werden + function demo() { + return 'Auch reguläre Ausdrücke (RegEx) werden unterstützt'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'einzelne Begriffe' /Auch.*unterstützt/" %} + // Auch einzelne Begriffe können hervorgehoben werden + function demo() { + return 'Auch reguläre Ausdrücke (RegEx) werden unterstützt'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [Text oder Zeilen mit `ins` oder `del` als eingefügt oder gelöscht markieren](https://expressive-code.com/key-features/text-markers/#selecting-inline-marker-types-mark-ins-del): + + ```js "return true;" ins="eingefügte" del="gelöschte" + function demo() { + console.log('Dies sind eingefügte und gelöschte Markertypen'); + // Die return-Anweisung verwendet den Standard-Markierungstyp + return true; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "return true;" ins="eingefügte" del="gelöschte" + function demo() { + console.log('Dies sind eingefügte und gelöschte Markertypen'); + // Die return-Anweisung verwendet den Standard-Markierungstyp + return true; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'return true;' ins='eingefügte' del='gelöschte'" %} + function demo() { + console.log('Dies sind eingefügte und gelöschte Markertypen'); + // Die return-Anweisung verwendet den Standard-Markierungstyp + return true; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [Kombiniere die Syntaxhervorhebung mit einer `diff`-ähnlichen Syntax](https://expressive-code.com/key-features/text-markers/#combining-syntax-highlighting-with-diff-like-syntax): + + ```diff lang="js" + function thisIsJavaScript() { + // Dieser gesamte Block wird als JavaScript hervorgehoben, + // und wir können ihm immer noch Diff-Markierungen hinzufügen! + - console.log('Zu entfernender alter Code') + + console.log('Neuer, glänzender Code!') + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```diff lang="js" + function thisIsJavaScript() { + // Dieser gesamte Block wird als JavaScript hervorgehoben, + // und wir können ihm immer noch Diff-Markierungen hinzufügen! + - console.log('Zu entfernender alter Code') + + console.log('Neuer, glänzender Code!') + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```diff {% meta="lang='js'" %} + function thisIsJavaScript() { + // Dieser gesamte Block wird als JavaScript hervorgehoben, + // und wir können ihm immer noch Diff-Markierungen hinzufügen! + - console.log('Zu entfernender alter Code') + + console.log('Neuer, glänzender Code!') + } + ``` + ```` + + </TabItem> + + </Tabs> + +#### Rahmen und Überschriften + +Codeblöcke können innerhalb eines fensterähnlichen Rahmens dargestellt werden. +Ein Rahmen, der wie ein Terminalfenster aussieht, wird für Shell-Skriptsprachen (z. B. `bash` oder `sh`) verwendet. +Andere Sprachen werden in einem Rahmen im Stil eines Code-Editors angezeigt, wenn sie einen Titel enthalten. + +Der optionale Titel eines Code-Blocks kann entweder mit einem `title="..."`-Attribut gesetzt werden, das den öffnenden Backticks und dem Sprachbezeichner des Code-Blocks folgt, oder mit einem Dateinamenkommentar in den ersten Zeilen des Codes. + +- [Hinzufügen einer Registerkarte für den Dateinamen mit einem Kommentar](https://expressive-code.com/key-features/frames/#code-editor-frames) + + ```js + // meine-test-datei.js + console.log('Hallo Welt!'); + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js + // meine-test-datei.js + console.log('Hallo Welt!'); + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````md + ```js + // meine-test-datei.js + console.log('Hallo Welt!'); + ``` + ```` + + </TabItem> + + </Tabs> + +- [Hinzufügen eines Titels zu einem Terminalfenster](https://expressive-code.com/key-features/frames/#terminal-frames) + + ```bash title="Installieren von Abhängigkeiten…" + npm install + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash title="Installieren von Abhängigkeiten…" + npm install + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% title="Installieren von Abhängigkeiten…" %} + npm install + ``` + ```` + + </TabItem> + + </Tabs> + +- [Fensterrahmen mit `frame="none"` deaktivieren](https://expressive-code.com/key-features/frames/#overriding-frame-types) + + ```bash frame="none" + echo "Dies wird trotz Verwendung der Bash-Sprache nicht als Terminal dargestellt" + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash frame="none" + echo "Dies wird trotz Verwendung der Bash-Sprache nicht als Terminal dargestellt" + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% frame="none" %} + echo "Dies wird trotz Verwendung der Bash-Sprache nicht als Terminal dargestellt" + ``` + ```` + + </TabItem> + + </Tabs> + +## Details + +Details (auch bekannt als „Offenlegungen“ oder „Akkordeons“) sind nützlich, um Inhalte zu verbergen, die nicht unmittelbar relevant sind. +Die Nutzer können auf eine kurze Zusammenfassung klicken, um den gesamten Inhalt zu sehen. + +Verwende die Standard-HTML-Elemente [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details) und [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary) in deinem Markdown-Inhalt, um ein Offenlegungs-Widget zu erstellen. + +Du kannst jede andere Markdown-Syntax innerhalb eines `<details>`-Elements verschachteln. + +<details> +<summary>Wo und wann ist das Sternbild Andromeda am besten zu sehen?</summary> + +Das Sternbild [Andromeda](<https://de.wikipedia.org/wiki/Andromeda_(Sternbild)>) ist am Nachthimmel im Monat November in Breitengraden zwischen `+90°` und `−40°` am besten sichtbar. + +</details> + +```md +<details> +<summary>Wo und wann ist das Sternbild Andromeda am besten zu sehen?</summary> + +Das Sternbild [Andromeda](<https://de.wikipedia.org/wiki/Andromeda_(Sternbild)>) ist am Nachthimmel im Monat November in Breitengraden zwischen `+90°` und `−40°` am besten sichtbar. + +</details> +``` + +## Fußnoten + +[Fußnoten](https://www.markdownguide.org/extended-syntax/#footnotes) sind nützlich, um kurze Hinweise oder Erklärungen hinzuzufügen, ohne den Textfluss zu stören. Sie werden hochgestellt als nummerierte Links im Text angezeigt, die zu den entsprechenden Erläuterungen am Ende der Seite führen. + +Erstelle eine Fußnote mit eckigen Klammern, einem Caret (auch bekannt als Zirkumflex oder Dach) und einer Nummer: + +```md +Hier ist eine Fußnote[^1] mit nachfolgendem Referenztext. + +[^1]: Meine Referenz. +``` + +## Andere allgemeine Markdown-Funktionen + +Starlight unterstützt alle anderen Markdown-Autorensyntaxen, wie Listen und Tabellen. Einen schnellen Überblick über alle Markdown-Syntaxelemente findest du im [Markdown Cheat Sheet von The Markdown Guide](https://www.markdownguide.org/cheat-sheet/). + +## Erweiterte Markdown- und MDX-Konfiguration + +Starlight verwendet Astros Markdown- und MDX-Renderer, der auf remark und rehype aufbaut. Du kannst eine Unterstützung für eigene Syntax und Verhalten hinzufügen, indem du `remarkPlugins` oder `rehypePlugins` in deiner Astro-Konfigurationsdatei hinzufügst. Weitere Informationen findest du unter ["Markdown konfigurieren"](https://docs.astro.build/de/guides/markdown-content/#markdown-plugins) in der Astro-Dokumentation. + +## Markdoc + +Starlight unterstützt die Erstellung von Inhalten in Markdoc mithilfe der experimentellen [Astro Markdoc-Integration](https://docs.astro.build/de/guides/integrations-guide/markdoc/) und der Starlight-Markdoc-Voreinstellung. + +### Erstelle ein neues Projekt mit Markdoc + +Starte ein neues Starlight-Projekt mit vorkonfiguriertem Markdoc mit `create astro`: + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight/markdoc +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight/markdoc +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight/markdoc +``` + +</TabItem> +</Tabs> + +### Markdoc zu einem bestehenden Projekt hinzufügen + +Wenn du bereits eine Starlight-Website hast und Markdoc hinzufügen möchtest, befolge diese Schritte. + +<Steps> + +1. Füge Astros Markdoc-Integration hinzu: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npx astro add markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm astro add markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn astro add markdoc + ``` + + </TabItem> + + </Tabs> + +2. Installiere die Starlight-Markdoc-Voreinstellung: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-markdoc + ``` + + </TabItem> + + </Tabs> + +3. Erstelle eine Markdoc-Konfigurationsdatei unter `markdoc.config.mjs` und verwende die Starlight-Markdoc-Voreinstellung: + + ```js + import { defineMarkdocConfig } from '@astrojs/markdoc/config'; + import starlightMarkdoc from '@astrojs/starlight-markdoc'; + + export default defineMarkdocConfig({ + extends: [starlightMarkdoc()], + }); + ``` + +</Steps> + +Weitere Informationen zur Syntax und den Funktionen von Markdoc findest du in der [Markdoc-Dokumentation](https://markdoc.dev/docs/syntax) oder im [Astro Markdoc-Integrations­handbuch](https://docs.astro.build/de/guides/integrations-guide/markdoc/). + +### Konfigurieren der Markdoc-Voreinstellung + +Die Voreinstellung `starlightMarkdoc()` akzeptiert die folgenden Konfigurationsoptionen: + +#### `headingLinks` + +**Typ:** `boolean` +**Standard:** `true` + +Legt fest, ob Überschriften mit einem anklickbaren Ankerlink dargestellt werden oder nicht. +Entspricht der Option [`markdown.headingLinks`](/de/reference/configuration/#markdown), die für Markdown- und MDX-Dateien gilt. + +```js "headingLinks: false" +export default defineMarkdocConfig({ + // Deaktiviere die Standardunterstützung für Überschrift-Ankerlinks + extends: [starlightMarkdoc({ headingLinks: false })], +}); +``` diff --git a/docs/src/content/docs/de/guides/css-and-tailwind.mdx b/docs/src/content/docs/de/guides/css-and-tailwind.mdx new file mode 100644 index 00000000000..8bd93dba3f8 --- /dev/null +++ b/docs/src/content/docs/de/guides/css-and-tailwind.mdx @@ -0,0 +1,362 @@ +--- +title: CSS & Styling +description: Lerne, wie du deine Starlight-Website mit benutzerdefiniertem CSS gestalten oder mit Tailwind CSS integrieren kannst. +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +Du kannst deine Starlight-Website mit benutzerdefinierten CSS-Dateien gestalten oder das Starlight Tailwind-Plugin verwenden. + +Eine schnelle Möglichkeit, das Standardtheme deiner Website zu ändern, findest du unter [Cummunity-Themes](/de/resources/themes/). + +## Benutzerdefinierte CSS-Styles (Stile) + +Passe die Styles deiner Starlight-Website an, indem du zusätzliche CSS-Dateien bereitstellst, um die Standard-Styles von Starlight zu verändern oder zu erweitern. + +<Steps> + +1. Füge eine CSS-Datei zu deinem `src/`-Verzeichnis hinzu. + Du kannst zum Beispiel eine größere Standard-Spaltenbreite und eine größere Textgröße für den Seitentitel festlegen: + + ```css + /* src/styles/custom.css */ + :root { + --sl-content-width: 50rem; + --sl-text-5xl: 3.5rem; + } + ``` + +2. Füge den Pfad zu deiner CSS-Datei in Starlights `customCss`- Array in `astro.config.mjs` ein: + + ```diff lang="js" + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Dokumentation mit benutzerdefiniertem CSS', + customCss: [ + + // Relativer Pfad zu deiner benutzerdefinierten CSS-Datei + + './src/styles/custom.css', + ], + }), + ], + }); + ``` + +</Steps> + +Du kannst dir alle CSS-Eigenschaften, die von Starlight verwendet werden und die du einstellen kannst, um deine Website anzupassen, in der [Datei `props.css` auf GitHub](https://github.com/withastro/starlight/blob/main/packages/starlight/style/props.css) ansehen. + +### Kaskadenschichten + +Starlight verwendet intern [Kaskadenschichten](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers), um die Reihenfolge der Stile zu verwalten. +Dies gewährleistet eine vorhersehbare CSS-Reihenfolge und ermöglicht einfachere Überschreibungen. +Jedes benutzerdefinierte CSS ohne Schichten überschreibt die Standardstile von Starlight. + +Wenn du Kaskadenschichten verwendest, kannst du [`@layer`](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) in deinem benutzerdefinierten CSS verwenden, um die Rangfolge der verschiedenen Schichten in Bezug auf die Stile der Schicht `starlight` festzulegen: + +```css "starlight" +/* src/styles/custom.css */ +@layer my-reset, starlight, my-overrides; +``` + +Das obige Beispiel definiert eine benutzerdefinierte Schicht namens `my-reset`, die vor allen Starlight-Schichten angewendet wird, und eine weitere Schicht namens `my-overrides`, die nach allen Starlight-Schichten angewendet wird. +Alle Stile in der Schicht `my-overrides` haben Vorrang vor den Stilen von Starlight, aber Starlight kann immer noch Stile ändern, die in der Schicht `my-reset` festgelegt wurden. + +## Tailwind CSS + +Die Unterstützung für Tailwind CSS v4 in Astro-Projekten wird durch das [Tailwind Vite-Plugin](https://tailwindcss.com/docs/installation/using-vite) bereitgestellt. +Starlight bietet komplementäres CSS, um Tailwind für die Kompatibilität mit den Styles von Starlight zu konfigurieren. + +Das Starlight Tailwind CSS wendet die folgende Konfiguration an: + +- Konfiguriert Tailwinds `dark:`-Varianten so, dass sie mit Starlights Dark Mode funktionieren. +- Verwendet Tailwind [Themenfarben und Schriftarten](#starlight-mit-tailwind-designen) in Starlights UI. +- Stellt wesentliche Teile der Preflight-Reset-Stile von Tailwind wieder her. + +### Erstelle ein neues Projekt mit Tailwind + +Starte ein neues Starlight-Projekt mit Tailwind CSS vorkonfiguriert, indem du `create astro` verwendest: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight/tailwind +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight/tailwind +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight/tailwind +``` + +</TabItem> +</Tabs> + +### Tailwind zu einem bestehenden Projekt hinzufügen + +Wenn du bereits eine Starlight-Website hast und Tailwind CSS hinzufügen möchtest, folge dieser Anleitung. + +<Steps> + +1. Richte Tailwind in deinem Projekt ein, indem du den folgenden Befehl ausführst und den Anweisungen in deinem Terminal folgst: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npx astro add tailwind + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm astro add tailwind + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn astro add tailwind + ``` + + </TabItem> + + </Tabs> + +2. Installiere das Tailwind-Kompatibilitätspaket von Starlight: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-tailwind + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-tailwind + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-tailwind + ``` + + </TabItem> + + </Tabs> + +3. Ersetze den Inhalt der Datei `src/styles/global.css`, die von Astro für die Kompatibilität mit Starlight gerüstet wurde: + + ```css + /* src/styles/global.css */ + @layer base, starlight, theme, components, utilities; + + @import '@astrojs/starlight-tailwind'; + @import 'tailwindcss/theme.css' layer(theme); + @import 'tailwindcss/utilities.css' layer(utilities); + ``` + + Diese Tailwind-Theme-Konfiguration legt die Reihenfolge der [Kaskadenschichten](#kaskadenschichten) von Starlight fest, importiert das ergänzende CSS von Starlight für Tailwind und importiert die Theme- und Utility-Stile von Tailwind. + Wenn dein Projekt eine zusätzliche Tailwind-Konfiguration erfordert, schau dir den Abschnitt [„Mehrere Tailwind-Konfigurationen verwenden“](#mehrere-tailwind-konfigurationen-verwenden) an. + +4. Aktualisiere die Starlight-Konfiguration, um die Tailwind-CSS-Datei als erstes Element im Array `customCss` hinzuzufügen: + + ```js ins={11-12} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import tailwindcss from '@tailwindcss/vite'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Dokumentation mit Tailwind', + customCss: [ + // Pfad zu deinen grundlegenden Tailwind-Styles + './src/styles/global.css', + ], + }), + ], + vite: { plugins: [tailwindcss()] }, + }); + ``` + +</Steps> + +### Starlight mit Tailwind designen + +Wenn du ein [neues Starlight-Projekt mit Tailwind erstellst](#erstelle-ein-neues-projekt-mit-tailwind) oder [Tailwind zu einem bestehenden Starlight-Projekt hinzufügst](#tailwind-zu-einem-bestehenden-projekt-hinzufügen), verwendet Starlight die Werte aus deiner [Tailwind-Themenkonfiguration](https://tailwindcss.com/docs/theme) in der Datei `src/styles/global.css`, um die Benutzeroberfläche zu gestalten. + +Wenn diese Option aktiviert ist, überschreiben die folgenden benutzerdefinierten CSS-Eigenschaften die Standardstile von Starlight: + +- `--color-accent-*` - wird für Links und die Hervorhebung des aktuellen Elements verwendet +- `--color-gray-*` - wird für Hintergrundfarben und Rahmen verwendet +- `--font-sans` - wird für UI und Inhaltstext verwendet +- `--font-mono` - wird für Code-Beispiele verwendet + +```css {9-12,14-17,19-22,34-37} +/* src/styles/global.css */ +@layer base, starlight, theme, components, utilities; + +@import '@astrojs/starlight-tailwind'; +@import 'tailwindcss/theme.css' layer(theme); +@import 'tailwindcss/utilities.css' layer(utilities); + +@theme { + /* + Deine bevorzugte Schriftart. + Starlight verwendet standardmäßig eine Systemschriftart. + */ + --font-sans: 'Atkinson Hyperlegible'; + /* + Deine bevorzugte Code-Schriftart. + Starlight verwendet standardmäßig die Systemschriftart Monospace. + */ + --font-mono: 'IBM Plex Mono'; + /* + Deine bevorzugte Akzentfarbe. + Indigo entspricht am ehesten den Standardeinstellungen von Starlight. + */ + --color-accent-50: var(--color-indigo-50); + --color-accent-100: var(--color-indigo-100); + --color-accent-200: var(--color-indigo-200); + --color-accent-300: var(--color-indigo-300); + --color-accent-400: var(--color-indigo-400); + --color-accent-500: var(--color-indigo-500); + --color-accent-600: var(--color-indigo-600); + --color-accent-700: var(--color-indigo-700); + --color-accent-800: var(--color-indigo-800); + --color-accent-900: var(--color-indigo-900); + --color-accent-950: var(--color-indigo-950); + /* + Deine bevorzugte Grauskala. + Zink kommt den Standardeinstellungen von Starlight am nächsten. + */ + --color-gray-50: var(--color-zinc-50); + --color-gray-100: var(--color-zinc-100); + --color-gray-200: var(--color-zinc-200); + --color-gray-300: var(--color-zinc-300); + --color-gray-400: var(--color-zinc-400); + --color-gray-500: var(--color-zinc-500); + --color-gray-600: var(--color-zinc-600); + --color-gray-700: var(--color-zinc-700); + --color-gray-800: var(--color-zinc-800); + --color-gray-900: var(--color-zinc-900); + --color-gray-950: var(--color-zinc-950); +} +``` + +### Mehrere Tailwind-Konfigurationen verwenden + +Mehrere Tailwind-Konfigurationen können verwendet werden, um verschiedene Stile auf verschiedene Teile deiner Website anzuwenden, z. B. wenn du [Starlight in einem Unterpfad verwendest](/de/manual-setup/#starlight-mit-einem-anderen-pfad-verwenden) oder wenn du [benutzerdefinierte Seiten](/de/guides/pages/#benutzerdefinierte-seiten) zu deiner Website hinzufügst. +Du möchtest vielleicht die Preflight-Reset-Stile von Tailwind auf deinen benutzerdefinierten Seiten verwenden und trotzdem die Kompatibilitätsschicht von Starlight auf Starlight-Seiten anwenden. + +Die folgende Tailwind-CSS-Konfiguration richtet Tailwind ohne Plugins oder zusätzliche Einstellungen ein und kann als Ausgangspunkt für Seiten verwendet werden, die nicht mit Starlight erstellt wurden: + +```css title="src/styles/custom-pages-tailwind.css" +/* Lade Tailwind ohne die zusätzlichen CSS-Dateien von Starlight. */ +@import 'tailwindcss'; +``` + +<Steps> + +1. Nimm für Starlight-Seiten deine bevorzugte Tailwind-CSS-Konfiguration, indem du [„Tailwind zu einem bestehenden Projekt hinzufügen“](#tailwind-zu-einem-bestehenden-projekt-hinzufügen) befolgst. + +2. Für andere Seiten nimm einfach deine Tailwind CSS-Einstellungen, indem du sie dort importierst. Das macht man oft in einer Layout-Komponente, damit die Tailwind-Stile auf allen Seiten mit dem gleichen Layout funktionieren. + ```astro + --- + // src/layouts/CustomPageLayout.astro + import '../styles/custom-pages-tailwind.css'; + --- + ``` + +</Steps> + +Weitere Infos zu Tailwind-Theme-Konfigurationen findest du in der [Tailwind CSS-Dokumentation](https://tailwindcss.com/docs/theme). + +## Themes + +Das Farbtheme von Starlight kann gesteuert werden, indem die Standard­einstellungen überschrieben werden. +Diese Variablen werden in der gesamten Benutzeroberfläche verwendet, wobei eine Reihe von Grautönen für Text- und Hintergrundfarben sowie eine Akzentfarbe für Links und zur Hervorhebung aktueller Elemente in der Navigation verwendet werden. + +### Farbdesign-Editor + +Verwende die Schieberegler unten, um die Akzent- und Graufarbpalette von Starlight zu ändern. +Die dunklen und hellen Vorschaubereiche zeigen die resultierenden Farben, und die gesamte Seite wird ebenfalls aktualisiert, um deine Änderungen anzuzeigen. + +Verwende die Option Kontraststufe, um festzulegen, welche der Richtlinie für die Zugänglichkeit von Webinhalten [Farbkontrast­standards](https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast) erfüllt werden soll. + +Wenn du mit deinen Änderungen zufrieden bist, kopiere den CSS- oder Tailwind-Code unten und verwende ihn in deinem Projekt. + +import ThemeDesigner from '~/components/theme-designer.astro'; + +<ThemeDesigner + labels={{ + presets: { + label: 'Voreinstellungen', + ocean: 'Ozean', + forest: 'Wald', + oxide: 'Oxid', + nebula: 'Nebel', + default: 'Standard', + random: 'Zufällig', + }, + contrast: { + label: 'Kontraststufe', + }, + editor: { + accentColor: 'Akzent', + grayColor: 'Grau', + hue: 'Farbton', + chroma: 'Sättigung', + pickColor: 'Wähle Farbe', + }, + preview: { + darkMode: 'Dark mode', + lightMode: 'Light mode', + bodyText: + 'Der Fließtext wird in einem Grauton mit hohem Kontrast zum Hintergrund dargestellt.', + linkText: 'Links sind farbig.', + dimText: + 'Einige Texte, wie z. B. das Inhaltsverzeichnis, haben einen geringeren Kontrast.', + inlineCode: 'Inline-Code hat einen eindeutigen Hintergrund.', + }, + }} +> + <Fragment slot="css-docs"> + Füge das folgende CSS in deinem Projekt in eine [benutzerdefinierte + CSS-Datei](#benutzerdefinierte-css-styles-stile) ein, um dieses Theme auf + deiner Website anzuwenden. + </Fragment> + <Fragment slot="tailwind-docs"> + Füge die folgenden CSS-Variablen in den `@theme`-Block in deiner + [Tailwind-CSS Datei](#starlight-mit-tailwind-designen) hinzu, um dieses + Thema auf deiner Seite anzuwenden. + </Fragment> +</ThemeDesigner> diff --git a/docs/src/content/docs/de/guides/customization.mdx b/docs/src/content/docs/de/guides/customization.mdx new file mode 100644 index 00000000000..999ed959193 --- /dev/null +++ b/docs/src/content/docs/de/guides/customization.mdx @@ -0,0 +1,474 @@ +--- +title: Starlight anpassen +description: Lerne, wie du deine Starlight-Website mit deinem Logo, eigenen Schriftarten, Landing-Page-Design und vielem mehr zu deiner eigenen machen kannst. +--- + +import { Tabs, TabItem, FileTree, Steps } from '@astrojs/starlight/components'; + +Starlight bietet sinnvolle Standard-Styling und -Funktionen, so dass du schnell loslegen kannst, ohne dass eine Konfiguration erforderlich ist. +Wenn du das Aussehen deiner Starlight-Website anpassen willst, findest du in dieser Anleitung alle nötigen Informationen. + +## Dein Logo hinzufügen + +Das Hinzufügen eines eigenen Logos im Header ist ein schneller Weg, um einer Starlight-Website dein individuelles Branding zu geben. + +<Steps> + +1. Füge deine Logodatei in das Verzeichnis `src/assets/` ein: + + <FileTree> + + - src/ + - assets/ + - **mein-logo.svg** + - content/ + - astro.config.mjs + + </FileTree> + +2. Füge den Pfad zu deinem Logo als Starlights [`logo.src`](/de/reference/configuration/#logo) Option in `astro.config.mjs` ein: + + ```diff lang="js" + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Dokumentation mit meinem Logo', + logo: { + + src: './src/assets/mein-logo.svg', + }, + }), + ], + }); + ``` + +</Steps> + +Standardmäßig wird das Logo neben dem `title` deiner Website angezeigt. +Wenn dein Logobild bereits den Titel der Website enthält, kannst du den Titeltext optisch ausblenden, indem du die Option `replacesTitle` setzt. +Der `title`-Text wird für Bildschirmleser weiterhin angezeigt, so dass die Kopfzeile zugänglich bleibt. + +```js {5} +starlight({ + title: 'Dokumentation mit meinem Logo', + logo: { + src: './src/assets/mein-logo.svg', + replacesTitle: true, + }, +}), +``` + +### Light- und Dark-Mode Logovarianten + +Du kannst verschiedene Versionen deines Logos im Light- und Dark-Mode anzeigen. + +<Steps> + +1. Füge eine Bilddatei für jede Variante zu `src/assets/` hinzu: + + <FileTree> + + - src/ + - assets/ + - **light-logo.svg** + - **dark-logo.svg** + - content/ + - astro.config.mjs + + </FileTree> + +2. Füge den Pfad zu deiner Logovarianten als die Optionen `light` und `dark` anstelle von `src` in `astro.config.mjs` ein: + + ```diff lang="js" + starlight({ + title: 'Dokumentation mit meinem Logo', + logo: { + + light: './src/assets/light-logo.svg', + + dark: './src/assets/dark-logo.svg', + }, + }), + ``` + +</Steps> + +## Sitemap aktivieren + +Starlight hat eine eingebaute Unterstützung für die Erstellung einer Sitemap. Aktiviere die Sitemap-Generierung, indem du deine URL als `site` in `astro.config.mjs` angibst: + +```js {4} +// astro.config.mjs + +export default defineConfig({ + site: 'https://stargazers.club', + integrations: [starlight({ title: 'Website mit Sitemap' })], +}); +``` + +Erfahre in den Astro Docs, wie du [einen Sitemap-Link zur `robots.txt` hinzufügst] (https://docs.astro.build/de/guides/integrations-guide/sitemap/#sitemap-link-in-robotstxt). + +## Seitenlayout + +Starlight-Seiten verwenden standardmäßig ein Layout mit einer globalen Navigation und einem Inhaltsverzeichnis, das die aktuellen Seitenüberschriften anzeigt. + +Du kannst ein breiteres Seitenlayout ohne Navigationen verwenden, indem du [`template: splash`](/de/reference/frontmatter/#template) im Frontmatter einer Seite setzt. +Dies funktioniert besonders gut für Landingpages, und du kannst es in Aktion auf der [Homepage dieser Website](/de/) sehen. + +```md {5} +--- +# src/content/docs/index.md + +title: Meine Landing Page +template: splash +--- +``` + +## Inhaltsverzeichnis + +Starlight zeigt auf jeder Seite ein Inhaltsverzeichnis an, um es den Lesern zu erleichtern, zu der gesuchten Überschrift zu springen. +Du kannst das Inhaltsverzeichnis global in der Starlight-Integration oder seitenweise im Frontmatter anpassen - oder sogar deaktivieren. + +Standardmäßig werden die Überschriften `<h2>` und `<h3>` in das Inhaltsverzeichnis aufgenommen. Ändere die Überschriftsebenen für die gesamte Website mit den Optionen `minHeadingLevel` und `maxHeadingLevel` in deinem [globalen `tableOfContents`](/de/reference/configuration/#tableofcontents). Überschreibe diese Standardwerte auf einer individuellen Seite, indem du die entsprechenden [Frontmatter `tableOfContents`](/de/reference/frontmatter/#tableofcontents) Eigenschaften hinzufügst: + +<Tabs syncKey="config-type"> + <TabItem label="Frontmatter"> + +```md {4-6} +--- +# src/content/docs/example.md +title: Seite mit nur H2s im Inhaltsverzeichnis +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 2 +--- +``` + + </TabItem> + <TabItem label="Globale Konfiguration"> + +```js {7} +// astro.config.mjs + +defineConfig({ + integrations: [ + starlight({ + title: 'Dokumentation mit benutzerdefinierten Inhaltsverzeichnissen', + tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 2 }, + }), + ], +}); +``` + + </TabItem> +</Tabs> + +Deaktiviere das Inhaltsverzeichnis vollständig, indem du die Option `tableOfContents` auf `false` setzt: + +<Tabs syncKey="config-type"> + <TabItem label="Frontmatter"> + +```md {4} +--- +# src/content/docs/example.md +title: Seite ohne Inhaltsverzeichnis +tableOfContents: false +--- +``` + + </TabItem> + <TabItem label="Globale Konfiguration"> + +```js {7} +// astro.config.mjs + +defineConfig({ + integrations: [ + starlight({ + title: 'Dokumentation mit global deaktiviertem Inhaltsverzeichnis', + tableOfContents: false, + }), + ], +}); +``` + + </TabItem> +</Tabs> + +## Soziale Links + +Starlight bietet integrierte Unterstützung für das Hinzufügen von Links zu deinen Social-Media-Accounts in der Kopfzeile der Website über die Option [`social`](/de/reference/configuration/#social) in der Starlight-Integration. + +Jeder Eintrag im Array `social` muss ein Objekt mit drei Eigenschaften sein: + +- `icon`: eines der [eingebauten Symbolen](/de/reference/icons/) von Starlight, z. B. `"github"`. +- `label`: eine zugängliche Bezeichnung für den Link, z. B. `"GitHub"`. +- `href`: die URL für den Link, z. B. `"https://github.com/withastro/starlight"`. + +Das folgende Beispiel fügt Links zum Astro Discord Chat und zum Starlight GitHub Repository hinzu: + +```js {9-16} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Dokumentation mit sozialen Links', + social: [ + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { + icon: 'github', + label: 'GitHub', + href: 'https://github.com/withastro/starlight', + }, + ], + }), + ], +}); +``` + +## Bearbeitungslinks + +Starlight kann einen "Seite bearbeiten"-Link in der Fußzeile jeder Seite anzeigen. +Dies macht es dem Leser leicht, die zu bearbeitende Datei zu finden, um deine Dokumentation zu verbessern. +Insbesondere bei Open-Source-Projekten kann dies dazu beitragen, Beiträge aus deiner Community zu fördern. + +Um Edit-Links zu aktivieren, setze [`editLink.baseUrl`](/de/reference/configuration/#editlink) auf die URL, die du zum Bearbeiten deines Repositorys in der Starlight-Integrations­konfiguration verwendest. +Der Wert von `editLink.baseUrl` wird dem Pfad zur aktuellen Seite vorangestellt, um den vollständigen Bearbeitungslink zu bilden. + +Übliche Muster sind: + +- GitHub: `https://github.com/BENUTZERNAME/REPOSITORY_NAME/edit/BRANCH_NAME/` +- GitLab: `https://gitlab.com/BENUTZERNAME/REPOSITORY_NAME/-/edit/BRANCH_NAME/` + +Wenn sich dein Starlight-Projekt nicht im Stammverzeichnis deines Repositorys befindet, füge den Pfad zum Projekt am Ende der Basis-URL ein. + +Dieses Beispiel zeigt den Bearbeitungslink, der für die Starlight-Dokumentation konfiguriert ist, die sich im Unterverzeichnis `docs/` im `main`-Branch des `withastro/starlight`-Repository auf GitHub befinden: + +```js {9-11} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Dokumentation mit Bearbeitungslinks', + editLink: { + baseUrl: 'https://github.com/withastro/starlight/edit/main/docs/', + }, + }), + ], +}); +``` + +## Benutzerdefinierte 404-Seite + +Starlight-Websites zeigen standardmäßig eine einfache 404-Seite an. +Du kannst dies anpassen, indem du eine `404.md` (oder `404.mdx`) Datei zu deinem `src/content/docs/` Verzeichnis hinzufügst: + +<FileTree> + +- src/ + - content/ + - docs/ + - **404.md** + - index.md +- astro.config.mjs + +</FileTree> + +Du kannst alle Seitenlayout- und Anpassungstechniken von Starlight in deiner 404-Seite verwenden. Zum Beispiel verwendet die Standard 404-Seite die [`splash` Vorlage](#seitenlayout) und [`hero`](/de/reference/frontmatter/#hero) Komponente in Frontmatter: + +```md {4,6-8} +--- +# src/content/docs/404.md +title: '404' +template: splash +editUrl: false +hero: + title: '404' + tagline: Seite nicht gefunden. Überprüfe die URL oder versuche es mit der Suchfunktion. +--- +``` + +### Deaktivieren der Standard-404-Seite + +Wenn dein Projekt ein komplett angepasstes 404-Layout benötigt, kannst du eine `src/pages/404.astro`-Route erstellen und die [`disable404Route`](/de/reference/configuration/#disable404route) Konfigurations­option setzen, um die Standard-Route von Starlight zu deaktivieren: + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Dokumentation mit benutzerdefinierten 404', + disable404Route: true, + }), + ], +}); +``` + +## Benutzerdefinierte Schriftarten + +Standardmäßig verwendet Starlight serifenlose Schriften, die auf dem lokalen Gerät des Benutzers verfügbar sind, für den gesamten Text. +Dadurch wird sichergestellt, dass die Dokumentation schnell in einer Schriftart geladen wird, die jedem Benutzer vertraut ist, ohne dass zusätzliche Bandbreite für das Herunterladen großer Schriftdateien benötigt wird. + +Wenn du deiner Starlight-Website eine eigene Schriftart hinzufügen musst, kannst du die Schriftarten in eigenen CSS-Dateien oder mit anderen [Astro-Styling-Techniken](https://docs.astro.build/de/guides/styling/) einrichten. + +### Schriftarten einrichten + +Wenn du bereits über Schriftartdateien verfügst, folge der [Anleitung zum Einrichten lokaler Schriftartdateien](#lokale-schriftartendateien-einrichten). +Um Google Fonts zu verwenden, folge der [Anleitung Fontsource einrichten](#einrichten-einer-fontsource-schriftart). + +#### Lokale Schriftartendateien einrichten + +<Steps> + +1. Füge deine Schriftdateien in ein `src/fonts/`-Verzeichnis ein und erstelle eine leere `font-face.css`-Datei: + + <FileTree> + + - src/ + - content/ + - fonts/ + - **CustomFont.woff2** + - **font-face.css** + - astro.config.mjs + + </FileTree> + +2. Füge eine [`@font-face`-Deklaration](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face) für jede deiner Schriftarten in `src/fonts/font-face.css` ein. + Verwende einen relativen Pfad zu der Schriftartdatei in der Funktion `url()`. + + ```css + /* src/fonts/font-face.css */ + + @font-face { + font-family: 'Custom Font'; + /* Verwende einen relativen Pfad zur lokalen Schriftdatei in `url()`. */ + src: url('./CustomFont.woff2') format('woff2'); + font-weight: normal; + font-style: normal; + font-display: swap; + } + ``` + +3. Füge den Pfad zu deiner `font-face.css`-Datei zu Starlights `customCss`-Array in `astro.config.mjs` hinzu: + + ```diff lang="js" + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Dokumentation mit benutzerdefinierter Schriftart', + customCss: [ + + // Relativer Pfad zu deiner @font-face CSS-Datei. + + './src/fonts/font-face.css', + ], + }), + ], + }); + ``` + +</Steps> + +#### Einrichten einer Fontsource-Schriftart + +Das [Fontsource](https://fontsource.org/) Projekt vereinfacht die Verwendung von Google Fonts und anderen Open-Source-Schriften. +Es bietet npm-Module, die du für die gewünschten Schriftarten installieren kannst, und enthält fertige CSS-Dateien, die du deinem Projekt hinzufügen kannst. + +<Steps> + +1. Suche die Schriftart, die du verwenden möchten, im [Fontsource-Katalog](https://fontsource.org/). + In diesem Beispiel wird [IBM Plex Serif](https://fontsource.org/fonts/ibm-plex-serif) verwendet. + +2. Installiere das Paket für deine gewählte Schriftart. + Du findest den Namen des Pakets, indem du auf der Fontsource-Website auf `Installieren` klickst. + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @fontsource/ibm-plex-serif + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @fontsource/ibm-plex-serif + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @fontsource/ibm-plex-serif + ``` + + </TabItem> + + </Tabs> + +3. Füge die CSS-Dateien von Fontsource zum Array `customCss` von Starlight in `astro.config.mjs` hinzu: + + ```diff lang="js" + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Dokumentation mit benutzerdefinierter Schriftart', + customCss: [ + + // Schriftquelldateien für normale und halbfette Schriftschnitte. + + '@fontsource/ibm-plex-serif/400.css', + + '@fontsource/ibm-plex-serif/600.css', + ], + }), + ], + }); + ``` + + Fontsource liefert mehrere CSS-Dateien für jede Schriftart. Siehe die [Fontsource-Dokumentation](https://fontsource.org/docs/getting-started/install#4-weights-and-styles) über das Einbinden verschiedener Schriftstärken und Styles, um zu verstehen, welche zu verwenden sind. + +</Steps> + +### Schriftarten verwenden + +Um deine eingerichtete Schriftart auf deiner Website anzuwenden, verwende den Namen der gewählten Schriftart in einer [benutzerdefinierten CSS-Datei](/de/guides/css-and-tailwind/#benutzerdefinierte-css-styles-stile). +Um zum Beispiel die Standard-Schriftart von Starlight überall zu überschreiben, setze die benutzerdefinierte Eigenschaft `--sl-font`: + +```css +/* src/styles/custom.css */ + +:root { + --sl-font: 'IBM Plex Serif', serif; +} +``` + +Du kannst auch spezifischeres CSS schreiben, wenn du deine Schriftart selektiver anwenden willst. +Zum Beispiel, um eine Schriftart nur auf den Hauptinhalt zu setzen, aber nicht auf die Seitennavigation: + +```css +/* src/styles/custom.css */ + +main { + font-family: 'IBM Plex Serif', serif; +} +``` + +Folge der [Anleitung für benutzerdefiniertes CSS-Styles](/de/guides/css-and-tailwind/#benutzerdefinierte-css-styles-stile), um deine Styles zu deiner Website hinzuzufügen. diff --git a/docs/src/content/docs/de/guides/i18n.mdx b/docs/src/content/docs/de/guides/i18n.mdx new file mode 100644 index 00000000000..444e20d570d --- /dev/null +++ b/docs/src/content/docs/de/guides/i18n.mdx @@ -0,0 +1,410 @@ +--- +title: Internationalisierung (i18n) +description: Lerne, wie du deine Starlight-Website so konfigurierst, dass sie mehrere Sprachen unterstützt. +--- + +import { FileTree, Steps } from '@astrojs/starlight/components'; + +Starlight bietet eingebaute Unterstützung für mehrsprachige Websites, einschließlich Routing, Fallback-Inhalte und vollständige Unterstützung von rechts-nach-links (RTL) Sprachen. + +## Konfiguriere i18n + +<Steps> + +1. Teile Starlight mit, welche Sprachen du unterstützt, indem du [`locales`](/de/reference/configuration/#locales) und [`defaultLocale`](/de/reference/configuration/#defaultlocale) an die Starlight Integration übergibst: + + ```js {9-26} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Meine Dokumentation', + // Lege Englisch als Standardsprache für diese Website fest. + defaultLocale: 'en', + locales: { + // Englische Dokumentation in `src/content/docs/en/` + en: { + label: 'English', + }, + // Vereinfachte chinesische Dokumentation in `src/content/docs/zh-cn/` + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + // Arabische Dokumentation in `src/content/docs/ar/` + ar: { + label: 'العربية', + dir: 'rtl', + }, + }, + }), + ], + }); + ``` + + Dein `defaultLocale` wird für Fallback-Inhalte und UI-Labels verwendet, wähle also die Sprache, in der du am ehesten mit dem Schreiben von Inhalten beginnen wirst oder für die du bereits Inhalte hast. + +2. Erstelle ein Verzeichnis für jede Sprache in `src/content/docs/`. + Für die oben gezeigte Konfiguration erstellst du zum Beispiel die folgenden Verzeichnisse: + + <FileTree> + + - src/ + - content/ + - docs/ + - ar/ + - en/ + - zh-cn/ + + </FileTree> + +3. Du kannst nun Inhaltsdateien in deinen Sprach­verzeichnissen hinzufügen. Verwende den gleichen Dateinamen, um Seiten in verschiedenen Sprachen zuzuordnen und nutze Starlights volle i18n-Funktionen, einschließlich Fallback-Inhalte, Übersetzungs­hinweise und mehr. + + Erstelle zum Beispiel `ar/index.md` und `en/index.md`, um die Homepage für Arabisch bzw. Englisch darzustellen. + +</Steps> + +Für fortgeschrittene i18n-Szenarien unterstützt Starlight auch die Konfiguration der Internationalisierung mit [Astro's `i18n`-Konfigurations­option](https://docs.astro.build/de/guides/internationalization/#configure-i18n-routing). + +### Verwende ein Root-Verzeichnis + +Du kannst ein Root-Verzeichnis verwenden, um eine Sprache ohne i18n-Präfix in ihrem Pfad anzubieten. Wenn zum Beispiel Englisch dein Stammverzeichnis ist, würde ein englischer Seitenpfad unter `/about` anstelle von `/en/about` zu finden sein. + +Um ein Stammverzeichnis festzulegen, verwende den Key `root` in deiner `locales`-Konfiguration. Wenn das Root-Verzeichnis auch das Standard-Verzeichnis für deinen Inhalt ist, entferne `defaultLocale` oder setze es auf `'root'`. + +```js {9,11-14} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Meine Dokumentation', + defaultLocale: 'root', // optional + locales: { + root: { + label: 'English', + lang: 'en', // lang ist für Stammverzeichnis erforderlich + }, + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + }, + }), + ], +}); +``` + +Wenn du ein `root`-Verzeichnis verwendest, speichere die Seiten für diese Sprache direkt in `src/content/docs/`, anstatt in einem speziellen Sprachordner. Zum Beispiel sind hier die Homepage-Dateien für Englisch und Chinesisch, wenn man die obige Konfiguration verwendet: + +<FileTree> + +- src/ + - content/ + - docs/ + - **index.md** + - zh-cn/ + - **index.md** + +</FileTree> + +#### Einsprachige Websites + +Standardmäßig ist Starlight eine einsprachige (englische) Website. Um eine einsprachige Website in einer anderen Sprache zu erstellen, setze diese als `root` in deiner `locales` Konfiguration: + +```diff lang="js" {10-13} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'My Docs', + locales: { + root: { + label: '简体中文', + lang: 'zh-CN', + }, + }, + }), + ], +}); +``` + +Dies ermöglicht es dir, die Standardsprache von Starlight zu überschreiben, ohne andere Internationalisierungs­funktionen für mehrsprachige Websites zu aktivieren, wie z. B. die Sprachauswahl. + +## Fallback-Inhalt + +Starlight erwartet, dass du äquivalente Seiten in allen deinen Sprachen erstellst. Wenn du zum Beispiel eine `de/about.md` Datei hast, erstelle eine `about.md` für jede andere Sprache, die du unterstützt. Dies ermöglicht Starlight, automatisch Ersatzinhalte für Seiten zu liefern, die noch nicht übersetzt wurden. + +Wenn für eine Sprache noch keine Übersetzung verfügbar ist, zeigt Starlight den Lesern den Inhalt dieser Seite in der Standardsprache (eingestellt über `defaultLocale`). Wenn du z. B. noch keine französische Version deiner "About"-Seite erstellt hast und deine Standardsprache Englisch ist, werden Besucher von `/fr/about` den englischen Inhalt von `/en/about` sehen, mit einem Hinweis, dass diese Seite noch nicht übersetzt wurde. Auf diese Weise kannst du Inhalte in deiner Standardsprache hinzufügen und sie dann nach und nach übersetzen, wenn du Lust dazu hast. + +## Übersetze den Seitentitel + +Standardmäßig verwendet Starlight denselben Titel für alle Sprachen. +Wenn du den Titel für jedes Gebietsschema anpassen möchtest, kannst du in den Optionen von Starlight ein Objekt an [`title`](/de/reference/configuration/#title-erforderlich) übergeben: + +```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' }, + }, + }), + ], +}); +``` + +## Starlights UI übersetzen + +import LanguagesList from '~/components/languages-list.astro'; +import UIStringsList from '~/components/ui-strings-list.astro'; + +Starlight bietet nicht nur übersetzte Inhaltsdateien, sondern auch die Möglichkeit, die Standard-Benutzeroberfläche zu übersetzen (z. B. die Überschrift "Auf dieser Seite" im Inhaltsverzeichnis), so dass deine Leser deine Website vollständig in der ausgewählten Sprache erleben können. + +<LanguagesList startsSentence /> werden standardmäßig übersetzt, und wir freuen +uns über [Beiträge zur Aufnahme weiterer +Standardsprachen](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md). + +Du kannst Übersetzungen für zusätzliche Sprachen, die du unterstützt, über die `i18n` Datensammlung zur Verfügung stellen - oder unsere Standard­bezeichnungen überschreiben. + +<Steps> + +1. Konfiguriere die `i18n` Datensammlung in `src/content.config.ts`, wenn sie nicht bereits konfiguriert ist: + + ```diff lang="js" ins=/, (i18nLoader|i18nSchema)/ + // src/content.config.ts + import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; + import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + + export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), + }; + ``` + +2. Erstelle eine JSON-Datei in `src/content/i18n/` für jedes zusätzliche Gebietsschema, für das du UI-Übersetzungsstrings bereitstellen möchtest. + Dies würde zum Beispiel Übersetzungsdateien für Arabisch und vereinfachtes Chinesisch hinzufügen: + + <FileTree> + + - src/ + - content/ + - i18n/ + - ar.json + - zh-CN.json + + </FileTree> + +3. Füge Übersetzungen für die Schlüssel hinzu, die in den JSON-Dateien übersetzt werden sollen. Übersetze nur die Werte und belasse die Schlüssel auf Englisch (z. B. `"search.label": "Buscar"`). + + Dies sind die englischen Standardwerte der vorhandenen Strings, mit denen Starlight ausgeliefert wird: + + <UIStringsList /> + + Die Codeblöcke von Starlight werden von der [Expressive Code](https://expressive-code.com/) Bibliothek unterstützt. + Du kannst die Übersetzungen für die UI-Strings in derselben JSON-Datei mit Hilfe von `expressiveCode`-Schlüsseln festlegen: + + ```json + { + "expressiveCode.copyButtonCopied": "Copied!", + "expressiveCode.copyButtonTooltip": "Copy to clipboard", + "expressiveCode.terminalWindowFallbackTitle": "Terminal window" + } + ``` + + Die Suchfunktion von Starlight wird von der [Pagefind-Bibliothek](https://pagefind.app/) unterstützt. + Du kannst die Übersetzungen für Pagefinds UI in der gleichen JSON Datei mit `pagefind`-Schlüsseln setzen: + + ```json + { + "pagefind.clear_search": "Clear", + "pagefind.load_more": "Load more results", + "pagefind.search_label": "Search this site", + "pagefind.filters_label": "Filters", + "pagefind.zero_results": "No results for [SEARCH_TERM]", + "pagefind.many_results": "[COUNT] results for [SEARCH_TERM]", + "pagefind.one_result": "[COUNT] result for [SEARCH_TERM]", + "pagefind.alt_search": "No results for [SEARCH_TERM]. Showing results for [DIFFERENT_TERM] instead", + "pagefind.search_suggestion": "No results for [SEARCH_TERM]. Try one of the following searches:", + "pagefind.searching": "Searching for [SEARCH_TERM]..." + } + ``` + +</Steps> + +### Übersetzungsschema erweitern + +Füge benutzerdefinierte Schlüssel zu den Übersetzungs­wörterbüchern deiner Website hinzu, indem du die Option `extend` in den `i18nSchema()`-Optionen setzt. +Im folgenden Beispiel wird ein neuer, optionaler Schlüssel `custom.label` zu den Standardschlüsseln hinzugefügt: + +```diff lang="js" +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ ++ extend: z.object({ ++ 'custom.label': z.string().optional(), ++ }), + }), + }), +}; +``` + +Mehr über Inhaltssammlungs­schemas erfährst du in [„Ein Sammelschema definieren“](https://docs.astro.build/de/guides/content-collections/#defining-the-collection-schema) in der Astro-Dokumentation. + +## UI-Übersetzungen verwenden + +Du kannst auf Starlights [eingebaute UI-Strings](/de/guides/i18n/#starlights-ui-übersetzen) sowie auf [benutzerdefinierte](/de/guides/i18n/#übersetzungsschema-erweitern) und [plugin-provided](/de/reference/plugins/#injecttranslations) UI-Strings über eine einheitliche API zugreifen, die von [i18next](https://www.i18next.com/) unterstützt wird. +Dazu gehört die Unterstützung von Funktionen wie [Interpolation](https://www.i18next.com/translation-function/interpolation) und [Pluralisierung](https://www.i18next.com/translation-function/plurals). + +In Astro-Komponenten ist diese API als Teil des [globalen `Astro`-Objekts](https://docs.astro.build/de/reference/api-reference/#locals) als `Astro.locals.t` verfügbar: + +```astro title="example.astro" +<p dir={Astro.locals.t.dir()}> + {Astro.locals.t('404.text')} +</p> +``` + +Du kannst die API auch bei [Endpunkten](https://docs.astro.build/de/guides/endpoints/) verwenden, wo das Objekt `locals` als Teil des [Endpunkt-Kontextes](https://docs.astro.build/de/reference/api-reference/#locals) verfügbar ist: + +```ts title="src/pages/404.ts" +export const GET = (context) => { + return new Response(context.locals.t('404.text')); +}; +``` + +Im Kontext eines Starlight-Plugins kannst du den Helfer [`useTranslations()`](/de/reference/plugins/#usetranslations) verwenden, um auf diese API für eine bestimmte Sprache zuzugreifen. +Weitere Informationen findest du in der [Plugins Referenz](/de/reference/plugins/). + +### Rendering eines UI-Strings + +Rendere UI-Strings mit der Funktion `locals.t()`. +Dies ist eine Instanz der i18next-Funktion `t()`, die einen UI-String-Schlüssel als erstes Argument nimmt und die entsprechende Übersetzung für die aktuelle Sprache zurückgibt. + +Nehmen wir zum Beispiel eine benutzerdefinierte Übersetzungsdatei mit folgendem Inhalt: + +```json title="src/content/i18n/de.json" +{ + "link.astro": "Astro Dokumentation", + "link.astro.custom": "Astro-Dokumentation für {{feature}}" +} +``` + +Der erste UI-String kann gerendert werden, indem man `'link.astro'` an die Funktion `t()` übergibt: + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/"> + {Astro.locals.t('link.astro')} +</a> +<!-- Rendert: <a href="...">Astro Dokumentation</a> --> +``` + +Der zweite UI-String verwendet die [Interpolations­syntax](https://www.i18next.com/translation-function/interpolation) von i18next für den Platzhalter `{{feature}}`. +Der Wert für `feature` muss in einem Optionsobjekt gesetzt werden, das als zweites Argument an `t()` übergeben wird: + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/en/guides/astro-db/"> + {Astro.locals.t('link.astro.custom', { feature: 'Astro DB' })} +</a> +<!-- Rendert: <a href="...">Astro-Dokumentation für Astro DB</a> --> +``` + +In der [i18next-Dokumentation](https://www.i18next.com/overview/api#t) findest du weitere Informationen darüber, wie du die Funktion `t()` mit Interpolation, Formatierung und mehr verwenden kannst. + +### Fortgeschrittene APIs + +#### `t.all()` + +Die Funktion `locals.t.all()` gibt ein Objekt zurück, das alle für das aktuelle Gebietsschema verfügbaren UI-Strings enthält. + +```astro +--- +// src/components/Example.astro +const allStrings = Astro.locals.t.all(); +// ^ +// { +// "skipLink.label": "Zum Inhalt springen", +// "search.label": "Suche", +// … +// } +--- +``` + +#### `t.exists()` + +Um zu überprüfen, ob ein Übersetzungs­schlüssel existiert, verwende die Funktion `locals.t.exists()` mit dem Übersetzungs­schlüssel als erstem Argument. +Gib ein optionales zweites Argument an, wenn du überprüfen möchtest, ob eine Übersetzung für eine bestimmte Sprache vorhanden ist. + +```astro +--- +// src/components/Example.astro +const keyExists = Astro.locals.t.exists('a.key'); +// ^ true +const keyExistsInFrench = Astro.locals.t.exists('other.key', { lngs: ['fr'] }); +// ^ false +--- +``` + +Siehe [Verweis auf `exists()` in der i18next-Dokumentation](https://www.i18next.com/overview/api#exists) für weitere Informationen. + +#### `t.dir()` + +Die Funktion `locals.t.dir()` gibt die Textrichtung des aktuellen oder eines bestimmten Gebietsschemas zurück. + +```astro +--- +// src/components/Example.astro +const currentDirection = Astro.locals.t.dir(); +// ^ +// 'ltr' +const arabicDirection = Astro.locals.t.dir('ar'); +// ^ +// 'rtl' +--- +``` + +Weitere Informationen findest du in der [`dir()`-Referenz in der i18next-Dokumentation](https://www.i18next.com/overview/api#dir). + +## Zugriff auf das aktuelle Gebietsschema + +Du kannst [`Astro.currentLocale`](https://docs.astro.build/de/reference/api-reference/#currentlocale) verwenden, um das aktuelle Gebietsschema in `.astro` Komponenten zu lesen. + +Das folgende Beispiel liest das aktuelle Gebietsschema aus und verwendet es mit Hilfe der [`getRelativeLocaleUrl()`](https://docs.astro.build/de/reference/modules/astro-i18n/#getrelativelocaleurl)-Methode, um einen Link zu einer Informationsseite in der aktuellen Sprache zu erzeugen: + +```astro +--- +// src/components/AboutLink.astro +import { getRelativeLocaleUrl } from 'astro:i18n'; +--- + +<a href={getRelativeLocaleUrl(Astro.currentLocale ?? 'en', 'about')}>Über uns</a +> +``` diff --git a/docs/src/content/docs/de/guides/overriding-components.mdx b/docs/src/content/docs/de/guides/overriding-components.mdx new file mode 100644 index 00000000000..bb98d07aecd --- /dev/null +++ b/docs/src/content/docs/de/guides/overriding-components.mdx @@ -0,0 +1,152 @@ +--- +title: Komponenten ersetzen +description: In Starlight kannst du eingebauten Komponenten ersetzen, um eigene Elemente in die Benutzeroberfläche deiner Dokumentationswebsite einzufügen. +--- + +import { Steps } from '@astrojs/starlight/components'; + +Starlights Standard-UI und Konfigurations­optionen sind so gestaltet, dass sie flexibel sind und für eine Reihe von Inhalten funktionieren. Ein Großteil des Standardaussehens von Starlight kann mit [CSS](/de/guides/css-and-tailwind/) und [Konfigurations­optionen](/de/guides/customization/) angepasst werden. + +Wenn du mehr brauchst als das, was von Haus aus möglich ist, unterstützt Starlight die Erstellung eigener Komponenten, um die Standardkomponenten zu erweitern oder zu ersetzen. + +## Wann solltest du ersetzen + +Die Standardkomponenten von Starlight zu überschreiben kann nützlich sein, wenn: + +- Du das Aussehen eines Teils der Starlight-Benutzeroberfläche auf eine Weise ändern möchest, was mit [eigenem CSS](/de/guides/css-and-tailwind/) nicht möglich ist. +- Du das Verhalten eines Teils der Starlight-Benutzeroberfläche ändern möchtest. +- Du zusätzliche UI neben Starlights bestehender UI hinzufügen willst. + +## Wie kann man das ersetzen + +<Steps> + +1. Wähle die Starlight-Komponente, die du überschreiben möchtest. + Du kannst eine vollständige Liste der Komponenten in der [Komponenten-Ersetzung Referenz](/de/reference/overrides/) finden. + + :::tip + Du bist dir nicht sicher, welche Komponente du überschreiben musst? Benutze die [interaktive Starlight Overrides Map](https://starlight-overrides-map.netlify.app/), um die Namen von Starlights UI-Komponenten zu erfahren. + ::: + + In diesem Beispiel wird die Starlight-Komponente [`SocialIcons`](/de/reference/overrides/#socialicons) in der Navigationsleiste der Website außer Kraft gesetzt. + +2. Erstelle eine Astro-Komponente, mit der du die Starlight-Komponente ersetzt. + Dieses Beispiel rendert einen Kontakt-Link. + + ```astro + --- + // src/components/EmailLink.astro + + const email = 'houston@example.com'; + --- + + <a href=`mailto:${email}`>Schreib mir</a> + ``` + +3. Sage Starlight, dass deine benutzerdefinierte Komponente in der Konfigurations­option [`components`](/de/reference/configuration/#components) in `astro.config.mjs` verwendet werden soll: + + ```js {9-12} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Meine Dokumentation nutzt eigene Komponenten', + components: { + // Ersetze den Standardkomponent `SocialIcons` + SocialIcons: './src/components/EmailLink.astro', + }, + }), + ], + }); + ``` + +</Steps> + +## Eine integrierte Komponente wiederverwenden + +Du kannst mit den Standard-UI-Komponenten von Starlight genauso arbeiten, wie du es mit deinen eigenen tun würdest: Importieren und Rendern in deinen eigenen benutzerdefinierten Komponenten. Dadurch kannst du die gesamte grundlegende Benutzeroberfläche von Starlight in deinem Design beibehalten und gleichzeitig zusätzliche Benutzeroberflächen hinzufügen. + +Das folgende Beispiel zeigt eine benutzerdefinierte Komponente, die einen E-Mail-Link zusammen mit der Standardkomponente `SocialIcons` rendert: + +```astro {3,7} +--- +// src/components/EmailLink.astro +import Default from '@astrojs/starlight/components/SocialIcons.astro'; +--- + +<a href="mailto:houston@example.com">Schreib mir</a> +<Default><slot /></Default> +``` + +Wenn du eine eingebaute Komponente innerhalb einer benutzerdefinierten Komponente renderst, füge ein [`<slot />`](https://docs.astro.build/de/basics/astro-components/#slots) innerhalb der Standardkomponente hinzu. Dadurch wird sichergestellt, dass Astro weiß, wo die Komponente gerendert werden soll, wenn sie Kindelemente erhält. + +Wenn du die Komponenten [`PageFrame`](/de/reference/overrides/#pageframe) oder [`TwoColumnContent`](/de/reference/overrides/#twocolumncontent) wiederverwendst, die [benannte Slots](https://docs.astro.build/de/basics/astro-components/#benannte-slots) enthalten, musst du auch diese Slots [übertragen](https://docs.astro.build/de/basics/astro-components/#slots-weitergeben). + +Das folgende Beispiel zeigt eine benutzerdefinierte Komponente, die die Komponente `TwoColumnContent` wiederverwendet. Diese integrierte Komponente enthält einen zusätzlichen benannten Slot, nämlich `right-sidebar`, welcher übertragen werden muss: + +```astro {8} +--- +// src/components/CustomContent.astro +import Default from '@astrojs/starlight/components/TwoColumnContent.astro'; +--- + +<Default> + <slot /> + <slot name="right-sidebar" slot="right-sidebar" /> +</Default> +``` + +## Seitendaten verwenden + +Wenn du eine Starlight-Komponente überschreibst, kannst du auf das globale [`starlightRoute`-Objekt](/de/guides/route-data/) zugreifen, das alle Daten für die aktuelle Seite enthält. +Dadurch kannst du diese Werte verwenden, um zu steuern, wie deine Komponentenvorlage gerendert wird. + +Im folgenden Beispiel zeigt eine Ersatzkomponente [`PageTitle`](/de/reference/overrides/#pagetitle) den Titel der aktuellen Seite an, wie er im Frontmatter des Inhalts festgelegt wird: + +```astro {4} "{title}" +--- +// src/components/Title.astro + +const { title } = Astro.locals.starlightRoute.entry.data; +--- + +<h1 id="_top">{title}</h1> + +<style> + h1 { + font-family: 'Comic Sans'; + } +</style> +``` + +Weitere Informationen zu allen verfügbaren Eigenschaften findest du in der [Routendaten-Referenz](/de/reference/route-data/). + +### Nur auf bestimmten Seiten überschreiben + +Komponenten­überschreibungen gelten für alle Seiten. Du kannst jedoch bedingt mit Werten aus `starlightRoute` rendern, um zu bestimmen, wann deine benutzerdefinierte Benutzeroberfläche, wann die Standard­benutzeroberfläche von Starlight oder sogar etwas völlig anderes angezeigt werden soll. + +Im folgenden Beispiel zeigt eine Komponente, die Starlights [`Footer`](/de/reference/overrides/#fußzeile) überschreibt, nur auf der Startseite „Verwendet Starlight 🌟“ an und zeigt ansonsten auf allen anderen Seiten die Standardfußzeile an: + +```astro +--- +// src/components/ConditionalFooter.astro +import Default from '@astrojs/starlight/components/Footer.astro'; + +const isHomepage = Astro.locals.starlightRoute.id === ''; +--- + +{ + isHomepage ? ( + <footer>Verwendet Starlight 🌟</footer> + ) : ( + <Default> + <slot /> + </Default> + ) +} +``` + +Weitere Informationen zum bedingten Rendering findest du im [Astro-Leitfaden zur Vorlagensyntax](https://docs.astro.build/de/basics/astro-syntax/#dynamisches-html). diff --git a/docs/src/content/docs/de/guides/pages.mdx b/docs/src/content/docs/de/guides/pages.mdx new file mode 100644 index 00000000000..ec430da0727 --- /dev/null +++ b/docs/src/content/docs/de/guides/pages.mdx @@ -0,0 +1,233 @@ +--- +title: Seiten +description: Lerne, wie du mit Starlight die Seiten deiner Dokumentationswebsite erstellst und verwaltest. +sidebar: + order: 1 +tableOfContents: + maxHeadingLevel: 4 +--- + +Starlight generiert die HTML-Seiten deiner Website auf der Grundlage deines Inhalts, wobei flexible Optionen über das Markdown-Frontmatter bereitgestellt werden. +Außerdem haben Starlight-Projekte vollen Zugriff auf [Astros leistungsstarke Werkzeuge zur Seitengenerierung](https://docs.astro.build/de/basics/astro-pages/). +Dieser Leitfaden zeigt, wie die Seitenerstellung in Starlight funktioniert. + +## Seiten mit Inhalten + +### Dateiformate + +Starlight unterstützt das Verfassen von Inhalten in Markdown und MDX, ohne dass eine Konfiguration erforderlich ist. +Du kannst die Unterstützung für Markdoc hinzufügen, indem du dem [„Markdoc“ Leitfaden](/de/guides/authoring-content/#markdoc) folgst. + +### Seiten hinzufügen + +Füge neue Seiten zu deiner Website hinzu, indem du `.md` oder `.mdx` Dateien in `src/content/docs/` erstellst. +Verwende Unterordner, um deine Dateien zu organisieren und um mehrere Pfadsegmente zu erstellen. + +Die folgende Dateistruktur erzeugt zum Beispiel Seiten unter `example.com/hello-world` und `example.com/reference/faq`: + +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - reference/ + - faq.md + +</FileTree> + +### Typsicheres Frontmatter + +Alle Starlight-Seiten haben ein anpassbares [gemeinsames Set von Frontmatter-Eigenschaften](/de/reference/frontmatter/), um zu steuern, wie die Seite aussieht: + +```md +--- +title: Hallo, Welt! +description: Dies ist eine Seite in meiner Starlight-Website +--- +``` + +Wenn du etwas Wichtiges vergisst, wird dich Starlight darauf aufmerksam machen. + +## Benutzerdefinierte Seiten + +Für fortgeschrittene Anwendungsfälle kannst du benutzerdefinierte Seiten hinzufügen, indem du ein Verzeichnis `src/pages/` erstellst. +Das Verzeichnis `src/pages/` verwendet [Astros dateibasiertes Routing](https://docs.astro.build/de/basics/astro-pages/#dateibasiertes-routing) und unterstützt neben anderen Seitenformaten auch `.astro`-Dateien. +Das ist hilfreich, wenn du Seiten mit einem völlig eigenen Layout erstellen oder eine Seite aus einer anderen Datenquelle generieren willst. + +In diesem Projekt werden zum Beispiel Markdown-Inhalte in `src/content/docs/` mit Astro- und HTML-Routen in `src/pages/` gemischt: + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - pages/ + - custom.astro + - archived.html + +</FileTree> + +Mehr dazu findest du in der [„Seiten“-Anleitung in der Astro-Dokumentation](https://docs.astro.build/de/basics/astro-pages/). + +### Das Starlight-Design in eigenen Seiten verwenden + +Um das Starlight-Layout in benutzerdefinierten Seiten zu verwenden, umhüllst du deinen Seiteninhalt mit der [Komponente `<StarlightPage />`](#starlightpage-komponente). +Das kann hilfreich sein, wenn du Inhalte dynamisch generierst, aber trotzdem das Starlight-Design verwenden willst. + +Um Ankerlinks zu Überschriften hinzuzufügen, die den Markdown-Ankerlinkstilen von Starlight entsprechen, kannst du die [`<AnchorHeading>`-Komponente](#anchorheading-komponente) in deinen eigenen Seiten verwenden. + +```astro +--- +// src/pages/custom-page/example.astro +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +import CustomComponent from './CustomComponent.astro'; +--- + +<StarlightPage frontmatter={{ title: 'Meine eigene Seite' }}> + <p> + Dies ist eine benutzerdefinierte Seite mit einer benutzerdefinierten + Komponente: + </p> + <CustomComponent /> + + <AnchorHeading level="2" id="erfahre-menr">Erfahre mehr</AnchorHeading> + <p> + <a href="https://starlight.astro.build/"> + Lies mehr in der Starlight-Dokumentation + </a> + </p> +</StarlightPage> +``` + +#### `<StarlightPage>`-Komponente + +Die Komponente `<StarlightPage />` rendert eine ganze Seite mit dem Layout und den Stilen von Starlight. + +```astro +--- +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +--- + +<StarlightPage frontmatter={{ title: 'Meine eigene Seite' }}> + <!-- Benutzerdefinierter Seiteninhalt --> +</StarlightPage> +``` + +Die Komponente `<StarlightPage />` akzeptiert die folgenden Eigenschaften. + +##### `frontmatter` + +**erforderlich** +**Typ:** `StarlightPageFrontmatter` + +Setzt die [Frontmatter Eigenschaften](/de/reference/frontmatter/) für diese Seite, ähnlich wie Frontmatter in Markdown-Seiten. +Die Eigenschaft [`title`](/de/reference/frontmatter/#title-erforderlich) ist erforderlich und alle anderen Eigenschaften sind optional. + +Die folgenden Eigenschaften unterscheiden sich von Markdown frontmatter: + +- Die Eigenschaft [`slug`](/de/reference/frontmatter/#slug) wird nicht unterstützt und wird automatisch anhand der URL der benutzerdefinierten Seite gesetzt. +- Die Option [`editUrl`](/de/reference/frontmatter/#editurl) erfordert eine URL, um einen Bearbeitungslink anzuzeigen. +- Die Frontmatter-Eigenschaft [`sidebar`](/de/reference/frontmatter/#sidebar), mit der du festlegen kannst, wie die Seite in [autogenerierten Linkgruppen](/de/reference/configuration/#sidebar) erscheint, ist nicht verfügbar. Seiten, die die Komponente `<StarlightPage />` verwenden, sind nicht Teil einer Sammlung und können nicht zu einer automatisch generierten Seitenleistengruppe hinzugefügt werden. +- Die Option [`draft`](/de/reference/frontmatter/#draft) zeigt nur einen [Hinweis](/de/reference/overrides/#draftcontentnotice) an, dass die Seite ein Entwurf ist, schließt sie aber nicht automatisch von der Produktion aus. + +##### `sidebar` + +**Typ:** [`SidebarItem[]`](/de/reference/configuration/#sidebaritem) +**Standard:** die Seitenleiste, die auf der Grundlage der [globalen `Sidebar`-Konfiguration](/de/reference/configuration/#sidebar) erzeugt wird + +Legt eine benutzerdefinierte Navigationsleiste für diese Seite fest. +Wenn sie nicht gesetzt wird, verwendet die Seite die globale Standard-Seitenleiste. + +Die folgende Seite ersetzt zum Beispiel die Standard-Seitenleiste durch einen Link zur Homepage und eine Gruppe von Links zu verschiedenen anderen benutzerdefinierten Seiten. + +```astro {3-13} +<StarlightPage + frontmatter={{ title: 'Orion' }} + sidebar={[ + { label: 'Home', link: '/' }, + { + label: 'Constellations', + items: [ + { label: 'Andromeda', link: '/andromeda/' }, + { label: 'Orion', link: '/orion/' }, + { label: 'Ursa Minor', link: '/ursa-minor/', badge: 'Platzhalter' }, + ], + }, + ]} +> + Beispiel-Inhalt. +</StarlightPage> +``` + +In der Anleitung [„Seitenleisten-Navigation“](/de/guides/sidebar/) erfährst du mehr über die verfügbaren Optionen zum Anpassen der Seitenleiste. + +##### `hasSidebar` + +**Typ:** `boolean` +**Standard:** `false` wenn [`frontmatter.template`](/de/reference/frontmatter/#template) `'splash'` ist, sonst `true` + +Legt fest, ob die Seitenleiste auf dieser Seite angezeigt werden soll oder nicht. + +##### `headings` + +**Typ:** `{ depth: number; slug: string; text: string }[]` +**Standard:** `[]` + +Gib ein Array mit allen Überschriften auf dieser Seite an. +Starlight wird das Inhaltsverzeichnis der Seite aus diesen Überschriften generieren, wenn sie angegeben sind. + +##### `dir` + +**Typ:** `'ltr' | 'rtl'` +**Standard:** die Schreibrichtung für das aktuelle Gebietsschema + +Legt die Schreibrichtung für den Inhalt dieser Seite fest. + +##### `lang` + +**Typ:** `String` +**Standard:** die Sprache des aktuellen Gebietsschemas + +Setzt das BCP-47 Sprach-Tag für den Inhalt dieser Seite, z. B. `en`, `zh-CN` oder `pt-BR`. + +##### `isFallback` + +**Typ:** `boolean` +**Standard:** `false` + +Gibt an, ob diese Seite [Fallback-Inhalt](/de/guides/i18n/#fallback-inhalt) verwendet, weil es für die aktuelle Sprache keine Übersetzung gibt. + +#### `<AnchorHeading>`-Komponente + +Die Komponente `<AnchorHeading />` rendert ein HTML-Überschriftenelement mit einem klickbaren Anker-Link, der den Markdown-Styles von Starlight entspricht. + +```astro +--- +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +--- + +<AnchorHeading level="2" id="unterüberschrift">Unterüberschrift</AnchorHeading> +``` + +Sie akzeptiert die folgenden Requisiten sowie alle anderen gültigen [globalen HTML-Attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes). + +##### `level` + +**erforderlich** +**Typ:** `1 | 2 | 3 | 4 | 5 | 6` + +Die zu rendernde Überschriftsebene. +Zum Beispiel würde `level="1"` ein `<h1>`-Element darstellen. + +##### `id` + +**erforderlich** +**Typ:** `string` + +Die eindeutige ID für diese Überschrift. +Dieser wird als `id`-Attribut der gerenderten Überschrift verwendet und das Ankersymbol verlinkt darauf. diff --git a/docs/src/content/docs/de/guides/project-structure.mdx b/docs/src/content/docs/de/guides/project-structure.mdx new file mode 100644 index 00000000000..b10e44a470a --- /dev/null +++ b/docs/src/content/docs/de/guides/project-structure.mdx @@ -0,0 +1,47 @@ +--- +title: Projektstruktur +description: Lerne, wie du Dateien in deinem Starlight-Projekt organisierst. +--- + +Diese Anleitung zeigt dir, wie ein Starlight-Projekt organisiert ist und was die verschiedenen Dateien in deinem Projekt tun. + +Starlight-Projekte folgen im Allgemeinen der gleichen Datei- und Verzeichnisstruktur wie andere Astro-Projekte. Siehe [Astros Dokumentation zur Projektstruktur](https://docs.astro.build/de/basics/project-structure/) für weitere Details. + +## Dateien und Verzeichnisse + +- `astro.config.mjs` - Die Astro-Konfigurationsdatei; enthält die Starlight-Integration und -Konfiguration. +- `src/content.config.ts` - Konfigurationsdatei für Inhaltssammlungen; fügt Starlights Frontmatter-Schema zu deinem Projekt hinzu. +- `src/content/docs/` - Inhaltsdateien. Starlight verwandelt jede `.md`, `.mdx` oder `.mdoc` Datei in diesem Verzeichnis in eine Seite auf deiner Website. +- `src/content/i18n/` (optional) - Übersetzungsdaten zur Unterstützung der [Internationalisierung](/de/guides/i18n/). +- `src/` - Anderer Quellcode und Dateien (Komponenten, Stile, Bilder, etc.) für dein Projekt. +- `public/` - Statische Assets (Schriftarten, Favicon, PDFs, etc.), die nicht von Astro verarbeitet werden. + +## Beispielhafte Projektinhalte + +Ein Starlight-Projektverzeichnis könnte wie folgt aussehen: + +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- public/ + - favicon.svg +- src/ + - assets/ + - logo.svg + - screenshot.jpg + - components/ + - CustomButton.astro + - InteractiveWidget.jsx + - content/ + - docs/ + - guides/ + - 01-getting-started.md + - 02-advanced.md + - index.mdx + - content.config.ts +- astro.config.mjs +- package.json +- tsconfig.json + +</FileTree> diff --git a/docs/src/content/docs/de/guides/route-data.mdx b/docs/src/content/docs/de/guides/route-data.mdx new file mode 100644 index 00000000000..f723db98ada --- /dev/null +++ b/docs/src/content/docs/de/guides/route-data.mdx @@ -0,0 +1,139 @@ +--- +title: Routendaten +description: Erfahre, wie das Seitendatenmodell von Starlight zum Rendern deiner Seiten verwendet wird und wie du es anpassen kannst. +--- + +import { Steps } from '@astrojs/starlight/components'; + +Wenn Starlight eine Seite in deiner Dokumentation rendert, erstellt es zunächst ein Routendatenobjekt, das den Inhalt der Seite darstellt. +In diesem Leitfaden wird erklärt, wie Routendaten erzeugt werden, wie du sie verwendest und wie du sie anpassen kannst, um das Standardverhalten von Starlight zu ändern. + +Eine vollständige Liste der verfügbaren Eigenschaften findest du in der [„Routendaten-Referenz“](/de/reference/route-data/). + +## Was sind Routendaten? + +Starlight-Routendaten sind in einem Objekt enthalten, welches alle Informationen enthält, die zum Rendern einer einzelnen Seite benötigt werden. +Es enthält Informationen für die aktuelle Seite sowie Daten, die aus deiner Starlight-Konfiguration generiert werden. + +## Routendaten verwenden + +Alle Starlight-Komponenten verwenden Routendaten, um zu entscheiden, was für jede Seite gerendert werden soll. +Zum Beispiel wird die Zeichenkette [`siteTitle`](/de/reference/route-data/#sitetitle) verwendet, um den Titel der Seite anzuzeigen, und das Array [`sidebar`](/de/reference/route-data/#sidebar) wird verwendet, um die globale Navigation der Seitenleiste darzustellen. + +Du kannst auf diese Daten über das Global `Astro.locals.starlightRoute` in Astro-Komponenten zugreifen: + +```astro title="example.astro" {2} +--- +const { siteTitle } = Astro.locals.starlightRoute; +--- + +<p>Der Titel dieser Seite lautet „{siteTitle}“</p> +``` + +Das kann zum Beispiel nützlich sein, wenn du [Komponenten­überschreibungen](/de/guides/overriding-components/) erstellst, um die Anzeige anzupassen. + +## Anpassen der Routendaten + +Starlights Routendaten funktionieren sofort und müssen nicht konfiguriert werden. +Für fortgeschrittene Anwendungsfälle möchtest du jedoch vielleicht die Routendaten für einige oder alle Seiten anpassen, um die Darstellung deiner Website zu verändern. + +Das ist ein ähnliches Konzept wie die [Komponenten­ersetzung](/de/guides/overriding-components/), aber anstatt zu ändern, wie Starlight deine Daten rendert, änderst du die Daten, die Starlight rendert. + +### Wann du die Routendaten anpassen solltest + +Das Anpassen von Routendaten kann nützlich sein, wenn du die Art und Weise, wie Starlight deine Daten verarbeitet, auf eine Weise ändern möchtest, die mit den bestehenden Konfigurations­optionen nicht möglich ist. + +Du kannst zum Beispiel die Elemente in der Seitenleiste filtern oder die Titel für bestimmte Seiten anpassen. +Bei Änderungen wie dieser müssen die Standardkomponenten von Starlight nicht geändert werden, sondern nur die Daten, die an diese Komponenten übergeben werden. + +### Wie du die Routendaten anpasst + +Du kannst die Routendaten mithilfe einer speziellen Form von „Middleware“ anpassen. +Dies ist eine Funktion, die jedes Mal aufgerufen wird, wenn Starlight eine Seite rendert, und die Werte im Routendatenobjekt ändern kann. + +<Steps> + +1. Erstelle eine neue Datei, die eine `onRequest`-Funktion mit Starlights `defineRouteMiddleware()`-Dienstprogramm exportiert: + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware(() => {}); + ``` + +2. Teile Starlight in der Datei `astro.config.mjs` mit, wo sich deine Routendaten-Middleware-Datei befindet: + + ```js ins={9} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Meine wunderbare Dokumentationswebsite', + routeMiddleware: './src/routeData.ts', + }), + ], + }); + ``` + +3. Aktualisiere deine `onRequest`-Funktion, um die Routendaten zu ändern. + + Das erste Argument, das deine Middleware erhält, ist [Astros `context`-Objekt](https://docs.astro.build/de/reference/api-reference/). + Es enthält alle Informationen über die aktuell gerenderte Seite, einschließlich der aktuellen URL und `locals`. + + In diesem Beispiel werden wir unsere Dokumentation spannender machen, indem wir ein Ausrufezeichen am Ende jedes Seitentitels hinzufügen. + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware((context) => { + // Hol dir den Eintrag der Inhaltssammlung für diese Seite. + const { entry } = context.locals.starlightRoute; + // Aktualisiere den Titel, um ein Ausrufezeichen hinzuzufügen. + entry.data.title = entry.data.title + '!'; + }); + ``` + +</Steps> + +#### Mehrere Routen-Middleware + +Starlight unterstützt auch die Bereitstellung mehrerer Middlewares. +Setze `routeMiddleware` auf ein Array von Pfaden, um mehr als einen Middleware-Handler hinzuzufügen: + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Meine Website mit mehreren Middlewares', + routeMiddleware: ['./src/middleware-one.ts', './src/middleware-two.ts'], + }), + ], +}); +``` + +#### Warten auf spätere Routen-Middleware + +Um darauf zu warten, dass die Middleware später im Stapel ausgeführt wird, bevor du deinen Code ausführst, kannst du den `next()` Callback abwarten, der als zweites Argument an deine Middleware-Funktion übergeben wird. +Das kann z. B. nützlich sein, um zu warten, bis die Middleware eines Plugins läuft, bevor du Änderungen vornimmst. + +```ts "next" "await next();" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware(async (context, next) => { + // Warte darauf, dass die spätere Middleware ausgeführt wird. + await next(); + // Ändere die Routendaten. + const { entry } = context.locals.starlightRoute; + entry.data.title = entry.data.title + '!'; +}); +``` diff --git a/docs/src/content/docs/de/guides/sidebar.mdx b/docs/src/content/docs/de/guides/sidebar.mdx new file mode 100644 index 00000000000..1454595ee90 --- /dev/null +++ b/docs/src/content/docs/de/guides/sidebar.mdx @@ -0,0 +1,745 @@ +--- +title: Seitenleisten-Navigation +description: Erfahre, wie du die Navigationslinks in der Seitenleiste deiner Starlight-Website einrichten und anpassen kannst. +--- + +import { FileTree } from '@astrojs/starlight/components'; +import SidebarPreview from '~/components/sidebar-preview.astro'; + +Eine gut organisierte Seitenleiste ist der Schlüssel zu einer guten Dokumentation, da sie eine der Hauptwege ist, auf denen die Benutzer durch deine Website navigieren werden. Starlight bietet eine ganze Reihe von Optionen, um das Layout und den Inhalt der Seitenleiste anzupassen. + +## Standard-Seitenleiste + +Standardmäßig erzeugt Starlight automatisch eine Seitenleiste, die auf der Dateistruktur deiner Dokumentation basiert und die Eigenschaft `title` jeder Datei als Seitenleisten­eintrag verwendet. + +Zum Beispiel wird mit der folgenden Datenstruktur: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - andromeda.md + - orion.md + - stars/ + - betelgeuse.md + +</FileTree> + +Die folgende Seitenleiste automatisch generiert: + +<SidebarPreview + config={[ + { + label: 'constellations', + items: [ + { label: 'Andromeda', link: '' }, + { label: 'Orion', link: '' }, + ], + }, + { + label: 'stars', + items: [{ label: 'Beteigeuze', link: '' }], + }, + ]} +/> + +Erfahre mehr über autogenerierte Seitenleisten im Abschnitt [autogenerierte Gruppen](#automatisch-generierte-gruppen). + +## Links und Linkgruppen hinzufügen + +Um deiner Seitenleiste Links und Gruppen von Links (innerhalb einer einklappbaren Kopfzeile) zu konfigurieren, verwende die Eigenschaft [`starlight.sidebar`](/de/reference/configuration/#sidebar) in `astro.config.mjs`. + +Durch die Kombination von Links und Gruppen kannst du eine Vielzahl von Seitenleisten­layouts erstellen. + +### Interne Links + +Füge einen Link zu einer Seite in `src/content/docs/` mit Hilfe eines Objekts mit der Eigenschaft `slug` hinzu. +Der Titel der verlinkten Seite wird standardmäßig als Bezeichnung verwendet. + +Zum Beispiel wird mit der folgenden Konfiguration: + +```js "slug:" +starlight({ + sidebar: [ + { slug: 'constellations/andromeda' }, + { slug: 'constellations/orion' }, + ], +}); +``` + +Und der folgende Dateistruktur: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - andromeda.md + - orion.md + +</FileTree> + +Die folgende Seitenleiste erstellt: + +<SidebarPreview + config={[ + { label: 'Andromeda', link: '' }, + { label: 'Orion', link: '' }, + ]} +/> + +Um die Werte zu überschreiben, die aus dem Frontmatter einer verlinkten Seite abgeleitet werden, kannst du die Eigenschaften `label`, [`translations`](#internationalisierung) und [`attrs`](#benutzerdefinierte-html-attribute) hinzufügen. + +Unter [„Anpassen von automatisch generierten Links“](#autogenerierte-links-im-frontmatter-anpassen) findest du weitere Informationen über die Steuerung des Erscheinungsbildes der Seitenleiste über das Frontmatter der Seite. + +#### Kürzel für interne Links + +Interne Links können auch angegeben werden, indem nur ein String für den Slug der Seite als Kurzform angegeben wird. + +Die folgende Konfiguration entspricht zum Beispiel der obigen Konfiguration, die `slug` verwendet: + +```js +starlight({ + sidebar: ['constellations/andromeda', 'constellations/orion'], +}); +``` + +### Andere Links + +Füge einen Link zu einer externen oder Nicht-Dokumentations-Seite hinzu, indem du ein Objekt mit den Eigenschaften `label` und `link` verwendest. + +```js "label:" "link:" +starlight({ + sidebar: [ + // Ein Link zu einer Nicht-Dokumentations-Seite auf dieser Website. + { label: 'Meteor-Laden', link: '/laden/' }, + // Ein externer Link zur NASA-Website. + { label: 'NASA', link: 'https://www.nasa.gov/' }, + ], +}); +``` + +Die obige Konfiguration erzeugt die folgende Seitenleiste: + +<SidebarPreview + config={[ + { label: 'Meteor-Laden', link: '' }, + { label: 'NASA', link: 'https://www.nasa.gov/' }, + ]} +/> + +### Gruppen + +Du kannst deine Seitenleiste strukturieren, indem du zusammengehörige Links unter einer zusammenklappbaren Überschrift gruppierst. +Gruppen können sowohl Links als auch andere Untergruppen enthalten. + +Füge eine Gruppe mit einem Objekt mit den Eigenschaften `label` und `items` hinzu. +Das `label` wird als Überschrift für die Gruppe verwendet. +Füge Links oder Untergruppen zu dem `items` Array hinzu. + +```js /^\s*(label:|items:)/ +starlight({ + sidebar: [ + // Eine Gruppe von Links mit der Bezeichnung 'Konstellationen'. + { + label: 'Konstellationen', + items: [ + 'constellations/carina', + 'constellations/centaurus', + // Eine verschachtelte Gruppe von Links für saisonale Konstellationen. + { + label: 'Saisonale', + items: [ + 'constellations/andromeda', + 'constellations/orion', + 'constellations/ursa-minor', + ], + }, + ], + }, + ], +}); +``` + +Die obige Konfiguration erzeugt die folgende Seitenleiste: + +<SidebarPreview + config={[ + { + label: 'Konstellationen', + items: [ + { label: 'Kiel des Schiffes', link: '' }, + { label: 'Zentaur', link: '' }, + { + label: 'Saisonale', + items: [ + { label: 'Andromeda', link: '' }, + { label: 'Orion', link: '' }, + { label: 'Kleiner Bär', link: '' }, + ], + }, + ], + }, + ]} +/> + +### Automatisch generierte Gruppen + +Starlight kann automatisch eine Gruppe in deiner Seitenleiste erzeugen, die auf einem Verzeichnis deiner Dokumente basiert. +Dies ist hilfreich, wenn du nicht jedes Element der Seitenleiste manuell in eine Gruppe eintragen willst. + +Standardmäßig werden die Seiten in alphabetischer Reihenfolge nach der Datei [`slug`](/de/reference/route-data/#slug) sortiert. + +Füge eine automatisch generierte Gruppe hinzu, indem du ein Objekt mit den Eigenschaften `label` und `autogenerate` verwendest. In der Konfiguration von `autogenerate` muss das `directory` angegeben werden, das für die Einträge in der Seitenleiste verwendet werden soll. + +Zum Beispiel wird mit der folgenden Konfiguration: + +```js "label:" "autogenerate:" +starlight({ + sidebar: [ + { + label: 'Konstellationen', + // Automatisches Erzeugen einer Gruppe von Links für das Verzeichnis 'constellations'. + autogenerate: { directory: 'constellations' }, + }, + ], +}); +``` + +Und der folgende Dateistruktur: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - carina.md + - centaurus.md + - seasonal/ + - andromeda.md + +</FileTree> + +Die folgende Seitenleiste erzeugt: + +<SidebarPreview + config={[ + { + label: 'Konstellationen', + items: [ + { label: 'Kiel des Schiffes', link: '' }, + { label: 'Zentaur', link: '' }, + { + label: 'seasonal', + items: [{ label: 'Andromeda', link: '' }], + }, + ], + }, + ]} +/> + +## Autogenerierte Links im Frontmatter anpassen + +Verwende das [`sidebar`-Frontmatter-Feld](/de/reference/frontmatter/#sidebar) in einzelnen Seiten, um automatisch generierte Links anzupassen. + +Mit den Frontmatter-Optionen in der Seitenleiste kannst du eine [benutzerdefinierte Bezeichnung](/de/reference/frontmatter/#label) festlegen, [benutzerdefinierte Attribute](/de/reference/frontmatter/#attrs) verwenden, ein [Abzeichen](/de/reference/frontmatter/#badge) zu einem Link hinzufügen, einen Link aus der Seitenleiste [verstecken](/de/reference/frontmatter/#hidden) oder eine [eigene Reihenfolge](/de/reference/frontmatter/#order) definieren. + +```md "sidebar:" +--- +# src/content/docs/example.md +title: Meine Seite +sidebar: + # Setzt eine eigene Beschriftung für den Link + label: Benutzerdefinierte Seitenleistenbeschriftung + # Legen du eine benutzerdefinierte Reihenfolge für den Link fest (niedrigere Zahlen werden weiter oben angezeigt) + order: 2 + # Fügen du dem Link ein Abzeichen hinzu + badge: + text: Neu + variant: tip +--- +``` + +Eine autogenerierte Gruppe, die eine Seite mit dem obigen Frontmatter enthält, erzeugt die folgende Seitenleiste: + +<SidebarPreview + config={[ + { + label: 'Anleitungen', + items: [ + { label: 'Eine Seite', link: '' }, + { + label: 'Benutzerdefinierte Seitenleistenbeschriftung', + link: '', + badge: { text: 'Neu', variant: 'tip' }, + }, + { label: 'Andere Seite', link: '' }, + ], + }, + ]} +/> + +:::note[Anmerkung] +Die `sidebar` Frontmatter-Konfiguration wird nur für Links in automatisch generierten Gruppen und für Dokumentations-Links verwendet, die mit der Eigenschaft `slug` definiert wurden. Sie gilt nicht für Links, die mit der Eigenschaft `link` definiert wurden. +::: + +## Abzeichen + +Links, Gruppen und automatisch generierte Gruppen können auch eine `badge`-Eigenschaft enthalten, um ein Abzeichen neben dem jeweiligen Text anzuzeigen. + +```js {9,16} +starlight({ + sidebar: [ + { + label: 'Sterne', + items: [ + //Ein Link mit einem "Überriese"-Abzeichen. + { + slug: 'stars/persei', + badge: 'Überriese', + }, + ], + }, + // Eine automatisch generierte Gruppe mit dem "Veraltet"-Abzeichen. + { + label: 'Monde', + badge: 'Veraltet', + autogenerate: { directory: 'moons' }, + }, + ], +}); +``` + +Die obige Konfiguration erzeugt die folgende Seitenleiste: + +<SidebarPreview + config={[ + { + label: 'Sterne', + items: [ + { + label: 'Persei', + link: '', + badge: { text: 'Überriese', variant: 'default' }, + }, + ], + }, + { + label: 'Monde', + badge: { text: 'Veraltet', variant: 'default' }, + items: [ + { + label: 'Io', + link: '', + }, + { + label: 'Europa', + link: '', + }, + { + label: 'Ganymed', + link: '', + }, + ], + }, + ]} +/> + +### Abzeichenvarianten + +Passe das Design des Abzeichens mit einem Objekt mit den Eigenschaften `text`, `variant` und `class` an. + +Der `text` steht für den anzuzeigenden Inhalt (z. B. "Neu"). +Überschreibe das `default`-Styling, das die Akzentfarbe deiner Website verwendet, indem du die Eigenschaft `variant` auf einen der folgenden Werte setzt: `note`, `tip`, `danger`, `caution` oder `success`. + +Optional kannst du einen benutzerdefinierten Abzeichenstil erstellen, indem du die Eigenschaft `class` auf einen CSS-Klassennamen setzt. + +```js {9} +starlight({ + sidebar: [ + { + label: 'Sterne', + items: [ + // Ein Link mit einem gelben „Platzhalter“-Abzeichen. + { + slug: 'stars/sirius', + badge: { text: 'Platzhalter', variant: 'caution' }, + }, + ], + }, + ], +}); +``` + +Die obige Konfiguration erzeugt die folgende Seitenleiste: + +<SidebarPreview + config={[ + { + label: 'Sterne', + items: [ + { + label: 'Sirius', + link: '', + badge: { text: 'Platzhalter', variant: 'caution' }, + }, + ], + }, + ]} +/> + +Erfahre mehr über [Verwendung und Anpassung von Badges](/de/components/badges/#verwendung). + +## Benutzerdefinierte HTML-Attribute + +Links können auch eine Eigenschaft `attrs` enthalten, um dem Link-Element benutzerdefinierte HTML-Attribute hinzuzufügen. + +Im folgenden Beispiel wird `attrs` verwendet, um ein `target="_blank"`-Attribut hinzuzufügen, so dass der Link in einem neuen Tab geöffnet wird, und um ein benutzerdefiniertes `style`-Attribut anzuwenden, um die Linkbeschriftung kursiv zu machen: + +```js {10} +starlight({ + sidebar: [ + { + label: 'Ressourcen', + items: [ + // Ein externer Link zur NASA-Website, der in einem neuen Tab geöffnet wird. + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { target: '_blank', style: 'font-style: italic' }, + }, + ], + }, + ], +}); +``` + +Die obige Konfiguration erzeugt die folgende Seitenleiste: + +<SidebarPreview + config={[ + { + label: 'Ressourcen', + items: [ + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { + target: '_blank', + style: 'font-style: italic', + }, + }, + ], + }, + ]} +/> + +### Benutzerdefinierte HTML-Attribute für automatisch generierte Links + +Du kannst die HTML-Attribute aller Links in [automatisch generierten Gruppen](#automatisch-generierte-gruppen) anpassen, indem du die Eigenschaft `attrs` in der Konfiguration `autogenerate` festlegst. +Einzelne Seiten können eigene Attribute über das [`sidebar.attrs`-Frontmatter-Feld](/de/reference/frontmatter/#attrs) festlegen, welches mit der `autogenerate.attrs`-Konfiguration zusammengeführt wird. + +Zum Beispiel wird mit der folgenden Konfiguration: + +```js {10} +starlight({ + sidebar: [ + { + label: 'Konstellationen', + autogenerate: { + // Erstelle automatisch eine Gruppe von Links + // für das Verzeichnis 'constellations'. + directory: 'constellations', + // Alle Link-Bezeichnungen in dieser Gruppe kursiv darstellen. + attrs: { style: 'font-style: italic' }, + }, + }, + ], +}); +``` + +Und der folgenden Dateistruktur: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - carina.md + - centaurus.md + - seasonal/ + - andromeda.md + +</FileTree> + +Die folgende Seitenleiste mit allen automatisch generierten Links in Kursivschrift erstellt: + +<SidebarPreview + config={[ + { + label: 'Konstellationen', + items: [ + { + label: 'Kiel des Schiffes', + link: '', + attrs: { style: 'font-style: italic' }, + }, + { + label: 'Zentaur', + link: '', + attrs: { style: 'font-style: italic' }, + }, + { + label: 'seasonal', + items: [ + { + label: 'Andromeda', + link: '', + attrs: { style: 'font-style: italic' }, + }, + ], + }, + ], + }, + ]} +/> + +## Internationalisierung + +Verwende die Eigenschaft `translations` für Link- und Gruppeneinträge, um die Link- oder Gruppenbeschriftung für jede unterstützte Sprache zu übersetzen, indem du ein [BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags) Sprach-Tag, z. B. `"en"`, `"ar"`, oder `"zh-CN"`, als Schlüssel und die übersetzte Beschriftung als Wert angibst. +Die Eigenschaft `label` wird für das Standard­gebietsschema und für Sprachen ohne Übersetzung verwendet. + +```js {5-7,11-13,18-20} +starlight({ + sidebar: [ + { + label: 'Konstellationen', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { + label: 'Andromeda', + translations: { + 'pt-BR': 'Andrômeda', + }, + slug: 'constellations/andromeda', + }, + { + label: 'Skorpion', + translations: { + 'pt-BR': 'Escorpião', + }, + slug: 'constellations/scorpius', + }, + ], + }, + ], +}); +``` + +Wenn du die Dokumentation in brasilianischem Portugiesisch durchsuchst, wird die folgende Seitenleiste angezeigt: + +<SidebarPreview + config={[ + { + label: 'Constelação', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +### Internationalisierung mit internen Links + +[Interne Links](#interne-links) verwenden standardmäßig automatisch übersetzte Seitentitel aus dem Frontmatter des Inhalts: + +```js {9-10} +starlight({ + sidebar: [ + { + label: 'Konstellationen', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { slug: 'constellations/andromeda' }, + { slug: 'constellations/scorpius' }, + ], + }, + ], +}); +``` + +Wenn du die Dokumentation auf brasilianisches Portugiesisch durchsuchst, wird die folgende Seitenleiste angezeigt: + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +Bei mehrsprachigen Websites enthält der Wert von `slug` nicht den sprachlichen Teil der URL. +Wenn du zum Beispiel Seiten unter `en/intro` und `pt-br/intro` hast, ist der Slug `intro`, wenn du die Seitenleiste konfigurierst. + +### Internationalisierung mit Badges + +Für [Abzeichen](#abzeichen) kann die Eigenschaft `text` ein String sein oder für mehrsprachige Seiten ein Objekt mit Werten für jedes unterschiedliche Gebietsschema. +Wenn du die Objektform verwendest, müssen die Schlüssel [BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags) Tags sein (z. B. `en`, `ar` oder `zh-CN`): + +```js {11-16} +starlight({ + sidebar: [ + { + label: 'Konstellationen', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { + slug: 'constellations/andromeda', + badge: { + text: { + de: 'Neu', + 'pt-BR': 'Novo', + }, + }, + }, + ], + }, + ], +}); +``` + +Wenn du die Dokumentation auf brasilianisches Portugiesisch durchsuchst, wird die folgende Seitenleiste angezeigt: + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { + label: 'Andrômeda', + link: '', + badge: { text: 'Novo', variant: 'default' }, + }, + ], + }, + ]} +/> + +## Zusammenklappen von Gruppen + +Gruppen von Links können standardmäßig eingeklappt werden, indem man die Eigenschaft `collapsed` auf `true` setzt. + +```js {5-6} +starlight({ + sidebar: [ + { + label: 'Konstellationen', + // Schließe die Gruppe standardmäßig. + collapsed: true, + items: ['constellations/andromeda', 'constellations/orion'], + }, + ], +}); +``` + +Die obige Konfiguration erzeugt die folgende Seitenleiste: + +<SidebarPreview + config={[ + { + label: 'Konstellationen', + collapsed: true, + items: [ + { label: 'Andromeda', link: '' }, + { label: 'Orion', link: '' }, + ], + }, + ]} +/> + +[Autogenerierte Gruppen](#automatisch-generierte-gruppen) respektieren den `collapsed` Wert ihrer Elterngruppe: + +```js {5-7} +starlight({ + sidebar: [ + { + label: 'Konstellationen', + // Die Gruppe und ihre automatisch generierte + // Untergruppen standardmäßig einklappen. + collapsed: true, + autogenerate: { directory: 'constellations' }, + }, + ], +}); +``` + +Die obige Konfiguration erzeugt die folgende Seitenleiste: + +<SidebarPreview + config={[ + { + label: 'Konstellationen', + collapsed: true, + items: [ + { label: 'Kiel des Schiffes', link: '' }, + { label: 'Zentaur', link: '' }, + { + label: 'seasonal', + collapsed: true, + items: [{ label: 'Andromeda', link: '' }], + }, + ], + }, + ]} +/> + +Dieses Verhalten kann durch die Definition der Eigenschaft `autogenerate.collapsed` außer Kraft gesetzt werden. + +```js {5-7} "collapsed: true" +starlight({ + sidebar: [ + { + label: 'Konstellationen', + // Die Gruppe "Konstellationen" nicht einklappen, aber ihre + // automatisch generierten Untergruppen. + collapsed: false, + autogenerate: { directory: 'constellations', collapsed: true }, + }, + ], +}); +``` + +Die obige Konfiguration erzeugt die folgende Seitenleiste: + +<SidebarPreview + config={[ + { + label: 'Konstellationen', + items: [ + { label: 'Kiel des Schiffes', link: '' }, + { label: 'Zentaur', link: '' }, + { + label: 'seasonal', + collapsed: true, + items: [{ label: 'Andromeda', link: '' }], + }, + ], + }, + ]} +/> diff --git a/docs/src/content/docs/de/guides/site-search.mdx b/docs/src/content/docs/de/guides/site-search.mdx new file mode 100644 index 00000000000..f8ddb2f0220 --- /dev/null +++ b/docs/src/content/docs/de/guides/site-search.mdx @@ -0,0 +1,242 @@ +--- +title: Suche +description: Finde heraus, welche Suchfunktionen in Starlight integriert sind und wie du sie anpassen kannst. +tableOfContents: + maxHeadingLevel: 4 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +Standardmäßig enthalten Websites, die Starlight verwenden, eine Volltextsuche mit [Pagefind](https://pagefind.app/), einem schnellen, bandbreitenarmen Suchwerkzeug für statische Websites. + +Es ist keine Konfiguration erforderlich, um die Suche zu aktivieren. Erstelle und implementiere deine Website und benutze dann die Suchleiste im Kopfbereich der Website, um nach Inhalten zu suchen. + +## Inhalte in den Suchergebnissen ausblenden + +### Eine Seite ausschließen + +Um eine Seite aus deinem Suchindex auszuschließen, füge [`pagefind: false`](/de/reference/frontmatter/#pagefind) zum Frontmatter der Seite hinzu: + +```md title="src/content/docs/not-indexed.md" ins={3} +--- +title: Inhalt, der vor der Suche verborgen werden soll. +pagefind: false +--- +``` + +### Einen Teil einer Seite ausschließen + +Pagefind ignoriert den Inhalt innerhalb eines Elements mit dem Attribut [`data-pagefind-ignore`](https://pagefind.app/docs/indexing/#removing-individual-elements-from-the-index). + +Im folgenden Beispiel wird der erste Absatz in den Suchergebnissen angezeigt, aber der Inhalt von `<div>` wird nicht angezeigt: + +```md title="src/content/docs/partially-indexed.md" ins="data-pagefind-ignore" +--- +title: Seite teilweise indiziert +--- + +Dieser Text kann über die Suche gefunden werden. + +<div data-pagefind-ignore> + +Dieser Text wird von der Suche ausgeblendet. + +</div> +``` + +## Alternative Suchanbieter + +### Algolia DocSearch + +Wenn du Zugang zum [Algolia DocSearch-Programm](https://docsearch.algolia.com/) hast und es anstelle von Pagefind verwenden möchtest, kannst du das offizielle DocSearch-Plugin von Starlight verwenden. + +<Steps> + +1. Installiere `@astrojs/starlight-docsearch`: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-docsearch + ``` + + </TabItem> + + </Tabs> + +2. Füge DocSearch zu deiner Starlight-Konfiguration [`plugins`](/de/reference/configuration/#plugins) in der Datei `astro.config.mjs` hinzu und gib deine `appId`, `apiKey` und `indexName` von Algolia an: + + ```js ins={4,10-16} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Website mit DocSearch', + plugins: [ + starlightDocSearch({ + appId: 'DEINE_APP_ID', + apiKey: 'DEIN_SUCH_API_SCHLÜSSEL', + indexName: 'DEIN_INDEX_NAME', + }), + ], + }), + ], + }); + ``` + +</Steps> + +Mit dieser aktualisierten Konfiguration öffnet die Suchleiste deiner Website nun ein Algolia-Modal anstelle des Standardmodals. + +#### DocSearch Konfiguration + +Das Starlight DocSearch Plugin unterstützt die Anpassung der DocSearch Komponente mit den folgenden Optionen, die in der Konfiguration des Erweiterungsmoduls angegeben werden: + +- `maxResultsPerGroup`: Begrenzt die Anzahl der Ergebnisse, die für jede Suchgruppe angezeigt werden. Der Standardwert ist `5`. +- `disableUserPersonalization`: Verhindere, dass DocSearch die letzten Suchen und Favoriten eines Nutzers im lokalen Speicher speichert. Der Standardwert ist `false`. +- `insights`: Aktiviere das Algolia Insights Plugin und sende Suchereignisse an deinen DocSearch-Index. Der Standardwert ist `false`. +- `searchParameters`: Ein Objekt, das die [Algolia Search Parameters](https://www.algolia.com/doc/api-reference/search-api-parameters/) anpasst. + +##### Zusätzliche DocSearch-Optionen + +Eine separate Konfigurationsdatei ist erforderlich, um Funktionsoptionen wie `transformItems()` oder `resultsFooterComponent()` an die DocSearch-Komponente zu übergeben. + +<Steps> + +1. Erstelle eine TypeScript-Datei, die deine DocSearch-Konfiguration exportiert. + + ```ts + // src/config/docsearch.ts + import type { DocSearchClientOptions } from '@astrojs/starlight-docsearch'; + export default { + appId: 'DEINE_APP_ID', + apiKey: 'DEIN_SUCH_API_SCHLÜSSEL', + indexName: 'DEIN_INDEX_NAME', + getMissingResultsUrl({ query }) { + return `https://github.com/algolia/docsearch/issues/new?title=${query}`; + }, + // ... + } satisfies DocSearchClientOptions; + ``` + +2. Übergib den Pfad zu deiner Konfigurationsdatei an das Starlight DocSearch Plugin in der Datei `astro.config.mjs`. + + ```js {11-13} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + export default defineConfig({ + integrations: [ + starlight({ + title: 'Website mit DocSearch', + plugins: [ + starlightDocSearch({ + clientOptionsModule: './src/config/docsearch.ts', + }), + ], + }), + ], + }); + ``` + +</Steps> + +Alle unterstützten Optionen findest du in der [DocSearch JavaScript Client API Referenz](https://docsearch.algolia.com/docs/api/). + +#### Die Benutzeroberfläche von DocSearch übersetzen + +DocSearch stellt standardmäßig nur englische Benutzeroberflächen-Strings zur Verfügung. +Füge mithilfe des in Starlight integrierten [Internationalisierungs­systems](/de/guides/i18n/#starlights-ui-übersetzen) Übersetzungen der Benutzeroberfläche der Modale für deine Sprache hinzu. + +<Steps> + +1. Erweitere die Definition der Starlight-Inhaltssammlung `i18n` um das DocSearch-Schema in `src/content.config.ts`: + + ```js ins={5} ins=/{ extend: .+ }/ + // src/content.config.ts + import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; + import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + import { docSearchI18nSchema } from '@astrojs/starlight-docsearch/schema'; + + export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ extend: docSearchI18nSchema() }), + }), + }; + ``` + +2. Füge Übersetzungen zu deinen JSON-Dateien in `src/content/i18n/` hinzu. + + Hier sind die englischen Standardwerte, die von DocSearch verwendet werden: + + ```json title="src/content/i18n/en.json" + { + "docsearch.searchBox.resetButtonTitle": "Clear the query", + "docsearch.searchBox.resetButtonAriaLabel": "Clear the query", + "docsearch.searchBox.cancelButtonText": "Cancel", + "docsearch.searchBox.cancelButtonAriaLabel": "Cancel", + "docsearch.searchBox.searchInputLabel": "Search", + + "docsearch.startScreen.recentSearchesTitle": "Recent", + "docsearch.startScreen.noRecentSearchesText": "No recent searches", + "docsearch.startScreen.saveRecentSearchButtonTitle": "Save this search", + "docsearch.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", + "docsearch.startScreen.favoriteSearchesTitle": "Favorite", + "docsearch.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + + "docsearch.errorScreen.titleText": "Unable to fetch results", + "docsearch.errorScreen.helpText": "You might want to check your network connection.", + + "docsearch.footer.selectText": "to select", + "docsearch.footer.selectKeyAriaLabel": "Enter key", + "docsearch.footer.navigateText": "to navigate", + "docsearch.footer.navigateUpKeyAriaLabel": "Arrow up", + "docsearch.footer.navigateDownKeyAriaLabel": "Arrow down", + "docsearch.footer.closeText": "to close", + "docsearch.footer.closeKeyAriaLabel": "Escape key", + "docsearch.footer.searchByText": "Search by", + + "docsearch.noResultsScreen.noResultsText": "No results for", + "docsearch.noResultsScreen.suggestedQueryText": "Try searching for", + "docsearch.noResultsScreen.reportMissingResultsText": "Believe this query should return results?", + "docsearch.noResultsScreen.reportMissingResultsLinkText": "Let us know." + } + ``` + +</Steps> + +### Community-Suchanbieter + +[Community-Plugins](/de/resources/plugins/#community-plugins) können auch Alternativen zum integrierten Suchanbieter Pagefind von Starlight bieten. + +#### Typesense DocSearch + +Das Community-Plugin [Starlight DocSearch Typesense](https://starlight-docsearch.typesense.org/) bietet eine Open-Source- und selbst hostbare Alternative, die die [DocSearch](https://github.com/typesense/typesense-docsearch.js)-Schnittstelle mit einem [Typesense](https://typesense.org/)-Backend integriert. + +Lies die Anleitung [„Erste Schritte“](https://starlight-docsearch.typesense.org/getting-started/) in der Starlight DocSearch Typesense-Dokumentation, um zu erfahren, wie du es in deinem Projekt verwenden kannst. diff --git a/docs/src/content/docs/de/index.mdx b/docs/src/content/docs/de/index.mdx index fd28e650b31..04f020e2170 100644 --- a/docs/src/content/docs/de/index.mdx +++ b/docs/src/content/docs/de/index.mdx @@ -1,44 +1,157 @@ --- title: Starlight 🌟 Einfache Dokumentations-Websites mit Astro +head: + - tag: title + content: Starlight 🌟 Einfache Dokumentations-Websites mit Astro description: Erstelle schöne, leistungsstarke Dokumentations-Websites mit Starlight und Astro. template: splash +editUrl: false +lastUpdated: false hero: title: Bringe deine Dokumentation mit Starlight zum Leuchten tagline: Alles, was du brauchst, um eine erstklassige Dokumentations-Website zu erstellen. Schnell, barrierefrei und einfach zu bedienen. image: - file: ../../../assets/hero-star.webp + file: ~/assets/hero-star.webp actions: - - text: Los geht's + - text: Los geht’s icon: right-arrow - variant: primary link: /de/getting-started/ - text: Auf GitHub icon: external + variant: minimal link: https://github.com/withastro/starlight --- import { CardGrid, Card } from '@astrojs/starlight/components'; -import AboutAstro from '../../../components/about-astro.astro'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; <CardGrid stagger> <Card title="Dokumentation, die begeistert" icon="open-book"> - Site-Navigation, Suche, Internationalisierung, SEO, leicht lesbare - Typografie, Code-Hervorhebung, Dunkelmodus und mehr. + Website-Navigation, Suche, Internationalisierung, SEO, leicht lesbare + Typografie, Code-Hervorhebung, Dark-Mode und mehr. </Card> <Card title="Angetrieben durch Astro" icon="rocket"> Nutze die volle Kraft und Leistung von Astro. Erweitere Starlight mit deinen bevorzugten Astro-Integrationen. </Card> <Card title="Markdown, Markdoc und MDX" icon="document"> - Bringe deine bevorzugte Dokumentenformat mit. Starlight behält alles im Auge + Bringe dein bevorzugtes Dokumentformat mit. Starlight behält alles im Auge mit integrierte Frontmatter-Validierung. </Card> <Card title="Bringe deine eigenen Komponenten mit" icon="puzzle"> - Starlight wird als Framework-unabhängige, vollständige Dokumentationslösung - geliefert. Erweitere mit React, Vue, Svelte, Solid und mehr. + Starlight wird als frameworkunabhängige, vollständige + Dokumentations­lösung geliefert. Erweitere mit React, Vue, Svelte, Solid + und mehr. </Card> </CardGrid> +<TestimonialGrid title="Was die Leute sagen"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + Das Astro-Team hat die Art und Weise, wie Dokumentationen erstellt werden können, ENTWICKELT, und mit ihrem Starlight-Projekt kannst du sie sofort nutzen. + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + Astros offizielles Starterkit Starlight ist ein unglaubliches Werkzeug für die Erstellung einer Dokumentations-Website + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + Starlight ist unser Paradebeispiel für einen großartigen DX: Die Geschwindigkeit, der Komfort + und die Liebe zum Detail sind inspirierend. Es kümmert sich um die Technik und das Aussehen, + damit du dich auf deine Inhalte konzentrieren kannst 👏. + + Das StackBlitz-Team liebt es! + + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + Starlight hat meine Arbeit grundlegend verändert und mir die Möglichkeit gegeben, mich auf die Erstellung von Inhalten zu konzentrieren. + + Sein intuitives Design vereinfacht nicht nur meinen Arbeitsablauf, sondern verkürzt auch die Einarbeitungszeit für Open-Source-Entwickler. + + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + Ich habe etwas mehr Zeit mit Starlight für die Kurs-Bauer-Dokumentation verbracht und es ist bisher großartig. Ich kann mich auf das Schreiben in Markdown konzentrieren und muss nicht mehr an der Website herumfummeln. + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + Ich habe angefangen, mit Starlight zu spielen. Ich muss sagen, ich bin sehr beeindruckt von der Leistung, die es bietet. + + 💯💯💯💯 + + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + Starlight ist der beste Weg, um mit der Dokumentation zu beginnen. + Leistung und Geschwindigkeit von Astro und den Werkzeugen von Starlight, es ist wie im siebten Himmel. + Ich benutze es schon seit einer Weile und bin immer noch begeistert! + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + Ich habe Starlight in meinem letzten Job benutzt und war begeistert. Tolle Komponenten, intuitives Design + und eine sehr reaktionsfreudige Community (wann immer jemand etwas brauchte, + haben sie es schnell integriert oder dir eine temporäre Lösung gezeigt). Eine sehr angenehme Erfahrung. + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + Die Dokumentation auf meiner Monorepo-Website sehen dank Starlight besser aus als je zuvor. Es ist extrem einfach zu bedienen, ohne dabei die ganze Leistung von Astro zu verlieren. Danke, dass ihr daran arbeitet! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + Starlight ist mein bevorzugtes Tool für Dokumentationen. Mit Starlight war es super einfach, meiner bestehenden Astro-Produktwebsite Dokumentation hinzuzufügen, anstatt eine Subdomain für ein anderes Tool zu benötigen. + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + Ich habe die WPEngine Atlas Platform Dokumentation neu aufgebaut. Vertrau mir, wenn ich sage, dass Starlight alles hat, was du brauchst, um eine hervorragende Doku-Plattform zu machen 🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + Probiere Starlight aus! + + Ich benutze es für ein paar meiner Websites und es ist großartig. + + </Testimonial> +</TestimonialGrid> + <AboutAstro title="Präsentiert von"> Astro ist ein Web-Framework, das eine Komplettlösung zur Erstellung schneller Websites darstellt. Rufe deine Inhalte von überall ab und stelle sie überall bereit, alles unterstützt durch deine bevorzugten UI-Komponenten und Bibliotheken. diff --git a/docs/src/content/docs/de/manual-setup.mdx b/docs/src/content/docs/de/manual-setup.mdx index f13b21c8541..42212785c74 100644 --- a/docs/src/content/docs/de/manual-setup.mdx +++ b/docs/src/content/docs/de/manual-setup.mdx @@ -5,7 +5,7 @@ description: Lerne wie du Starlight manuell konfigurierst, um es zu einem besteh import { Tabs, TabItem } from '@astrojs/starlight/components'; -Der schnellste Weg, eine neue Starlight-Site zu erstellen, ist die Verwendung von `create astro`, wie auf der Seite [Erste Schritte](/de/getting-started/#erstelle-ein-neues-projekt) beschrieben. +Der schnellste Weg, eine neue Starlight-Website zu erstellen, ist die Verwendung von `create astro`, wie auf der Seite [Erste Schritte](/de/getting-started/#erstelle-ein-neues-projekt) beschrieben. Wie du Starlight zu einem bestehenden Astro-Projekt hinzufügst, wird in dieser Anleitung erklärt. ## Starlight einrichten @@ -14,9 +14,9 @@ Um dieser Anleitung folgen zu können, benötigst du ein bestehendes Astro-Proje ### Hinzufügen der Starlight-Integration -Starlight ist eine [Astro-Integration](https://docs.astro.build/de/guides/integrations-guide/). Füge sie zu deiner Website hinzu, indem du den Befehl `astro add` im Wurzelverzeichnis deines Projekts ausführst: +Starlight ist eine [Astro-Integration](https://docs.astro.build/de/guides/integrations-guide/). Füge sie zu deiner Website hinzu, indem du den Befehl `astro add` im Projektstamm­verzeichnis deines Projekts ausführst: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh npx astro add starlight @@ -44,7 +44,7 @@ Die Starlight-Integration wird in der Datei `astro.config.mjs` konfiguriert. Füge zunächst einen Titel mit der Eigenschaft `title` hinzu: -```js {7-9} +```js ins={8} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -58,24 +58,28 @@ export default defineConfig({ }); ``` -Alle verfügbaren Optionen findest du in der [Starlight-Konfigurationsreferenz](/de/reference/configuration/). +Alle verfügbaren Optionen findest du in der [Starlight-Konfigurations­referenz](/de/reference/configuration/). ### Konfigurieren von Inhaltssammlungen -Starlight baut auf Astros [Inhaltssammlungen](https://docs.astro.build/de/guides/content-collections/) auf, die in der Datei `src/content/config.ts` konfiguriert werden. +Starlight baut auf Astros [Inhaltssammlungen](https://docs.astro.build/de/guides/content-collections/) auf, die in der Datei `src/content.config.ts` konfiguriert werden. -Erstelle oder aktualisiere die Inhaltskonfigurationsdatei und füge eine `docs`-Sammlung hinzu, die Starlight's `docsSchema` verwendet: +Erstelle oder aktualisiere die Inhalts­konfigurationsdatei und füge eine `docs`-Sammlung hinzu, die Starlights [`docsLoader`](/de/reference/configuration/#docsloader) und [`docsSchema`](/de/reference/configuration/#docsschema) verwendet: -```js ins={3,6} -// src/content/config.ts +```js ins={3-4,7} +// src/content.config.ts import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; import { docsSchema } from '@astrojs/starlight/schema'; export const collections = { - docs: defineCollection({ schema: docsSchema() }), + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), }; ``` +Starlight unterstützt auch die Option [`legacy.collections`](https://docs.astro.build/de/reference/legacy-flags/), bei dem Sammlungen mit der Legacy-Implementierung von Inhaltssammlungen behandelt werden. +Dies ist nützlich, wenn du ein bestehendes Astro-Projekt hast und zum jetzigen Zeitpunkt keine Änderungen an den Sammlungen vornehmen kannst, um einen Loader zu verwenden. + ### Inhalte hinzufügen Starlight ist jetzt konfiguriert und du kannst Inhalte hinzuzufügen. @@ -87,7 +91,7 @@ Dies wird die Startseite deiner neuen Website sein: --- # src/content/docs/index.md title: Meine Dokumentation -description: Erfahre mehr über mein Projekt auf dieser mit Starlight erstellten Dokumentseite. +description: Erfahre mehr über mein Projekt auf dieser mit Starlight erstellten Dokumentationswebsite. --- Willkommen bei meinem Projekt! @@ -106,7 +110,7 @@ Um alle Starlight-Seiten mit einem anderen Pfad aufrufen zu können, lege den ge Wenn zum Beispiel die URL alle Starlight-Seiten mit `/guides/` beginnen sollen, füge deine Inhalte in das Verzeichnis `src/content/docs/guides/` ein: -import FileTree from '../../../components/file-tree.astro'; +import { FileTree } from '@astrojs/starlight/components'; <FileTree> @@ -125,4 +129,6 @@ Für die Zukunft planen wir, diesen Anwendungsfall besser zu unterstützen, um d ### Starlight mit SSR verwenden -Derzeit unterstützt Starlight kein [Serverseitiges Rendern \(SSR\)](https://docs.astro.build/de/guides/server-side-rendering/) mit Astros Server-Adaptern. Wir hoffen, dies bald unterstützen zu können. +Um SSR zu aktivieren, folge der Anleitung [„Serverseitiges Rendern (SSR)“](https://docs.astro.build/de/guides/on-demand-rendering/) in der Astro-Dokumentation, um einen Server-Adapter zu deinem Starlight-Projekt hinzuzufügen. + +Die von Starlight erzeugten Dokumentations­seiten werden standardmäßig vorgerendert, unabhängig vom Ausgabemodus deines Projekts. Wenn du nicht möchtest, dass deine Starlight-Seiten vorgerendert werden, setze die [Konfigurations­option `prerender`](/de/reference/configuration/#prerender) auf `false`. diff --git a/docs/src/content/docs/de/reference/configuration.md b/docs/src/content/docs/de/reference/configuration.md deleted file mode 100644 index de88c323a74..00000000000 --- a/docs/src/content/docs/de/reference/configuration.md +++ /dev/null @@ -1,414 +0,0 @@ ---- -title: Konfigurations­referenz -description: Ein Überblick über alle von Starlight unterstützten Konfigurationsoptionen. ---- - -## Konfiguriere die `starlight` Integration - -Starlight ist eine Integration, die auf dem [Astro](https://astro.build) Web-Framework aufbaut. Du kannst dein Projekt innerhalb der Astro-Konfigurationsdatei `astro.config.mjs` anpassen: - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'My delightful docs site', - }), - ], -}); -``` - -Du kannst die folgenden Optionen an die `starlight` Integration übergeben. - -### `title` (erforderlich) - -**Typ:** `string` - -Lege den Titel für deine Website fest. Wird in den Metadaten und im Titel der Browser-Tabs verwendet. - -### `description` - -**Typ:** `string` - -Lege die Beschreibung für deine Website fest. Wird in den Metadaten verwendet, die mit Suchmaschinen im `<meta name="description">`-Tag geteilt werden, für Seiten wo `description` nicht im Frontmatter festgelegt ist. - -### `logo` - -**Typ:** [`LogoConfig`](#logoconfig) - -Legt ein Logobild fest, das in der Navigationsleiste neben oder anstelle des Seitentitels angezeigt wird. Du kannst entweder eine einzige `src`-Eigenschaft oder separate Bildquellen für `light` und `dark` festlegen. - -```js -starlight({ - logo: { - src: './src/assets/my-logo.svg', - }, -}); -``` - -#### `LogoConfig` - -```ts -type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( - | { src: string } - | { light: string; dark: string } -); -``` - -### `tableOfContents` - -**Typ:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` -**Voreinstellung:** `{ minHeadingLevel: 2; maxHeadingLevel: 3; }` - -Konfiguriere das Inhaltsverzeichnis, das rechts auf jeder Seite angezeigt wird. Standardmäßig werden `<h2>` und `<h3>` Überschriften in dieses Inhaltsverzeichnis aufgenommen. - -### `editLink` - -**Typ:** `{ baseUrl: string }` - -Aktiviere "Diese Seite bearbeiten"-Links, indem du die Basis-URL für diese festlegst. Der endgültige Link wird `editLink.baseUrl` + der aktuelle Seitenpfad sein. Zum Beispiel, um das Bearbeiten von Seiten im `withastro/starlight` Repo auf GitHub zu ermöglichen: - -```js -starlight({ - editLink: { - baseUrl: 'https://github.com/withastro/starlight/edit/main/', - }, -}); -``` - -Mit dieser Konfiguration würde eine `/einfuehrung` einen Bearbeitungslink haben, der auf `https://github.com/withastro/starlight/edit/main/src/docs/einfuehrung.md` zeigt. - -### `sidebar` - -**Typ:** [`SidebarItem[]`](#sidebaritem) - -Konfiguriere die Navigationselemente der Seitenleiste deiner Website. - -Eine Seitenleiste ist eine Array von Links und Linkgruppen. -Jedes Element muss ein `label` und eine der folgenden Eigenschaften haben: - -- `link` - ein einzelner Link zu einer bestimmten URL, z.B. `'/home'` oder `'https://example.com'`. -- `items` - ein Array, das weitere Links und Untergruppen enthält. -- `autogenerate` - ein Objekt, das ein Verzeichnis deiner Dokumentation angibt, aus dem automatisch eine Gruppe von Links erzeugt werden soll. - -```js -starlight({ - sidebar: [ - // Ein einzelner Link mit der Bezeichnung "Startseite". - { label: 'Startseite', link: '/' }, - // Eine Gruppe mit der Bezeichnung "Hier anfangen", die zwei Links enthält. - { - label: 'Hier anfangen', - items: [ - { label: 'Einleitung', link: '/intro' }, - { label: 'Nächste Schritte', link: '/next-steps' }, - ], - }, - // Eine Gruppe, die auf alle Seiten im Referenzverzeichnis verweist. - { - label: 'Referenz', - autogenerate: { - directory: 'referenz', - }, - }, - ], -}); -``` - -#### Sortierung - -Die automatisch erstellten Seitenleisten-Gruppen werden alphabetisch nach dem Dateinamen sortiert. -Zum Beispiel würde eine Seite, die aus der Datei `astro.md` erzeugt wurde, über der Seite für `starlight.md` erscheinen. - -#### Zusammenklappbare Gruppen - -Gruppen von Links sind standardmäßig aufgeklappt. Du kannst dieses Verhalten ändern, indem du die Eigenschaft `collapsed` einer Gruppe auf `true` setzt. - -Autogenerierte Untergruppen respektieren standardmäßig die Eigenschaft `collapsed` ihrer übergeordneten Gruppe. Dies kannst du mit der Eigenschaft `autogenerate.collapsed` außer Kraft setzen. - -```js -sidebar: [ - // Eine zusammengefasste Gruppe von Links - { - label: 'Collapsed Links', - collapsed: true, - items: [ - { label: 'Einleitung', link: '/intro' }, - { label: 'Nächste Schritte', link: '/next-steps' }, - ], - }, - // Eine aufgeklappte Gruppe, die automatisch generierte Untergruppen enthält, welche standardmäßig eingeklappt sind. - { - label: 'Referenz', - autogenerate: { - directory: 'reference', - collapsed: true, - }, - }, -], -``` - -#### Labels übersetzen - -Wenn deine Website mehrsprachig ist, wird das `label` jedes Elements als in der Standard-Sprache verfasst betrachtet. Du kannst die Eigenschaft `translations` verwenden, um die Labels für andere unterstützte Sprachen festzulegen: - -```js -sidebar: [ - // Ein Beispiel für eine Seitenleiste mit ins Französische übersetzten Beschriftungen - { - label: 'Hier anfangen', - translations: { fr: 'Commencez ici' }, - items: [ - { - label: 'Erste Schritte', - translations: { fr: 'Bien démarrer' }, - link: '/getting-started', - }, - { - label: 'Projektstruktur', - translations: { fr: 'Structure du projet' }, - link: '/structure', - }, - ], - }, -], -``` - -#### `SidebarItem` - -```ts -type SidebarItem = { - label: string; - translations?: Record<string, string>; -} & ( - | { link: string } - | { items: SidebarItem[]; collapsed?: boolean } - | { - autogenerate: { directory: string; collapsed?: boolean }; - collapsed?: boolean; - } -); -``` - -### `locales` - -**Typ:** <code>{ \[dir: string\]: [LocaleConfig](#localeconfig) }</code> - -[Konfiguriere die Internationalisierung (i18n)](/de/guides/i18n/) für Ihre Website, indem du festlegst, welche `Locales` unterstützt werden. - -Jeder Eintrag sollte das Verzeichnis, in dem die Dateien der jeweiligen Sprache gespeichert sind, als Schlüssel verwenden. - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'My Docs', - // Englisch als Standardsprache festlegen. - defaultLocale: 'en', - locales: { - // Englische Seiten in `src/content/docs/en/` - en: { - label: 'English', - }, - // Chinesische Seiten in `src/content/docs/zh/` - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - // Arabische Seiten in `src/content/docs/ar/` - ar: { - label: 'العربية', - dir: 'rtl', - }, - }, - }), - ], -}); -``` - -#### `LocaleConfig` - -```ts -interface LocaleConfig { - label: string; - lang?: string; - dir?: 'ltr' | 'rtl'; -} -``` - -Du kannst die folgenden Optionen für jedes Locale-Schema festlegen: - -##### `label` (erforderlich) - -**Typ:** `string` - -Die Bezeichnung für diese Sprache, die den Benutzern angezeigt werden soll, z. B. im Sprachumschalter. Meistens wird dies der Name der Sprache sein, wie ihn ein Benutzer dieser Sprache erwarten würde, z.B. `"English"`, `"العربية"`, oder `"简体中文"`. - -##### `lang` - -**Typ:** `string` - -Das BCP-47-Tag für diese Sprache, z. B. `"en"`, `"ar"` oder `"zh-CN"`. Wenn nicht gesetzt, wird standardmäßig der Verzeichnisname der Sprache verwendet. Sprach-Tags mit regionalen Unter-Tags (z.B. `"pt-BR"` oder `"en-US"`) verwenden integrierte UI-Übersetzungen für ihre Basissprache, wenn keine regionalspezifischen Übersetzungen gefunden werden. - -##### `dir` - -**Typ:** `'ltr' | 'rtl'` - -Die Schreibrichtung dieser Sprache; `"ltr"` für links-nach-rechts (die Voreinstellung) oder `"rtl"` für rechts-nach-links. - -#### Root-Locale - -Du kannst die Standardsprache ohne ein `/lang/`-Verzeichnis anbieten, indem du ein `root`-Locale setzst: - -```js -starlight({ - locales: { - root: { - label: 'Englisch', - lang: 'en', - }, - fr: { - label: 'Français', - }, - }, -}); -``` - -So kannst du zum Beispiel `/getting-started/` als englische Seite und `/fr/getting-started/` als entsprechende französische Seite verwenden. - -### `defaultLocale` - -**Typ:** `string` - -Legt die Sprache fest, die als Standard für diese Webseite gilt. -Der Wert sollte mit einem der Schlüssel deines [`locales`](#locales)-Objekts übereinstimmen. -(Wenn deine Standardsprache deiner [Root-Locale](#root-locale) ist, kannst du dies überspringen). - -Das `defaultLocale` wird verwendet, um Ersatzinhalte bereitzustellen, wenn Übersetzungen fehlen. - -### `social` - -**Typ:** `Partial<Record<'bitbucket' | 'codeberg' | 'codePen' | 'discord' | 'github' | 'gitlab' | 'gitter' | 'instagram' | 'linkedin' | 'mastodon' | 'microsoftTeams' | 'threads' | 'twitch' | 'twitter' | 'youtube', string>>` - -Optionale Angaben zu den Social-Media-Konten für diese Site. Wenn du eines dieser Konten hinzufügst, werden sie als Icon-Links in der Kopfzeile der Website angezeigt. - -```js -starlight({ - social: { - codeberg: 'https://codeberg.org/knut/examples', - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - gitlab: 'https://gitlab.com/delucis', - linkedin: 'https://www.linkedin.com/company/astroinc', - mastodon: 'https://m.webtoo.ls/@astro', - threads: 'https://www.threads.net/@nmoodev', - twitch: 'https://www.twitch.tv/bholmesdev', - twitter: 'https://twitter.com/astrodotbuild', - youtube: 'https://youtube.com/@astrodotbuild', - }, -}); -``` - -### `customCss` - -**Typ:** `string[]` - -Stellen CSS-Dateien zur Verfügung, um das Aussehen deines Starlight-Projekts anzupassen. - -Unterstützt lokale CSS-Dateien relativ zum Stammverzeichnis deines Projekts, z.B. `'./src/custom.css'`, und CSS, die du als npm-Modul installiert hast, z.B. `'@fontsource/roboto'`. - -```js -starlight({ - customCss: ['./src/custom-styles.css', '@fontsource/roboto'], -}); -``` - -### `head` - -**Typ:** [`HeadConfig[]`](#headconfig) - -Füge zusätzliche Tags in den `<head>` deines Starlight-Projekts ein. -Kann nützlich sein, um Analytics und andere Skripte und Ressourcen von Drittanbietern hinzuzufügen. - -```js -starlight({ - head: [ - // Beispiel: Fathom Analytics Skript-Tag hinzufügen. - { - tag: 'script', - attrs: { - src: 'https://cdn.usefathom.com/script.js', - 'data-site': 'MY-FATHOM-ID', - defer: true, - }, - }, - ], -}); -``` - -#### `HeadConfig` - -```ts -interface HeadConfig { - tag: string; - attrs?: Record<string, string | boolean | undefined>; - content?: string; -} -``` - -### `lastUpdated` - -**Typ:** `boolean` -**Standard:** `false` - -Legt fest, ob in der Fußzeile angezeigt werden soll, wann die Seite zuletzt aktualisiert wurde. - -Standardmäßig verwendet diese Funktion die Git-Historie Ihres Repositorys und kann auf einigen Bereitstellungsplattformen, die [shallow clones](https://git-scm.com/docs/git-clone/de#git-clone---depthltTiefegt) durchführen, nicht genau sein. Eine Seite kann diese Einstellung oder das Git-basierte Datum mit dem [`lastUpdated` Frontmatter-Feld](/de/reference/frontmatter/#lastupdated) überschreiben. - -### `pagination` - -**Typ:** `boolean` -**Standard:** `true` - -Legt fest, ob die Fußzeile Links zur vorherigen und nächsten Seite enthalten soll. - -Eine Seite kann diese Einstellung oder den Linktext und/oder die URL mit Hilfe der Frontmatter-Felder [`prev`](/de/reference/frontmatter/#prev) und [`next`](/de/reference/frontmatter/#next) überschreiben. - -### `favicon` - -**Typ:** `string` -**Standard:** `'/favicon.svg'` - -Legt den Pfad des Standard-Favicons für deine Website fest. Dieses sollte sich im Verzeichnis `public/` befinden und eine gültige Icon-Datei (`.ico`, `.gif`, `.jpg`, `.png` oder `.svg`) sein. - -```js -starlight({ - favicon: '/images/favicon.svg', -}), -``` - -Wenn du zusätzliche Varianten oder Fallback-Favicons festlegen musst, kannst du diese mit der Option [`head`](#head) Tags hinzufügen: - -```js -starlight({ - favicon: '/images/favicon.svg'. - head: [ - // ICO-Favicon als Fallback für Safari hinzufügen - { - tag: 'link', - attrs: { - rel: 'icon', - href:'/images/favicon.ico', - sizes: '32x32', - }, - }, - ], -}); -``` diff --git a/docs/src/content/docs/de/reference/configuration.mdx b/docs/src/content/docs/de/reference/configuration.mdx new file mode 100644 index 00000000000..0cbc897164f --- /dev/null +++ b/docs/src/content/docs/de/reference/configuration.mdx @@ -0,0 +1,820 @@ +--- +title: Konfigurationsreferenz +description: Ein Überblick über alle von Starlight unterstützten Konfigurations­optionen. +sidebar: + label: Konfiguration +--- + +## Konfiguriere die `starlight` Integration + +Starlight ist eine Integration, die auf dem [Astro](https://astro.build) Web-Framework aufbaut. Du kannst dein Projekt innerhalb der Astro-Konfigurationsdatei `astro.config.mjs` anpassen: + +```js +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'My delightful docs site', + }), + ], +}); +``` + +Du kannst die folgenden Optionen an die `starlight` Integration übergeben. + +### `title` (erforderlich) + +**Typ:** `string | Record<string, string>` + +Lege den Titel für deine Website fest. Wird in den Metadaten und im Titel der Browser-Tabs verwendet. + +Der Wert kann eine Zeichenkette sein, oder für mehrsprachige Websites ein Objekt mit Werten für jedes Gebietsschema. +Wenn die Objektform verwendet wird, müssen die Schlüssel BCP-47-Tags sein (z. B. `en`, `ar` oder `zh-CN`): + +```ts +starlight({ + title: { + en: 'My delightful docs site', + de: 'Meine bezaubernde Dokumentationswebsite', + }, +}); +``` + +### `description` + +**Typ:** `string` + +Lege die Beschreibung für deine Website fest. Wird in den Metadaten verwendet, die mit Suchmaschinen im `<meta name="description">`-Tag geteilt werden, für Seiten wo `description` nicht im Frontmatter festgelegt ist. + +### `logo` + +**Typ:** [`LogoConfig`](#logoconfig) + +Legt ein Logobild fest, das in der Navigationsleiste neben oder anstelle des Seitentitels angezeigt wird. Du kannst entweder eine einzige `src`-Eigenschaft oder separate Bildquellen für `light` und `dark` festlegen. + +```js +starlight({ + logo: { + src: './src/assets/my-logo.svg', + }, +}); +``` + +#### `LogoConfig` + +```ts +type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( + | { src: string } + | { light: string; dark: string } +); +``` + +### `tableOfContents` + +**Typ:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number }` +**Standard:** `{ minHeadingLevel: 2, maxHeadingLevel: 3 }` + +Konfiguriere das Inhaltsverzeichnis, das rechts auf jeder Seite angezeigt wird. Standardmäßig werden `<h2>` und `<h3>` Überschriften in dieses Inhaltsverzeichnis aufgenommen. + +### `editLink` + +**Typ:** `{ baseUrl: string }` + +Aktiviere „Diese Seite bearbeiten“-Links, indem du die Basis-URL für diese festlegst. Der endgültige Link wird `editLink.baseUrl` + der aktuelle Seitenpfad sein. Zum Beispiel, um das Bearbeiten von Seiten im `withastro/starlight` Repo auf GitHub zu ermöglichen: + +```js +starlight({ + editLink: { + baseUrl: 'https://github.com/withastro/starlight/edit/main/', + }, +}); +``` + +Mit dieser Konfiguration würde eine `/einfuehrung` einen Bearbeitungslink haben, der auf `https://github.com/withastro/starlight/edit/main/src/content/docs/einfuehrung.md` zeigt. + +### `sidebar` + +**Typ:** [`SidebarItem[]`](#sidebaritem) + +Konfiguriere die Navigationselemente der Seitenleiste deiner Website. + +Eine Seitenleiste ist eine Array von Links und Linkgruppen. +Mit Ausnahme von Einträgen, die `slug` verwenden, muss jeder Eintrag ein `label` und eine der folgenden Eigenschaften haben: + +- `link` - ein einzelner Link zu einer bestimmten URL, z. B. `'/home'` oder `'https://example.com'`. + +- `slug` - ein Verweis auf eine interne Seite, z. B. `'guides/getting-started'`. + +- `items` - ein Array, das weitere Links und Untergruppen enthält. + +- `autogenerate` - ein Objekt, das ein Verzeichnis deiner Dokumentation angibt, aus dem automatisch eine Gruppe von Links erzeugt werden soll. + +Interne Links können auch als Zeichenkette anstelle eines Objekts mit der Eigenschaft `slug` angegeben werden. + +```js +starlight({ + sidebar: [ + // Ein einzelner Link mit der Bezeichnung "Startseite". + { label: 'Startseite', link: '/' }, + // Eine Gruppe mit der Bezeichnung „Hier beginnen“, die vier Links enthält. + { + label: 'Hier anfangen', + items: [ + // Verwendung von `slug` für interne Links. + { slug: 'intro' }, + { slug: 'installation' }, + // Oder du verwendst die Abkürzung für interne Links. + 'tutorial', + 'next-steps', + ], + }, + // Eine Gruppe, die auf alle Seiten im Referenzverzeichnis verweist. + { + label: 'Referenzen', + autogenerate: { directory: 'referenz' }, + }, + ], +}); +``` + +#### Sortierung + +Die automatisch erstellten Seitenleisten-Gruppen werden alphabetisch nach dem Dateinamen sortiert. +Zum Beispiel würde eine Seite, die aus der Datei `astro.md` erzeugt wurde, über der Seite für `starlight.md` erscheinen. + +#### Zusammenklappbare Gruppen + +Gruppen von Links sind standardmäßig aufgeklappt. Du kannst dieses Verhalten ändern, indem du die Eigenschaft `collapsed` einer Gruppe auf `true` setzt. + +Autogenerierte Untergruppen respektieren standardmäßig die Eigenschaft `collapsed` ihrer übergeordneten Gruppe. Dies kannst du mit der Eigenschaft `autogenerate.collapsed` außer Kraft setzen. + +```js {5,13} +sidebar: [ + // Eine zusammengefasste Gruppe von Links + { + label: 'Zusammengeklappte Links', + collapsed: true, + items: ['intro', 'next-steps'], + }, + // Eine aufgeklappte Gruppe, die automatisch generierte Untergruppen enthält, welche standardmäßig eingeklappt sind. + { + label: 'Referenzen', + autogenerate: { + directory: 'reference', + collapsed: true, + }, + }, +], +``` + +#### Labels übersetzen + +Wenn deine Website mehrsprachig ist, wird das `label` jedes Elements als in der Standard-Sprache verfasst betrachtet. Du kannst die Eigenschaft `translations` verwenden, um die Labels für andere unterstützte Sprachen festzulegen: + +```js {5,9,14} +sidebar: [ + // Ein Beispiel für eine Seitenleiste mit ins Französische übersetzten Beschriftungen + { + label: 'Hier anfangen', + translations: { fr: 'Commencez ici' }, + items: [ + { + label: 'Erste Schritte', + translations: { fr: 'Bien démarrer' }, + link: '/getting-started', + }, + { + label: 'Projektstruktur', + translations: { fr: 'Structure du projet' }, + link: '/structure', + }, + ], + }, +], +``` + +#### `SidebarItem` + +```ts +type SidebarItem = + | string + | ({ + translations?: Record<string, string>; + badge?: string | BadgeConfig; + } & ( + | { + // Link + link: string; + label: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // Interner Link + slug: string; + label?: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // Gruppe von Links + label: string; + items: SidebarItem[]; + collapsed?: boolean; + } + | { + // Automatisch generierte Linkgruppe + label: string; + autogenerate: { + directory: string; + collapsed?: boolean; + attrs?: Record<string, string | number | boolean | undefined>; + }; + collapsed?: boolean; + } + )); +``` + +#### `BadgeConfig` + +```ts +interface BadgeConfig { + text: string; + variant?: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; + class?: string; +} +``` + +### `locales` + +**Typ:** <code>\{ \[dir: string\]: [LocaleConfig](#localeconfig) \}</code> + +[Konfiguriere die Internationalisierung (i18n)](/de/guides/i18n/) für deine Website, indem du festlegst, welche `locales` unterstützt werden. + +Jeder Eintrag sollte das Verzeichnis, in dem die Dateien der jeweiligen Sprache gespeichert sind, als Schlüssel verwenden. + +```js +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'My Docs', + // Englisch als Standardsprache festlegen. + defaultLocale: 'en', + locales: { + // Englische Seiten in `src/content/docs/en/` + en: { + label: 'English', + }, + // Chinesische Seiten in `src/content/docs/zh-cn/` + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + // Arabische Seiten in `src/content/docs/ar/` + ar: { + label: 'العربية', + dir: 'rtl', + }, + }, + }), + ], +}); +``` + +#### `LocaleConfig` + +```ts +interface LocaleConfig { + label: string; + lang?: string; + dir?: 'ltr' | 'rtl'; +} +``` + +Du kannst die folgenden Optionen für jedes Locale-Schema festlegen: + +##### `label` (erforderlich) + +**Typ:** `string` + +Die Bezeichnung für diese Sprache, die den Benutzern angezeigt werden soll, z. B. im Sprachumschalter. Meistens wird dies der Name der Sprache sein, wie ihn ein Benutzer dieser Sprache erwarten würde, z. B. `"English"`, `"العربية"`, oder `"简体中文"`. + +##### `lang` + +**Typ:** `string` + +Das BCP-47-Tag für diese Sprache, z. B. `"en"`, `"ar"` oder `"zh-CN"`. Wenn nicht gesetzt, wird standardmäßig der Verzeichnisname der Sprache verwendet. Sprach-Tags mit regionalen Unter-Tags (z. B. `"pt-BR"` oder `"en-US"`) verwenden integrierte UI-Übersetzungen für deine Basissprache, wenn keine regional­spezifischen Übersetzungen gefunden werden. + +##### `dir` + +**Typ:** `'ltr' | 'rtl'` + +Die Schreibrichtung dieser Sprache; `"ltr"` für links-nach-rechts (die Voreinstellung) oder `"rtl"` für rechts-nach-links. + +#### Root-Locale + +Du kannst die Standardsprache ohne ein `/lang/`-Verzeichnis anbieten, indem du ein `root`-Locale setzst: + +```js {3-6} +starlight({ + locales: { + root: { + label: 'Englisch', + lang: 'en', + }, + fr: { + label: 'Français', + }, + }, +}); +``` + +So kannst du zum Beispiel `/getting-started/` als englische Seite und `/fr/getting-started/` als entsprechende französische Seite verwenden. + +### `defaultLocale` + +**Typ:** `string` + +Legt die Sprache fest, die als Standard für diese Website gilt. +Der Wert sollte mit einem der Schlüssel deines [`locales`](#locales)-Objekts übereinstimmen. +(Wenn deine Standardsprache deiner [Root-Locale](#root-locale) ist, kannst du dies überspringen). + +Das standard Locale wird verwendet, um Ersatzinhalte bereitzustellen, wenn Übersetzungen fehlen. + +### `social` + +**Typ:** <code>{`Array<{ label: string; icon: `}[StarlightIcon](/de/reference/icons/){`; href: string }>`}</code> + +Optionale Angaben zu den Social-Media-Konten für diese Website. +Jeder Eintrag wird als Symbol-Link in der Kopfzeile der Seite angezeigt. + +```js +starlight({ + social: [ + { icon: 'codeberg', label: 'Codeberg', href: 'https://codeberg.org/knut' }, + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro' }, + { icon: 'gitlab', label: 'GitLab', href: 'https://gitlab.com/delucis' }, + { icon: 'mastodon', label: 'Mastodon', href: 'https://m.webtoo.ls/@astro' }, + ], +}), +``` + +### `customCss` + +**Typ:** `string[]` + +Stellen CSS-Dateien zur Verfügung, um das Aussehen deines Starlight-Projekts anzupassen. + +Unterstützt lokale CSS-Dateien relativ zum Stammverzeichnis deines Projekts, z. B. `'./src/custom.css'`, und CSS, die du als npm-Modul installiert hast, z. B. `'@fontsource/roboto'`. + +```js +starlight({ + customCss: ['./src/custom-styles.css', '@fontsource/roboto'], +}); +``` + +### `markdown` + +**Typ:** `{ headingLinks?: boolean; processedDirs?: string[] }` +**Standard:** `{ headingLinks: true, processedDirs: [] }` + +Konfiguriere die Markdown-Verarbeitung von Starlight. + +#### `headingLinks` + +**Typ:** `boolean` +**Standard:** `true` + +Steuert, ob Überschriften mit einem anklickbaren Ankerlink dargestellt werden oder nicht. + +```js +starlight({ + markdown: { + // Deaktiviere die anklickbaren Überschrift-Ankerlinks von Starlight. + headingLinks: false, + }, +}), +``` + +#### `processedDirs` + +**Typ:** `string[]` +**Standard:** `[]` + +Gib zusätzliche Ordner an, in denen Dateien von Starlights Markdown-Pipeline bearbeitet werden sollen. +Standardmäßig werden nur Markdown- und MDX-Inhalte verarbeitet, die mit Starlights [`docsLoader()`](/de/reference/configuration/#docsloader) geladen wurden. +Unterstützt lokale Verzeichnisse, die relativ zum Stammverzeichnis deines Projekts liegen, z. B. `./src/data/comments/`. + +Starlight unterstützt [anklickbare Überschriften-Ankerlinks](#headinglinks), die [Markdown-Direktiven-Syntax für Asides](/de/guides/authoring-content/#nebenbemerkungen) und die RTL-Unterstützung für Code-Blöcke. +Diese Option kann nützlich sein, wenn du Inhalte aus einer benutzerdefinierten Inhaltssammlung in einer [benutzerdefinierten Seite](/de/guides/pages/#benutzerdefinierte-seiten) mit der Komponente `<StarlightPage>` rendern und erwartest, dass die Markdown-Verarbeitung von Starlight auch auf diese Inhalte angewendet wird. + +```js +starlight({ + markdown: { + // Verarbeite Markdown-Dateien aus der Inhaltssammlung `reviews` + // im Verzeichnis `src/data/reviews/`. + processedDirs: ['./src/data/reviews/'], + }, +}), +``` + +### `expressiveCode` + +**Typ:** `StarlightExpressiveCodeOptions | boolean` +**Standard:** `true` + +Starlight verwendet [Expressive Code](https://expressive-code.com), um Codeblöcke zu rendern und Unterstützung für das Hervorheben von Teilen von Codebeispielen, das Hinzufügen von Dateinamen zu Codeblöcken und mehr hinzuzufügen. +Im [Handbuch „Codeblöcke“](/de/guides/authoring-content/#codeblöcke) erfährst du, wie du die Expressive Code-Syntax in deinen Markdown- und MDX-Inhalten verwendest. + +Du kannst alle standardmäßigen [Expressive Code-Konfigurations­optionen](https://expressive-code.com/reference/configuration/) sowie einige Starlight-spezifische Eigenschaften verwenden, indem du sie in der Option `expressiveCode` von Starlight festlegst. +Lege beispielsweise die Option `styleOverrides` von Expressive Code fest, um das Standard-CSS zu überschreiben. Dadurch sind Anpassungen möglich, beispielsweise das Hinzufügen abgerundeter Ecken zu deinen Codeblöcken: + +```js ins={2-4} +starlight({ + expressiveCode: { + styleOverrides: { borderRadius: '0.5rem' }, + }, +}); +``` + +Wenn du Expressive Code deaktivieren möchtest, setze in deiner Starlight-Konfiguration `expressiveCode: false`: + +```js ins={2} +starlight({ + expressiveCode: false, +}); +``` + +Zusätzlich zu den standardmäßigen Expressive Code-Optionen kannst du in deiner `expressiveCode`-Konfiguration auch die folgenden Starlight-spezifischen Eigenschaften festlegen, um das Designverhalten für deine Codeblöcke weiter anzupassen: + +#### `themes` + +**Typ:** `Array<string | ThemeObject | ExpressiveCodeTheme>` +**Standard:** `['starlight-dark', 'starlight-light']` + +Lege die Designs fest, die zum Stylen von Codeblöcken verwendet werden. +Weitere Informationen zu den unterstützten Designformaten findest du in der [Expressive Code-Dokumentation zu Designs](https://expressive-code.com/guides/themes/). + +Starlight verwendet standardmäßig die dunkle und helle Variante von Sarah Drasners [Night Owl-Thema](https://github.com/sdras/night-owl-vscode-theme). + +Wenn du mindestens ein dunkles und ein helles Design angibst, wird Starlight das aktive Codeblock-Design automatisch mit dem aktuellen Website-Design synchron halten. +Konfiguriere dieses Verhalten mit der Option [`useStarlightDarkModeSwitch`](#usestarlightdarkmodeswitch). + +#### `useStarlightDarkModeSwitch` + +**Typ:** `boolean` +**Standard:** `true` + +Falls `true`, wechseln Codeblöcke automatisch zwischen hellen und dunklen Designs, wenn sich das Website-Design ändert. +Falls `false`, musst du manuell CSS hinzufügen, um das Wechseln zwischen mehreren Designs zu handhaben. + +:::note +Beim Festlegen von `themes` musst du mindestens ein dunkles und ein helles Design angeben, damit der Wechsel zum Starlight-Dunkelmodus funktioniert. +::: + +#### `useStarlightUiThemeColors` + +**Typ:** `boolean` +**Standard:** `true` wenn `themes` nicht gesetzt ist, andernfalls `false` + +Falls `true`, werden Starlights CSS-Variablen für die Farben von Codeblock-UI-Elementen (Hintergründe, Schaltflächen, Schatten usw.) verwendet, die dem [Website-Farbdesign](/de/guides/css-and-tailwind/#themes) entsprechen. +Falls `false`, werden für diese Elemente die vom aktiven Syntaxhervorhebungs­design bereitgestellten Farben verwendet. + +:::note +Wenn du benutzerdefinierte Themes verwendest und dies auf `true` setzt, musst du mindestens ein dunkles und ein helles Theme bereitstellen, um den richtigen Farbkontrast zu gewährleisten. +::: + +### `pagefind` + +**Typ:** <code>boolean | <a href="#pagefindoptions">PagefindOptions</a></code> +**Standard:** `true` + +Konfiguriere den Standard-Site-Suchanbieter von Starlight [Pagefind](https://pagefind.app/). + +Setze diese Option auf `false`, um die Indizierung deiner Website mit Pagefind zu deaktivieren. +Dadurch wird auch die Standard-Suchoberfläche ausgeblendet, falls sie verwendet wird. + +Pagefind kann nicht aktiviert werden, wenn die Option [`prerender`](#prerender) auf `false` gesetzt ist. + +Setze `pagefind` auf ein Objekt, um den Pagefind-Suchclient zu konfigurieren: + +- Siehe [„Anpassen des Pagefind-Rankings (EN)“](https://pagefind.app/docs/ranking/) in der Pagefind-Dokumentation für weitere Details über die Verwendung der Option `pagefind.ranking`, um zu kontrollieren, wie die Rangfolge der Suchergebnisse berechnet wird +- Siehe [„Mehrere Websites durchsuchen (EN)“](https://pagefind.app/docs/multisite/) in der Pagefind-Dokumentation für weitere Informationen über die Verwendung der Option `pagefind.mergeIndex` zur Steuerung der Suche über mehrere Websites + +#### `PagefindOptions` + +```ts +interface PagefindOptions { + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + indexWeight?: number; + mergeIndex?: Array<{ + bundlePath: string; + indexWeight?: number; + basePath?: string; + baseUrl?: string; + mergeFilter?: Record<string, string | string[]>; + language?: string; + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + }>; +} +``` + +### `prerender` + +**Typ:** `boolean` +**Standard:** `true` + +Lege fest, ob Starlight-Seiten vorgerendert zu statischem HTML oder bei Bedarf von einem [SSR-Adapter](https://docs.astro.build/de/guides/on-demand-rendering/) gerendert werden sollen. + +Starlight-Seiten werden standardmäßig vorgerendert. +Wenn du einen SSR-Adapter verwendest und Starlight-Seiten bei Bedarf rendern möchtest, setze `prerender: false`. + +### `head` + +**Typ:** [`HeadConfig[]`](#headconfig) + +Füge zusätzliche Tags in den `<head>` deines Starlight-Projekts ein. +Kann nützlich sein, um Analytics und andere Skripte und Ressourcen von Drittanbietern hinzuzufügen. + +```js +starlight({ + head: [ + // Beispiel: Fathom Analytics Skript-Tag hinzufügen. + { + tag: 'script', + attrs: { + src: 'https://cdn.usefathom.com/script.js', + 'data-site': 'MY-FATHOM-ID', + defer: true, + }, + }, + ], +}); +``` + +Einträge in `head` werden direkt in HTML-Elemente umgewandelt und durchlaufen nicht Astros [script](https://docs.astro.build/de/guides/client-side-scripts/#script-bundling) oder [style](https://docs.astro.build/de/guides/styling/#styles-stile-in-astro) Verarbeitung. +Wenn du lokale Elemente wie Skripte, Stile oder Bilder importieren musst, [überschreibe die Komponente Head](/de/guides/overriding-components/#eine-integrierte-komponente-wiederverwenden). + +#### `HeadConfig` + +```ts +interface HeadConfig { + tag: string; + attrs?: Record<string, string | boolean | undefined>; + content?: string; +} +``` + +### `lastUpdated` + +**Typ:** `boolean` +**Standard:** `false` + +Legt fest, ob in der Fußzeile angezeigt werden soll, wann die Seite zuletzt aktualisiert wurde. + +Standardmäßig verwendet diese Funktion die Git-Historie deines Repositorys und kann auf einigen Bereitstellungs­plattformen, die [shallow clones](https://git-scm.com/docs/git-clone/de#git-clone---depthltTiefegt) durchführen, nicht genau sein. Eine Seite kann diese Einstellung oder das Git-basierte Datum mit dem [`lastUpdated` Frontmatter-Feld](/de/reference/frontmatter/#lastupdated) überschreiben. + +### `pagination` + +**Typ:** `boolean` +**Standard:** `true` + +Legt fest, ob die Fußzeile Links zur vorherigen und nächsten Seite enthalten soll. + +Eine Seite kann diese Einstellung oder den Linktext und/oder die URL mit Hilfe der Frontmatter-Felder [`prev`](/de/reference/frontmatter/#prev) und [`next`](/de/reference/frontmatter/#next) überschreiben. + +### `favicon` + +**Typ:** `string` +**Standard:** `'/favicon.svg'` + +Legt den Pfad des Standard-Favicons für deine Website fest. Dieses sollte sich im Verzeichnis `public/` befinden und eine gültige Symbol-Datei (`.ico`, `.gif`, `.jpg`, `.png` oder `.svg`) sein. + +```js +starlight({ + favicon: '/images/favicon.svg', +}), +``` + +Wenn du zusätzliche Varianten oder Fallback-Favicons festlegen musst, kannst du diese mit der Option [`head`](#head) Tags hinzufügen: + +```js +starlight({ + favicon: '/images/favicon.svg', + head: [ + // ICO-Favicon als Fallback für Safari hinzufügen + { + tag: 'link', + attrs: { + rel: 'icon', + href: '/images/favicon.ico', + sizes: '32x32', + }, + }, + ], +}); +``` + +### `titleDelimiter` + +**Typ:** `string` +**Standard:** `'|'` + +Legt das Trennzeichen zwischen Seitentitel und dem Titel der Website im `<title>`-Tag der Website fest, welches in den Browser-Tabs angezeigt wird. + +Standardmäßig hat jede Seite einen `<title>` von `Seiten-Titel | Websitename`. +Zum Beispiel heißt diese Seite „Konfigurations­referenz“ und diese Website heißt „Starlight“, also ist der `<titel>` für diese Seite „Konfigurations­referenz | Starlight“. + +### `disable404Route` + +**Typ:** `Boolean` +**Standard:** `false` + +Deaktiviert die Einspeisung von Starlights Standard [404-Seite](https://docs.astro.build/de/basics/astro-pages/#benutzerdefinierte-404-fehlerseite). Um eine eigene `src/pages/404.astro`-Route in deinem Projekt zu verwenden, setze diese Option auf `true`. + +### `routeMiddleware` + +**Typ:** `string | string[]` + +Gib Pfade zu Route-Middleware an, welche die Verarbeitung deiner Daten durch Starlight verändern kann. +Diese Dateipfade dürfen nicht mit [Astros Middleware](https://docs.astro.build/de/guides/middleware/) kollidieren. + +In der [Routendaten-Anleitung](/de/guides/route-data/#anpassen-der-routendaten) findest du weitere Informationen zur Erstellung von Route-Middleware. + +### `components` + +**Typ:** `Record<string, string>` + +Gib die Pfade zu den Komponenten an, um die Standard­implementierungen von Starlight zu ersetzen. + +```js +starlight({ + components: { + SocialLinks: './src/components/MySocialLinks.astro', + }, +}); +``` + +Siehe die [Referenz der Ersetzung von Komponenten](/de/reference/overrides/) für Details zu allen Komponenten, die du überschreiben kannst. + +### `plugins` + +**Typ:** [`StarlightPlugin[]`](/de/reference/plugins/#api-schnellreferenz) + +Erweitere Starlight mit eigenen Plugins. +Plugins nehmen Änderungen an deinem Projekt vor, um die Funktionen von Starlight zu verändern oder zu erweitern. + +Besuche das [Plugins Schaufenster](/de/resources/plugins/#plugins) um eine Liste der verfügbaren Plugins zu sehen. + +```js +starlight({ + plugins: [starlightPlugin()], +}); +``` + +Siehe die [Referenz für Plugins](/de/reference/plugins/) für Details zur Erstellung eigener Plugins. + +### `credits` + +**Typ:** `boolean` +**Standard:** `false` + +Aktiviere die Anzeige eines „Erstellt mit Starlight“-Links in der Fußzeile deiner Website. + +```js +starlight({ + credits: true, +}); +``` + +## Inhaltssammlungen konfigurieren + +Starlight nutzt Astro [Inhaltssammlungen](https://docs.astro.build/de/guides/content-collections/), um deine Inhalte zu laden. +Die Inhaltslader und Schemata von Starlight helfen dir dabei, die Sammlungen nach Bedarf zu konfigurieren. + +```js +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + // Optional: Die i18n-Sammlung wird verwendet, + // um die Benutzeroberfläche auf mehrsprachigen Websites zu übersetzen + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), +}; +``` + +### Inhaltslader + +Starlight exportiert die folgenden [Astro-Lader](https://docs.astro.build/de/reference/content-loader-reference/) aus dem Modul `@astrojs/starlight/loaders`, um die Konfiguration von Inhaltssammlungen zu vereinfachen. + +#### `docsLoader()` + +Der `docsLoader()` lädt lokale Markdown-, MDX- und Markdoc-Dateien aus dem Verzeichnis `src/content/docs/`. +Dateinamen, die mit einem Unterstrich (`_`) beginnen, werden ignoriert. + +##### Import + +```js +import { docsLoader } from '@astrojs/starlight/loaders'; +``` + +##### Optionen + +###### `generateId()` + +**Typ:** `({ entry: string; base: URL; data: Record<string, unknown> }) => string` + +Standardmäßig werden mit `docsLoader()` erstellte Seiten so verarbeitet, dass Sonderzeichen entfernt und Dateinamen in Kleinbuchstaben umgewandelt werden. +Wenn du diese Standardeinstellung überschreiben möchtest, gib deine eigene `generateId()`-Funktion an. + +Dies kann beispielsweise nützlich sein, um Sonderzeichen zu erhalten, die sonst entfernt würden. +Standardmäßig würde `Beispiel.Datei.md` unter `/beispieldatei` bereitgestellt werden. +Wenn du die Datei unter `/Beispiel.Datei` bereitstellen möchtest, kannst du dies tun, indem du eine benutzerdefinierte `generateId()`-Funktion definierst: + +```js +docsLoader({ + // Entferne die Erweiterung `.md` oder `.mdx`, + // aber verarbeite ansonsten die Dateinamen nicht. + generateId: ({ entry }) => entry.split('.').slice(0, -1).join('.'), +}), +``` + +Weitere Infos findest du unter [`generateId()` in der Astro-Dokumentation](https://docs.astro.build/de/reference/content-loader-reference/#generateid). + +#### `i18nLoader()` + +`i18nLoader()` lädt lokale JSON- und YAML-Dateien aus dem Verzeichnis `src/content/i18n/`. +Dateinamen, die mit einem Unterstrich (`_`) beginnen, werden ignoriert. + +##### Import + +```js +import { i18nLoader } from '@astrojs/starlight/loaders'; +``` + +##### Optionen + +Derzeit gibt es keine Optionen zum Konfigurieren von `i18nLoader()`. + +### Schemata + +Starlight stellt die folgenden [Inhaltssammlungs­schemata](https://docs.astro.build/de/guides/content-collections/#defining-the-collection-schema) aus dem Modul `@astrojs/starlight/schema` zur Verfügung. +Diese Schemata müssen für die Sammlungen `docs` und `i18n` verwendet werden, von denen Starlight abhängt. + +#### `docsSchema()` + +`docsSchema()` analysiert die Frontmatter für alle deine Inhalte in der Sammlung `docs`. + +##### Import + +```js +import { docsSchema } from '@astrojs/starlight/schema'; +``` + +##### Optionen + +###### `extend` + +**Typ:** Zod-Schema oder Funktion, die ein Zod-Schema zurückgibt +**Standard:** `z.object({})` + +Erweitere das Frontmatter-Schema von Starlight um zusätzliche Felder. +Weitere Infos zur Verwendung der Option `extend` findest du unter [„Frontmatter-Schema anpassen“](/de/reference/frontmatter/#frontmatter-schema-anpassen). + +#### `i18nSchema()` + +`i18nSchema()` analysiert alle Dateien, die Daten enthalten, in der `i18n`-Sammlung. + +##### Import + +```js +import { i18nSchema } from '@astrojs/starlight/schema'; +``` + +##### Optionen + +###### `extend` + +**Typ:** Zod-Objekt +**Standard:** `z.object({})` + +Erweitere das i18n-Schema von Starlight um zusätzliche Felder. +Weitere Infos zur Verwendung der Option `extend` findest du unter [„Übersetzungsschema erweitern“](/de/guides/i18n/#übersetzungsschema-erweitern). diff --git a/docs/src/content/docs/de/reference/frontmatter.md b/docs/src/content/docs/de/reference/frontmatter.md new file mode 100644 index 00000000000..0fc2a5b502f --- /dev/null +++ b/docs/src/content/docs/de/reference/frontmatter.md @@ -0,0 +1,475 @@ +--- +title: Frontmatter Referenz +description: Ein Überblick über die von Starlight unterstützten Standard-Frontmatter-Felder. +sidebar: + label: Frontmatter +--- + +Du kannst einzelne Markdown- und MDX-Seiten in Starlight anpassen, indem du Werte in deren Frontmatter setzt. Zum Beispiel könnte eine normale Seite die Felder `title` und `description` setzen: + +```md {3-4} +--- +# src/content/docs/example.md +title: Über dieses Projekt +description: Erfahre mehr über das Projekt, an dem ich gerade arbeite. +--- + +Willkommen auf der Info-Seite! +``` + +## Frontmatter-Felder + +### `title` (erforderlich) + +**Typ:** `string` + +Du musst für jede Seite einen Titel angeben. Dieser wird oben auf der Seite, in Browser-Tabs und in den Seiten-Metadaten angezeigt. + +### `description` + +**Typ:** `string` + +Die Seitenbeschreibung wird für die Metadaten der Seite verwendet und wird von Suchmaschinen und in der Vorschau von sozialen Medien angezeigt. + +### `slug` + +**Typ**: `string` + +Setzt den Slug der Seite außer Kraft. Siehe [„Benutzerdefinierte IDs definieren“](https://docs.astro.build/de/guides/content-collections/#defining-custom-ids) in der Astro-Dokumentation für weitere Details. + +### `editUrl` + +**Typ:** `string | boolean` + +Überschreibt die [globale `editLink`-Konfiguration](/de/reference/configuration/#editlink). Setze die Konfiguration auf `false`, um den Link `Seite bearbeiten` für eine bestimmte Seite zu deaktivieren oder gibt eine alternative URL an, unter welcher der Inhalt dieser Seite bearbeitet werden kann. + +### `head` + +**Typ:** [`HeadConfig[]`](/de/reference/configuration/#headconfig) + +Du kannst zusätzliche Tags zum `<head>` deiner Seite hinzufügen, indem du das Feld `head` Frontmatter verwendest. Dies bedeutet, dass du benutzerdefinierte Stile, Metadaten oder andere Tags zu einer einzelnen Seite hinzufügen kannst. Ähnlich wie bei der [globalen `head` Option](/de/reference/configuration/#head). + +```md +--- +# src/content/docs/example.md +title: Über uns +head: + # Benutze einen eigenen <title> Tag + - tag: title + content: Benutzerdefinierter "Über uns"-Titel +--- +``` + +### `tableOfContents` + +**Typ:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` + +Überschreibt die [globale `tableOfContents`-Konfiguration](/de/reference/configuration/#tableofcontents). +Passe die einzuschließenden Überschriftsebenen an oder setze sie auf `false`, um das Inhaltsverzeichnis auf dieser Seite auszublenden. + +```md +--- +# src/content/docs/example.md +title: Seite mit nur H2s im Inhaltsverzeichnis +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 2 +--- +``` + +```md +--- +# src/content/docs/example.md +title: Seite ohne Inhaltsverzeichnis +tableOfContents: false +--- +``` + +### `template` + +**Typ:** `'doc' | 'splash'` +**Standard:** `'doc'` + +Legt die Layoutvorlage für diese Seite fest. +Seiten verwenden standardmäßig das `'doc'`-Layout. +Setze den Typen auf `'splash'`, um ein breiteres Layout ohne Seitenleisten zu verwenden, welches spezifisch für Startseiten entwickelt wurde. + +### `hero` + +**Typ:** [`HeroConfig`](#heroconfig) + +Fügt eine Hero-Komponente oben auf der Seite ein. Kann sehr gut mit `template: splash` kombiniert werden. + +Zum Beispiel zeigt diese Konfiguration einige übliche Optionen, einschließlich des Ladens eines Bildes aus deinem Repository. + +```md +--- +# src/content/docs/example.md +title: Meine Website +template: splash +hero: + title: 'Mein Projekt: Schnell ins All' + tagline: Bringe deine Wertgegenstände im Handumdrehen auf den Mond und wieder zurück. + image: + alt: Ein glitzerndes, leuchtend farbiges Logo + file: ~/assets/logo.png + actions: + - text: Erzähl mir mehr + link: /getting-started/ + icon: right-arrow + - text: Schau mal auf GitHub vorbei + link: https://github.com/astronaut/mein-projekt + icon: external + variant: minimal + attrs: + rel: me +--- +``` + +Du kannst verschiedene Versionen der Hero-Komponente im hellen und dunklen Modus anzeigen. + +```md +--- +# src/content/docs/example.md +hero: + image: + alt: Ein glitzerndes, farbenfrohes Logo + dark: ~/assets/logo-dark.png + light: ~/assets/logo-light.png +--- +``` + +#### `HeroConfig` + +```ts +interface HeroConfig { + title?: string; + tagline?: string; + image?: + | { + // Relativer Pfad zu einem Bild in deinem Repository. + file: string; + // Alt-Text, um das Bild für unterstützende Technologien zugänglich zu machen + alt?: string; + } + | { + // Relativer Pfad zu einem Bild in deinem Repository, das für den dunklen Modus verwendet werden soll. + dark: string; + // Relativer Pfad zu einem Bild in deinem Repository, das für den hellen Modus verwendet werden soll. + light: string; + // Alt-Text, um das Bild für unterstützende Technologien zugänglich zu machen + alt?: string; + } + | { + // HTML, welches im Bild-Slot verwendet werden soll. + // Dies kann ein benutzerdefinierter `<img>`-Tag oder ein Inline-`<svg>` sein. + html: string; + }; + actions?: Array<{ + text: string; + link: string; + variant?: 'primary' | 'secondary' | 'minimal'; + icon?: string; + attrs?: Record<string, string | number | boolean>; + }>; +} +``` + +### `banner` + +**Typ:** `{ content: string }` + +Zeigt ein Ankündigungsbanner oben auf dieser Seite an. + +Der Wert `content` kann HTML für Links oder andere Inhalte enthalten. +Auf dieser Seite wird beispielsweise ein Banner mit einem Link zu `example.com` angezeigt. + +```md +--- +# src/content/docs/example.md +title: Seite mit Banner +banner: + content: | + Wir haben gerade etwas Cooles angefangen! + <a href="https://example.com">Jetzt besuchen</a> +--- +``` + +### `lastUpdated` + +**Typ:** `Date | boolean` + +Überschreibt die [globale Option `lastUpdated`](/de/reference/configuration/#lastupdated). Wenn ein Datum angegeben wird, muss es ein gültiger [YAML-Zeitstempel](https://yaml.org/type/timestamp.html) sein und überschreibt somit das im Git-Verlauf für diese Seite gespeicherte Datum. + +```md +--- +# src/content/docs/example.md +title: Seite mit einem benutzerdefinierten Datum der letzten Aktualisierung +lastUpdated: 2022-08-09 +--- +``` + +### `prev` + +**Typ:** `boolean | string | { link?: string; label?: string }` + +Überschreibt die [globale Option `pagination`](/de/reference/configuration/#pagination). Wenn eine Zeichenkette angegeben wird, wird der generierte Linktext ersetzt und wenn ein Objekt angegeben wird, werden sowohl der Link als auch der Text überschrieben. + +```md +--- +# src/content/docs/example.md +# Versteckt den Link zur vorherigen Seite +prev: false +--- +``` + +```md +--- +# src/content/docs/example.md +# Überschreibe den Linktext der vorherigen Seite +prev: Fortsetzung des Tutorials +--- +``` + +```md +--- +# src/content/docs/example.md +# Überschreibe sowohl den Link zur vorherigen Seite als auch den Text +prev: + link: /unverwandte-seite/ + label: Schau dir diese andere Seite an +--- +``` + +### `next` + +**Typ:** `boolean | string | { link?: string; label?: string }` + +Dasselbe wie [`prev`](#prev), aber für den Link zur nächsten Seite. + +```md +--- +# src/content/docs/example.md +# Versteckt den Link zur nächsten Seite +next: false +--- +``` + +### `pagefind` + +**Typ:** `boolean` +**Standard:** `true` + +Legt fest, ob diese Seite in den [Pagefind](https://pagefind.app/)-Suchindex aufgenommen werden soll. Setze das Feld auf `false`, um eine Seite von den Suchergebnissen auszuschließen: + +```md +--- +# src/content/docs/example.md +# Diese Seite aus dem Suchindex ausblenden +pagefind: false +--- +``` + +### `draft` + +**Typ:** `boolean` +**Standard:** `false` + +Legt fest, ob diese Seite als Entwurf betrachtet werden soll und nicht in [Produktions-Builds](https://docs.astro.build/de/reference/cli-reference/#astro-build). Setze die Eigenschaft auf `true`, um eine Seite als Entwurf zu markieren und sie nur während der Entwicklung sichtbar zu machen. + +```md +--- +# src/content/docs/example.md +# Diese Seite von den Produktions-Builds ausschließen +draft: true +--- +``` + +Da Entwurfsseiten nicht in die Build-Ausgabe aufgenommen werden, kannst du keine Entwurfsseiten direkt mit [Slugs](/de/guides/sidebar/#interne-links) zu deiner Seitenleisten­konfiguration hinzufügen. +Entwurfsseiten in Verzeichnissen, die für [autogenerierte Seitenleisten-Gruppen](/de/guides/sidebar/#automatisch-generierte-gruppen) verwendet werden, werden bei Produktions-Builds automatisch ausgeschlossen. + +### `sidebar` + +**Typ:** [`SidebarConfig`](#sidebarconfig) + +Steuert, wie diese Seite in der [Seitenleiste](/de/reference/configuration/#sidebar) angezeigt wird, wenn eine automatisch generierte Linkgruppe verwendet wird. + +#### `SidebarConfig` + +```ts +interface SidebarConfig { + label?: string; + order?: number; + hidden?: boolean; + badge?: string | BadgeConfig; + attrs?: Record<string, string | number | boolean | undefined>; +} +``` + +#### `label` + +**Typ:** `string` +**Standard:** der Seitentitel ([`title`](#title-erforderlich)) + +Legt die Bezeichnung für diese Seite in der Seitenleiste fest, wenn sie in einer automatisch generierten Linkgruppe angezeigt wird. + +```md +--- +# src/content/docs/example.md +title: Über dieses Projekt +sidebar: + label: Infos +--- +``` + +#### `order` + +**Typ:** `number` + +Steuere die Reihenfolge dieser Seite beim Sortieren einer automatisch erstellten Gruppe von Links. +Niedrigere Nummern werden in der Linkgruppe weiter oben angezeigt. + +```md +--- +# src/content/docs/example.md +title: Erste Seite +sidebar: + order: 1 +--- +``` + +#### `hidden` + +**Typ:** `boolean` +**Standard:** `false` + +Verhindert, dass diese Seite in eine automatisch generierte Seitenleistengruppe aufgenommen wird. + +```md +--- +# src/content/docs/example.md +title: Versteckte Seite +sidebar: + hidden: true +--- +``` + +#### `badge` + +**Typ:** <code>string | <a href="/de/reference/configuration/#badgeconfig">BadgeConfig</a></code> + +Füge der Seite in der Seitenleiste ein Abzeichen hinzu, wenn es in einer automatisch generierten Gruppe von Links angezeigt wird. +Bei Verwendung einer Zeichenkette wird das Abzeichen mit einer Standard-Akzentfarbe angezeigt. +Optional kann ein [`BadgeConfig` Objekt](/de/reference/configuration/#badgeconfig) mit den Feldern `text`, `variant` and `class` übergeben werden, um das Abzeichen anzupassen. + +```md +--- +# src/content/docs/example.md +title: Seite mit einem Badge +sidebar: + # Verwendet die Standardvariante, die der Akzentfarbe deiner Website entspricht + badge: Neu +--- +``` + +```md +--- +# src/content/docs/example.md +title: Seite mit einem Abzeichen +sidebar: + badge: + text: Experimentell + variant: caution +--- +``` + +#### `attrs` + +**Typ:** `Record<string, string | number | boolean | undefined>` + +HTML-Attribute, die dem Seitenlink in der Seitenleiste hinzugefügt werden, wenn er in einer automatisch generierten Gruppe von Links angezeigt wird. +Wenn [`autogenerate.attrs`](/de/guides/sidebar/#benutzerdefinierte-html-attribute-für-automatisch-generierte-links) für die automatisch generierte Gruppe, zu welcher diese Seite gehört, festgelegt ist, werden Frontmatter-Attribute mit den Gruppenattributen zusammengeführt. + +```md +--- +# src/content/docs/example.md +title: Seite im neuen Tab öffnen +sidebar: + # Dies öffnet den Link in einem neuen Tab + attrs: + target: _blank +--- +``` + +## Frontmatter-Schema anpassen + +Das Frontmatter-Schema für die Starlight-Inhaltssammlung `docs` wird in `src/content.config.ts` mit dem `docsSchema()`-Helper konfiguriert: + +```ts {4,7} +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; +``` + +Mehr über Schemata für Inhaltssammlungen erfährst du in [„Definieren eines Sammelschemas“](https://docs.astro.build/de/guides/content-collections/#defining-the-collection-schema) in der Astro-Dokumentation. + +`docsSchema()` nimmt die folgenden Optionen an: + +### `extend` + +**Typ:** Zod-Schema oder Funktion, die ein Zod-Schema zurückgibt +**Standard:** `z.object({})` + +Erweitere das Schema von Starlight um zusätzliche Felder, indem du `extend` in den `docsSchema()` Optionen setzt. +Der Wert sollte ein [Zod-Schema](https://docs.astro.build/de/guides/content-collections/#datentypen-mit-zod-definieren) sein. + +Im folgenden Beispiel geben wir einen strengeren Typ für `description` an, um es zur Pflicht zu machen und fügen ein neues optionales Feld `category` hinzu: + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: z.object({ + // Mache ein eingebautes Feld erforderlich statt optional. + description: z.string(), + // Füge dem Schema ein neues Feld hinzu. + category: z.enum(['tutorial', 'guide', 'reference']).optional(), + }), + }), + }), +}; +``` + +Um die Vorteile der [Astro `image()`-Hilfe](https://docs.astro.build/de/guides/images/#bilder-in-inhaltssammlungen) zu nutzen, verwende eine Funktion, die deine Schemaerweiterung zurückgibt: + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: ({ image }) => { + return z.object({ + // Füge ein Feld hinzu, das auf ein lokales Bild aufgelöst werden muss. + cover: image(), + }); + }, + }), + }), +}; +``` diff --git a/docs/src/content/docs/de/reference/icons.mdx b/docs/src/content/docs/de/reference/icons.mdx new file mode 100644 index 00000000000..0bd3fabc175 --- /dev/null +++ b/docs/src/content/docs/de/reference/icons.mdx @@ -0,0 +1,34 @@ +--- +title: Symbole Referenz +description: Eine Übersicht über alle in Starlight verfügbaren Symbole. +sidebar: + label: Symbole +--- + +Starlight bietet eine Reihe von eingebauten Symbolen, die du mit Hilfe der Komponente `<Icon>` in deinem Inhalt anzeigen kannst. + +## Symbole verwenden + +Symbole können mit der Komponente [`<Icon>`](/de/components/icons/) angezeigt werden. +Sie werden auch häufig in anderen Komponenten verwendet, wie [Karten](/de/components/cards/) oder Umgebungen wie [Hero-Komponenten](/de/reference/frontmatter/#hero). + +## `StarlightIcon`-Typ + +Verwende den TypeScript-Typ `StarlightIcon`, um die Namen von [Starlights eingebauten Symbolen](#alle-symbole) zu referenzieren. + +```ts {2} /icon: (StarlightIcon)/ +// src/icon.ts +import type { StarlightIcon } from '@astrojs/starlight/types'; + +function getIconLabel(icon: StarlightIcon) { + // … +} +``` + +## Alle Symbole + +Nachstehend findest du eine Liste aller verfügbaren Symbole mit den zugehörigen Namen. Klicke auf ein Symbol, um den Namen in deine Zwischenablage zu kopieren. + +import IconsList from '~/components/icons-list.astro'; + +<IconsList labels={{ copied: 'Kopiert!' }} /> diff --git a/docs/src/content/docs/de/reference/overrides.md b/docs/src/content/docs/de/reference/overrides.md new file mode 100644 index 00000000000..0132514559c --- /dev/null +++ b/docs/src/content/docs/de/reference/overrides.md @@ -0,0 +1,265 @@ +--- +title: Ersetzung von Komponenten Referenz +description: Ein Überblick über die Komponenten und Komponenten­eigenschaften, die von Starlight Ersetzungen unterstützt werden. +tableOfContents: + maxHeadingLevel: 4 +sidebar: + label: Ersetzung von Komponenten +--- + +Du kannst Starlights eingebaute Komponenten überschreiben, indem du Pfade zu Ersatzkomponenten in Starlights [`components`](/de/reference/configuration/#components)-Konfigurations­option angibst. +Diese Seite listet alle Komponenten auf, die überschrieben werden können, und verweist auf ihre Standard­implementierungen auf GitHub. + +Erfahre mehr in der [Anleitung zum Überschreiben von Komponenten](/de/guides/overriding-components/). + +--- + +## Komponenten + +### Head + +Diese Komponenten werden innerhalb des `<head>`-Elements jeder Seite gerendert. +Sie sollten nur [innerhalb von `<head>` erlaubte Elemente](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head#see_also) enthalten. + +#### `Head` + +**Standardkomponente:** [`Head.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Head.astro) + +Diese Komponente wird innerhalb des `<head>` einer jeden Seite gerendert. + +Überschreibe diese Komponente nur, wenn es unbedingt notwendig ist. +Bevorzuge die [Konfigurationsoption `head`](/de/reference/configuration/#head), das [Frontmatter-Feld `head`](/de/reference/frontmatter/#head) oder eine [Routendaten-Middleware](/de/guides/route-data/#anpassen-der-routendaten), um die von der Standardkomponente dargestellten Routendaten nach Möglichkeit anzupassen. + +#### `ThemeProvider` + +**Standardkomponente:** [`ThemeProvider.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeProvider.astro) + +Diese Komponente wird innerhalb von `<head>` gerendert und richtet die Unterstützung für dunkle/helle Themen ein. +Die Standard-Implementierung enthält ein Inline-Skript und ein `<template>`, welches vom Skript in [`<ThemeSelect />`](#themeselect) verwendet wird. + +--- + +### Barrierefreiheit + +#### `SkipLink` + +**Standardkomponente:** [`SkipLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SkipLink.astro) + +Diese Komponente wird als erstes Element innerhalb von `<body>` dargestellt und verweist aus Gründen der Barrierefreiheit auf den Hauptinhalt der Seite. +Die Standard­implementierung ist ausgeblendet, bis ein Benutzer sie durch Tabulatorbewegungen mit der Tastatur aktiviert. + +--- + +### Layout + +Diese Komponenten sind für das Layout der Starlight-Komponenten und die Verwaltung von Ansichten über verschiedene Haltepunkte hinweg verantwortlich. +Das Überschreiben dieser Komponenten ist mit erheblicher Komplexität verbunden. +Wenn möglich, bevorzuge das Überschreiben einer Komponente auf einer niedrigeren Ebene. + +#### `PageFrame` + +**Standardkomponente:** [`PageFrame.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageFrame.astro) +**Benannte Slots:** `header`, `sidebar` + +Diese Layout-Komponente beinhaltet den größten Teil des Seiteninhalts. +Die Standard­implementierung konfiguriert das Kopfzeilen-Seitennavigation-Haupt-Layout und beinhaltet `header` und `sidebar` benannte Slots zusammen mit einem Standard-Slot für den Hauptinhalt. +Sie rendert auch [`<MobileMenuToggle />`](#mobilemenutoggle), um das Umschalten der Seitenleisten­navigation auf kleinen (mobilen) Viewports zu unterstützen. + +#### `MobileMenuToggle` + +**Standardkomponente:** [`MobileMenuToggle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuToggle.astro) + +Diese Komponente wird innerhalb von [`<PageFrame>`](#pageframe) gerendert und ist für das Umschalten der Seitenleisten­navigation auf kleinen (mobilen) Viewports verantwortlich. + +#### `TwoColumnContent` + +**Standardkomponente:** [`TwoColumnContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TwoColumnContent.astro) +**Benannter Slot:** `right-sidebar` + +Dies ist die Layout-Komponente, welche die Hauptinhaltsspalte und die rechte Seitenleiste (Inhaltsverzeichnis) beinhaltet. +Die Standard­implementierung behandelt den Wechsel zwischen einem einspaltigen Layout mit kleinem Sichtfeld und einem zweispaltigen Layout mit größerem Sichtfeld. + +--- + +### Kopfzeile + +Diese Komponenten stellen die obere Navigationsleiste von Starlight dar. + +#### `Header` + +**Standardkomponente:** [`Header.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Header.astro) + +Dies ist eine Kopfzielen-Komponente, welche oben auf jeder Seite angezeigt wird. +Die Standard­implementierung zeigt [`<SiteTitle />`](#sitetitle), [`<Search />`](#search), [`<SocialIcons />`](#socialicons), [`<ThemeSelect />`](#themeselect), und [`<LanguageSelect />`](#languageselect). + +#### `SiteTitle` + +**Standardkomponente:** [`SiteTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SiteTitle.astro) + +Die Komponente wird die am Anfang des Website-Headers gerendert, um den Titel der Website darzustellen. +Die Standard­implementierung enthält die Logik für die Darstellung von Logos, die in der Starlight-Konfiguration definiert sind. + +#### `Search` + +**Standardkomponente:** [`Search.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Search.astro) + +Diese Komponente wird verwendet, um Starlights Suchoberfläche darzustellen. +Die Standard­implementierung enthält die Schaltfläche in der Kopfzeile und den Code für die Anzeige eines Suchmodals, wenn darauf geklickt wird, und das Laden von [Pagefinds UI](https://pagefind.app/). + +Wenn [`pagefind`](/de/reference/configuration/#pagefind) deaktiviert ist, wird die Standard-Suchkomponente nicht angezeigt. +Wenn du jedoch `Search` überschreibst, wird deine benutzerdefinierte Komponente immer angezeigt, auch wenn die Konfigurations­option `pagefind` auf `false` gesetzt ist. +So kannst du eine Benutzeroberfläche für alternative Suchanbieter hinzufügen, wenn du Pagefind deaktivierst. + +#### `SocialIcons` + +**Standardkomponente:** [`SocialIcons.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SocialIcons.astro) + +Diese Komponente wird in der Kopfzeile der Website gerendert und enthält Symbol-Links zu sozialen Netzwerken. +Die Standard­implementierung verwendet die Option [`social`](/de/reference/configuration/#social) in der Starlight-Konfiguration, um Symbole und Links darzustellen. + +#### `ThemeSelect` + +**Standardkomponente:** [`ThemeSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeSelect.astro) + +Diese Komponente wird in der Kopfzeile der Website gerendert und ermöglicht es den Benutzern, ihr bevorzugtes Farbschema auszuwählen. + +#### `LanguageSelect` + +**Standardkomponente:** [`LanguageSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LanguageSelect.astro) + +Die Komponente wird in der Kopfzeile der Website angezeigt und ermöglicht es den Nutzern, die Sprache auszuwählen. + +--- + +### Globale Seitenleiste + +Die globale Seitenleiste von Starlight enthält die Hauptnavigation der Website. +Bei schmalen Ansichtsfenstern ist diese hinter einem Dropdown-Menü versteckt. + +#### `Sidebar` + +**Standardkomponente:** [`Sidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Sidebar.astro) + +Die Komponente wird die vor dem Seiteninhalt gerendert und enthält eine globale Navigation. +Die Standard­implementierung wird als Seitenleiste in ausreichend breiten Ansichtsfenstern und innerhalb eines Dropdown-Menüs in kleinen (mobilen) Ansichtsfenstern angezeigt. +Sie rendert auch [`<MobileMenuFooter />`](#mobilemenufooter), um zusätzliche Elemente innerhalb des mobilen Menüs anzuzeigen. + +#### `MobileMenuFooter` + +**Standardkomponente:** [`MobileMenuFooter.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuFooter.astro) + +Diese Komponente wird die am unteren Ende des mobilen Dropdown-Menüs gerendert. +Die Standard­implementierung rendert [`<ThemeSelect />`](#themeselect) und [`<LanguageSelect />`](#languageselect). + +--- + +### Seitenleiste des Inhalts + +Die Seitenleiste von Starlight ist für die Anzeige eines Inhalts­verzeichnisses verantwortlich, welches die Untertitel der aktuellen Seite anzeigt. +Bei schmalen Ansichtsfenstern wird diese Leiste zu einem Dropdown-Menü. + +#### `PageSidebar` + +**Standardkomponente:** [`PageSidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageSidebar.astro) + +Diese Komponente wird die vor dem Inhalt der Hauptseite gerendert, um ein Inhaltsverzeichnis anzuzeigen. +Die Standard­implementierung rendert [`<TableOfContents />`](#tableofcontents) und [`<MobileTableOfContents />`](#mobiletableofcontents). + +#### `TableOfContents` + +**Standardkomponente:** [`TableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TableOfContents.astro) + +Eine Komponente zur Darstellung des Inhalts­verzeichnisses der aktuellen Seite in breiteren Ansichtsfenstern. + +#### `MobileTableOfContents` + +**Standardkomponente:** [`MobileTableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileTableOfContents.astro) + +Diese Komponete zeigt das Inhaltsverzeichnis der aktuellen Seite auf kleinen (mobilen) Bildschirmen an. + +--- + +### Inhalt + +Folgende Komponenten werden in der Hauptspalte des Seiteninhalts wiedergegeben. + +#### `Banner` + +**Standardkomponente:** [`Banner.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Banner.astro) + +Diese Bannerkomponente wird oben auf jeder Seite angezeigt. +Die Standard-Implementierung verwendet den [`banner`](/de/reference/frontmatter/#banner)-Frontmatter-Wert der Seite, um zu entscheiden, ob sie gerendert wird oder nicht. + +#### `ContentPanel` + +**Standardkomponente:** [`ContentPanel.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ContentPanel.astro) + +Diese Layout-Komponente beinhaltet Abschnitte der Hauptinhaltsspalte. + +#### `PageTitle` + +**Standardkomponente:** [`PageTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageTitle.astro) + +Eine Komponente, welche das `<h1>`-Element für die aktuelle Seite enthält. + +Implementierungen sollten sicherstellen, dass sie `id="_top"` auf dem `<h1>` Element wie in der Standard­implementierung setzen. + +#### `DraftContentNotice` + +**Standardkomponente:** [`DraftContentNotice.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/DraftContentNotice.astro) + +Hinweis, der den Nutzern während der Entwicklung angezeigt wird, wenn die aktuelle Seite als Entwurf markiert ist. + +#### `FallbackContentNotice` + +**Standardkomponente:** [`FallbackContentNotice.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/FallbackContentNotice.astro) + +Ein Hinweis, welcher den Benutzern auf der Seite angezeigt wird, für die keine Übersetzung in der aktuellen Sprache verfügbar ist. +Wird nur auf mehrsprachigen Websites verwendet. + +#### `Hero` + +**Standardkomponente:** [`Hero.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Hero.astro) + +Diese Komponente wird am oberen Rand der Seite angezeigt, wenn [`hero`](/de/reference/frontmatter/#hero) in frontmatter eingestellt ist. +Die Standard­implementierung zeigt einen großen Titel, eine Tagline und Call-to-Action-Links neben einem optionalen Bild. + +#### `MarkdownContent` + +**Standardkomponente:** [`MarkdownContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MarkdownContent.astro) + +Die Kompoente wird um den Hauptinhalt jeder Seite gerendert. +Die Standard­implementierung richtet grundlegende Stile ein, die auf Markdown-Inhalte angewendet werden. + +Die Markdown-Inhaltsstile werden auch in der Datei `@astrojs/starlight/style/markdown.css` veröffentlicht und auf die CSS-Klasse `.sl-markdown-content` bezogen. + +--- + +### Fußzeile + +Diese Komponenten werden am unteren Ende der Hauptspalte des Seiteninhalts dargestellt. + +#### `Footer` + +**Standardkomponente:** [`Footer.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Footer.astro) + +Diese Fußzeile-Komponente wird am unteren Rand jeder Seite angezeigt. +Die Standard­implementierung zeigt [`<LastUpdated />`](#lastupdated), [`<Pagination />`](#pagination), und [`<EditLink />`](#editlink). + +#### `LastUpdated` + +**Standardkomponente:** [`LastUpdated.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LastUpdated.astro) + +Eine Komponente, die in der Fußzeile der Seite gerendert wird, um das zuletzt aktualisierte Datum anzuzeigen. + +#### `EditLink` + +**Standardkomponente:** [`EditLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/EditLink.astro) + +Die Komponente wird in der Fußzeile der Seite gerendert, um einen Link anzuzeigen, über den die Seite bearbeitet werden kann. + +#### `Pagination` + +**Standardkomponente:** [`Pagination.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Pagination.astro) + +Diese Komponente wird in der Fußzeile der Seite gerendert, um Navigationspfeile zwischen vorherigen/nächsten Seiten anzuzeigen. diff --git a/docs/src/content/docs/de/reference/plugins.md b/docs/src/content/docs/de/reference/plugins.md new file mode 100644 index 00000000000..6201a519d2c --- /dev/null +++ b/docs/src/content/docs/de/reference/plugins.md @@ -0,0 +1,377 @@ +--- +title: Plugins Referenz +description: Ein Überblick über die Starlight-Plugin-API. +tableOfContents: + maxHeadingLevel: 4 +sidebar: + label: Plugins +--- + +Starlight-Plugins können die Konfiguration, die Benutzeroberfläche und das Verhalten von Starlight anpassen und sind gleichzeitig einfach weiterzugeben und wiederzuverwenden. +Diese Referenzseite dokumentiert die API, auf die Plugins Zugriff haben. + +Erfahre mehr über die Verwendung eines Starlight-Plugins in der [Konfigurations­referenz](/de/reference/configuration/#plugins) oder besuche das [Plugins Schaufenster](/de/resources/plugins/#plugins), um eine Liste der verfügbaren Plugins zu sehen. + +## API-Schnellreferenz + +Ein Starlight-Plugin hat die folgende Form. +Siehe unten für Details zu den verschiedenen Eigenschaften und Hook-Parametern. + +<!-- prettier-ignore-start --> +```ts +interface StarlightPlugin { + name: string; + hooks: { + 'i18n:setup'?: (options: { + injectTranslations: ( + translations: Record<string, Record<string, string>> + ) => void; + }) => void | Promise<void>; + 'config:setup': (options: { + config: StarlightUserConfig; + updateConfig: (newConfig: StarlightUserConfig) => void; + addIntegration: (integration: AstroIntegration) => void; + addRouteMiddleware: (config: { entrypoint: string; order?: 'pre' | 'post' | 'default' }) => void; + astroConfig: AstroConfig; + command: 'dev' | 'build' | 'preview'; + isRestart: boolean; + logger: AstroIntegrationLogger; + useTranslations: (lang: string) => I18nT; + absolutePathToLang: (path: string) => string; + }) => void | Promise<void>; + }; +} +``` +<!-- prettier-ignore-end --> + +## `name` + +**Typ:** `string` + +Ein Plugin muss einen eindeutigen Namen angeben, der es beschreibt. Der Name wird verwendet, wenn [Logging-Nachrichten](#logger) sich auf dieses Plugin bezieht und kann von anderen Plugins verwendet werden, um das Vorhandensein dieses Plugins zu erkennen. + +## `hooks` + +Hooks sind Funktionen, die Starlight aufruft, um Plugin-Code zu bestimmten Zeiten auszuführen. + +Um den Typ der Argumente eines Hooks zu erhalten, verwende den Utility-Typ `HookParameters` und gib den Namen des Hooks an. +Im folgenden Beispiel wird der Parameter `options` so eingegeben, dass er mit den Argumenten übereinstimmt, die an den Hook `config:setup` übergeben werden: + +```ts +import type { HookParameters } from '@astrojs/starlight/types'; + +function configSetup(options: HookParameters['config:setup']) { + options.useTranslations('de'); +} +``` + +### `i18n:setup` + +Die Funktion zum Einrichten der Plugin-Internationalisierung wird beim Initialisieren von Starlight aufgerufen. +Der `i18n:setup`-Hook kann verwendet werden, um Übersetzungsstrings zu injizieren, damit ein Plugin verschiedene Locales unterstützen kann. +Diese Übersetzungen werden über [`useTranslations()`](#usetranslations) im `config:setup`-Hook und in UI-Komponenten über [`Astro.locals.t()`](/de/guides/i18n/#ui-übersetzungen-verwenden) verfügbar sein. + +Der `i18n:setup`-Hook wird mit den folgenden Optionen aufgerufen: + +#### `injectTranslations` + +**Typ:** `(translations: Record<string, Record<string, string>>) => void` + +Eine Callback-Funktion zum Hinzufügen oder Aktualisieren von Übersetzungsstrings, die in Starlights [Lokalisierungs-APIs](/de/guides/i18n/#ui-übersetzungen-verwenden) verwendet werden. + +Im folgenden Beispiel injiziert ein Plugin Übersetzungen für einen benutzerdefinierten UI-String mit dem Namen `myPlugin.doThing` für die Sprachumgebungen `en` und `fr`: + +```ts {6-13} /(injectTranslations)[^(]/ +// plugin.ts +export default { + name: 'plugin-use-translations', + hooks: { + 'i18n:setup'({ injectTranslations }) { + injectTranslations({ + en: { + 'myPlugin.doThing': 'Do the thing', + }, + fr: { + 'myPlugin.doThing': 'Faire le truc', + }, + }); + }, + }, +}; +``` + +Um die injizierten Übersetzungen in der Benutzeroberfläche deines Plugins zu verwenden, befolge die [„UI-Übersetzungen verwenden“-Anleitung](/de/guides/i18n/#ui-übersetzungen-verwenden). +Wenn du UI-Strings im Zusammenhang mit dem [`config:setup`](#configsetup)-Hook deines Plugins verwenden musst, kannst du den [`useTranslations()`](#usetranslations)-Callback verwenden. + +Die Typen für die injizierten Übersetzungsstrings eines Plugins werden im Projekt des Benutzers automatisch generiert, sind aber bei der Arbeit in der Codebasis deines Plugins noch nicht verfügbar. +Um das Objekt `locals.t` im Kontext deines Plugins zu typisieren, deklariere die folgenden globalen Namespaces in einer TypeScript-Deklarationsdatei: + +```ts +// env.d.ts +declare namespace App { + type StarlightLocals = import('@astrojs/starlight').StarlightLocals; + // Definiere das Objekt `locals.t` im Kontext eines Plugins. + interface Locals extends StarlightLocals {} +} + +declare namespace StarlightApp { + // Definiere die zusätzlichen Plugin-Übersetzungen in der `I18n`-Schnittstelle. + interface I18n { + 'myPlugin.doThing': string; + } +} +``` + +Du kannst die Typen für die Schnittstelle `StarlightApp.I18n` auch aus einer Quelldatei ableiten, wenn du ein Objekt hast, das deine Übersetzungen enthält. + +Nehmen wir zum Beispiel die folgende Quelldatei: + +```ts title="ui-strings.ts" +export const UIStrings = { + en: { 'myPlugin.doThing': 'Do the thing' }, + fr: { 'myPlugin.doThing': 'Faire le truc' }, +}; +``` + +Die folgende Deklaration würde die Typen aus den englischen Schlüsseln in der Quelldatei ableiten: + +```ts title="env.d.ts" +declare namespace StarlightApp { + type UIStrings = typeof import('./ui-strings').UIStrings.en; + interface I18n extends UIStrings {} +} +``` + +### `config:setup` + +Plugin-Konfiguration-Setup-Funktion, die aufgerufen wird, wenn Starlight initialisiert wird (während des [`astro:config:setup`](https://docs.astro.build/de/reference/integrations-reference/#astroconfigsetup) Integrations-Hooks). +Der `config:setup`-Hook kann verwendet werden, um die Starlight-Konfiguration zu aktualisieren oder Astro-Integrationen hinzuzufügen. + +Dieser Hook wird mit den folgenden Optionen aufgerufen: + +#### `config` + +**Typ:** `StarlightUserConfig` + +Eine schreibgeschützte Kopie der vom Benutzer bereitgestellten [Starlight-Konfiguration](/de/reference/configuration/). +Diese Konfiguration kann durch andere Plugins, die vor dem aktuellen Plugin konfiguriert wurden, aktualisiert worden sein. + +#### `updateConfig` + +**Typ:** `(newConfig: StarlightUserConfig) => void` + +Eine Callback-Funktion zur Aktualisierung der vom Benutzer bereitgestellten [Starlight-Konfiguration](/de/reference/configuration/). +Gib die Konfigurations­schlüssel der root-Ebene an, die du überschreiben möchtest. +Um verschachtelte Konfigurationswerte zu aktualisieren, musst du das gesamte verschachtelte Objekt bereitstellen. + +Um eine vorhandene Konfigurations­option zu erweitern, ohne sie außer Kraft zu setzen, wird der vorhandene Wert in den neuen Wert übertragen. +Im folgenden Beispiel wird ein neues [`social`](/de/reference/configuration/#social) Medienkonto zur bestehenden Konfiguration hinzugefügt, indem `config.social` in das neue `social`-Array übertragen wird: + +```ts {6-15} +// plugin.ts +export default { + name: 'add-twitter-plugin', + hooks: { + 'config:setup'({ config, updateConfig }) { + updateConfig({ + social: [ + ...config.social, + { + icon: 'twitter', + label: 'Twitter', + href: 'https://twitter.com/astrodotbuild', + }, + ], + }); + }, + }, +}; +``` + +#### `addIntegration` + +**Typ:** `(integration: AstroIntegration) => void` + +Eine Callback-Funktion zum Hinzufügen einer [Astro-Integration](https://docs.astro.build/de/reference/integrations-reference/), die vom Plugin benötigt wird. + +Im folgenden Beispiel prüft das Plugin zunächst, ob [Astros React-Integration](https://docs.astro.build/de/guides/integrations-guide/react/) konfiguriert ist, und fügt sie, falls nicht, mit `addIntegration()` hinzu: + +```ts {14} "addIntegration," +// plugin.ts +import react from '@astrojs/react'; + +export default { + name: 'plugin-using-react', + hooks: { + 'config:setup'({ addIntegration, astroConfig }) { + const isReactLoaded = astroConfig.integrations.find( + ({ name }) => name === '@astrojs/react' + ); + + // Füge die React-Integration nur hinzu, wenn sie nicht bereits geladen ist. + if (!isReactLoaded) { + addIntegration(react()); + } + }, + }, +}; +``` + +#### `addRouteMiddleware` + +**Typ:** `(config: { entrypoint: string; order?: 'pre' | 'post' | 'default'}) => void` + +Eine Callback-Funktion, um der Website einen [Routen-Middleware-Handler](/de/guides/route-data/) hinzuzufügen. + +Die Eigenschaft `entrypoint` muss ein Modulbezeichner für die Middleware-Datei deines Plugins sein, die einen `onRequest`-Handler exportiert. + +Im folgenden Beispiel fügt ein Plugin, das unter dem Namen `@example/starlight-plugin` veröffentlicht wurde, eine Route-Middleware über einen npm-Modul-Spezifizierer hinzu: + +```js {6-9} +// plugin.ts +export default { + name: '@example/starlight-plugin', + hooks: { + 'config:setup'({ addRouteMiddleware }) { + addRouteMiddleware({ + entrypoint: '@example/starlight-plugin/route-middleware', + }); + }, + }, +}; +``` + +##### Kontrolle der Ausführungs­reihenfolge + +Standardmäßig wird die Plugin-Middleware in der Reihenfolge ausgeführt, in der die Plugins hinzugefügt werden. + +Verwende die optionale Eigenschaft `order`, wenn du mehr Kontrolle darüber brauchst, wann deine Middleware läuft. +Setze `order: "pre"`, um vor der Middleware eines Benutzers zu laufen. +Setze `order: "post"`, um nach allen anderen Middlewares zu laufen. + +Wenn zwei Plugins Middleware mit demselben `order`-Wert hinzufügen, wird das zuerst hinzugefügte Plugin zuerst ausgeführt. + +#### `astroConfig` + +**Typ:** `AstroConfig` + +Eine schreibgeschützte Kopie der vom Benutzer bereitgestellten [Astro-Konfiguration](https://docs.astro.build/de/reference/configuration-reference/). + +#### `command` + +**Typ:** `'dev' | 'build' | 'preview'` + +Der Befehl, mit dem Starlight gestartet wird: + +- `dev` - Projekt wird mit `astro dev` ausgeführt +- `build` - Projekt wird mit `astro build` ausgeführt +- `preview` - Projekt wird mit `astro preview` ausgeführt + +#### `isRestart` + +**Typ:** `boolean` + +`false`, wenn der Dev-Server startet, `true`, wenn ein Reload ausgelöst wird. +Häufige Gründe für einen Neustart sind, dass ein Benutzer seine `astro.config.mjs` bearbeitet, während der Dev-Server läuft. + +#### `logger` + +**Typ:** `AstroIntegrationLogger` + +Eine Instanz des [Astro-Integrationsloggers](https://docs.astro.build/de/reference/integrations-reference/#astrointegrationlogger), die du zum Schreiben von Protokollen verwenden kannst. +Allen protokollierten Meldungen wird der Name des Plugins vorangestellt. + +```ts {6} +// plugin.ts +export default { + name: 'long-process-plugin', + hooks: { + 'config:setup'({ logger }) { + logger.info('Beginn eines langen Prozesses…'); + // Ein langer Prozess… + }, + }, +}; +``` + +Im obigen Beispiel wird eine Meldung protokolliert, die die angegebene Info-Meldung enthält: + +```shell +[long-process-plugin] Beginn eines langen Prozesses… +``` + +#### `useTranslations` + +**Typ:** `(lang: string) => I18nT` + +Rufe `useTranslations()` mit einem BCP-47-Sprach-Tag auf, um eine Utility-Funktion zu generieren, die Zugriff auf UI-Strings für diese Sprache bietet. +`useTranslations()` gibt ein Äquivalent der API `Astro.locals.t()` zurück, die in Astro-Komponenten verfügbar ist. +Weitere Informationen zu den verfügbaren APIs findest du im Leitfaden [„UI-Übersetzungen verwenden“](/de/guides/i18n/#ui-übersetzungen-verwenden). + +```ts {6} +// plugin.ts +export default { + name: 'plugin-use-translations', + hooks: { + 'config:setup'({ useTranslations, logger }) { + const t = useTranslations('zh-CN'); + logger.info(t('builtWithStarlight.label')); + }, + }, +}; +``` + +Im obigen Beispiel wird eine Meldung protokolliert, die einen integrierten UI-String für die vereinfachte chinesische Sprache enthält: + +```shell +[plugin-use-translations] 基于 Starlight 构建 +``` + +#### `absolutePathToLang` + +**Typ:** `(path: string) => string` + +Rufe `absolutePathToLang()` mit einem absoluten Dateipfad auf, um die Sprache für diese Datei zu erhalten. + +Dies kann besonders nützlich sein, wenn du [remark oder rehype Plugins](https://docs.astro.build/de/guides/markdown-content/#markdown-plugins) hinzufügst, um Markdown- oder MDX-Dateien zu verarbeiten. +Das von diesen Plugins verwendete [virtuelle Dateiformat](https://github.com/vfile/vfile) enthält den [absoluten Pfad](https://github.com/vfile/vfile#filepath) der zu verarbeitenden Datei, der mit `absolutePathToLang()` verwendet werden kann, um die Sprache der Datei zu bestimmen. +Die zurückgegebene Sprache kann mit dem Helfer [`useTranslations()`](#usetranslations) verwendet werden, um UI-Strings für diese Sprache zu erhalten. + +Nehmen wir zum Beispiel die folgende Starlight-Konfiguration: + +```js +starlight({ + title: 'Meine Dokumentation', + defaultLocale: 'en', + locales: { + // Englische Dokumentationen in `src/content/docs/en/` + en: { label: 'English' }, + // Französische Dokumentationen in `src/content/docs/fr/` + fr: { label: 'Français', lang: 'fr' }, + }, +}); +``` + +Ein Plugin kann die Sprache einer Datei anhand ihres absoluten Pfads bestimmen: + +```ts {6-8} /fr/ +// plugin.ts +export default { + name: 'plugin-use-translations', + hooks: { + 'config:setup'({ absolutePathToLang, useTranslations, logger }) { + const lang = absolutePathToLang( + '/absolute/path/to/project/src/content/docs/fr/index.mdx' + ); + const t = useTranslations(lang); + logger.info(t('aside.tip')); + }, + }, +}; +``` + +Im obigen Beispiel wird eine Meldung protokolliert, die einen integrierten UI-String für die französische Sprache enthält: + +```shell +[plugin-use-translations] Astuce +``` diff --git a/docs/src/content/docs/de/reference/route-data.mdx b/docs/src/content/docs/de/reference/route-data.mdx new file mode 100644 index 00000000000..4b6e20a83ab --- /dev/null +++ b/docs/src/content/docs/de/reference/route-data.mdx @@ -0,0 +1,206 @@ +--- +title: Routendaten Referenz +description: Die vollständige Referenz­dokumentation für Starlights Routendatenobjekt. +sidebar: + label: Routendaten +--- + +Das Routendatenobjekt von Starlight enthält Informationen über die aktuelle Seite. +Erfahre mehr darüber, wie das Datenmodell von Starlight funktioniert, in der [„Routendaten“-Anleitung](/de/guides/route-data/). + +In Astro-Komponenten greifst du auf die Routendaten von `Astro.locals.starlightRoute` zu: + +```astro {4} +--- +// src/components/Custom.astro + +const { hasSidebar } = Astro.locals.starlightRoute; +--- +``` + +In der [Routen-Middleware](/de/guides/route-data/#anpassen-der-routendaten) greifst du auf die Routendaten aus dem Kontextobjekt zu, das an deine Middleware-Funktion übergeben wird: + +```ts {5} +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + const { hasSidebar } = context.locals.starlightRoute; +}); +``` + +## `starlightRoute` + +Das Objekt `starlightRoute` hat die folgenden Eigenschaften: + +### `dir` + +**Typ:** `'ltr' | 'rtl'` + +Schreibrichtung der Seite. + +### `lang` + +**Typ:** `string` + +BCP-47-Sprachkennzeichen für das Gebietsschema dieser Seite, z. B. `de`, `zh-CN` oder `pt-BR`. + +### `locale` + +**Typ:** `string | undefined` + +Der Basispfad, unter dem eine Sprache angeboten wird. `undefined` für Root-Locale-Slugs. + +### `siteTitle` + +**Typ:** `string` + +Der Seitentitel für das Gebietsschema dieser Seite. + +### `siteTitleHref` + +**Typ:** `string` + +Der Wert für das Attribut `href` des Seitentitels, der auf die Homepage zurückverweist, z. B. `/`. +Bei mehrsprachigen Websites wird hier das aktuelle Gebietsschema angegeben, z. B. `/en/` oder `/zh-cn/`. + +### `slug` + +**Typ:** `string` + +Der aus dem Dateinamen des Inhalts generierte Slug für diese Seite. + +Diese Eigenschaft ist veraltet und wird in einer zukünftigen Version von Starlight entfernt werden. +Stelle auf die neue Content Layer API um, indem du [Starlights `docsLoader`](/de/manual-setup/#konfigurieren-von-inhaltssammlungen) benutzt und verwende stattdessen die Eigenschaft [`id`](#id). + +### `id` + +**Typ:** `string` + +Der Slug für diese Seite oder die eindeutige ID für diese Seite, die auf dem Dateinamen des Inhalts basiert, wenn du das Flag [`legacy.collections`](https://docs.astro.build/de/reference/legacy-flags/#collections) benutzt. + +### `isFallback` + +**Typ:** `boolean | undefined` + +`true`, wenn diese Seite in der aktuellen Sprache unübersetzt ist und Fallback-Inhalte aus dem Standardgebiets­schema verwendet. +Wird nur in mehrsprachigen Websites verwendet. + +### `entryMeta` + +**Typ:** `{ dir: 'ltr' | 'rtl'; lang: string }` + +Gebietsschema-Metadaten für den Seiteninhalt. Du kannst von den Werten der Top-Level-Locale unterscheiden, wenn eine Seite Fallback-Inhalte verwendet. + +### `entry` + +Der Astro-Inhaltssammlungs­eintrag für die aktuelle Seite. +Beinhaltet Frontmatter-Werte für die aktuelle Seite in `entry.data`. + +```ts +entry: { + data: { + title: string; + description: string | undefined; + // usw. + } +} +``` + +Erfahre mehr über die Form dieses Objekts in der [Astros Eintragstyp-Sammlung](https://docs.astro.build/de/reference/modules/astro-content/#collectionentry) Referenz. + +### `sidebar` + +**Typ:** `SidebarEntry[]` + +Seitennavigations­einträge für diese Seite. + +### `hasSidebar` + +**Typ:** `boolean` + +Ob die Seitenleiste auf dieser Seite angezeigt werden soll oder nicht. + +### `pagination` + +**Typ:** `{ prev?: Link; next?: Link }` + +Links zur vorherigen und nächsten Seite in der Seitenleiste, falls aktiviert. + +### `toc` + +**Typ:** `{ minHeadingLevel: number; maxHeadingLevel: number; items: TocItem[] } | undefined` + +Inhaltsverzeichnis für diese Seite, falls aktiviert. + +### `headings` + +**Typ:** `{ depth: number; slug: string; text: string }[]` + +Array aller Markdown-Überschriften, die aus der aktuellen Seite extrahiert wurden. +Verwende stattdessen [`toc`](#toc), wenn du einen Inhaltsverzeichnis-Komponenten erstellen willst, welches die Konfigurations­optionen von Starlight berücksichtigt. + +### `lastUpdated` + +**Typ:** `Date | undefined` + +JavaScript `Date` Objekt, welches angibt, wann diese Seite zuletzt aktualisiert wurde, falls aktiviert. + +### `editUrl` + +**Typ:** `URL | undefined` + +`URL`-Objekt für die Adresse, unter der diese Seite bearbeitet werden kann, falls aktiviert. + +### `head` + +**Typ:** [`HeadConfig[]`](/de/reference/configuration/#headconfig) + +Array mit allen Tags, die in den `<head>` der aktuellen Seite aufgenommen werden sollen. +Enthält wichtige Tags wie `<title>` und `<meta charset="utf-8">`. + +## Hilfsmittel + +### `defineRouteMiddleware()` + +Verwende das Hilfsmethode `defineRouteMiddleware()`, um dein Route-Middleware-Modul zu definieren: + +```ts "defineRouteMiddleware" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + // ... +}); +``` + +### `StarlightRouteData`-Typ + +Wenn du Code schreibst, der mit den Routendaten von Starlight arbeiten muss, kannst du den Typ `StarlightRouteData` importieren, damit er der Form von `Astro.locals.starlightRoute` entspricht. + +Im folgenden Beispiel aktualisiert die Funktion `usePageTitleInTOC()` die Routedaten so, dass der Titel der aktuellen Seite als Beschriftung für den ersten Eintrag im Inhaltsverzeichnis verwendet wird und die Standard­beschriftung „Übersicht“ ersetzt. +Mit dem Typ `StarlightRouteData` kannst du prüfen, ob die Änderungen der Routendaten gültig sind. + +```ts "StarlightRouteData" +// src/route-utils.ts +import type { StarlightRouteData } from '@astrojs/starlight/route-data'; + +export function usePageTitleInTOC(starlightRoute: StarlightRouteData) { + const overviewLink = starlightRoute.toc?.items[0]; + if (overviewLink) { + overviewLink.text = starlightRoute.entry.data.title; + } +} +``` + +Diese Funktion kann dann von einer Route Middleware aufgerufen werden: + +```ts {3,6} +// src/route-middleware.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; +import { usePageTitleInTOC } from './route-utils'; + +export const onRequest = defineRouteMiddleware((context) => { + usePageTitleInTOC(context.locals.starlightRoute); +}); +``` diff --git a/docs/src/content/docs/de/resources/community-content.mdx b/docs/src/content/docs/de/resources/community-content.mdx new file mode 100644 index 00000000000..b06846b8fe6 --- /dev/null +++ b/docs/src/content/docs/de/resources/community-content.mdx @@ -0,0 +1,252 @@ +--- +title: Community-Inhalte +description: Entdecke von der Community erstellte Anleitungen, Artikel und Videos, die dir helfen, Starlight zu erlernen und zu bauen! +--- + +:::tip[Füge dein eigenes hinzu!] +Hast du Inhalte über Starlight produziert? +Eröffne eine PR und füge einen Link zu dieser Seite hinzu! +::: + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +## Artikel und Rezensionen + +Hier findest du eine Sammlung von Beiträgen und Artikeln, in denen du mehr über Starlight und die Erfahrungen anderer Menschen erfährst: + +<CardGrid> + <LinkCard + href="https://devm.io/open-source/starlight-astro" + title="Statische Website-Erstellung mit Starlight" + description="“Bei der Entwicklung von Komponenten ist keine Idee zu groß oder zu klein“ - ein Interview mit Chris Swithinbank, Starlight Leiter" + /> + <LinkCard + href="https://frontendatscale.com/blog/hybrid-frontend-architecture/" + title="Hybride Frontend-Architektur mit Astro und Starlight" + description="Maxi Ferreira und Ben Holmes bauen eine Dokumentationswebsite mit Starlight, TinaCMS und einem interaktiven API Playground mit Authentifizierung." + /> + <LinkCard + href="https://www.olets.dev/posts/comparing-docs-site-builders-vuepress-vs-starlight/" + title="Vergleich von Dokumentations­websites-Frameworks: VuePress vs. Starlight" + description="Wie schneiden diese beiden Frameworks ab?" + /> + <LinkCard + href="https://astro.build/case-studies/wp-engine/" + title="Fallstudie: Senkung der Entwicklungskosten" + description="Wie WP Engine mit Astro's Starlight die Entwicklungskosten um über 50% senken konnte." + /> + <LinkCard + href="https://maciekpalmowski.dev/blog/building-a-documentation-site-using-astro-starlight/" + title="Aufbau einer Dokumentationswebsite mit Astro Starlight" + description="Maciek Palmowski beschreibt, wie Patchstack seine Dokumentation zu Starlight migriert hat" + /> + <LinkCard + href="https://blog.cloudflare.com/open-source-all-the-way-down-upgrading-our-developer-documentation/" + title="Open Source von Anfang bis Ende" + description="Wie Cloudflare Starlight benutzt hat, um seine Entwickler­dokumentation zu verbessern." + /> + <LinkCard + href="https://starlight-changelog.netlify.app/" + title="Starlight Changelog" + description="Sieh dir alle Veröffentlichungen des @astrojs/starlight-Pakets auf einer einzigen schönen Website an." + /> + <LinkCard + href="https://hideoo.dev/notes/contributing-to-starlight" + title="Zu Starlight beitragen" + description="Meine Erfahrungen und Tipps, wie man bei Open-Source-Projekten wie Starlight mitmachen kann." + /> +</CardGrid> + +## Beispiele und Leitfäden + +Beispiele sind in der Regel kurze, konzentrierte Anleitungen, die den Leser durch ein funktionierendes Beispiel für eine bestimmte Aufgabe führen. Beispiele sind eine gute Möglichkeit, deinem Starlight-Projekt neue Funktionen oder Verhaltensweisen hinzuzufügen, indem du Schritt-für-Schritt-Anweisungen befolgst! Andere Anleitungen erklären Konzepte, die sich auf einen bestimmten Inhaltsbereich beziehen, z. B. die Verwendung von Bildern oder das Arbeiten mit MDX. + +Erkunde die von der Community erstellten Inhalte, die von Starlight-Benutzern gepflegt werden: + +<CardGrid> + <LinkCard + href="https://www.webpro.nl/scraps/versioned-docs-with-starlight-and-vercel" + title="Versionierte Dokumentation mit Starlight & Vercel" + description="Ein Leitfaden für die Implementierung separater Versionen der Dokumentation für jede Hauptversion eines Projekts." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-heading-links" + title="Links zu Starlight Überschriften hinzufügen" + description="Eine Anleitung zur Verwendung eines Rehype-Plugins, um Links zu bestimmten Abschnitten deiner Dokumentation zu teilen." + /> + <LinkCard + href="https://blog.otterlord.dev/posts/starlight-sponsors/" + title="Füge Sponsoren zu deiner Starlight-Website hinzu" + description="Eine Anleitung zur Implementierung einer benutzerdefinierten Sponsorenkomponente in deiner Dokumentations-Seitenleiste." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images" + title="Open Graph Bilder zu Starlight hinzufügen" + description="Ein Leitfaden zur Erstellung von sozialen Bildern und den entsprechenden Meta-Tags für deine Website." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-third-party-icon-sets" + title="Symbol-Sets von Drittanbietern in Starlight verwenden" + description="Eine Anleitung zur Verwendung von unplugin-icons, um die Auswahl an verfügbaren Symbolen für Starlight zu erweitern." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-html-head" + title="Bearbeite den HTML-Kopf von Starlight-Websites" + description="Lerne, wie du gängige Kopfinhalte wie Webanalysen, Schriftarten und Skripte hinzufügen kannst." + /> + <LinkCard + href="https://dev.to/mrrobot/publishing-documentation-with-astro-starlight-691" + title="Dokumentation mit Astro Starlight veröffentlichen" + description="Erste Schritte mit der Starlight-Dokumentation." + /> + <LinkCard + href="https://events-3bg.pages.dev/jotter/starlight/" + title="Aktiviere Ansichtsübergänge" + description="Füge Unterstützung für Ansichtsübergänge, clientseitiges Routing und SPA-ähnliche Navigation zu deiner Starlight-Dokumentationsseite hinzu." + /> + <LinkCard + href="https://jamcomments.com/posts/structured-data-with-starlight" + title="Hinzufügen von strukturierten Daten zu Starlight-Websites" + description="Lerne, wie du dynamische JSON-LD strukturierte Daten für deine Dokumentations­websites erstellst." + /> + <LinkCard + href="https://starlight-examples.netlify.app/" + title="Starlight Beispiele" + description="Eine Sammlung von StackBlitz-Einbettungen, die zeigen, wie man in Starlight-Dokumentations­websites praktische Dinge tun kann." + /> + <LinkCard + href="https://hideoo.dev/notebooks/starlight-plugins-by-example" + title="Starlight-Plugins anhand von Beispielen" + description="Eine Sammlung von Notizen und Beispielen zu Starlight-Plugins und gängigen Mustern, die zum Erstellen dieser Plugins verwendet werden." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-progress-indicator/" + title="Lesefortschrittsanzeige hinzufügen" + description="Erfahre, wie du eine horizontale Lesefortschrittsanzeige zu deiner Starlight-Website hinzufügen kannst." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-sidebar-whitespace/" + title="Verwende eigene Stile für deine Starlight-Seitenleiste" + description="Mit ein bisschen CSS kannst du Schriftarten, Farben und mehr in der Starlight-Seitenleiste anpassen." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-dropdown-and-list-together/" + title="Starlight-Themen Dropdown auf Mobilgeräten, Liste auf Desktop-Computern" + description="Kombiniere zwei Plugins, um das Beste aus beiden auf Desktop- und Mobilgeräten zu erhalten." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-autogenerate-whole-sidebar/" + title="Verarbeitung von Starlight-Seitenleisten mit Middleware" + description="Benutze Route-Middleware, um die Reihenfolge der Seitenleisten und Gruppenbeschriftungen zu steuern, inspiriert von den Konventionen von Nuxt Content." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-social-links" + title="Füge soziale Links mit benutzerdefinierten Symbolen zu Starlight hinzu" + description="Hier erfährst du, wie du eigene Symbole für Social-Media-Links im Header der Starlight-Website verwenden kannst." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-paste-images-with-visual-studio-code" + title="Bilder mit Visual Studio Code in Starlight-Seiten einfügen" + description="Verbessere deinen Starlight-Dokumentations-Workflow, indem du Bilder mit Visual Studio Code in deine Dokumentationsseiten einfügst." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-add-diagrams-using-d2" + title="Füge Diagramme mit D2 zu deiner Starlight-Dokumentation hinzu" + description="Lerne, wie du mit D2 Diagramme zu deiner Starlight-Dokumentation hinzufügen kannst." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images-cloudinary-astro-sdk" + title="Erstelle Open-Graph-Bilder für Starlight mit dem Cloudinary Astro SDK." + description="Lerne, wie du mit dem Cloudinary Astro SDK Open-Graph-Bilder für deine Starlight-Dokumentationswebsite machst." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-list-recent-github-releases" + title="Zeig die neuesten GitHub-Veröffentlichungen in Starlight mit der Astro Content Layer API an." + description="Lerne, wie du die Astro Content Layer API nutzen kannst, um die neuesten GitHub-Veröffentlichungen in einem Starlight-Projekt aufzulisten." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-sitewide-banner" + title="Füge ein siteweites Banner zu Starlight hinzu" + description="Lerne, wie du mit der integrierten Bannerfunktion von Starlight ein siteweites Banner erstellen kannst." + /> + <LinkCard + href="https://lirantal.com/blog/customizing-astro-starlight-sidebar-gated-content-auth" + title="Anpassen der Astro Starlight-Seitenleiste für geschützte Inhalte mit Authentifizierung" + description="Schütze dein Kursmaterial, indem du Clerk und SSR nutzt, um die Kapitel in der Starlight-Seitenleiste je nach Benutzeranmeldung dynamisch auszublenden oder anzuzeigen." + /> +</CardGrid> + +## Video-Inhalte + +Entdecke Videos und Kanäle mit Starlight-Inhalten, darunter Live-Streams und Bildungsinhalte. + +import YouTubeGrid from '~/components/youtube-grid.astro'; + +### Official-Videos + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=5u0Ds7wzUeI', + title: 'Starlight von Astro', + description: 'Sieh dir das offizielle Starlight-Startvideo an', + }, + { + href: 'https://www.youtube.com/watch?v=j8K-ESJF814', + title: 'Ein Jahr Starlight!', + description: + 'Sarah redet über Astros von der Community erstelltes Dokumentationstheme', + }, + ]} +/> + +### Community Videos und Streams + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/shorts/zjOWezSzd18', + title: '🌟 SUB 1 MINUTE RUN', + description: + 'Sieh dir an, wie Ben eine neue Starlight-Website in weniger als einer Minute startet!', + }, + { + href: 'https://www.youtube.com/watch?v=sF6UcV3moZg', + title: 'Dokumentation mit Starlight und Astro erstellen', + description: + 'Schau dir an, wie Chris und Alex mit CodingCat.dev in den Code von Starlight eintauchen', + }, + { + href: 'https://www.youtube.com/watch?v=sWkkHbwDeQc', + title: 'Astro Starlight', + description: 'Einführung in Starlight in weniger als einer Minute.', + }, + { + href: 'https://www.youtube.com/watch?v=-Ki-1E5gNCk', + title: + 'Astro Starlight Dokumentations­vorlage (Erstelle eigene Applikations-Dokumentation!)', + description: + 'Eine neue Starlight-Website ist in etwa 5 Minuten einsatzbereit', + }, + { + href: 'https://www.youtube.com/watch?v=12o7WxjAxjM', + title: + 'Starlight-Dokumentation in ein Next.js-Projekt mit Proxys einbinden', + description: + 'Starlight als Unterverzeichnis-Projekt innerhalb einer Next.js-Website einrichten', + }, + { + href: 'https://www.youtube.com/watch?v=5pq80drDrNs', + title: + 'Mit diesem tollen Tool habe ich Shadcns Dokumentation in 30 Minuten neu erstellt', + description: + 'In diesem Video erkläre ich dir, was Starlight so cool macht und warum du es vielleicht bei deinem nächsten Projekt ausprobieren solltest.', + }, + { + href: 'https://www.youtube.com/watch?v=Q1E4Gkt63ko', + title: 'Astro Starlight und Emoji-Blast mit Chris Swithinbank', + description: + 'Chris, der Schöpfer von Astros Starlight-Framework, zeigt mir, wie ich es für eine neue Emoji-Website einrichte. 🌟 🎇', + }, + ]} +/> diff --git a/docs/src/content/docs/de/resources/plugins.mdx b/docs/src/content/docs/de/resources/plugins.mdx new file mode 100644 index 00000000000..2996cd00e07 --- /dev/null +++ b/docs/src/content/docs/de/resources/plugins.mdx @@ -0,0 +1,305 @@ +--- +title: Plugins und Integrationen +description: Entdecke Community-Tools wie Plugins und Integrationen, die Starlight erweitern! +sidebar: + order: 1 +--- + +:::tip[Füge dein eigenes hinzu!] +Hast du ein Plugin oder ein Tool für Starlight entwickelt? +Eröffne einen PR und füge einen Link zu dieser Seite hinzu! +::: + +## Plugins + +[Plugins](/de/reference/plugins/) können die Konfiguration, die Benutzeroberfläche und das Verhalten von Starlight anpassen und sind gleichzeitig einfach weiterzugeben und wiederzuverwenden. +Erweitere deine Website mit offiziellen Plugins, die vom Starlight-Team unterstützt werden, und mit Community-Plugins, die von Starlight-Nutzern gepflegt werden. + +### Offizielle Plugins + +<CardGrid> + <LinkCard + href="/de/guides/site-search/#algolia-docsearch" + title="Algolia DocSearch" + description="Ersetze Pagefind, den Standard-Suchanbieter, durch Algolia DocSearch." + /> +</CardGrid> + +### Community-Plugins + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-links-validator" + title="starlight-links-validator" + description="Überprüfe deine Starlight-Website auf defekte Links." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-typedoc" + title="starlight-typedoc" + description="Erstelle Starlight-Websites aus TypeScript mit TypeDoc." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-blog" + title="starlight-blog" + description="Füge einen Blog zu deiner Dokumentationswebsite hinzu." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-openapi" + title="starlight-openapi" + description="Erstelle Dokumentations­websites aus OpenAPI/Swagger-Spezifikationen." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-obsidian" + title="starlight-obsidian" + description="Veröffentliche Obsidian-Tresore auf deiner Starlight-Website." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-image-zoom" + title="starlight-image-zoom" + description="Füge deinen Dokumentations­bildern Zoomfunktionen hinzu." + /> + <LinkCard + href="https://github.com/lorenzolewis/starlight-utils" + title="starlight-utils" + description="Erweitere Starlight mit einer Sammlung von allgemeinen Dienstprogrammen." + /> + <LinkCard + href="https://github.com/trueberryless/starlight-view-modes" + title="starlight-view-modes" + description="Füge deiner Dokumentations-Website verschiedene Ansichtsmodi hinzu." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-versions" + title="starlight-versions" + description="Versioniere deine Starlight-Dokumentations­website." + /> + <LinkCard + href="https://inox-tools.fryuni.dev/star-warp" + title="star-warp" + description="Warp-Drive durch die Suchergebnisse in deiner Dokumentation." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-heading-badges" + title="starlight-heading-badges" + description="Füge Abzeichen zu deinen Markdown- und MDX-Überschriften hinzu." + /> + <LinkCard + href="https://github.com/Fevol/starlight-site-graph" + title="starlight-site-graph" + description="Füge einen interaktiven Graphen in die Seitenleiste deiner Website ein." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-sidebar-topics" + title="starlight-sidebar-topics" + description="Unterteile deine Dokumentation in verschiedene Abschnitte, die jeweils eine eigene Seitenleiste haben." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-cooler-credit" + title="starlight-cooler-credit" + description="Füge einen netten Verweis auf Starlight oder Astro am Ende des Inhalts­verzeichnisses ein." + /> + <LinkCard + href="https://github.com/dragomano/starlight-giscus" + title="starlight-giscus" + description="Füge Giscus-Kommentare zu deiner Dokumentations-Website hinzu." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-videos" + title="starlight-videos" + description="Verbessere deine Dokumentation mit Videoanleitungen und Kursen." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-kbd" + title="starlight-kbd" + description="Dokumentiere Tastaturkürzel mit Leichtigkeit." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-auto-sidebar" + title="starlight-auto-sidebar" + description="Modifiziere deine automatisch generierten Seitenleistengruppen." + /> + <LinkCard + href="https://github.com/delucis/starlight-llms-txt" + title="starlight-llms-txt" + description="Füge llms.txt zu deiner Dokumentationsseite hinzu, welche auf llmstxt.org basiert." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-toc-overview-customizer" + title="starlight-toc-overview-customizer" + description="Modifiziere Starlights Inhaltsverzeichnis mit anpassbarem Übersichtstitel." + /> + <LinkCard + href="https://delucis.github.io/starlight-markdown-blocks/" + title="starlight-markdown-blocks" + description="Erweiter Starlights Markdown-Nebenbemerkungs-Syntax um eigene Blocktypen." + /> + <LinkCard + href="https://github.com/WindMillCode/starlight-fullview-mode" + title="starlight-fullview-mode" + description="Klappe die Seitenleisten ein und erweitere den Inhalt für ein Vollbildschirm-Erlebnis." + /> + <LinkCard + href="https://github.com/frostybee/starlight-scroll-to-top" + title="starlight-scroll-to-top" + description="Füge deiner Dokumentations-Website eine Schaltfläche „Nach oben scrollen“ hinzu." + /> + <LinkCard + href="https://github.com/frostybee/starlight-codeblock-fullscreen" + title="starlight-codeblock-fullscreen" + description="Füge eine Funktion zum Umschalten zwischen Vollbildmodus und Normalansicht zu den Expressive Code-Blöcken in deiner Dokumentation hinzu." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-auto-drafts" + title="starlight-auto-drafts" + description="Passe das Standardverhalten von Entwurfsseiten an und entferne automatisch Links zur Seitenleiste zu Entwurfsseiten im Produktionsmodus." + /> + <LinkCard + href="https://github.com/corsfix/starlight-contextual-menu" + title="starlight-contextual-menu" + description="Füge ein Kontextmenü zu deiner Starlight-Dokumentation hinzu." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-changelogs" + title="starlight-changelogs" + description="Zeige Änderungsprotokolle neben deiner Projektdokumentation an." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-github-alerts" + title="starlight-github-alerts" + description="GitHub-Warnungen als Starlight-Nebenbemerkungen anzeigen." + /> + <LinkCard + href="https://github.com/dlcastillop/starlight-page-actions" + title="starlight-page-actions" + description="Fügt deiner Dokumentation Seitenaktionsschaltflächen hinzu." + /> + <LinkCard + href="https://github.com/typesense/starlight-docsearch-typesense" + title="starlight-docsearch-typesense" + description="Eine von Typesense unterstützte Alternative zum offiziellen Algolia DocSearch-Plugin." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-swipe/" + title="starlight-sidebar-swipe" + description="Mach die linke Seitenleiste auf Handys wischbar wie Discord Mobile." + /> + <LinkCard + href="https://github.com/Rettend/starlight-plugin-icons" + title="starlight-plugin-icons" + description="Füge Symbole zu Astro Starlight hinzu: Seitenleiste, Codeblöcke, Dateibaum." + /> + <LinkCard + href="https://github.com/dlcastillop/starlight-ui-tweaks" + title="starlight-ui-tweaks" + description="Erweitert die Kernkomponenten der Benutzeroberfläche mit benutzerdefinierten Navigationslinks, Anzeigen, Marketing-Fußzeilen und einer übersichtlicheren Themenumschaltung." + /> + <LinkCard + href="https://frostybee.github.io/starlight-tags/" + title="starlight-tags" + description="Füge Tags zu deinen Starlight-Dokumentationsseiten hinzu, um Inhalte zu organisieren und leichter zu finden." + /> + <LinkCard + href="https://github.com/dionysuzx/starlight-copy-button" + title="starlight-copy-button" + description="Kopiere das gesamte Markdown der Dokumentationsseite mit einem schicken Button im Seitentitel." + /> + <LinkCard + href="https://frostybee.github.io/starlight-telescope/" + title="starlight-telescope" + description="Navigiere schnell zu jeglichen Dokumentationsseiten mithilfe von Fuzzy-Search und Tastaturkombinationen." + /> + <LinkCard + href="https://frostybee.github.io/starlight-announcement/" + title="starlight-announcement" + description="Füge verbesserte Ankündigungsbanner mit Varianten, Schließmöglichkeit, Zeitplanung und Seiteneinschränkung zu deiner Dokumentation hinzu." + /> +</CardGrid> + +## Community-Tools und Integrationen + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +Diese Community-Tools und Integrationen können verwendet werden, um deiner Starlight-Website Funktionen hinzuzufügen. + +<CardGrid> + <LinkCard + href="https://www.feelback.dev/blog/new-astro-starlight-integration/" + title="FeelBack" + description="Füge ein Nutzer-Feedback-System zu deinen Dokumentationswebsites hinzu." + /> + <LinkCard + href="https://github.com/val-town/notion-to-astro" + title="notion-to-astro" + description="Konvertiere Notion-Exporte in Astro Starlight-Dokumentation." + /> + <LinkCard + href="https://github.com/mattjennings/astro-live-code" + title="astro-live-code" + description="Rendere deine MDX-Codeblöcke als interaktive Komponenten." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-i18n" + title="starlight-i18n" + description="Visual Studio Code-Erweiterung, die bei der Übersetzung von Starlight-Seiten hilft." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-package-managers" + title="starlight-package-managers" + description="Zeige schnell npm-bezogene Befehle für mehrere Paketmanager an." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-showcases" + title="starlight-showcases" + description="Ein Set von Starlight-Komponenten zum Erstellen von Schaufensterseiten." + /> + <LinkCard + href="https://github.com/HiDeoo/generator-starlight-plugin" + title="@hideoo/starlight-plugin" + description="Ein Generator, um schnell Starlight-Plugins zu erstellen." + /> + <LinkCard + href="https://github.com/Linkerin/starlight-to-pdf" + title="starlight-to-pdf" + description="Ein Kommandozeilen­werkzeug zur Konvertierung von Starlight-Websites in PDF-Dateien." + /> + <LinkCard + href="https://github.com/joesaby/astro-plantuml" + title="astro-plantuml" + description="PlantUML-Inhalte in Markdown-Codeblöcken wiedergeben." + /> + <LinkCard + href="https://github.com/joesaby/astro-mermaid" + title="astro-mermaid" + description="Rendere Mermaid-Inhalte in Markdown-Code-Blöcken auf der Client-Seite." + /> + <LinkCard + href="https://github.com/HiDeoo/astro-d2" + title="astro-d2" + description="D2 Markdown-Code-Blöcke in Diagramme umwandeln." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-links" + title="starlight-links" + description="Visual Studio Code-Erweiterung, die IntelliSense für Starlight Markdown- und MDX-Inhaltslinks bietet." + /> + <LinkCard + href="https://docs.contentisland.net/templates/starlight/" + title="contentisland-cli" + description="Verbinde und synchronisiere dein Starlight-Projekt mit Content Island Headless CMS, um deine Dokumentation zu bearbeiten und zu verwalten." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown" + title="starlight-sidebar-topics-dropdown" + description="Teile deine Dokumentationswebsite in mehrere Abschnitte auf und wechsle zwischen ihnen mit einem Dropdown-Menü in der Seitenleiste." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-save-file-component" + title="starlight-save-file-component" + description="Zeig schnell einen Link zu einem Download-Asset auf deiner Starlight-Website an." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-contributor-list" + title="starlight-contributor-list" + description="Zeig eine Liste aller Leute an, die zu deinem Projekt beigetragen haben." + /> +</CardGrid> diff --git a/docs/src/content/docs/de/resources/showcase.mdx b/docs/src/content/docs/de/resources/showcase.mdx new file mode 100644 index 00000000000..85364fd254f --- /dev/null +++ b/docs/src/content/docs/de/resources/showcase.mdx @@ -0,0 +1,21 @@ +--- +title: Starlight Schaufenster +description: Entdecke Websites, die mit Starlight erstellt wurden! +sidebar: + label: Website-Schaufenster +--- + +:::tip[Füge deine eigene hinzu!] +Hast du eine Starlight-Website gebaut? +[Eröffne einen PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#showcase) und füge einen Link zu dieser Seite hinzu! +::: + +## Websites + +import ShowcaseSites from '~/components/showcase-sites.astro'; + +Starlight wird bereits in der Produktion eingesetzt. Dies sind einige der Websites im Internet: + +<ShowcaseSites /> + +Siehe alle [öffentlichen Projekt-Repos mit Starlight auf GitHub](https://github.com/withastro/starlight/network/dependents). diff --git a/docs/src/content/docs/de/resources/themes.mdx b/docs/src/content/docs/de/resources/themes.mdx new file mode 100644 index 00000000000..7a5430ca477 --- /dev/null +++ b/docs/src/content/docs/de/resources/themes.mdx @@ -0,0 +1,124 @@ +--- +title: Themes +description: Gestalte deine Dokumentation mit einem Community-Theme für Starlight +tableOfContents: false +sidebar: + order: 2 +head: + - tag: style + content: | + body { --sl-content-width: 66.75rem; } +--- + +import ThemeGrid from '~/components/theme-grid.astro'; + +Ein Theme ist ein Starlight-Plugin, welches das Erscheinungsbild einer Website mit [benutzerdefiniertem CSS](/de/guides/css-and-tailwind/), [Komponenten­ersetzung](/de/guides/overriding-components/) oder anderen neuen Funktionen verändert. + +## Community-Themes + +Installiere ein von der Community erstelltes Theme, um das Aussehen deiner Website schnell anzupassen. + +Schau dir unten eine Vorschau aller Designs an oder probier sie interaktiv auf der [Starlight Themes-Demo-Website](https://starlight-themes.netlify.app/) aus. + +<ThemeGrid + labels={{ + /** Barrierefreie Beschriftung für den Themenschalter. */ + legend: 'Vorschau', + /** Barrierefreies Label für die dunkle Farbschema-Variante. */ + dark: 'Dunkel', + /** Barrierefreies Label für die helle Farbschema-Variante. */ + light: 'Hell', + }} + themes={[ + { + title: 'Starlight Rapide', + description: + 'Starlight-Theme inspiriert vom Visual Studio Code Vitesse-Theme.', + href: 'https://starlight-theme-rapide.vercel.app/', + previews: { light: 'rapide-light.png', dark: 'rapide-dark.png' }, + }, + { + title: 'Starlight Obsidian', + description: + 'Starlight-Theme inspiriert vom Obsidian Publish-Websites-Theme.', + href: 'https://fevol.github.io/starlight-theme-obsidian/', + previews: { light: 'obsidian-light.png', dark: 'obsidian-dark.png' }, + }, + { + title: 'Catppuccin für Starlight', + description: 'Beruhigendes Pastelltheme für Starlight.', + href: 'https://starlight.catppuccin.com/', + previews: { light: 'catppuccin-light.png', dark: 'catppuccin-dark.png' }, + }, + { + title: 'Ion', + description: 'Ein elegantes, modernes Theme für Starlight.', + href: 'https://louisescher.github.io/starlight-ion-theme/', + previews: { light: 'ion-light.png', dark: 'ion-dark.png' }, + }, + { + title: 'Starlight Black', + description: 'Starlight-Theme inspiriert von der Shadcn-Dokumentation.', + href: 'https://starlight-theme-black.vercel.app/', + previews: { light: 'black-light.png', dark: 'black-dark.png' }, + }, + { + title: 'Starlight Flexoki', + description: + 'Ein warmes und freundliches Theme basierend auf der Flexoki-Farbpalette.', + href: 'https://delucis.github.io/starlight-theme-flexoki/', + previews: { light: 'flexoki-light.png', dark: 'flexoki-dark.png' }, + }, + { + title: 'Starlight Nova', + description: 'Ein modernes und wunderschönes Theme für Starlight.', + href: 'https://starlight-theme-nova.pages.dev/', + previews: { light: 'nova-light.png', dark: 'nova-dark.png' }, + }, + { + title: 'Starlight Next.js Theme', + description: 'Starlight-Theme inspiriert von der Next.js-Dokumentation.', + href: 'https://starlight-theme-next.trueberryless.org/', + previews: { light: 'nextjs-light.png', dark: 'nextjs-dark.png' }, + }, + { + title: 'Starlight Galaxy', + description: + 'Ein Astro Starlight-Theme, das perfekt für die Veröffentlichung von Dokumentationen und Bildungsinhalten ist.', + href: 'https://frostybee.github.io/starlight-theme-galaxy/', + previews: { light: 'galaxy-light.png', dark: 'galaxy-dark.png' }, + }, + { + title: 'Starlight Page', + description: + 'Ein intuitives, modernes Starlight-Theme mit flüssigen Einblend-Animationen.', + href: 'https://pelagornis-page.netlify.app/', + previews: { light: 'page-light.png', dark: 'page-dark.png' }, + }, + { + title: 'Starlight Gruvbox', + description: 'Retro-Groove-Theme für Starlight', + href: 'https://starlight-theme-gruvbox.otterlord.dev/', + previews: { light: 'gruvbox-light.png', dark: 'gruvbox-dark.png' }, + }, + { + title: 'Starlight Six', + description: + 'Das schlichte und moderne Astro.js Starlight-Theme von Six Technology', + href: 'https://six-tech.github.io/Six.StarlightTheme/', + previews: { light: 'six-light.png', dark: 'six-dark.png' }, + }, + { + title: 'Starlight Vintage', + description: + 'Ein Starlight Theme, welches stark vom zeitlosen Design der alten Astro-Dokumentation inspiriert ist.', + href: 'https://starlight-theme-vintage.netlify.app/', + previews: { light: 'vintage-light.png', dark: 'vintage-dark.png' }, + }, + ]} +/> + +:::tip[Füge dein eigenes Theme hinzu!] +Hast du ein Starlight-Theme gebaut? +[Eröffne einen PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#themes) welcher dein Theme zu dieser Seite hinzufügt. +::: diff --git a/docs/src/content/docs/es/404.md b/docs/src/content/docs/es/404.md index 652c7b0741e..0740182ef44 100644 --- a/docs/src/content/docs/es/404.md +++ b/docs/src/content/docs/es/404.md @@ -2,6 +2,7 @@ title: No encontrada template: splash editUrl: false +lastUpdated: false hero: title: '404' tagline: <strong>Houston, tenemos un problema.</strong> No pudimos encontrar esa página.<br>Verifica la URL o intenta usar la barra de búsqueda. diff --git a/docs/src/content/docs/es/components/asides.mdx b/docs/src/content/docs/es/components/asides.mdx new file mode 100644 index 00000000000..f329defed3b --- /dev/null +++ b/docs/src/content/docs/es/components/asides.mdx @@ -0,0 +1,158 @@ +--- +title: Apartados +description: Aprende a usar apartados en Starlight para mostrar información secundaria junto al contenido principal de una página. +--- + +import { Aside } from '@astrojs/starlight/components'; + +Para mostrar información secundaria junto al contenido principal de una página, usa el componente `<Aside>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Aside slot="preview"> + Incluye información no esencial y complementaria en un `<Aside>`. +</Aside> + +</Preview> + +## Importación + +```tsx +import { Aside } from '@astrojs/starlight/components'; +``` + +## Uso + +Muestra un apartado (también conocido como “admoniciones” o “llamadas”) usando el componente `<Aside>`. + +Un `<Aside>` también puede tener un atributo opcional [`type`](#type), que controla el color, el icono y el título predeterminado del apartado. + +<Preview> + +````mdx +import { Aside } from '@astrojs/starlight/components'; + +<Aside>Contenido en un apartado.</Aside> + +<Aside type="caution">Contenido de precaución.</Aside> + +<Aside type="tip"> + +Otro tipo de contenido también es compatible en los apartados. + +```js +// Por ejemplo, un fragmento de código. +``` + +</Aside> + +<Aside type="danger">No des tu contraseña a nadie.</Aside> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% aside %} +Contenido en un apartado. +{% /aside %} + +{% aside type="caution" %} +Contenido de precaución. +{% /aside %} + +{% aside type="tip" %} +Otro tipo de contenido también es compatible en los apartados. + +```js +// Por ejemplo, un fragmento de código. +``` +{% /aside %} + +{% aside type="danger" %} +No des tu contraseña a nadie. +{% /aside %} +```` + +</Fragment> + +<Fragment slot="preview"> + + <Aside>Contenido en un apartado.</Aside> + + <Aside type="caution">Contenido de precaución.</Aside> + + <Aside type="tip"> + + Otro tipo de contenido también es compatible en los apartados. + + ```js + // Por ejemplo, un fragmento de código. + ``` + + </Aside> + + <Aside type="danger">No des tu contraseña a nadie.</Aside> + +</Fragment> + +</Preview> + +Starlight también proporciona una sintaxis personalizada para renderizar apartados en Markdown y MDX como una alternativa al componente `<Aside>`. +Ver la guía [“Redacción de contenido en Markdown”](/es/guides/authoring-content/#apartados) para obtener detalles de la sintaxis personalizada. + +### Usa títulos personalizados + +Sobreescribe los títulos predeterminados de los apartados usando el atributo [`title`](#title). + +<Preview> + +```mdx 'title="Watch out!"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="caution" title="¡Cuidado!"> + Una advertencia *con* un título personalizado. +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'title="Watch out!"' +{% aside type="caution" title="¡Cuidado!" %} +Una advertencia *con* un título personalizado. +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="caution" title="¡Cuidado!"> + Una advertencia *con* un título personalizado. +</Aside> + +</Preview> + +## Props de `<Aside>` + +**Implementación:** [`Aside.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Aside.astro) + +El componente `<Aside>` acepta las siguientes propiedades: + +### `type` + +**tipo:** `'note' | 'tip' | 'caution' | 'danger'` +**por defecto:** `'note'` + +El tipo de apartado a mostrar: + +- apartados `note` (el predeterminado) son azules y muestran un icono de información. +- apartados `tip` son morados y muestran un icono de cohete. +- apartados `caution` son amarillos y muestran un icono de advertencia. +- apartados `danger` son rojos y muestran un icono de advertencia octogonal. + +### `title` + +**tipo:** `string` + +El título del apartado a mostrar. +Si `title` no está establecido, se usará el título predeterminado para el `type` actual del apartado. diff --git a/docs/src/content/docs/es/components/badges.mdx b/docs/src/content/docs/es/components/badges.mdx new file mode 100644 index 00000000000..cf470c66d0a --- /dev/null +++ b/docs/src/content/docs/es/components/badges.mdx @@ -0,0 +1,150 @@ +--- +title: Insignias +description: Aprende a usar insignias en Starlight para mostrar información adicional. +--- + +import { Badge } from '@astrojs/starlight/components'; + +Para mostrar pequeñas piezas de información, como un estado o categoría, usa el componente `<Badge>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Badge slot="preview" text="Nuevo" /> + +</Preview> + +## Importación + +```tsx +import { Badge } from '@astrojs/starlight/components'; +``` + +## Uso + +Muestra una insignia usando el componente `<Badge>` y pasa el contenido que deseas mostrar al atributo [`text`](#text) del componente `<Badge>`. + +Por defecto, la insignia usará el color de acento del tema de tu sitio. +Para usar un color de insignia integrado, establece el atributo [`variant`](#variant) en uno de los valores admitidos. + +<Preview> + +```mdx +import { Badge } from '@astrojs/starlight/components'; + +<Badge text="Nota" variant="note" /> +<Badge text="Éxito" variant="success" /> +<Badge text="Consejo" variant="tip" /> +<Badge text="Precaución" variant="caution" /> +<Badge text="Peligro" variant="danger" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% badge text="Nota" variant="note" /%} +{% badge text="Éxito" variant="success" /%} +{% badge text="Consejo" variant="tip" /%} +{% badge text="Precaución" variant="caution" /%} +{% badge text="Peligro" variant="danger" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Badge text="Nota" variant="note" /> + <Badge text="Éxito" variant="success" /> + <Badge text="Consejo" variant="tip" /> + <Badge text="Precaución" variant="caution" /> + <Badge text="Peligro" variant="danger" /> +</Fragment> + +</Preview> + +### Usa diferentes tamaños + +Usa el atributo [`size`](#size) para controlar el tamaño del texto de la insignia. + +<Preview> + +```mdx /size="\w+"/ +import { Badge } from '@astrojs/starlight/components'; + +<Badge text="Nuevo" size="small" /> +<Badge text="Nuevo y mejorado" size="medium" /> +<Badge text="Nuevo, mejorado y grande" size="large" /> +``` + +<Fragment slot="markdoc"> + +```markdoc /size="\w+"/ +{% badge text="Nuevo" size="small" /%} +{% badge text="Nuevo y mejorado" size="medium" /%} +{% badge text="Nuevo, mejorado y grande" size="large" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Badge text="Nuevo" size="small" /> + <Badge text="Nuevo y mejorado" size="medium" /> + <Badge text="Nuevo, mejorado y grande" size="large" /> +</Fragment> + +</Preview> + +### Personaliza las insignias + +Personaliza las insignias usando cualquier otro atributo `<span>` como `class` o `style` con CSS personalizado. + +<Preview> + +```mdx "style={{ fontStyle: 'italic' }}" +import { Badge } from '@astrojs/starlight/components'; + +<Badge text="Personalizado" variant="success" style={{ fontStyle: 'italic' }} /> +``` + +<Fragment slot="markdoc"> + +```markdoc 'style="font-style: italic;"' +{% badge text="Personalizado" variant="success" style="font-style: italic;" /%} +``` + +</Fragment> + +<Badge + slot="preview" + text="Personalizado" + variant="success" + style={{ fontStyle: 'italic' }} +/> + +</Preview> + +## Props de `<Badge>` + +**Implementación:** [`Badge.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Badge.astro) + +El componente `<Badge>` acepta las siguientes propiedades y también cualquier [otro atributo `<span>`](https://developer.mozilla.org/es/docs/Web/HTML/Atributos_globales): + +### `text` + +**requerido** +**tipo:** `string` + +El contenido de texto que se mostrará en la insignia. + +### `variant` + +**tipo:** `'note' | 'danger' | 'success' | 'caution' | 'tip' | 'default'` +**por defecto:** `'default'` + +El color de la insignia a usar: `note` (azul), `tip` (morado), `danger` (rojo), `caution` (naranja), `success` (verde) o `default` (color de acento del tema). + +### `size` + +**tipo:** `'small' | 'medium' | 'large'` + +Define el tamaño de la insignia a mostrar. diff --git a/docs/src/content/docs/es/components/card-grids.mdx b/docs/src/content/docs/es/components/card-grids.mdx new file mode 100644 index 00000000000..f0957bf92e7 --- /dev/null +++ b/docs/src/content/docs/es/components/card-grids.mdx @@ -0,0 +1,179 @@ +--- +title: Cuadrículas de tarjetas +description: Aprende a envolver varias tarjetas en una cuadrícula en Starlight. +sidebar: + order: 4 +--- + +import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; + +Para envolver múltiples componentes [`<Card>`](/es/components/cards/) o [`<LinkCard>`](/es/components/link-cards/) en una cuadrícula, usa el componente `<CardGrid>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<CardGrid slot="preview"> + <Card title="Estrellas" icon="star"> + Sirius, Vega, Betelgeuse + </Card> + <Card title="Lunas" icon="moon"> + Io, Europa, Ganymede + </Card> +</CardGrid> + +</Preview> + +## Importación + +```tsx +import { CardGrid } from '@astrojs/starlight/components'; +``` + +## Uso + +### Agrupar tarjetas + +Muestra varios componentes [`<Card>`](/es/components/cards/) uno al lado del otro cuando hay suficiente espacio agrupándolos con el componente `<CardGrid>`. + +<Preview> + +```mdx {3,10} +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <Card title="Revisa esto" icon="open-book"> + Contenido interesante que deseas destacar. + </Card> + <Card title="Otra caracaterística" icon="information"> + Más información que deseas compartir. + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,9} +{% cardgrid %} +{% card title="Revisa esto" icon="open-book" %} +Contenido interesante que deseas destacar. +{% /card %} + +{% card title="Otra caracaterística" icon="information" %} +Más información que deseas compartir. +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <Card title="Revisa esto" icon="open-book"> + Contenido interesante que deseas destacar. + </Card> + <Card title="Otra caracaterística" icon="information"> + Más información que deseas compartir. + </Card> +</CardGrid> + +</Preview> + +### Agrupar tarjetas de enlace + +Muestra varios componentes [`<LinkCard>`](/es/components/link-cards/) uno al lado del otro cuando hay suficiente espacio agrupándolos con el componente `<CardGrid>`. + +<Preview> + +```mdx {3,9} +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <LinkCard + title="Creación de contenido en Markdown" + href="/es/guides/authoring-content/" + /> + <LinkCard title="Componentes" href="/es/components/using-components/" /> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,5} +{% cardgrid %} +{% linkcard title="Creación de contenido en Markdown" href="/es/guides/authoring-content/" /%} + +{% linkcard title="Componentes" href="/es/components/using-components/" /%} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <LinkCard + title="Creación de contenido en Markdown" + href="/es/guides/authoring-content/" + /> + <LinkCard title="Componentes" href="/es/components/using-components/" /> +</CardGrid> + +</Preview> + +### Tarjetas escalonadas + +Cambia la segunda columna de la cuadrícula verticalmente para agregar interés visual agregando el atributo [`stagger`](#stagger) al componente `<CardGrid>`. + +Este atributo es útil en tu página de inicio para mostrar las características clave de tu proyecto. + +<Preview> + +```mdx "stagger" +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid stagger> + <Card title="Revisa esto" icon="open-book"> + Contenido interesante que deseas destacar. + </Card> + <Card title="Otra característica" icon="information"> + Más información que deseas compartir. + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc "stagger=true" +{% cardgrid stagger=true %} +{% card title="Revisa esto" icon="open-book" %} +Contenido interesante que deseas destacar. +{% /card %} + +{% card title="Otra característica" icon="information" %} +Más información que deseas compartir. +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview" stagger> + <Card title="Revisa esto" icon="open-book"> + Contenido interesante que deseas destacar. + </Card> + <Card title="Otra característica" icon="information"> + Más información que deseas compartir. + </Card> +</CardGrid> + +</Preview> + +## Props de `<CardGrid>` + +**Implementación:** [`CardGrid.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/CardGrid.astro) + +El componente `<CardGrid>` acepta las siguientes propiedades: + +### `stagger` + +**tipo:** `boolean` + +Define si se deben escalonar las tarjetas en la cuadrícula o no. diff --git a/docs/src/content/docs/es/components/cards.mdx b/docs/src/content/docs/es/components/cards.mdx new file mode 100644 index 00000000000..ab972b89c57 --- /dev/null +++ b/docs/src/content/docs/es/components/cards.mdx @@ -0,0 +1,108 @@ +--- +title: Tarjetas +description: Aprende a usar tarjetas en Starlight para mostrar contenido en una caja. +sidebar: + order: 2 +--- + +import { Card } from '@astrojs/starlight/components'; + +Para mostrar contenido en una caja que coincida con los estilos de Starlight, usa el componente `<Card>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Card slot="preview" title="Lunas" icon="moon"> + Io, Europa, Ganymede +</Card> + +</Preview> + +## Importación + +```tsx +import { Card } from '@astrojs/starlight/components'; +``` + +## Uso + +Muestra una tarjeta usando el componente `<Card>` y proporciona un [`title`](#title) para la tarjeta. + +<Preview> + +```mdx +import { Card } from '@astrojs/starlight/components'; + +<Card title="Revisa esto">Contenido interesante que deseas destacar.</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% card title="Revisa esto" %} +Contenido interesante que deseas destacar. +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="Revisa esto"> + Contenido interesante que deseas destacar. +</Card> + +</Preview> + +### Agregar iconos a las tarjetas + +Incluye un icono en una tarjeta usando el atributo [`icon`](#icon) establecido en el nombre de [uno de los iconos integrados de Starlight](/es/reference/icons/#todos-los-iconos). + +<Preview> + +```mdx 'icon="star"' +import { Card } from '@astrojs/starlight/components'; + +<Card title="Estrellas" icon="star"> + Sirius, Vega, Betelgeuse +</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="star"' +{% card title="Estrellas" icon="star" %} +Sirius, Vega, Betelgeuse +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="Estrellas" icon="star"> + Sirius, Vega, Betelgeuse +</Card> + +</Preview> + +### Agrupar tarjetas + +Muestra varias tarjetas una al lado de la otra cuando hay suficiente espacio agrupándolas con el componente [`<CardGrid>`](/es/components/card-grids/). +Consulta la guía [“Agrupar tarjetas”](/es/components/card-grids/#agrupar-tarjetas) para un ejemplo. + +## Props de `<Card>` + +**Implementación:** [`Card.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Card.astro) + +El componente `<Card>` acepta las siguientes propiedades: + +### `title` + +**requerido** +**tipo:** `string` + +El título de la tarjeta a mostrar. + +### `icon` + +**tipo:** `string` + +Una tarjeta puede incluir un atributo `icon` establecido en el nombre de [uno de los iconos integrados de Starlight](/es/reference/icons/#todos-los-iconos). diff --git a/docs/src/content/docs/es/components/code.mdx b/docs/src/content/docs/es/components/code.mdx new file mode 100644 index 00000000000..77fbd0df038 --- /dev/null +++ b/docs/src/content/docs/es/components/code.mdx @@ -0,0 +1,103 @@ +--- +title: Código +description: Aprende a mostrar código con resaltado de sintaxis en Starlight sin bloques de código de Markdown. +--- + +import { Code } from '@astrojs/starlight/components'; + +El componente `<Code>` muestra código con resaltado de sintaxis. +Es útil cuando no es posible usar un [bloque de código de Markdown](/es/guides/authoring-content/#bloques-de-código), por ejemplo, para mostrar datos provenientes de fuentes externas como archivos, bases de datos o APIs. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Code + slot="preview" + code={`## Bienvenido + +¡Hola desde **el espacio**!`} +lang="md" +title="example.md" +ins={3} +/> + +</Preview> + +## Importación + +```tsx +import { Code } from '@astrojs/starlight/components'; +``` + +## Uso + +Usa el componente `<Code>` para renderizar código con resaltado de sintaxis, por ejemplo, al mostrar código obtenido de fuentes externas. + +Ver la [documentación de Expressive Code “Componente de código”](https://expressive-code.com/key-features/code-component/) para obtener detalles completos sobre cómo usar el componente `<Code>` y la lista de props disponibles. + +<Preview> + +```mdx +import { Code } from '@astrojs/starlight/components'; + +export const exampleCode = `console.log('¡Esto podría provenir de un archivo o CMS!');`; +export const fileName = 'example.js'; +export const highlights = ['archivo', 'CMS']; + +<Code code={exampleCode} lang="js" title={fileName} mark={highlights} /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% code + code="console.log('¡Esto podría provenir de un archivo o CMS!');" + lang="js" + title="example.js" + meta="'archivo' 'CMS'" /%} +``` + +</Fragment> + +export const exampleCode = `console.log('¡Esto podría provenir de un archivo o CMS!');`; +export const fileName = 'example.js'; +export const highlights = ['archivo', 'CMS']; + +<Code + slot="preview" + code={exampleCode} + lang="js" + title={fileName} + mark={highlights} +/> + +</Preview> + +### Mostrar código importado + +En los archivos MDX y componentes de Astro, usa [el sufijo de importación `?raw` de Vite](https://es.vite.dev/guide/assets#importar-recursos-como-cadenas-de-texto) para importar cualquier archivo de código como un string. +Puedes pasar este string importado al componente `<Code>` para incluirlo en tu página. + +<Preview> + +```mdx "?raw" +# src/content/docs/example.mdx + +import { Code } from '@astrojs/starlight/components'; +import importedCode from '/tsconfig.json?raw'; + +<Code code={importedCode} lang="json" title="tsconfig.json" /> +``` + +import importedCode from '../../../../../../examples/basics/tsconfig.json?raw'; + +<Code slot="preview" code={importedCode} lang="json" title="tsconfig.json" /> + +</Preview> + +## Props de `<Code>` + +**Implementación:** [`Code.astro`](https://github.com/expressive-code/expressive-code/blob/main/packages/astro-expressive-code/components/Code.astro) + +El componente `<Code>` acepta todas las propiedades documentadas en la [documentación de Expressive Code “Componente de código”](https://expressive-code.com/key-features/code-component/#available-props). diff --git a/docs/src/content/docs/es/components/file-tree.mdx b/docs/src/content/docs/es/components/file-tree.mdx new file mode 100644 index 00000000000..e884acf0261 --- /dev/null +++ b/docs/src/content/docs/es/components/file-tree.mdx @@ -0,0 +1,225 @@ +--- +title: Árbol de archivos +description: Aprende a mostrar la estructura de un directorio con iconos de archivo y subdirectorios colapsables en Starlight. +--- + +import { FileTree } from '@astrojs/starlight/components'; + +Para mostrar la estructura de un directorio con iconos de archivo y subdirectorios colapsables, usa el componente `<FileTree>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<FileTree slot="preview"> + +- astro.config.mjs un archivo **importante** +- package.json +- README.md +- src + - components + - **Header.astro** + - … +- pages/ + +</FileTree> + +</Preview> + +## Importación + +```tsx +import { FileTree } from '@astrojs/starlight/components'; +``` + +## Uso + +Muestra un árbol de archivos con iconos de archivo y subdirectorios colapsables usando el componente `<FileTree>`. + +Especifica la estructura de tus archivos y directorios con una [lista Markdown no ordenada](https://www.markdownguide.org/basic-syntax/#unordered-lists) dentro de `<FileTree>`. +Crea un subdirectorio usando una lista anidada o agrega una `/` al final de un elemento de la lista para renderizarlo como un directorio sin contenido específico. + +<Preview> + +```mdx +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% filetree %} +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> + +</Preview> + +### Resaltar entradas + +Haz que un archivo o directorio destaque haciendo que su nombre esté en negrita, por ejemplo, `**README.md**`. + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - **Header.astro** + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> + +</Preview> + +### Agregar comentarios + +Agrega un comentario a un archivo o directorio agregando más texto después del nombre. +El formateo de Markdown en línea como negritas e itálicas es compatible en los comentarios. + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro un archivo **importante** + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - Header.astro un archivo **importante** + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro un archivo **importante** + - Title.astro + +</FileTree> + +</Preview> + +### Agregar marcadores de posición + +Agrega archivos y directorios de marcador de posición usando `...` o `…` como nombre. +Esto puede ser útil para indicar a un lector que se espera que una carpeta contenga más elementos sin especificarlos todos explícitamente. + +<Preview> + +```mdx {8} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro + - … + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {5} +{% filetree %} +- src + - components + - Header.astro + - … +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro + - … + +</FileTree> + +</Preview> + +## Props de `<FileTree>` + +**Implementación:** [`FileTree.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/FileTree.astro) + +El componente `<FileTree>` no acepta ninguna propiedad. diff --git a/docs/src/content/docs/es/components/icons.mdx b/docs/src/content/docs/es/components/icons.mdx new file mode 100644 index 00000000000..35d005842ae --- /dev/null +++ b/docs/src/content/docs/es/components/icons.mdx @@ -0,0 +1,128 @@ +--- +title: Iconos +description: Aprende a mostrar iconos en Starlight. +--- + +import { Icon } from '@astrojs/starlight/components'; + +Para mostrar los iconos del [conjunto de iconos integrados](/es/reference/icons/#todos-los-iconos) de Starlight, usa el componente `<Icon>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Icon + slot="preview" + name="open-book" + color="var(--sl-color-text-accent)" + size="4rem" +/> + +</Preview> + +## Importación + +```tsx +import { Icon } from '@astrojs/starlight/components'; +``` + +## Uso + +Muestra un icono usando el componente `<Icon>`. +Un icono requiere un [`name`](#name) establecido en [uno de los iconos integrados de Starlight](/es/reference/icons/#todos-los-iconos) y opcionalmente puede incluir un [`label`](#label) para proporcionar contexto a los lectores de pantalla. + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" /> +<Icon name="starlight" label="El logo de Starlight" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" /%} +{% icon name="starlight" label="El logo de Starlight" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" /> + <Icon name="starlight" label="El logo de Starlight" /> +</Fragment> + +</Preview> + +### Personalizar iconos + +Los atributos [`size`](#size) y [`color`](#color) se pueden usar para ajustar la apariencia del icono utilizando unidades CSS y valores de color. +El atributo [`class`](#class) se puede usar para agregar clases CSS personalizadas al icono. + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" color="goldenrod" size="2rem" /> +<Icon name="rocket" color="var(--sl-color-text-accent)" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" color="goldenrod" size="2rem" /%} +{% icon name="rocket" color="var(--sl-color-text-accent)" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" color="goldenrod" size="2rem" /> + <Icon name="rocket" color="var(--sl-color-text-accent)" /> +</Fragment> + +</Preview> + +## Props de `<Icon>` + +**Implementación:** [`Icon.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Icon.astro) + +El componente `<Icon>` acepta las siguientes propiedades: + +### `name` + +**requerido** +**tipo:** `string` + +El nombre del icono a mostrar establecido en [uno de los iconos integrados de Starlight](/es/reference/icons/#todos-los-iconos). + +### `label` + +**tipo:** `string` + +Una etiqueta opcional para proporcionar contexto a las tecnologías de asistencia, como los lectores de pantalla. + +Cuando no se establece `label`, el icono estará completamente oculto para las tecnologías de asistencia. +En este caso, asegúrate de que el contexto siga siendo comprensible sin el icono. +Por ejemplo, un enlace que contenga solo el icono **debe** incluir el atributo `label` para ser accesible, pero si un enlace contiene texto y el icono es puramente decorativo, omitir el `label` puede tener sentido. + +### `size` + +**tipo:** `string` + +El tamaño de un icono usando unidades CSS. + +### `color` + +**tipo:** `string` + +El color de un icono utilizando un valor de color CSS. + +### `class` + +**tipo:** `string` + +Personaliza las clases CSS para agregar al icono. diff --git a/docs/src/content/docs/es/components/link-buttons.mdx b/docs/src/content/docs/es/components/link-buttons.mdx new file mode 100644 index 00000000000..62599b0d6ad --- /dev/null +++ b/docs/src/content/docs/es/components/link-buttons.mdx @@ -0,0 +1,145 @@ +--- +title: Botones de enlace +description: Aprende a crear botones de enlace en Starlight para enlaces de llamada a la acción visualmente distintos. +--- + +import { LinkButton } from '@astrojs/starlight/components'; + +Para mostrar enlaces de llamada a la acción visualmente distintos, usa el componente `<LinkButton>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkButton slot="preview" href="/es/getting-started/"> + Lee la documentación +</LinkButton> + +</Preview> + +## Importación + +```tsx +import { LinkButton } from '@astrojs/starlight/components'; +``` + +## Uso + +Usa el componente `<LinkButton>` para mostrar un enlace de llamada a la acción visualmente distinto. +Un botón de enlace es útil para dirigir a los usuarios al contenido más relevante o accionable y se usa a menudo en páginas de destino. + +Un `<LinkButton>` requiere un atributo [`href`](#href). +Opcionalmente, personaliza la apariencia del botón de enlace usando el atributo [`variant`](#variant), que se puede establecer en `primary` (el valor predeterminado), `secondary` o `minimal`. + +<Preview> + +```mdx +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton href="/es/getting-started/">Comienza</LinkButton> +<LinkButton href="/es/reference/configuration/" variant="secondary"> + Referencia de configuración +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkbutton href="/es/getting-started/" %}Comienza{% /linkbutton %} + +{% linkbutton href="/es/reference/configuration/" variant="secondary" %} +Referencia de configuración +{% /linkbutton %} +``` + +</Fragment> + +<Fragment slot="preview"> + <LinkButton href="/es/getting-started/">Comienza</LinkButton> + <LinkButton href="/es/reference/configuration/" variant="secondary"> + Referencia de configuración + </LinkButton> +</Fragment> + +</Preview> + +### Agregar iconos a los botones de enlace + +Incluye un icono en un botón de enlace usando el atributo [`icon`](#icon) establecido en el nombre de [uno de los iconos integrados de Starlight](/es/reference/icons/#todos-los-iconos). + +El atributo [`iconPlacement`](#iconplacement) se puede usar para colocar el icono antes del texto estableciéndolo en `start` (el valor predeterminado es `end`). + +<Preview> + +```mdx {6-7} +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" +> + Relacionado: Astro +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc {4-5} +{% linkbutton + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" %} +Relacionado: Astro +{% /linkbutton %} +``` + +</Fragment> + +<LinkButton + slot="preview" + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" +> + Relacionado: Astro +</LinkButton> + +</Preview> + +## Props de `<LinkButton>` + +**Implementación:** [`LinkButton.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkButton.astro) + +El componente `<LinkButton>` acepta las siguientes props y también cualquier [otro atributo `<a>`](https://developer.mozilla.org/es/docs/Web/HTML/Element/a): + +### `href` + +**requerido** +**tipo:** `string` + +El URL al que apunta el botón de enlace. + +### `variant` + +**tipo:** `'primary' | 'secondary' | 'minimal'` +**por defecto:** `'primary'` + +La apariencia del botón de enlace. +Establece `primary` para un enlace de llamada a la acción prominente que usa el color de acento del tema, `secondary` para un enlace menos prominente o `minimal` para un enlace con un estilo mínimo. + +### `icon` + +**tipo:** `string` + +Un botón de enlace puede incluir un atributo `icon` establecido en el nombre de [uno de los iconos integrados de Starlight](/es/reference/icons/#todos-los-iconos). + +### `iconPlacement` + +**tipo:** `'start' | 'end'` +**por defecto:** `'end'` + +Determina la ubicación del icono en relación con el texto del botón de enlace. diff --git a/docs/src/content/docs/es/components/link-cards.mdx b/docs/src/content/docs/es/components/link-cards.mdx new file mode 100644 index 00000000000..b92db5ab65b --- /dev/null +++ b/docs/src/content/docs/es/components/link-cards.mdx @@ -0,0 +1,128 @@ +--- +title: Tarjetas de enlace +description: Aprende a mostrar enlaces de forma destacada como tarjetas en Starlight. +sidebar: + order: 3 +--- + +import { LinkCard } from '@astrojs/starlight/components'; + +Para mostrar enlaces a diferentes páginas de forma destacada, utiliza el componente `<LinkCard>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkCard + slot="preview" + title="Personalización de Starlight" + description="Aprende a personalizar tu sitio de Starlight con estilos personalizados, fuentes y más." + href="/es/guides/customization/" +/> + +</Preview> + +## Importación + +```tsx +import { LinkCard } from '@astrojs/starlight/components'; +``` + +## Uso + +Mostrar un enlace de forma destacada utilizando el componente `<LinkCard>`. +Cada `<LinkCard>` requiere un atributo [`title`](#title) y un atributo [`href`](#href). + +<Preview> + +```mdx +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard + title="Creación de contenido en Markdown" + href="/es/guides/authoring-content/" +/> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkcard title="Creación de contenido en Markdown" href="/es/guides/authoring-content/" /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="Creación de contenido en Markdown" + href="/es/guides/authoring-content/" +/> + +</Preview> + +### Agregar una descripción de enlace + +Agrega una descripción breve a una tarjeta de enlace utilizando el atributo [`description`](#description). + +<Preview> + +```mdx {6} +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard + title="Internacionalización" + href="/es/guides/i18n/" + description="Configura Starlight para admitir varios idiomas." +/> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% linkcard + title="Internacionalización" + href="/es/guides/i18n/" + description="Configura Starlight para admitir varios idiomas." /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="Internacionalización" + href="/es/guides/i18n/" + description="Configura Starlight para admitir varios idiomas." +/> + +</Preview> + +### Agrupar tarjetas de enlace + +Muestra varias tarjetas de enlace una al lado de la otra cuando hay suficiente espacio agrupándolas con el componente [`<CardGrid>`](/es/components/card-grids/). +Ve la guía [“Agrupar tarjetas de enlace”](/es/components/card-grids/#agrupar-tarjetas) para un ejemplo. + +## Props de `<LinkCard>` + +**Implementación:** [`LinkCard.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkCard.astro) + +El componente `<LinkCard>` acepta las siguientes propiedades, así como todos los demás atributos de los elementos [`<a>`](https://developer.mozilla.org/es/docs/Web/HTML/Element/a): + +### `title` + +**requerido** +**tipo:** `string` + +El título de la tarjeta de enlace a mostrar. + +### `href` + +**requerido** +**tipo:** `string` + +El URL al que enlazar cuando se interactúa con la tarjeta. + +### `description` + +**tipo:** `string` + +Una descripción opcional para mostrar debajo del título. diff --git a/docs/src/content/docs/es/components/steps.mdx b/docs/src/content/docs/es/components/steps.mdx new file mode 100644 index 00000000000..5cd1e596075 --- /dev/null +++ b/docs/src/content/docs/es/components/steps.mdx @@ -0,0 +1,120 @@ +--- +title: Pasos +description: Aprende como dar estilo a listas numeradas de tareas para crear guías paso a paso en Starlight. +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +Para estilar una lista numerada de tareas para crear guías paso a paso, utiliza el componente `<Steps>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Steps slot="preview"> + +1. Crea un nuevo proyecto de Starlight: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm create astro@latest -- --template starlight + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm create astro --template starlight + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn create astro --template starlight + ``` + + </TabItem> + + </Tabs> + +2. Escribe tu primera página de documentación. + +</Steps> + +</Preview> + +## Importación + +```tsx +import { Steps } from '@astrojs/starlight/components'; +``` + +## Uso + +Usa el componente `<Steps>` para estilar listas numeradas de tareas. +Esto es útil para guías paso a paso más complejas donde cada paso necesita ser claramente resaltado. + +Envuelve `<Steps>` alrededor de una lista ordenada de Markdown estándar. +Toda la sintaxis de Markdown estándar es aplicable dentro de `<Steps>`. + +<Preview> + +````mdx +import { Steps } from '@astrojs/starlight/components'; + +<Steps> + +1. Importa el componente en tu archivo MDX: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Envuelve `<Steps>` alrededor de tus elementos de lista ordenada. + +</Steps> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% steps %} + +1. Importa el componente en tu archivo MDX: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Envuelve `<Steps>` alrededor de tus elementos de lista ordenada. + +{% /steps %} +```` + +</Fragment> + +<Steps slot="preview"> + +1. Importa el componente en tu archivo MDX: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Envuelve `<Steps>` alrededor de tus elementos de lista ordenada. + +</Steps> + +</Preview> + +## Props de `<Steps>` + +**Implementación:** [`Steps.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Steps.astro) + +El componente `<Steps>` no acepta ninguna propiedad. diff --git a/docs/src/content/docs/es/components/tabs.mdx b/docs/src/content/docs/es/components/tabs.mdx new file mode 100644 index 00000000000..fb4c4be210d --- /dev/null +++ b/docs/src/content/docs/es/components/tabs.mdx @@ -0,0 +1,221 @@ +--- +title: Pestañas +description: Aprende a crear interfaces con pestañas en Starlight para agrupar información equivalente. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +Para crear una interfaz con pestañas usa los componentes `<Tabs>` y `<TabItem>`. +Las pestañas son útiles para agrupar información equivalente donde un usuario solo necesita ver una de varias opciones. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Tabs slot="preview"> + <TabItem label="Estrellas">Sirius, Vega, Betelgeuse</TabItem> + <TabItem label="Lunas">Io, Europa, Ganymede</TabItem> +</Tabs> + +</Preview> + +## Importación + +```tsx +import { Tabs, TabItem } from '@astrojs/starlight/components'; +``` + +## Uso + +Muestra una interfaz con pestañas usando los componentes `<Tabs>` y `<TabItem>`. +Cada `<TabItem>` debe tener una [`label`](#label) para mostrar a los usuarios. + +<Preview> + +```mdx +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="Estrellas">Sirius, Vega, Betelgeuse</TabItem> + <TabItem label="Lunas">Io, Europa, Ganymede</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% tabs %} +{% tabitem label="Estrellas" %} +Sirius, Vega, Betelgeuse +{% /tabitem %} + +{% tabitem label="Lunas" %} +Io, Europa, Ganymede +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="Estrellas">Sirius, Vega, Betelgeuse</TabItem> + <TabItem label="Lunas">Io, Europa, Ganymede</TabItem> +</Tabs> + +</Preview> + +### Sincronizar pestañas + +Mantén sincronizados varios grupos de pestañas agregando el atributo [`syncKey`](#synckey). + +Todos las `<Tabs>` en una página con el mismo valor de `syncKey` mostrarán la misma etiqueta activa. +Esto permite que el lector elija una vez (por ejemplo, su sistema operativo o administrador de paquetes) y vea su elección persistida a través de las navegaciones de página. + +Para sincronizar pestañas relacionadas, agrega una propiedad `syncKey` idéntica a cada componente `<Tabs>` y asegúrate de que todos usen las mismas etiquetas `<TabItem>`: + +<Preview> + +```mdx 'syncKey="constelaciones"' +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +_Algunas estrellas:_ + +<Tabs syncKey="constelaciones"> + <TabItem label="Orion">Bellatrix, Rigel, Betelgeuse</TabItem> + <TabItem label="Gemini">Pollux, Castor A, Castor B</TabItem> +</Tabs> + +_Algunos exoplanetas:_ + +<Tabs syncKey="constelaciones"> + <TabItem label="Orion">HD 34445 b, Gliese 179 b, Wasp-82 b</TabItem> + <TabItem label="Gemini">Pollux b, HAT-P-24b, HD 50554 b</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc 'syncKey="constelaciones"' +_Algunas estrellas:_ + +{% tabs syncKey="constelaciones" %} +{% tabitem label="Orion" %} +Bellatrix, Rigel, Betelgeuse +{% /tabitem %} + +{% tabitem label="Gemini" %} +Pollux, Castor A, Castor B +{% /tabitem %} +{% /tabs %} + +_Algunos exoplanetas:_ + +{% tabs syncKey="constelaciones" %} +{% tabitem label="Orion" %} +HD 34445 b, Gliese 179 b, Wasp-82 b +{% /tabitem %} + +{% tabitem label="Gemini" %} +Pollux b, HAT-P-24b, HD 50554 b +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Fragment slot="preview"> + +_Algunas estrellas:_ + +<Tabs syncKey="constelaciones"> + <TabItem label="Orion">Bellatrix, Rigel, Betelgeuse</TabItem> + <TabItem label="Gemini">Pollux, Castor A, Castor B</TabItem> +</Tabs> + +_Algunos exoplanetas:_ + +<Tabs syncKey="constelaciones"> + <TabItem label="Orion">HD 34445 b, Gliese 179 b, Wasp-82 b</TabItem> + <TabItem label="Gemini">Pollux b, HAT-P-24b, HD 50554 b</TabItem> +</Tabs> + +</Fragment> + +</Preview> + +### Agregar iconos a las pestañas + +Incluye un icono en un elemento de pestaña usando el atributo [`icon`](#icon) establecido en el nombre de [uno de los iconos integrados de Starlight](/es/reference/icons/#todos-los-iconos) para mostrar un icono junto a la etiqueta. + +<Preview> + +```mdx /icon="\w+"/ +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="Estrellas" icon="star"> + Sirius, Vega, Betelgeuse + </TabItem> + <TabItem label="Lunas" icon="moon"> + Io, Europa, Ganymede + </TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc /icon="\w+"/ +{% tabs %} +{% tabitem label="Estrellas" icon="star" %} +Sirius, Vega, Betelgeuse +{% /tabitem %} + +{% tabitem label="Lunas" icon="moon" %} +Io, Europa, Ganymede +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="Estrellas" icon="star"> + Sirius, Vega, Betelgeuse + </TabItem> + <TabItem label="Lunas" icon="moon"> + Io, Europa, Ganymede + </TabItem> +</Tabs> + +</Preview> + +## Props de `<Tabs>` + +**Implementación:** [`Tabs.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Tabs.astro) + +El componente `<Tabs>` agrupa varios componentes `<TabItem>` y acepta las siguientes propiedades: + +### `syncKey` + +**tipo:** `string` + +Una clave utilizada para mantener sincronizados varios grupos de pestañas en varias páginas. + +## Props de `<TabItem>` + +**Implementación:** [`TabItem.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/TabItem.astro) + +Un conjunto de pestañas está compuesto por elementos de pestaña, cada uno con las siguientes propiedades: + +### `label` + +**requerido** +**tipo:** `string` + +Un elemento de pestaña debe incluir un atributo `label` establecido en el texto que se mostrará en la pestaña. + +### `icon` + +**tipo:** `string` + +Cada elemento de pestaña puede incluir un atributo `icon` establecido en el nombre de [uno de los iconos integrados de Starlight](/es/reference/icons/#todos-los-iconos) para mostrar un icono junto a la etiqueta. diff --git a/docs/src/content/docs/es/components/using-components.mdx b/docs/src/content/docs/es/components/using-components.mdx new file mode 100644 index 00000000000..89ffab7ee6c --- /dev/null +++ b/docs/src/content/docs/es/components/using-components.mdx @@ -0,0 +1,97 @@ +--- +title: Usando componentes +description: Usando componentes en MDX y Markdoc con Starlight. +sidebar: + order: 1 +--- + +Los componentes te permiten reutilizar fácilmente un fragmento de UI o estilos de manera consistente. +Los ejemplos pueden incluir una tarjeta de enlace o un incrustado de YouTube. +Starlight admite el uso de componentes en archivos [MDX](https://mdxjs.com/) y [Markdoc](https://markdoc.dev/) y proporciona algunos componentes comunes para que los uses. + +[Conoce más sobre la construcción de componentes en la documentación de Astro](https://docs.astro.build/es/core-concepts/astro-components/). + +## Usando un componente en MDX + +Puedes usar un componente importándolo en tu archivo MDX y luego renderizándolo como una etiqueta JSX. +Estos se ven como etiquetas HTML pero comienzan con una letra mayúscula que coincide con el nombre en tu declaración de `import`: + +```mdx +--- +# src/content/docs/example.mdx +title: Bienvenido a mi documentación +--- + +import { Icon } from '@astrojs/starlight/components'; +import CustomCard from '../../components/CustomCard.astro'; + +<Icon name="open-book" /> + +<CustomCard> + Los componentes también pueden contener **contenido anidado**. +</CustomCard> +``` + +Debido a que Starlight está impulsado por Astro, puedes agregar soporte para componentes construidos con cualquier [framework de UI compatible (React, Preact, Svelte, Vue, Solid y Alpine)](https://docs.astro.build/es/core-concepts/framework-components/) en tus archivos MDX. +{/* TODO: Actualizar esta liga cuando los docs en español de Astro incluyan el fragmento de la versión en inglés. */} +Aprende más sobre [usar componentes en MDX](https://docs.astro.build/en/guides/integrations-guide/mdx/#using-components-in-mdx) en la documentación de Astro. + +## Usando un componente en Markdoc + +Agrega soporte para la creación de contenido en Markdoc siguiendo nuestra [guía de configuración de Markdoc](/es/guides/authoring-content/#markdoc). + +Usando el preset de Starlight Markdoc, puedes usar los componentes incorporados de Starlight con la sintaxis de etiqueta de Markdoc `{% %}`. +A diferencia de MDX, los componentes en Markdoc no necesitan ser importados. +El siguiente ejemplo renderiza el [componente de tarjeta](/es/components/cards/) de Starlight en un archivo Markdoc: + +```markdoc +--- +# src/content/docs/example.mdoc +title: Bienvenido a mi documentación +--- + +{% card title="Estrellas" icon="star" %} +Sirius, Vega, Betelgeuse +{% /card %} +``` + +Ver la [documentación de integración de Astro Markdoc](https://docs.astro.build/es/guides/integrations-guide/markdoc/#render-components) para más información sobre cómo usar componentes en archivos Markdoc. + +## Componentes incorporados + +Starlight proporcona componentes integrados para casos de uso comunes en la documentación. +Estos componentes están disponibles en el paquete `@astrojs/starlight/components` en archivos MDX y en el [preset de Starlight Markdoc](/es/guides/authoring-content/#markdoc) en archivos Markdoc. + +Ve la barra lateral para una lista de componentes disponibles y cómo usarlos. + +## Compatibilidad con los estilos de Starlight + +Starlight aplica estilos predeterminados a tu contenido de Markdown, por ejemplo, agregando márgenes entre elementos. +Si estos estilos entran en conflicto con la apariencia de tu componente, establece la clase `not-content` en tu componente para deshabilitarlos. + +```astro 'class="not-content"' +--- +// src/components/Example.astro +--- + +<div class="not-content"> + <p>No se ve afectado por los estilos predeterminados de Starlight.</p> +</div> +``` + +## Props de componentes + +Usa el tipo [`ComponentProps`](https://docs.astro.build/es/guides/typescript/#tipo-componentprops) de `astro/types` para hacer referencia a las `Props` aceptadas por un componente incluso si no están exportadas por el componente en sí. +Esto puede ser util al envolver o extender un componente existente. + +El siguiente ejemplo usa `ComponentProps` para obtener el tipo de las props aceptadas por el componente `Icon` incorporado de Starlight: + +```astro +--- +// src/components/Example.astro +import type { ComponentProps } from 'astro/types'; +import { Icon } from '@astrojs/starlight/icon'; + +type IconProps = ComponentProps<typeof Icon>; +--- +``` diff --git a/docs/src/content/docs/es/environmental-impact.md b/docs/src/content/docs/es/environmental-impact.md index 32c24f7f6fa..95896bb4eb7 100644 --- a/docs/src/content/docs/es/environmental-impact.md +++ b/docs/src/content/docs/es/environmental-impact.md @@ -73,20 +73,21 @@ Elegir un proveedor de alojamiento que utilice energía renovable significa tene ¿Curioso por saber cómo se comparan otros frameworks de documentación? Estas pruebas con el [Calculadora de Carbono de Sitios Web][wcc] comparan páginas similares construidas con diferentes herramientas. -| Framework | CO₂ por visita a la página | -| --------------------------- | -------------------------- | -| [Starlight][sl-carbon] | 0.01g | -| [VitePress][vp-carbon] | 0.05g | -| [Docus][dc-carbon] | 0.05g | -| [Sphinx][sx-carbon] | 0.07g | -| [MkDocs][mk-carbon] | 0.10g | -| [Nextra][nx-carbon] | 0.11g | -| [docsify][dy-carbon] | 0.11g | -| [Docusaurus][ds-carbon] | 0.24g | -| [Read the Docs][rtd-carbon] | 0.24g | -| [GitBook][gb-carbon] | 0.71g | - -<small>Datos recopilados el 14 de mayo de 2023. Haz clic en un enlace para ver cifras actualizadas.</small> +| Framework | CO₂ por visita a la página | Calificación | +| --------------------------- | -------------------------- | :----------: | +| [Starlight][sl-carbon] | 0.01g | A+ | +| [Read the Docs][rtd-carbon] | 0.05g | A+ | +| [Sphinx][sx-carbon] | 0.06g | A+ | +| [VitePress][vp-carbon] | 0.07g | A+ | +| [Docus][dc-carbon] | 0.09g | A+ | +| [docsify][dy-carbon] | 0.10g | A | +| [Nextra][nx-carbon] | 0.11g | A | +| [MkDocs][mk-carbon] | 0.19g | B | +| [Docusaurus][ds-carbon] | 0.21g | B | +| [GitBook][gb-carbon] | 0.43g | C | +| [Mintlify][mt-carbon] | 1.22g | F | + +<small>Datos recopilados el 22 de Julio de 2024. Haz clic en un enlace para ver cifras actualizadas.</small> [sl-carbon]: https://www.websitecarbon.com/website/starlight-astro-build-getting-started/ [vp-carbon]: https://www.websitecarbon.com/website/vitepress-dev-guide-what-is-vitepress/ @@ -98,6 +99,7 @@ Estas pruebas con el [Calculadora de Carbono de Sitios Web][wcc] comparan págin [ds-carbon]: https://www.websitecarbon.com/website/docusaurus-io-docs/ [rtd-carbon]: https://www.websitecarbon.com/website/docs-readthedocs-io-en-stable-index-html/ [gb-carbon]: https://www.websitecarbon.com/website/docs-gitbook-com/ +[mt-carbon]: https://www.websitecarbon.com/website/mintlify-com-docs-quickstart/ ## Más recursos diff --git a/docs/src/content/docs/es/getting-started.mdx b/docs/src/content/docs/es/getting-started.mdx index 68381bb5049..a8c44dae81a 100644 --- a/docs/src/content/docs/es/getting-started.mdx +++ b/docs/src/content/docs/es/getting-started.mdx @@ -5,17 +5,20 @@ description: Aprende cómo empezar a construir tu próximo sitio de documentaci import { Tabs, TabItem } from '@astrojs/starlight/components'; -## Creando un nuevo proyecto - Starlight es un tema de documentación completo construido sobre el framework [Astro](https://astro.build). +Esta guía te ayudará a comenzar con un nuevo proyecto. +Consulta las [instrucciones de configuración manual](/es/manual-setup/) para agregar Starlight a un proyecto de Astro existente. + +## Inicio rápido + +### Crea un nuevo proyecto -Puedes crear un nuevo proyecto de Astro + Starlight utilizando el siguiente comando: +Crea un nuevo proyecto de Astro + Starlight ejecutando el siguiente comando en tu terminal: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# crear un nuevo proyecto con npm npm create astro@latest -- --template starlight ``` @@ -23,7 +26,6 @@ npm create astro@latest -- --template starlight <TabItem label="pnpm"> ```sh -# crear un nuevo proyecto con pnpm pnpm create astro --template starlight ``` @@ -31,7 +33,6 @@ pnpm create astro --template starlight <TabItem label="Yarn"> ```sh -# crear un nuevo proyecto con yarn yarn create astro --template starlight ``` @@ -45,85 +46,95 @@ Prueba Starlight en tu navegador: [abre la plantilla en StackBlitz](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). ::: -## Creando contenido con Starlight +### Inicia el servidor de desarrollo -Starlight está listo para que añadas nuevo contenido o traigas tus archivos existentes. +Cuando trabajas localmente, el [servidor de desarrollo de Astro](https://docs.astro.build/es/reference/cli-reference/#astro-dev) te permite previsualizar tu trabajo y actualiza automáticamente tu navegador cuando realizas cambios. -### Formatos de archivo +Dentro del directorio de tu proyecto, ejecuta el siguiente comando para iniciar el servidor de desarrollo: -Starlight admite la creación de contenido en Markdown y MDX. (Puedes agregar compatibilidad con Markdoc instalando la integración experimental de [Astro Markdoc](https://docs.astro.build/es/guides/integrations-guide/markdoc/).) +<Tabs syncKey="pkg"> +<TabItem label="npm"> -### Agregar páginas +```sh +npm run dev +``` -Agrega nuevas páginas a tu sitio automáticamente creando archivos `.md` o `.mdx` en `src/content/docs/`. Agrega subcarpetas para organizar tus archivos y crear segmentos de ruta múltiples. +</TabItem> +<TabItem label="pnpm"> +```sh +pnpm dev ``` -src/content/docs/hello-world.md => tu-sitio.com/hello-world -src/content/docs/guides/faq.md => tu-sitio.com/guides/faq + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev ``` -### Frontmatter con seguridad de tipos +</TabItem> +</Tabs> + +Esto imprimirá un mensaje en tu terminal con la URL de la vista previa local. +Abre esta URL para comenzar a navegar por tu sitio. -Todas las páginas de Starlight comparten un [conjunto común personalizable de propiedades frontmatter](/es/reference/frontmatter/) para controlar cómo se muestra la página: +### Añade contenido -```md ---- -title: ¡Hola, Mundo! -description: Esta es una página en mi sitio impulsado por Starlight ---- -``` +Starlight está listo para que añadas nuevo contenido o ¡traigas tus archivos existentes!. -Si olvidas algo importante, Starlight te lo hará saber. +Agrega nuevas páginas a tu sitio web creando archivos Markdown en el directorio `src/content/docs/`. -## Desplegando tu sitio web de Starlight +Lee más sobre el enrutamiento basado en archivos y el soporte para archivos MDX y Markdoc en la [Guía de Páginas](/es/guides/pages/) -Una vez que hayas creado y personalizado tu sitio web de Starlight, puedes implementarlo en un servidor web o plataforma de alojamiento de tu elección, incluyendo Netlify, Vercel, GitHub Pages y muchos más. +### Siguientes pasos -[Aprende sobre cómo desplegar un sitio Astro en la documentación de Astro.](https://docs.astro.build/es/guides/deploy/) +- **Configura:** Aprende acerca de las opciones comunes en [“Personalizando Starlight”](/es/guides/customization/). +- **Navega:** Configura tu barra lateral siguiendo la guía [“Barra Lateral de Navegación”](/es/guides/sidebar/). +- **Componentes:** Descubre tarjetas incorporadas, pestañas y más en la guía [“Componentes”](/es/components/using-components/). +- **Despliega:** Publica tu trabajo siguiendo la guía [“Despliega tu sitio”](https://docs.astro.build/es/guides/deploy/) en la documentación de Astro. ## Actualizando Starlight :::tip -Debido a que Starlight es un software beta, habrá actualizaciones y mejoras frecuentes. ¡Asegúrate de actualizar Starlight regularmente! +Debido a que Starlight es un software beta, habrá actualizaciones y mejoras frecuentes. +¡Asegúrate de actualizar Starlight regularmente! ::: -Starlight es una integración Astro y se actualiza de la misma manera que cualquier otra integración `@astrojs/*`: +Starlight es una integración Astro. Puedes actualizarlo y otros paquetes de Astro ejecutando el siguiente comando en tu terminal: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# actualizar Starlight con npm -npm install @astrojs/starlight@latest +npx @astrojs/upgrade ``` </TabItem> <TabItem label="pnpm"> ```sh -# actualizar Starlight con pnpm -pnpm upgrade @astrojs/starlight --latest +pnpm dlx @astrojs/upgrade ``` </TabItem> <TabItem label="Yarn"> ```sh -# actualizar Starlight con yarn -yarn upgrade @astrojs/starlight --latest +yarn dlx @astrojs/upgrade ``` </TabItem> </Tabs> -Puedes ver una lista completa de los cambios realizados en cada versión en [el registro de cambios de Starlight](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md). +Consulta el [registro de cambios de Starlight](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md) para obtener una lista completa de los cambios realizados en cada versión. ## Solución de problemas de Starlight -Tanto la [configuración del proyecto](/es/reference/configuration/) como la [configuración individual de frontmatter](/es/reference/frontmatter/) de cada página están disponibles en la sección de Referencia de este sitio. Utiliza estas páginas para asegurarte de que tu sitio Starlight está configurado y funcionando correctamente. - -Revisa la creciente lista de guías en la barra lateral para obtener ayuda para agregar contenido y personalizar tu sitio Starlight. +Utiliza las páginas de referencia de [configuración del proyecto](/es/reference/configuration/) y [configuración del frontmatter de páginas individuales](/es/reference/frontmatter/) para asegurarte de que tu sitio de Starlight esté configurado y funcione correctamente. +Consulta las guías en la barra lateral para obtener ayuda en la adición de contenido y personalización de tu sitio de Starlight. -Si no encuentras la respuesta en la documentación, visita la [documentación completa de Astro](https://docs.astro.build) para obtener la documentación completa de Astro. Es posible que tu pregunta se responda comprendiendo cómo funciona Astro en general, debajo de este tema Starlight. +Si no encuentras la respuesta en la documentación, visita la [documentación completa de Astro](https://docs.astro.build/es/) para obtener la documentación completa de Astro. +Es posible que tu pregunta se responda comprendiendo cómo funciona Astro en general, debajo de este tema Starlight. También puedes revisar cualquier problema conocido de [Starlight en GitHub](https://github.com/withastro/starlight/issues) y obtener ayuda en el [Discord de Astro](https://astro.build/chat/) de nuestra activa y amigable comunidad. ¡Publica preguntas en nuestro foro `#support` con la etiqueta "starlight" o visita nuestro canal dedicado `#starlight` para discutir el desarrollo actual y más! diff --git a/docs/src/content/docs/es/guides/authoring-content.md b/docs/src/content/docs/es/guides/authoring-content.md deleted file mode 100644 index 67a66181159..00000000000 --- a/docs/src/content/docs/es/guides/authoring-content.md +++ /dev/null @@ -1,208 +0,0 @@ ---- -title: Creación de contenido en Markdown -description: Una descripción general de la sintaxis Markdown que soporta Starlight. ---- - -Starlight admite la gama completa de la sintaxis [Markdown](https://daringfireball.net/projects/markdown/) en archivos `.md`, así como el frontmatter en [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) para definir metadatos como el título y la descripción. - -Por favor, asegúrate de consultar la documentación de [MDX](https://mdxjs.com/docs/what-is-mdx/#markdown) o [Markdoc](https://markdoc.dev/docs/syntax) si estás utilizando esos formatos de archivo, ya que el soporte y el uso de Markdown pueden variar. - -## Estilos en línea - -El texto puede estar **en negrita**, _en cursiva_, o ~~tachado~~. - -```md -El texto puede estar **en negrita**, _en cursiva_, o ~~tachado~~. -``` - -Puedes [enlazar a otra página](/es/getting-started/). - -```md -Puedes [enlazar a otra página](/es/getting-started/). -``` - -Puedes resaltar `código en línea` con comillas invertidas. - -```md -Puedes resaltar `código en línea` con comillas invertidas. -``` - -## Imágenes - -Las imágenes en Starlight utilizan el [soporte de assets optimizados incorporado en Astro](https://docs.astro.build/en/guides/assets/). - -Markdown y MDX admiten la sintaxis Markdown para mostrar imágenes, que incluye alt-text para lectores de pantalla y tecnología de asistencia. - -![Una ilustración de planetas y estrellas con la palabra “astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) - -```md -![Una ilustración de planetas y estrellas con la palabra “astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) -``` - -También se admiten rutas de imágenes relativas para imágenes almacenadas localmente en tu proyecto. - -```md -// src/content/docs/page-1.md - -![Una nave espacial en el espacio](../../assets/images/rocket.svg) -``` - -## Encabezados - -Puedes estructurar el contenido utilizando encabezados. Los encabezados en Markdown se indican con uno o más `#` al comienzo de la línea. - -### Cómo estructurar el contenido de la página en Starlight - -Starlight está configurado para utilizar automáticamente el título de tu página como un encabezado de nivel superior y se incluirá un encabezado "Visión general" en la parte superior de la tabla de contenido de cada página. Recomendamos comenzar cada página con contenido de texto de párrafo regular y utilizar encabezados dentro de la página a partir de `<h2>` en adelante: - -```md ---- -title: Guía de Markdown -description: Cómo utilizar Markdown en Starlight ---- - -Esta página describe cómo utilizar Markdown en Starlight. - -## Estilos en línea - -## Encabezados -``` - -### Enlaces de anclaje automáticos para encabezados. - -Al utilizar encabezados en Markdown, se generan automáticamente enlaces de anclaje para que puedas vincular directamente a ciertas secciones de tu página: - -```md ---- -title: Mi página de contenido -description: Cómo utilizar los enlaces de anclaje integrados de Starlight. ---- - -## Introducción - -Puedo enlazar a [mi conclusión](#conclusión) más abajo en la misma página. - -## Conclusión - -`https://mi-sitio.com/page1/#introduction` navega directamente a mi Introducción. -``` - -Los encabezados de nivel 2 (`<h2>`) y nivel 3 (`<h3>`) aparecerán automáticamente en la tabla de contenido de la página. - -## Apartados - -Los apartados (también conocidos como “apartados” o ”contenido destacado”) son útiles para mostrar información secundaria junto al contenido principal de una página. - -Starlight proporciona una sintaxis personalizada de Markdown para renderizar apartados. Los bloques de apartados se indican utilizando un par de triples dos puntos `:::` para envolver tu contenido, y pueden ser de tipo `note`, `tip`, `caution` o `danger`. - -Puedes anidar cualquier otro tipo de contenido Markdown dentro de un apartado, pero los apartados son más adecuados para fragmentos de contenido cortos y concisos. - -### Nota de apartados - -:::note -Starlight es un conjunto de herramientas para crear sitios web de documentación construido con [Astro](https://astro.build/). Puedes comenzar con este comando: - -```sh -npm run create astro@latest --template starlight -``` - -::: - -````md -:::note -Starlight es un conjunto de herramientas para sitios de documentación construido con [Astro](https://astro.build/). Puedes comenzar con este comando: - -```sh -npm run create astro@latest --template starlight -``` - -::: -```` - -### Títulos personalizados para los apartados - -Puedes especificar un título personalizado para el apartado utilizando corchetes cuadrados después del tipo del apartado, por ejemplo, `:::tip[¿Sabías esto?]`. - -:::tip[¿Sabías esto?] -Astro te ayuda a construir sitios web más rápidos con la[“Arquitectura de Islas”](https://docs.astro.build/es/concepts/islands/). -::: - -```md -:::tip[¿Sabías esto?] -Astro te ayuda a construir sitios web más rápidos con la[“Arquitectura de Islas”](https://docs.astro.build/es/concepts/islands/). -::: -``` - -### Más tipos de apartados - -Los apartados de caution y danger son útiles para llamar la atención del usuario sobre detalles que podrían generar problemas. Si te encuentras utilizando estos tipos de apartados con frecuencia, también puede ser una señal de que lo que estás documentando podría beneficiarse de una reestructuración o rediseño. - -:::caution -Si no estás seguro de si deseas un sitio de documentación increíble, piénsalo dos veces antes de usar [Starlight](../../). -::: - -:::danger -Tus usuarios pueden ser más productivos y encontrar más fácil de usar tu producto gracias a las útiles características de Starlight. - -- Navegación clara -- Tema de color configurable por el usuario -- [Soporte de i18n](/guides/i18n) - -::: - -```md -:::caution -Si no estás seguro de si deseas un sitio de documentación increíble, piénsalo dos veces antes de usar [Starlight](../../). -::: - -:::danger -Tus usuarios pueden ser más productivos y encontrar más fácil de usar tu producto gracias a las útiles características de Starlight. - -- Navegación clara -- Tema de color configurable por el usuario -- [Soporte de i18n](/guides/i18n) - -::: -``` - -## Citas en bloque - -> Esto es una cita en bloque, que se utiliza comúnmente para citar a otra persona o documento. -> -> Las citas en bloque se indican con un `>` al inicio de cada línea. - -```md -> Esto es una cita en bloque, que se utiliza comúnmente para citar a otra persona o documento. -> -> Las citas en bloque se indican con un `>` al inicio de cada línea. -``` - -## Bloques de código - -Un bloque de código se indica con un bloque de tres comillas invertidas <code>```</code> al inicio y al final. Puedes indicar el lenguaje de programación que se está utilizando después de las comillas invertidas de apertura. - -```js -// Código JavaScript con resaltado de sintaxis. -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` - -````md -```js -// Código JavaScript con resaltado de sintaxis. -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` -```` - -```md -Los bloques de código largos de una sola línea no deben ajustarse automáticamente. Deben desplazarse horizontalmente si son demasiado largos. Esta línea debe ser lo suficientemente larga para demostrar esto. -``` - -## Otras características comunes de Markdown - -Starlight admite todas las demás sintaxis de autoría de Markdown, como listas y tablas. Puedes consultar la [Guía de referencia de Markdown](https://www.markdownguide.org/cheat-sheet/) para obtener una descripción general rápida de todos los elementos de sintaxis de Markdown. diff --git a/docs/src/content/docs/es/guides/authoring-content.mdx b/docs/src/content/docs/es/guides/authoring-content.mdx new file mode 100644 index 00000000000..7f8fee2778a --- /dev/null +++ b/docs/src/content/docs/es/guides/authoring-content.mdx @@ -0,0 +1,509 @@ +--- +title: Creación de contenido en Markdown +description: Una descripción general de la sintaxis Markdown que soporta Starlight. +--- + +Starlight admite la gama completa de la sintaxis [Markdown](https://daringfireball.net/projects/markdown/) en archivos `.md`, así como el frontmatter en [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) para definir metadatos como el título y la descripción. + +Por favor, asegúrate de consultar la documentación de [MDX](https://mdxjs.com/docs/what-is-mdx/#markdown) o [Markdoc](https://markdoc.dev/docs/syntax) si estás utilizando esos formatos de archivo, ya que el soporte y el uso de Markdown pueden variar. + +## Frontmatter + +Puedes personalizar individualmente las páginas en Starlight estableciendo valores en el frontmatter. +El frontmatter se establece en la parte superior de tus archivos entre separadores `---`: + +```md title="src/content/docs/example.md" +--- +title: Mi título de página +--- + +El contenido de la página sigue luego de los `---`. +``` + +Cada página debe incluir al menos un `title`. +Consulta la [referencia de frontmatter](/es/reference/frontmatter/) para ver todos los campos disponibles y cómo añadir campos personalizados. + +## Estilos en línea + +El texto puede estar **en negrita**, _en cursiva_, o ~~tachado~~. + +```md +El texto puede estar **en negrita**, _en cursiva_, o ~~tachado~~. +``` + +Puedes [enlazar a otra página](/es/getting-started/). + +```md +Puedes [enlazar a otra página](/es/getting-started/). +``` + +Puedes resaltar `código en línea` con comillas invertidas. + +```md +Puedes resaltar `código en línea` con comillas invertidas. +``` + +## Imágenes + +Las imágenes en Starlight utilizan el [soporte de assets optimizados incorporado en Astro](https://docs.astro.build/en/guides/assets/). + +Markdown y MDX admiten la sintaxis Markdown para mostrar imágenes, que incluye alt-text para lectores de pantalla y tecnología de asistencia. + +![Una ilustración de planetas y estrellas con la palabra “astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) + +```md +![Una ilustración de planetas y estrellas con la palabra “astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) +``` + +También se admiten rutas de imágenes relativas para imágenes almacenadas localmente en tu proyecto. + +```md +// src/content/docs/page-1.md + +![Una nave espacial en el espacio](../../assets/images/rocket.svg) +``` + +## Encabezados + +Puedes estructurar el contenido utilizando encabezados. Los encabezados en Markdown se indican con uno o más `#` al comienzo de la línea. + +### Cómo estructurar el contenido de la página en Starlight + +Starlight está configurado para utilizar automáticamente el título de tu página como un encabezado de nivel superior y se incluirá un encabezado "Visión general" en la parte superior de la tabla de contenido de cada página. Recomendamos comenzar cada página con contenido de texto de párrafo regular y utilizar encabezados dentro de la página a partir de `<h2>` en adelante: + +```md +--- +title: Guía de Markdown +description: Cómo utilizar Markdown en Starlight +--- + +Esta página describe cómo utilizar Markdown en Starlight. + +## Estilos en línea + +## Encabezados +``` + +### Enlaces de anclaje automáticos para encabezados. + +Al utilizar encabezados en Markdown, se generan automáticamente enlaces de anclaje para que puedas vincular directamente a ciertas secciones de tu página: + +```md +--- +title: Mi página de contenido +description: Cómo utilizar los enlaces de anclaje integrados de Starlight. +--- + +## Introducción + +Puedo enlazar a [mi conclusión](#conclusión) más abajo en la misma página. + +## Conclusión + +`https://mi-sitio.com/page1/#introduction` navega directamente a mi Introducción. +``` + +Los encabezados de nivel 2 (`<h2>`) y nivel 3 (`<h3>`) aparecerán automáticamente en la tabla de contenido de la página. + +Aprende más sobre cómo Astro procesa los `id`s de los encabezados en [la documentación de Astro](https://docs.astro.build/es/guides/markdown-content/#ids-de-encabezado) + +## Apartados + +Los apartados (también conocidos como “apartados” o ”contenido destacado”) son útiles para mostrar información secundaria junto al contenido principal de una página. + +Starlight proporciona una sintaxis personalizada de Markdown para renderizar apartados. Los bloques de apartados se indican utilizando un par de triples dos puntos `:::` para envolver tu contenido, y pueden ser de tipo `note`, `tip`, `caution` o `danger`. + +Puedes anidar cualquier otro tipo de contenido Markdown dentro de un apartado, pero los apartados son más adecuados para fragmentos de contenido cortos y concisos. + +### Nota de apartados + +:::note +Starlight es un conjunto de herramientas para crear sitios web de documentación construido con [Astro](https://astro.build/). Puedes comenzar con este comando: + +```sh +npm run create astro@latest --template starlight +``` + +::: + +````md +:::note +Starlight es un conjunto de herramientas para sitios de documentación construido con [Astro](https://astro.build/). Puedes comenzar con este comando: + +```sh +npm run create astro@latest --template starlight +``` + +::: +```` + +### Títulos personalizados para los apartados + +Puedes especificar un título personalizado para el apartado utilizando corchetes cuadrados después del tipo del apartado, por ejemplo, `:::tip[¿Sabías esto?]`. + +:::tip[¿Sabías esto?] +Astro te ayuda a construir sitios web más rápidos con la[“Arquitectura de Islas”](https://docs.astro.build/es/concepts/islands/). +::: + +```md +:::tip[¿Sabías esto?] +Astro te ayuda a construir sitios web más rápidos con la[“Arquitectura de Islas”](https://docs.astro.build/es/concepts/islands/). +::: +``` + +### Más tipos de apartados + +Los apartados de caution y danger son útiles para llamar la atención del usuario sobre detalles que podrían generar problemas. Si te encuentras utilizando estos tipos de apartados con frecuencia, también puede ser una señal de que lo que estás documentando podría beneficiarse de una reestructuración o rediseño. + +:::caution +Si no estás seguro de si deseas un sitio de documentación increíble, piénsalo dos veces antes de usar [Starlight](/es/). +::: + +:::danger +Tus usuarios pueden ser más productivos y encontrar más fácil de usar tu producto gracias a las útiles características de Starlight. + +- Navegación clara +- Tema de color configurable por el usuario +- [Soporte de i18n](/es/guides/i18n/) + +::: + +```md +:::caution +Si no estás seguro de si deseas un sitio de documentación increíble, piénsalo dos veces antes de usar [Starlight](/es/). +::: + +:::danger +Tus usuarios pueden ser más productivos y encontrar más fácil de usar tu producto gracias a las útiles características de Starlight. + +- Navegación clara +- Tema de color configurable por el usuario +- [Soporte de i18n](/es/guides/i18n/) + +::: +``` + +## Citas en bloque + +> Esto es una cita en bloque, que se utiliza comúnmente para citar a otra persona o documento. +> +> Las citas en bloque se indican con un `>` al inicio de cada línea. + +```md +> Esto es una cita en bloque, que se utiliza comúnmente para citar a otra persona o documento. +> +> Las citas en bloque se indican con un `>` al inicio de cada línea. +``` + +## Bloques de código + +Un bloque de código se indica con un bloque de tres comillas invertidas <code>```</code> al inicio y al final. Puedes indicar el lenguaje de programación que se está utilizando después de las comillas invertidas de apertura. + +```js +// Código JavaScript con resaltado de sintaxis. +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` + +````md +```js +// Código JavaScript con resaltado de sintaxis. +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` +```` + +### Características de Expressive Code + +Starlight usa [Expressive Code](https://github.com/expressive-code/expressive-code/tree/main/packages/astro-expressive-code) para ampliar las posibilidades de formato de los bloques de código. +Los marcadores de texto de Expressive Code y los plugins de marcos de ventana están habilitados de forma predeterminada. +El renderizado de los bloques de código se puede configurar utilizando la opción de configuración [`expressiveCode`](/es/reference/configuration/#expressivecode) de Starlight. + +#### Marcadores de texto + +Puedes resaltar líneas específicas o partes de tus bloques de código utilizando [los marcadores de texto de Expressive Code](https://github.com/expressive-code/expressive-code/blob/main/packages/%40expressive-code/plugin-text-markers/README.md#usage-in-markdown--mdx-documents) en la línea de apertura de tu bloque de código. +Usa llaves (`{ }`) para resaltar líneas enteras, y comillas para resaltar cadenas de texto. + +Hay tres estilos de resaltado: neutral para llamar la atención sobre el código, verde para indicar código insertado y rojo para indicar código eliminado. +Tanto el texto como las líneas enteras pueden marcarse con el marcador predeterminado, o en combinación con `ins=` y `del=` para producir el resaltado deseado. + +Expressive Code proporciona varias opciones para personalizar la apariencia visual de tus ejemplos de código. +Muchas de estas opciones se pueden combinar, para obtener ejemplos de código altamente ilustrativos. +Por favor, explora la [documentación de Expressive Code](https://github.com/expressive-code/expressive-code/blob/main/packages/%40expressive-code/plugin-text-markers/README.md) para ver las extensas opciones disponibles. +Algunos de los ejemplos más comunes se muestran a continuación: + +- [Marca líneas enteras y rangos de líneas usando el marcador `{ }`](https://github.com/expressive-code/expressive-code/blob/main/packages/%40expressive-code/plugin-text-markers/README.md#marking-entire-lines--line-ranges): + + ```js {2-3} + function demo() { + // Esta línea (#2) y la siguiente están resaltadas + retrun 'Esta es la línea #3 de este fragmento' + } + ``` + + ````md + ```js {2-3} + function demo() { + // Esta línea (#2) y la siguiente están resaltadas + return 'Esta es la línea #3 de este fragmento'; + } + ``` + ```` + +- [Marca selecciones de texto usando el marcador `" "` o expresiones regulares](https://github.com/expressive-code/expressive-code/blob/main/packages/%40expressive-code/plugin-text-markers/README.md#marking-individual-text-inside-lines): + + ```js "Términos individuales" /También.*compatibles/ + // Términos individuales también pueden ser resaltados + function demo() { + return 'También las expresiones regulares son compatibles'; + } + ``` + + ````md + ```js "Términos individuales" /También.*compatibles/ + // Términos individuales también pueden ser resaltados + function demo() { + return 'También las expresiones regulares son compatibles'; + } + ``` + ```` + +- [Marca texto o líneas como insertadas o eliminadas con `ins` o `del`](https://github.com/expressive-code/expressive-code/blob/main/packages/%40expressive-code/plugin-text-markers/README.md#selecting-marker-types-mark-ins-del): + + ```js "return true;" ins="insertados" del="eliminados" + function demo() { + console.log('Estos son tipos de marcadores insertados y eliminados'); + // La declaración de retorno utiliza el tipo de marcador predeterminado + return true; + } + ``` + + ````md + ```js "return true;" ins="insertados" del="eliminados" + function demo() { + console.log('Estos son tipos de marcadores insertados y eliminados'); + // La declaración de retorno utiliza el tipo de marcador predeterminado + return true; + } + ``` + ```` + +- [Combina el resaltado de sintaxis con la sintaxis similar a `diff`](https://github.com/expressive-code/expressive-code/blob/main/packages/%40expressive-code/plugin-text-markers/README.md#combining-syntax-highlighting-with-diff-like-syntax): + + ```diff lang="js" + function thisIsJavaScript() { + // ¡El bloque completo se resalta como JavaScript, + // y aún podemos añadir marcadores de diferencias a él! + - console.log('Código antiguo a eliminar') + + console.log('¡Nuevo y brillante código!') + } + ``` + + ````md + ```diff lang="js" + function thisIsJavaScript() { + // ¡El bloque completo se resalta como JavaScript, + // y aún podemos añadir marcadores de diferencias a él! + - console.log('Código antiguo a eliminar') + + console.log('¡Nuevo y brillante código!') + } + ``` + ```` + +#### Marcos y títulos + +Los bloques de código se pueden representar dentro de un marco similar a una ventana. +Un marco que se parece a una ventana de código se utilizará para todos los demás lenguajes de programación (por ejemplo, `bash`o `sh`). +Otros lenguajes se muestran dentro de un marco de estilo de editor de código si incluyen un título. + +Un título opcional del bloque de código se puede establecer con un atributo `title="..."` después de las comillas invertidas de apertura del bloque de código y el identificador del lenguaje, o con un comentario del nombre del archivo en las primeras líneas del código. + +- [Añade una pestaña con el nombre del archivo con un comentario](https://github.com/expressive-code/expressive-code/blob/main/packages/%40expressive-code/plugin-frames/README.md#adding-titles-open-file-tab-or-terminal-window-title) + + ```js + // mi-archivo-de-prueba.js + console.log('¡Hola mundo!'); + ``` + + ````md + ```js + // mi-archivo-de-prueba.js + console.log('¡Hola mundo!'); + ``` + ```` + +- [Agrega un título a la ventana Terminal](https://github.com/expressive-code/expressive-code/blob/main/packages/%40expressive-code/plugin-frames/README.md#adding-titles-open-file-tab-or-terminal-window-title) + + ```bash title="Instalando dependencias…" + npm install + ``` + + ````md + ```bash title="Instalando dependencias…" + npm install + ``` + ```` + +- [Desactiva los marcos de ventana con `frame="none"`](https://github.com/expressive-code/expressive-code/blob/main/packages/%40expressive-code/plugin-frames/README.md#overriding-frame-types) + + ```bash frame="none" + echo "Esto no se renderiza como una terminal a pesar de usar el lenguaje bash" + ``` + + ````md + ```bash frame="none" + echo "Esto no se renderiza como una terminal a pesar de usar el lenguaje bash" + ``` + ```` + +## Details + +Los details (también conocidos como "revelaciones" o "acordeones") son útiles para ocultar contenido que no es inmediatamente relevante. +Los usuarios pueden hacer clic en un breve resumen para expandir y ver el contenido completo. + +Usa el elemento HTML estándar [`<details>`](https://developer.mozilla.org/es/docs/Web/HTML/Element/details) y [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary) en tu contenido Markdown para crear un widget de revelación. + +Puedes anidar cualquier otra sintaxis de Markdown dentro de un elemento `<details>`. + +<details> +<summary>¿Dónde y cuándo es más visible la constelación de Andrómeda?</summary> + +La [constelación de Andrómeda](<https://es.wikipedia.org/wiki/Andr%C3%B3meda_(constelaci%C3%B3n)>) es más visible en el cielo nocturno durante el mes de noviembre en latitudes entre `+90°` y `−40°`. + +</details> + +```md +<details> +<summary>¿Dónde y cuándo es más visible la constelación de Andrómeda?</summary> + +La [constelación de Andrómeda](<https://es.wikipedia.org/wiki/Andr%C3%B3meda_(constelaci%C3%B3n)>) es más visible en el cielo nocturno durante el mes de noviembre en latitudes entre `+90°` y `−40°`. + +</details> +``` + +## Otras características comunes de Markdown + +Starlight admite todas las demás sintaxis de autoría de Markdown, como listas y tablas. Puedes consultar la [Guía de referencia de Markdown](https://www.markdownguide.org/cheat-sheet/) para obtener una descripción general rápida de todos los elementos de sintaxis de Markdown. + +## Configuración avanzada de Markdown y MDX + +Starlight utiliza el motor de renderizado de Markdown y MDX de Astro, construido sobre remark y rehype. Puedes añadir soporte para sintaxis y comportamientos personalizados añadiendo `remarkPlugins` o `rehypePlugins` en tu archivo de configuración de Astro. Consulta la sección ["Plugins de Markdown"](https://docs.astro.build/es/guides/markdown-content/#plugins-de-markdown) en la documentación de Astro para obtener más información. + +## Markdoc + +Starlight admite la creación de contenido en Markdoc utilizando la integración experimental de [Astro Markdoc](https://docs.astro.build/es/guides/integrations-guide/markdoc/) y el preset de Starlight Markdoc. + +### Crea un nuevo proyecto con Markdoc + +Empieza un nuevo proyecto en Starlight con Markdoc preconfigurado usando `create astro`: + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight/markdoc +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight/markdoc +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight/markdoc +``` + +</TabItem> +</Tabs> + +### Agrega Markdoc a un proyecto existente + +Si ya tienes un sitio Starlight y quieres agregar Markdoc, sigue estos pasos. + +<Steps> + +1. Agrega la integración de Markdoc de Astro: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npx astro add markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm astro add markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn astro add markdoc + ``` + + </TabItem> + + </Tabs> + +2. Instala el preajuste de Starlight Markdoc: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-markdoc + ``` + + </TabItem> + + </Tabs> + +3. Crea un archivo de configuración de Markdoc en `markdoc.config.mjs` y utiliza el preset de Starlight Markdoc: + + ```js + import { defineMarkdocConfig } from '@astrojs/markdoc/config'; + import starlightMarkdoc from '@astrojs/starlight-markdoc'; + + export default defineMarkdocConfig({ + extends: [starlightMarkdoc()], + }); + ``` + +</Steps> + +Para obtener más información sobre la sintaxis y las características de Markdoc, consulta la [documentación de Markdoc](https://markdoc.dev/docs/syntax) o la [guía de integración de Astro Markdoc](https://docs.astro.build/es/guides/integrations-guide/markdoc/). diff --git a/docs/src/content/docs/es/guides/components.mdx b/docs/src/content/docs/es/guides/components.mdx deleted file mode 100644 index 51c71d913f7..00000000000 --- a/docs/src/content/docs/es/guides/components.mdx +++ /dev/null @@ -1,210 +0,0 @@ ---- -title: Componentes -description: Utilizando componentes en MDX con Starlight. ---- - -Los componentes te permiten reutilizar fácilmente una parte de la interfaz de usuario o un estilo de manera consistente. Ejemplos podrían incluir una tarjeta de enlace o un incrustado de YouTube. Starlight admite el uso de componentes en archivos [MDX](https://mdxjs.com/) y proporciona algunos componentes comunes para que los utilices. - -[Aprende más sobre la construcción de componentes en los docs de Astro](https://docs.astro.build/en/core-concepts/astro-components/). - -## Usando un componente - -Puedes utilizar un componente importándolo en tu archivo MDX y luego renderizándolo como una etiqueta JSX. Estas etiquetas se ven como etiquetas HTML, pero comienzan con una letra mayúscula que coincide con el nombre en tu declaración de `import`: - -```mdx ---- -# src/content/docs/index.mdx -title: Bienvenido a mis docs ---- - -import UnComponente from '../../componentes/UnComponente.astro'; -import OtroComponente from '../../componentes/OtroComponente.astro'; - -<UnComponente prop="algo" /> - -<OtroComponente> - Los componentes también pueden contener **contenido anidado**. -</OtroComponente> -``` - -Debido a que Starlight está impulsado por Astro, puedes agregar soporte para componentes construidos con cualquier [framework UI compatible (React, Preact, Svelte, Vue, Solid, Lit y Alpine)](https://docs.astro.build/en/core-concepts/framework-components/) en tus archivos MDX. - -### Compatibilidad con los estilos de Starlight - -Starlight aplica estilos predeterminados a tu contenido de Markdown, por ejemplo, agregando márgenes entre elementos. -Si estos estilos entran en conflicto con la apariencia de tu componente, establece la clase `not-content` en tu componente para desactivarlos. - -```astro ---- -// src/components/Ejemplo.astro ---- - -<div class="not-content"> - <p> - No se ve afectado por los estilos predeterminados de contenido de Starlight. - </p> -</div> -``` - -### Compatibilidad con los estilos de Starlight - -Starlight aplica estilos predeterminados a tu contenido en Markdown, por ejemplo, añadiendo margen entre elementos. -Si estos estilos entran en conflicto con la apariencia de tu componente, establece la clase `not-content` en tu componente para deshabilitarlos. - -```astro ---- -// src/components/Ejemplo.astro ---- - -<div class="not-content"> - <p> - No se ve afectado por el estilo de contenido predeterminado de Starlight. - </p> -</div> -``` - -## Componentes integrados - -Starlight proporciona algunos componentes integrados para casos de uso comunes en la documentación. Estos componentes están disponibles en el paquete `@astrojs/starlight/components`. - -### Pestañas - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -Puedes mostrar una interfaz con pestañas utilizando los componentes `<Tabs>` y `<TabItem>`. Cada `<TabItem>` debe tener una `label` que se mostrará a los usuarios. - -```mdx -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -<Tabs> - <TabItem label="Estrellas">Sirius, Vega, Betelgeuse</TabItem> - <TabItem label="Lunas">Io, Europa, Ganymede</TabItem> -</Tabs> -``` - -El código anterior genera las siguientes pestañas en la página: - -<Tabs> - <TabItem label="Estrellas">Sirius, Vega, Betelgeuse</TabItem> - <TabItem label="Lunas">Io, Europa, Ganymede</TabItem> -</Tabs> - -### Tarjetas - -import { Card, CardGrid } from '@astrojs/starlight/components'; - -Puedes mostrar contenido en una caja que coincida con los estilos de Starlight utilizando el componente `<Card>`. Envuelve varias tarjetas en el componente `<CardGrid>` para mostrar las tarjetas una al lado de la otra cuando hay suficiente espacio. - -El componente `<Card>` requiere un `title` y opcionalmente puede incluir un atributo `icon` establecido con el nombre de [uno de los iconos integrados de Starlight](#todos-los-iconos). - -```mdx -import { Card, CardGrid } from '@astrojs/starlight/components'; - -<Card title="¡Echa un vistazo a esto!"> - Contenido interesante que quieres resaltar. -</Card> - -<CardGrid> - <Card title="Estrellas" icon="star"> - Sirius, Vega, Betelgeuse - </Card> - <Card title="Lunas" icon="moon"> - Io, Europa, Ganymede - </Card> -</CardGrid> -``` - -El código anterior genera lo siguiente en la página: - -<Card title="¡Echa un vistazo a esto!"> - Contenido interesante que quieres resaltar. -</Card> - -<CardGrid> - <Card title="Estrellas" icon="star"> - Sirius, Vega, Betelgeuse - </Card> - <Card title="Lunas" icon="moon"> - Io, Europa, Ganymede - </Card> -</CardGrid> - -:::tip -Utiliza una cuadrícula de tarjetas en tu página de inicio para mostrar las características clave de tu proyecto. Agrega el atributo `stagger` para desplazar verticalmente la segunda columna de tarjetas y agregar interés visual: - -```astro -<CardGrid stagger> - <!-- tarjetas --> -</CardGrid> -``` - -::: - -### Tarjetas de enlace - -Usa el componente `<LinkCard>` para vincular de forma prominente a diferentes páginas. - -Un `<LinkCard>` requiere un `title` y un atributo [`href`](https://developer.mozilla.org/es/docs/Web/HTML/Element/a#href). Opcionalmente puedes incluir una breve `description` u otros atributos de enlace como `target`. - -Agrupa varios componentes `<LinkCard>` en `<CardGrid>` para mostrar las tarjetas una al lado de la otra cuando hay suficiente espacio. - -```mdx -import { LinkCard, CardGrid } from '@astrojs/starlight/components'; - -<LinkCard - title="Personalizando Starlight" - description="Aprende a hacer que tu sitio Starlight sea único con estilos personalizados, fuentes y más." - href="/es/guides/customization/" -/> - -<CardGrid> - <LinkCard - title="Creación de contenido en Markdown" - href="/es/guides/authoring-content/" - /> - <LinkCard title="Componentes" href="/es/guides/components/" /> -</CardGrid> -``` - -El código anterior genera lo siguiente en la página: - -import { LinkCard } from '@astrojs/starlight/components'; - -<LinkCard - title="Personalizando Starlight" - description="Aprende a hacer que tu sitio Starlight sea único con estilos personalizados, fuentes y más." - href="/es/guides/customization/" -/> - -<CardGrid> - <LinkCard - title="Creación de contenido en Markdown" - href="/es/guides/authoring-content/" - /> - <LinkCard title="Componentes" href="/es/guides/components/" /> -</CardGrid> - -### Iconos - -import { Icon } from '@astrojs/starlight/components'; -import IconsList from '../../../../components/icons-list.astro'; - -Starlight proporciona un conjunto de iconos comunes que puedes mostrar en tu contenido utilizando el componente `<Icon>`. - -Cada `<Icon>` requiere un atributo `name` que se puede encontrar en la lista de [todos los iconos](#all-icons), y opcionalmente puede incluir atributos como `label`, `size` y `color`. - -```mdx -import { Icon } from '@astrojs/starlight/components'; - -<Icon name="star" color="goldenrod" size="2rem" /> -``` - -El código anterior genera lo siguiente en la página: - -<Icon name="star" color="goldenrod" size="2rem" /> - -#### Todos los iconos - -A continuación se muestra una lista de todos los iconos disponibles con sus nombres asociados. Haz clic en un ícono para copiar el código del componente correspondiente. - -<IconsList /> diff --git a/docs/src/content/docs/es/guides/css-and-tailwind.mdx b/docs/src/content/docs/es/guides/css-and-tailwind.mdx index f2ed5cb7b71..bf37249db08 100644 --- a/docs/src/content/docs/es/guides/css-and-tailwind.mdx +++ b/docs/src/content/docs/es/guides/css-and-tailwind.mdx @@ -3,12 +3,16 @@ title: CSS y Estilos description: Aprende a darle estilo a tu sitio Starlight con CSS personalizado o integrado con Tailwind CSS. --- +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + Puedes darle estilo a tu sitio de Starlight con archivos CSS personalizados o usar el plugin Starlight Tailwind. ## Estilos CSS personalizados Personaliza los estilos aplicados a tu sitio Starlight proporcionando archivos CSS adicionales para modificar o extender los estilos predeterminados de Starlight. +<Steps> + 1. Agrega un archivo CSS a tu directorio `src/`. Por ejemplo, podrías establecer un ancho de columna predeterminado más ancho y un tamaño de texto más grande para los títulos de las páginas: @@ -22,7 +26,7 @@ Personaliza los estilos aplicados a tu sitio Starlight proporcionando archivos C 2. Agrega la ruta de tu archivo CSS al array `customCss` de Starlight en `astro.config.mjs`: - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -32,14 +36,16 @@ Personaliza los estilos aplicados a tu sitio Starlight proporcionando archivos C starlight({ title: 'Docs With Custom CSS', customCss: [ - // Ruta relativa a tu archivo CSS personalizado - './src/styles/custom.css', + + // Ruta relativa a tu archivo CSS personalizado + + './src/styles/custom.css', ], }), ], }); ``` +</Steps> + Puedes ver todas las propiedades CSS personalizadas utilizadas por Starlight que puedes establecer para personalizar tu sitio en el archivo [`props.css` en GitHub](https://github.com/withastro/starlight/blob/main/packages/starlight/style/props.css). ## Tailwind CSS @@ -55,11 +61,9 @@ El plugin Starlight Tailwind aplica la siguiente configuración: ### Crea un nuevo proyecto con Tailwind -import { Tabs, TabItem } from '@astrojs/starlight/components'; - Empieza un nuevo proyecto en Starlight con Tailwind CSS preconfigurado usando `create astro`: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh @@ -87,9 +91,11 @@ yarn create astro --template starlight/tailwind Si ya tienes un sitio en Starlight y quieres agregar Tailwind CSS, sigue estos pasos. +<Steps> + 1. Agrega la integración de Tailwind de Astro: - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -119,7 +125,7 @@ Si ya tienes un sitio en Starlight y quieres agregar Tailwind CSS, sigue estos p 2. Instala el plugin Starlight Tailwind: - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -132,7 +138,7 @@ Si ya tienes un sitio en Starlight y quieres agregar Tailwind CSS, sigue estos p <TabItem label="pnpm"> ```sh - pnpm install @astrojs/starlight-tailwind + pnpm add @astrojs/starlight-tailwind ``` </TabItem> @@ -181,19 +187,21 @@ Si ya tienes un sitio en Starlight y quieres agregar Tailwind CSS, sigue estos p }); ``` -5. Agrega el plugin Starlight Tailwind a `tailwind.config.cjs`: +5. Agrega el plugin Starlight Tailwind a `tailwind.config.mjs`: ```js ins={2,7} - // tailwind.config.cjs - const starlightPlugin = require('@astrojs/starlight-tailwind'); + // tailwind.config.mjs + import starlightPlugin from '@astrojs/starlight-tailwind'; /** @type {import('tailwindcss').Config} */ - module.exports = { + export default { content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], plugins: [starlightPlugin()], }; ``` +</Steps> + ### Estilando Starlight con Tailwind Starlight utilizará los valores de la [configuración de tema Tailwind](https://tailwindcss.com/docs/theme) en su UI. @@ -206,12 +214,12 @@ Si se establece, las siguientes opciones anularán los estilos predeterminados d - `fontFamily.mono` - usada para ejemplos de código ```js {12,14,18,20} -// tailwind.config.cjs -const starlightPlugin = require('@astrojs/starlight-tailwind'); -const colors = require('tailwindcss/colors'); +// tailwind.config.mjs +import starlightPlugin from '@astrojs/starlight-tailwind'; +import colors from 'tailwindcss/colors'; /** @type {import('tailwindcss').Config} */ -module.exports = { +export default { content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], theme: { extend: { @@ -243,9 +251,11 @@ Estas variables son utilizadas en toda la UI con una gama de tonos grises utiliz Usa los controles deslizantes a continuación para modificar las paletas de colores de acento y gris de Starlight. Las áreas de vista previa oscura y clara mostrarán los colores resultantes, y toda la página también se actualizará para obtener una vista previa de tus cambios. +Usa la opción Nivel de Contraste para especificar qué estándares de contraste de color de las [pautas de accesibilidad de contenido web](https://developer.mozilla.org/es/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast) debe cumplir. + Cuando estés satisfecho con tus cambios, copia el código CSS o Tailwind a continuación y úsalo en tu proyecto. -import ThemeDesigner from '../../../../components/theme-designer.astro'; +import ThemeDesigner from '~/components/theme-designer.astro'; <ThemeDesigner labels={{ @@ -258,6 +268,9 @@ import ThemeDesigner from '../../../../components/theme-designer.astro'; default: 'Por defecto', random: 'Aleatorio', }, + contrast: { + label: 'Nivel de Contraste', + }, editor: { accentColor: 'Acento', grayColor: 'Gris', diff --git a/docs/src/content/docs/es/guides/customization.mdx b/docs/src/content/docs/es/guides/customization.mdx index b1603164115..44f367bd218 100644 --- a/docs/src/content/docs/es/guides/customization.mdx +++ b/docs/src/content/docs/es/guides/customization.mdx @@ -3,8 +3,7 @@ title: Personalizando Starlight description: Aprende cómo personalizar tu sitio de Starlight con estilos personalizados, fuentes y mucho más. --- -import { Tabs, TabItem } from '@astrojs/starlight/components'; -import FileTree from '../../../../components/file-tree.astro'; +import { Tabs, TabItem, FileTree, Steps } from '@astrojs/starlight/components'; Starlight proporciona estilos y características predeterminadas sensatas, por lo que puedes comenzar rápidamente sin necesidad de configuración. Cuando desees comenzar a personalizar la apariencia de tu sitio de Starlight, esta guía te proporciona toda la información necesaria. @@ -12,6 +11,8 @@ Starlight proporciona estilos y características predeterminadas sensatas, por l Agregando un logo personalizado al encabezado del sitio es una forma rápida de agregar tu marca personalizada a un sitio de Starlight. +<Steps> + 1. Agrega el archivo de imagen de tu logo al directorio `src/assets/`: <FileTree> @@ -26,7 +27,7 @@ Agregando un logo personalizado al encabezado del sitio es una forma rápida de 2. Agrega la ruta de tu logotipo como opción [`logo.src`](/es/reference/configuration/#logo) de Starlight en el archivo `astro.config.mjs`: - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -36,18 +37,20 @@ Agregando un logo personalizado al encabezado del sitio es una forma rápida de starlight({ title: 'Docs Con Mi Logo', logo: { - src: './src/assets/mi-logo.svg', + + src: './src/assets/my-logo.svg', }, }), ], }); ``` +</Steps> + De forma predeterminada, el logo se mostrará junto al título de tu sitio. Si tu imagen de logo ya incluye el título del sitio, puedes ocultar visualmente el texto del título estableciendo la opción `replacesTitle`. El texto del título seguirá estando disponible para lectores de pantalla para garantizar la accesibilidad del encabezado. -```js +```js {5} starlight({ title: 'Docs Con Mi Logo', logo: { @@ -61,6 +64,8 @@ starlight({ Puedes mostrar diferentes versiones de tu logo en modos claro y oscuro. +<Steps> + 1. Agrega un archivo de imagen para cada variante en el directorio `src/assets/`: <FileTree> @@ -76,21 +81,23 @@ Puedes mostrar diferentes versiones de tu logo en modos claro y oscuro. 2. Agrega la ruta de tus variantes de logo como opciones `light` y `dark` en lugar de `src` en el archivo `astro.config.mjs`: - ```js + ```diff lang="js" starlight({ title: 'Docs Con Mi Logo', logo: { - light: './src/assets/logo-claro.svg', - dark: './src/assets/logo-oscuro.svg', + + light: './src/assets/light-logo.svg', + + dark: './src/assets/dark-logo.svg', }, }), ``` +</Steps> + ## Habilitar el mapa del sitio Starlight tiene soporte incorporado para generar un mapa del sitio. Habilita la generación del mapa del sitio estableciendo tu URL como `site` en `astro.config.mjs`: -```js +```js {4} // astro.config.mjs export default defineConfig({ @@ -99,13 +106,15 @@ export default defineConfig({ }); ``` +Aprende cómo [agregar un enlace del mapa del sitio a `robots.txt`](https://docs.astro.build/es/guides/integrations-guide/sitemap/#enlace-de-sitemap-en-robotstxt) en la documentación de Astro. + ## Diseño de página De forma predeterminada, las páginas de Starlight utilizan un diseño con una barra lateral de navegación global y una tabla de contenidos que muestra los encabezados de la página actual. Puedes aplicar un diseño de página más amplio sin barras laterales estableciendo [`template: splash`](/es/reference/frontmatter/#template) en el frontmatter de una página. Esto funciona especialmente bien para páginas de inicio y puedes verlo en acción en la [página de inicio de este sitio](/es/). -```md +```md {5} --- # src/content/docs/index.md @@ -120,10 +129,10 @@ Starlight muestra una tabla de contenidos en cada página para facilitar que los De forma predeterminada, los encabezados `<h2>` y `<h3>` se incluyen en la tabla de contenidos. Puedes cambiar qué niveles de encabezados se incluyen en toda la página utilizando las opciones `minHeadingLevel` y `maxHeadingLevel` en tu configuración [global de `tableOfContents`](/es/reference/configuration/#tableofcontents). Puedes anular estas configuraciones predeterminadas en una página individual agregando las propiedades correspondientes de [`tableOfContents` en el frontmatter](/es/reference/frontmatter/#tableofcontents): -<Tabs> +<Tabs syncKey="config-type"> <TabItem label="Frontmatter"> -```md +```md {4-6} --- # src/content/docs/example.md title: Página con solo encabezados H2 en la tabla de contenidos @@ -136,13 +145,13 @@ tableOfContents: </TabItem> <TabItem label="Configuración global"> -```js +```js {7} // astro.config.mjs defineConfig({ integrations: [ starlight({ - title: '', + title: 'Docs con una configuración personalizada de tabla de contenidos', tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 2 }, }), ], @@ -154,10 +163,10 @@ defineConfig({ Desactiva completamente la tabla de contenidos estableciendo la opción `tableOfContents` en `false`: -<Tabs> +<Tabs syncKey="config-type"> <TabItem label="Frontmatter"> -```md +```md {4} --- # src/content/docs/example.md title: Página sin tabla de contenidos @@ -168,7 +177,7 @@ tableOfContents: false </TabItem> <TabItem label="Configuración global"> -```js +```js {7} // astro.config.mjs defineConfig({ @@ -188,9 +197,9 @@ defineConfig({ Starlight cuenta con soporte incorporado para agregar enlaces a tus cuentas de redes sociales en el encabezado del sitio mediante la opción [`social`](/es/reference/configuration/#social) en la integración de Starlight. -Actualmente, se admiten enlaces a Bitbucket, Codeberg, CodePen, Discord, GitHub, GitLab, Gitter, Instagram, LinkedIn, Mastodon, Microsoft Teams, Stack Overflow, Threads, Twitch, Twitter, y Youtube ¡Háznoslo saber en GitHub o Discord si necesitas soporte para otro servicio! +Puedes encontrar una lista completa de todos los iconos de enlaces compatibles en la [Referencia de Configuración](/es/reference/configuration/#social). -```js +```js {9-12} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -224,7 +233,7 @@ Si tu proyecto de Starlight no se encuentra en la raíz de tu repositorio, inclu Este ejemplo muestra el enlace de edición configurado para la documentación de Starlight, que se encuentra en el subdirectorio `docs/` en la rama `main` del repositorio `withastro/starlight` en GitHub: -```js +```js {9-12} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -258,8 +267,9 @@ Los sitios de Starlight muestran de forma predeterminada una página de error 40 Puedes utilizar todas las técnicas de diseño y personalización de páginas de Starlight en tu página de error 404. Por ejemplo, la página de error 404 predeterminada utiliza la [plantilla `splash`](#diseño-de-página) y el componente [`hero`](/es/reference/frontmatter/#hero) en el frontmatter: -```md +```md {4, 6-8} --- +# src/content/docs/404.md title: '404' template: splash editUrl: false @@ -269,6 +279,25 @@ hero: --- ``` +### Desactivar la página 404 predeterminada + +Si tu proyecto requiere un diseño 404 completamente personalizado, puedes crear una ruta `src/pages/404.astro` y establecer la opción de configuración [`disable404Route`](/es/reference/configuration/#disable404route) para desactivar la ruta predeterminada de Starlight: + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Docs With Custom 404', + disable404Route: true, + }), + ], +}); +``` + ## Fuentes personalizadas De forma predeterminada, Starlight utiliza fuentes sans-serif disponibles en el dispositivo local del usuario para todo el texto. @@ -283,6 +312,8 @@ Para utilizar Google Fonts, sigue la [guía de configuración de Fontsource](#co #### Configurar archivos de fuentes locales. +<Steps> + 1. Agrega tus archivos de fuente a un directorio `src/fonts/` y crea un archivo `font-face.css` vacío. <FileTree> @@ -314,7 +345,7 @@ Para utilizar Google Fonts, sigue la [guía de configuración de Fontsource](#co 3. Agrega la ruta al archivo `font-face.css` al arreglo `customCss` de Starlight en `astro.config.mjs`. - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -324,26 +355,30 @@ Para utilizar Google Fonts, sigue la [guía de configuración de Fontsource](#co starlight({ title: 'Docs Con Un Tipo De Letra Personalizado', customCss: [ - // Ruta relativa al archivo CSS de `@font-face`. - './src/fonts/font-face.css', + + // Ruta relativa a tu archivo CSS @font-face. + + './src/fonts/font-face.css', ], }), ], }); ``` +</Steps> + #### Configurar una fuente de Fontsource El proyecto [Fontsource](https://fontsource.org/) simplifica el uso de fuentes de Google Fonts y otras fuentes de código abierto. Proporciona módulos npm que puedes instalar para las fuentes que deseas utilizar e incluye archivos CSS listos para usar que puedes agregar a tu proyecto. +<Steps> + 1. Encuentra la fuente que deseas utilizar en el catálogo de [Fontsource](https://fontsource.org/). En este ejemplo, se utilizará [IBM Plex Serif](https://fontsource.org/fonts/ibm-plex-serif). 2. Instala el paquete para la fuente que has elegido. Puedes encontrar el nombre del paquete haciendo clic en “Install” en la página de la fuente de Fontsource. - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -356,7 +391,7 @@ Proporciona módulos npm que puedes instalar para las fuentes que deseas utiliza <TabItem label="pnpm"> ```sh - pnpm install @fontsource/ibm-plex-serif + pnpm add @fontsource/ibm-plex-serif ``` </TabItem> @@ -373,7 +408,7 @@ Proporciona módulos npm que puedes instalar para las fuentes que deseas utiliza 3. Agrega los archivos CSS de Fontsource al arreglo `customCss` de Starlight en `astro.config.mjs`. - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -383,9 +418,9 @@ Proporciona módulos npm que puedes instalar para las fuentes que deseas utiliza starlight({ title: 'Docs Con Un Tipo De Letra Personalizado', customCss: [ - // Archivos de Fontsource para las variantes de fuente regular y semi-bold. - '@fontsource/ibm-plex-serif/400.css', - '@fontsource/ibm-plex-serif/600.css', + + // Archivos de Fontsource para pesos de fuente regular y semi-negrita. + + '@fontsource/ibm-plex-serif/400.css', + + '@fontsource/ibm-plex-serif/600.css', ], }), ], @@ -394,9 +429,11 @@ Proporciona módulos npm que puedes instalar para las fuentes que deseas utiliza Fontsource incluye varios archivos CSS para cada fuente. Consulta la [documentación de Fontsource](https://fontsource.org/docs/getting-started/install#4-weights-and-styles) sobre cómo incluir diferentes pesos y estilos para comprender cuál debes usar. +</Steps> + ### Usar fuentes -Para aplicar la fuente que configuraste a tu sitio, utiliza el nombre de la fuente elegida en un [archivo CSS personalizado](/es/guides/css-and-tailwind/#custom-css-styles). +Para aplicar la fuente que configuraste a tu sitio, utiliza el nombre de la fuente elegida en un [archivo CSS personalizado](/es/guides/css-and-tailwind/#estilos-css-personalizados). Por ejemplo, para anular la fuente predeterminada de Starlight en todas partes, establece la propiedad personalizada `--sl-font`: ```css @@ -418,4 +455,4 @@ main { } ``` -Sigue las [instrucciones de CSS personalizado](/guides/css-and-tailwind/#estilos-css-personalizados) para agregar tus estilos a tu sitio. +Sigue las [instrucciones de CSS personalizado](/es/guides/css-and-tailwind/#estilos-css-personalizados) para agregar tus estilos a tu sitio. diff --git a/docs/src/content/docs/es/guides/i18n.mdx b/docs/src/content/docs/es/guides/i18n.mdx index cce43098484..fc7d6a57cb0 100644 --- a/docs/src/content/docs/es/guides/i18n.mdx +++ b/docs/src/content/docs/es/guides/i18n.mdx @@ -3,15 +3,17 @@ title: Internacionalización (i18n) description: Aprende a configurar tu sitio Starlight para admitir varios idiomas. --- -import FileTree from '../../../../components/file-tree.astro'; +import { FileTree, Steps } from '@astrojs/starlight/components'; Starlight proporciona soporte incorporado para sitios multilingües, incluidas las rutas, el contenido de respaldo y el soporte completo de idiomas de derecha a izquierda (RTL). ## Configura i18n +<Steps> + 1. Indícale a Starlight los idiomas que admites pasando [`locales`](/es/reference/configuration/#locales) y [`defaultLocale`](/es/reference/configuration/#defaultlocale) a la integración de Starlight: - ```js + ```js {9-26} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -27,8 +29,8 @@ Starlight proporciona soporte incorporado para sitios multilingües, incluidas l en: { label: 'English', }, - // Chino simplificado en `src/content/docs/zh/` - zh: { + // Chino simplificado en `src/content/docs/zh-cn/` + 'zh-cn': { label: '简体中文', lang: 'zh-CN', }, @@ -55,7 +57,7 @@ Starlight proporciona soporte incorporado para sitios multilingües, incluidas l - docs/ - ar/ - en/ - - zh/ + - zh-cn/ </FileTree> @@ -63,13 +65,17 @@ Starlight proporciona soporte incorporado para sitios multilingües, incluidas l Por ejemplo, crea `ar/index.md` y `en/index.md` para representar la página de inicio en árabe e inglés, respectivamente. +</Steps> + +Para escenarios de i18n más avanzados, Starlight también admite la configuración de internacionalización utilizando la [opción `i18n` de Astro](https://docs.astro.build/es/guides/internationalization/#configuración-de-rutas-i18n). + ### Usa una raíz de configuración regional Puedes usar una raíz de configuración regional para servir un idioma sin ningún prefijo i18n en tu ruta. Por ejemplo, si el inglés es tu configuración regional, una ruta de página en inglés se vería como `/about` en lugar de `/en/about`. Para establecer una configuración regional, usa la clave `root` en tu configuración de `locales`. Si la configuración regional raíz también es la configuración regional predeterminada para tu contenido, elimina `defaultLocale` o configúralo en `'root'`. -```js +```js {9,11-14} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -84,7 +90,7 @@ export default defineConfig({ label: 'English', lang: 'en', // lang es obligatorio para los locales raíz }, - zh: { + 'zh-cn': { label: '简体中文', lang: 'zh-CN', }, @@ -102,7 +108,7 @@ Cuando uses una `root` locale, mantén las páginas para ese idioma directamente - content/ - docs/ - **index.md** - - zh/ + - zh-cn/ - **index.md** </FileTree> @@ -111,7 +117,7 @@ Cuando uses una `root` locale, mantén las páginas para ese idioma directamente De forma predeterminada, Starlight es un sitio monolingüe (en inglés). Para crear un sitio de un solo idioma en otro idioma, configúralo como el `root` en tu configuración de `locales`: -```js +```diff lang="js" {10-13} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -138,20 +144,60 @@ Starlight espera que crees páginas equivalentes en todos tus idiomas. Por ejemp Si no hay una traducción disponible para un idioma, Starlight mostrará a los lectores el contenido de esa página en el idioma predeterminado (establecido mediante `defaultLocale`). Por ejemplo, si aún no has creado una versión en francés de tu página Acerca de y tu idioma predeterminado es el inglés, los visitantes a `/fr/about` verán el contenido en inglés de `/en/about` con un aviso de que esta página aún no se ha traducido. Esto te ayuda a agregar contenido en tu idioma predeterminado y luego traducirlo progresivamente cuando tus traductores tengan tiempo. +## Traduce el título del sitio + +Por defecto, Starlight usará el mismo título del sitio para todos los idiomas. +Si necesitas personalizar el título para cada idioma, puedes pasar un objeto a [`title`](/es/reference/configuration/#title-requerido) en las opciones de Starlight: + +```diff lang="js" +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ +- title: 'Mi Documentación', ++ title: { ++ es: 'Mi Documentación', ++ 'zh-CN': '我的文档', ++ }, + defaultLocale: 'es', + locales: { + es: { label: 'Español' }, + 'zh-cn': { label: '简体中文', lang: 'zh-CN' }, + }, + }), + ], +}); +``` + ## Traduce la UI de Starlight -Starlight proporciona de forma predeterminada traducciones para los textos utilizados en la UI al inglés, checo, francés, alemán, italiano, japonés, holandés, portugués, danés, español, turco, árabe, noruego, farsi, hebreo, chino simplificado, coreano, indonesio, ruso y sueco. También damos la bienvenida a [contribuciones para agregar más idiomas predeterminados](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md). +import LanguagesList from '~/components/languages-list.astro'; +import UIStringsList from '~/components/ui-strings-list.astro'; + +Además de alojar archivos de contenido traducidos, Starlight te permite traducir las etiquetas de UI predeterminadas (p. ej. el encabezado "En esta página" en la tabla de contenidos) para que tus lectores puedan experimentar tu sitio completamente en el idioma seleccionado. + +<LanguagesList startsSentence /> los strings de UI traducidos se proporcionan de +forma predeterminada, y damos la bienvenida a [contribuciones para agregar más +idiomas +predeterminados](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md). + +Puedes proprocionar traducciones para idiomas adicionales, o editar nuestras etiquetas predeterminadas, a través de la colección de datos `i18n`. + +<Steps> 1. Configura la colección de datos `i18n` en `src/content/config.ts` si aún no está configurada: - ```js + ```diff lang="js" ins=/, (i18nSchema)/ // src/content/config.ts import { defineCollection } from 'astro:content'; import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; export const collections = { docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), + + i18n: defineCollection({ type: 'data', schema: i18nSchema() }), }; ``` @@ -170,46 +216,189 @@ Starlight proporciona de forma predeterminada traducciones para los textos utili 3. Agrega traducciones para las claves que deseas traducir en los archivos JSON. Traduce solo los valores, dejando las claves en inglés (p. ej. `"search.label": "Buscar"`). -Estos son los valores predeterminados en inglés de las cadenas existentes que se incluyen en Starlight: + Estos son los valores predeterminados en inglés de las cadenas existentes que se incluyen en Starlight: -```json -{ - "skipLink.label": "Skip to content", - "search.label": "Search", - "search.shortcutLabel": "(Press / to Search)", - "search.cancelLabel": "Cancel", - "search.devWarning": "Search is only available in production builds. \nTry building and previewing the site to test it out locally.", - "themeSelect.accessibleLabel": "Select theme", - "themeSelect.dark": "Dark", - "themeSelect.light": "Light", - "themeSelect.auto": "Auto", - "languageSelect.accessibleLabel": "Select language", - "menuButton.accessibleLabel": "Menu", - "sidebarNav.accessibleLabel": "Main", - "tableOfContents.onThisPage": "On this page", - "tableOfContents.overview": "Overview", - "i18n.untranslatedContent": "This content is not available in your language yet.", - "page.editLink": "Edit page", - "page.lastUpdated": "Last updated:", - "page.previousLink": "Next", - "page.nextLink": "Previous" -} + <UIStringsList /> + + Los bloques de código de Starlight están impulsados por la biblioteca [Expressive Code](https://github.com/expressive-code/expressive-code). + Puedes establecer traducciones para las cadenas de UI en el mismo archivo JSON utilizando las llaves `expressiveCode`: + + ```json + { + "expressiveCode.copyButtonCopied": "Copied!", + "expressiveCode.copyButtonTooltip": "Copy to clipboard", + "expressiveCode.terminalWindowFallbackTitle": "Terminal window" + } + ``` + + El modal de búsqueda de Starlight está impulsado por la biblioteca [Pagefind](https://pagefind.app/). + Puedes establecer traducciones para la UI de Pagefind en el mismo archivo JSON utilizando claves `pagefind`: + + ```json + { + "pagefind.clear_search": "Clear", + "pagefind.load_more": "Load more results", + "pagefind.search_label": "Search this site", + "pagefind.filters_label": "Filters", + "pagefind.zero_results": "No results for [SEARCH_TERM]", + "pagefind.many_results": "[COUNT] results for [SEARCH_TERM]", + "pagefind.one_result": "[COUNT] result for [SEARCH_TERM]", + "pagefind.alt_search": "No results for [SEARCH_TERM]. Showing results for [DIFFERENT_TERM] instead", + "pagefind.search_suggestion": "No results for [SEARCH_TERM]. Try one of the following searches:", + "pagefind.searching": "Searching for [SEARCH_TERM]..." + } + ``` + +</Steps> + +### Extiende el esquema de traducción + +Agrega claves personalizadas a los diccionarios de traducción de tu sitio estableciendo `extend` en las opciones de `i18nSchema()`. +En el siguiente ejemplo, una clave nueva, opcional `custom.label` se agrega a las claves predeterminadas: + +```diff lang="js" +// src/content/config.ts +import { defineCollection, z } from 'astro:content'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ schema: docsSchema() }), + i18n: defineCollection({ + type: 'data', + schema: i18nSchema({ ++ extend: z.object({ ++ 'custom.label': z.string().optional(), ++ }), + }), + }), +}; +``` + +Aprende más sobre los esquemas de colección de contenido en [“Definir un esquema de colección”](https://docs.astro.build/es/guides/content-collections/#definiendo-un-esquema-de-colección) en la documentación de Astro. + +## Usar traducciones de UI + +Puedes acceder a las [strings de UI integradas](/es/guides/i18n/#traduce-la-ui-de-starlight) de Starlight, así como a las cadenas de UI [definidas por el usuario](/es/guides/i18n/#extiende-el-esquema-de-traducción) y [proporcionadas por plugins](/es/reference/plugins/#injecttranslations) a través de una API unificada impulsada por [i18next](https://www.i18next.com/). +Esto incluye soporte para funciones como [interpolación](https://www.i18next.com/translation-function/interpolation) y [pluralización](https://www.i18next.com/translation-function/plurals). + +En componentes de Astro, esta API está disponible como parte del [objeto global `Astro`](https://docs.astro.build/es/reference/api-reference/#astrolocals) como `Astro.locals.t`: + +```astro title="example.astro" +<p dir={Astro.locals.t.dir()}> + {Astro.locals.t('404.text')} +</p> ``` -El modal de búsqueda de Starlight está impulsado por la biblioteca [Pagefind](https://pagefind.app/). -Puedes establecer traducciones para la UI de Pagefind en el mismo archivo JSON utilizando claves `pagefind`: +También puedes usar la API en [endpoints](https://docs.astro.build/es/guides/endpoints/), donde el objeto `locals` está disponible como parte del [contexto del endpoint](https://docs.astro.build/es/reference/api-reference/#contextlocals): -```json +```ts title="src/pages/404.ts" +export const GET = (context) => { + return new Response(context.locals.t('404.text')); +}; +``` + +### Renderizar una string de UI + +Renderiza strings de UI utilizando la función `locals.t()`. +Esta es una instancia de la función `t()` de i18next, que toma una clave de cadena de UI como su primer argumento y devuelve la traducción correspondiente para el idioma actual. + +Por ejemplo, dado un archivo de traducción personalizado con el siguiente contenido: + +```json title="src/content/i18n/en.json" { - "pagefind.clear_search": "Clear", - "pagefind.load_more": "Load more results", - "pagefind.search_label": "Search this site", - "pagefind.filters_label": "Filters", - "pagefind.zero_results": "No results for [SEARCH_TERM]", - "pagefind.many_results": "[COUNT] results for [SEARCH_TERM]", - "pagefind.one_result": "[COUNT] result for [SEARCH_TERM]", - "pagefind.alt_search": "No results for [SEARCH_TERM]. Showing results for [DIFFERENT_TERM] instead", - "pagefind.search_suggestion": "No results for [SEARCH_TERM]. Try one of the following searches:", - "pagefind.searching": "Searching for [SEARCH_TERM]..." + "link.astro": "Astro documentation", + "link.astro.custom": "Astro documentation for {{feature}}" } ``` + +La primera string de UI se puede renderizar pasando `'link.astro'` a la función `t()`: + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/"> + {Astro.locals.t('link.astro')} +</a> +<!-- Renderiza: <a href="...">Astro documentation</a> --> +``` + +La segunda string de UI utiliza la [sintaxis de interpolación](https://www.i18next.com/translation-function/interpolation) de i18next para el marcador `{{feature}}`. +El valor de `feature` debe establecerse en un objeto de opciones pasado como segundo argumento a `t()`: + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/en/guides/astro-db/"> + {Astro.locals.t('link.astro.custom', { feature: 'Astro DB' })} +</a> +<!-- Renderiza: <a href="...">Astro documentation for Astro DB</a> --> +``` + +Ver la [documentación de i18next](https://www.i18next.com/overview/api#t) para obtener más información sobre cómo usar la función `t()` con interpolación, formato y más. + +### APIs avanzadas + +#### `t.all()` + +La función `locals.t.all()` devuelve un objeto que contiene todas las strings de UI disponibles para el idioma actual. + +```astro +--- +// src/components/Example.astro +const allStrings = Astro.locals.t.all(); +// ^ +// { +// "skipLink.label": "Skip to content", +// "search.label": "Search", +// … +// } +--- +``` + +#### `t.exists()` + +Para comprobar si una clave de traducción existe para un idioma, utiliza la función `locals.t.exists()` con la clave de traducción como primer argumento. +Pasa un segundo argumento opcional si necesitas anular el idioma actual. + +```astro +--- +// src/components/Example.astro +const keyExistsInCurrentLocale = Astro.locals.t.exists('a.key'); +// ^ true +const keyExistsInFrench = Astro.locals.t.exists('another.key', { lng: 'fr' }); +// ^ false +--- +``` + +Ver la [referencia de `exists()` en la documentación de i18next](https://www.i18next.com/overview/api#exists) para obtener más información. + +#### `t.dir()` + +La función `locals.t.dir()` devuelve la dirección del texto del idioma actual o de un idioma específico. + +```astro +--- +// src/components/Example.astro +const currentDirection = Astro.locals.t.dir(); +// ^ +// 'ltr' +const arabicDirection = Astro.locals.t.dir('ar'); +// ^ +// 'rtl' +--- +``` + +Ver la [referencia de `dir()` en la documentación de i18next](https://www.i18next.com/overview/api#dir) para obtener más información. + +## Acceder al idioma actual + +Puedes usar [`Astro.currentLocale`](https://docs.astro.build/es/reference/api-reference/#astrocurrentlocale) para leer el idioma actual en componentes `.astro`. + +El siguiente ejemplo lee el idioma actual y lo utiliza con la función [`getRelativeLocaleUrl()`](https://docs.astro.build/es/reference/modules/astro-i18n/#getrelativelocaleurl) para generar un enlace a una página Acerca de en el idioma actual: + +```astro +--- +// src/components/AboutLink.astro +import { getRelativeLocaleUrl } from 'astro:i18n'; +--- + +<a href={getRelativeLocaleUrl(Astro.currentLocale ?? 'en', 'about')}>Acerca</a> +``` diff --git a/docs/src/content/docs/es/guides/overriding-components.mdx b/docs/src/content/docs/es/guides/overriding-components.mdx new file mode 100644 index 00000000000..6723738de62 --- /dev/null +++ b/docs/src/content/docs/es/guides/overriding-components.mdx @@ -0,0 +1,141 @@ +--- +title: Sobreescribiendo Componentes +description: Aprende como sobreescribir los componentes integrados de Starlight para agregar elementos personalizados a la interfaz de tu sitio de documentación. +--- + +import { Steps } from '@astrojs/starlight/components'; + +La UI por defecto de Starlight y las opciones de configuración están diseñadas para ser flexibles y funcionar para una variedad de contenidos. Gran parte de la apariencia predeterminada de Starlight se puede personalizar con [CSS](/es/guides/css-and-tailwind/) y [opciones de configuración](/es/guides/customization/). + +Cuando necesites más de lo que es posible por defecto, Starlight soporta la construcción de tus propios componentes personalizados para extender o sobreescribir (reemplazar completamente) sus componentes por defecto. + +## Cuando sobreescribir + +Sobreescribir los componentes por defecto de Starlight puede ser útil cuando: + +- Quieres cambiar como una parte de la UI de Starlight se ve de una manera que no es posible con [CSS personalizado](/es/guides/css-and-tailwind/). +- Quieres cambiar como una parte de la UI de Starlight se comporta. +- Quieres agregar partes adicionales de la UI junto a la UI existente de Starlight. + +## Cómo sobreescribir + +<Steps> + +1. Escoge el componente de Starlight que quieres sobreescribir. + Puedes encontrar una lista completa de componentes en la [Referencia de Personalización de Componentes](/es/reference/overrides/). + + :::tip + ¿No estás seguro de qué componente necesitas sobreescribir? Usa el [Mapa Interactivo de Sobreescripciones de Starlight](https://starlight-overrides-map.netlify.app/) para descubrir los nombres de los componentes de UI de Starlight. + ::: + + Este ejemplo sobreescribe el componente [`SocialIcons`](/es/reference/overrides/#socialicons) de Starlight en la barra de navegación de la página. + +2. Crea un componente de Astro para reemplazar el componente de Starlight. + Este ejemplo renderiza un enlace de contacto. + + ```astro + --- + // src/components/EmailLink.astro + import type { Props } from '@astrojs/starlight/props'; + --- + + <a href="mailto:houston@example.com">Escríbeme</a> + ``` + +3. Dile a Starlight que use tu componente personalizado en la opción de configuración [`components`](/es/reference/configuration/#components) en `astro.config.mjs`: + + ```js {9-12} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'My Docs with Overrides', + components: { + // Sobreescribe el componente `SocialIcons` por defecto. + SocialIcons: './src/components/EmailLink.astro', + }, + }), + ], + }); + ``` + +</Steps> + +## Reusa un componente integrado + +Puedes construir con los componentes de UI por defecto de Starlight de la misma manera que lo harías con los tuyos: importándolos y renderizándolos en tus propios componentes personalizados. Esto te permite mantener toda la UI básica de Starlight dentro de tu diseño, mientras agregas UI adicional junto a ellos. + +El ejemplo a continuación muestra un componente personalizado que renderiza un enlace de correo electrónico junto con el componente `SocialIcons` por defecto: + +```astro {4,8} +--- +// src/components/EmailLink.astro +import type { Props } from '@astrojs/starlight/props'; +import Default from '@astrojs/starlight/components/SocialIcons.astro'; +--- + +<a href="mailto:houston@example.com">Escríbeme</a> +<Default {...Astro.props}><slot /></Default> +``` + +Cuando renderizas un componente integrado dentro de un componente personalizado: + +- Propaga `Astro.props` dentro de él. Esto se asegura de que reciba todos los datos que necesita para renderizar. +- Agrega un [`<slot />`](https://docs.astro.build/es/core-concepts/astro-components/#slots) dentro del componente por defecto. Esto se asegura de que si el componente recibe cualquier elemento hijo, Astro sepa donde renderizarlos. + +## Usa los datos de la página + +Cuando sobreescribes un componente de Starlight, tu implementación personalizada recibe un objeto `Astro.props` estándar que contiene todos los datos de la página actual. +Esto te permite usar estos valores para controlar como se renderiza tu plantilla de componente. + +Por ejemplo, puedes leer los valores de frontmatter de la página como `Astro.props.entry.data`. En el siguiente ejemplo, un componente de reemplazo [`PageTitle`](/es/reference/overrides/#pagetitle) usa esto para mostrar el título de la página actual: + +```astro {5} "{title}" +--- +// src/components/Title.astro +import type { Props } from '@astrojs/starlight/props'; + +const { title } = Astro.props.entry.data; +--- + +<h1 id="_top">{title}</h1> + +<style> + h1 { + font-family: 'Comic Sans'; + } +</style> +``` + +Aprende más sobre todas las props disponibles en la [Referencia de Sobreescripciones](/es/reference/overrides/#props-de-componentes). + +### Solo sobreescribe en páginas específicas + +Los cambios de componentes se aplican a todas las páginas. Sin embargo, puedes renderizar condicionalmente usando los valores de `Astro.props` para determinar cuando mostrar tu UI personalizada, cuando mostrar la UI por defecto de Starlight, o incluso cuando mostrar algo completamente diferente. + +En el siguiente ejemplo, un componente que sobreescribe el [`Footer`](/es/reference/overrides/#footer) de Starlight muestra "Construido con Starlight 🌟" solo en la página de inicio, y de otra manera muestra el footer por defecto en todas las otras páginas: + +```astro +--- +// src/components/ConditionalFooter.astro +import type { Props } from '@astrojs/starlight/props'; +import Default from '@astrojs/starlight/components/Footer.astro'; + +const isHomepage = Astro.props.slug === ''; +--- + +{ + isHomepage ? ( + <footer>Construido con Starlight 🌟</footer> + ) : ( + <Default {...Astro.props}> + <slot /> + </Default> + ) +} +``` + +Aprende más sobre el renderizado condicional en la [Guía de Sintaxis de Astro](https://docs.astro.build/es/core-concepts/astro-syntax/#html-dinamico). diff --git a/docs/src/content/docs/es/guides/pages.mdx b/docs/src/content/docs/es/guides/pages.mdx new file mode 100644 index 00000000000..e99d7c2716d --- /dev/null +++ b/docs/src/content/docs/es/guides/pages.mdx @@ -0,0 +1,175 @@ +--- +title: Páginas +description: Aprende cómo crear y gestionar las páginas de tu sitio de documentación con Starlight. +sidebar: + order: 1 +--- + +Starlight genera las páginas HTML de tu sitio basadas en tu contenido, con opciones flexibles proporcionadas a través del frontmatter de Markdown. +Además, los proyectos de Starlight tienen acceso completo a las [herramientas de generación de páginas de Astro](https://docs.astro.build/es/basics/astro-pages/). +Esta guía muestra cómo funciona la generación de páginas en Starlight. + +## Páginas de contenido + +### Formatos de archivo + +Starlight admite la creación de contenido en Markdown y MDX sin necesidad de configuración. +Puedes agregar soporte para Markdoc siguiendo la [guía de “Markdoc”](/es/guides/authoring-content/#markdoc). + +### Agregar páginas + +Añade nuevas páginas a tu sitio creando archivos `.md` o `.mdx` en `src/content/docs/`. +Utiliza subcarpetas para organizar tus archivos y crear múltiples segmentos de ruta. + +Por ejemplo, la siguiente estructura de archivos generará páginas en `example.com/hello-world` y `example.com/reference/faq`: + +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - reference/ + - faq.md + +</FileTree> + +### Frontmatter tipado + +Todas las páginas de Starlight comparten un [conjunto común de propiedades de frontmatter personalizables](/es/reference/frontmatter/) para controlar cómo aparece la página: + +```md +--- +title: ¡Hola, mundo! +description: Esta es una página en mi sitio impulsado por Starlight +--- +``` + +Si olvidas algo importante, Starlight te lo hará saber. + +## Páginas personalizadas + +Para casos de uso avanzados, puedes agregar páginas personalizadas creando un directorio `src/pages/`. +El directorio `src/pages/` utiliza [enrutamiento basado en archivos de Astro](https://docs.astro.build/es/basics/astro-pages/#enrutamiento-basado-en-archivos) e incluye soporte para archivos `.astro` entre otros formatos de página. +Esto es útil si necesitas construir páginas con un diseño completamente personalizado o generar una página desde una fuente de datos alternativa. + +Por ejemplo, este proyecto mezcla contenido Markdown en `src/content/docs/` con rutas de Astro y HTML en `src/pages/`: + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - pages/ + - custom.astro + - archived.html + +</FileTree> + +Lee más en la [Guía de Páginas en la documentación de Astro](https://docs.astro.build/es/basics/astro-pages/). + +### Usar el diseño de Starlight en páginas personalizadas + +Para usar el diseño de Starlight en páginas personalizadas, envuelve el contenido de tu página con el componente `<StarlightPage />`. +Esto puede ser útil si estás generando contenido dinámicamente pero aún quieres usar el diseño de Starlight. + +```astro +--- +// src/pages/custom-page/example.astro +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +import CustomComponent from './CustomComponent.astro'; +--- + +<StarlightPage frontmatter={{ title: 'Mi página personalizada' }}> + <p>Esta es una página personalizada con un componente personalizado:</p> + <CustomComponent /> +</StarlightPage> +``` + +#### Props + +El componente `<StarlightPage />` acepta las siguientes props. + +##### `frontmatter` (requerido) + +**tipo:** `StarlightPageFrontmatter` + +Establece las [propiedades de frontmatter](/es/reference/frontmatter/) para esta página, similar al frontmatter en las páginas de Markdown. +La propiedad [`title`](/es/reference/frontmatter/#title-requerido) es requerida y todas las demás propiedades son opcionales. + +Las siguientes propiedades difieren del frontmatter de Markdown: + +- La propiedad [`slug`](/es/reference/frontmatter/#slug) no es compatible y se establece automáticamente en función de la URL de la página personalizada. +- La opción [`editUrl`](/es/reference/frontmatter/#editurl) requiere una URL para mostrar un enlace de edición. +- La propiedad frontmatter [`sidebar`](/es/reference/frontmatter/#sidebar) para personalizar cómo aparece la página en [grupos de enlaces autogenerados](/es/reference/configuration/#sidebar) no está disponible. Las páginas que utilizan el componente `<StarlightPage />` no forman parte de una colección y no pueden ser agregadas a un grupo de barra lateral autogenerado. +- La opción [`draft`](/es/reference/frontmatter/#draft) solo muestra un [aviso](/es/reference/overrides/#draftcontentnotice) de que la página es un borrador, pero no la excluye automáticamente de las compilaciones de producción. + +##### `sidebar` + +**tipo:** [`SidebarItem[]`](/es/reference/configuration/#sidebaritem) +**por defecto:** la barra lateral generada basada en la [configuración global de `sidebar`](/es/reference/configuration/#sidebar) + +Proporciona una barra lateral de navegación personalizada para esta página. +Si no se establece, la página usará la barra lateral global predeterminada. + +Por ejemplo, la siguiente página anula la barra lateral predeterminada con un enlace a la página de inicio y un grupo de enlaces a varias otras páginas personalizadas. + +```astro {3-13} +<StarlightPage + frontmatter={{ title: 'Orion' }} + sidebar={[ + { label: 'Home', link: '/' }, + { + label: 'Constelaciones', + items: [ + { label: 'Andromeda', link: '/andromeda/' }, + { label: 'Orion', link: '/orion/', isCurrent: true }, + { label: 'Osa Menor', link: '/ursa-minor/', badge: 'Stub' }, + ], + }, + ]} +> + Contenido de la página +</StarlightPage> +``` + +Ver la guía [“Navegación de la barra lateral”](/es/guides/sidebar/) para obtener más información sobre las opciones disponibles para personalizar la barra lateral. + +##### `hasSidebar` + +**tipo:** `boolean` +**por defecto:** `false` si [`frontmatter.template`](/es/reference/frontmatter/#template) es `'splash'`, de lo contrario `true` + +Controla si la barra lateral debe mostrarse en esta página o no. + +##### `headings` + +**tipo:** `{ depth: number; slug: string; text: string }[]` +**por defecto:** `[]` + +Proporciona un array de todos los encabezados en esta página. +Starlight generará la tabla de contenidos de la página a partir de estos encabezados si se proporcionan. + +##### `dir` + +**tipo:** `'ltr' | 'rtl'` +**por defecto:** la dirección de escritura para la configuración regional actual + +Establece la dirección de escritura para el contenido de esta página. + +##### `lang` + +**tipo:** `string` +**por defecto:** el idioma de la configuración regional actual + +Establece la etiqueta de idioma BCP-47 para el contenido de esta página, por ejemplo, `en`, `zh-CN` o `pt-BR`. + +##### `isFallback` + +**tipo:** `boolean` +**por defecto:** `false` + +Indica si esta página está utilizando [contenido alternativo](/es/guides/i18n/#contenido-de-respaldo) porque no hay traducción para el idioma actual. diff --git a/docs/src/content/docs/es/guides/project-structure.mdx b/docs/src/content/docs/es/guides/project-structure.mdx index c1e4f8c5ab5..b5a5f5065ca 100644 --- a/docs/src/content/docs/es/guides/project-structure.mdx +++ b/docs/src/content/docs/es/guides/project-structure.mdx @@ -12,7 +12,7 @@ Los proyectos de Starlight generalmente siguen la misma estructura de archivos y - `astro.config.mjs` — El archivo de configuración de Astro; incluye la integración y configuración de Starlight. - `src/content/config.ts` — El archivo de configuración de las colecciones de contenido; añade los esquemas del frontmatter de Starlight a tu proyecto. - `src/content/docs/` — Archivos de contenido. Starlight convierte cada archivo `.md`, `.mdx` o `.mdoc` en este directorio en una página de tu sitio. -- `src/content/i18n/` (opcional) — Datos de traducción para soportar la [internacionalización](/guides/i18n/). +- `src/content/i18n/` (opcional) — Datos de traducción para soportar la [internacionalización](/es/guides/i18n/). - `src/` — Otros códigos fuente y archivos (componentes, estilos, imágenes, etc.) para tu proyecto. - `public/` — Recursos estáticos (fuentes, favicon, PDF, etc.) que no serán procesados por Astro. @@ -20,7 +20,7 @@ Los proyectos de Starlight generalmente siguen la misma estructura de archivos y Un directorio de proyecto de Starlight podría lucir así: -import FileTree from '../../../../components/file-tree.astro'; +import { FileTree } from '@astrojs/starlight/components'; <FileTree> diff --git a/docs/src/content/docs/es/guides/route-data.mdx b/docs/src/content/docs/es/guides/route-data.mdx new file mode 100644 index 00000000000..7af82bccc8c --- /dev/null +++ b/docs/src/content/docs/es/guides/route-data.mdx @@ -0,0 +1,139 @@ +--- +title: Datos de Ruta +description: Aprende cómo se utiliza el modelo de datos de página de Starlight para renderizar tus páginas y cómo puedes personalizarlo. +--- + +import { Steps } from '@astrojs/starlight/components'; + +Cuando Starlight renderiza una página en tu documentación, primero crea un objeto de datos de ruta para representar lo que hay en esa página. +Esta guía explica cómo se generan los datos de ruta, cómo usarlos y cómo puedes personalizarlos para modificar el comportamiento predeterminado de Starlight. + +Consulta la [“Referencia de los Datos de Ruta”](/es/reference/route-data/) para obtener una lista completa de las propiedades disponibles. + +## ¿Qué son los datos de ruta? + +Los datos de ruta de Starlight son un objeto que contiene toda la información necesaria para renderizar una sola página. +Incluye información de la página actual, así como datos generados a partir de tu configuración de Starlight. + +## Uso de los datos de ruta + +Todos los componentes de Starlight utilizan los datos de ruta para decidir qué renderizar en cada página. +Por ejemplo, la cadena [`siteTitle`](/es/reference/route-data/#sitetitle) se utiliza para mostrar el título del sitio y el array [`sidebar`](/es/reference/route-data/#sidebar) se utiliza para renderizar la navegación global de la barra lateral. + +Puedes acceder a estos datos desde la variable global `Astro.locals.starlightRoute` en los componentes de Astro: + +```astro title="ejemplo.astro" {2} +--- +const { siteTitle } = Astro.locals.starlightRoute; +--- + +<p>El título de este sitio es “{siteTitle}”</p> +``` + +Esto puede ser útil, por ejemplo, al construir [sustituciones de componentes](/es/guides/overriding-components/) para personalizar lo que se muestra. + +## Personalización de los datos de ruta + +Los datos de ruta de Starlight funcionan de forma predeterminada y no requieren ninguna configuración. +Sin embargo, para casos de uso avanzados, es posible que desees personalizar los datos de ruta para algunas o todas las páginas para modificar cómo se muestra tu sitio. + +Este es un concepto similar a las [sustituciones de componentes](/es/guides/overriding-components/), pero en lugar de modificar cómo Starlight renderiza tus datos, modificas los datos que Starlight renderiza. + +### Cuándo personalizar los datos de ruta + +La personalización de los datos de ruta puede ser útil cuando deseas modificar cómo Starlight procesa tus datos de una manera que no es posible con las opciones de configuración existentes. + +Por ejemplo, es posible que desees filtrar elementos de la barra lateral o personalizar los títulos de páginas específicas. +Cambios como este no requieren modificar los componentes predeterminados de Starlight, solo los datos que se pasan a esos componentes. + +### Cómo personalizar los datos de ruta + +Puedes personalizar los datos de ruta utilizando una forma especial de “middleware”. +Esta es una función que se llama cada vez que Starlight renderiza una página y puede modificar los valores del objeto de datos de ruta. + +<Steps> + +1. Crea un nuevo archivo que exporte una función `onRequest` utilizando la utilidad `defineRouteMiddleware()` de Starlight: + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware(() => {}); + ``` + +2. Indica a Starlight dónde se encuentra tu archivo de middleware de datos de ruta en `astro.config.mjs`: + + ```js ins={9} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Mi increíble sitio de documentación', + routeMiddleware: './src/routeData.ts', + }), + ], + }); + ``` + +3. Actualiza tu función `onRequest` para modificar los datos de ruta. + + El primer argumento que recibirá tu middleware es el [objeto `context` de Astro](https://docs.astro.build/es/reference/api-reference/). + Este contiene información completa sobre la renderización de la página actual, incluyendo la URL actual y las `locals`. + + En este ejemplo, vamos a hacer que nuestra documentación sea más emocionante añadiendo un signo de exclamación al final del título de cada página. + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware((context) => { + // Obtiene la entrada de la colección de contenido para esta página. + const { entry } = context.locals.starlightRoute; + // Actualiza el título para añadir un signo de exclamación. + entry.data.title = entry.data.title + '!'; + }); + ``` + +</Steps> + +#### Múltiple middleware de ruta + +Starlight también admite proporcionar múltiples middleware. +Establece `routeMiddleware` en un array de rutas para añadir más de un manejador de middleware: + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Mi sitio con múltiples middleware', + routeMiddleware: ['./src/middleware-one.ts', './src/middleware-two.ts'], + }), + ], +}); +``` + +#### Esperando middleware de ruta posterior + +Para esperar a que se ejecute el middleware posterior en la pila antes de ejecutar tu código, puedes usar `await` en la función de callback `next()` que se pasa como segundo argumento a tu función de middleware. +Esto puede ser útil para esperar a que se ejecute el middleware de un plugin antes de realizar cambios, por ejemplo. + +```ts "next" "await next();" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware(async (context, next) => { + // Espera a que se ejecute el middleware posterior. + await next(); + // Modifica los datos de ruta. + const { entry } = context.locals.starlightRoute; + entry.data.title = entry.data.title + '!'; +}); +``` diff --git a/docs/src/content/docs/es/guides/sidebar.mdx b/docs/src/content/docs/es/guides/sidebar.mdx index 23a398f0df0..386c9501677 100644 --- a/docs/src/content/docs/es/guides/sidebar.mdx +++ b/docs/src/content/docs/es/guides/sidebar.mdx @@ -1,12 +1,10 @@ --- title: Barra Lateral de Navegación description: Aprende a configurar y personalizar los enlaces de navegación de la barra lateral de tu sitio Starlight. -sidebar: - badge: Nuevo --- -import FileTree from '../../../../components/file-tree.astro'; -import SidebarPreview from '../../../../components/sidebar-preview.astro'; +import { FileTree } from '@astrojs/starlight/components'; +import SidebarPreview from '~/components/sidebar-preview.astro'; Una barra lateral bien organizada es clave para una buena documentación, ya que es una de las principales formas en que los usuarios navegarán por su sitio. Starlight proporciona un conjunto completo de opciones para personalizar el diseño y el contenido de tu barra lateral. @@ -21,11 +19,11 @@ Por ejemplo, dada la siguiente estructura de archivos: - src/ - content/ - docs/ - - guides/ - - components.md - - i18n.md - - reference/ - - configuration.md + - constellations/ + - andromeda.md + - orion.md + - stars/ + - betelgeuse.md </FileTree> @@ -34,20 +32,15 @@ La siguiente barra lateral se generará automáticamente: <SidebarPreview config={[ { - label: 'guides', + label: 'constellations', items: [ - { label: 'Componentes', link: '/guides/components/' }, - { label: 'Internacionalización (i18n)', link: '/guides/i18n/' }, + { label: 'Andrómeda', link: '' }, + { label: 'Orión', link: '' }, ], }, { - label: 'referencia', - items: [ - { - label: 'Referencia de configuración', - link: '/reference/configuration/', - }, - ], + label: 'stars', + items: [{ label: 'Betelgeuse', link: '' }], }, ]} /> @@ -56,21 +49,75 @@ Aprende más sobre las barras laterales generadas automáticamente en la secció ## Agregar enlaces y grupos de enlaces -Para configurar los [enlaces](#enlaces) de tu barra lateral y [grupos de enlaces](#grupos) (dentro de un encabezado plegable), usa la propiedad [`starlight.sidebar`](/es/reference/configuration/#sidebar) en `astro.config.mjs`. +Para configurar los enlaces de tu barra lateral y grupos de enlaces (dentro de un encabezado plegable), usa la propiedad [`starlight.sidebar`](/es/reference/configuration/#sidebar) en `astro.config.mjs`. Combinando enlaces y grupos, puedes crear una amplia variedad de diseños de barra lateral. -### Enlaces +### Enlaces internos + +Agrega un enlace a una página en `src/content/docs/` usando un objeto con la propiedad `slug`. +El título de la página vinculada se utilizará como etiqueta de forma predeterminada. -Agrega un enlace a una página interna o externa usando un objeto con las propiedades `label` y `link`. +Por ejemplo, con la siguiente configuración: -```js +```js "slug:" starlight({ sidebar: [ - // Un enlace a la guía CSS y Estilos. - { label: 'CSS y Estilos', link: '/guides/css-and-tailwind/' }, - // Un enlace externo al sitio web de Astro. - { label: 'Astro', link: 'https://astro.build/' }, + { slug: 'constellations/andromeda' }, + { slug: 'constellations/orion' }, + ], +}); +``` + +Y la siguiente estructura de archivos: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - andromeda.md + - orion.md + +</FileTree> + +La siguiente barra lateral se generará automáticamente: + +<SidebarPreview + config={[ + { label: 'Andrómeda', link: '' }, + { label: 'Orión', link: '' }, + ]} +/> + +Para sobreescribir los valores inferidos del frontmatter de una página vinculada, puedes agregar las propiedades `label`, [`translations`](#internacionalización) y [`attrs`](#atributos-html-personalizados). + +Ve [“Personalización de enlaces autogenerados”](#personalización-de-enlaces-autogenerados-en-el-frontmatter) para más detalles sobre cómo controlar la apariencia de la barra lateral desde el frontmatter de la página. + +#### Atajo para enlaces internos + +Los enlaces internos también se pueden especificar proporcionando solo un string para el slug de la página como un atajo. + +Por ejemplo, la siguiente configuración es equivalente a la configuración anterior, que usaba `slug`: + +```js "slug:" +starlight({ + sidebar: ['constellations/andromeda', 'constellations/orion'], +}); +``` + +### Otros enlaces + +Agrega un enlace a una página externa o un enlace que no sea de documentación usando un objeto con las propiedades `label` y `link`. + +```js "label:" "link:" +starlight({ + sidebar: [ + // Un enlace a una página que no sea de documentación en este sitio. + { label: 'Tienda de Meteoritos', link: '/shop/' }, + // Un enlace externo al sitio web de la NASA. + { label: 'NASA', link: 'https://www.nasa.gov/' }, ], }); ``` @@ -79,8 +126,8 @@ La configuración anterior genera la siguiente barra lateral: <SidebarPreview config={[ - { label: 'CSS y Estilos', link: '/guides/css-and-tailwind/' }, - { label: 'Astro', link: 'https://astro.build/' }, + { label: 'Tienda de Meteoritos', link: '' }, + { label: 'NASA', link: 'https://www.nasa.gov/' }, ]} /> @@ -93,22 +140,22 @@ Agrega un grupo usando un objeto con las propiedades `label` y `items`. La `label` se utilizará como encabezado del grupo. Agrega enlaces o subgrupos al arreglo `items`. -```js +```js /^\s*(label:|items:)/ starlight({ sidebar: [ - // Un grupo de enlaces etiquetados como "Guides" + // Un grupo de enlaces etiquetado "Constelaciones". { - label: 'Guías', + label: 'Constelaciones', items: [ - { label: 'Componentes', link: '/guides/components/' }, - { label: 'Internacionalización (i18n)', link: '/guides/i18n/' }, - // Un grupo anidado de enlaces. + 'constellations/carina', + 'constellations/centaurus', + // Un grupo anidado de enlaces para constelaciones estacionales. { - label: 'Estilando', + label: 'Estacional', items: [ - { label: 'CSS', link: '/guides/css-and-tailwind/' }, - { label: 'Tailwind', link: '/guides/css-and-tailwind/' }, - { label: 'Shiki', link: '/guides/css-and-tailwind/' }, + 'constellations/andromeda', + 'constellations/orion', + 'constellations/ursa-minor', ], }, ], @@ -122,16 +169,16 @@ La configuración anterior genera la siguiente barra lateral: <SidebarPreview config={[ { - label: 'Guías', + label: 'Constelaciones', items: [ - { label: 'Componentes', link: '/guides/components/' }, - { label: 'Internacionalización (i18n)', link: '/guides/i18n/' }, + { label: 'Carina', link: '' }, + { label: 'Centaurus', link: '' }, { - label: 'Estilando', + label: 'Estacional', items: [ - { label: 'CSS', link: '/guides/css-and-tailwind/' }, - { label: 'Tailwind', link: '/guides/css-and-tailwind/' }, - { label: 'Shiki', link: '/guides/css-and-tailwind/' }, + { label: 'Andrómeda', link: '' }, + { label: 'Orión', link: '' }, + { label: 'Osa Menor', link: '' }, ], }, ], @@ -143,17 +190,18 @@ La configuración anterior genera la siguiente barra lateral: Starlight puede generar automáticamente un grupo en tu barra lateral basado en un directorio de tu documentación. Esto es útil cuando no deseas ingresar manualmente cada elemento de la barra lateral en un grupo. -Las páginas serán ordenadas alfabéticamente por nombre de archivo de forma predeterminada. + +Por defecto, las páginas se ordenan en orden alfabético según el [`slug`](/es/reference/overrides/#slug) del archivo. Agrega un grupo autogenerado usando un objeto con las propiedades `label` y `autogenerate`. Tu configuración `autogenerate` debe especificar el `directory` para usar en las entradas de la barra lateral. Por ejemplo, con la siguiente configuración: -```js +```js "label:" "autogenerate:" starlight({ sidebar: [ { - label: 'Guías', - // Autogenera un grupo de enlaces para el directorio 'guides'. - autogenerate: { directory: 'guides' }, + label: 'Constelaciones', + // Un grupo de enlaces autogenerados para el directorio 'constellations'. + autogenerate: { directory: 'constellations' }, }, ], }); @@ -166,11 +214,11 @@ Y la siguiente estructura de archivos: - src/ - content/ - docs/ - - guides/ - - components.md - - i18n.md - - advanced/ - - project-structure.md + - constellations/ + - carina.md + - centaurus.md + - seasonal/ + - andromeda.md </FileTree> @@ -179,31 +227,26 @@ La siguiente barra lateral se generará automáticamente: <SidebarPreview config={[ { - label: 'Guías', + label: 'Constelaciones', items: [ - { label: 'Componentes', link: '/guides/components/' }, - { label: 'Internacionalización (i18n)', link: '/guides/i18n/' }, + { label: 'Carina', link: '' }, + { label: 'Centaurus', link: '' }, { - label: 'avanzado', - items: [ - { - label: 'Estructura de Proyecto', - link: '/guides/project-structure/', - }, - ], + label: 'seasonal', + items: [{ label: 'Andrómeda', link: '' }], }, ], }, ]} /> -#### Personalización de enlaces autogenerados en el frontmatter +## Personalización de enlaces autogenerados en el frontmatter Usa el campo [`sidebar`](/es/reference/frontmatter/#sidebar) en las páginas individuales para personalizar los enlaces autogenerados. Las opciones del frontmatter de la barra lateral te permiten establecer un [etiqueta personalizada](/es/reference/frontmatter/#label) o agregar una [insignia](/es/reference/frontmatter/#badge) a un enlace, [ocultar](/es/reference/frontmatter/#hidden) un enlace de la barra lateral o definir un [peso de ordenación personalizado](/es/reference/frontmatter/#order). -```md +```md "sidebar:" --- title: Mi página sidebar: @@ -225,40 +268,45 @@ Un grupo autogenerado que incluye una página con el frontmatter anterior genera { label: 'Guías', items: [ - { label: 'Una página', link: '#' }, + { label: 'Una página', link: '' }, { label: 'Etiqueta personalizada de la barra lateral', - link: '#', + link: '', badge: { text: 'Nuevo', variant: 'tip' }, }, - { label: 'Otra página', link: '#' }, + { label: 'Otra página', link: '' }, ], }, ]} /> :::note -La configuración `sidebar` del frontmatter solo se usa para enlaces autogenerados y se ignorará para enlaces definidos manualmente. +El frontmatter `sidebar` solo se utiliza para enlaces en grupos autogenerados y enlaces de documentos definidos con la propiedad `slug`. No se aplica a los enlaces definidos con la propiedad `link`. ::: ## Insignias -Los enlaces también pueden incluir una propiedad `badge` para mostrar una insignia junto a la etiqueta del enlace. +Los enlaces, grupos y grupos autogenerados también pueden incluir una propiedad `badge` para mostrar una insignia junto a la etiqueta del enlace. -```js +```js {9,16} starlight({ sidebar: [ { - label: 'Guías', + label: 'Estrellas', items: [ - // Un enlace con una insignia "Nuevo". + // Un enlace con una insignia "Supergigante". { - label: 'Componentes', - link: '/guides/components/', - badge: 'Nuevo', + slug: 'stars/persei', + badge: 'Supergigante', }, ], }, + // Un grupo autogenerado con una insignia "Obsoleto". + { + label: 'Moons', + badge: 'Obsoleto', + autogenerate: { directory: 'moons' }, + }, ], }); ``` @@ -268,36 +316,55 @@ La configuración anterior genera la siguiente barra lateral: <SidebarPreview config={[ { - label: 'Guías', + label: 'Estrellas', + items: [ + { + label: 'Persei', + link: '', + badge: { text: 'Supergigante', variant: 'default' }, + }, + ], + }, + { + label: 'Lunas', + badge: { text: 'Obsoleto', variant: 'default' }, items: [ { - label: 'Componentes', - link: '/guides/components/', - badge: { text: 'Nuevo', variant: 'default' }, + label: 'Ío', + link: '', + }, + { + label: 'Europa', + link: '', + }, + { + label: 'Ganímedes', + link: '', }, ], }, ]} /> -### Variantes de insignia +### Variantes de insignia y estilos personalizados -Personaliza el estilo de la insignia usando un objeto con las propiedades `text` y `variant`. +Personaliza el estilo de la insignia usando un objeto con las propiedades `text`, `variant` y `class`. La propiedad `text` representa el contenido a mostrar (por ejemplo, "Nuevo"). -Remplaza el estilo `default`, que usa el color de acento de tu sitio, estableciendo la propiedad `variant` a uno de los siguientes valores: `note`, `tip`, `danger`, `caution` o `success`. +Por defecto, la insignia usará el color de acento de tu sitio. Para usar un estilo de insignia integrado, establece la propiedad `variant` en uno de los siguientes valores: `note`, `tip`, `danger`, `caution` o `success`. + +Opcionalmente, puedes crear un estilo de insignia personalizado estableciendo la propiedad `class` en un nombre de clase CSS. -```js +```js {9} starlight({ sidebar: [ { - label: 'Guías', + label: 'Estrellas', items: [ - // Un enlace con una insignia "Experimental" amarilla. + // Un enlace con una insignia "Stub" amarilla. { - label: 'Componentes', - link: '/guides/components/', - badge: { text: 'Experimental', variant: 'caution' }, + slug: 'stars/sirius', + badge: { text: 'Stub', variant: 'caution' }, }, ], }, @@ -310,12 +377,55 @@ La configuración anterior genera la siguiente barra lateral: <SidebarPreview config={[ { - label: 'Guías', + label: 'Estrellas', items: [ { - label: 'Componentes', - link: '/guides/components/', - badge: { text: 'Experimental', variant: 'caution' }, + label: 'Sirio', + link: '', + badge: { text: 'Stub', variant: 'caution' }, + }, + ], + }, + ]} +/> + +## Atributos HTML personalizados + +Los enlaces también pueden incluir una propiedad `attrs` para agregar atributos HTML personalizados al elemento de enlace. + +En el siguiente ejemplo, `attrs` se usa para agregar un atributo `target="_blank"`, de modo que el enlace se abra en una nueva pestaña, y para aplicar un atributo `style` personalizado para poner en cursiva la etiqueta del enlace: + +```js {9} +starlight({ + sidebar: [ + { + label: 'Recursos', + items: [ + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { target: '_blank', style: 'font-style: italic' }, + }, + ], + }, + ], +}); +``` + +La configuración anterior genera la siguiente barra lateral: + +<SidebarPreview + config={[ + { + label: 'Recursos', + items: [ + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { + target: '_blank', + style: 'font-style: italic', + }, }, ], }, @@ -324,32 +434,32 @@ La configuración anterior genera la siguiente barra lateral: ## Internacionalización -Usa la propiedad `translations` en las entradas de enlace y grupo para traducir la etiqueta del enlace o grupo para cada idioma compatible. +Usa la propiedad `translations` en las entradas de enlace y grupo para traducir la etiqueta del enlace o grupo para cada idioma compatible especificando una etiqueta de idioma [BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags), p. ej. `"en"`, `"ar"`, o `"zh-CN"`, como clave, y la etiqueta traducida como valor. La propiedad `label` se utilizará para el idioma predeterminado y para los idiomas sin traducción. -```js +```js {5-7,11-13,18-20} starlight({ sidebar: [ { - label: 'Guides', + label: 'Constelaciones', translations: { - es: 'Guías', + 'pt-BR': 'Constelações', }, items: [ { - label: 'Components', + label: 'Andrómeda', translations: { - es: 'Componentes', + 'pt-BR': 'Andrômeda', }, - link: '/guides/components/', + slug: 'constellations/andromeda', }, { - label: 'Internationalization (i18n)', + label: 'Escorpio', translations: { - es: 'Internacionalización (i18n)', + 'pt-BR': 'Escorpião', }, - link: '/guides/i18n/', + slug: 'constellations/scorpius', }, ], }, @@ -357,15 +467,99 @@ starlight({ }); ``` -Navegar por la documentación en español generará la siguiente barra lateral: +Navegar por la documentación en portugués de Brasil generará la siguiente barra lateral: <SidebarPreview config={[ { - label: 'Guías', + label: 'Constelação', items: [ - { label: 'Componentes', link: '/guides/components/' }, - { label: 'Internacionalización (i18n)', link: '/guides/i18n/' }, + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +### Internacionalización con enlaces internos + +[Los Enlaces internos](#enlaces-internos) utilizarán automáticamente los títulos de página traducidos del frontmatter de contenido de forma predeterminada: + +```js {9-10} +starlight({ + sidebar: [ + { + label: 'Constellations', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { slug: 'constellations/andromeda' }, + { slug: 'constellations/scorpius' }, + ], + }, + ], +}); +``` + +Navegando por la documentación en portugués de Brasil generará la siguiente barra lateral: + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> +En sitios multilingües, el valor de `slug` no incluye la parte del idioma de la +URL. Por ejemplo, si tienes páginas en `en/intro` y `pt-br/intro`, el slug es +`intro` al configurar la barra lateral. + +### Internacionalización con insignias + +Para [insignias](#insignias), la propiedad `text` puede ser un string, o para sitios multilingües, un objeto con valores para cada idioma diferente. +Cuando se usa la forma de objeto, las claves deben ser etiquetas [BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags) (p. ej. `en`, `ar`, o `zh-CN`): + +```js {11-16} +starlight({ + sidebar: [ + { + label: 'Constellations', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { + slug: 'constellations/andromeda', + badge: { + text: { + en: 'New', + 'pt-BR': 'Novo', + }, + }, + }, + ], + }, + ], +}); +``` + +Navegando por la documentación en portugués de Brasil generará la siguiente barra lateral: + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { + label: 'Andrômeda', + link: '', + badge: { text: 'Novo', variant: 'default' }, + }, ], }, ]} @@ -375,17 +569,14 @@ Navegar por la documentación en español generará la siguiente barra lateral: Los grupos de enlaces pueden colapsarse por defecto estableciendo la propiedad `collapsed` en `true`. -```js +```js {5-6} starlight({ sidebar: [ { - label: 'Guías', + label: 'Constelaciones', // Collapsa el grupo de forma predeterminada. collapsed: true, - items: [ - { label: 'Componentes', link: '/guides/components/' }, - { label: 'Internacionalización (i18n)', link: '/guides/i18n/' }, - ], + items: ['constellations/andromeda', 'constellations/orion'], }, ], }); @@ -396,11 +587,11 @@ La configuración anterior genera la siguiente barra lateral: <SidebarPreview config={[ { - label: 'Guías', + label: 'Constelaciones', collapsed: true, items: [ - { label: 'Componentes', link: '/guides/components/' }, - { label: 'Internacionalización (i18n)', link: '/guides/i18n/' }, + { label: 'Andrómeda', link: '' }, + { label: 'Orion', link: '' }, ], }, ]} @@ -408,14 +599,14 @@ La configuración anterior genera la siguiente barra lateral: [Grupos autogenerados](#grupos-autogenerados) respetan el valor `collapsed` de su grupo padre: -```js +```js {5-6} starlight({ sidebar: [ { - label: 'Guías', + label: 'Constelaciones', // Colapsa el grupo y sus subgrupos autogenerados de forma predeterminada. collapsed: true, - autogenerate: { directory: 'guides' }, + autogenerate: { directory: 'constellations' }, }, ], }); @@ -426,37 +617,34 @@ La configuración anterior genera la siguiente barra lateral: <SidebarPreview config={[ { - label: 'Guías', + label: 'Constelaciones', collapsed: true, items: [ - { label: 'Componentes', link: '/guides/components/' }, - { label: 'Internacionalización (i18n)', link: '/guides/i18n/' }, - { - label: 'advanced', - collapsed: true, - items: [ - { - label: 'Estructura de Proyecto', - link: '/guides/project-structure/', - }, - ], - }, - ], - }, - ]} + + { label: 'Carina', link: '' }, + { label: 'Centaurus', link: '' }, + { + label: 'seasonal', + collapsed: true, + items: [{ label: 'Andrómeda', link: '' }], + }, + ], + }, + ]} + /> Este comportamiento puede remplazarse definiendo la propiedad `autogenerate.collapsed`. -```js +```js {5-7} "collapsed: true" starlight({ sidebar: [ { - label: 'Guías', - // No colapsa el grupo "Guides" pero colapsa sus + label: 'Constelaciones', + // No colapsa el grupo "Constelattions" pero colapsa sus // subgrupos autogenerados. collapsed: false, - autogenerate: { directory: 'guides', collapsed: true }, + autogenerate: { directory: 'constellations', collapsed: true }, }, ], }); @@ -467,19 +655,14 @@ La configuración anterior genera la siguiente barra lateral: <SidebarPreview config={[ { - label: 'Guías', + label: 'Constelaciones', items: [ - { label: 'Componentes', link: '/guides/components/' }, - { label: 'Internacionalización (i18n)', link: '/guides/i18n/' }, + { label: 'Carina', link: '' }, + { label: 'Centaurus', link: '' }, { - label: 'advanced', + label: 'seasonal', collapsed: true, - items: [ - { - label: 'Estructura de Proyecto', - link: '/guides/project-structure/', - }, - ], + items: [{ label: 'Andrómeda', link: '' }], }, ], }, diff --git a/docs/src/content/docs/es/guides/site-search.mdx b/docs/src/content/docs/es/guides/site-search.mdx new file mode 100644 index 00000000000..144c32a5a5a --- /dev/null +++ b/docs/src/content/docs/es/guides/site-search.mdx @@ -0,0 +1,173 @@ +--- +title: Búsqueda en el sitio +description: Aprende sobre las funciones de búsqueda de sitios integradas de Starlight y cómo personalizarlas. +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +Por defecto, los sitios de Starlight incluyen una búsqueda de texto completo impulsada por [Pagefind](https://pagefind.app/), que es una herramienta de búsqueda rápida y de bajo ancho de banda para sitios estáticos. + +No es necesaria ninguna configuración para habilitar la búsqueda. Construye e implementa tu sitio, luego usa la barra de búsqueda en el encabezado del sitio para encontrar contenido. + +## Ocultar contenido en los resultados de búsqueda + +### Excluye una página + +Para excluir una página del índice de búsqueda, agrega [`pagefind: false`](/es/reference/frontmatter/#pagefind) al frontmatter de la página: + +```md title="src/content/docs/not-indexed.md" ins={3} +--- +title: Contenido para ocultar de la búsqueda +pagefind: false +--- +``` + +### Excluye parte de una página + +Pagefind ignorará el contenido dentro de un elemento con el atributo [`data-pagefind-ignore`](https://pagefind.app/docs/indexing/#removing-individual-elements-from-the-index). + +En el siguiente ejemplo, el primer párrafo se mostrará en los resultados de búsqueda, pero el contenido del `<div>` no: + +```md title="src/content/docs/partially-indexed.md" ins="data-pagefind-ignore" +--- +title: Página parcialmente indexada +--- + +Este texto será descubrible a través de la búsqueda. + +<div data-pagefind-ignore> + +Este texto estará oculto de la búsqueda. + +</div> +``` + +## Proveedores de búsqueda alternativos + +### Algolia DocSearch + +Si tienes acceso al [programa DocSearch de Algolia](https://docsearch.algolia.com/) y quieres usarlo en lugar de Pagefind, puedes usar el plugin oficial Starlight DocSearch. + +<Steps> + +1. Instala `@astrojs/starlight-docsearch`: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-docsearch + ``` + + </TabItem> + + </Tabs> + +2. Agrega DocSearch a tu configuración de Starlight [`plugins`](/es/reference/configuration/#plugins) en `astro.config.mjs` y pásale tu `appId`, `apiKey` e `indexName` de Algolia: + + ```js ins={4,10-16} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Sitio con DocSearch', + plugins: [ + starlightDocSearch({ + appId: 'TU_ID_DE_APP' + apiKey: 'TU_LLAVE_DE_API_DE_BÚSQUEDA' + indexName: 'TU_NOMBRE_DE_ÍNDICE', + }), + ], + }), + ], + }); + ``` + +</Steps> + +Con esta configuración actualizada, la barra de búsqueda de tu sitio ahora abrirá un modal de Algolia en lugar del modal de búsqueda predeterminado. + +#### Traduciendo la UI de DocSearch + +DocSearch solo proporciona cadenas de UI en inglés de forma predeterminada. +Para agregar traducciones de la UI al modal en otros idiomas, usa el [sistema de internacionalización](/es/guides/i18n/#traduce-la-ui-de-starlight) incorporado de Starlight. + +<Steps> + +1. Extiende la definición de la colección de contenido `i18n` de Starlight con el esquema de DocSearch en `src/content/config.ts`: + + ```js ins={4} ins=/{ extend: .+ }/ + // src/content/config.ts + import { defineCollection } from 'astro:content'; + import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + import { docSearchI18nSchema } from '@astrojs/starlight-docsearch/schema'; + + export const collections = { + docs: defineCollection({ schema: docsSchema() }), + i18n: defineCollection({ + type: 'data', + schema: i18nSchema({ extend: docSearchI18nSchema() }), + }), + }; + ``` + +2. Agrega traducciones a tus archivos JSON en `src/content/i18n/`. + + Estas son las predeterminadas en inglés que usa DocSearch: + + ```json title="src/content/i18n/en.json" + { + "docsearch.searchBox.resetButtonTitle": "Clear the query", + "docsearch.searchBox.resetButtonAriaLabel": "Clear the query", + "docsearch.searchBox.cancelButtonText": "Cancel", + "docsearch.searchBox.cancelButtonAriaLabel": "Cancel", + "docsearch.searchBox.searchInputLabel": "Search", + + "docsearch.startScreen.recentSearchesTitle": "Recent", + "docsearch.startScreen.noRecentSearchesText": "No recent searches", + "docsearch.startScreen.saveRecentSearchButtonTitle": "Save this search", + "docsearch.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", + "docsearch.startScreen.favoriteSearchesTitle": "Favorite", + "docsearch.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + + "docsearch.errorScreen.titleText": "Unable to fetch results", + "docsearch.errorScreen.helpText": "You might want to check your network connection.", + + "docsearch.footer.selectText": "to select", + "docsearch.footer.selectKeyAriaLabel": "Enter key", + "docsearch.footer.navigateText": "to navigate", + "docsearch.footer.navigateUpKeyAriaLabel": "Arrow up", + "docsearch.footer.navigateDownKeyAriaLabel": "Arrow down", + "docsearch.footer.closeText": "to close", + "docsearch.footer.closeKeyAriaLabel": "Escape key", + "docsearch.footer.searchByText": "Search by", + + "docsearch.noResultsScreen.noResultsText": "No results for", + "docsearch.noResultsScreen.suggestedQueryText": "Try searching for", + "docsearch.noResultsScreen.reportMissingResultsText": "Believe this query should return results?", + "docsearch.noResultsScreen.reportMissingResultsLinkText": "Let us know." + } + ``` + +</Steps> diff --git a/docs/src/content/docs/es/index.mdx b/docs/src/content/docs/es/index.mdx index 056e7b307c2..4d2515ab485 100644 --- a/docs/src/content/docs/es/index.mdx +++ b/docs/src/content/docs/es/index.mdx @@ -1,33 +1,31 @@ --- title: Starlight 🌟 Construye sitios de documentación con Astro +head: + - tag: title + content: Starlight 🌟 Construye sitios de documentación con Astro description: Starlight te ayuda a construir sitios web de documentación hermosos y de alto rendimiento utilizando Astro. template: splash -banner: - content: | - <span class="ph-banner"> - <span class="ph-houston"><img src="/ph-houston.svg" alt="" width="72" height="72"/></span> - <span class="ph-text"> - <strong>Bienvenidos Product Hunters 👋</strong> - <a href="https://www.producthunt.com/posts/starlight-by-astro">¡Estamos en vivo ahora!</a> - </span> - </span> +editUrl: false +lastUpdated: false hero: title: Haz que tus docs brillen con Starlight tagline: Todo lo que necesitas para construir un sitio web de documentación estelar. Rápido, accesible y fácil de usar. image: - file: ../../../assets/hero-star.webp + file: ~/assets/hero-star.webp actions: - text: Empezar icon: right-arrow - variant: primary link: /es/getting-started/ - text: Ver en GitHub icon: external + variant: minimal link: https://github.com/withastro/starlight --- import { CardGrid, Card } from '@astrojs/starlight/components'; -import AboutAstro from '../../../components/about-astro.astro'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; <CardGrid stagger> <Card title="Documentación que deleita" icon="open-book"> @@ -49,6 +47,114 @@ import AboutAstro from '../../../components/about-astro.astro'; </Card> </CardGrid> +<TestimonialGrid title="Lo que nuestros usuarios opinan"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + El equipo de Astro ha EVOLUCIONADO la forma en que se pueden hacer la documentación y puedes obtenerlo todo directamente con tu proyecto Starlight. + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + La plantilla oficial de Astro Starlight es una herramienta realmente increíble para construir un sitio web de documentación + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + Starlight es nuestro ejemplo de una gran DX: la velocidad, la comodidad y + la atención a los detalles son inspiradores. Se encarga de la tecnología y el aspecto, + para que puedas centrarte en tu contenido 👏 + +¡El equipo de StackBlitz lo ama absolutamente! + + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + Starlight ha sido un cambio de juego para mí, permitiéndome centrarme en la creación de contenido. + + Su diseño intuitivo no solo agiliza mi flujo de trabajo, sino que también reduce el tiempo de incorporación para los desarrolladores de código abierto. + + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + Pasé más tiempo con Starlight para la documentación de Course Builder y ha sido genial hasta ahora. Muchos toques agradables y puedo centrarme en escribir en Markdown y no en jugar con el sitio. + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + Empecé a jugar con Starlight. Tengo que decir que estoy muy impresionado con el rendimiento que ofrece de forma predeterminada. + + 💯💯💯💯 + + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + Starlight es la mejor manera de empezar con la documentación, entre la + potencia y la velocidad de Astro y las herramientas de Starlight + coinciden con el cielo. + + ¡Ha sido mi elección durante un tiempo y sigo amándolo! + + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + Yo usé Starlight en mi último trabajo y me encantó. Buenos componentes, diseño + intuitivo y una comunidad super receptiva (cuando alguien necesitaba algo, + lo enviaban pronto o te decían una solución alternativa). Una experiencia muy agradable. + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + La documentación del monorepo de mi sitio se ve mejor que nunca gracias a Starlight. Es extremadamente fácil de usar sin perder todo el poder de Astro. ¡Gracias por trabajar en ello! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + Starlight es mi herramienta de documentación por defecto. Hizo que fuera muy fácil añadir documentación a mi sitio web de producto Astro existente, en lugar de necesitar un subdominio para usar con otra herramienta. + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + Yo he estado reconstruyendo la documentación de la plataforma WPEngine Atlas. Créeme cuando digo que Starlight tiene todo lo que necesitas para hacer una plataforma de documentación A+ 🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + ¡Dale una oportunidad a Starlight! + + Yo lo uso para algunos de mis sitios y es genial. + + </Testimonial> +</TestimonialGrid> + <AboutAstro title="Presentado por"> Astro es el framework web todo en uno diseñado para la velocidad. Obtén tu contenido desde cualquier lugar y despliégalo en cualquier parte, todo potenciado por tus componentes y bibliotecas de UI favoritas. diff --git a/docs/src/content/docs/es/manual-setup.mdx b/docs/src/content/docs/es/manual-setup.mdx index 488699bd9be..274d3ef3913 100644 --- a/docs/src/content/docs/es/manual-setup.mdx +++ b/docs/src/content/docs/es/manual-setup.mdx @@ -5,7 +5,7 @@ description: Aprende como configurar Starlight manualmente para agregarlo a un p import { Tabs, TabItem } from '@astrojs/starlight/components'; -La manera más rápida de crear un nuevo sitio Starlight es usando `create astro` como se muestra en la [Guía de Inicio Rápido](/es/getting-started/#creando-un-nuevo-proyecto). +La manera más rápida de crear un nuevo sitio Starlight es usando `create astro` como se muestra en la [Guía de Inicio Rápido](/es/getting-started/#crea-un-nuevo-proyecto). Si quieres agregar Starlight a un proyecto de Astro existente, esta guía te explicará como hacerlo. ## Configuración de Starlight @@ -16,7 +16,7 @@ Para seguir esta guía, necesitarás un proyecto de Astro existente. Starlight es una [integración de Astro](https://docs.astro.build/es/guides/integrations-guide/). Agregala a tu sitio ejecutando el comando `astro add` en el directorio raíz de tu proyecto: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh npx astro add starlight @@ -44,7 +44,7 @@ La integración de Starlight está configurada en tu archivo `astro.config.mjs`. Agrega un `title` para comenzar: -```js {7-9} +```js ins={8} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -106,7 +106,7 @@ Para agregar todas las páginas de Starlight en una subruta, coloca todo tu cont Por ejemplo, si las páginas de Starlight deben comenzar con `/guides/`, agrega tu contenido en el directorio `src/content/docs/guides/`: -import FileTree from '../../../components/file-tree.astro'; +import { FileTree } from '@astrojs/starlight/components'; <FileTree> @@ -125,4 +125,6 @@ En el futuro, planeamos soportar mejor este caso de uso para evitar la necesidad ### Usa Starlight con SSR -Por el momento, Starlight no soporta el [despliegue SSR](https://docs.astro.build/es/guides/server-side-rendering/) usando los adaptadores de servidor de Astro. Esperamos poder soportar esto pronto. +Para habilitar el SSR, sigue la guía [“Adaptadores de Renderizado bajo Demanda”](https://docs.astro.build/es/guides/server-side-rendering/) en la documentación de Astro para agregar un adaptador de servidor a tu proyecto Starlight. + +Las páginas de documentación generadas por Starlight se pre-renderizan de forma predeterminada independientemente del modo de salida de tu proyecto. Para excluir tus páginas de Starlight de la pre-renderización, establece la [opción de configuración `prerender`](/es/reference/configuration/#prerender) en `false`. diff --git a/docs/src/content/docs/es/reference/configuration.md b/docs/src/content/docs/es/reference/configuration.md deleted file mode 100644 index 3d7df8e148d..00000000000 --- a/docs/src/content/docs/es/reference/configuration.md +++ /dev/null @@ -1,426 +0,0 @@ ---- -title: Referencia de Configuración -description: Una descripción general de todas las opciones de configuración que admite Starlight. ---- - -## Configurar la integración `starlight` - -Starlight es una integración construida sobre el framework [Astro](https://astro.build). Puedes configurar tu proyecto dentro del archivo de configuración `astro.config.mjs`: - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; -export default defineConfig({ - integrations: [ - starlight({ - title: 'Mi encantador sitio de documentación', - }), - ], -}); -``` - -Puedes pasar las siguientes opciones a la integración `starlight`. - -### `title` (requerido) - -**tipo:** `string` - -Establece el título de tu sitio web. Se utilizará en los metadatos y en el título de la pestaña del navegador. - -### `description` - -**tipo:** `string` - -Establece la descripción de tu sitio web. Es usada en los metadatos compartidos con los motores de búsqueda en la etiqueta `<meta name="description">` si no se establece `description` en el frontmatter de una página. - -### `logo` - -**tipo:** [`LogoConfig`](#logoconfig) - -Establece un logotipo para mostrarlo en la barra de navegación junto al título del sitio o en su lugar. Puedes establecer una única propiedad `src` o establecer fuentes de imagen separadas para `light` y `dark`. - -```js -starlight({ - logo: { - src: './src/assets/mi-logo.svg', - }, -}); -``` - -#### `LogoConfig` - -```ts -type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( - | { src: string } - | { light: string; dark: string } -); -``` - -### `tableOfContents` - -**tipo:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` -**por defecto:** `{ minHeadingLevel: 2; maxHeadingLevel: 3; }` - -Configura la tabla de contenidos que se muestra a la derecha de cada página. De forma predeterminada, los encabezados `<h2>` y `<h3>` se incluirán en esta tabla de contenidos. - -### `editLink` - -**tipo:** `{ baseUrl: string }` - -Hablita "Editar los enlaces" de está página estableciendo la URL base que se debe usar. El enlace final será `editLink.baseUrl` + la ruta de la página actual. Por ejemplo, para habilitar la edición de páginas en el repositorio `withastro/starlight` en GitHub: - -```js -starlight({ - editLink: { - baseUrl: 'https://github.com/withastro/starlight/edit/main/', - }, -}); -``` - -Con esta configuración, una página `/introduction` tendría un enlace de edición que apunta a `https://github.com/withastro/starlight/edit/main/src/docs/introduction.md`. - -### `sidebar` - -**tipo:** [`SidebarItem[]`](#sidebaritem) - -Configura los elementos de navegación de la barra lateral de tu sitio. - -Una barra lateral es un conjunto de enlaces y grupos de enlaces. -Cada elemento debe tener una propiedad `label` y una de las siguientes propiedades: - -- `link` — Un solo enlace a una URL específica, p. ej. `'/home'` o `'https://example.com'`. - -- `items` — Un array que contiene más enlaces de la barra lateral y subgrupos. - -- `autogenerate` — Un objeto que especifica un directorio de tus documentos para generar automáticamente un grupo de enlaces. - -```js -starlight({ - sidebar: [ - // Un solo elemento de enlace etiquetado como “Home”. - { label: 'Home', link: '/' }, - // Un grupo etiquetado como "Start Here" que contiene dos enlaces. - { - label: 'Start Here', - items: [ - { label: 'Introduction', link: '/intro' }, - { label: 'Next Steps', link: '/next-steps' }, - ], - }, - // Un grupo que enlaza a todas las páginas del directorio de referencia. - { - label: 'Reference', - autogenerate: { - directory: 'reference', - }, - }, - ], -}); -``` - -#### Ordenación - -Los grupos de la barra lateral generados automáticamente se ordenan alfabéticamente por el nombre del archivo. -Por ejemplo, una página generada a partir de `astro.md` aparecería por encima de la página `starlight.md`. - -#### Colapsando grupos - -Los grupos de enlaces se expanden de forma predeterminada. Puedes cambiar este comportamiento estableciendo la propiedad `collapsed` de un grupo como `true`. - -Los subgrupos generados automáticamente respetan por defecto la propiedad `collapsed` de su grupo padre. Puedes establecer la propiedad `autogenerate.collapsed` para anular esto. - -```js -sidebar: [ - // Un grupo colapsado de enlaces. - { - label: 'Collapsed Links', - collapsed: true, - items: [ - { label: 'Introduction', link: '/intro' }, - { label: 'Next Steps', link: '/next-steps' }, - ], - }, - // Un grupo expandido que contiene subgrupos generados automáticamente colapsados. - { - label: 'Reference', - autogenerate: { - directory: 'reference', - collapsed: true, - }, - }, -], -``` - -#### Traduciendo etiquetas - -Si tu sitio es multilingüe, se considera que la etiqueta de cada elemento está en el idioma predeterminado. Puedes establecer una propiedad de `translations` para proporcionar etiquetas en los otros idiomas que tu sitio admita: - -```js -sidebar: [ - // Un ejemplo de barra lateral con etiquetas traducidas al francés. - { - label: 'Start Here', - translations: { fr: 'Commencez ici' }, - items: [ - { - label: 'Getting Started', - translations: { fr: 'Bien démarrer' }, - link: '/getting-started', - }, - { - label: 'Project Structure', - translations: { fr: 'Structure du projet' }, - link: '/structure', - }, - ], - }, -], -``` - -#### `SidebarItem` - -```ts -type SidebarItem = { - label: string; - translations?: Record<string, string>; -} & ( - | { - link: string; - badge?: string | BadgeConfig; - } - | { items: SidebarItem[]; collapsed?: boolean } - | { - autogenerate: { directory: string; collapsed?: boolean }; - collapsed?: boolean; - } -); -``` - -#### `BadgeConfig` - -```ts -interface BadgeConfig { - text: string; - variant: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; -} -``` - -### `locales` - -**tipo:** <code>{ \[dir: string\]: [LocaleConfig](#localeconfig) }</code> - -[Configura la internacionalización (i18n)](/es/guides/i18n/) para tu sitio estableciendo qué `locales` se admiten. - -Cada entrada debe usar el directorio donde se guardan los archivos de ese idioma como clave. - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'My Docs', - // Establece el inglés como el idioma predeterminado para este sitio. - defaultLocale: 'en', - locales: { - // Los documentos en inglés en `src/content/docs/en/` - en: { - label: 'English', - }, - // Los documentos en chino simplificado en `src/content/docs/zh/` - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - // Los documentos en árabe en `src/content/docs/ar/` - ar: { - label: 'العربية', - dir: 'rtl', - }, - }, - }), - ], -}); -``` - -#### `LocaleConfig` - -```ts -interface LocaleConfig { - label: string; - lang?: string; - dir?: 'ltr' | 'rtl'; -} -``` - -Puedes establecer las siguientes opciones para cada idioma: - -##### `label` (requerido) - -**tipo:** `string` - -La etiqueta para este idioma que se muestra a los usuarios, por ejemplo, en el selector de idioma. Lo más probable es que quieras que este sea el nombre del idioma como un usuario de ese idioma esperaría leerlo, por ejemplo, `"English"`, `"العربية"` o `"简体中文"`. - -##### `lang` - -**tipo:** `string` - -La etiqueta BCP-47 para este lenguaje, por ejemplo, `"en"`, `"ar"` o `"zh-CN"`. Si no se establece, se utilizará el nombre del directorio del idioma de forma predeterminada. Las etiquetas de idioma con subetiquetas regionales (por ejemplo, `"pt-BR"` o `"en-US"`) utilizarán las traducciones de la interfaz de usuario integradas para su idioma base si no se encuentran traducciones específicas de la región. - -##### `dir` - -**tipo:** `'ltr' | 'rtl'` - -La dirección de escritura de este idioma; `"ltr"` para de izquierda a derecha (el valor predeterminado) o `"rtl"` para de derecha a izquierda. - -#### Idioma raíz - -Puedes servir el idioma predeterminado sin un directorio `/lang/` estableciendo un idioma `root`: - -```js -starlight({ - locales: { - root: { - label: 'English', - lang: 'en', - }, - fr: { - label: 'Français', - }, - }, -}); -``` - -Por ejemplo, esto te permite servir `/getting-started/` como una ruta en inglés y usar `/fr/getting-started/` como la página francesa equivalente. - -### `defaultLocale` - -**tipo:** `string` - -Establece el idioma que es el predeterminado para este sitio. -Este valor debe coincidir con una de las claves de tu objeto [`locales`](#locales). -(Si tu idioma predeterminado es tu [idioma raíz](#idioma-raíz), puedes omitir esto.) - -El idioma predeterminado se utilizará para proporcionar contenido de respaldo donde faltan las traducciones. - -### `social` - -**tipo:** `Partial<Record<'bitbucket' | 'codeberg' | 'codePen' | 'discord' | 'github' | 'gitlab' | 'gitter' | 'instagram' | 'linkedin' | 'mastodon' | 'microsoftTeams' | 'stackOverflow' | 'threads' | 'twitch' | 'twitter' | 'youtube', string>>` - -Detalles opcionales sobre las cuentas de redes sociales para este sitio. Agregar cualquiera de estos los mostrará como enlaces de iconos en el encabezado del sitio. - -```js -starlight({ - social: { - codeberg: 'https://codeberg.org/knut/examples', - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - linkedin: 'https://www.linkedin.com/company/astroinc', - mastodon: 'https://m.webtoo.ls/@astro', - threads: 'https://www.threads.net/@nmoodev', - twitch: 'https://www.twitch.tv/bholmesdev', - twitter: 'https://twitter.com/astrodotbuild', - youtube: 'https://youtube.com/@astrodotbuild', - }, -}); -``` - -### `customCss` - -**tipo:** `string[]` - -Proporciona archivos CSS para personalizar el aspecto y la sensación de tu sitio Starlight. - -Admite archivos CSS locales relativos a la raíz de tu proyecto, por ejemplo, `'./src/custom.css'`, y CSS que instalaste como un módulo npm, por ejemplo, `'@fontsource/roboto'`. - -```js -starlight({ - customCss: ['./src/custom-styles.css', '@fontsource/roboto'], -}); -``` - -### `head` - -**tipo:** [`HeadConfig[]`](#headconfig) - -Agrega etiquetas personalizadas a la etiqueta `<head>` de tu sitio Starlight. -Puede ser útil para agregar análisis y otros scripts y recursos de terceros. - -```js -starlight({ - head: [ - // Ejemplo: agregar etiqueta de script de análisis de Fathom. - { - tag: 'script', - attrs: { - src: 'https://cdn.usefathom.com/script.js', - 'data-site': 'MY-FATHOM-ID', - defer: true, - }, - }, - ], -}); -``` - -#### `HeadConfig` - -```ts -interface HeadConfig { - tag: string; - attrs?: Record<string, string | boolean | undefined>; - content?: string; -} -``` - -### `lastUpdated` - -**type:** `boolean` -**default:** `false` - -Controla si se muestra el pie de página que indica cuándo se actualizó por última vez la página. - -De forma predeterminada, esta función se basa en el historial Git de tu repositorio y puede no ser precisa en algunas plataformas de implementación que realizan [copias superficiales](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt). Una página puede anular esta configuración o la fecha basada en Git utilizando el campo [`lastUpdated`](/reference/frontmatter/#lastupdated) en el frontmatter. - -### `pagination` - -**tipo:** `boolean` -**por defecto:** `true` - -Define si el pie de página debe incluir enlaces a la página anterior y siguiente. - -Una página puede anular esta configuración o el texto del enlace y/o la URL utilizando los campos de metadatos [`prev`](/reference/frontmatter/#prev) y [`next`](/reference/frontmatter/#next). - -### `favicon` - -**tipo:** `string` -**por defecto:** `'/favicon.svg'` - -Establece la ruta del favicon predeterminado para tu sitio web, el cual debería ubicarse en el directorio `public/` y ser un archivo de icono válido (`.ico`, `.gif`, `.jpg`, `.png` o `.svg`). - -```js -starlight({ - favicon: '/images/favicon.svg', -}), -``` - -Si necesitas establecer variantes adicionales o favicons de respaldo, puedes agregar etiquetas utilizando la opción [`head`](#head): - -```js -starlight({ - favicon: '/images/favicon.svg'. - head: [ - // Agregar un favicon ICO de respaldo para Safari. - { - tag: 'link', - attrs: { - rel: 'icon', - href:'/images/favicon.ico', - sizes: '32x32', - }, - }, - ], -}); -``` diff --git a/docs/src/content/docs/es/reference/configuration.mdx b/docs/src/content/docs/es/reference/configuration.mdx new file mode 100644 index 00000000000..1e000e643cc --- /dev/null +++ b/docs/src/content/docs/es/reference/configuration.mdx @@ -0,0 +1,614 @@ +--- +title: Referencia de Configuración +description: Una descripción general de todas las opciones de configuración que admite Starlight. +--- + +## Configurar la integración `starlight` + +Starlight es una integración construida sobre el framework [Astro](https://astro.build). Puedes configurar tu proyecto dentro del archivo de configuración `astro.config.mjs`: + +```js +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; +export default defineConfig({ + integrations: [ + starlight({ + title: 'Mi encantador sitio de documentación', + }), + ], +}); +``` + +Puedes pasar las siguientes opciones a la integración `starlight`. + +### `title` (requerido) + +**tipo:** `string | Record<string, string>` + +Establece el título de tu sitio web. Se utilizará en los metadatos y en el título de la pestaña del navegador. + +El valor puede ser un string o para sitios multilingües, un objeto con valores para cada idioma diferente. +Cuando se usa la forma de objeto, las claves deben ser etiquetas BCP-47 (por ejemplo, `en`, `ar` o `zh-CN`): + +```ts +starlight({ + title: { + es: 'Mi encantador sitio de documentación', + de: 'Meine bezaubernde Dokumentationsseite', + }, +}); +``` + +### `description` + +**tipo:** `string` + +Establece la descripción de tu sitio web. Es usada en los metadatos compartidos con los motores de búsqueda en la etiqueta `<meta name="description">` si no se establece `description` en el frontmatter de una página. + +### `logo` + +**tipo:** [`LogoConfig`](#logoconfig) + +Establece un logotipo para mostrarlo en la barra de navegación junto al título del sitio o en su lugar. Puedes establecer una única propiedad `src` o establecer fuentes de imagen separadas para `light` y `dark`. + +```js +starlight({ + logo: { + src: './src/assets/mi-logo.svg', + }, +}); +``` + +#### `LogoConfig` + +```ts +type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( + | { src: string } + | { light: string; dark: string } +); +``` + +### `tableOfContents` + +**tipo:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` +**por defecto:** `{ minHeadingLevel: 2; maxHeadingLevel: 3; }` + +Configura la tabla de contenidos que se muestra a la derecha de cada página. De forma predeterminada, los encabezados `<h2>` y `<h3>` se incluirán en esta tabla de contenidos. + +### `editLink` + +**tipo:** `{ baseUrl: string }` + +Hablita "Editar los enlaces" de está página estableciendo la URL base que se debe usar. El enlace final será `editLink.baseUrl` + la ruta de la página actual. Por ejemplo, para habilitar la edición de páginas en el repositorio `withastro/starlight` en GitHub: + +```js +starlight({ + editLink: { + baseUrl: 'https://github.com/withastro/starlight/edit/main/', + }, +}); +``` + +Con esta configuración, una página `/introduction` tendría un enlace de edición que apunta a `https://github.com/withastro/starlight/edit/main/src/content/docs/introduction.md`. + +### `sidebar` + +**tipo:** [`SidebarItem[]`](#sidebaritem) + +Configura los elementos de navegación de la barra lateral de tu sitio. + +Una barra lateral es un conjunto de enlaces y grupos de enlaces. +Con la excepción de los elementos que usan `slug`, cada elemento debe tener una `label` y una de las siguientes propiedades: + +- `link` — Un solo enlace a una URL específica, p. ej. `'/home'` o `'https://example.com'`. + +- `slug` — una referencia a una página interna, p. ej. `'guides/getting-started'`. + +- `items` — Un array que contiene más enlaces de la barra lateral y subgrupos. + +- `autogenerate` — Un objeto que especifica un directorio de tus documentos para generar automáticamente un grupo de enlaces. + +Los enlaces internos también se pueden especificar como una cadena en lugar de un objeto con una propiedad `slug`. + +```js +starlight({ + sidebar: [ + // Un solo elemento de enlace etiquetado como “Home”. + { label: 'Home', link: '/' }, + // Un grupo etiquetado como "Start Here" que contiene cuatro enlaces. + { + label: 'Start Here', + items: [ + // Usando `slug` para enlaces internos. + { slug: 'intro' }, + { slug: 'installation' }, + // O usando la forma abreviada para enlaces internos. + 'tutorial', + 'next-steps', + ], + }, + // Un grupo que enlaza a todas las páginas del directorio de referencia. + { + label: 'Reference', + autogenerate: { + directory: 'reference', + }, + }, + ], +}); +``` + +#### Ordenación + +Los grupos de la barra lateral generados automáticamente se ordenan alfabéticamente por el nombre del archivo. +Por ejemplo, una página generada a partir de `astro.md` aparecería por encima de la página `starlight.md`. + +#### Colapsando grupos + +Los grupos de enlaces se expanden de forma predeterminada. Puedes cambiar este comportamiento estableciendo la propiedad `collapsed` de un grupo como `true`. + +Los subgrupos generados automáticamente respetan por defecto la propiedad `collapsed` de su grupo padre. Puedes establecer la propiedad `autogenerate.collapsed` para anular esto. + +```js {5,13} +sidebar: [ + // Un grupo colapsado de enlaces. + { + label: 'Collapsed Links', + collapsed: true, + items: ['intro', 'next-steps'], + }, + // Un grupo expandido que contiene subgrupos generados automáticamente colapsados. + { + label: 'Reference', + autogenerate: { + directory: 'reference', + collapsed: true, + }, + }, +], +``` + +#### Traduciendo etiquetas + +Si tu sitio es multilingüe, se considera que la etiqueta de cada elemento está en el idioma predeterminado. Puedes establecer una propiedad de `translations` para proporcionar etiquetas en los otros idiomas que tu sitio admita: + +```js {5,9,14} +sidebar: [ + // Un ejemplo de barra lateral con etiquetas traducidas al portugués de Brasil. + { + label: 'Start Here', + translations: { 'pt-BR': 'Comece Aqui' }, + items: [ + { + label: 'Getting Started', + translations: { 'pt-BR': 'Introdução' }, + link: '/getting-started', + }, + { + label: 'Project Structure', + translations: { 'pt-BR': 'Estrutura de Projetos' }, + link: '/structure', + }, + ], + }, +], +``` + +#### `SidebarItem` + +```ts +type SidebarItem = + | string + | ({ + translations?: Record<string, string>; + badge?: string | BadgeConfig; + } & ( + | { + // Enlace + link: string; + label: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // Enlace interno + slug: string; + label?: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // Grupo de enlaces + label: string; + items: SidebarItem[]; + collapsed?: boolean; + } + | { + // Grupo de enlaces autogenerado + label: string; + autogenerate: { directory: string; collapsed?: boolean }; + collapsed?: boolean; + } + )); +``` + +#### `BadgeConfig` + +```ts +interface BadgeConfig { + text: string; + variant?: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; + class?: string; +} +``` + +### `locales` + +**tipo:** <code>\{ \[dir: string\]: [LocaleConfig](#localeconfig) \}</code> + +[Configura la internacionalización (i18n)](/es/guides/i18n/) para tu sitio estableciendo qué `locales` se admiten. + +Cada entrada debe usar el directorio donde se guardan los archivos de ese idioma como clave. + +```js +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'My Docs', + // Establece el inglés como el idioma predeterminado para este sitio. + defaultLocale: 'en', + locales: { + // Los documentos en inglés en `src/content/docs/en/` + en: { + label: 'English', + }, + // Los documentos en chino simplificado en `src/content/docs/zh-cn/` + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + // Los documentos en árabe en `src/content/docs/ar/` + ar: { + label: 'العربية', + dir: 'rtl', + }, + }, + }), + ], +}); +``` + +#### `LocaleConfig` + +```ts +interface LocaleConfig { + label: string; + lang?: string; + dir?: 'ltr' | 'rtl'; +} +``` + +Puedes establecer las siguientes opciones para cada idioma: + +##### `label` (requerido) + +**tipo:** `string` + +La etiqueta para este idioma que se muestra a los usuarios, por ejemplo, en el selector de idioma. Lo más probable es que quieras que este sea el nombre del idioma como un usuario de ese idioma esperaría leerlo, por ejemplo, `"English"`, `"العربية"` o `"简体中文"`. + +##### `lang` + +**tipo:** `string` + +La etiqueta BCP-47 para este lenguaje, por ejemplo, `"en"`, `"ar"` o `"zh-CN"`. Si no se establece, se utilizará el nombre del directorio del idioma de forma predeterminada. Las etiquetas de idioma con subetiquetas regionales (por ejemplo, `"pt-BR"` o `"en-US"`) utilizarán las traducciones de la interfaz de usuario integradas para su idioma base si no se encuentran traducciones específicas de la región. + +##### `dir` + +**tipo:** `'ltr' | 'rtl'` + +La dirección de escritura de este idioma; `"ltr"` para de izquierda a derecha (el valor predeterminado) o `"rtl"` para de derecha a izquierda. + +#### Idioma raíz + +Puedes servir el idioma predeterminado sin un directorio `/lang/` estableciendo un idioma `root`: + +```js {3-6} +starlight({ + locales: { + root: { + label: 'English', + lang: 'en', + }, + fr: { + label: 'Français', + }, + }, +}); +``` + +Por ejemplo, esto te permite servir `/getting-started/` como una ruta en inglés y usar `/fr/getting-started/` como la página francesa equivalente. + +### `defaultLocale` + +**tipo:** `string` + +Establece el idioma que es el predeterminado para este sitio. +Este valor debe coincidir con una de las claves de tu objeto [`locales`](#locales). +(Si tu idioma predeterminado es tu [idioma raíz](#idioma-raíz), puedes omitir esto.) + +El idioma predeterminado se utilizará para proporcionar contenido de respaldo donde faltan las traducciones. + +### `social` + +import SocialLinksType from '~/components/social-links-type.astro'; + +**tipo:** <SocialLinksType /> + +Detalles opcionales sobre las cuentas de redes sociales para este sitio. Agregar cualquiera de estos los mostrará como enlaces de iconos en el encabezado del sitio. + +```js +starlight({ + social: { + codeberg: 'https://codeberg.org/knut/examples', + discord: 'https://astro.build/chat', + github: 'https://github.com/withastro/starlight', + linkedin: 'https://www.linkedin.com/company/astroinc', + mastodon: 'https://m.webtoo.ls/@astro', + threads: 'https://www.threads.net/@nmoodev', + twitch: 'https://www.twitch.tv/bholmesdev', + twitter: 'https://twitter.com/astrodotbuild', + 'x.com': 'https://x.com/astrodotbuild', + youtube: 'https://youtube.com/@astrodotbuild', + }, +}); +``` + +### `customCss` + +**tipo:** `string[]` + +Proporciona archivos CSS para personalizar el aspecto y la sensación de tu sitio Starlight. + +Admite archivos CSS locales relativos a la raíz de tu proyecto, por ejemplo, `'./src/custom.css'`, y CSS que instalaste como un módulo npm, por ejemplo, `'@fontsource/roboto'`. + +```js +starlight({ + customCss: ['./src/custom-styles.css', '@fontsource/roboto'], +}); +``` + +### `expressiveCode` + +**tipo:** `StarlightExpressiveCodeOptions | boolean` +**por defecto:** `true` + +Starlight usa [Expressive Code](https://github.com/expressive-code/expressive-code/tree/main/packages/astro-expressive-code) para renderizar bloques de código y agregar soporte para resaltar partes de ejemplos de código, agregar nombres de archivo a bloques de código y más. +Consulta la [guía de “Bloques de código”](/es/guides/authoring-content/#bloques-de-código) para aprender a usar la sintaxis de Expressive Code en tu contenido Markdown y MDX. + +Puedes usar cualquier de las [opciones de configuración estándar de Expressive Code](https://github.com/expressive-code/expressive-code/blob/main/packages/astro-expressive-code/README.md#configuration) así como algunas propiedades específicas de Starlight, estableciéndolas en la opción `expressiveCode` de Starlight. +Por ejemplo, establece la opción `styleOverrides` de Expressive Code para anular el CSS predeterminado. Esto permite personalizaciones como darle a tus bloques de código esquinas redondeadas: + +```js ins={2-4} +starlight({ + expressiveCode: { + styleOverrides: { borderRadius: '0.5rem' }, + }, +}); +``` + +Si quieres deshabilitar Expressive Code, establece `expressiveCode: false` en tu configuración de Starlight: + +```js ins={2} +starlight({ + expressiveCode: false, +}); +``` + +Adicionalmente a las opciones estándar de Expressive Code, también puedes establecer las siguientes propiedades específicas de Starlight en tu configuración `expressiveCode` para personalizar aún más el comportamiento del tema para tus bloques de código: + +#### `themes` + +**tipo:** `Array<string | ThemeObject | ExpressiveCodeTheme>` +**por defecto:** `['starlight-dark', 'starlight-light']` + +Establece los temas utilizados para dar estilo a los bloques de código. +Consulta la [documentación de temas de Expressive Code](https://github.com/expressive-code/expressive-code/blob/main/packages/astro-expressive-code/README.md#themes) para obtener detalles de los formatos de tema admitidos. + +Starlight usa por defecto las variantes oscura y clara del [tema Night Owl](https://github.com/sdras/night-owl-vscode-theme) de Sarah Drasner. + +Si proporcionas por lo menos un tema oscuro y uno claro, Starlight mantendrá automáticamente el tema de bloque de código activo sincronizado con el tema actual del sitio. +Configura este comportamiento con la opción [`useStarlightDarkModeSwitch`](#usestarlightdarkmodeswitch). + +#### `useStarlightDarkModeSwitch` + +**tipo:** `boolean` +**por defecto:** `true` + +Cuando sea `true`, los bloques de código cambian automáticamente entre temas claros y oscuros cuando cambia el tema del sitio. +Cuando sea `false`, debes agregar manualmente CSS para manejar el cambio entre múltiples temas. + +:::note +Cuando estableces `themes`, debes proporcionar por lo menos un tema oscuro y uno claro para que el interruptor de modo oscuro de Starlight funcione. +::: + +#### `useStarlightUiThemeColors` + +**tipo:** `boolean` +**por defecto:** `true` si `themes` no está establecido, de lo contrario `false` + +Cuando sea `true`, se utilizan las variables CSS de Starlight para los colores de los elementos de la UI del bloque de código (fondos, botones, sombras, etc.), coincidiendo con el [tema de color del sitio](/es/guides/css-and-tailwind/#temas). +Cuando sea `false`, se utilizan los colores proporcionados por el tema de resaltado de sintaxis activo para estos elementos. + +:::note +Cuando usas temas personalizados y estableces esto en `true`, debes proporcionar por lo menos un tema oscuro y uno claro para asegurar un contraste de color adecuado. +::: + +### `pagefind` + +**tipo:** `boolean` +**por defecto:** `true` + +Define si el proveedor de búsqueda predeterminado de Starlight [Pagefind](https://pagefind.app/) está habilitado. + +Establece esta opción a `false` para excluir una página de los resultados de búsqueda. +Esto también ocultará la interfaz de usuario de búsqueda predeterminada si está en uso. + +Pagefind no puede estar habilitado cuando la opción [`prerender`](#prerender) está establecida en `false`. + +### `prerender` + +**tipo:** `boolean` +**por defecto:** `true` + +Define si las páginas de Starlight deben ser pre-renderizadas a HTML estático o renderizadas bajo demanda por un [adaptador SSR](https://docs.astro.build/es/guides/server-side-rendering/). + +Las páginas de Starlight se pre-renderizan de forma predeterminada. +Si estás usando un adaptador SSR y deseas renderizar las páginas de Starlight bajo demanda, establece `prerender: false`. + +### `head` + +**tipo:** [`HeadConfig[]`](#headconfig) + +Agrega etiquetas personalizadas a la etiqueta `<head>` de tu sitio Starlight. +Puede ser útil para agregar análisis y otros scripts y recursos de terceros. + +```js +starlight({ + head: [ + // Ejemplo: agregar etiqueta de script de análisis de Fathom. + { + tag: 'script', + attrs: { + src: 'https://cdn.usefathom.com/script.js', + 'data-site': 'MY-FATHOM-ID', + defer: true, + }, + }, + ], +}); +``` + +Las entradas en el `head` son convertidas directamente a elementos HTML y no pasan por el [procesamiento de script](https://docs.astro.build/es/guides/client-side-scripts/#procesamiento-de-scripts) o [estilo](https://docs.astro.build/es/guides/styling/#estilando-en-astro) de Astro. +Si necesitas importar activos locales como scripts, estilos o imágenes, [anula el componente Head](/es/guides/overriding-components/#reusa-un-componente-integrado). + +#### `HeadConfig` + +```ts +interface HeadConfig { + tag: string; + attrs?: Record<string, string | boolean | undefined>; + content?: string; +} +``` + +### `lastUpdated` + +**type:** `boolean` +**default:** `false` + +Controla si se muestra el pie de página que indica cuándo se actualizó por última vez la página. + +De forma predeterminada, esta función se basa en el historial Git de tu repositorio y puede no ser precisa en algunas plataformas de implementación que realizan [copias superficiales](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt). Una página puede anular esta configuración o la fecha basada en Git utilizando el campo [`lastUpdated`](/es/reference/frontmatter/#lastupdated) en el frontmatter. + +### `pagination` + +**tipo:** `boolean` +**por defecto:** `true` + +Define si el pie de página debe incluir enlaces a la página anterior y siguiente. + +Una página puede anular esta configuración o el texto del enlace y/o la URL utilizando los campos de metadatos [`prev`](/es/reference/frontmatter/#prev) y [`next`](/es/reference/frontmatter/#next). + +### `favicon` + +**tipo:** `string` +**por defecto:** `'/favicon.svg'` + +Establece la ruta del favicon predeterminado para tu sitio web, el cual debería ubicarse en el directorio `public/` y ser un archivo de icono válido (`.ico`, `.gif`, `.jpg`, `.png` o `.svg`). + +```js +starlight({ + favicon: '/images/favicon.svg', +}), +``` + +Si necesitas establecer variantes adicionales o favicons de respaldo, puedes agregar etiquetas utilizando la opción [`head`](#head): + +```js +starlight({ + favicon: '/images/favicon.svg', + head: [ + // Agregar un favicon ICO de respaldo para Safari. + { + tag: 'link', + attrs: { + rel: 'icon', + href: '/images/favicon.ico', + sizes: '32x32', + }, + }, + ], +}); +``` + +### `titleDelimiter` + +**tipo:** `string` +**por defecto:** `'|'` + +Establece un delimitador entre el título de la página y el título del sitio web en la etiqueta `<title>`, que se muestra en las pestañas del navegador. + +Por defecto, cada página tiene un `<title>` de `Título de la página | Título del sitio web`. +Por ejemplo, esta página es titulada "Referencia de Configuración" y este sitio web es titulado "Starlight", por lo que el `<title>` de esta página es "Referencia de Configuración | Starlight". + +### `disable404Route` + +**tipo:** `boolean` +**por defecto:** `false` + +Deshabilita la inyección de la [página 404](https://docs.astro.build/es/core-concepts/astro-pages/#página-de-error-404-personalizada) predeterminada de Starlight. Para usar una ruta `src/pages/404.astro` personalizada en tu proyecto, establece esta opción en `true`. + +### `components` + +**tipo:** `Record<string, string>` + +Proporciona las rutas a los componentes para sobreescribir las implementaciones predeterminadas de Starlight. + +```js +starlight({ + components: { + SocialLinks: './src/components/MySocialLinks.astro', + }, +}); +``` + +Consulta la [Referencia de Personalización de Componentes](/es/reference/overrides/) para obtener detalles de todos los componentes que puedes anular. + +### `plugins` + +**tipo:** [`StarlightPlugin[]`](/es/reference/plugins/#referencia-rápida-de-la-api) + +Extiende Starlight con plugins personalizados. +Los plugins aplican cambios a tu proyecto para modificar o agregar a las funcionalidades a Starlight. + +Visita la [exhibición de plugins](/es/resources/plugins/#plugins) para ver una lista de los plugins disponibles. + +```js +starlight({ + plugins: [starlightPlugin()], +}); +``` + +Consulta la [Referencia de Plugins](/es/reference/plugins/) para obtener detalles sobre cómo crear tus propios plugins. + +### `credits` + +Habilita la visualización de un enlace “Hecho con Starlight” en el pie de página de tu sitio. + +```js +starlight({ + credits: true, +}); +``` diff --git a/docs/src/content/docs/es/reference/frontmatter.md b/docs/src/content/docs/es/reference/frontmatter.md index d80f99bd6da..ee1dc616887 100644 --- a/docs/src/content/docs/es/reference/frontmatter.md +++ b/docs/src/content/docs/es/reference/frontmatter.md @@ -5,8 +5,9 @@ description: Una visión general de los campos de frontmatter predeterminados qu Puedes personalizar individualmente las páginas Markdown y MDX en Starlight estableciendo valores en su frontmatter. Por ejemplo, una página regular podría establecer los campos `title` y `description`: -```md +```md {3-4} --- +# src/content/docs/example.md title: Acerca de este proyecto description: Aprende más sobre el proyecto en el que estoy trabajando. --- @@ -28,20 +29,27 @@ Debes proporcionar un título para cada página. Este se mostrará en la parte s La descripción de la página es usada para los metadatos de la página y será recogida por los motores de búsqueda y en las vistas previas de las redes sociales. +### `slug` + +**tipo**: `string` + +Sobreescribe el slug de la página. Consulta [“Definiendo slugs personalizados”](https://docs.astro.build/es/guides/content-collections/#definiendo-slugs-personalizados) en la documentación de Astro para más detalles. + ### `editUrl` **tipo:** `string | boolean` -Reemplaza la [configuración global `editLink`](/reference/configuration/#editlink). Establece a `false` para deshabilitar el enlace "Editar página" para una página específica o proporciona una URL alternativa donde el contenido de esta página es editable. +Reemplaza la [configuración global `editLink`](/es/reference/configuration/#editlink). Establece a `false` para deshabilitar el enlace "Editar página" para una página específica o proporciona una URL alternativa donde el contenido de esta página es editable. ### `head` -**tipo:** [`HeadConfig[]`](/reference/configuration/#headconfig) +**tipo:** [`HeadConfig[]`](/es/reference/configuration/#headconfig) -Puedes agregar etiquetas adicionales a la etiqueta `<head>` de tu página usando el campo `head` del frontmatter. Esto significa que puedes agregar estilos personalizados, metadatos u otras etiquetas a una sola página. Similar a la [opción global `head`](/reference/configuration/#head). +Puedes agregar etiquetas adicionales a la etiqueta `<head>` de tu página usando el campo `head` del frontmatter. Esto significa que puedes agregar estilos personalizados, metadatos u otras etiquetas a una sola página. Similar a la [opción global `head`](/es/reference/configuration/#head). ```md --- +# src/content/docs/example.md title: Acerca de nosotros head: # Usa una etiqueta <title> personalizada @@ -54,11 +62,12 @@ head: **tipo:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` -Reemplaza la [configuración global `tableOfContents`](/reference/configuration/#tableofcontents). +Reemplaza la [configuración global `tableOfContents`](/es/reference/configuration/#tableofcontents). Personaliza los niveles de encabezado que se incluirán o establece en `false` para ocultar la tabla de contenidos en esta página. ```md --- +# src/content/docs/example.md title: Página con solo encabezados H2 en la tabla de contenidos tableOfContents: minHeadingLevel: 2 @@ -68,6 +77,7 @@ tableOfContents: ```md --- +# src/content/docs/example.md title: Página sin tabla de contenidos tableOfContents: false --- @@ -92,6 +102,7 @@ Por ejemplo, esta configuración muestra algunas opciones comunes, incluyendo la ```md --- +# src/content/docs/example.md title: Mi página de inicio template: splash hero: @@ -104,10 +115,25 @@ hero: - text: Cuéntame más link: /getting-started/ icon: right-arrow - variant: primary - text: View on GitHub link: https://github.com/astronaut/my-project icon: external + variant: minimal + attrs: + rel: me +--- +``` + +Puedes mostrar diferentes versiones de la imagen hero en los modos claro y oscuro. + +```md +--- +# src/content/docs/example.md +hero: + image: + alt: Un logotipo brillante, de colores brillantes + dark: ../../assets/logo-dark.png + light: ../../assets/logo-light.png --- ``` @@ -117,19 +143,32 @@ hero: interface HeroConfig { title?: string; tagline?: string; - image?: { - alt?: string; - // Ruta relativa a una imagen en tu repositorio. - file?: string; - // HTML crudo para usar en el espacio de la imagen. - // Podría ser una etiqueta `<img>` personalizada o un `<svg>` en línea. - html?: string; - }; + image?: + | { + // Ruta relativa a una imagen en tu repositorio. + file: string; + // Texto alternativo para hacer que la imagen sea accesible a la tecnología de asistencia + alt?: string; + } + | { + // Ruta relativa a una imagen en tu repositorio para usar en el modo oscuro. + dark: string; + // Ruta relativa a una imagen en tu repositorio para usar en el modo claro. + light: string; + // Texto alternativo para hacer que la imagen sea accesible a la tecnología de asistencia + alt?: string; + } + | { + // HTML crudo para usar en el espacio de la imagen. + // Podría ser una etiqueta `<img>` personalizada o un `<svg>` en línea. + html: string; + }; actions?: Array<{ text: string; link: string; - variant: 'primary' | 'secondary' | 'minimal'; - icon: string; + variant?: 'primary' | 'secondary' | 'minimal'; + icon?: string; + attrs?: Record<string, string | number | boolean>; }>; } ``` @@ -145,6 +184,7 @@ Por ejemplo, esta página muestra un banner que incluye un enlace a `example.com ```md --- +# src/content/docs/example.md title: Página con un banner banner: content: | @@ -157,10 +197,11 @@ banner: **type:** `Date | boolean` -Sobrescribe la [opción global `lastUpdated`](/reference/configuration/#lastupdated). Si se especifica una fecha, debe ser una [marca de tiempo YAML](https://yaml.org/type/timestamp.html) válida y sobrescribirá la fecha almacenada en el historial de Git para esta página. +Sobrescribe la [opción global `lastUpdated`](/es/reference/configuration/#lastupdated). Si se especifica una fecha, debe ser una [marca de tiempo YAML](https://yaml.org/type/timestamp.html) válida y sobrescribirá la fecha almacenada en el historial de Git para esta página. ```md --- +# src/content/docs/example.md title: Página con una fecha de última actualización personalizada lastUpdated: 2022-08-09 --- @@ -170,10 +211,11 @@ lastUpdated: 2022-08-09 **tipo:** `boolean | string | { link?: string; label?: string }` -Anula la [opción global de `pagination`](/reference/configuration/#pagination). Si se especifica un string, el texto del enlace generado se reemplazará, y si se especifica un objeto, tanto el enlace como el texto serán anulados. +Anula la [opción global de `pagination`](/es/reference/configuration/#pagination). Si se especifica un string, el texto del enlace generado se reemplazará, y si se especifica un objeto, tanto el enlace como el texto serán anulados. ```md --- +# src/content/docs/example.md # Ocultar el enlace de la página anterior prev: false --- @@ -181,6 +223,7 @@ prev: false ```md --- +# src/content/docs/example.md # Sobrescribir el texto del enlace de la página anterior prev: Continuar con el tutorial --- @@ -188,6 +231,7 @@ prev: Continuar con el tutorial ```md --- +# src/content/docs/example.md # Sobrescribir tanto el enlace de la página anterior como el texto prev: link: /página-no-relacionada/ @@ -204,6 +248,8 @@ Lo mismo que [`prev`](#prev), pero para el enlace de la página siguiente. ```md --- +# src/content/docs/example.md + # Ocultar el enlace de la página siguiente next: false @@ -218,16 +264,44 @@ Establece si esta página debe incluirse en el índice de búsqueda de [Pagefind ```md --- +# src/content/docs/example.md # Ocultar esta página del índice de búsqueda pagefind: false --- ``` +### `draft` + +**tipo:** `boolean` +**por defecto:** `false` + +Establece si esta página debe considerarse como un borrador y no incluirse en las [compilaciones de producción](https://docs.astro.build/es/reference/cli-reference/#astro-build) y [grupos de enlaces autogenerados](/es/guides/sidebar/#grupos-autogenerados). Establece en `true` para marcar una página como borrador y hacerla visible solo durante el desarrollo. + +```md +--- +# src/content/docs/example.md +# Excluye esta página de las compilaciones de producción +draft: true +--- +``` + ### `sidebar` -**tipo:** `{ label?: string; order?: number; hidden?: boolean; badge?: string | BadgeConfig }` +**tipo:** [`SidebarConfig`](#sidebarconfig) -Controla cómo se muestra esta página en el [sidebar](/reference/configuration/#sidebar) al utilizar un grupo de enlaces generado automáticamente. +Controla cómo se muestra esta página en el [sidebar](/es/reference/configuration/#sidebar) al utilizar un grupo de enlaces generado automáticamente. + +#### `SidebarConfig` + +```ts +interface SidebarConfig { + label?: string; + order?: number; + hidden?: boolean; + badge?: string | BadgeConfig; + attrs?: Record<string, string | number | boolean | undefined>; +} +``` #### `label` @@ -238,6 +312,7 @@ Establece la etiqueta para esta página en la barra lateral cuando se muestra en ```md --- +# src/content/docs/example.md title: Acerca de este proyecto sidebar: label: Acerca de @@ -253,6 +328,7 @@ Los números más bajos se muestran más arriba en el grupo de enlaces. ```md --- +# src/content/docs/example.md title: Página para mostrar primero sidebar: order: 1 @@ -268,6 +344,7 @@ Previene que esta página se incluya en un grupo de enlaces generado automática ```md --- +# src/content/docs/example.md title: Página para ocultar de la barra lateral autogenerada sidebar: hidden: true @@ -280,10 +357,11 @@ sidebar: Agrega una insignia a la página en la barra lateral cuando se muestra en un grupo de enlaces generado automáticamente. Cuando se usa un string, la insignia se mostrará con el color de acento predeterminado. -Opcionalmente, pasa un objeto [`BadgeConfig`](/es/reference/configuration/#badgeconfig) con los campos `text` y `variant` para personalizar la insignia. +Opcionalmente, pasa un objeto [`BadgeConfig`](/es/reference/configuration/#badgeconfig) con los campos `text`, `variant` y `class` para personalizar la insignia. ```md --- +# src/content/docs/example.md title: Página con una insignia sidebar: # Usa la variante predeterminada que coincide con el color de acento de tu sitio @@ -293,6 +371,7 @@ sidebar: ```md --- +# src/content/docs/example.md title: Página con una insignia sidebar: badge: @@ -300,3 +379,88 @@ sidebar: variant: caution --- ``` + +#### `attrs` + +**type:** `Record<string, string | number | boolean | undefined>` + +Atributos HTML para agregar al enlace de la página en la barra lateral cuando se muestra en un grupo de enlaces generado automáticamente. + +```md +--- +# src/content/docs/example.md +title: Página que se abre en una nueva pestaña +sidebar: + # Abre la página en una nueva pestaña + attrs: + target: _blank +--- +``` + +## Personaliza el esquema del frontmatter + +El esquema del frontmatter para la colección de contenido `docs` de Starlight se configura en `src/content/config.ts` usando el auxiliar `docsSchema()`: + +```ts {3,6} +// src/content/config.ts +import { defineCollection } from 'astro:content'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ schema: docsSchema() }), +}; +``` + +Aprende más sobre los esquemas de colección de contenido en [“Definir un esquema de colección”](https://docs.astro.build/es/guides/content-collections/#definiendo-un-esquema-de-colección) en la documentación de Astro. + +`docsSchema()` toma las siguientes opciones: + +### `extend` + +**tipo:** esquema Zod o función que devuelve un esquema Zod +**por defecto:** `z.object({})` + +Extiende el esquema de Starlight con campos adicionales estableciendo `extend` en las opciones de `docsSchema()`. +El valor debe ser un [esquema Zod](https://docs.astro.build/es/guides/content-collections/#definiendo-tipos-de-datos-con-zod). + +En el siguiente ejemplo, proporcionamos un tipo más estricto para `description` para hacerlo requerido y agregamos un nuevo campo opcional `category`: + +```ts {8-13} +// src/content/config.ts +import { defineCollection, z } from 'astro:content'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + schema: docsSchema({ + extend: z.object({ + // Hacer un campo integrado requerido en lugar de opcional. + description: z.string(), + // Agrega un nuevo campo al esquema. + category: z.enum(['tutorial', 'guide', 'reference']).optional(), + }), + }), + }), +}; +``` + +Para tomar ventaja del [auxiliar `image()` de Astro](https://docs.astro.build/es/guides/images/#imágenes-en-colecciones-de-contenido), usa una función que devuelva tu extensión de esquema: + +```ts {8-13} +// src/content/config.ts +import { defineCollection, z } from 'astro:content'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + schema: docsSchema({ + extend: ({ image }) => { + return z.object({ + // Agrega un campo que debe resolverse a una imagen local. + cover: image(), + }); + }, + }), + }), +}; +``` diff --git a/docs/src/content/docs/es/reference/icons.mdx b/docs/src/content/docs/es/reference/icons.mdx new file mode 100644 index 00000000000..ea106cc7936 --- /dev/null +++ b/docs/src/content/docs/es/reference/icons.mdx @@ -0,0 +1,19 @@ +--- +title: Referencia de iconos +description: Una descripción general de todos los iconos disponibles en Starlight. +--- + +Starlight proporciona un conjunto de iconos integrados que puedes mostrar en tu contenido usando el componente `<Icon>`. + +## Usar iconos + +Los iconos se pueden mostrar usando el componente [`<Icon>`](/es/components/icons/). +Estos también se utilizan a menudo en otros componentes, como [tarjetas](/es/components/cards/) o configuraciones como [acciones de hero](/es/reference/frontmatter/#hero). + +## Todos los iconos + +Una lista de todos los iconos disponibles se muestra a continuación con sus nombres asociados. Haz clic en un icono para copiar su nombre al portapapeles. + +import IconsList from '~/components/icons-list.astro'; + +<IconsList labels={{ copied: '¡Copiado!' }} /> diff --git a/docs/src/content/docs/es/reference/overrides.md b/docs/src/content/docs/es/reference/overrides.md new file mode 100644 index 00000000000..870ccec00b3 --- /dev/null +++ b/docs/src/content/docs/es/reference/overrides.md @@ -0,0 +1,400 @@ +--- +title: Referencia de Personalización de Componentes +description: Una descripción general de los componentes y props de componentes compatibles con los reemplazos de Starlight. +tableOfContents: + maxHeadingLevel: 4 +--- + +Puedes reemplazar los componentes integrados de Starlight proporcionando rutas a los componentes en la opción de configuración [`components`](/es/reference/configuration/#components) de Starlight. + +Esta página enumera todos los componentes disponibles para reemplazar y enlaces a sus implementaciones predeterminadas en GitHub. + +Aprende más en la [Guía para Personalizar Componentes](/es/guides/overriding-components/). + +## Props de Componentes + +Todos los componentes pueden acceder a un objeto estándar `Astro.props` que contiene información sobre la página actual. + +Para escribir los tipos de tus componentes personalizados, importa el tipo `Props` de Starlight: + +```astro +--- +// src/components/Custom.astro +import type { Props } from '@astrojs/starlight/props'; + +const { hasSidebar } = Astro.props; +// ^ tipo: boolean +--- +``` + +Esto te dará autocompletado y tipos al acceder a `Astro.props`. + +### Props + +Starlight pasará las siguientes props a tus componentes personalizados. + +#### `dir` + +**Tipo:** `'ltr' | 'rtl'` + +La dirección de escritura de la página. + +#### `lang` + +**Tipo:** `string` + +Etiqueta de idioma BCP-47 para la configuración regional de esta página, por ejemplo, `en`, `zh-CN` o `pt-BR`. + +#### `locale` + +**Tipo:** `string | undefined` + +La ruta base en la que se sirve un idioma. `undefined` para los slugs de idioma raíz. + +#### `siteTitle` + +**Tipo:** `string` + +El título del sitio para el idioma de esta página. + +#### `siteTitleHref` + +**Tipo:** `string` + +El valor del atributo `href` del título del sitio, enlazando de vuelta a la página de inicio, por ejemplo `/`. +Para sitios multilingües, esto incluirá la configuración regional actual, por ejemplo, `/en/` o `/zh-cn/`. + +#### `slug` + +**Tipo:** `string` + +El slug se genera a partir del nombre de archivo de contenido. + +#### `id` + +**Tipo:** `string` + +El ID único para esta página basado en el nombre de archivo de contenido. + +#### `isFallback` + +**Tipo:** `true | undefined` + +`true` si esta página no está traducida en el idioma actual y está utilizando contenido de respaldo del idioma predeterminado. +Solo se usa en sitios multilingües. + +#### `entryMeta` + +**Tipo:** `{ dir: 'ltr' | 'rtl'; lang: string }` + +Metadatos de configuración regional para el contenido de la página. Puede ser diferente de los valores de configuración regional de nivel superior cuando una página está utilizando contenido de respaldo. + +#### `entry` + +La entrada de la colección de contenido Astro para la página actual. +Incluye los valores de frontmatter para la página actual en `entry.data`. + +```ts +entry: { + data: { + title: string; + description: string | undefined; + // etc. + } +} +``` + +Aprende más sobre la forma de este objeto en la referencia de [Tipo de Entrada de la Colección de Astro](https://docs.astro.build/es/reference/api-reference/#tipo-de-entrada-de-la-colección). + +#### `sidebar` + +**Tipo:** `SidebarEntry[]` + +Navegación de sitio entradas de barra lateral para esta página. + +#### `hasSidebar` + +**Tipo:** `boolean` + +Si la barra lateral debe mostrarse o no en esta página. + +#### `pagination` + +**Tipo:** `{ prev?: Link; next?: Link }` + +Los enlaces a la página anterior y siguiente en la barra lateral si están habilitados. + +#### `toc` + +**Tipo:** `{ minHeadingLevel: number; maxHeadingLevel: number; items: TocItem[] } | undefined` + +Tabla de contenidos para esta página si está habilitada. + +#### `headings` + +**Tipo:** `{ depth: number; slug: string; text: string }[]` + +Array de todos los encabezados Markdown extraídos de la página actual. +Usa [`toc`](#toc) en su lugar si deseas construir un componente de tabla de contenidos que respete las opciones de configuración de Starlight. + +#### `lastUpdated` + +**Tipo:** `Date | undefined` + +Objeto `Date` de JavaScript que representa cuándo se actualizó por última vez esta página si está habilitado. + +#### `editUrl` + +**Tipo:** `URL | undefined` + +Objeto `URL` para la dirección donde se puede editar esta página si está habilitado. + +--- + +## Componentes + +### Head + +Estos componentes son renderizados dentro del elemento `<head>` de cada página. +Solo deben incluir [elementos permitidos dentro de `<head>`](https://developer.mozilla.org/es/docs/Web/HTML/Element/head#see_also). + +#### `Head` + +**Componente por defecto:** [`Head.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Head.astro) + +Componente renderizado dentro del elemento `<head>` de cada página. +Incluye etiquetas importantes como `<title>` y `<meta charset="utf-8">`. + +Reemplaza este componente como último recurso. +Si es posible, prefiere la opción [`head`](/es/reference/configuration/#head) de la configuración de Starlight si es posible. + +#### `ThemeProvider` + +**Componente por defecto:** [`ThemeProvider.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeProvider.astro) + +Componente renderizado dentro de `<head>` que configura el soporte de tema claro/oscuro. +La implementación predeterminada incluye un script en línea y una `<template>` utilizada por el script en [`<ThemeSelect />`](#themeselect). + +--- + +### Accesibilidad + +#### `SkipLink` + +**Componente por defecto:** [`SkipLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SkipLink.astro) + +El componente renderizado como el primer elemento dentro de `<body>` que enlaza al contenido principal de la página para la accesibilidad. +La implementación predeterminada está oculta hasta que un usuario la enfoca al presionar la tecla de tabulación con su teclado. + +--- + +### Plantilla + +Estos componentes son responsables de la ubicación de los componentes de Starlight y de la gestión de las vistas en diferentes tamaños de pantalla. +Reemplazar estos componentes viene con una complejidad significativa. +Cuando sea posible, es preferible reemplazar un componente de nivel inferior. + +#### `PageFrame` + +**Componente por defecto:** [`PageFrame.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageFrame.astro) + +El componente plantilla que envuelve la mayor parte del contenido de la página. +La implementación predeterminada configura la plantilla header-sidebar-main e incluye slots nombrados `header` y `sidebar` con un slot predeterminado para el contenido principal. +También renderiza [`<MobileMenuToggle />`](#mobilemenutoggle) para alternar el renderizado de la navegación de la barra lateral en pantallas estrechas (móviles). + +#### `MobileMenuToggle` + +**Componente por defecto:** [`MobileMenuToggle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuToggle.astro) + +Componente renderizado dentro de [`<PageFrame>`](#pageframe) que es responsable de alternar la navegación de la barra lateral en pantallas estrechas (móviles). + +#### `TwoColumnContent` + +**Componente por defecto:** [`TwoColumnContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TwoColumnContent.astro) + +Componente plantilla que envuelve la columna de contenido principal y la barra lateral derecha (tabla de contenidos). +La implementación predeterminada maneja el cambio entre un diseño de una sola columna, en pantallas estrechas y un diseño de dos columnas en pantallas más grande. + +--- + +### Header + +Estos componentes renderizan la barra de navegación superior de Starlight. + +#### `Header` + +**Componente por defecto:** [`Header.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Header.astro) + +Componente de encabezado que se muestra en la parte superior de cada página. +La implementación predeterminada muestra [`<SiteTitle />`](#sitetitle-1), [`<Search />`](#search), [`<SocialIcons />`](#socialicons), [`<ThemeSelect />`](#themeselect) y [`<LanguageSelect />`](#languageselect). + +#### `SiteTitle` + +**Componente por defecto:** [`SiteTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SiteTitle.astro) + +Componente renderizado al comienzo del encabezado para renderizar el título de la web. +La implementación predeterminada incluye lógica para renderizar logotipos definidos en la configuración de Starlight. + +#### `Search` + +**Componente por defecto:** [`Search.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Search.astro) + +Componente utilizado para renderizar la UI de búsqueda de Starlight. +La implementación predeterminada incluye el botón en el encabezado y el código para mostrar un modal de búsqueda cuando se hace clic y cargar la UI de [Pagefind](https://pagefind.app/). + +Cuando [`pagefind`](/es/reference/configuration/#pagefind) está deshabilitado, el componente de búsqueda predeterminado no se renderizará. Sin embargo, si reemplazas `Search`, tu componente personalizado siempre se renderizará incluso si la opción de configuración `pagefind` es `false`. Esto te permite agregar una interfaz de usuario para proveedores de búsqueda alternativos cuando se deshabilita Pagefind. + +#### `SocialIcons` + +**Componente por defecto:** [`SocialIcons.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SocialIcons.astro) + +Componente renderizado en el encabezado del sitio que incluye enlaces de iconos sociales. +La implementación predeterminada utiliza la opción [`social`](/es/reference/configuration/#social) en la configuración de Starlight para renderizar iconos y enlaces. + +#### `ThemeSelect` + +**Componente por defecto:** [`ThemeSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeSelect.astro) + +Componente renderizado en el encabezado del sitio que permite a los usuarios seleccionar su esquema de color preferido. + +#### `LanguageSelect` + +**Componente por defecto:** [`LanguageSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LanguageSelect.astro) + +Componente renderizado en el encabezado del sitio que permite a los usuarios cambiar a un idioma diferente. + +--- + +### Barra lateral global + +La barra lateral global de Starlight incluye la navegación principal del sitio. +En los pantallas estrechas esto está oculto detrás de un menú desplegable. + +#### `Sidebar` + +**Componente por defecto:** [`Sidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Sidebar.astro) + +Componente renderizado antes del contenido de la página que contiene la navegación global. +La implementación predeterminada muestra una barra lateral lo suficientemente ancha y dentro de un menú desplegable en pantallas estrechas (móviles). +También renderiza [`<MobileMenuFooter />`](#mobilemenufooter) para mostrar elementos adicionales dentro del menú móvil. + +#### `MobileMenuFooter` + +**Componente por defecto:** [`MobileMenuFooter.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuFooter.astro) + +Componente renderizado en la parte inferior del menú desplegable móvil. +La implementación por defecto renderiza [`<ThemeSelect />`](#themeselect) y [`<LanguageSelect />`](#languageselect). + +--- + +### Barra lateral de la página + +La barra lateral de la página de Starlight es responsable de mostrar una tabla de contenidos que describe los subtítulos de la página actual. +En pantallas estrechas esto se colapsa en un menú desplegable fijado. + +#### `PageSidebar` + +**Componente por defecto:** [`PageSidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageSidebar.astro) + +El componente renderizado antes del contenido principal de la página para mostrar una tabla de contenidos. +La implementación renderiza [`<TableOfContents />`](#tableofcontents) y [`<MobileTableOfContents />`](#mobiletableofcontents) + +#### `TableOfContents` + +**Componente por defecto:** [`TableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TableOfContents.astro) + +Componente que renderiza la tabla de contenidos de la página actual en pantallas más anchas. + +#### `MobileTableOfContents` + +**Componente por defecto:** [`MobileTableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileTableOfContents.astro) + +Componente que renderiza la tabla de contenidos de la página actual en pantallas más estrechas (móviles). + +--- + +### Contenido + +Estos componentes se renderizan en la columna principal del contenido de la página. + +#### `Banner` + +**Componente por defecto:** [`Banner.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Banner.astro) + +Componente Banner renderizado en la parte superior de cada página. +La implementación predeterminada usa el valor de frontmatter [`banner`](/es/reference/frontmatter/#banner) de la página para decidir si renderizar o no. + +#### `ContentPanel` + +**Componente por defecto:** [`ContentPanel.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ContentPanel.astro) + +Componente plantilla utilizado para envolver secciones de la columna de contenido principal. + +#### `PageTitle` + +**Componente por defecto:** [`PageTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageTitle.astro) + +Componente que contiene el elemento `<h1>` de la página actual. + +Las implementaciones deben asegurarse de establecer `id="_top"` en el elemento `<h1>` como en la implementación predeterminada. + +#### `DraftContentNotice` + +**Componente por defecto:** [`DraftContentNotice.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/DraftContentNotice.astro) + +Aviso mostrado a los usuarios durante el desarrollo cuando la página actual está marcada como borrador. + +#### `FallbackContentNotice` + +**Componente por defecto:** [`FallbackContentNotice.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/FallbackContentNotice.astro) + +Aviso mostrado a los usuarios en páginas donde no está disponible una traducción para el idioma actual. + +Solo se usa en sitios multilingües. + +#### `Hero` + +**Componente por defecto:** [`Hero.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Hero.astro) + +Componente renderizado en la parte superior de la página cuando [`hero`](/es/reference/frontmatter/#hero) está establecido en frontmatter. +La implementación predeterminada muestra un título grande, un lema y enlaces de llamada a la acción junto con una imagen opcional. + +#### `MarkdownContent` + +**Componente por defecto:** [`MarkdownContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MarkdownContent.astro) + +Componente renderizado alrededor del contenido principal de cada página. +La implementación predeterminada configura estilos básicos para aplicar al contenido de Markdown. + +Los estilos de contenido Markdown también están expuestos en `@astrojs/starlight/style/markdown.css` y están limitados al ámbito de la clase CSS `.sl-markdown-content`. + +--- + +### Pie de página + +Estos componentes se renderizan en la parte inferior de la columna principal del contenido de la página. + +#### `Footer` + +**Componente por defecto:** [`Footer.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Footer.astro) + +Componente de pie de página que se muestra en la parte inferior de cada página. +La implementación predeterminada muestra [`<LastUpdated />`](#lastupdated), [`<Pagination />`](#pagination) y [`<EditLink />`](#editlink). + +#### `LastUpdated` + +**Componente por defecto:** [`LastUpdated.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LastUpdated.astro) + +Componente renderizado en el pie de página de la página para mostrar la fecha de la última actualización. + +#### `EditLink` + +**Componente por defecto:** [`EditLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/EditLink.astro) + +Componente renderizado en el pie de página de la página para mostrar un enlace a donde se puede editar la página. + +#### `Pagination` + +**Componente por defecto:** [`Pagination.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Pagination.astro) + +Componente renderizado en el pie de página de la página para mostrar flechas de navegación entre páginas anteriores/siguientes. diff --git a/docs/src/content/docs/es/reference/plugins.md b/docs/src/content/docs/es/reference/plugins.md new file mode 100644 index 00000000000..9be9663f69b --- /dev/null +++ b/docs/src/content/docs/es/reference/plugins.md @@ -0,0 +1,232 @@ +--- +title: Referencia de Plugins +description: Una descripción general de la API de plugins de Starlight. +tableOfContents: + maxHeadingLevel: 4 +--- + +Los plugins de Starlight pueden personalizar la configuración, la UI y el comportamiento, mientras que son fáciles de compartir y reutilizar. +Esta página de referencia documenta la API a la que tienen acceso los plugins. + +Aprende más sobre el uso de un plugin de Starlight en la [Referencia de Configuración](/es/reference/configuration/#plugins) o visita la [exhibición de plugins](/es/resources/plugins/#plugins) para ver una lista de los plugins disponibles. + +## Referencia rápida de la API + +Un plugin de Starlight tiene la siguiente forma. +Consulta a continuación los detalles de las diferentes propiedades y parámetros del hook. + +```ts +interface StarlightPlugin { + name: string; + hooks: { + setup: (options: { + config: StarlightUserConfig; + updateConfig: (newConfig: StarlightUserConfig) => void; + addIntegration: (integration: AstroIntegration) => void; + astroConfig: AstroConfig; + command: 'dev' | 'build' | 'preview'; + isRestart: boolean; + logger: AstroIntegrationLogger; + }) => void | Promise<void>; + }; +} +``` + +## `name` + +**tipo:** `string` + +Un plugin debe proporcionar un nombre único que lo describa. El nombre se utiliza cuando se [registran mensajes](#logger) relacionados con este plugin y puede ser utilizado por otros plugins para detectar la presencia de este plugin. + +## `hooks` + +Los hooks son funciones que Starlight llama para ejecutar código de plugin en momentos específicos. Actualmente, Starlight admite un único hook `setup`. + +### `hooks.setup` + +La función de configuración es llamada cuando se inicializa Starlight (durante el hook de integración [`astro:config:setup`](https://docs.astro.build/es/reference/integrations-reference/#astroconfigsetup)). + +El hook `setup` se puede utilizar para actualizar la configuración de Starlight o añadir integraciones de Astro. + +Este hook es llamado con las siguientes opciones: + +#### `config` + +**tipo:** `StarlightUserConfig` + +Una copia de lectura de la [configuración de Starlight](/es/reference/configuration/) proporcionada por el usuario. +Esta configuración puede haber sido actualizada por otros plugins configurados antes del actual. + +#### `updateConfig` + +**tipo:** `(newConfig: StarlightUserConfig) => void` + +Una función callback para actualizar la [configuración de Starlight](/es/reference/configuration/). +Proporciona las claves de configuración de nivel raíz que deseas sobreescribir. +Para actualizar los valores de configuración anidados, debes proporcionar el objeto anidado completo. + +Para extender una opción de configuración existente sin sobreescribirla, extiende el valor existente en tu nuevo valor. +En el siguiente ejemplo, se agrega una nueva cuenta en [`social`](/es/reference/configuration/#social) a la configuración existente extendiendo 'config.social' en el nuevo objeto social: + +```ts {6-11} +// plugin.ts +export default { + name: 'add-twitter-plugin', + hooks: { + setup({ config, updateConfig }) { + updateConfig({ + social: { + ...config.social, + twitter: 'https://twitter.com/astrodotbuild', + }, + }); + }, + }, +}; +``` + +#### `addIntegration` + +**tipo:** `(integration: AstroIntegration) => void` + +Una función callback para añadir una [integración de Astro](https://docs.astro.build/es/reference/integrations-reference/) requerida por el plugin. + +En el siguiente ejemplo, el plugin primero comprueba si la [integración de React de Astro](https://docs.astro.build/es/guides/integrations-guide/react/) está configurada y, si no lo está, utiliza `addIntegration()` para añadirla: + +```ts {14} "addIntegration," +// plugin.ts +import react from '@astrojs/react'; + +export default { + name: 'plugin-using-react', + hooks: { + setup({ addIntegration, astroConfig }) { + const isReactLoaded = astroConfig.integrations.find( + ({ name }) => name === '@astrojs/react' + ); + + // Solo agrega la integración de React si aún no está cargada. + if (!isReactLoaded) { + addIntegration(react()); + } + }, + }, +}; +``` + +#### `astroConfig` + +**tipo:** `AstroConfig` + +Una copia de lectura de la [configuración de Astro](https://docs.astro.build/es/reference/configuration-reference/) proporcionada por el usuario. + +#### `command` + +**tipo:** `'dev' | 'build' | 'preview'` + +El comando usado para ejecutar Starlight: + +- `dev` - El proyecto se ejecuta con `astro dev` +- `build` - El proyecto se ejecuta con `astro build` +- `preview` - El proyecto se ejecuta con `astro preview` + +#### `isRestart` + +**tipo:** `boolean` + +`false` cuando el servidor de desarrollo se inicia, `true` cuando se activa una recarga. +Common reasons for a restart include a user editing their `astro.config.mjs` while the dev server is running. + +#### `logger` + +**tipo:** `AstroIntegrationLogger` + +Una instancia del [logger de integración de Astro](https://docs.astro.build/es/reference/integrations-reference/#astrointegrationlogger) que puedes utilizar para escribir logs. +Todos los mensajes de registro se prefijarán con el nombre del plugin. + +```ts {6} +// plugin.ts +export default { + name: 'long-process-plugin', + hooks: { + setup({ logger }) { + logger.info('Empezando un proceso largo…'); + // Algun proceso largo… + }, + }, +}; +``` + +El ejemplo anterior registrará un mensaje que incluye el mensaje de información proporcionado: + +```shell +[long-process-plugin] Empezando un proceso largo… +``` + +#### `injectTranslations` + +**tipo:** `(translations: Record<string, Record<string, string>>) => void` + +Una función callback para añadir o actualizar las strings de traducción utilizadas en las [APIs de localización](/es/guides/i18n/#usar-traducciones-de-ui) de Starlight. + +En el siguiente ejemplo, un plugin inyecta traducciones para una string de UI personalizada llamada `myPlugin.doThing` para los locales `en` y `fr`: + +```ts {6-13} /(injectTranslations)[^(]/ +// plugin.ts +export default { + name: 'plugin-with-translations', + hooks: { + setup({ injectTranslations }) { + injectTranslations({ + en: { + 'myPlugin.doThing': 'Do the thing', + }, + fr: { + 'myPlugin.doThing': 'Faire le truc', + }, + }); + }, + }, +}; +``` + +Para usar las traducciones inyectadas en tu plugin de UI, sigue la [guía “Usar traducciones de UI”](/es/guides/i18n/#usar-traducciones-de-ui). + +Los tipos para las strings de traducción inyectadas en un plugin se generan automáticamente en el proyecto de un usuario, pero aún no están disponibles cuando trabajas en el código de tu plugin. +Para tipar el objeto `locals.t` en el contexto de tu plugin, declara los siguientes espacios de nombres globales en un archivo de declaración de TypeScript: + +```ts +// env.d.ts +declare namespace App { + type StarlightLocals = import('@astrojs/starlight').StarlightLocals; + // Define el objeto `locals.t` en el contexto de un plugin. + interface Locals extends StarlightLocals {} +} + +declare namespace StarlightApp { + // Define las traducciones adicionales del plugin en la interfaz `I18n`. + interface I18n { + 'myPlugin.doThing': string; + } +} +``` + +También puedes inferir los tipos para la interfaz `StarlightApp.I18n` a partir de un archivo fuente si tienes un objeto que contiene tus traducciones. + +Por ejemplo, dado el siguiente archivo fuente: + +```ts title="ui-strings.ts" +export const UIStrings = { + en: { 'myPlugin.doThing': 'Do the thing' }, + fr: { 'myPlugin.doThing': 'Faire le truc' }, +}; +``` + +La siguiente declaración inferiría los tipos de las claves en inglés del archivo fuente: + +```ts title="env.d.ts" +declare namespace StarlightApp { + type UIStrings = typeof import('./ui-strings').UIStrings.en; + interface I18n extends UIStrings {} +} +``` diff --git a/docs/src/content/docs/es/reference/route-data.mdx b/docs/src/content/docs/es/reference/route-data.mdx new file mode 100644 index 00000000000..a4e89dde996 --- /dev/null +++ b/docs/src/content/docs/es/reference/route-data.mdx @@ -0,0 +1,204 @@ +--- +title: Referencia de los Datos de Ruta +description: La documentación de referencia completa para el objeto de datos de ruta de Starlight. +--- + +El objeto de datos de ruta de Starlight contiene información sobre la página actual. +Aprende más sobre cómo funciona el modelo de datos de Starlight en la guía de [“Datos de Ruta”](/es/guides/route-data/). + +En los componentes de Astro, accede a los datos de ruta desde `Astro.locals.starlightRoute`: + +```astro {4} +--- +// src/components/Custom.astro + +const { hasSidebar } = Astro.locals.starlightRoute; +--- +``` + +En el [middleware de ruta](/es/guides/route-data/#personalización-de-los-datos-de-ruta), accede a los datos de ruta desde el objeto de contexto pasado a tu función de middleware: + +```ts {5} +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + const { hasSidebar } = context.locals.starlightRoute; +}); +``` + +## `starlightRoute` + +El objeto `starlightRoute` tiene las siguientes propiedades: + +### `dir` + +**Tipo:** `'ltr' | 'rtl'` + +Dirección de escritura de la página. + +### `lang` + +**Tipo:** `string` + +Etiqueta de idioma BCP-47 para la configuración regional de esta página, por ejemplo, `en`, `zh-CN` o `pt-BR`. + +### `locale` + +**Tipo:** `string | undefined` + +La ruta base en la que se sirve un idioma. `undefined` para los slugs de la configuración regional raíz. + +### `siteTitle` + +**Tipo:** `string` + +El título del sitio para la configuración regional de esta página. + +### `siteTitleHref` + +**Tipo:** `string` + +El valor para el atributo `href` del título del sitio, que enlaza de vuelta a la página de inicio, por ejemplo, `/`. +Para sitios multilingües, esto incluirá la configuración regional actual, por ejemplo, `/en/` o `/zh-cn/`. + +### `slug` + +**Tipo:** `string` + +El slug para esta página generado a partir del nombre del archivo de contenido. + +Esta propiedad está obsoleta y se eliminará en una futura versión de Starlight. +Migra a la nueva API de Content Layer utilizando el [`docsLoader`](/es/manual-setup/#configura-las-colecciones-de-contenido) de Starlight y utiliza la propiedad [`id`](#id) en su lugar. + +### `id` + +**Tipo:** `string` + +El slug para esta página o el ID único para esta página basado en el nombre del archivo de contenido si se utiliza el flag [`legacy.collections`](https://docs.astro.build/en/reference/legacy-flags/#collections). + +### `isFallback` + +**Tipo:** `boolean | undefined` + +`true` si esta página no está traducida en el idioma actual y está utilizando contenido de respaldo de la configuración regional predeterminada. +Solo se utiliza en sitios multilingües. + +### `entryMeta` + +**Tipo:** `{ dir: 'ltr' | 'rtl'; lang: string }` + +Metadatos de configuración regional para el contenido de la página. Puede ser diferente de los valores de configuración regional de nivel superior cuando una página está utilizando contenido de respaldo. + +### `entry` + +La entrada de la colección de contenido de Astro para la página actual. +Incluye los valores del frontmatter para la página actual en `entry.data`. + +```ts +entry: { + data: { + title: string; + description: string | undefined; + // etc. + } +} +``` + +Aprende más sobre la forma de este objeto en la referencia del [Tipo de Entrada de Colección de Astro](https://docs.astro.build/en/reference/modules/astro-content/#collectionentry). + +### `sidebar` + +**Tipo:** `SidebarEntry[]` + +Entradas de la barra lateral de navegación del sitio para esta página. + +### `hasSidebar` + +**Tipo:** `boolean` + +Indica si la barra lateral debe mostrarse o no en esta página. + +### `pagination` + +**Tipo:** `{ prev?: Link; next?: Link }` + +Enlaces a la página anterior y siguiente en la barra lateral si está habilitada. + +### `toc` + +**Tipo:** `{ minHeadingLevel: number; maxHeadingLevel: number; items: TocItem[] } | undefined` + +Tabla de contenido para esta página si está habilitada. + +### `headings` + +**Tipo:** `{ depth: number; slug: string; text: string }[]` + +Array de todos los encabezados de Markdown extraídos de la página actual. +Utiliza [`toc`](#toc) en su lugar si deseas construir un componente de tabla de contenido que respete las opciones de configuración de Starlight. + +### `lastUpdated` + +**Tipo:** `Date | undefined` + +Objeto `Date` de JavaScript que representa cuándo se actualizó por última vez esta página si está habilitado. + +### `editUrl` + +**Tipo:** `URL | undefined` + +Objeto `URL` para la dirección donde se puede editar esta página si está habilitado. + +### `head` + +**tipo:** [`HeadConfig[]`](/es/reference/configuration/#headconfig) + +Array de todas las etiquetas para incluir en el `<head>` de la página actual. +Incluye etiquetas importantes como `<title>` y `<meta charset="utf-8">`. + +## Utilidades + +### `defineRouteMiddleware()` + +Utiliza la utilidad `defineRouteMiddleware()` para ayudar a tipar tu módulo de middleware de ruta: + +```ts "defineRouteMiddleware" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + // ... +}); +``` + +### Tipo `StarlightRouteData` + +Si estás escribiendo código que necesita trabajar con los datos de ruta de Starlight, puedes importar el tipo `StarlightRouteData` para que coincida con la forma de `Astro.locals.starlightRoute`. + +En el siguiente ejemplo, una función `usePageTitleInTOC()` actualiza los datos de ruta para utilizar el título de la página actual como etiqueta para el primer elemento de la tabla de contenido, reemplazando la etiqueta predeterminada "Overview". +El tipo `StarlightRouteData` te permite verificar si los cambios en los datos de ruta son válidos. + +```ts "StarlightRouteData" +// src/route-utils.ts +import type { StarlightRouteData } from '@astrojs/starlight/route-data'; + +export function usePageTitleInTOC(starlightRoute: StarlightRouteData) { + const overviewLink = starlightRoute.toc?.items[0]; + if (overviewLink) { + overviewLink.text = starlightRoute.entry.data.title; + } +} +``` + +Esta función se puede llamar desde un middleware de ruta: + +```ts {3,6} +// src/route-middleware.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; +import { usePageTitleInTOC } from './route-utils'; + +export const onRequest = defineRouteMiddleware((context) => { + usePageTitleInTOC(context.locals.starlightRoute); +}); +``` diff --git a/docs/src/content/docs/es/resources/community-content.mdx b/docs/src/content/docs/es/resources/community-content.mdx new file mode 100644 index 00000000000..28f091d5e5c --- /dev/null +++ b/docs/src/content/docs/es/resources/community-content.mdx @@ -0,0 +1,161 @@ +--- +title: Contenido de la comunidad +description: ¡Descubre guías, artículos y videos producidos por la comunidad para ayudarte a aprender y construir con Starlight! +--- + +:::tip[¡Agrega el tuyo!] +¿Has producido contenido sobre Starlight? +¡Abre una PR añadiendo un enlace a esta página! +::: + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +## Artículos y Reseñas + +Aquí tienes una colección de publicaciones y artículos para aprender más sobre Starlight y las experiencias de otras personas: + +<CardGrid> + <LinkCard + href="https://devm.io/open-source/starlight-astro" + title="Generación de sitios estáticos con Starlight" + description="“Ninguna idea es demasiado grande o demasiado pequeña al diseñar componentes” — una entrevista con Chris Swithinbank, líder de Starlight" + /> + <LinkCard + href="https://frontendatscale.com/blog/hybrid-frontend-architecture/" + title="Arquitectura híbrida de frontend con Astro y Starlight." + description="Maxi Ferreira y Ben Holmes construyen un sitio de documentación con Starlight, TinaCMS, y un Playground de API interactivo con autenticación." + /> + <LinkCard + href="https://www.olets.dev/posts/comparing-docs-site-builders-vuepress-vs-starlight/" + title="Comparando constructores de sitios de documentación: VuePress vs. Starlight" + description="¿Cómo se comparan estos dos frameworks?" + /> +</CardGrid> + +## Recetas y Guías + +Las Recetas suelen ser cortas, centradas en guiar al lector a través de la realización de un ejemplo práctico de una tarea específica. ¡Las Recetas son una forma estupenda de añadir nuevas características o comportamientos a tu proyecto de Starlight siguiendo las instrucciones paso a paso! Otras guías pueden explicar conceptos relacionados con un área de contenido específica, como el uso de imágenes o trabajar con MDX. + +Explora contenido producido por la comunidad mantenido por usuarios de Starlight: + +<CardGrid> + <LinkCard + href="https://www.webpro.nl/scraps/versioned-docs-with-starlight-and-vercel" + title="Documentación versionada con Starlight y Vercel" + description="Una guía para implementar versiones separadas de la documentación para cada versión principal de un proyecto." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-heading-links" + title="Agrega enlaces a los encabezados de Starlight" + description="Una guía sobre cómo usar el plugin de rehype para compartir enlaces en secciones específicas de tu documentación" + /> + <LinkCard + href="https://blog.otterlord.dev/posts/starlight-sponsors/" + title="Agrega patrocinadores a tu sitio de Starlight" + description="Una guía para implementar un componente personalizado de patrocinadores en la barra lateral de tu documentación" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images" + title="Agrega imágenes Open Graph a Starlight" + description="Una guía para generar imágenes sociales y las etiquetas meta correspondientes para tus páginas" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-third-party-icon-sets" + title="Utiliza conjuntos de iconos de terceros en Starlight" + description="Una guía para usar unplugin-icons para ampliar la selección de los iconos disponibles para Starlight" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-html-head" + title="Edita las sección head del HTML para las páginas de Starlight" + description="Aprende como agregar contenido común en la sección head como analíticas web, fuentes y scripts" + /> + <LinkCard + href="https://dev.to/mrrobot/publishing-documentation-with-astro-starlight-691" + title="Publicación de documentación con Astro Starlight" + description="Comenzando con la documentación de Starlight." + /> + <LinkCard + href="https://events-3bg.pages.dev/jotter/starlight/guide/" + title="Habilita View Transitions" + description="Consigue esa apariencia SPA con el soporte de View Transitions de Bag of Tricks" + /> + <LinkCard + href="https://jamcomments.com/posts/structured-data-with-starlight" + title="Agregando datos estructurados a las páginas de Starlight" + description="Aprende a construir datos estructurados JSON-LD dinámicos para tus páginas de documentación." + /> + <LinkCard + href="https://starlight-examples.netlify.app/" + title="Ejemplos de Starlight" + description="Una colección de embeds de StackBlitz que demuestran formas prácticas de hacer cosas en sitios de documentación de Starlight." + /> +</CardGrid> + +## Contenido en Video + +Descubre videos y canales con contenido de Starlight, incluyendo transmisiones en vivo y contenido educativo. + +import YouTubeGrid from '~/components/youtube-grid.astro'; + +### Videos de Astro + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=5u0Ds7wzUeI', + title: 'Starlight por Astro', + description: 'Mira el video oficial del lanzamiento de Starlight', + }, + { + href: 'https://www.youtube.com/shorts/zjOWezSzd18', + title: '🌟 MENOS DE 1 MINUTO', + description: + '¡Mira como Ben crea un nuevo sitio de Starlight en menos de un minuto!', + }, + ]} +/> + +### Videos de la Comunidad y Transmisiones + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=sF6UcV3moZg', + title: 'Construyendo documentación con Starlight y Astro', + description: + 'Ve a Chris y Alex sumergirse en Starlight en Code with CodingCat.dev', + }, + { + href: 'https://www.youtube.com/watch?v=sWkkHbwDeQc', + title: 'Astro Starlight', + description: 'Introducción a Starlight en menos de un minuto.', + }, + { + href: 'https://www.youtube.com/watch?v=-Ki-1E5gNCk', + title: + 'Plantilla de documentación de Astro Starlight (¡construye documentación personalizada para tu aplicación!)', + description: + 'Pon en marcha un nuevo sitio de Starlight en unos 5 minutos', + }, + { + href: 'https://www.youtube.com/watch?v=12o7WxjAxjM', + title: + 'Incluye la documentación de Starlight en un proyecto de Next.js con proxies', + description: + 'Configura Starlight como un proyecto de subdirectorio dentro de un sitio web de Next.js', + }, + { + href: 'https://www.youtube.com/watch?v=5pq80drDrNs', + title: + 'Recreé la documentación de Shadcn en 30 minutos con esta increíble herramienta', + description: + 'En este video repaso lo que hace que Starlight sea tan genial y por qué querrías probarlo en tu próximo proyecto.', + }, + { + href: 'https://www.youtube.com/watch?v=Q1E4Gkt63ko', + title: 'Astro Starlight y emoji-blast con Chris Swithinbank', + description: + 'Donde Chris, el creador del framework sobre framework Starlight de Astro, me guía a través de la configuración de un nuevo sitio web de emoji-blast. 🌟 🎇', + }, + ]} +/> diff --git a/docs/src/content/docs/es/resources/plugins.mdx b/docs/src/content/docs/es/resources/plugins.mdx new file mode 100644 index 00000000000..054593b1ff0 --- /dev/null +++ b/docs/src/content/docs/es/resources/plugins.mdx @@ -0,0 +1,152 @@ +--- +title: Plugins e Integraciones +description: ¡Descubre herramientas de la comunidad como plugins e integraciones que amplían Starlight! +sidebar: + order: 1 +--- + +:::tip[¡Agrega el tuyo!] +¿Has construido un plugin o herramienta para Starlight? +¡Abre una PR añadiendo un enlace a esta página! +::: + +## Plugins + +Los [Plugins](/es/reference/plugins/) pueden personalizar la configuración, UI y comportamiento de Starlight, a la vez que son fáciles de compartir y reutilizar. +Amplia tu sitio con un plugins oficiales respaldados por el equipo de Starlight y plugins de la comunidad mantenidos por usuario de Starlight. + +### Plugins oficiales + +<CardGrid> + <LinkCard + href="/es/guides/site-search/#algolia-docsearch" + title="Algolia DocSearch" + description="Reemplaza Pagefind, el proveedor de búsqueda por defecto, por Algolia DocSearch." + /> +</CardGrid> + +### Plugins de la comunidad + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-links-validator" + title="starlight-links-validator" + description="Comprueba si hay enlaces rotos en tus páginas de Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-typedoc" + title="starlight-typedoc" + description="Genera páginas de Starlight desde TypeScript usando TypeDoc" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-blog" + title="starlight-blog" + description="Agrega un blog a tu sitio de documentación." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-openapi" + title="starlight-openapi" + description="Crea páginas de documentación a partir de especificaciones OpenAPI/Swagger." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-obsidian" + title="starlight-obsidian" + description="Publica bóvedas de Obsidian en tu sitio de Starlight." + /> + <LinkCard + href="https://astro-ghostcms.xyz/intro/starlight/install/" + title="starlight-ghostcms" + description="Agrega tus publicaciones de blog de GhostCMS junto con tus documentos de Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-image-zoom" + title="starlight-image-zoom" + description="Agrega capacidades de zoom a las imágenes de tu documentación." + /> + <LinkCard + href="https://github.com/lorenzolewis/starlight-utils" + title="starlight-utils" + description="Extiende Starlight con una colección de utilidades comunes." + /> + <LinkCard + href="https://github.com/trueberryless/starlight-view-modes" + title="starlight-view-modes" + description="Agrega diferentes capacidades de modo de vista a tu sitio de documentación." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-versions" + title="starlight-versions" + description="Agrega versiones a tus páginas de documentación de Starlight." + /> + <LinkCard + href="https://inox-tools.fryuni.dev/star-warp" + title="star-warp" + description="Viaja a través de los resultados de búsqueda en tu documentación" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-heading-badges" + title="starlight-heading-badges" + description="Agrega insignias a tus encabezados de Markdown y MDX." + /> +</CardGrid> + +### Temas de la comunidad + +Un tema es un plugin de Starlight que cambia la apariencia visual de un sitio con reemplazos de componentes, CSS personalizado u otras nuevas características. + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-theme-rapide" + title="starlight-theme-rapide" + description="Tema de Starlight inspirado en el tema Vitesse de Visual Studio Code." + /> +</CardGrid> + +## Herramientas e integraciones de la comunidad + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +Estas herramientas e integraciones de la comunidad se pueden utilizar para añadir características a tu sitio de Starlight. + +<CardGrid> + <LinkCard + href="https://www.feelback.dev/blog/new-astro-starlight-integration/" + title="FeelBack" + description="Agrega un sistema de comentarios de usuarios a la páginas de tus docs." + /> + <LinkCard + href="https://github.com/val-town/notion-to-astro" + title="notion-to-astro" + description="Convierte las exportaciones de Notion a docs de Astro Starlight." + /> + <LinkCard + href="https://github.com/mattjennings/astro-live-code" + title="astro-live-code" + description="Renderiza bloques de código MDX como componentes interactivos." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-i18n" + title="starlight-i18n" + description="Extensión de Visual Studio Code para ayudar a traducir páginas de Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-package-managers" + title="starlight-package-managers" + description="Muestra rápidamente comandos relacionados con npm para varios gestores de paquetes." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-showcases" + title="starlight-showcases" + description="Conjunto de componentes de Starlight para crear páginas de vitrina." + /> + <LinkCard + href="https://github.com/HiDeoo/generator-starlight-plugin" + title="@hideoo/starlight-plugin" + description="Un generador para crear rápidamente plugins de Starlight." + /> + <LinkCard + href="https://docs.contentisland.net/templates/starlight/" + title="contentisland-cli" + description="Conecta y sincroniza tu proyecto Starlight con Content Island Headless CMS para editar y gestionar tu documentación." + /> +</CardGrid> diff --git a/docs/src/content/docs/es/resources/showcase.mdx b/docs/src/content/docs/es/resources/showcase.mdx new file mode 100644 index 00000000000..979d8be196f --- /dev/null +++ b/docs/src/content/docs/es/resources/showcase.mdx @@ -0,0 +1,21 @@ +--- +title: Exhibición de Starlight +description: ¡Descubre sitios construidos con Starlight! +sidebar: + label: Galería de sitios +--- + +:::tip[¡Agrega el tuyo!] +¿Has construido un sitio de Starlight o una herramienta para Starlight? +¡[Abre una PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#showcase) agregando un enlace a esta página! +::: + +## Sitios + +import ShowcaseSites from '~/components/showcase-sites.astro'; + +Starlight ya está siendo usado en producción. Estos son algunos de los sitios en la web: + +<ShowcaseSites /> + +Mira todos los [repositorios públicos de proyectos usando Starlight en GitHub](https://github.com/withastro/starlight/network/dependents). diff --git a/docs/src/content/docs/es/resources/themes.mdx b/docs/src/content/docs/es/resources/themes.mdx new file mode 100644 index 00000000000..ca75a1fda51 --- /dev/null +++ b/docs/src/content/docs/es/resources/themes.mdx @@ -0,0 +1,88 @@ +--- +title: Temas +description: Dale estilo a tus documentos con un tema de la comunidad para Starlight +tableOfContents: false +sidebar: + order: 2 +head: + - tag: style + content: | + body { --sl-content-width: 66.75rem; } +--- + +import ThemeGrid from '~/components/theme-grid.astro'; + +Un tema es un plugin de Starlight que cambia la apariencia visual de un sitio con [CSS personalizado](/es/guides/css-and-tailwind/), [sustituciones de componentes](/es/guides/overriding-components/) u otras nuevas funcionalidades. + +## Temas de la Comunidad + +Instala un tema creado por la comunidad para personalizar rápidamente la apariencia de tu sitio. + +<ThemeGrid + labels={{ + /** Etiqueta accesible para el interruptor de tema. */ + legend: 'Vista previa', + /** Etiqueta accesible para la variante de esquema de color oscuro. */ + dark: 'Oscuro', + /** Etiqueta accesible para la variante de esquema de color claro. */ + light: 'Claro', + }} + themes={[ + { + title: 'Starlight Rapide', + description: + 'Tema de Starlight inspirado en el tema Vitesse de Visual Studio Code.', + href: 'https://starlight-theme-rapide.vercel.app/', + previews: { light: 'rapide-light.png', dark: 'rapide-dark.png' }, + }, + { + title: 'Starlight Obsidian Theme', + description: + 'Tema de Starlight inspirado en el estilo de los sitios de Obsidian Publish.', + href: 'https://fevol.github.io/starlight-theme-obsidian/', + previews: { light: 'obsidian-light.png', dark: 'obsidian-dark.png' }, + }, + { + title: 'Catppuccin for Starlight', + description: 'Suave tema pastel para Starlight.', + href: 'https://catppuccin-starlight.otterlord.dev/', + previews: { light: 'catppuccin-light.png', dark: 'catppuccin-dark.png' }, + }, + { + title: 'Ion', + description: 'Un tema elegante y moderno para Starlight.', + href: 'https://louisescher.github.io/starlight-ion-theme/', + previews: { light: 'ion-light.png', dark: 'ion-dark.png' }, + }, + { + title: 'Starlight Black', + description: 'Tema de Starlight inspirado en la documentación de shadcn.', + href: 'https://starlight-theme-black.vercel.app/', + previews: { light: 'black-light.png', dark: 'black-dark.png' }, + }, + { + title: 'Starlight Flexoki', + description: + 'Un tema cálido y amigable basado en la paleta de colores Flexoki.', + href: 'https://delucis.github.io/starlight-theme-flexoki/', + previews: { light: 'flexoki-light.png', dark: 'flexoki-dark.png' }, + }, + { + title: 'Starlight Nova', + description: 'Un tema moderno y hermoso para Starlight.', + href: 'https://starlight-theme-nova.pages.dev/', + previews: { light: 'nova-light.png', dark: 'nova-dark.png' }, + }, + { + title: 'Tema Starlight NextJS', + description: 'Tema de Starlight inspirado en la documentación de NextJS.', + href: 'https://starlight-nextjs-theme.trueberryless.org/', + previews: { light: 'nextjs-light.png', dark: 'nextjs-dark.png' }, + }, + ]} +/> + +:::tip[¡Añade el tuyo!] +¿Has creado un tema para Starlight? +¡[Abre una PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#themes) añadiendo tu tema a esta página! +::: diff --git a/docs/src/content/docs/es/showcase.mdx b/docs/src/content/docs/es/showcase.mdx deleted file mode 100644 index 2a28fab0bac..00000000000 --- a/docs/src/content/docs/es/showcase.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Mostrador de Starlight -description: ¡Descubre los sitios construidos con Starlight y herramientas comunitarias que amplían Starlight! ---- - -:::tip[¡Agrega el tuyo!] -¿Has construido un sitio de Starlight o una herramienta para Starlight? -¡Abre una PR agregando un enlace a esta página! -::: - -## Sitios - -import ShowcaseSites from '../../../components/showcase-sites.astro'; - -Starlight ya está siendo utilizado en producción. Estos son algunos de los sitios en la web: - -<ShowcaseSites /> - -Consulta todos los [repositorios de proyectos públicos que utilizan Starlight en GitHub](https://github.com/withastro/starlight/network/dependents). - -## Plugins de la comunidad - -import { CardGrid, LinkCard } from '@astrojs/starlight/components'; - -Estas herramientas de la comunidad, plugins e integraciones funcionan junto a Starlight para ampliar su funcionalidad. - -<CardGrid> - <LinkCard - href="https://www.feelback.dev/blog/new-astro-starlight-integration/" - title="FeelBack" - description="Agrega un sistema de opinión de usuarios a tus páginas de documentación." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-blog" - title="starlight-blog" - description="Agrega un blog a tu sitio de documentación." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-links-validator" - title="starlight-links-validator" - description="Verifica en tus páginas de Starlight si hay enlaces rotos." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-typedoc" - title="starlight-typedoc" - description="Genera páginas de Starlight a partir de TypeScript usando TypeDoc." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-openapi" - title="starlight-openapi" - description="Crea páginas de documentación a partir de especificaciones OpenAPI/Swagger." - /> -</CardGrid> diff --git a/docs/src/content/docs/fr/404.md b/docs/src/content/docs/fr/404.md index b2e7aa1d681..0c2912c7a3a 100644 --- a/docs/src/content/docs/fr/404.md +++ b/docs/src/content/docs/fr/404.md @@ -2,6 +2,7 @@ title: Page Introuvable template: splash editUrl: false +lastUpdated: false hero: title: '404' tagline: <strong>Houston, nous avons un problème.</strong> Nous n’avons pas pu trouver cette page.<br>Vérifiez l’URL ou essayez la barre de recherche. diff --git a/docs/src/content/docs/fr/components/asides.mdx b/docs/src/content/docs/fr/components/asides.mdx new file mode 100644 index 00000000000..074e62b4bdd --- /dev/null +++ b/docs/src/content/docs/fr/components/asides.mdx @@ -0,0 +1,194 @@ +--- +title: Encarts +description: Apprenez à utiliser les encarts dans Starlight pour afficher des informations secondaires à côté du contenu principal d'une page. +--- + +import { Aside } from '@astrojs/starlight/components'; + +Pour afficher des informations secondaires à côté du contenu principal d'une page, utilisez le composant `<Aside>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Aside slot="preview"> +Incluez des informations supplémentaires non essentielles avec le composant `<Aside>`. +</Aside> + +</Preview> + +## Importation + +```tsx +import { Aside } from '@astrojs/starlight/components'; +``` + +## Utilisation + +Affichez un encart (également connus sous le nom de « admonition » ou « aside » en anglais) en utilisant le composant `<Aside>`. + +Le composant `<Aside>` peut avoir un attribut facultatif [`type`](#type), qui contrôle la couleur, l'icône et le titre par défaut de l'encart. + +<Preview> + +````mdx +import { Aside } from '@astrojs/starlight/components'; + +<Aside>Un peu de contenu dans un encart.</Aside> + +<Aside type="caution">Quelques mises en garde.</Aside> + +<Aside type="tip"> + +D'autres contenus sont également pris en charge dans les encarts. + +```js +// Un extrait de code, par exemple. +``` + +</Aside> + +<Aside type="danger">Ne communiquez votre mot de passe à personne.</Aside> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% aside %} +Un peu de contenu dans un encart. +{% /aside %} + +{% aside type="caution" %} +Quelques mises en garde. +{% /aside %} + +{% aside type="tip" %} +D'autres contenus sont également pris en charge dans les encarts. + +```js +// Un extrait de code, par exemple. +``` +{% /aside %} + +{% aside type="danger" %} +Ne communiquez votre mot de passe à personne. +{% /aside %} +```` + +</Fragment> + +<Fragment slot="preview"> + + <Aside>Un peu de contenu dans un encart.</Aside> + + <Aside type="caution">Quelques mises en garde.</Aside> + + <Aside type="tip"> + + D'autres contenus sont également pris en charge dans les encarts. + + ```js + // Un extrait de code, par exemple. + ``` + + </Aside> + + <Aside type="danger">Ne communiquez votre mot de passe à personne.</Aside> + +</Fragment> + +</Preview> + +Starlight fournit également une syntaxe personnalisée pour afficher des encarts dans du contenu Markdown et MDX comme alternative au composant `<Aside>`. +Voir le guide [« Création de contenu en Markdown »](/fr/guides/authoring-content/#encarts) pour plus de détails sur la syntaxe personnalisée. + +### Utiliser des titres personnalisés + +Remplacez les titres par défaut des encarts en utilisant l'attribut [`title`](#title). + +<Preview> + +```mdx 'title="Attention !"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="caution" title="Attention !"> + Un encart d'avertissement *avec* un titre personnalisé. +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'title="Attention !"' +{% aside type="caution" title="Attention !" %} +Un encart d'avertissement *avec* un titre personnalisé. +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="caution" title="Attention !"> + Un encart d'avertissement *avec* un titre personnalisé. +</Aside> + +</Preview> + +### Utiliser des icônes personnalisées + +Remplacez les icônes par défaut des encarts en utilisant l'attribut [`icon`](#icon) défini avec le nom de [l'une des icônes intégrées à Starlight](/fr/reference/icons/#toutes-les-icônes). + +<Preview> + +```mdx 'icon="starlight"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="tip" icon="starlight"> + Un encart d'astuce *avec* une icône personnalisée. +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="starlight"' +{% aside type="tip" icon="starlight" %} +Un encart d'astuce *avec* une icône personnalisée. +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="tip" icon="starlight"> + Un encart d'astuce *avec* une icône personnalisée. +</Aside> + +</Preview> + +## Props de `<Aside>` + +**Implémentation :** [`Aside.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Aside.astro) + +Le composant `<Aside>` accepte les props suivantes : + +### `type` + +**Type :** `'note' | 'tip' | 'caution' | 'danger'` +**Par défaut :** `'note'` + +Le type d'encart à afficher : + +- L'encart `note` (par défaut) est bleu et affiche une icône d'information. +- L'encart `tip` est violet et affiche une icône de fusée. +- L'encart `caution` est jaune et affiche une icône d'avertissement triangulaire. +- L'encart `danger` est rouge et affiche une icône d'avertissement octogonale. + +### `title` + +**Type :** `string` + +Le titre de l'encart à afficher. +Si `title` n'est pas défini, le titre par défaut du `type` de l'encart en cours sera utilisé. + +### `icon` + +**Type :** [`StarlightIcon`](/fr/reference/icons/#type-starlighticon) + +Un encart peut inclure un attribut `icon` défini avec le nom de [l'une des icônes intégrées à Starlight](/fr/reference/icons/#toutes-les-icônes). diff --git a/docs/src/content/docs/fr/components/badges.mdx b/docs/src/content/docs/fr/components/badges.mdx new file mode 100644 index 00000000000..b7499e459ec --- /dev/null +++ b/docs/src/content/docs/fr/components/badges.mdx @@ -0,0 +1,150 @@ +--- +title: Badges +description: Apprenez à utiliser les badges dans Starlight pour afficher des informations supplémentaires. +--- + +import { Badge } from '@astrojs/starlight/components'; + +Pour afficher de petits éléments d'information, tels qu'un statut ou une étiquette, utilisez le composant `<Badge>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Badge slot="preview" text="Nouveau" /> + +</Preview> + +## Importation + +```tsx +import { Badge } from '@astrojs/starlight/components'; +``` + +## Utilisation + +Affichez un badge en utilisant le composant `<Badge>` et passez le contenu que vous souhaitez afficher à l'attribut [`text`](#text) du composant `<Badge>`. + +Par défaut, le badge utilisera la couleur d'accentuation du thème de votre site. +Pour utiliser une des couleurs de badge disponibles, définissez l'attribut [`variant`](#variant) à l'une des valeurs prises en charge. + +<Preview> + +```mdx +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="Note" variant="note" /> +- <Badge text="Succès" variant="success" /> +- <Badge text="Astuce" variant="tip" /> +- <Badge text="Attention" variant="caution" /> +- <Badge text="Danger" variant="danger" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +- {% badge text="Note" variant="note" /%} +- {% badge text="Succès" variant="success" /%} +- {% badge text="Astuce" variant="tip" /%} +- {% badge text="Attention" variant="caution" /%} +- {% badge text="Danger" variant="danger" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="Note" variant="note" /> + - <Badge text="Succès" variant="success" /> + - <Badge text="Astuce" variant="tip" /> + - <Badge text="Attention" variant="caution" /> + - <Badge text="Danger" variant="danger" /> +</Fragment> + +</Preview> + +### Utiliser différentes tailles + +Utilisez l'attribut [`size`](#size) pour contrôler la taille du texte du badge. + +<Preview> + +```mdx /size="\w+"/ +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="Nouveau" size="small" /> +- <Badge text="Nouveau et amélioré" size="medium" /> +- <Badge text="Nouveau, amélioré et plus grand" size="large" /> +``` + +<Fragment slot="markdoc"> + +```markdoc /size="\w+"/ +- {% badge text="Nouveau" size="small" /%} +- {% badge text="Nouveau et amélioré" size="medium" /%} +- {% badge text="Nouveau, amélioré et plus grand" size="large" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="Nouveau" size="small" /> + - <Badge text="Nouveau et amélioré" size="medium" /> + - <Badge text="Nouveau, amélioré et plus grand" size="large" /> +</Fragment> + +</Preview> + +### Personnaliser les badges + +Personnalisez les badges en utilisant n'importe quel autre attribut de l'élément `<span>` tel que `class` ou `style` avec du CSS personnalisé. + +<Preview> + +```mdx "style={{ fontStyle: 'italic' }}" +import { Badge } from '@astrojs/starlight/components'; + +<Badge text="Personnalisé" variant="success" style={{ fontStyle: 'italic' }} /> +``` + +<Fragment slot="markdoc"> + +```markdoc 'style="font-style: italic;"' +{% badge text="Personnalisé" variant="success" style="font-style: italic;" /%} +``` + +</Fragment> + +<Badge + slot="preview" + text="Personnalisé" + variant="success" + style={{ fontStyle: 'italic' }} +/> + +</Preview> + +## Props de `<Badge>` + +**Implémentation :** [`Badge.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Badge.astro) + +Le composant `<Badge>` accepte les props suivantes ainsi que [tous les autres attributs de l'élément `<span>`](https://developer.mozilla.org/fr/docs/Web/HTML/Global_attributes) : + +### `text` + +**Obligatoire** +**Type :** `string` + +Le texte à afficher dans le badge. + +### `variant` + +**Type :** `'note' | 'danger' | 'success' | 'caution' | 'tip' | 'default'` +**Par défaut :** `'default'` + +La variante de couleur du badge à utiliser : `note` (bleu), `tip` (violet), `danger` (rouge), `caution` (orange), `success` (vert), ou `default` (couleur d'accentuation du thème). + +### `size` + +**Type :** `'small' | 'medium' | 'large'` + +Définit la taille du badge à afficher. diff --git a/docs/src/content/docs/fr/components/card-grids.mdx b/docs/src/content/docs/fr/components/card-grids.mdx new file mode 100644 index 00000000000..7a715c46894 --- /dev/null +++ b/docs/src/content/docs/fr/components/card-grids.mdx @@ -0,0 +1,181 @@ +--- +title: Grilles de cartes +description: Apprenez à regrouper plusieurs cartes dans une grille dans Starlight. +sidebar: + order: 4 +--- + +import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; + +Pour regrouper plusieurs composants [`<Card>`](/fr/components/cards/) ou [`<LinkCard>`](/fr/components/link-cards/) dans une grille, utilisez le composant `<CardGrid>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<CardGrid slot="preview"> + <Card title="Étoiles" icon="star"> + Sirius, Véga, Bételgeuse + </Card> + <Card title="Lunes" icon="moon"> + Io, Europe, Ganymède + </Card> +</CardGrid> + +</Preview> + +## Importation + +```tsx +import { CardGrid } from '@astrojs/starlight/components'; +``` + +## Utilisation + +### Grouper des cartes + +Affichez plusieurs composants [`<Card>`](/fr/components/cards/) côte à côte lorsqu'il y a suffisamment d'espace en les regroupant à l'aide du composant `<CardGrid>`. + +<Preview> + +```mdx {3,10} +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <Card title="Regardez-ça" icon="open-book"> + Contenu intéressant que vous souhaitez mettre en évidence. + </Card> + <Card title="Et autre chose" icon="information"> + Plus d'informations que vous souhaitez partager. + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,9} +{% cardgrid %} +{% card title="Regardez-ça" icon="open-book" %} +Contenu intéressant que vous souhaitez mettre en évidence. +{% /card %} + +{% card title="Et autre chose" icon="information" %} +Plus d'informations que vous souhaitez partager. +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <Card title="Regardez-ça" icon="open-book"> + Contenu intéressant que vous souhaitez mettre en évidence. + </Card> + <Card title="Et autre chose" icon="information"> + Plus d'informations que vous souhaitez partager. + </Card> +</CardGrid> + +</Preview> + +### Grouper des cartes de liaison + +Affichez plusieurs composants [`<LinkCard>`](/fr/components/link-cards/) côte à côte lorsqu'il y a suffisamment d'espace en les regroupant à l'aide du composant `<CardGrid>`. + +<Preview> + +```mdx {3,9} +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <LinkCard + title="Création de contenu en Markdown" + href="/fr/guides/authoring-content/" + /> + <LinkCard title="Composants" href="/fr/components/using-components/" /> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,7} +{% cardgrid %} +{% linkcard + title="Création de contenu en Markdown" + href="/fr/guides/authoring-content/" /%} + +{% linkcard title="Composants" href="/fr/components/using-components/" /%} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <LinkCard + title="Création de contenu en Markdown" + href="/fr/guides/authoring-content/" + /> + <LinkCard title="Composants" href="/fr/components/using-components/" /> +</CardGrid> + +</Preview> + +### Décaler des cartes + +Décalez la deuxième colonne de la grille verticalement pour ajouter un intérêt visuel en ajoutant l'attribut [`stagger`](#stagger) au composant `<CardGrid>`. + +Cet attribut est utile sur votre page d'accueil pour afficher les principales fonctionnalités de votre projet. + +<Preview> + +```mdx "stagger" +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid stagger> + <Card title="Regardez-ça" icon="open-book"> + Contenu intéressant que vous souhaitez mettre en évidence. + </Card> + <Card title="Et autre chose" icon="information"> + Plus d'informations que vous souhaitez partager. + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc "stagger=true" +{% cardgrid stagger=true %} +{% card title="Regardez-ça" icon="open-book" %} +Contenu intéressant que vous souhaitez mettre en évidence. +{% /card %} + +{% card title="Et autre chose" icon="information" %} +Plus d'informations que vous souhaitez partager. +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview" stagger> + <Card title="Regardez-ça" icon="open-book"> + Contenu intéressant que vous souhaitez mettre en évidence. + </Card> + <Card title="Et autre chose" icon="information"> + Plus d'informations que vous souhaitez partager. + </Card> +</CardGrid> + +</Preview> + +## Props de `<CardGrid>` + +**Implémentation :** [`CardGrid.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/CardGrid.astro) + +Le composant `<CardGrid>` accepte les props suivantes : + +### `stagger` + +**Type :** `boolean` + +Définit si les cartes de la grille doivent être décalées ou non. diff --git a/docs/src/content/docs/fr/components/cards.mdx b/docs/src/content/docs/fr/components/cards.mdx new file mode 100644 index 00000000000..a24816f42e2 --- /dev/null +++ b/docs/src/content/docs/fr/components/cards.mdx @@ -0,0 +1,110 @@ +--- +title: Cartes +description: Apprenez à utiliser des cartes dans Starlight pour afficher du contenu dans un cadre. +sidebar: + order: 2 +--- + +import { Card } from '@astrojs/starlight/components'; + +Pour afficher du contenu dans un cadre correspondant aux styles de Starlight, utilisez le composant `<Card>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Card slot="preview" title="Lunes" icon="moon"> + Io, Europe, Ganymède +</Card> + +</Preview> + +## Importation + +```tsx +import { Card } from '@astrojs/starlight/components'; +``` + +## Utilisation + +Affichez une carte en utilisant le composant `<Card>` et fournissez un titre à la carte en utilisant la propriété [`title`](#title). + +<Preview> + +```mdx +import { Card } from '@astrojs/starlight/components'; + +<Card title="Regardez-ça"> + Contenu intéressant que vous souhaitez mettre en évidence. +</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% card title="Regardez-ça" %} +Contenu intéressant que vous souhaitez mettre en évidence. +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="Regardez-ça"> + Contenu intéressant que vous souhaitez mettre en évidence. +</Card> + +</Preview> + +### Ajouter des icônes aux cartes + +Incluez une icône dans une carte en utilisant l'attribut [`icon`](#icon) défini avec le nom de [l'une des icônes intégrées à Starlight](/fr/reference/icons/#toutes-les-icônes). + +<Preview> + +```mdx 'icon="star"' +import { Card } from '@astrojs/starlight/components'; + +<Card title="Étoiles" icon="star"> + Sirius, Véga, Bételgeuse +</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="star"' +{% card title="Étoiles" icon="star" %} +Sirius, Véga, Bételgeuse +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="Étoiles" icon="star"> + Sirius, Véga, Bételgeuse +</Card> + +</Preview> + +### Grouper des cartes + +Affichez plusieurs cartes côte à côte lorsqu'il y a suffisamment d'espace en les regroupant à l'aide du composant [`<CardGrid>`](/fr/components/card-grids/). +Consultez le guide [« Grouper des cartes »](/fr/components/card-grids/#grouper-des-cartes) pour un exemple. + +## Props de `<Card>` + +**Implémentation :** [`Card.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Card.astro) + +Le composant `<Card>` accepte les props suivantes : + +### `title` + +**Obligatoire** +**Type :** `string` + +Le titre de la carte à afficher. + +### `icon` + +**Type :** `string` + +Une carte peut inclure un attribut `icon` défini avec le nom de [l'une des icônes intégrées à Starlight](/fr/reference/icons/#toutes-les-icônes). diff --git a/docs/src/content/docs/fr/components/code.mdx b/docs/src/content/docs/fr/components/code.mdx new file mode 100644 index 00000000000..5d4d7d437d0 --- /dev/null +++ b/docs/src/content/docs/fr/components/code.mdx @@ -0,0 +1,103 @@ +--- +title: Code +description: Apprenez à afficher du code avec coloration syntaxique dans Starlight sans blocs de code Markdown. +--- + +import { Code } from '@astrojs/starlight/components'; + +Le composant `<Code>` affiche du code avec coloration syntaxique. +Il est utile lorsque l'utilisation d'un [bloc de code Markdown](/fr/guides/authoring-content/#blocs-de-code) n'est pas possible, par exemple pour afficher des données provenant de sources externes comme des fichiers, des bases de données ou des API. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Code + slot="preview" + code={`## Bienvenue + +Bonjour depuis **l'espace** !`} +lang="md" +title="exemple.md" +ins={3} +/> + +</Preview> + +## Importation + +```tsx +import { Code } from '@astrojs/starlight/components'; +``` + +## Utilisation + +Utilisez le composant `<Code>` pour afficher du code avec coloration syntaxique, par exemple lorsque vous affichez du code provenant de sources externes. + +Consultez la [documentation sur le « Composant Code » d'Expressive Code](https://expressive-code.com/key-features/code-component/) pour plus de détails sur l'utilisation du composant `<Code>` et la liste des props disponibles. + +<Preview> + +```mdx +import { Code } from '@astrojs/starlight/components'; + +export const exampleCode = `console.log("Cela peut provenir d'un fichier ou d'un CMS !");`; +export const fileName = 'exemple.js'; +export const highlights = ['fichier', 'CMS']; + +<Code code={exampleCode} lang="js" title={fileName} mark={highlights} /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% code + code="console.log(\"Cela peut provenir d'un fichier ou d'un CMS !\");" + lang="js" + title="exemple.js" + meta="'fichier' 'CMS'" /%} +``` + +</Fragment> + +export const exampleCode = `console.log("Cela peut provenir d'un fichier ou d'un CMS !");`; +export const fileName = 'exemple.js'; +export const highlights = ['fichier', 'CMS']; + +<Code + slot="preview" + code={exampleCode} + lang="js" + title={fileName} + mark={highlights} +/> + +</Preview> + +### Afficher du code importé + +Dans les fichiers MDX et les composants Astro, utilisez le [suffixe d'importation `?raw` de Vite](https://vite.dev/guide/assets#importing-asset-as-string) pour importer n'importe quel fichier de code sous forme de chaîne de caractères. +Vous pouvez ensuite passer cette chaîne importée au composant `<Code>` pour l'inclure dans votre page. + +<Preview> + +```mdx "?raw" +# src/content/docs/example.mdx + +import { Code } from '@astrojs/starlight/components'; +import importedCode from '/tsconfig.json?raw'; + +<Code code={importedCode} lang="json" title="tsconfig.json" /> +``` + +import importedCode from '../../../../../../examples/basics/tsconfig.json?raw'; + +<Code slot="preview" code={importedCode} lang="json" title="tsconfig.json" /> + +</Preview> + +## Props de `<Code>` + +**Implémentation :** [`Code.astro`](https://github.com/expressive-code/expressive-code/blob/main/packages/astro-expressive-code/components/Code.astro) + +Le composant `<Code>` accepte toutes les props documentées dans la [documentation sur le « Composant Code » d'Expressive Code](https://expressive-code.com/key-features/code-component/#available-props). diff --git a/docs/src/content/docs/fr/components/file-tree.mdx b/docs/src/content/docs/fr/components/file-tree.mdx new file mode 100644 index 00000000000..2be1c76ecc0 --- /dev/null +++ b/docs/src/content/docs/fr/components/file-tree.mdx @@ -0,0 +1,265 @@ +--- +title: Arborescence de fichiers +description: Apprenez à afficher la structure d'un répertoire avec des icônes de fichiers et des sous-répertoires repliables dans Starlight. +--- + +import { FileTree } from '@astrojs/starlight/components'; + +Pour afficher la structure d'un répertoire avec des icônes de fichiers et des sous-répertoires repliables, utilisez le composant `<FileTree>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<FileTree slot="preview"> + +- astro.config.mjs un fichier **important** +- package.json +- README.md +- src + - components + - **Header.astro** + - … +- pages/ + +</FileTree> + +</Preview> + +## Importation + +```tsx +import { FileTree } from '@astrojs/starlight/components'; +``` + +## Utilisation + +Affichez une arborescence de fichiers avec des icônes de fichiers et des sous-répertoires repliables en utilisant le composant `<FileTree>`. + +Spécifiez la structure de vos fichiers et répertoires avec une [liste Markdown non ordonnée](https://www.markdownguide.org/basic-syntax/#unordered-lists) à l'intérieur de `<FileTree>`. +Créez un sous-répertoire à l'aide d'une liste imbriquée ou ajoutez un `/` à la fin d'un élément de liste pour l'afficher comme un répertoire sans contenu spécifique. + +<Preview> + +```mdx +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% filetree %} +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> + +</Preview> + +### Mettre en évidence les entrées + +Faites ressortir un fichier ou un répertoire en mettant son nom en gras, par exemple `**README.md**`. + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - **Header.astro** + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> + +</Preview> + +### Ajouter des commentaires + +Ajoutez un commentaire à un fichier ou à un répertoire en ajoutant du texte après le nom. +La syntaxe de mise en forme Markdown, telle que le gras et l'italique, est prise en charge dans les commentaires. + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro un fichier **important** + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - Header.astro un fichier **important** + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro un fichier **important** + - Title.astro + +</FileTree> + +</Preview> + +### Ajouter des entrées fictives + +Ajoutez des fichiers et des répertoires fictifs en utilisant soit `...` soit `…` comme nom. +Cela peut être utile pour indiquer à un lecteur qu'un dossier est censé contenir plus d'éléments sans les spécifier tous explicitement. + +<Preview> + +```mdx {8} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro + - … + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {5} +{% filetree %} +- src + - components + - Header.astro + - … +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro + - … + +</FileTree> + +</Preview> + +### Échapper les caractères spéciaux + +Échappez les caractères spéciaux tels que les tirets bas ou les espaces dans les noms de fichiers en entourant le nom de fichier avec des accents graves. + +<Preview> + +```mdx +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- `__init__.py` +- `Hello world.txt` +- **`À LIRE EN PREMIER.md`** + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% filetree %} +- `__init__.py` +- `Hello world.txt` +- **`À LIRE EN PREMIER.md`** +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- `__init__.py` +- `Hello world.txt` +- **`À LIRE EN PREMIER.md`** + +</FileTree> + +</Preview> + +## Props de `<FileTree>` + +**Implémentation :** [`FileTree.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/FileTree.astro) + +Le composant `<FileTree>` n'accepte aucune props. diff --git a/docs/src/content/docs/fr/components/icons.mdx b/docs/src/content/docs/fr/components/icons.mdx new file mode 100644 index 00000000000..30749974137 --- /dev/null +++ b/docs/src/content/docs/fr/components/icons.mdx @@ -0,0 +1,128 @@ +--- +title: Icônes +description: Apprenez à afficher des icônes avec Starlight. +--- + +import { Icon } from '@astrojs/starlight/components'; + +Pour afficher des icônes depuis un [ensemble d'icônes disponibles](/fr/reference/icons/#toutes-les-icônes) avec Starlight, utilisez le composant `<Icon>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Icon + slot="preview" + name="open-book" + color="var(--sl-color-text-accent)" + size="4rem" +/> + +</Preview> + +## Importation + +```tsx +import { Icon } from '@astrojs/starlight/components'; +``` + +## Utilisation + +Affichez une icône en utilisant le composant `<Icon>`. +Une icône requiert un attribut [`name`](#name) défini avec [une des icônes disponibles avec Starlight](/fr/reference/icons/#toutes-les-icônes) et peut éventuellement inclure un [`label`](#label) pour fournir un contexte aux lecteurs d'écran. + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" /> +<Icon name="starlight" label="Le logo de Starlight" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" /%} +{% icon name="starlight" label="Le logo de Starlight" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" /> + <Icon name="starlight" label="Le logo de Starlight" /> +</Fragment> + +</Preview> + +### Personnaliser les icônes + +Les attributs [`size`](#size) et [`color`](#color) peuvent être utilisés pour ajuster l'apparence de l'icône en utilisant des unités et valeurs de couleur CSS. +L'attribut [`class`](#class) peut être utilisé pour ajouter des classes CSS personnalisées à l'icône. + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" color="goldenrod" size="2rem" /> +<Icon name="rocket" color="var(--sl-color-text-accent)" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" color="goldenrod" size="2rem" /%} +{% icon name="rocket" color="var(--sl-color-text-accent)" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" color="goldenrod" size="2rem" /> + <Icon name="rocket" color="var(--sl-color-text-accent)" /> +</Fragment> + +</Preview> + +## Props de `<Icon>` + +**Implémentation :** [`Icon.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Icon.astro) + +Le composant `<Icon>` accepte les props suivants : + +### `name` + +**Obligatoire** +**Type :** [`StarlightIcon`](/fr/reference/icons/#type-starlighticon) + +Le nom de l'icône à afficher correspondant à [une des icônes disponibles avec Starlight](/fr/reference/icons/#toutes-les-icônes). + +### `label` + +**Type :** `string` + +Une étiquette optionnelle pour fournir un contexte aux technologies d'assistance, comme les lecteurs d'écran. + +Quand l'attribut `label` n'est pas défini, l'icône sera complètement masquée des technologies d'assistance. +Dans ce cas, assurez-vous que le contexte reste compréhensible sans l'icône. +Par exemple, un lien contenant uniquement l'icône **doit** inclure l'attribut `label` pour être accessible, mais si un lien contient du texte et que l'icône est purement décorative, omettre l'attribut `label` peut avoir du sens. + +### `size` + +**Type :** `string` + +La taille de l'icône utilisant des unités CSS. + +### `color` + +**Type :** `string` + +La couleur de l'icône utilisant une valeur de couleur CSS. + +### `class` + +**Type :** `string` + +Classes CSS personnalisées à ajouter à l'icône. diff --git a/docs/src/content/docs/fr/components/link-buttons.mdx b/docs/src/content/docs/fr/components/link-buttons.mdx new file mode 100644 index 00000000000..5bddc79f7f7 --- /dev/null +++ b/docs/src/content/docs/fr/components/link-buttons.mdx @@ -0,0 +1,145 @@ +--- +title: Boutons de liaison +description: Apprenez à créer des boutons de liaison dans Starlight pour des liens visuellement distincts qui appellent à l'action. +--- + +import { LinkButton } from '@astrojs/starlight/components'; + +Pour afficher des liens visuellement distincts qui appellent à l'action (également connus sous le nom de « call-to-action » ou « CTA » en anglais), utilisez le composant `<LinkButton>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkButton slot="preview" href="/fr/getting-started/"> + Lire la documentation +</LinkButton> + +</Preview> + +## Importation + +```tsx +import { LinkButton } from '@astrojs/starlight/components'; +``` + +## Utilisation + +Utilisez le composant `<LinkButton>` pour afficher un lien visuellement distinct qui appelle à l'action. +Un bouton de liaison est utile pour diriger les utilisateurs vers le contenu le plus pertinent ou actionnable et est souvent utilisé sur les pages d'accueil. + +Le composant `<LinkButton>` nécessite un attribut [`href`](#href). +Facultativement, personnalisez l'apparence du bouton de liaison en utilisant l'attribut [`variant`](#variant), qui peut être défini sur `primary` (la valeur par défaut), `secondary` ou `minimal`. + +<Preview> + +```mdx +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton href="/fr/getting-started/">Mise en route</LinkButton> +<LinkButton href="/fr/reference/configuration/" variant="secondary"> + Référence de configuration +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkbutton href="/fr/getting-started/" %}Mise en route{% /linkbutton %} + +{% linkbutton href="/fr/reference/configuration/" variant="secondary" %} +Référence de configuration +{% /linkbutton %} +``` + +</Fragment> + +<Fragment slot="preview"> + <LinkButton href="/fr/getting-started/">Mise en route</LinkButton> + <LinkButton href="/fr/reference/configuration/" variant="secondary"> + Référence de configuration + </LinkButton> +</Fragment> + +</Preview> + +### Ajouter des icônes aux boutons de liaison + +Incluez une icône dans un bouton de liaison en utilisant l'attribut [`icon`](#icon) défini avec [une des icônes disponibles avec Starlight](/fr/reference/icons/#toutes-les-icônes). + +L'attribut [`iconPlacement`](#iconplacement) peut être utilisé pour positionner l'icône avant le texte en le définissant sur `start` (par défaut à `end`). + +<Preview> + +```mdx {6-7} +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton + href="https://docs.astro.build/fr/" + variant="secondary" + icon="external" + iconPlacement="start" +> + Référence : Astro +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc {4-5} +{% linkbutton + href="https://docs.astro.build/fr/" + variant="secondary" + icon="external" + iconPlacement="start" %} +Référence : Astro +{% /linkbutton %} +``` + +</Fragment> + +<LinkButton + slot="preview" + href="https://docs.astro.build/fr/" + variant="secondary" + icon="external" + iconPlacement="start" +> + Référence : Astro +</LinkButton> + +</Preview> + +## Props de `<LinkButton>` + +**Implémentation :** [`LinkButton.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkButton.astro) + +Le composant `<LinkButton>` accepte les props suivantes et également tout [autre attribut de l'élément `<a>`](https://developer.mozilla.org/fr/docs/Web/HTML/Element/a) : + +### `href` + +**Obligatoire** +**Type :** `string` + +L'URL vers laquelle le bouton de liaison pointe. + +### `variant` + +**Type :** `'primary' | 'secondary' | 'minimal'` +**Par défaut :** `'primary'` + +L'apparence du bouton de liaison. +Définissez `primary` pour un lien qui appelle à l'action proéminent utilisant la couleur d'accentuation du thème, `secondary` pour un lien moins proéminent, ou `minimal` pour un lien avec un style minimal. + +### `icon` + +**Type :** `string` + +Un bouton de liaison peut inclure un attribut `icon` défini avec [une des icônes disponibles avec Starlight](/fr/reference/icons/#toutes-les-icônes). + +### `iconPlacement` + +**Type :** `'start' | 'end'` +**Par défaut :** `'end'` + +Détermine la position de l'icône par rapport au texte du bouton de liaison. diff --git a/docs/src/content/docs/fr/components/link-cards.mdx b/docs/src/content/docs/fr/components/link-cards.mdx new file mode 100644 index 00000000000..707aea906e3 --- /dev/null +++ b/docs/src/content/docs/fr/components/link-cards.mdx @@ -0,0 +1,130 @@ +--- +title: Cartes de liaison +description: Apprenez à afficher des liens de manière proéminente sous forme de cartes dans Starlight. +sidebar: + order: 3 +--- + +import { LinkCard } from '@astrojs/starlight/components'; + +Pour afficher des liens vers différentes pages de manière proéminente, utilisez le composant `<LinkCard>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkCard + slot="preview" + title="Personnaliser Starlight" + description="Apprenez à vous approprier votre site Starlight avec des styles personnalisés, des polices de caractères, et plus encore." + href="/fr/guides/customization/" +/> + +</Preview> + +## Importation + +```tsx +import { LinkCard } from '@astrojs/starlight/components'; +``` + +## Utilisation + +Affichez un lien en évidence en utilisant le composant `<LinkCard>`. +Chaque `<LinkCard>` nécessite un attribut [`title`](#title) ainsi qu'un attribut [`href`](#href). + +<Preview> + +```mdx +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard + title="Création de contenu en Markdown" + href="/fr/guides/authoring-content/" +/> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkcard + title="Création de contenu en Markdown" + href="/fr/guides/authoring-content/" /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="Création de contenu en Markdown" + href="/fr/guides/authoring-content/" +/> + +</Preview> + +### Ajouter une description à un lien + +Ajoutez une courte description à une carte de liaison en utilisant l'attribut [`description`](#description). + +<Preview> + +```mdx {6} +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard + title="Internationalisation" + href="/fr/guides/i18n/" + description="Configurer Starlight pour prendre en charge plusieurs langues." +/> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% linkcard + title="Internationalisation" + href="/fr/guides/i18n/" + description="Configurer Starlight pour prendre en charge plusieurs langues." /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="Internationalisation" + href="/fr/guides/i18n/" + description="Configurer Starlight pour prendre en charge plusieurs langues." +/> + +</Preview> + +### Grouper des cartes de liaison + +Affichez plusieurs cartes de liaison côte à côte lorsqu'il y a suffisamment d'espace en les regroupant à l'aide du composant [`<CardGrid>`](/fr/components/card-grids/). +Consultez le guide [« Grouper des cartes de liaison »](/fr/components/card-grids/#grouper-des-cartes-de-liaison) pour un exemple. + +## Props de `<LinkCard>` + +**Implémentation :** [`LinkCard.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkCard.astro) + +Le composant `<LinkCard>` accepte les props suivantes, ainsi que tous les autres [attributs de l'élément `<a>`](https://developer.mozilla.org/fr/docs/Web/HTML/Element/a) : + +### `title` + +**Obligatoire** +**Type :** `string` + +Le titre de la carte de liaison à afficher. + +### `href` + +**Obligatoire** +**Type :** `string` + +L'URL vers laquelle pointer lors d'une interaction avec la carte. + +### `description` + +**Type :** `string` + +Une description facultative à afficher sous le titre. diff --git a/docs/src/content/docs/fr/components/steps.mdx b/docs/src/content/docs/fr/components/steps.mdx new file mode 100644 index 00000000000..76b239fddbd --- /dev/null +++ b/docs/src/content/docs/fr/components/steps.mdx @@ -0,0 +1,120 @@ +--- +title: Étapes +description: Apprenez à mettre en forme des listes numérotées de tâches pour créer des guides étape par étape dans Starlight. +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +Pour mettre en forme une liste numérotée de tâches et créer des guides étape par étape, utilisez le composant `<Steps>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Steps slot="preview"> + +1. Créez un nouveau projet Starlight : + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm create astro@latest -- --template starlight + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm create astro --template starlight + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn create astro --template starlight + ``` + + </TabItem> + + </Tabs> + +2. Écrivez votre première page de documentation. + +</Steps> + +</Preview> + +## Importation + +```tsx +import { Steps } from '@astrojs/starlight/components'; +``` + +## Utilisation + +Utilisez le composant `<Steps>` pour mettre en forme des listes numérotées de tâches. +Celui-ci est utile pour des guides étape par étape plus complexes où chaque étape doit être clairement mise en évidence. + +Entourez une liste ordonnée standard Markdown avec le composant `<Steps>`. +Toute la syntaxe Markdown habituelle est utilisable à l'intérieur de `<Steps>`. + +<Preview> + +````mdx +import { Steps } from '@astrojs/starlight/components'; + +<Steps> + +1. Importez le composant dans votre fichier MDX : + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Entourez les éléments de votre liste ordonnée avec `<Steps>`. + +</Steps> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% steps %} + +1. Importez le composant dans votre fichier MDX : + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Entourez les éléments de votre liste ordonnée avec `<Steps>`. + +{% /steps %} +```` + +</Fragment> + +<Steps slot="preview"> + +1. Importez le composant dans votre fichier MDX : + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Entourez les éléments de votre liste ordonnée avec `<Steps>`. + +</Steps> + +</Preview> + +## Props de `<Steps>` + +**Implémentation :** [`Steps.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Steps.astro) + +Le composant `<Steps>` n'accepte pas de props. diff --git a/docs/src/content/docs/fr/components/tabs.mdx b/docs/src/content/docs/fr/components/tabs.mdx new file mode 100644 index 00000000000..31d6449f130 --- /dev/null +++ b/docs/src/content/docs/fr/components/tabs.mdx @@ -0,0 +1,221 @@ +--- +title: Onglets +description: Apprenez à créer des interfaces à onglets dans Starlight pour regrouper des informations équivalentes. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +Pour créer une interface à onglets, utilisez les composants `<Tabs>` et `<TabItem>`. +Des onglets sont utiles pour regrouper des informations équivalentes où un utilisateur n'a besoin de voir qu'une des options. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Tabs slot="preview"> + <TabItem label="Étoiles">Sirius, Véga, Bételgeuse</TabItem> + <TabItem label="Lunes">Io, Europe, Ganymède</TabItem> +</Tabs> + +</Preview> + +## Importation + +```tsx +import { Tabs, TabItem } from '@astrojs/starlight/components'; +``` + +## Utilisation + +Affichez une interface à onglets en utilisant les composants `<Tabs>` et `<TabItem>`. +Chaque composant `<TabItem>` doit avoir un [`label`](#label) à afficher aux utilisateurs. + +<Preview> + +```mdx +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="Étoiles">Sirius, Véga, Bételgeuse</TabItem> + <TabItem label="Lunes">Io, Europe, Ganymède</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% tabs %} +{% tabitem label="Étoiles" %} +Sirius, Véga, Bételgeuse +{% /tabitem %} + +{% tabitem label="Lunes" %} +Io, Europe, Ganymède +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="Étoiles">Sirius, Véga, Bételgeuse</TabItem> + <TabItem label="Lunes">Io, Europe, Ganymède</TabItem> +</Tabs> + +</Preview> + +### Synchroniser des onglets + +Conservez plusieurs groupes d'onglets synchronisés en ajoutant l'attribut [`syncKey`](#synckey). + +Tous les composants `<Tabs>` avec la même valeur `syncKey` afficheront le même label actif. +Cela permet à votre lecteur de choisir une fois (par exemple, son système d'exploitation ou son gestionnaire de paquets) et de voir son choix persister en naviguant entre différentes pages. + +Pour synchroniser des onglets liés, ajoutez une propriété `syncKey` identique à chaque composant `<Tabs>` et assurez-vous qu'ils utilisent tous les mêmes libellés avec le composant `<TabItem>` : + +<Preview> + +```mdx 'syncKey="constellations"' +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +_Quelques étoiles :_ + +<Tabs syncKey="constellations"> + <TabItem label="Orion">Bellatrix, Rigel, Bételgeuse</TabItem> + <TabItem label="Gémeaux">Pollux, Castor A, Castor B</TabItem> +</Tabs> + +_Quelques exoplanètes :_ + +<Tabs syncKey="constellations"> + <TabItem label="Orion">HD 34445 b, Gliese 179 b, Wasp-82 b</TabItem> + <TabItem label="Gémeaux">Pollux b, HAT-P-24b, HD 50554 b</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc 'syncKey="constellations"' +_Quelques étoiles :_ + +{% tabs syncKey="constellations" %} +{% tabitem label="Orion" %} +Bellatrix, Rigel, Bételgeuse +{% /tabitem %} + +{% tabitem label="Gémeaux" %} +Pollux, Castor A, Castor B +{% /tabitem %} +{% /tabs %} + +_Quelques exoplanètes :_ + +{% tabs syncKey="constellations" %} +{% tabitem label="Orion" %} +HD 34445 b, Gliese 179 b, Wasp-82 b +{% /tabitem %} + +{% tabitem label="Gémeaux" %} +Pollux b, HAT-P-24b, HD 50554 b +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Fragment slot="preview"> + +_Quelques étoiles :_ + +<Tabs syncKey="constellations"> + <TabItem label="Orion">Bellatrix, Rigel, Bételgeuse</TabItem> + <TabItem label="Gémeaux">Pollux, Castor A, Castor B</TabItem> +</Tabs> + +_Quelques exoplanètes :_ + +<Tabs syncKey="constellations"> + <TabItem label="Orion">HD 34445 b, Gliese 179 b, Wasp-82 b</TabItem> + <TabItem label="Gémeaux">Pollux b, HAT-P-24b, HD 50554 b</TabItem> +</Tabs> + +</Fragment> + +</Preview> + +### Ajouter des icônes aux onglets + +Incluez une icône dans un onglet en utilisant l'attribut [`icon`](#icon) défini avec [une des icônes disponibles avec Starlight](/fr/reference/icons/#toutes-les-icônes) pour afficher une icône à côté du libellé. + +<Preview> + +```mdx /icon="\w+"/ +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="Étoiles" icon="star"> + Sirius, Véga, Bételgeuse + </TabItem> + <TabItem label="Lunes" icon="moon"> + Io, Europe, Ganymède + </TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc /icon="\w+"/ +{% tabs %} +{% tabitem label="Étoiles" icon="star" %} +Sirius, Véga, Bételgeuse +{% /tabitem %} + +{% tabitem label="Lunes" icon="moon" %} +Io, Europe, Ganymède +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="Étoiles" icon="star"> + Sirius, Véga, Bételgeuse + </TabItem> + <TabItem label="Lunes" icon="moon"> + Io, Europe, Ganymède + </TabItem> +</Tabs> + +</Preview> + +## Props de `<Tabs>` + +**Implémentation :** [`Tabs.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Tabs.astro) + +Le composant `<Tabs>` regroupe plusieurs composants `<TabItem>` et accepte les props suivantes : + +### `syncKey` + +**Type :** `string` + +Une clé utilisée pour conserver plusieurs groupes d'onglets synchronisés sur plusieurs pages. + +## Props de `<TabItem>` + +**Implémentation :** [`TabItem.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/TabItem.astro) + +Un ensemble d'onglets est composé d'onglets, chacun avec les props suivantes : + +### `label` + +**Obligatoire** +**Type :** `string` + +Un onglet doit inclure un attribut `label` défini avec le texte qui sera affiché dans l'onglet. + +### `icon` + +**Type :** `string` + +Chaque onglet peut inclure un attribut `icon` défini avec [une des icônes disponibles avec Starlight](/fr/reference/icons/#toutes-les-icônes) pour afficher une icône à côté du libellé. diff --git a/docs/src/content/docs/fr/components/using-components.mdx b/docs/src/content/docs/fr/components/using-components.mdx new file mode 100644 index 00000000000..c5b26ce54c2 --- /dev/null +++ b/docs/src/content/docs/fr/components/using-components.mdx @@ -0,0 +1,96 @@ +--- +title: Utilisation des composants +description: Utilisation des composants avec MDX et Markdoc avec Starlight. +sidebar: + order: 1 +--- + +Les composants vous permettent de réutiliser facilement un élément d'interface utilisateur ou de style de manière cohérente. +Il peut s'agir par exemple d'une carte de liaison ou d'une intégration YouTube. +Starlight prend en charge l'utilisation de composants dans les fichiers [MDX](https://mdxjs.com/) et [Markdoc](https://markdoc.dev/) et fournit des composants courants que vous pouvez utiliser. + +[Pour en savoir plus sur la création de composants, consultez la documentation d'Astro](https://docs.astro.build/fr/basics/astro-components/). + +## Utilisation d'un composant avec MDX + +Vous pouvez utiliser un composant en l'important dans votre fichier MDX et ensuite l'afficher en tant que balise JSX. +Ces balises ressemblent à des balises HTML, mais commencent par une lettre majuscule correspondant au nom utilisé dans votre instruction `import` : + +```mdx +--- +# src/content/docs/exemple.mdx +title: Bienvenue dans ma documentation +--- + +import { Icon } from '@astrojs/starlight/components'; +import CustomCard from '../../components/CustomCard.astro'; + +<Icon name="open-book" /> + +<CustomCard> + Les composants peuvent également contenir du **contenu imbriqué**. +</CustomCard> +``` + +Starlight étant basé sur Astro, vous pouvez ajouter la prise en charge de composants construits avec n'importe quel [framework d'interface utilisateur pris en charge (React, Preact, Svelte, Vue, Solid et Alpine)](https://docs.astro.build/fr/guides/framework-components/) dans vos fichiers MDX. +Pour en savoir plus sur [l'utilisation de composants avec MDX](https://docs.astro.build/fr/guides/integrations-guide/mdx/#utilisation-de-composants-dans-mdx), consultez la documentation d'Astro. + +## Utilisation d'un composant avec Markdoc + +Ajoutez la prise en charge de la rédaction de contenu avec Markdoc en suivant notre [guide de configuration Markdoc](/fr/guides/authoring-content/#markdoc). + +En utilisant le préréglage Markdoc de Starlight, vous pouvez utiliser les composants intégrés à Starlight avec la syntaxe de balises `{% %}` de Markdoc. +À la différence du format MDX, les composants dans les fichiers Markdoc n'ont pas besoin d'être importés. +L'exemple suivant affiche le [composant de carte](/fr/components/cards/) de Starlight dans un fichier Markdoc : + +```markdoc +--- +# src/content/docs/exemple.mdoc +title: Bienvenue dans ma documentation +--- + +{% card title="Étoiles" icon="star" %} +Sirius, Véga, Bételgeuse +{% /card %} +``` + +Consultez la [documentation de l'intégration Markdoc d'Astro](https://docs.astro.build/fr/guides/integrations-guide/markdoc/#restituer-les-composants) pour plus d'informations sur l'utilisation des composants dans les fichiers Markdoc. + +## Composants intégrés + +Starlight fournit des composants intégrés par défaut pour des cas d'utilisation courants à une documentation. +Ces composants sont disponibles dans le paquet `@astrojs/starlight/components` dans les fichiers MDX et dans le [préréglage Markdoc de Starlight](/fr/guides/authoring-content/#markdoc) dans les fichiers Markdoc. + +Utilisez la barre latérale pour obtenir une liste des composants disponibles et savoir comment les utiliser. + +## Compatibilité avec les styles de Starlight + +Starlight applique des styles par défaut à votre contenu Markdown, par exemple en ajoutant une marge entre les éléments. +Si ces styles entrent en conflit avec l'apparence de votre composant, utilisez la classe `not-content` sur votre composant pour les désactiver. + +```astro 'class="not-content"' +--- +// src/components/Exemple.astro +--- + +<div class="not-content"> + <p>Contenu non affecté par les styles par défaut de Starlight.</p> +</div> +``` + +## Props des composants + +Utilisez le type [`ComponentProps`](https://docs.astro.build/fr/guides/typescript/#type-componentprops) depuis `astro/types` pour référencer les `Props` acceptées par un composant même si elles ne sont pas exportées par le composant lui-même. +Cela peut être utile lorsqu'il s'agit d'entourer ou d'étendre un composant existant. + +L'exemple suivant utilise `ComponentProps` pour obtenir le type des props acceptées par le composant `Badge` intégré à Starlight : + +```astro +--- +// src/components/Exemple.astro +import type { ComponentProps } from 'astro/types'; +import { Badge } from '@astrojs/starlight/components'; + +type BadgeProps = ComponentProps<typeof Badge>; +--- +``` diff --git a/docs/src/content/docs/fr/environmental-impact.md b/docs/src/content/docs/fr/environmental-impact.md index 6afb6fe3445..dc06c2f568e 100644 --- a/docs/src/content/docs/fr/environmental-impact.md +++ b/docs/src/content/docs/fr/environmental-impact.md @@ -1,32 +1,32 @@ --- -title: Documents écologiques +title: Documentations écologiques description: Découvrez comment Starlight peut vous aider à créer des documentations plus écologiques et à réduire votre empreinte carbone. --- Les estimations de l'impact climatique de l'industrie du web varient entre [2 %][sf] et [4 % des émissions mondiales de carbone][bbc], ce qui équivaut à peu près aux émissions de l'industrie du transport aérien. -Le calcul de l'impact écologique d'un site web repose sur de nombreux facteurs complexes, mais ce guide contient quelques conseils pour réduire l'empreinte écologique de votre site documentaire. +Le calcul de l'impact écologique d'un site web repose sur de nombreux facteurs complexes, mais ce guide contient quelques conseils pour réduire l'empreinte écologique de votre site de documentation. La bonne nouvelle, c'est que le choix de Starlight est un excellent début. -Selon le Website Carbon Calculator, ce site est [plus propre que 99 % des pages web testées][sl-carbon], produisant 0,01 g de CO₂ par page visitée. +Selon le Website Carbon Calculator, ce site est [plus propre que 98 % des pages web testées][sl-carbon], produisant 0,01 g de CO₂ par page visitée. ## Poids de la page Plus une page web transfère de données, plus elle nécessite de ressources énergétiques. En avril 2023, la page web médiane demandait à l'utilisateur de télécharger plus de 2 000 Ko selon les [données de l'archive HTTP][http]. -Starlight construit des pages aussi légères que possible. +Starlight crée des pages aussi légères que possible. Par exemple, lors de sa première visite, un utilisateur téléchargera moins de 50 Ko de données compressées, soit seulement 2,5 % de la médiane des archives HTTP. Avec une bonne stratégie de mise en cache, les navigations suivantes peuvent télécharger jusqu'à 10 Ko. ### Images Bien que Starlight fournisse une bonne base de référence, les images que vous ajoutez à vos pages de documentation peuvent rapidement augmenter le poids de vos pages. -Starlight utilise le [support d'actifs optimisés][assets] d'Astro pour optimiser les images locales dans vos fichiers Markdown et MDX. +Starlight utilise la [prise en charge des ressources optimisées][assets] d'Astro pour optimiser les images locales dans vos fichiers Markdown et MDX. ### Composants d'interface utilisateur -Les composants construits avec des frameworks d'interface utilisateur tels que React ou Vue peuvent facilement ajouter de grandes quantités de JavaScript à une page. -Starlight étant construit sur Astro, les composants de ce type chargent **zéro JavaScript côté client par défaut** grâce à [Astro Islands][islands]. +Les composants créés avec des frameworks d'interface utilisateur tels que React ou Vue peuvent facilement ajouter de grandes quantités de JavaScript à une page. +Starlight étant construit sur Astro, les composants de ce type chargent **zéro JavaScript côté client par défaut** grâce aux [îlots d'Astro][islands]. ### Mise en cache @@ -35,7 +35,7 @@ Une bonne stratégie de mise en cache permet à l'utilisateur d'obtenir un nouve La façon la plus courante de configurer la mise en cache est d'utiliser l'en-tête HTTP [`Cache-Control`][cache]. Lorsque vous utilisez Starlight, vous pouvez définir une longue durée de mise en cache pour tout ce qui se trouve dans le répertoire `/_astro/`. -Ce répertoire contient des fichiers CSS, JavaScript, et d'autres actifs intégrés qui peuvent être mis en cache pour toujours, réduisant ainsi les téléchargements inutiles : +Ce répertoire contient des fichiers CSS, JavaScript, et d'autres ressources intégrées qui peuvent être mises en cache pour toujours, réduisant ainsi les téléchargements inutiles : ``` Cache-Control: public, max-age=604800, immutable @@ -59,13 +59,13 @@ La façon dont une page web est construite peut avoir un impact sur la puissance En utilisant un minimum de JavaScript, Starlight réduit la puissance de traitement dont le téléphone, la tablette ou l'ordinateur d'un utilisateur a besoin pour charger et afficher les pages. Soyez vigilant lorsque vous ajoutez des fonctionnalités telles que des scripts de suivi analytique ou des contenus à forte teneur en JavaScript, comme des vidéos intégrées, car ils peuvent augmenter la consommation d'énergie de la page. -Si vous avez besoin d'analyses, envisagez de choisir une option légère comme [Cabin][cabin], [Fathom][fathom], ou [Plausible][plausible]. +Si vous avez besoin de mesures d'audience, envisagez de choisir une option légère comme [Cabin][cabin], [Fathom][fathom], ou [Plausible][plausible]. Les vidéos intégrées comme celles de YouTube et de Vimeo peuvent être améliorées en attendant de [charger la vidéo lors de l'interaction avec l'utilisateur][lazy-video]. Des paquets comme [`astro-embed`][embed] peuvent aider pour les services communs. :::tip[Le saviez-vous ?] L'analyse et la compilation de JavaScript est l'une des tâches les plus coûteuses pour les navigateurs. -Par rapport au rendu d'une image JPEG de même taille, [le traitement de JavaScript peut prendre plus de 30 fois plus de temps][coût-de-js]. +Par rapport au rendu d'une image JPEG de même taille, [le traitement de JavaScript peut prendre plus de 30 fois plus de temps][cost-of-js]. ::: [cabin]: https://withcabin.com/ @@ -89,31 +89,37 @@ Le choix d'un hébergeur utilisant des énergies renouvelables se traduira par u Curieux de savoir comment les autres frameworks de documentation se comparent ? Ces tests avec le [Website Carbon Calculator][wcc] comparent des pages similaires construites avec différents outils. -| Framework | CO₂ par page visitée | -| --------------------------- | -------------------- | -| [Starlight][sl-carbon] | 0.01g | -| [VitePress][vp-carbon] | 0.05g | -| [Docus][dc-carbon] | 0.05g | -| [Sphinx][sx-carbon] | 0.07g | -| [MkDocs][mk-carbon] | 0.10g | -| [Nextra][nx-carbon] | 0.11g | -| [docsify][dy-carbon] | 0.11g | -| [Docusaurus][ds-carbon] | 0.24g | -| [Read the Docs][rtd-carbon] | 0.24g | -| [GitBook][gb-carbon] | 0.71g | - -<small>Données collectées le 14 mai 2023. Cliquez sur un lien pour voir les chiffres actualisés.</small> +| Framework | CO₂ par page visitée | Notation | +| --------------------------- | -------------------- | :------: | +| [Starlight][sl-carbon] | 0.01g | A+ | +| [Sphinx][sx-carbon] | 0.01g | A+ | +| [Read the Docs][rtd-carbon] | 0.03g | A+ | +| [VitePress][vp-carbon] | 0.04g | A | +| [docsify][dy-carbon] | 0.05g | A | +| [mdBook][md-carbon] | 0.05g | A | +| [Nextra][nx-carbon] | 0.05g | A | +| [MkDocs][mk-carbon] | 0.07g | A | +| [Fumadocs][fs-carbon] | 0.07g | A | +| [Docusaurus][ds-carbon] | 0.10g | B | +| [Docus][dc-carbon] | 0.11g | B | +| [GitBook][gb-carbon] | 0.42g | F | +| [Mintlify][mt-carbon] | 0.48g | F | + +<small>Données collectées le 7 août 2025. Cliquez sur un lien pour voir les chiffres actualisés.</small> [sl-carbon]: https://www.websitecarbon.com/website/starlight-astro-build-getting-started/ [vp-carbon]: https://www.websitecarbon.com/website/vitepress-dev-guide-what-is-vitepress/ -[dc-carbon]: https://www.websitecarbon.com/website/docus-dev-introduction-getting-started/ +[dc-carbon]: https://www.websitecarbon.com/website/docus-dev-en-getting-started-project-structure/ [sx-carbon]: https://www.websitecarbon.com/website/sphinx-doc-org-en-master-usage-quickstart-html/ [mk-carbon]: https://www.websitecarbon.com/website/mkdocs-org-getting-started/ +[md-carbon]: https://www.websitecarbon.com/website/rust-lang-github-io-mdbook/ [nx-carbon]: https://www.websitecarbon.com/website/nextra-site-docs-docs-theme-start/ +[fs-carbon]: https://www.websitecarbon.com/website/fumadocs-dev-docs-ui/ [dy-carbon]: https://www.websitecarbon.com/website/docsify-js-org/ [ds-carbon]: https://www.websitecarbon.com/website/docusaurus-io-docs/ [rtd-carbon]: https://www.websitecarbon.com/website/docs-readthedocs-io-en-stable-index-html/ -[gb-carbon]: https://www.websitecarbon.com/website/docs-gitbook-com/ +[gb-carbon]: https://www.websitecarbon.com/website/gitbook-com-docs/ +[mt-carbon]: https://www.websitecarbon.com/website/mintlify-com-docs-quickstart/ ## Plus de ressources @@ -135,6 +141,6 @@ Ces tests avec le [Website Carbon Calculator][wcc] comparent des pages similaire [sf]: https://www.sciencefocus.com/science/what-is-the-carbon-footprint-of-the-internet/ [bbc]: https://www.bbc.com/future/article/20200305-why-your-internet-habits-are-not-as-clean-as-you-think [http]: https://httparchive.org/reports/state-of-the-web -[assets]: https://docs.astro.build/en/guides/assets/ -[islands]: https://docs.astro.build/en/concepts/islands/ +[assets]: https://docs.astro.build/fr/guides/images/ +[islands]: https://docs.astro.build/fr/concepts/islands/ [wcc]: https://www.websitecarbon.com/ diff --git a/docs/src/content/docs/fr/getting-started.mdx b/docs/src/content/docs/fr/getting-started.mdx index c51c6997851..27b6135a2fd 100644 --- a/docs/src/content/docs/fr/getting-started.mdx +++ b/docs/src/content/docs/fr/getting-started.mdx @@ -5,17 +5,20 @@ description: Apprenez à créer votre prochain site de documentation avec Starli import { Tabs, TabItem } from '@astrojs/starlight/components'; -## Créer un nouveau projet +Starlight est un thème de documentation complet construit sur la base du framework [Astro](https://astro.build). +Ce guide vous aidera à démarrer un nouveau projet. +Consultez les [instructions d'installation manuelle](/fr/manual-setup/) pour ajouter Starlight à un projet Astro existant. -Starlight est un thème de documentation complet construit sur le framework [Astro](https://astro.build). +## Démarrage rapide -Vous pouvez créer un nouveau projet Astro + Starlight en utilisant la commande suivante : +### Créer un nouveau projet -<Tabs> +Créez un nouveau projet Astro + Starlight en lançant la commande suivante dans votre terminal : + +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# créer un nouveau projet avec npm npm create astro@latest -- --template starlight ``` @@ -23,7 +26,6 @@ npm create astro@latest -- --template starlight <TabItem label="pnpm"> ```sh -# créer un nouveau projet avec pnpm pnpm create astro --template starlight ``` @@ -31,7 +33,6 @@ pnpm create astro --template starlight <TabItem label="Yarn"> ```sh -# créer un nouveau projet avec yarn yarn create astro --template starlight ``` @@ -45,85 +46,96 @@ Essayez Starlight dans votre navigateur : [ouvrir le modèle sur StackBlitz](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). ::: -## Créer du contenu avec Starlight +### Démarrer le serveur de développement -Starlight est conçu pour que vous puissiez ajouter du nouveau contenu, ou apporter vos fichiers existants ! +Lorsque vous travaillez localement, [le serveur de développement d'Astro](https://docs.astro.build/fr/reference/cli-reference/#astro-dev) vous permet de prévisualiser votre travail et actualise automatiquement votre navigateur lorsque vous apportez des modifications. -### Formats de fichiers +À l'intérieur du répertoire de votre projet, exécutez la commande suivante pour démarrer le serveur de développement : -Starlight prend en charge la création de contenu en Markdown et MDX. (Vous pouvez ajouter la prise en charge de Markdoc en installant l'intégration expérimentale [Astro Markdoc integration](https://docs.astro.build/fr/guides/integrations-guide/markdoc/).) +<Tabs syncKey="pkg"> +<TabItem label="npm"> -### Ajouter des pages +```sh +npm run dev +``` -Ajoutez automatiquement de nouvelles pages à votre site en créant des fichiers `.md` ou `.mdx` dans `src/content/docs/`. Ajoutez des sous-dossiers pour organiser vos fichiers, et pour créer plusieurs segments de chemin : +</TabItem> +<TabItem label="pnpm"> +```sh +pnpm dev ``` -src/content/docs/hello-world.md => votre-site.com/hello-world -src/content/docs/guides/faq.md => votre-site.com/guides/faq + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev ``` -### Type-safe frontmatter +</TabItem> +</Tabs> -Toutes les pages Starlight partagent un [ensemble commun de propriétés de présentation](/fr/reference/frontmatter/) personnalisable pour contrôler l'apparence de la page : +Un message indiquant l'URL de votre aperçu local s'affichera dans votre terminal. +Ouvrez cette URL pour commencer à naviguer sur votre site. -```md ---- -title: Bonjour, le monde ! -description: Ceci est une page de mon site web propulsé par Starlight. ---- -``` +### Ajouter du contenu -Si vous oubliez quelque chose d'important, Starlight vous le fera savoir. +Starlight est prêt pour que vous puissiez ajouter du nouveau contenu, ou apporter vos fichiers existants ! -## Déployer votre site web Starlight +Ajoutez de nouvelles pages à votre site en créant des fichiers Markdown dans le répertoire `src/content/docs/`. -Une fois que vous avez créé et personnalisé votre site Web Starlight, vous pouvez le déployer sur un serveur Web ou une plateforme d'hébergement de votre choix, y compris Netlify, Vercel, GitHub Pages et bien d'autres. +Pour en savoir plus sur le routage par fichier et la prise en charge des fichiers MDX et Markdoc, consultez le guide [« Pages »](/fr/guides/pages/). -[Pour en savoir plus sur le déploiement d'un site Astro, consultez la documentation Astro](https://docs.astro.build/fr/guides/deploy/) +### Prochaines étapes + +- **Configurer :** Découvrez les options courantes dans [« Personnaliser Starlight »](/fr/guides/customization/). +- **Naviguer :** Configurez votre barre latérale avec le guide [« Barre latérale de navigation »](/fr/guides/sidebar/). +- **Composants :** Découvrez les cartes, les onglets et d'autres composants intégrés dans le guide [« Composants »](/fr/components/using-components/). +- **Enrichir :** Explorez les modules complémentaires créés par la communauté dans nos galeries [« Modules d'extension »](/fr/resources/plugins/) et [« Thèmes »](/fr/resources/themes/). +- **Déployer :** Publiez votre travail avec le guide [« Déployer votre site »](https://docs.astro.build/fr/guides/deploy/) dans la documentation d'Astro. ## Mettre à jour Starlight :::tip -Comme Starlight est un logiciel bêta, il y aura des mises à jour et des améliorations fréquentes. Assurez-vous de mettre à jour Starlight régulièrement ! +Comme Starlight est un logiciel en version bêta, il y aura des mises à jour et des améliorations fréquentes. +Assurez-vous de mettre à jour Starlight régulièrement ! ::: -Starlight est une intégration Astro, et est mis à jour comme toute intégration `@astrojs/*` : +Starlight est une intégration Astro. Vous pouvez la mettre à jour ainsi que tout autre paquet d'Astro en exécutant la commande suivante dans votre terminal : -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# mettre à jour Starlight avec npm -npm install @astrojs/starlight@latest +npx @astrojs/upgrade ``` </TabItem> <TabItem label="pnpm"> ```sh -# mettre à jour Starlight avec pnpm -pnpm upgrade @astrojs/starlight --latest +pnpm dlx @astrojs/upgrade ``` </TabItem> <TabItem label="Yarn"> ```sh -# mettre à jour Starlight avec yarn -yarn upgrade @astrojs/starlight --latest +yarn dlx @astrojs/upgrade ``` </TabItem> </Tabs> -Vous pouvez voir une liste complète des modifications apportées à chaque version dans [le journal des modifications de Starlight](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md). +Consultez le [journal des modifications de Starlight](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md) pour une liste complète des modifications apportées à chaque version. ## Dépannage de Starlight -Les informations [configuration de projet](/fr/reference/configuration/) et [configuration du frontmatter de la page individuelle](/fr/reference/frontmatter/) pour Starlight sont disponibles dans la section Référence de ce site. Utilisez ces pages pour vous assurer que votre site Starlight est configuré et fonctionne correctement. - -Utilisez la liste croissante de guides dans la barre latérale pour vous aider à ajouter du contenu et à personnaliser votre site Starlight. +Utilisez les pages de référence de [configuration de projet](/fr/reference/configuration/) et de [configuration du frontmatter pour chaque page](/fr/reference/frontmatter/) pour vous assurer que votre site Starlight est configuré et fonctionne correctement. +Consultez les guides de la barre latérale pour vous aider à ajouter du contenu et à personnaliser votre site Starlight. -Si vous ne trouvez pas votre réponse dans cette documentation, veuillez consulter la [documentation complète d'Astro](https://docs.astro.build). Votre question peut être résolue en comprenant comment Astro fonctionne en général, sous ce thème Starlight. +Si vous ne trouvez pas votre réponse dans cette documentation, merci de consulter la [documentation d'Astro](https://docs.astro.build/fr/) pour la documentation complète d'Astro. +Votre question peut être résolue en comprenant comment Astro fonctionne de manière générale, sous ce thème Starlight. -Vous pouvez également vérifier [tous les problèmes connus de Starlight sur GitHub](https://github.com/withastro/starlight/issues) et obtenir de l'aide dans le [Discord Astro](https://astro.build/chat/) de notre communauté active et sympathique ! Publiez des questions dans notre forum `#support` avec le tag "starlight" ou visiter notre canal dédié `#starlight` pour discuter des développements en cours et plus encore ! +Vous pouvez également vérifier [tous les problèmes connus de Starlight sur GitHub](https://github.com/withastro/starlight/issues) et obtenir de l'aide auprès de notre communauté active et sympathique dans le [Discord d'Astro](https://astro.build/chat/) ! Publiez des questions dans notre forum `#support` avec le tag « starlight » ou visiter notre canal dédié `#starlight` pour discuter des développements en cours et plus encore ! diff --git a/docs/src/content/docs/fr/guides/authoring-content.md b/docs/src/content/docs/fr/guides/authoring-content.md deleted file mode 100644 index 0757290ea60..00000000000 --- a/docs/src/content/docs/fr/guides/authoring-content.md +++ /dev/null @@ -1,208 +0,0 @@ ---- -title: Création de contenu en Markdown -description: Un aperçu de la syntaxe Markdown prise en charge par Starlight. ---- - -Starlight prend en charge l'ensemble de la syntaxe [Markdown](https://daringfireball.net/projects/markdown/) dans les fichiers `.md` ainsi que la syntaxe frontale [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) pour définir des métadonnées telles qu'un titre et une description. - -Veillez à consulter les [MDX docs](https://mdxjs.com/docs/what-is-mdx/#markdown) ou les [Markdoc docs](https://markdoc.dev/docs/syntax) si vous utilisez ces formats de fichiers, car la prise en charge et l'utilisation de Markdown peuvent varier. - -## Styles en ligne - -Le texte peut être **gras**, _italique_, ou ~~barré~~. - -```md -Le texte peut être **gras**, _italique_, ou ~~barré~~. -``` - -Vous pouvez [faire un lien vers une autre page](/fr/getting-started/). - -```md -Vous pouvez [faire un lien vers une autre page](/fr/getting-started/). -``` - -Vous pouvez mettre en évidence le `code en ligne` à l'aide d'un astérisque. - -```md -Vous pouvez mettre en évidence le `code en ligne` à l'aide de barres de défilement. -``` - -## Images - -Les images dans Starlight utilisent [la prise en charge intégrée des ressources optimisées d'Astro](https://docs.astro.build/en/guides/assets/). - -Markdown et MDX supportent la syntaxe Markdown pour l'affichage des images qui inclut le texte alt pour les lecteurs d'écran et les technologies d'assistance. - -![Une illustration de planètes et d'étoiles avec le mot "astro"](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) - -```md -![Une illustration de planètes et d'étoiles avec le mot "astro"](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) -``` - -Les chemins d'accès relatifs aux images sont également supportés pour les images stockées localement dans votre projet. - -```md -// src/content/docs/page-1.md - -![Une fusée dans l'espace](../../assets/images/rocket.svg) -``` - -## En-têtes - -Vous pouvez structurer le contenu à l'aide d'un titre. En Markdown, les titres sont indiqués par un nombre de `#` en début de ligne. - -### Comment structurer le contenu d'une page dans Starlight - -Starlight est configuré pour utiliser automatiquement le titre de votre page comme titre de premier niveau et inclura un titre "Aperçu" en haut de la table des matières de chaque page. Nous vous recommandons de commencer chaque page par un paragraphe de texte normal et d'utiliser des titres de page à partir de `<h2>` : - -```md ---- -title: Guide Markdown -description: Comment utiliser Markdown dans Starlight ---- - -Cette page décrit comment utiliser Markdown dans Starlight. - -## Styles en ligne - -## Titres -``` - -### Liens d'ancrage automatiques pour les titres - -L'utilisation de titres en Markdown vous donnera automatiquement des liens d'ancrage afin que vous puissiez accéder directement à certaines sections de votre page : - -```md ---- -title: Ma page de contenu -description: Comment utiliser les liens d'ancrage intégrés de Starlight ---- - -## Introduction - -Je peux faire un lien vers [ma conclusion](#conclusion) plus bas sur la même page. - -## Conclusion - -`https://my-site.com/page1/#introduction` renvoie directement à mon Introduction. -``` - -Les titres de niveau 2 (`<h2>`) et de niveau 3 (`<h3>`) apparaissent automatiquement dans la table des matières de la page. - -## Asides - -Les Asides (également connus sous le nom de "callouts") sont utiles pour afficher des informations secondaires à côté du contenu principal d'une page. - -Starlight fournit une syntaxe Markdown personnalisée pour le rendu des apartés. Les blocs d'apartés sont indiqués en utilisant une paire de triples points `:::` pour envelopper votre contenu, et peuvent être de type `note`, `tip`, `caution` ou `danger`. - -Vous pouvez imbriquer n'importe quel autre type de contenu Markdown à l'intérieur d'un aparté, mais les aparté sont mieux adaptés à des morceaux de contenu courts et concis. - -### Note aside - -:::note -Starlight est une boîte à outils pour sites web de documentation construite avec [Astro](https://astro.build/). Vous pouvez démarrer avec cette commande : - -```sh -npm run create astro@latest --template starlight -``` - -::: - -````md -:::note -Starlight est une boîte à outils pour sites web de documentation construite avec [Astro](https://astro.build/). Vous pouvez démarrer avec cette commande : - -```sh -npm run create astro@latest --template starlight -``` - -::: -```` - -### Titres personnalisés dans les asides - -Vous pouvez spécifier un titre personnalisé pour l'aparté entre crochets après le type d'aparté, par exemple `:::tip[Le saviez-vous ?]`. - -:::tip[Le saviez-vous ?] -Astro vous aide à construire des sites Web plus rapides grâce à ["Islands Architecture"](https://docs.astro.build/fr/concepts/islands/). -::: - -```md -:::tip[Le saviez-vous ?] -Astro vous aide à construire des sites Web plus rapides grâce à ["Islands Architecture"](https://docs.astro.build/fr/concepts/islands/). -::: -``` - -### Plus de types pour l'aside - -Les apartés de type Attention et Danger sont utiles pour attirer l'attention de l'utilisateur sur des détails qui pourraient le perturber. Si vous vous retrouvez à utiliser ces derniers fréquemment, cela pourrait aussi être un signe que ce que vous documentez pourrait bénéficier d'une refonte. - -:::caution -Si vous n'êtes pas sûr de vouloir un site de documentation génial, réfléchissez à deux fois avant d'utiliser [Starlight](../../../). -::: - -:::danger -Vos utilisateurs peuvent être plus productifs et trouver votre produit plus facile à utiliser grâce aux fonctionnalités utiles de Starlight. - -- Navigation claire -- Thème de couleurs configurable par l'utilisateur -- [Support i18n](/fr/guides/i18n) - -::: - -```md -:::caution -Si vous n'êtes pas sûr de vouloir un site de documentation génial, réfléchissez à deux fois avant d'utiliser [Starlight](../../../). -::: - -:::danger -Vos utilisateurs peuvent être plus productifs et trouver votre produit plus facile à utiliser grâce aux fonctionnalités utiles de Starlight. - -- Navigation claire -- Thème de couleurs configurable par l'utilisateur -- [Support i18n](/fr/guides/i18n) - -::: -``` - -## Blockquotes - -> Il s'agit d'une citation en bloc, couramment utilisée pour citer une autre personne ou un document. -> -> Les guillemets sont indiqués par un `>` au début de chaque ligne. - -```md -> Il s'agit d'une citation en bloc, couramment utilisée pour citer une autre personne ou un document. -> -> Les guillemets sont indiqués par un `>` au début de chaque ligne. -``` - -## Code blocks - -Un bloc de code est indiqué par un bloc avec trois crochets <code>```</code> au début et à la fin. Vous pouvez indiquer le langage de programmation utilisé après les premiers crochets. - -```js -// Code Javascript avec mise en évidence de la syntaxe. -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` - -````md -```js -// Code Javascript avec mise en évidence de la syntaxe. -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` -```` - -```md -Les longs blocs de code d'une seule ligne ne doivent pas être enveloppés. Ils doivent défiler horizontalement s'ils sont trop longs. Cette ligne devrait être suffisamment longue pour le démontrer. -``` - -## Autres fonctionnalités courantes de Markdown - -Starlight prend en charge toutes les autres syntaxes de rédaction Markdown, telles que les listes et les tableaux. Voir [Markdown Cheat Sheet from The Markdown Guide](https://www.markdownguide.org/cheat-sheet/) pour un aperçu rapide de tous les éléments de la syntaxe Markdown. diff --git a/docs/src/content/docs/fr/guides/authoring-content.mdx b/docs/src/content/docs/fr/guides/authoring-content.mdx new file mode 100644 index 00000000000..9e4f36c0ad7 --- /dev/null +++ b/docs/src/content/docs/fr/guides/authoring-content.mdx @@ -0,0 +1,697 @@ +--- +title: Création de contenu en Markdown +description: Un aperçu de la syntaxe Markdown prise en charge par Starlight. +--- + +Starlight prend en charge l'ensemble de la syntaxe [Markdown](https://daringfireball.net/projects/markdown/) dans les fichiers `.md` ainsi que le frontmatter en [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) pour définir des métadonnées telles qu'un titre et une description. + +Veillez à consulter la [documentation de MDX](https://mdxjs.com/docs/what-is-mdx/#markdown) ou la [documentation de Markdoc](https://markdoc.dev/docs/syntax) si vous utilisez ces formats de fichiers, car la prise en charge et l'utilisation de Markdown peuvent varier. + +## Frontmatter + +Vous pouvez personnaliser chaque page individuellement en définissant des valeurs dans leur frontmatter. +Le frontmatter se situe en haut de vos fichiers entre les séparateurs `---` : + +```md title="src/content/docs/exemple.md" +--- +title: Le titre de ma page +--- + +Le contenu de la page suit le second `---`. +``` + +Chaque page doit inclure au moins un titre (`title`). +Consultez la [référence du frontmatter](/fr/reference/frontmatter/) pour connaître tous les champs disponibles et comment ajouter des champs personnalisés. + +## Styles incorporés au texte + +Le texte peut être en **gras**, en _italique_, ou ~~barré~~. + +```md +Le texte peut être en **gras**, en _italique_, ou ~~barré~~. +``` + +Vous pouvez [faire un lien vers une autre page](/fr/getting-started/). + +```md +Vous pouvez [faire un lien vers une autre page](/fr/getting-started/). +``` + +Vous pouvez mettre en évidence le `code incorporé au texte` en utilisant des accents graves. + +```md +Vous pouvez mettre en évidence le `code incorporé au texte` en utilisant des accents graves. +``` + +## Images + +Les images dans Starlight utilisent [la prise en charge intégrée des ressources optimisées d'Astro](https://docs.astro.build/fr/guides/images/). + +Markdown et MDX prennent en charge la syntaxe Markdown pour l'affichage d'images qui incluent du texte alternatif pour les lecteurs d'écran et les technologies d'assistance. + +![Une illustration de planètes et d'étoiles avec le mot « astro »](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) + +```md +![Une illustration de planètes et d'étoiles avec le mot « astro »](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) +``` + +Les chemins d'accès relatifs aux images sont également pris en charge pour les images stockées localement dans votre projet. + +```md +// src/content/docs/page-1.md + +![Une fusée dans l'espace](../../assets/images/rocket.svg) +``` + +## En-têtes + +Vous pouvez structurer le contenu à l'aide d'en-têtes. En Markdown, les en-têtes sont indiqués par un certain nombre de `#` en début de ligne. + +### Comment structurer le contenu d'une page dans Starlight + +Starlight est configuré pour utiliser automatiquement le titre de votre page comme en-tête de premier niveau et inclura un en-tête « Aperçu » en haut de la table des matières de chaque page. Nous vous recommandons de commencer chaque page par un paragraphe de texte normal et d'utiliser des en-têtes de page à partir de `<h2>` : + +```md +--- +title: Guide Markdown +description: Comment utiliser Markdown dans Starlight +--- + +Cette page décrit comment utiliser Markdown dans Starlight. + +## Styles incorporés au texte + +## En-têtes +``` + +### Liens d'ancrage automatiques pour les en-têtes + +L'utilisation d'en-têtes en Markdown vous donnera automatiquement des liens d'ancrage afin que vous puissiez accéder directement à certaines sections de votre page : + +```md +--- +title: Ma page de contenu +description: Comment utiliser les liens d'ancrage intégrés de Starlight +--- + +## Introduction + +Je peux faire un lien vers [ma conclusion](#conclusion) plus bas sur la même page. + +## Conclusion + +`https://my-site.com/page1/#introduction` renvoie directement à mon Introduction. +``` + +Les en-têtes de niveau 2 (`<h2>`) et de niveau 3 (`<h3>`) apparaissent automatiquement dans la table des matières de la page. + +Pour en apprendre davantage sur la façon dont Astro traite les attributs `id` des en-têtes de section, consultez la [documentation d'Astro](https://docs.astro.build/fr/guides/markdown-content/#id-des-titres). + +## Encarts + +Les encarts (également connus sous le nom de « admonitions » ou « asides » en anglais) sont utiles pour afficher des informations secondaires à côté du contenu principal d'une page. + +Starlight fournit une syntaxe Markdown personnalisée pour le rendu des encarts. Les blocs d'encarts sont indiqués en utilisant une paire de triples points `:::` pour envelopper votre contenu, et peuvent être de type `note`, `tip`, `caution` ou `danger`. + +Vous pouvez imbriquer n'importe quel autre type de contenu Markdown à l'intérieur d'un encart, mais les encarts sont mieux adaptés à des morceaux de contenu courts et concis. + +### Encart de type note + +:::note +Starlight est une boîte à outils pour sites web de documentation construite avec [Astro](https://astro.build/). Vous pouvez démarrer avec cette commande : + +```sh +npm run create astro@latest --template starlight +``` + +::: + +````md +:::note +Starlight est une boîte à outils pour sites web de documentation construite avec [Astro](https://astro.build/). Vous pouvez démarrer avec cette commande : + +```sh +npm run create astro@latest --template starlight +``` + +::: +```` + +### Titres d'encarts personnalisés + +Vous pouvez spécifier un titre personnalisé pour un encart entre crochets après le type d'encart, par exemple `:::tip[Le saviez-vous ?]`. + +:::tip[Le saviez-vous ?] +Astro vous aide à construire des sites Web plus rapides grâce à [« l'Architecture en îlots »](https://docs.astro.build/fr/concepts/islands/). +::: + +```md +:::tip[Le saviez-vous ?] +Astro vous aide à construire des sites Web plus rapides grâce à [« l'Architecture en îlots »](https://docs.astro.build/fr/concepts/islands/). +::: +``` + +### Icônes d'encarts personnalisées + +Vous pouvez spécifier une icône personnalisée pour un encart en utilisant des accolades après le type d'encart ou le [titre personnalisé](#titres-dencarts-personnalisés), par exemple `:::tip{icon="heart"}` ou `:::tip[Le saviez-vous ?]{icon="heart"}` respectivement. +Le nom de l'icône doit être défini avec le nom de [l'une des icônes intégrées à Starlight](/fr/reference/icons/#toutes-les-icônes). + +:::tip{icon="heart"} +Astro vous aide à construire des sites Web plus rapides grâce à [« l'Architecture en îlots »](https://docs.astro.build/fr/concepts/islands/). +::: + +```md +:::tip{icon="heart"} +Astro vous aide à construire des sites Web plus rapides grâce à [« l'Architecture en îlots »](https://docs.astro.build/fr/concepts/islands/). +::: +``` + +### Plus de types d'encarts + +Les encarts de type Attention et Danger sont utiles pour attirer l'attention de l'utilisateur sur des détails qui pourraient le perturber. Si vous vous retrouvez à utiliser ces derniers fréquemment, cela pourrait aussi être un signe que ce que vous documentez pourrait bénéficier d'une refonte. + +:::caution +Si vous n'êtes pas sûr de vouloir un site de documentation génial, réfléchissez à deux fois avant d'utiliser [Starlight](/fr/). +::: + +:::danger +Vos utilisateurs peuvent être plus productifs et trouver votre produit plus facile à utiliser grâce aux fonctionnalités utiles de Starlight. + +- Navigation claire +- Thème de couleurs configurable par l'utilisateur +- [Prise en charge i18n](/fr/guides/i18n/) + +::: + +```md +:::caution +Si vous n'êtes pas sûr de vouloir un site de documentation génial, réfléchissez à deux fois avant d'utiliser [Starlight](/fr/). +::: + +:::danger +Vos utilisateurs peuvent être plus productifs et trouver votre produit plus facile à utiliser grâce aux fonctionnalités utiles de Starlight. + +- Navigation claire +- Thème de couleurs configurable par l'utilisateur +- [Prise en charge i18n](/fr/guides/i18n/) + +::: +``` + +## Blocs de citation + +> Il s'agit d'un bloc de citation, couramment utilisé pour citer une autre personne ou un document. +> +> Les blocs de citation sont indiqués par un `>` au début de chaque ligne. + +```md +> Il s'agit d'un bloc de citation, couramment utilisé pour citer une autre personne ou un document. +> +> Les blocs de citation sont indiqués par un `>` au début de chaque ligne. +``` + +## Blocs de code + +Un bloc de code est indiqué par un bloc avec trois accents graves <code>```</code> au début et à la fin. Vous pouvez indiquer le langage de programmation utilisé après les premiers accents graves. + +```js +// Code Javascript avec coloration syntaxique. +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` + +````md +```js +// Code Javascript avec coloration syntaxique. +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` +```` + +### Fonctionnalités d'Expressive Code + +Starlight utilise [Expressive Code](https://expressive-code.com/) pour étendre les possibilités de formatage des blocs de code. +Les modules d'extension Expressive Code de marqueurs de texte et de cadres de fenêtre sont activés par défaut. +L'affichage des blocs de code peut être configuré à l'aide de [l'option de configuration `expressiveCode`](/fr/reference/configuration/#expressivecode) de Starlight. + +#### Marqueurs de texte + +Vous pouvez mettre en évidence des lignes ou des portions spécifiques de vos blocs de code à l'aide des [marqueurs de texte d'Expressive Code](https://expressive-code.com/key-features/text-markers/) sur la première ligne de votre bloc de code. +Utilisez des accolades (`{ }`) pour mettre en évidence des lignes entières, et des guillemets pour mettre en évidence des chaînes de texte. + +Il existe trois styles de mise en évidence : neutre pour attirer l'attention sur le code, vert pour indiquer du code inséré, et rouge pour indiquer du code supprimé. +Du texte et des lignes entières peuvent être marqués à l'aide du marqueur par défaut, ou en combinaison avec `ins=` et `del=` pour produire la mise en évidence souhaitée. + +Expressive Code fournit plusieurs options pour personnaliser l'apparence visuelle de vos exemples de code. +Beaucoup d'entre elles peuvent être combinées pour obtenir des exemples de code très illustratifs. +Veuillez explorer la [documentation d'Expressive Code](https://expressive-code.com/key-features/text-markers/#configuration) pour obtenir une liste complète des options disponibles. +Certaines des options les plus courantes sont présentées ci-dessous : + +- [Marquer des lignes entières et des plages de lignes à l'aide du marqueur `{ }`](https://expressive-code.com/key-features/text-markers/#marking-full-lines--line-ranges) : + + ```js {2-3} + function demo() { + // Cette ligne (#2) et la suivante sont mises en évidence + return 'Ceci est la ligne #3 de cet exemple'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js {2-3} + function demo() { + // Cette ligne (#2) et la suivante sont mises en évidence + return 'Ceci est la ligne #3 de cet exemple'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="{2-3}" %} + function demo() { + // Cette ligne (#2) et la suivante sont mises en évidence + return 'Ceci est la ligne #3 de cet exemple'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [Marquer des sélections de texte à l'aide du marqueur `" "` ou d'expressions régulières](https://expressive-code.com/key-features/text-markers/#marking-individual-text-inside-lines) : + + ```js "termes individuels" /Même.*charge/ + // Des termes individuels peuvent également être mis en évidence + function demo() { + return 'Même les expressions régulières sont prises en charge'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "termes individuels" /Même.*charge/ + // Des termes individuels peuvent également être mis en évidence + function demo() { + return 'Même les expressions régulières sont prises en charge'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'termes individuels' /Même.*charge/" %} + // Des termes individuels peuvent également être mis en évidence + function demo() { + return 'Même les expressions régulières sont prises en charge'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [Marquer du texte ou des lignes comme insérés ou supprimés avec `ins` ou `del`](https://expressive-code.com/key-features/text-markers/#selecting-inline-marker-types-mark-ins-del) : + + ```js "return true;" ins="insertion" del="suppression" + function demo() { + console.log("Voici des marqueurs d'insertion et de suppression"); + // La déclaration return utilise le type de marqueur par défaut + return true; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "return true;" ins="insertion" del="suppression" + function demo() { + console.log("Voici des marqueurs d'insertion et de suppression"); + // La déclaration return utilise le type de marqueur par défaut + return true; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'return true;' ins='insertion' del='suppression'" %} + function demo() { + console.log("Voici des marqueurs d'insertion et de suppression"); + // La déclaration return utilise le type de marqueur par défaut + return true; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [Combiner coloration syntaxique et syntaxe de type `diff`](https://expressive-code.com/key-features/text-markers/#combining-syntax-highlighting-with-diff-like-syntax) : + + ```diff lang="js" + function ceciEstDuJavaScript() { + // Ce bloc entier utilise la coloration syntaxique JavaScript, + // et nous pouvons toujours y ajouter des marqueurs de différence ! + - console.log('Ancien code à supprimer') + + console.log('Nouveau code brillant !') + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```diff lang="js" + function ceciEstDuJavaScript() { + // Ce bloc entier utilise la coloration syntaxique JavaScript, + // et nous pouvons toujours y ajouter des marqueurs de différence ! + - console.log('Ancien code à supprimer') + + console.log('Nouveau code brillant !') + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```diff {% meta="lang='js'" %} + function ceciEstDuJavaScript() { + // Ce bloc entier utilise la coloration syntaxique JavaScript, + // et nous pouvons toujours y ajouter des marqueurs de différence ! + - console.log('Ancien code à supprimer') + + console.log('Nouveau code brillant !') + } + ``` + ```` + + </TabItem> + + </Tabs> + +#### Cadres et titres + +Les blocs de code peuvent être affichés dans un cadre ressemblant à une fenêtre. +Un cadre ressemblant à une fenêtre de terminal sera utilisé pour les langages de script shell (par exemple `bash` ou `sh`). +Les autres langages s'affichent dans un cadre de style éditeur de code s'ils incluent un titre. + +Le titre optionnel d'un bloc de code peut être défini soit avec un attribut `title="..."` après les accents graves d'ouverture et l'identifiant de langage, ou avec un nom de fichier en commentaire sur la première ligne du bloc de code. + +- [Ajouter un nom de fichier avec un commentaire](https://expressive-code.com/key-features/frames/#code-editor-frames) : + + ```js + // mon-fichier-de-test.js + console.log('Hello World!'); + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js + // mon-fichier-de-test.js + console.log('Hello World!'); + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````md + ```js + // mon-fichier-de-test.js + console.log('Hello World!'); + ``` + ```` + + </TabItem> + + </Tabs> + +- [Ajouter un titre à une fenêtre de terminal](https://expressive-code.com/key-features/frames/#terminal-frames) : + + ```bash title="Installation des dépendances…" + npm install + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash title="Installation des dépendances…" + npm install + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% title="Installation des dépendances…" %} + npm install + ``` + ```` + + </TabItem> + + </Tabs> + +- [Désactiver les cadres de fenêtre avec `frame="none"`](https://expressive-code.com/key-features/frames/#overriding-frame-types) : + + ```bash frame="none" + echo "Ceci n'est pas affiché comme un terminal malgré l'utilisation du langage bash" + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash frame="none" + echo "Ceci n'est pas affiché comme un terminal malgré l'utilisation du langage bash" + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% frame="none" %} + echo "Ceci n'est pas affiché comme un terminal malgré l'utilisation du langage bash" + ``` + ```` + + </TabItem> + + </Tabs> + +## Détails + +Détails (également connus comme « divulgations » ou « accordéons ») sont utiles pour masquer du contenu qui n'est pas immédiatement pertinent. +Les utilisateurs peuvent cliquer sur un court résumé pour développer et afficher le contenu complet. + +Utilisez les éléments HTML standard [`<details>`](https://developer.mozilla.org/fr/docs/Web/HTML/Element/details) et [`<summary>`](https://developer.mozilla.org/fr/docs/Web/HTML/Element/summary) dans votre contenu Markdown pour créer un widget de divulgation. + +Vous pouvez imbriquer n'importe quelle autre syntaxe Markdown à l'intérieur d'un élément `<details>`. + +<details> +<summary>Où et quand la constellation d'Andromède est-elle la plus visible ?</summary> + +La [constellation d'Andromède](<https://fr.wikipedia.org/wiki/Androm%C3%A8de_(constellation)>) est la plus visible dans le ciel nocturne pendant le mois de novembre aux latitudes comprises entre `+90°` et `−40°`. + +</details> + +```md +<details> +<summary>Où et quand la constellation d'Andromède est-elle la plus visible ?</summary> + +La [constellation d'Andromède](<https://fr.wikipedia.org/wiki/Androm%C3%A8de_(constellation)>) est la plus visible dans le ciel nocturne pendant le mois de novembre aux latitudes comprises entre `+90°` et `−40°`. + +</details> +``` + +## Notes de bas de page + +Les [notes de bas de page](https://www.markdownguide.org/extended-syntax/#footnotes) sont utiles pour ajouter de brèves références ou des précisions sans interrompre la lecture. Elles se présentent sous forme de liens numérotés en exposant qui permettent d'accéder au texte référencé, regroupé en bas de page. + +Définissez une note de bas de page à l'aide de crochets contenant un accent circonflexe et une référence numérotée : + +```md +Voici une note de bas de page[^1] avec un texte complémentaire après. + +[^1]: Ma référence. +``` + +## Autres fonctionnalités courantes de Markdown + +Starlight prend en charge toutes les autres syntaxes de rédaction Markdown, telles que les listes et les tableaux. Voir [Markdown Cheat Sheet from The Markdown Guide](https://www.markdownguide.org/cheat-sheet/) pour un aperçu rapide de tous les éléments de la syntaxe Markdown. + +## Configuration avancée de Markdown et MDX + +Starlight utilise le moteur de rendu Markdown et MDX d'Astro basé sur remark et rehype. Vous pouvez ajouter la prise en charge de syntaxe et comportement personnalisés en ajoutant `remarkPlugins` ou `rehypePlugins` dans votre fichier de configuration Astro. Pour en savoir plus, consultez [« Modules d’extension Markdown »](https://docs.astro.build/fr/guides/markdown-content/#modules-dextension-markdown) dans la documentation d'Astro. + +## Markdoc + +Starlight prend en charge la création de contenu en Markdoc en utilisant l'intégration expérimentale [Astro Markdoc](https://docs.astro.build/fr/guides/integrations-guide/markdoc/) et le préréglage Markdoc de Starlight. + +### Créer un nouveau projet avec Markdoc + +Créez un nouveau projet Starlight avec Markdoc préconfiguré en utilisant `create astro` : + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight/markdoc +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight/markdoc +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight/markdoc +``` + +</TabItem> +</Tabs> + +### Ajouter Markdoc à un projet existant + +Si vous disposez déjà d'un site Starlight et que vous souhaitez ajouter Markdoc, suivez ces étapes. + +<Steps> + +1. Ajoutez l'intégration Markdoc d'Astro : + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npx astro add markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm astro add markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn astro add markdoc + ``` + + </TabItem> + + </Tabs> + +2. Installez le préréglage Markdoc de Starlight : + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-markdoc + ``` + + </TabItem> + + </Tabs> + +3. Créez une configuration Markdoc dans le fichier `markdoc.config.mjs` et utilisez le préréglage Markdoc de Starlight : + + ```js + import { defineMarkdocConfig } from '@astrojs/markdoc/config'; + import starlightMarkdoc from '@astrojs/starlight-markdoc'; + + export default defineMarkdocConfig({ + extends: [starlightMarkdoc()], + }); + ``` + +</Steps> + +Pour en savoir plus sur la syntaxe et les fonctionnalités de Markdoc, consultez la [documentation Markdoc](https://markdoc.dev/docs/syntax) ou le [guide de l'intégration Astro Markdoc](https://docs.astro.build/fr/guides/integrations-guide/markdoc/). + +### Configuration du préréglage Markdoc + +Le préréglage `starlightMarkdoc()` accepte les options de configuration suivantes : + +#### `headingLinks` + +**Type :** `boolean` +**Par défaut :** `true` + +Contrôle si les en-têtes sont affichés avec des liens d'ancrage cliquables ou non. +Équivaut à l'option [`markdown.headingLinks`](/fr/reference/configuration/#markdown) qui s'applique aux fichiers Markdown et MDX. + +```js "headingLinks: false" +export default defineMarkdocConfig({ + // Désactive les liens d'ancrage par défaut pour les en-têtes + extends: [starlightMarkdoc({ headingLinks: false })], +}); +``` diff --git a/docs/src/content/docs/fr/guides/components.mdx b/docs/src/content/docs/fr/guides/components.mdx deleted file mode 100644 index 23761d9deef..00000000000 --- a/docs/src/content/docs/fr/guides/components.mdx +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Composants -description: Utilisation de composants dans MDX avec Starlight. ---- - -Les composants vous permettent de réutiliser facilement un élément d'interface utilisateur ou de style de manière cohérente. -Il peut s'agir par exemple d'une carte de lien ou d'une intégration YouTube. -Starlight prend en charge l'utilisation de composants dans les fichiers [MDX](https://mdxjs.com/) et fournit des composants courants que vous pouvez utiliser. - -[Pour en savoir plus sur la création de composants, consultez les Astro Docs](https://docs.astro.build/fr/core-concepts/astro-components/). - -## Utilisation d'un composant - -Vous pouvez utiliser un composant en l'important dans votre fichier MDX et en le rendant sous forme de balise JSX. -Ces balises ressemblent à des balises HTML mais commencent par une lettre majuscule correspondant au nom de votre déclaration `import` : - -```mdx ---- -# src/content/docs/index.mdx -title: Bienvenue dans ma documentation ---- - -import SomeComponent from '../../components/SomeComponent.astro'; -import AnotherComponent from '../../components/AnotherComponent.astro'; - -<SomeComponent prop="something" /> - -<AnotherComponent> - Les composants peuvent également contenir du **contenu imbriqué**. -</AnotherComponent> -``` - -Starlight étant alimenté par Astro, vous pouvez ajouter la prise en charge des composants construits avec n'importe quel [cadre d'interface utilisateur pris en charge (React, Preact, Svelte, Vue, Solid, Lit et Alpine)](https://docs.astro.build/fr/core-concepts/framework-components/) dans vos fichiers MDX. -Pour en savoir plus sur [l'utilisation de composants dans MDX](https://docs.astro.build/fr/guides/markdown-content/#using-components-in-mdx), consultez la documentation Astro. - -### Compatibilité avec les styles de Starlight - -Starlight applique des styles par défaut à votre contenu Markdown, par exemple en ajoutant une marge entre les éléments. -Si ces styles entrent en conflit avec l'apparence de votre composant, définissez la classe `not-content` sur votre composant pour les désactiver. - -```astro ---- -// src/components/Example.astro ---- - -<div class="not-content"> - <p>Contenu non affecté par les styles par défaut de Starlight.</p> -</div> -``` - -## Composants intégrés - -Starlight fournit quelques composants intégrés pour les cas d'utilisation courants de la documentation. -Ces composants sont disponibles dans le paquet `@astrojs/starlight/components`. - -### Onglets - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -Vous pouvez afficher une interface à onglets en utilisant les composants `<Tabs>` et `<TabItem>`. -Chaque `<TabItem>` doit avoir un `label` à afficher aux utilisateurs. - -```mdx -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -<Tabs> - <TabItem label="Stars">Sirius, Vega, Betelgeuse</TabItem> - <TabItem label="Moons">Io, Europa, Ganymede</TabItem> -</Tabs> -``` - -Le code ci-dessus génère les onglets suivants sur la page : - -<Tabs> - <TabItem label="Stars">Sirius, Vega, Betelgeuse</TabItem> - <TabItem label="Moons">Io, Europa, Ganymede</TabItem> -</Tabs> - -### Cartes - -import { Card, CardGrid } from '@astrojs/starlight/components'; - -Vous pouvez afficher du contenu dans une boîte correspondant aux styles de Starlight en utilisant le composant `<Card>`. -Enveloppez plusieurs cartes dans le composant `<CardGrid>` pour afficher les cartes côte à côte lorsqu'il y a suffisamment d'espace. - -Une `<Card>` nécessite un `title` et peut optionellement inclure un attribut `icon` fixé au nom de [l'une des icônes intégrées de Starlight](#toutes-les-icônes). - -```mdx -import { Card, CardGrid } from '@astrojs/starlight/components'; - -<Card title="Check this out"> - Contenu intéressant que vous souhaitez mettre en évidence. -</Card> - -<CardGrid> - <Card title="Stars" icon="star"> - Sirius, Vega, Betelgeuse - </Card> - <Card title="Moons" icon="moon"> - Io, Europa, Ganymede - </Card> -</CardGrid> -``` - -Le code ci-dessus génère ce qui suit sur la page : - -<Card title="Check this out"> - Contenu intéressant que vous souhaitez mettre en évidence. -</Card> - -<CardGrid> - <Card title="Stars" icon="star"> - Sirius, Vega, Betelgeuse - </Card> - <Card title="Moons" icon="moon"> - Io, Europa, Ganymede - </Card> -</CardGrid> - -:::tip -Utilisez une grille de cartes sur votre page d'accueil pour afficher les principales caractéristiques de votre projet. -Ajoutez l'attribut `stagger` pour décaler verticalement la deuxième colonne de cartes et ajouter un intérêt visuel : - -```astro -<CardGrid stagger> - <!-- cards --> -</CardGrid> -``` - -::: - -### Cartes de Liaison - -Utilisez le composant `<LinkCard>` pour créer un lien bien visible vers différentes pages. - -Une `<LinkCard>` nécessite les attributs `title` et [`href`](https://developer.mozilla.org/fr/docs/Web/HTML/Element/a#href). Vous pouvez optionellement inclure une courte `description` ou d'autres attributs de lien tels que `target`. - -Regroupez plusieurs composants `<LinkCard>` dans `<CardGrid>` pour afficher les cartes côte à côte lorsqu'il y a suffisamment d'espace. - -```mdx -import { LinkCard, CardGrid } from '@astrojs/starlight/components'; - -<LinkCard - title="Personnalisation de Starlight" - description="Apprenez à personnaliser votre site Starlight avec vos propres styles, vos polices et bien plus encore." - href="/fr/guides/customization/" -/> - -<CardGrid> - <LinkCard - title="Création de contenu en Markdown" - href="/fr/guides/authoring-content/" - /> - <LinkCard title="Composants" href="/fr/guides/components/" /> -</CardGrid> -``` - -Le code ci-dessus génère ce qui suit sur la page : - -import { LinkCard } from '@astrojs/starlight/components'; - -<LinkCard - title="Personnaliser Starlight" - description="Apprenez à personnaliser votre site Starlight avec vos propres styles, vos polices et bien plus encore." - href="/fr/guides/customization/" -/> - -<CardGrid> - <LinkCard - title="Création de contenu en Markdown" - href="/fr/guides/authoring-content/" - /> - <LinkCard title="Composants" href="/fr/guides/components/" /> -</CardGrid> - -### Icônes - -import { Icon } from '@astrojs/starlight/components'; -import IconsList from '../../../../components/icons-list.astro'; - -Starlight fournit un ensemble d'icônes courantes que vous pouvez afficher dans votre contenu à l'aide du composant `<Icon>`. - -Chaque `<Icon>` nécessite un [`name`](#toutes-les-icônes) et peut optionellement inclure un attribut `label`, `size` et `color`. - -```mdx -import { Icon } from '@astrojs/starlight/components'; - -<Icon name="star" color="goldenrod" size="2rem" /> -``` - -Le code ci-dessus génère ce qui suit sur la page : - -<Icon name="star" color="goldenrod" size="2rem" /> - -#### Toutes les icônes - -Une liste de toutes les icônes disponibles est affichée ci-dessous avec leurs noms associés. Cliquez sur une icône pour copier le code du composant. - -<IconsList /> diff --git a/docs/src/content/docs/fr/guides/css-and-tailwind.mdx b/docs/src/content/docs/fr/guides/css-and-tailwind.mdx index e1df3e4dcba..f2811b077da 100644 --- a/docs/src/content/docs/fr/guides/css-and-tailwind.mdx +++ b/docs/src/content/docs/fr/guides/css-and-tailwind.mdx @@ -3,12 +3,18 @@ title: CSS et mise en forme description: Apprendre à mettre en forme votre site Starlight avec du CSS personnalisé ou l'intégrer avec Tailwind CSS. --- +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + Vous pouvez mettre en forme votre site Starlight avec du CSS personnalisé ou utiliser le module d'extension Tailwind de Starlight. +Pour changer rapidement l'apparence par défaut de votre site, consultez les [thèmes communautaires](/fr/resources/themes/). + ## Styles CSS personnalisés Personnalisez les styles appliqués à votre site Starlight en fournissant des fichiers CSS supplémentaires pour modifier ou étendre les styles par défaut de Starlight. +<Steps> + 1. Ajoutez un fichier CSS à votre répertoire `src/`. Par exemple, vous pouvez définir une largeur de colonne par défaut plus large et une taille de texte plus grande pour les titres de page : @@ -22,7 +28,7 @@ Personnalisez les styles appliqués à votre site Starlight en fournissant des f 2. Ajoutez le chemin vers votre fichier CSS au tableau `customCss` de Starlight dans votre configuration `astro.config.mjs` : - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -32,34 +38,50 @@ Personnalisez les styles appliqués à votre site Starlight en fournissant des f starlight({ title: 'Documentation avec CSS personnalisé', customCss: [ - // Chemin relatif vers votre fichier CSS personnalisé - './src/styles/custom.css', + + // Chemin relatif vers votre fichier CSS personnalisé + + './src/styles/custom.css', ], }), ], }); ``` +</Steps> + Vous pouvez retrouver toutes les propriétés CSS personnalisées utilisées par Starlight que vous pouvez définir pour personnaliser votre site dans le fichier [`props.css` sur GitHub](https://github.com/withastro/starlight/blob/main/packages/starlight/style/props.css). +### Couche de cascade + +Starlight utilise [les couches de cascade](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers) en interne pour gérer l'ordre de ses styles. +Cela garantit un ordre CSS prévisible et permet des redéfinitions plus simples. +N'importe quel CSS personnalisé ne faisant pas partie d'une couche de cascade redéfinira les styles par défaut de Starlight. + +Si vous utilisez des couches de cascade, vous pouvez utiliser [`@layer`](https://developer.mozilla.org/fr/docs/Web/CSS/@layer) dans votre CSS personnalisé pour définir l'ordre de priorité pour différentes couches par rapport aux styles de la couche `starlight` : + +```css "starlight" +/* src/styles/custom.css */ +@layer ma-reinitialisation, starlight, mes-redefinitions; +``` + +L'exemple ci-dessus définit une couche personnalisée nommée `ma-reinitialisation`, appliquée avant toutes les couches de Starlight, et une autre nommée `mes-redefinitions`, appliquée après toutes les couches de Starlight. +N'importe quel style dans la couche `mes-redefinitions` aurait priorité sur les styles de Starlight, mais Starlight pourrait toujours changer les styles définis dans la couche `ma-reinitialisation`. + ## Tailwind CSS -Le support de Tailwind CSS dans les projets Astro est fourni par [l'intégration Astro pour Tailwind](https://docs.astro.build/en/guides/integrations-guide/tailwind/). -Starlight fournit un module d'extension Tailwind complémentaire pour aider à configurer Tailwind pour une meilleure compatibilité avec les styles de Starlight. +La prise en charge de Tailwind CSS v4 dans les projets Astro est fourni par le [module d'extension Vite pour Tailwind](https://tailwindcss.com/docs/installation/using-vite). +Starlight fournit du CSS additionnel pour aider à configurer Tailwind pour une compatibilité avec les styles de Starlight. -Le module d'extension Tailwind de Starlight applique la configuration suivante : +Le CSS Tailwind de Starlight applique la configuration suivante : - Configure les variantes `dark:` de Tailwind pour fonctionner avec le mode sombre de Starlight. - Utilise les [couleurs et polices de thème](#mettre-en-forme-starlight-avec-tailwind) de Tailwind dans l'interface utilisateur de Starlight. -- Désactive les styles de réinitialisation [Preflight](https://tailwindcss.com/docs/preflight) de Tailwind tout en restaurant sélectivement les parties essentielles de Preflight requises pour les classes utilitaires de bordure de Tailwind. +- Restaure des parties essentielles des styles de réinitialisation Preflight de Tailwind. ### Créer un nouveau projet avec Tailwind -import { Tabs, TabItem } from '@astrojs/starlight/components'; +Démarrez un nouveau projet Starlight avec Tailwind CSS préconfiguré en utilisant `create astro` : -Démarrez un nouveau projet Starlight avec Tailwind CSS préconfiguré en utilisant `create astro` : - -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh @@ -87,9 +109,11 @@ yarn create astro --template starlight/tailwind Si vous avez déjà un site Starlight et que vous souhaitez ajouter Tailwind CSS, suivez ces étapes. -1. Ajoutez l'intégration Astro pour Tailwind : +<Steps> + +1. Initialisez Tailwind dans votre projet en exécutant la commande suivante et en suivant les instructions dans votre terminal : - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -117,9 +141,9 @@ Si vous avez déjà un site Starlight et que vous souhaitez ajouter Tailwind CSS </Tabs> -2. Installez le module d'extension Tailwind de Starlight : +2. Installez le paquet de compatibilité Tailwind de Starlight : - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -132,7 +156,7 @@ Si vous avez déjà un site Starlight et que vous souhaitez ajouter Tailwind CSS <TabItem label="pnpm"> ```sh - pnpm install @astrojs/starlight-tailwind + pnpm add @astrojs/starlight-tailwind ``` </TabItem> @@ -147,22 +171,27 @@ Si vous avez déjà un site Starlight et que vous souhaitez ajouter Tailwind CSS </Tabs> -3. Créez un fichier CSS pour les styles de base de Tailwind, par exemple dans `src/tailwind.css` : +3. Remplacez le contenu du fichier `src/styles/global.css` créé par Astro pour une compatibilité avec Starlight : ```css - /* src/tailwind.css */ - @tailwind base; - @tailwind components; - @tailwind utilities; + /* src/styles/global.css */ + @layer base, starlight, theme, components, utilities; + + @import '@astrojs/starlight-tailwind'; + @import 'tailwindcss/theme.css' layer(theme); + @import 'tailwindcss/utilities.css' layer(utilities); ``` -4. Mettez à jour votre fichier de configuration Astro pour utiliser vos styles de base de Tailwind et désactiver les styles de base par défaut : + Cette configuration de thème Tailwind définit l'ordre des [couches de cascade](#couche-de-cascade) de Starlight, importe le CSS complémentaire de Starlight pour Tailwind et importe les styles des thèmes et utilitaires de Tailwind. + Si votre projet nécessite une configuration Tailwind supplémentaire, consultez la section [« Utiliser plusieurs configurations Tailwind »](#utiliser-plusieurs-configurations-tailwind). + +4. Mettez à jour la configuration de Starlight pour ajouter le fichier CSS Tailwind en tant que premier élément du tableau `customCss` : - ```js {11-12,16-17} + ```js ins={11-12} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; - import tailwind from '@astrojs/tailwind'; + import tailwindcss from '@tailwindcss/vite'; export default defineConfig({ integrations: [ @@ -170,86 +199,122 @@ Si vous avez déjà un site Starlight et que vous souhaitez ajouter Tailwind CSS title: 'Documentation avec Tailwind', customCss: [ // Chemin vers vos style de base de Tailwind: - './src/tailwind.css', + './src/styles/global.css', ], }), - tailwind({ - // Désactive les styles de base par défaut: - applyBaseStyles: false, - }), ], + vite: { plugins: [tailwindcss()] }, }); ``` -5. Ajoutez le module d'extension Tailwind de Starlight au fichier `tailwind.config.cjs` : +</Steps> - ```js ins={2,7} - // tailwind.config.cjs - const starlightPlugin = require('@astrojs/starlight-tailwind'); +### Mettre en forme Starlight avec Tailwind - /** @type {import('tailwindcss').Config} */ - module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - plugins: [starlightPlugin()], - }; - ``` +Lors de la [création d'un nouveau projet Starlight avec Tailwind](#créer-un-nouveau-projet-avec-tailwind), ou lors de [l'ajout de Tailwind à un projet Starlight existant](#ajouter-tailwind-à-un-projet-existant), Starlight utilisera les valeurs de votre [configuration de thème Tailwind](https://tailwindcss.com/docs/theme) située dans le fichier `src/styles/global.css` pour mettre en forme son interface utilisateur. + +Si définies, les propriétés personnalisées CSS suivantes remplaceront les styles par défaut de Starlight : + +- `--color-accent-*` — utilisée pour les liens et la mise en évidence de l'élément courant +- `--color-gray-*` — utilisée pour les couleurs d'arrière-plan et les bordures +- `--font-sans` — utilisée pour le texte de l'interface utilisateur et du contenu +- `--font-mono` — utilisée pour les exemples de code + +```css {9-12,14-17,19-22,34-37} +/* src/styles/global.css */ +@layer base, starlight, theme, components, utilities; + +@import '@astrojs/starlight-tailwind'; +@import 'tailwindcss/theme.css' layer(theme); +@import 'tailwindcss/utilities.css' layer(utilities); + +@theme { + /* + Votre police de texte préférée. + Starlight utilise une pile de polices système par défaut. + */ + --font-sans: 'Atkinson Hyperlegible'; + /* + Votre police de code préférée. + Starlight utilise des polices système à chasse fixe par défaut. + */ + --font-mono: 'IBM Plex Mono'; + /* + Votre couleur d'accentuation préférée. + Indigo est la plus proche des valeurs par défaut de Starlight. + */ + --color-accent-50: var(--color-indigo-50); + --color-accent-100: var(--color-indigo-100); + --color-accent-200: var(--color-indigo-200); + --color-accent-300: var(--color-indigo-300); + --color-accent-400: var(--color-indigo-400); + --color-accent-500: var(--color-indigo-500); + --color-accent-600: var(--color-indigo-600); + --color-accent-700: var(--color-indigo-700); + --color-accent-800: var(--color-indigo-800); + --color-accent-900: var(--color-indigo-900); + --color-accent-950: var(--color-indigo-950); + /* + Votre échelle de gris préférée. + Zinc est la plus proche des valeurs par défaut de Starlight. + */ + --color-gray-50: var(--color-zinc-50); + --color-gray-100: var(--color-zinc-100); + --color-gray-200: var(--color-zinc-200); + --color-gray-300: var(--color-zinc-300); + --color-gray-400: var(--color-zinc-400); + --color-gray-500: var(--color-zinc-500); + --color-gray-600: var(--color-zinc-600); + --color-gray-700: var(--color-zinc-700); + --color-gray-800: var(--color-zinc-800); + --color-gray-900: var(--color-zinc-900); + --color-gray-950: var(--color-zinc-950); +} +``` -### Mettre en forme Starlight avec Tailwind +### Utiliser plusieurs configurations Tailwind -Starlight utilise les valeurs de votre [configuration de thème Tailwind](https://tailwindcss.com/docs/theme) dans son interface utilisateur. - -Si définies, les options suivantes remplaceront les styles par défaut de Starlight : - -- `colors.accent` — utilisé pour les liens et la mise en évidence de l'élément courant -- `colors.gray` — utilisé pour les couleurs d'arrière-plan et les bordures -- `fontFamily.sans` — utilisé pour le texte de l'interface utilisateur et du contenu -- `fontFamily.mono` — utilisé pour les exemples de code - -```js {13,16,21,24} -// tailwind.config.cjs -const starlightPlugin = require('@astrojs/starlight-tailwind'); -const colors = require('tailwindcss/colors'); - -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: { - colors: { - // Votre couleur d'accentuation préférée. - // Indigo est la plus proche des valeurs par défaut de Starlight. - accent: colors.indigo, - // Votre échelle de gris préférée. - // Zinc est la plus proche des valeurs par défaut de Starlight. - gray: colors.zinc, - }, - fontFamily: { - // Votre police de texte préférée. - // Starlight utilise une pile de polices système par défaut. - sans: ['"Atkinson Hyperlegible"'], - // Votre police de code préférée. - // Starlight utilise des polices système à chasse fixe par défaut. - mono: ['"IBM Plex Mono"'], - }, - }, - }, - plugins: [starlightPlugin()], -}; +Plusieurs configurations Tailwind peuvent être utilisées pour appliquer différents styles à différentes parties de votre site, par exemple lorsque vous [utilisez Starlight dans un sous-chemin](/fr/manual-setup/#utiliser-starlight-dans-un-sous-chemin) ou lorsque vous ajoutez des [pages personnalisées](/fr/guides/pages/#pages-personnalisées) à votre site. +Par exemple, vous souhaiterez peut-être utiliser les styles de réinitialisation Preflight de Tailwind dans vos pages personnalisées, tout en appliquant la couche de compatibilité de Starlight aux pages Starlight. + +La configuration Tailwind CSS suivante configure Tailwind sans aucun module d'extension ni configuration supplémentaire et peut être utilisée comme point de départ pour les pages non gérées par Starlight : + +```css title="src/styles/custom-pages-tailwind.css" +/* Charge Tailwind sans aucun CSS complémentaire provenant de Starlight. */ +@import 'tailwindcss'; ``` +<Steps> + +1. Pour les pages Starlight, appliquez votre configuration Tailwind CSS préférée en suivant [« Ajouter Tailwind à un projet existant »](#ajouter-tailwind-à-un-projet-existant). + +2. Pour les autres pages, appliquez votre configuration Tailwind CSS préférée en l'important dans ces pages. Cette opération est souvent effectuée dans un composant de mise en page afin que les styles de Tailwind puissent être utilisés sur toutes les pages partageant cette mise en page. + ```astro + --- + // src/layouts/CustomPageLayout.astro + import '../styles/custom-pages-tailwind.css'; + --- + ``` + +</Steps> + +Pour en savoir plus sur les configurations de thème Tailwind, consultez la [documentation de Tailwind CSS](https://tailwindcss.com/docs/theme). + ## Personnalisation du thème Le thème de couleur de Starlight peut être contrôlé en remplaçant ses propriétés personnalisées par défaut. Ces variables sont utilisées dans toute l'interface utilisateur avec une gamme de nuances de gris utilisées pour les couleurs de texte et d'arrière-plan et une couleur d'accentuation utilisée pour les liens et pour mettre en évidence les éléments courants durant la navigation. -### Editeur de thème de couleur +### Éditeur de thème de couleur -Utiliser les contrôles ci-dessous pour modifier les palettes de couleurs d'accentuation et de gris de Starlight. +Utilisez les contrôles ci-dessous pour modifier les palettes de couleurs d'accentuation et de gris de Starlight. Les zones d'aperçu sombre et clair afficheront les couleurs résultantes, et la page entière sera également mise à jour pour prévisualiser vos modifications. +Utilisez l'option Niveau de contraste pour spécifier lequel des [standards de contraste de couleur](https://developer.mozilla.org/fr/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast) des règles pour l’accessibilité des contenus Web à respecter. + Quand vous êtes satisfait de vos modifications, copiez le code CSS ou Tailwind ci-dessous et utilisez-le dans votre projet. -import ThemeDesigner from '../../../../components/theme-designer.astro'; +import ThemeDesigner from '~/components/theme-designer.astro'; <ThemeDesigner labels={{ @@ -262,6 +327,9 @@ import ThemeDesigner from '../../../../components/theme-designer.astro'; default: 'Par défaut', random: 'Aléatoire', }, + contrast: { + label: 'Niveau de contraste', + }, editor: { accentColor: 'Accentuation', grayColor: 'Gris', @@ -287,9 +355,8 @@ import ThemeDesigner from '../../../../components/theme-designer.astro'; site. </Fragment> <Fragment slot="tailwind-docs"> - Le fichier d'exemple de [configuration - Tailwind](#mettre-en-forme-starlight-avec-tailwind) ci-dessous inclut les - palettes de couleurs `accent` et `gray` générées à utiliser dans l'objet de - configuration `theme.extend.colors`. + Ajouter les propriétés personnalisées CSS suivantes au bloc `@theme` dans + votre [fichier CSS Tailwind](#mettre-en-forme-starlight-avec-tailwind) pour + appliquer ce thème à votre site. </Fragment> </ThemeDesigner> diff --git a/docs/src/content/docs/fr/guides/customization.mdx b/docs/src/content/docs/fr/guides/customization.mdx index 1185031c6d0..0bc4bccae81 100644 --- a/docs/src/content/docs/fr/guides/customization.mdx +++ b/docs/src/content/docs/fr/guides/customization.mdx @@ -3,8 +3,7 @@ title: Personnaliser Starlight description: Apprenez à vous approprier votre site Starlight avec votre logo, polices personnalisées et bien plus encore. --- -import { Tabs, TabItem } from '@astrojs/starlight/components'; -import FileTree from '../../../../components/file-tree.astro'; +import { Tabs, TabItem, FileTree, Steps } from '@astrojs/starlight/components'; Starlight propose par défaut un style et des fonctionnalités pragmatiques, vous pouvez donc démarrer rapidement sans configuration nécessaire. Lorsque vous souhaitez commencer à personnaliser l’apparence de votre site Starlight, ce guide vous accompagne. @@ -13,6 +12,8 @@ Lorsque vous souhaitez commencer à personnaliser l’apparence de votre site St L’ajout d’un logo personnalisé à l’en-tête du site est un moyen rapide d’ajouter votre image de marque personnelle à un site Starlight. +<Steps> + 1. Ajoutez votre fichier logo au répertoire `src/assets/` : <FileTree> @@ -25,9 +26,9 @@ L’ajout d’un logo personnalisé à l’en-tête du site est un moyen rapide </FileTree> -2. Ajoutez le chemin vers votre logo à votre option de configuration Starlight [`logo.src`](/reference/configuration/#logo) dans `astro.config.mjs`: +2. Ajoutez le chemin vers votre logo à votre option de configuration Starlight [`logo.src`](/fr/reference/configuration/#logo) dans `astro.config.mjs` : - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -37,18 +38,20 @@ L’ajout d’un logo personnalisé à l’en-tête du site est un moyen rapide starlight({ title: 'Docs Avec Mon Logo', logo: { - src: './src/assets/mon-logo.svg', + + src: './src/assets/mon-logo.svg', }, }), ], }); ``` +</Steps> + Par défaut, le logo sera affiché à côté du nom de votre site (option `title` dans la configuration). Si l’image de votre logo inclut déjà le titre du site, vous pouvez masquer visuellement le texte du titre en définissant l’option `replacesTitle` à `true`. Le texte du titre (`title`) le texte sera toujours inclus pour les lecteurs d’écran afin que l’en-tête reste accessible. -```js +```js {5} starlight({ title: 'Docs Avec Mon Logo', logo: { @@ -62,7 +65,9 @@ starlight({ Vous pouvez afficher différentes versions de votre logo en modes clair et sombre. -1. Ajouter un fichier image pour chaque variante dans `src/assets/`: +<Steps> + +1. Ajouter un fichier image pour chaque variante dans `src/assets/` : <FileTree> @@ -75,23 +80,25 @@ Vous pouvez afficher différentes versions de votre logo en modes clair et sombr </FileTree> -2. Ajouter les chemins vers vos variantes de logo dans les options `light` (clair) et `dark` (sombre) en remplacement de l’option `src` dans `astro.config.mjs`: +2. Ajouter les chemins vers vos variantes de logo dans les options `light` (clair) et `dark` (sombre) en remplacement de l’option `src` dans `astro.config.mjs` : - ```js + ```diff lang="js" starlight({ title: 'Docs Avec Mon Logo', logo: { - light: './src/assets/logo-clair.svg', - dark: './src/assets/logo-sombre.svg', + + light: './src/assets/logo-clair.svg', + + dark: './src/assets/logo-sombre.svg', }, }), ``` +</Steps> + ## Activer un plan de site -Starlight possède une prise en charge intégrée pour la génération d’un plan de site. Activez la génération du plan de site en définissant votre URL comme `site` dans `astro.config.mjs`: +Starlight possède une prise en charge intégrée pour la génération d’un plan de site. Activez la génération du plan de site en définissant votre URL comme `site` dans `astro.config.mjs` : -```js +```js {4} // astro.config.mjs export default defineConfig({ @@ -100,14 +107,16 @@ export default defineConfig({ }); ``` -## Mise en Page +Apprenez comment [ajouter un lien du plan de site au fichier `robots.txt`](https://docs.astro.build/fr/guides/integrations-guide/sitemap/#lien-vers-le-plan-du-site-dans-le-fichier-robotstxt) dans la documentation d'Astro. + +## Mise en page -Par défaut, les pages Starlight utilisent une mise en page avec une barre latérale de navigation globale et une table des matières qui affiche les titres de la page courante. +Par défaut, les pages Starlight utilisent une mise en page avec une barre latérale de navigation globale et une table des matières qui affiche les en-têtes de la page courante. -Vous pouvez appliquer une mise en page plus large sans barres latérales en définissant [`template: splash`](/reference/frontmatter/#template) dans le frontmatter de votre page. -Cela fonctionne particulièrement bien pour les pages d’atterissage et vous pouvez le voir en action sur la [page d’accueil de ce site](/). +Vous pouvez appliquer une mise en page plus large sans barres latérales en définissant [`template: splash`](/fr/reference/frontmatter/#template) dans le frontmatter de votre page. +Cela fonctionne particulièrement bien pour les pages d’atterissage et vous pouvez le voir en action sur la [page d’accueil de ce site](/fr/). -```md +```md {5} --- # src/content/docs/index.md @@ -121,14 +130,14 @@ template: splash Starlight affiche une table des matières sur chaque page pour permettre aux lecteurs d’accéder plus facilement à la section qu’ils recherchent. Vous pouvez personnaliser - ou même désactiver - la table des matières globalement dans l’intégration Starlight ou page par page dans votre frontmatter. -Par défaut, les titres `<h2>` et `<h3>` sont inclus dans la table des matières. Modifiez les niveaux de titres à inclure à l’échelle du site à l’aide des options `minHeadingLevel` et `maxHeadingLevel` dans votre option de configuration [globale `tableOfContents`](/reference/configuration/#tableofcontents). Remplacez ces valeurs par défaut sur une page individuelle en ajoutant les propriétés [frontmatter `tableOfContents`](/reference/frontmatter/#tableofcontents) correspondantes : +Par défaut, les en-têtes `<h2>` et `<h3>` sont inclus dans la table des matières. Modifiez les niveaux des en-têtes à inclure à l’échelle du site à l’aide des options `minHeadingLevel` et `maxHeadingLevel` dans votre option de configuration [globale `tableOfContents`](/fr/reference/configuration/#tableofcontents). Remplacez ces valeurs par défaut sur une page individuelle en ajoutant les propriétés [frontmatter `tableOfContents`](/fr/reference/frontmatter/#tableofcontents) correspondantes : -<Tabs> +<Tabs syncKey="config-type"> <TabItem label="Frontmatter"> -```md +```md {4-6} --- -# src/content/docs/example.md +# src/content/docs/exemple.md title: Page avec seulement les H2s dans la table des matières tableOfContents: minHeadingLevel: 2 @@ -139,13 +148,13 @@ tableOfContents: </TabItem> <TabItem label="Configuration globale"> -```js +```js {7} // astro.config.mjs defineConfig({ integrations: [ starlight({ - title: '', + title: 'Site avec une configuration de table des matières personnalisée', tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 2 }, }), ], @@ -155,14 +164,14 @@ defineConfig({ </TabItem> </Tabs> -Désactivez la table des matières complètement en définissant l’option `tableOfContents` à `false`: +Désactivez la table des matières complètement en définissant l’option `tableOfContents` à `false` : -<Tabs> +<Tabs syncKey="config-type"> <TabItem label="Frontmatter"> -```md +```md {4} --- -# src/content/docs/example.md +# src/content/docs/exemple.md title: Page sans table des matières tableOfContents: false --- @@ -171,7 +180,7 @@ tableOfContents: false </TabItem> <TabItem label="Configuration globale"> -```js +```js {7} // astro.config.mjs defineConfig({ @@ -189,12 +198,17 @@ defineConfig({ ## Liens sociaux -Starlight supporte par défaut l’ajout de liens vers vos comptes de médias sociaux dans l’en-tête du site via l’option [`social`](/reference/configuration/#social) dans l’intégration Starlight. +Starlight prend en charge par défaut l’ajout de liens vers vos comptes de médias sociaux dans l’en-tête du site via l’option [`social`](/fr/reference/configuration/#social) dans l’intégration Starlight. -Actuellement, les liens vers Bitbucket, Codeberg, Codepen, Discord, GitHub, GitLab, Gitter, Instagram, LinkedIn, Mastodon, Microsoft Teams, Stack Overflow, Threads, Twitch, Twitter et Youtube sont pris en charge. -Faites-nous savoir sur GitHub ou Discord si vous avez besoin de la prise en charge d’un autre service ! +Chaque entrée dans le tableau `social` doit être un objet avec trois propriétés : -```js +- `icon` : une des [icônes intégrées à Starlight](/fr/reference/icons/), par exemple `"github"`. +- `label` : une étiquette utilisée pour l’accessibilité, par exemple `"GitHub"`. +- `href` : l'URL du lien, par exemple `"https://github.com/withastro/starlight"`. + +L'exemple suivant ajoute des liens vers le Discord d'Astro et le dépôt GitHub de Starlight : + +```js {9-16} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -203,10 +217,14 @@ export default defineConfig({ integrations: [ starlight({ title: 'Site avec des liens sociaux', - social: { - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - }, + social: [ + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { + icon: 'github', + label: 'GitHub', + href: 'https://github.com/withastro/starlight', + }, + ], }), ], }); @@ -214,23 +232,23 @@ export default defineConfig({ ## Liens d’édition de page -Starlight peut afficher un lien "Modifier cette page" dans le pied de page de chaque page. +Starlight peut afficher un lien « Modifier cette page » dans le pied de page de chaque page. Cela permet au lecteur de trouver facilement le fichier à modifier pour améliorer vos documents. Pour les projets open source en particulier, cela peut aider à encourager les contributions de votre communauté. -Pour activer les liens de modification, définissez l’option de configuration [`editLink.baseUrl`](/reference/configuration/#editlink) en lui assignant l’URL utilisée pour modifier votre référentiel dans la configuration de l’intégration Starlight. +Pour activer les liens de modification, définissez l’option de configuration [`editLink.baseUrl`](/fr/reference/configuration/#editlink) en lui assignant l’URL utilisée pour modifier votre dépôt dans la configuration de l’intégration Starlight. La valeur de `editLink.baseUrl` sera automatiquement ajoutée au chemin d’accès vers la page actuelle pour former le lien d’édition complet. Les formes d’URL les plus courantes incluent : -- GitHub: `https://github.com/NOM_UTILISATEUR/NOM_DU_DEPOT/edit/NOM_DE_LA_BRANCHE/` -- GitLab: `https://gitlab.com/NOM_UTILISATEUR/NOM_DU_DEPOT/-/edit/NOM_DE_LA_BRANCHE/` +- GitHub : `https://github.com/NOM_UTILISATEUR/NOM_DU_DEPOT/edit/NOM_DE_LA_BRANCHE/` +- GitLab : `https://gitlab.com/NOM_UTILISATEUR/NOM_DU_DEPOT/-/edit/NOM_DE_LA_BRANCHE/` Si votre projet Starlight ne se trouve pas à la racine de votre dépôt, incluez le chemin d’accès au projet à la fin de l’URL de base. Cet exemple montre le lien d’édition configuré pour les documents Starlight, qui se trouvent dans le sous-répertoire `docs/` sur la branche `main` du dépôt `withastro/starlight` sur GitHub : -```js +```js {9-11} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -263,10 +281,11 @@ Vous pouvez personnaliser cela en ajoutant un fichier `404.md` (ou `404.mdx`) à </FileTree> -Vous pouvez utiliser toutes les techniques de mise en page et de personnalisation de Starlight dans votre page 404. Par exemple, la page 404 par défaut utilise la [mise en page `splash`](#mise-en-page) et le composant [`hero`](/reference/frontmatter/#hero) dans son frontmatter : +Vous pouvez utiliser toutes les techniques de mise en page et de personnalisation de Starlight dans votre page 404. Par exemple, la page 404 par défaut utilise la [mise en page `splash`](#mise-en-page) et le composant [`hero`](/fr/reference/frontmatter/#hero) dans son frontmatter : -```md +```md {4,6-8} --- +# src/content/docs/404.md title: '404' template: splash editUrl: false @@ -276,20 +295,41 @@ hero: --- ``` +### Désactiver la page 404 par défaut + +Si votre projet nécessite une mise en page entièrement personnalisée pour votre page 404, vous pouvez créer une route `src/pages/404.astro` et définir l'option de configuration [`disable404Route`](/fr/reference/configuration/#disable404route) pour désactiver la route par défaut de Starlight : + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Documentation avec 404 personnalisée', + disable404Route: true, + }), + ], +}); +``` + ## Polices personnalisées Par défaut, Starlight utilise des polices sans empattement disponibles en local sur la machine du visiteur pour tout les textes. Cela garantit que la documentation se charge rapidement dans une police familière à chaque utilisateur, sans nécessiter de bande passante supplémentaire pour télécharger des fichiers de police volumineux. -Si vous souhaitez ajouter une police personnalisée à votre site Starlight, vous pouvez configurer les polices à utiliser dans des fichiers CSS personnalisés ou avec toute autre [technique de style Astro](https://docs.astro.build/en/guides/styling/). +Si vous souhaitez ajouter une police personnalisée à votre site Starlight, vous pouvez configurer les polices à utiliser dans des fichiers CSS personnalisés ou avec toute autre [technique de style Astro](https://docs.astro.build/fr/guides/styling/). ### Configurer les polices -Si vous avez déjà des fichiers de polices, suivez le [guide de configuration local](#configurer-les-polices-localement). +Si vous avez déjà des fichiers de polices, suivez le [guide de configuration locale](#configurer-les-polices-localement). Pour utiliser Google Fonts, suivez le [Guide de configuration de Fontsource](#configurer-les-polices-avec-fontsource). #### Configurer les polices localement +<Steps> + 1. Ajoutez vos fichiers de polices dans un répertoire `src/fonts/` et créez un fichier `font-face.css` vide : <FileTree> @@ -321,7 +361,7 @@ Pour utiliser Google Fonts, suivez le [Guide de configuration de Fontsource](#co 3. Ajoutez le chemin de votre fichier `font-face.css` au tableau `customCss` de Starlight dans `astro.config.mjs` : - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -331,36 +371,60 @@ Pour utiliser Google Fonts, suivez le [Guide de configuration de Fontsource](#co starlight({ title: 'Site avec polices personnalisées', customCss: [ - // Chemin relatif vers votre fichier CSS @font-face. - '/src/fonts/font-face.css', + + // Chemin relatif vers votre fichier CSS @font-face. + + '/src/fonts/font-face.css', ], }), ], }); ``` +</Steps> + #### Configurer les polices avec Fontsource Le projet [Fontsource](https://fontsource.org/) simplifie l’utilisation des polices Google et d’autres polices open source. Il fournit des modules npm que vous pouvez installer pour les polices que vous souhaitez utiliser et inclut des fichiers CSS prêts à l’emploi à ajouter à votre projet. -1. Trouvez la police que vous souhaitez utiliser dans le [catalogue de Fontsource](https://fontsource.org/). Cet exemple utilisera [IBM Plex Serif](https://fontsource.org/fonts/ibm-plex-serif). +<Steps> -2. Installez le package pour la police choisie. Vous pouvez trouver le nom du package en cliquant sur "Installer" sur la page de police Fontsource. +1. Trouvez la police que vous souhaitez utiliser dans le [catalogue de Fontsource](https://fontsource.org/). + Cet exemple utilisera [IBM Plex Serif](https://fontsource.org/fonts/ibm-plex-serif). -<Tabs> - <TabItem label="npm"> - ```sh npm install @fontsource/ibm-plex-serif ``` - </TabItem> - <TabItem label="pnpm"> - ```sh pnpm install @fontsource/ibm-plex-serif ``` - </TabItem> - <TabItem label="Yarn">```sh yarn add @fontsource/ibm-plex-serif ```</TabItem> -</Tabs> +2. Installez le paquet pour la police choisie. + Vous pouvez trouver le nom du paquet en cliquant sur « Installer » sur la page de police Fontsource. + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @fontsource/ibm-plex-serif + ``` + + </TabItem> -3. Ajoutez les fichiers CSS Fontsource au tableau `customCss` de Starlight dans `astro.config.mjs` : + <TabItem label="pnpm"> - ```js + ```sh + pnpm add @fontsource/ibm-plex-serif + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @fontsource/ibm-plex-serif + ``` + + </TabItem> + + </Tabs> + +3. Ajoutez les fichiers CSS Fontsource au tableau `customCss` de Starlight dans `astro.config.mjs` : + + ```diff lang="js" // astro.config.mjs import { defineConfig } from "astro/config"; import starlight from "@astrojs/starlight"; @@ -370,9 +434,9 @@ Il fournit des modules npm que vous pouvez installer pour les polices que vous s starlight({ title: "Site avec polices personnalisées Fontsource", customCss: [ - // Fichiers Fontsource pour les graisses regular et semi-bold. - "@fontsource/ibm-plex-serif/400.css", - "@fontsource/ibm-plex-serif/600.css", + + // Fichiers Fontsource pour les graisses regular et semi-bold. + + "@fontsource/ibm-plex-serif/400.css", + + "@fontsource/ibm-plex-serif/600.css", ], }), ], @@ -381,10 +445,12 @@ Il fournit des modules npm que vous pouvez installer pour les polices que vous s Fontsource fournit plusieurs fichiers CSS pour chaque police. Consultez la [documentation Fontsource](https://fontsource.org/docs/getting-started/install#4-weights-and-styles) sur l’inclusion de différentes graisses et styles pour comprendre lesquels utiliser. +</Steps> + ### Utiliser vos polices personnalisées Une fois configurée, pour appliquer votre police personnalisée à votre site, utilisez le nom de la police que vous avez choisie dans un [fichier CSS personnalisé](/fr/guides/css-and-tailwind/#styles-css-personnalisés). -Par exemple, pour remplacer la police par défaut de Starlight partout, définissez la propriété personnalisée `--sl-font` : +Par exemple, pour remplacer la police par défaut de Starlight partout, définissez la propriété personnalisée `--sl-font` : ```css /* src/styles/custom.css */ @@ -395,7 +461,7 @@ Par exemple, pour remplacer la police par défaut de Starlight partout, définis ``` Vous pouvez également écrire du CSS plus ciblé si vous souhaitez appliquer votre police de manière plus sélective. -Par exemple, pour définir uniquement une police sur le contenu principal, mais pas sur les barres latérales : +Par exemple, pour définir uniquement une police sur le contenu principal, mais pas sur les barres latérales : ```css /* src/styles/custom.css */ diff --git a/docs/src/content/docs/fr/guides/i18n.mdx b/docs/src/content/docs/fr/guides/i18n.mdx index 7613f777c5b..fb965079d27 100644 --- a/docs/src/content/docs/fr/guides/i18n.mdx +++ b/docs/src/content/docs/fr/guides/i18n.mdx @@ -3,15 +3,17 @@ title: Internationalisation (i18n) description: Apprenez à configurer votre site Starlight pour qu'il prenne en charge plusieurs langues. --- -import FileTree from '../../../../components/file-tree.astro'; +import { FileTree, Steps } from '@astrojs/starlight/components'; Starlight offre une prise en charge intégrée des sites multilingues, y compris le routage, le contenu de repli et la prise en charge complète des langues de droite à gauche (RTL). ## Configurer i18n +<Steps> + 1. Indiquez à Starlight les langues que vous prenez en charge en passant [`locales`](/fr/reference/configuration/#locales) et [`defaultLocale`](/fr/reference/configuration/#defaultlocale) à l'intégration Starlight : - ```js + ```js {9-26} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -27,8 +29,8 @@ Starlight offre une prise en charge intégrée des sites multilingues, y compris en: { label: 'English', }, - // Docs en chinois simplifié dans `src/content/docs/zh/` - zh: { + // Docs en chinois simplifié dans `src/content/docs/zh-cn/` + 'zh-cn': { label: '简体中文', lang: 'zh-CN', }, @@ -55,7 +57,7 @@ Starlight offre une prise en charge intégrée des sites multilingues, y compris - docs/ - ar/ - en/ - - zh/ + - zh-cn/ </FileTree> @@ -63,13 +65,17 @@ Starlight offre une prise en charge intégrée des sites multilingues, y compris Par exemple, créez `ar/index.md` et `en/index.md` pour représenter la page d'accueil en arabe et en anglais respectivement. -### Utiliser une racine locale +</Steps> + +Pour les scénarios i18n plus avancés, Starlight prend également en compte la configuration de l'internationalisation à l'aide de l'option de [configuration `i18n` d'Astro](https://docs.astro.build/fr/guides/internationalization/#configurer-le-routage-i18n). + +### Utiliser une locale racine -Vous pouvez utiliser une “racine” locale pour servir une langue sans aucun préfixe i18n dans son chemin. Par exemple, si l'anglais est votre racine locale, le chemin d'une page en anglais ressemblera à `/about` au lieu de `/en/about`. +Vous pouvez utiliser une locale « racine » pour servir une langue sans aucun préfixe i18n dans son chemin. Par exemple, si l'anglais est votre locale racine, le chemin d'une page en anglais ressemblera à `/about` au lieu de `/en/about`. -Pour définir une racine locale, utilisez la clé `root` dans votre configuration `locales`. Si la racine locale est aussi la locale par défaut de votre contenu, supprimez `defaultLocale` ou donnez-lui la valeur `'root''. +Pour définir une locale racine, utilisez la clé `root` dans votre configuration `locales`. Si la locale racine est aussi la locale par défaut de votre contenu, supprimez `defaultLocale` ou donnez-lui la valeur `'root'`. -```js +```js {9,11-14} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -82,9 +88,9 @@ export default defineConfig({ locales: { root: { label: 'English', - lang: 'en', // lang est nécessaire pour les locales de la racine + lang: 'en', // lang est nécessaire pour les locales racine }, - zh: { + 'zh-cn': { label: '简体中文', lang: 'zh-CN', }, @@ -94,7 +100,7 @@ export default defineConfig({ }); ``` -Lorsque vous utilisez une locale `root`, gardez les pages pour cette langue directement dans `src/content/docs/` au lieu d'un dossier dédié à la langue. Par exemple, voici les fichiers de la page d'accueil pour l'anglais et le chinois en utilisant la configuration ci-dessus : +Lorsque vous utilisez une locale racine avec la clé `root`, conservez les pages de cette langue directement dans `src/content/docs/` au lieu d'un dossier dédié à cette langue. Par exemple, voici les fichiers de la page d'accueil pour l'anglais et le chinois en utilisant la configuration ci-dessus : <FileTree> @@ -102,7 +108,7 @@ Lorsque vous utilisez une locale `root`, gardez les pages pour cette langue dire - content/ - docs/ - **index.md** - - zh/ + - zh-cn/ - **index.md** </FileTree> @@ -111,7 +117,7 @@ Lorsque vous utilisez une locale `root`, gardez les pages pour cette langue dire Par défaut, Starlight est un site monolingue (anglais). Pour créer un site monolingue dans une autre langue, définissez-la comme `root` dans votre configuration `locales` : -```js +```diff lang="js" {10-13} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -135,28 +141,64 @@ Cela vous permet de remplacer la langue par défaut de Starlight sans activer d' ## Contenu de repli -Starlight s'attend à ce que vous créiez des pages équivalentes dans toutes vos langues. Par exemple, si vous avez un fichier `en/about.md`, créez un `about.md` pour chaque autre langue que vous supportez. Cela permet à Starlight de fournir un contenu de repli automatique pour les pages qui n'ont pas encore été traduites. +Starlight s'attend à ce que vous créiez des pages équivalentes dans toutes vos langues. Par exemple, si vous avez un fichier `en/about.md`, créez un `about.md` pour chaque autre langue que vous prenez en charge. Cela permet à Starlight de fournir un contenu de repli automatique pour les pages qui n'ont pas encore été traduites. Si une traduction n'est pas encore disponible pour une langue, Starlight affichera aux lecteurs le contenu de cette page dans la langue par défaut (définie via `defaultLocale`). Par exemple, si vous n'avez pas encore créé de version française de votre page À propos et que votre langue par défaut est l'anglais, les visiteurs de `/fr/about` verront le contenu anglais de `/en/about` avec un avis indiquant que cette page n'a pas encore été traduite. Cela vous permet d'ajouter du contenu dans votre langue par défaut et de le traduire progressivement lorsque vos traducteurs en ont le temps. +## Traduire le titre du site + +Par défaut, Starlight utilisera le même titre de site pour toutes les langues. +Si vous avez besoin de personnaliser le titre pour chaque langue, vous pouvez passer un objet à [`title`](/fr/reference/configuration/#title-obligatoire) dans les options de Starlight : + +```diff lang="js" +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ +- title: 'Ma documentation', ++ title: { ++ fr: 'Ma documentation', ++ 'zh-CN': '我的文档', ++ }, + defaultLocale: 'fr', + locales: { + fr: { label: 'Français' }, + 'zh-cn': { label: '简体中文', lang: 'zh-CN' }, + }, + }), + ], +}); +``` + ## Traduire l'interface utilisateur de Starlight -En plus d'héberger des fichiers de contenu traduits, Starlight vous permet de traduire les chaînes de l'interface utilisateur par défaut (par exemple, l'en-tête "Sur cette page" dans la table des matières) afin que vos lecteurs puissent découvrir votre site entièrement dans la langue sélectionnée. +import LanguagesList from '~/components/languages-list.astro'; +import UIStringsList from '~/components/ui-strings-list.astro'; + +En plus d'héberger des fichiers de contenu traduits, Starlight vous permet de traduire les chaînes de l'interface utilisateur par défaut (par exemple, l'en-tête « Sur cette page » dans la table des matières) afin que vos lecteurs puissent découvrir votre site entièrement dans la langue sélectionnée. + +Les textes de l'interface utilisateur traduits en <LanguagesList /> +sont disponibles prêts à l'emploi, et nous acceptons les +[contributions pour ajouter d'autres langues par défaut](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md). -Les textes de l'interface utilisateur traduits en anglais, arabe, allemand, chinois simplifié, danois, espagnol, français, italien, japonais, néerlandais, norvégien, farsi, hébreu, portugais, tchèque, turc, coréen, indonésien, russe et suédois sont disponibles prêts à l'emploi, et nous acceptons les [contributions pour ajouter d'autres langues par défaut](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md). +Vous pouvez fournir des traductions pour les langues supplémentaires que vous prenez en charge — ou remplacer nos étiquettes par défaut — via la collection de contenus `i18n`. -Vous pouvez fournir des traductions pour les langues supplémentaires que vous supportez - ou remplacer nos étiquettes par défaut - via la collection de données `i18n`. +<Steps> -1. Configurez la collection de données `i18n` dans `src/content/config.ts` si elle n'est pas déjà configurée : +1. Configurez la collection de contenus `i18n` dans `src/content.config.ts` si elle n'est pas déjà configurée : - ```js - // src/content/config.ts + ```diff lang="js" ins=/, (i18nLoader|i18nSchema)/ + // src/content.config.ts import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; export const collections = { - docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), }; ``` @@ -175,47 +217,194 @@ Vous pouvez fournir des traductions pour les langues supplémentaires que vous s 3. Ajoutez des traductions pour les clés que vous souhaitez traduire dans les fichiers JSON. Traduire uniquement les valeurs, en laissant les clés en anglais (e.g. `"search.label": "Buscar"`). - Il s'agit des valeurs anglaises par défaut des chaînes de caractères existantes avec lesquelles Starlight est livré : + Voici les valeurs anglaises par défaut des chaînes de caractères existantes avec lesquelles Starlight est livré : + + <UIStringsList /> + + Les blocs de code de Starlight fonctionnent grâce à la librairie [Expressive Code](https://expressive-code.com/). + Vous pouvez définir des traductions pour les textes de l'interface utilisateur utilisés dans le même fichier JSON en utilisant les clés `expressiveCode` : ```json { - "skipLink.label": "Aller au contenu", - "search.label": "Rechercher", - "search.shortcutLabel": "(Presser / pour rechercher)", - "search.cancelLabel": "Annuler", - "search.devWarning": "La recherche est disponible uniquement en mode production. \nEssayez de construire puis de prévisualiser votre site pour tester la recherche localement.", - "themeSelect.accessibleLabel": "Selectionner le thème", - "themeSelect.dark": "Sombre", - "themeSelect.light": "Clair", - "themeSelect.auto": "Auto", - "languageSelect.accessibleLabel": "Selectionner la langue", - "menuButton.accessibleLabel": "Menu", - "sidebarNav.accessibleLabel": "principale", - "tableOfContents.onThisPage": "Sur cette page", - "tableOfContents.overview": "Vue d’ensemble", - "i18n.untranslatedContent": "Ce contenu n’est pas encore disponible dans votre langue.", - "page.editLink": "Modifier cette page", - "page.lastUpdated": "Dernière mise à jour :", - "page.previousLink": "Précédent", - "page.nextLink": "Suivant", - "404.text": "Page non trouvée. Vérifiez l’URL ou essayez d’utiliser la barre de recherche." + "expressiveCode.copyButtonCopied": "Copied!", + "expressiveCode.copyButtonTooltip": "Copy to clipboard", + "expressiveCode.terminalWindowFallbackTitle": "Terminal window" } ``` - La module de recherche de Starlight’s est propulsé par la librairie [Pagefind](https://pagefind.app/). - Vous pouvez défiinr les tradctions pour l'interface de Pagefinddans le même fichier JSON file en utilisant les propriétés `pagefind` : + Le module de recherche de Starlight s’appuie sur la librairie [Pagefind](https://pagefind.app/). + Vous pouvez définir des traductions pour l’interface utilisateur de Pagefind dans le même fichier JSON en utilisant les clés `pagefind` : ```json { - "pagefind.clear_search": "Effacer", - "pagefind.load_more": "Charger plus de résultats", - "pagefind.search_label": "Rechercher sur ce site", - "pagefind.filters_label": "Filtres", - "pagefind.zero_results": "Pas de résultat pour [SEARCH_TERM]", - "pagefind.many_results": "[COUNT] resultats pour [SEARCH_TERM]", - "pagefind.one_result": "[COUNT] resultat pour [SEARCH_TERM]", - "pagefind.alt_search": "Pas de résultats pour [SEARCH_TERM]. Voici à la place des résultats pour [DIFFERENT_TERM].", - "pagefind.search_suggestion": "Pas de résultats pour [SEARCH_TERM]. Essayez l'une de ces recherches :", - "pagefind.searching": "Recherche en cours pour [SEARCH_TERM]..." + "pagefind.clear_search": "Clear", + "pagefind.load_more": "Load more results", + "pagefind.search_label": "Search this site", + "pagefind.filters_label": "Filters", + "pagefind.zero_results": "No results for [SEARCH_TERM]", + "pagefind.many_results": "[COUNT] results for [SEARCH_TERM]", + "pagefind.one_result": "[COUNT] result for [SEARCH_TERM]", + "pagefind.alt_search": "No results for [SEARCH_TERM]. Showing results for [DIFFERENT_TERM] instead", + "pagefind.search_suggestion": "No results for [SEARCH_TERM]. Try one of the following searches:", + "pagefind.searching": "Searching for [SEARCH_TERM]..." } ``` + + </Steps> + +### Étendre le schéma de traduction + +Ajoutez des clés personnalisées aux dictionnaires de traduction de votre site en définissant `extend` dans les options de `i18nSchema()`. +Dans l'exemple suivant, une nouvelle clé optionnelle `custom.label` est ajoutée aux clés par défaut : + +```diff lang="js" +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ ++ extend: z.object({ ++ 'custom.label': z.string().optional(), ++ }), + }), + }), +}; +``` + +Consultez [« Définir un schéma de collection de contenus »](https://docs.astro.build/fr/guides/content-collections/#définition-dun-schéma-de-collection) dans la documentation d'Astro pour en savoir plus sur les schémas de collection de contenus. + +## Utiliser les traductions de l'interface utilisateur + +Vous pouvez accéder aux [chaînes de l'interface utilisateur intégrées](/fr/guides/i18n/#traduire-linterface-utilisateur-de-starlight) à Starlight ainsi qu'aux chaînes de l'interface utilisateur [définies par l'utilisateur](/fr/guides/i18n/#étendre-le-schéma-de-traduction), et celles [fournies par les modules d'extension](/fr/reference/plugins/#injecttranslations) via une API unifiée utilisant [i18next](https://www.i18next.com/). +Cela inclut la prise en charge de fonctionnalités telles que [l'interpolation](https://www.i18next.com/translation-function/interpolation) et [la pluralisation](https://www.i18next.com/translation-function/plurals). + +Dans les composants Astro, cette API est disponible via l'[objet global `Astro`](https://docs.astro.build/fr/reference/api-reference/#astrolocals) sous le nom `Astro.locals.t` : + +```astro title="exemple.astro" +<p dir={Astro.locals.t.dir()}> + {Astro.locals.t('404.text')} +</p> +``` + +Vous pouvez également utiliser l'API dans les [points de terminaison](https://docs.astro.build/fr/guides/endpoints/), où l'objet `locals` est disponible dans le cadre du [contexte du point de terminaison](https://docs.astro.build/fr/reference/api-reference/#contextlocals) : + +```ts title="src/pages/404.ts" +export const GET = (context) => { + return new Response(context.locals.t('404.text')); +}; +``` + +Dans le contexte d'un module d'extension Starlight, vous pouvez utiliser l'utilitaire [`useTranslations()`](/fr/reference/plugins/#usetranslations) pour accéder à cette API pour une langue spécifique. +Consultez la [référence des modules d'extension](/fr/reference/plugins/) pour plus d'informations. + +### Afficher une chaîne de l'interface utilisateur + +Affichez une chaîne de l'interface utilisateur en utilisant la fonction `locals.t()`. +C'est une instance de la fonction `t()` d'i18next, qui prend une clé de chaîne d'interface utilisateur en premier argument et renvoie la traduction correspondante pour la langue actuelle. + +Par exemple, étant donné un fichier de traduction personnalisé avec le contenu suivant : + +```json title="src/content/i18n/fr.json" +{ + "link.astro": "Documentation d'Astro", + "link.astro.custom": "Documentation d'Astro pour {{feature}}" +} +``` + +La première chaîne d'interface utilisateur peut être affichée en passant `'link.astro'` à la fonction `t()` : + +```astro {3} +<!-- src/components/Exemple.astro --> +<a href="https://docs.astro.build/"> + {Astro.locals.t('link.astro')} +</a> +<!-- Affiche: <a href="...">Documentation d'Astro</a> --> +``` + +La deuxième chaîne d'interface utilisateur utilise la [syntaxe d'interpolation](https://www.i18next.com/translation-function/interpolation) d'i18next pour le paramètre `{{feature}}`. +La valeur de `feature` doit être définie dans un objet d'options passé en tant que deuxième argument à `t()` : + +```astro {3} +<!-- src/components/Exemple.astro --> +<a href="https://docs.astro.build/en/guides/astro-db/"> + {Astro.locals.t('link.astro.custom', { feature: 'Astro DB' })} +</a> +<!-- Affiche: <a href="...">Documentation d'Astro pour Astro DB</a> --> +``` + +Consultez la [documentation d'i18next](https://www.i18next.com/overview/api#t) pour plus d'informations sur l'utilisation de la fonction `t()` avec l'interpolation, le formatage, et plus encore. + +### APIs avancées + +#### `t.all()` + +La fonction `locals.t.all()` renvoie un objet contenant toutes les chaînes d'interface utilisateur disponibles pour la langue actuelle. + +```astro +--- +// src/components/Exemple.astro +const allStrings = Astro.locals.t.all(); +// ^ +// { +// "skipLink.label": "Aller au contenu", +// "search.label": "Rechercher", +// … +// } +--- +``` + +#### `t.exists()` + +Pour vérifier si une clé de traduction existe, utilisez la fonction `locals.t.exists()` avec la clé de traduction comme premier argument. +Passez un deuxième argument facultatif si vous avez besoin de vérifier qu'une traduction existe pour une langue spécifique. + +```astro +--- +// src/components/Exemple.astro +const keyExists = Astro.locals.t.exists('a.key'); +// ^ true +const keyExistsInFrench = Astro.locals.t.exists('other.key', { lngs: ['fr'] }); +// ^ false +--- +``` + +Consultez la [référence pour `exists()` dans la documentation d'i18next](https://www.i18next.com/overview/api#exists) pour plus d'informations. + +#### `t.dir()` + +La fonction `locals.t.dir()` renvoie la direction du texte de la langue actuelle ou d'une langue spécifique. + +```astro +--- +// src/components/Exemple.astro +const currentDirection = Astro.locals.t.dir(); +// ^ +// 'ltr' +const arabicDirection = Astro.locals.t.dir('ar'); +// ^ +// 'rtl' +--- +``` + +Consultez la [référence pour `dir()` dans la documentation d'i18next](https://www.i18next.com/overview/api#dir) pour plus d'informations. + +## Accès aux paramètres régionaux + +Vous pouvez utiliser [`Astro.currentLocale`](https://docs.astro.build/fr/reference/api-reference/#astrocurrentlocale) pour lire les paramètres régionaux et linguistiques actuels dans les composants `.astro`. + +L'exemple suivant lit les paramètres régionaux actuels et les utilise avec la fonction [`getRelativeLocaleUrl()`](https://docs.astro.build/fr/reference/modules/astro-i18n/#getrelativelocaleurl) pour générer un lien vers une page d'information dans la langue actuelle : + +```astro +--- +// src/components/AboutLink.astro +import { getRelativeLocaleUrl } from 'astro:i18n'; +--- + +<a href={getRelativeLocaleUrl(Astro.currentLocale ?? 'en', 'about')}>À propos</a +> +``` diff --git a/docs/src/content/docs/fr/guides/overriding-components.mdx b/docs/src/content/docs/fr/guides/overriding-components.mdx new file mode 100644 index 00000000000..54b03599adc --- /dev/null +++ b/docs/src/content/docs/fr/guides/overriding-components.mdx @@ -0,0 +1,152 @@ +--- +title: Redéfinition de composants +description: Apprenez à redéfinir les composants intégrés à Starlight pour ajouter des éléments personnalisés à l’interface utilisateur de votre site de documentation. +--- + +import { Steps } from '@astrojs/starlight/components'; + +L'interface utilisateur et les options de configuration par défaut de Starlight sont conçues pour être flexibles et fonctionner pour une variété de contenus. Une grande partie de l'apparence par défaut de Starlight peut être personnalisée grâce au [CSS](/fr/guides/css-and-tailwind/) et aux [options de configuration](/fr/guides/customization/). + +Quand vos besoins dépassent ce qui est possible de base, Starlight prend en charge la création de vos propres composants personnalisés pour étendre ou redéfinir (remplacer complètement) ses composants par défaut. + +## Quand redéfinir + +Redéfinir les composants par défaut de Starlight peut être utile lorsque : + +- Vous souhaitez modifier l'apparence d'une partie de l'interface utilisateur de Starlight d'une manière qui n'est pas possible avec du [CSS personnalisé](/fr/guides/css-and-tailwind/). +- Vous souhaitez modifier le comportement d'une partie de l'interface utilisateur de Starlight. +- Vous souhaitez ajouter certains éléments supplémentaires à l'interface utilisateur existante de Starlight. + +## Comment redéfinir + +<Steps> + +1. Choisissez le composant de Starlight que vous souhaitez redéfinir. + Vous pouvez trouver une liste complète des composants dans la [référence des redéfinitions](/fr/reference/overrides/). + + :::tip + Vous ne savez pas quel composant vous devez redéfinir ? Utilisez la [carte interactive des redéfinitions de Starlight](https://starlight-overrides-map.netlify.app/) pour découvrir les noms des composants de l'interface utilisateur de Starlight. + ::: + + Cet exemple va redéfinir le composant [`SocialIcons`](/fr/reference/overrides/#socialicons) de Starlight dans la barre de navigation de la page. + +2. Créez un composant Astro pour remplacer le composant de Starlight. + Cet exemple affiche un lien de contact. + + ```astro + --- + // src/components/EmailLink.astro + + const email = 'houston@example.com'; + --- + + <a href=`mailto:${email}`>Me contacter par courriel</a> + ``` + +3. Configurez Starlight pour utiliser votre composant personnalisé avec l'option de configuration [`components`](/fr/reference/configuration/#components) dans le fichier `astro.config.mjs` : + + ```js {9-12} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Ma documentation avec redéfinitions', + components: { + // Redéfinit le composant par défaut `SocialIcons`. + SocialIcons: './src/components/EmailLink.astro', + }, + }), + ], + }); + ``` + +</Steps> + +## Réutiliser un composant intégré + +Vous pouvez utiliser les composants par défaut de Starlight de la même manière que les vôtres : en les important et en les affichant dans vos propres composants personnalisés. Cela vous permet de conserver toute l'interface utilisateur de base de Starlight dans votre design, tout en ajoutant des éléments supplémentaires à côté. + +L'exemple ci-dessous montre un composant personnalisé qui affiche un lien de courriel suivi du composant `SocialIcons` par défaut : + +```astro {3,7} +--- +// src/components/EmailLink.astro +import Default from '@astrojs/starlight/components/SocialIcons.astro'; +--- + +<a href="mailto:houston@example.com">Me contacter par courriel</a> +<Default><slot /></Default> +``` + +Lorsque vous affichez un composant intégré dans un composant personnalisé, ajoutez un élément [`<slot />`](https://docs.astro.build/fr/basics/astro-components/#les-slots) à l'intérieur du composant par défaut. Cela permet de s'assurer que si le composant reçoit des éléments enfants, Astro sait où les afficher. + +Si vous réutilisez les composants [`PageFrame`](/fr/reference/overrides/#pageframe) ou [`TwoColumnContent`](/fr/reference/overrides/#twocolumncontent) qui contiennent des [slots nommés](https://docs.astro.build/fr/basics/astro-components/#les-slots-nomm%C3%A9s), vous devez également [transférer](https://docs.astro.build/fr/basics/astro-components/#transf%C3%A9rer-des-slots) ces slots. + +L'exemple ci-dessous montre un composant personnalisé qui réutilise le composant `TwoColumnContent` qui contient un slot supplémentaire nommé `right-sidebar` qui doit être transféré : + +```astro {8} +--- +// src/components/CustomContent.astro +import Default from '@astrojs/starlight/components/TwoColumnContent.astro'; +--- + +<Default> + <slot /> + <slot name="right-sidebar" slot="right-sidebar" /> +</Default> +``` + +## Utiliser les données de la page + +Lorsque vous redéfinissez un composant de Starlight, vous pouvez accéder à l'objet global [`starlightRoute`](/fr/guides/route-data/) contenant toutes les données de la page courante. +Cela vous permet d'utiliser ces valeurs pour contrôler la manière dont votre composant est affiché. + +Dans l'exemple suivant, un composant de remplacement [`PageTitle`](/fr/reference/overrides/#pagetitle) affiche le titre de la page actuelle tel qu'il est défini dans le frontmatter du contenu : + +```astro {4} "{title}" +--- +// src/components/Title.astro + +const { title } = Astro.locals.starlightRoute.entry.data; +--- + +<h1 id="_top">{title}</h1> + +<style> + h1 { + font-family: 'Comic Sans'; + } +</style> +``` + +Pour en savoir plus sur les propriétés disponibles, consultez la [référence des données de route](/fr/reference/route-data/). + +### Redéfinir uniquement sur des pages spécifiques + +Les redéfinitions de composants s'appliquent à toutes les pages. Cependant, vous pouvez les utiliser conditionnellement grâce aux valeurs de `starlightRoute` pour déterminer quand afficher votre interface utilisateur personnalisée, quand afficher l'interface utilisateur par défaut de Starlight, ou même quand afficher quelque chose de complètement différent. + +Dans l'exemple suivant, un composant redéfinissant le composant [`Footer`](/fr/reference/overrides/#footer) de Starlight affiche « Construit avec Starlight 🌟 » sur la page d'accueil uniquement, et affiche sinon le pied de page par défaut sur toutes les autres pages : + +```astro +--- +// src/components/ConditionalFooter.astro +import Default from '@astrojs/starlight/components/Footer.astro'; + +const isHomepage = Astro.locals.starlightRoute.id === ''; +--- + +{ + isHomepage ? ( + <footer>Construit avec Starlight 🌟</footer> + ) : ( + <Default> + <slot /> + </Default> + ) +} +``` + +Pour en savoir plus sur le rendu conditionnel, consultez le [guide de syntaxe d'Astro](https://docs.astro.build/fr/basics/astro-syntax/#html-dynamique). diff --git a/docs/src/content/docs/fr/guides/pages.mdx b/docs/src/content/docs/fr/guides/pages.mdx new file mode 100644 index 00000000000..527582be32f --- /dev/null +++ b/docs/src/content/docs/fr/guides/pages.mdx @@ -0,0 +1,234 @@ +--- +title: Pages +description: Apprenez à créer et à gérer les pages de votre site de documentation avec Starlight. +sidebar: + order: 1 +tableOfContents: + maxHeadingLevel: 4 +--- + +Starlight génère les pages HTML de votre site en fonction de votre contenu, avec des options flexibles fournies via le frontmatter du fichier Markdown. +En outre, les projets Starlight bénéficient d'un accès complet aux [puissants outils de génération de pages d'Astro](https://docs.astro.build/fr/basics/astro-pages/). +Ce guide montre comment fonctionne la génération de pages dans Starlight. + +## Pages de contenu + +### Formats de fichiers + +Starlight prend en charge la création de contenu en Markdown et MDX sans aucune configuration requise. +Vous pouvez ajouter la prise en charge de Markdoc en suivant le [guide « Markdoc »](/fr/guides/authoring-content/#markdoc). + +### Ajouter des pages + +Ajoutez de nouvelles pages à votre site en créant des fichiers `.md` ou `.mdx` dans `src/content/docs/`. +Utilisez des sous-dossiers pour organiser vos fichiers et pour créer plusieurs segments de chemin. + +Par exemple, la structure de fichier suivante générera des pages à `exemple.com/hello-world` et `exemple.com/reference/faq` : + +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - reference/ + - faq.md + +</FileTree> + +### Frontmatter avec sûreté du typage + +Toutes les pages Starlight partagent un [ensemble commun de propriétés de frontmatter](/fr/reference/frontmatter/) personnalisable pour contrôler l'apparence de la page : + +```md +--- +title: Bonjour tout le monde ! +description: Voici une page de mon site propulsé par Starlight +--- +``` + +Si vous oubliez quelque chose d'important, Starlight vous le fera savoir. + +## Pages personnalisées + +Pour les cas d'utilisation avancés, vous pouvez ajouter des pages personnalisées en créant un répertoire `src/pages/`. +Le répertoire `src/pages/` utilise le [routage basé sur les fichiers d'Astro](https://docs.astro.build/fr/basics/astro-pages/#routage-basé-sur-les-fichiers) et inclut la prise en charge des fichiers `.astro` parmi d'autres formats de pages. +Ceci est utile si vous avez besoin de créer des pages avec une mise en page complètement personnalisée ou de générer une page à partir d'une source de données alternative. + +Par exemple, ce projet mélange du contenu Markdown dans `src/content/docs/` avec des routes Astro et HTML dans `src/pages/` : + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - pages/ + - custom.astro + - archived.html + +</FileTree> + +Pour en savoir plus, consultez le guide [« Pages » dans la documentation d'Astro](https://docs.astro.build/fr/basics/astro-pages/). + +### Utiliser le design de Starlight dans des pages personnalisées + +Pour utiliser la mise en page de Starlight dans des pages personnalisées, englobez le contenu de votre page avec le [composant `<StarlightPage />`](#composant-starlightpage). +Cela peut s'avérer utile si vous générez du contenu de manière dynamique, mais que vous souhaitez tout de même utiliser le design de Starlight. + +Pour ajouter des liens d'ancrage vers des en-têtes avec une apparence équivalente aux liens d'ancrage Markdown de Starlight, vous pouvez utiliser le [composant `<AnchorHeading>`](#composant-anchorheading) dans vos pages personnalisées. + +```astro +--- +// src/pages/page-perso/exemple.astro +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +import CustomComponent from './CustomComponent.astro'; +--- + +<StarlightPage frontmatter={{ title: 'Ma page personnalisée' }}> + <p>Il s'agit d'une page personnalisée avec un composant personnalisé :</p> + <CustomComponent /> + + <AnchorHeading level="2" id="en-savoir-plus">En savoir plus</AnchorHeading> + <p> + <a href="https://starlight.astro.build/"> + Consulter la documentation de Starlight + </a> + </p> +</StarlightPage> +``` + +#### Composant `<StarlightPage>` + +Le composant `<StarlightPage />` affiche une page complète de contenu en utilisant la mise en page et les styles de Starlight. + +```astro +--- +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +--- + +<StarlightPage frontmatter={{ title: 'Ma page personnalisée' }}> + <!-- Contenu de la page personnalisée --> +</StarlightPage> +``` + +Le composant `<StarlightPage />` accepte les props suivantes. + +##### `frontmatter` + +**Obligatoire** +**Type :** `StarlightPageFrontmatter` + +Définit les [propriétés du frontmatter](/fr/reference/frontmatter/) pour cette page, similaire au frontmatter dans les pages Markdown. +La propriété [`title`](/fr/reference/frontmatter/#title-obligatoire) est obligatoire et toutes les autres propriétés sont optionnelles. + +Les propriétés suivantes diffèrent du frontmatter des fichiers Markdown : + +- La propriété [`slug`](/fr/reference/frontmatter/#slug) n'est pas prise en charge et est automatiquement définie en fonction de l'URL de la page personnalisée. +- L'option [`editUrl`](/fr/reference/frontmatter/#editurl) nécessite une URL pour afficher un lien d'édition. +- La propriété [`sidebar`](/fr/reference/frontmatter/#sidebar) du frontmatter permettant de personnaliser l'affichage de la page dans les [groupes de liens autogénérés](/fr/reference/configuration/#sidebar) n'est pas disponible. Les pages utilisant le composant `<StarlightPage />` ne font pas partie d'une collection et ne peuvent pas être ajoutées à un groupe de liens autogénérés. +- L'option [`draft`](/fr/reference/frontmatter/#draft) affiche uniquement une [note](/fr/reference/overrides/#draftcontentnotice) indiquant que la page est une ébauche, mais ne l'exclut pas automatiquement des déploiements en production. + +##### `sidebar` + +**Type :** [`SidebarItem[]`](/fr/reference/configuration/#sidebaritem) +**Par défaut :** la barre latérale générée en fonction de la [configuration globale `sidebar`](/fr/reference/configuration/#sidebar) + +Fournit une barre latérale de navigation personnalisée pour cette page. +Si elle n'est pas définie, la page utilisera la barre latérale globale par défaut. + +Par exemple, la page suivante remplace la barre latérale par défaut par un lien vers la page d'accueil et un groupe de liens vers diverses autres pages personnalisées. + +```astro {3-17} +<StarlightPage + frontmatter={{ title: 'Orion' }} + sidebar={[ + { label: 'Accueil', link: '/' }, + { + label: 'Constellations', + items: [ + { label: 'Andromède', link: '/andromède/' }, + { label: 'Orion', link: '/orion/' }, + { + label: 'La Petite Ourse', + link: '/la-petite-ourse/', + badge: 'Ébauche', + }, + ], + }, + ]} +> + Exemple de contenu. +</StarlightPage> +``` + +Consultez le guide [« Barre latérale de navigation »](/fr/guides/sidebar/) pour en savoir plus sur les options disponibles pour personnaliser la barre latérale. + +##### `hasSidebar` + +**Type :** `boolean` +**Par défaut :** `false` si [`frontmatter.template`](/fr/reference/frontmatter/#template) utilise `'splash'`, autrement `true` + +Contrôle l'affichage ou non de la barre latérale sur cette page. + +##### `headings` + +**Type :** `{ depth: number; slug: string; text: string }[]` +**Par défaut :** `[]` + +Fournit un tableau de tous les en-têtes de cette page. +Starlight générera la table des matières de la page à partir de ces en-têtes s'ils sont fournis. + +##### `dir` + +**Type :** `'ltr' | 'rtl'` +**Par défaut :** le sens d'écriture pour la locale actuelle + +Définit le sens d’écriture pour le contenu de la page. + +##### `lang` + +**Type :** `string` +**Par défaut :** la langue de la locale actuelle + +Définit l'étiquette d’identification BCP-47 pour le contenu de cette page, par exemple `en`, `zh-CN`, ou `pt-BR`. + +##### `isFallback` + +**Type :** `boolean` +**Par défaut :** `false` + +Indique si cette page utilise un [contenu de repli](/fr/guides/i18n/#contenu-de-repli) parce qu'il n'y a pas de traduction pour la langue actuelle. + +#### Composant `<AnchorHeading>` + +Le composant `<AnchorHeading>` affiche un élément d'en-tête HTML avec un lien d'ancrage cliquable avec une apparence équivalente aux styles Markdown de Starlight. + +```astro +--- +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +--- + +<AnchorHeading level="2" id="sous-rubrique">Sous rubrique</AnchorHeading> +``` + +Il accepte les props suivantes ainsi que n'importe quel autre [attribut HTML universel valide](https://developer.mozilla.org/fr/docs/Web/HTML/Reference/Global_attributes). + +##### `level` + +**Obligatoire** +**Type :** `1 | 2 | 3 | 4 | 5 | 6` + +Le niveau d'en-tête à afficher. +Par exemple, `level="1"` afficherait un élément `<h1>`. + +##### `id` + +**Obligatoire** +**Type :** `string` + +Un identifiant unique pour cet en-tête. +Celui-ci sera utilisé comme attribut `id` de l'en-tête affiché et l'icône d'ancrage rendirigera vers celui-ci. diff --git a/docs/src/content/docs/fr/guides/project-structure.mdx b/docs/src/content/docs/fr/guides/project-structure.mdx index 26322543e64..7336f7fd94f 100644 --- a/docs/src/content/docs/fr/guides/project-structure.mdx +++ b/docs/src/content/docs/fr/guides/project-structure.mdx @@ -5,22 +5,22 @@ description: Apprenez à organiser les fichiers dans votre projet Starlight. Ce guide vous montrera comment un projet Starlight est organisé et ce que font les différents fichiers de votre projet. -Les projets Starlight suivent généralement la même structure de fichiers et de répertoires que les autres projets Astro. Voir [la documentation sur la structure des projets Astro](https://docs.astro.build/fr/core-concepts/project-structure/) pour plus de détails. +Les projets Starlight suivent généralement la même structure de fichiers et de répertoires que les autres projets Astro. Voir [la documentation sur la structure des projets Astro](https://docs.astro.build/fr/basics/project-structure/) pour plus de détails. ## Fichiers et répertoires - `astro.config.mjs` — Le fichier de configuration d'Astro ; inclut l'intégration et la configuration de Starlight. -- `src/content/config.ts` — Fichier de configuration des collections de contenu ; ajoute les schémas de la matière première de Starlight à votre projet. +- `src/content.config.ts` — Fichier de configuration des collections de contenu ; ajoute les schémas du frontmatter de Starlight à votre projet. - `src/content/docs/` — Fichiers de contenu. Starlight transforme chaque fichier `.md`, `.mdx` ou `.mdoc` de ce répertoire en une page de votre site. - `src/content/i18n/` (optionnel) — Données de traduction pour prendre en charge l'[internationalisation](/fr/guides/i18n/). - `src/` — Autre code source et fichiers (composants, styles, images, etc.) pour votre projet. -- `public/` — Actifs statiques (polices, favicon, PDFs, etc.) qui ne seront pas traités par Astro. +- `public/` — Ressources statiques (polices, favicon, PDF, etc.) qui ne seront pas traités par Astro. ## Exemple de contenu de projet Un répertoire de projet Starlight peut ressembler à ceci : -import FileTree from '../../../../components/file-tree.astro'; +import { FileTree } from '@astrojs/starlight/components'; <FileTree> @@ -39,8 +39,7 @@ import FileTree from '../../../../components/file-tree.astro'; - 01-getting-started.md - 02-advanced.md - index.mdx - - config.ts - - env.d.ts + - content.config.ts - astro.config.mjs - package.json - tsconfig.json diff --git a/docs/src/content/docs/fr/guides/route-data.mdx b/docs/src/content/docs/fr/guides/route-data.mdx new file mode 100644 index 00000000000..4bd1fd9297c --- /dev/null +++ b/docs/src/content/docs/fr/guides/route-data.mdx @@ -0,0 +1,139 @@ +--- +title: Données de route +description: Apprenez comment le modèle de données de page de Starlight est utilisé pour afficher vos pages et comment vous pouvez le personnaliser. +--- + +import { Steps } from '@astrojs/starlight/components'; + +Lorsque Starlight affiche une page dans votre documentation, un objet de données de route est d'abord créé pour représenter ce qui se trouve sur cette page. +Ce guide explique comment les données de route sont générées, comment les utiliser et comment vous pouvez les personnaliser pour modifier le comportement par défaut de Starlight. + +Consultez la [« Référence des données de route »](/fr/reference/route-data/) pour une liste complète des propriétés disponibles. + +## Qu'est-ce que les données de route? + +Les données de route de Starlight sont un objet contenant toutes les informations nécessaires pour afficher une seule page. +Il inclut des informations pour la page courante ainsi que des données générées à partir de votre configuration de Starlight. + +## Utilisation des données de route + +Tous les composants de Starlight utilisent les données de route pour décider de ce qui doit être affiché pour chaque page. +Par exemple, la chaîne de caractères [`siteTitle`](/fr/reference/route-data/#sitetitle) est utilisée pour afficher le titre du site et le tableau [`sidebar`](/fr/reference/route-data/#sidebar) est utilisé pour afficher la barre latérale de navigation. + +Vous pouvez accéder à ces données à partir de la variable globale `Astro.locals.starlightRoute` dans les composants Astro : + +```astro title="exemple.astro" {2} +--- +const { siteTitle } = Astro.locals.starlightRoute; +--- + +<p>Le titre de ce site est « {siteTitle} »</p> +``` + +Cela peut être utile, par exemple, lors de la mise en place de redéfinitions de composants pour personnaliser ce que vous affichez. + +## Personnalisation des données de route + +Les données de route de Starlight sont prêtes à l'emploi et ne nécessitent aucune configuration. +Cependant, pour des cas d'utilisation avancés, vous pourriez vouloir personnaliser les données de route pour certaines ou toutes les pages afin de modifier le rendu de votre site. + +Il s'agit d'un concept similaire aux [redéfinitions de composants](/fr/guides/overriding-components/), mais au lieu de modifier la façon dont Starlight affiche vos données, vous modifiez les données que Starlight affiche. + +### Quand personnaliser les données de route + +Personnaliser les données de route peut être utile lorsque vous souhaitez modifier la façon dont Starlight traite vos données d'une manière qui n'est pas possible avec les options de configuration existantes. + +Par exemple, vous pourriez vouloir filtrer les éléments de la barre latérale de navigation ou personnaliser les titres de certaines pages. +Ce type de modification ne nécessite pas de modifier les composants par défaut de Starlight, seulement les données transmises à ces composants. + +### Comment personnaliser les données de route + +Vous pouvez personnaliser les données de route en utilisant une forme spéciale de « middleware ». +C'est une fonction qui est appelée à chaque fois que Starlight affiche une page et peut modifier les valeurs contenues dans l'objet de données de route. + +<Steps> + +1. Créez un nouveau fichier exportant une fonction `onRequest` en utilisant l'utilitaire `defineRouteMiddleware()` de Starlight : + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware(() => {}); + ``` + +2. Indiquez à Starlight où se trouve le fichier contenant votre middleware de données de route dans `astro.config.mjs` : + + ```js ins={9} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Mon ravissant site de documentation', + routeMiddleware: './src/routeData.ts', + }), + ], + }); + ``` + +3. Mettez à jour votre fonction `onRequest` pour modifier les données de route. + + Le premier argument que votre middleware recevra est [l'objet `context` d'Astro](https://docs.astro.build/fr/reference/api-reference/). + Celui-ci contient toutes les informations concernant le rendu de la page courante, y compris l'URL actuelle et les `locals`. + + Dans cet exemple, nous allons rendre notre documentation plus passionnante en ajoutant un point d'exclamation à la fin du titre de chaque page. + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware((context) => { + // Récupérer l'entrée de la collection de contenus pour cette page. + const { entry } = context.locals.starlightRoute; + // Mettre à jour le titre pour ajouter un point d'exclamation. + entry.data.title = entry.data.title + ' !'; + }); + ``` + +</Steps> + +#### Plusieurs middleware de route + +Starlight accepte également d'utiliser plusieurs middlewares. +Définissez `routeMiddleware` comme un tableau de chemins pour ajouter plus d'un middleware : + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Mon site avec plusieurs middlewares', + routeMiddleware: ['./src/middleware-un.ts', './src/middleware-deux.ts'], + }), + ], +}); +``` + +#### Attendre des middlewares de route ultérieurs + +Pour attendre que des middlewares ultérieurs s'exécutent avant d'exécuter votre code, vous pouvez attendre la fin de l'appel à `next()` passé en deuxième argument à votre fonction middleware. +Cela peut être utile pour attendre que le middleware d'un module d'extension s'exécute avant de faire des modifications par exemple. + +```ts "next" "await next();" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware(async (context, next) => { + // Attendre que des middlewares ultérieurs s'exécutent. + await next(); + // Modifier les données de route. + const { entry } = context.locals.starlightRoute; + entry.data.title = entry.data.title + ' !'; +}); +``` diff --git a/docs/src/content/docs/fr/guides/sidebar.mdx b/docs/src/content/docs/fr/guides/sidebar.mdx new file mode 100644 index 00000000000..c3811db2688 --- /dev/null +++ b/docs/src/content/docs/fr/guides/sidebar.mdx @@ -0,0 +1,740 @@ +--- +title: Barre latérale de navigation +description: Apprendre à configurer et personnaliser les liens de la barre latérale de navigation de votre site Starlight. +--- + +import { FileTree } from '@astrojs/starlight/components'; +import SidebarPreview from '~/components/sidebar-preview.astro'; + +Une barre latérale bien organisée est une des clés d'une bonne documentation, car c'est l'une des principales méthodes de navigation qui sera utilisée par les utilisateurs de votre site. Starlight fournit un ensemble complet d'options pour personnaliser la structure et le contenu de votre barre latérale. + +## Barre latérale par défaut + +Par défaut, Starlight générera automatiquement une barre latérale basée sur la structure du système de fichiers de votre documentation, en utilisant la propriété `title` de chaque fichier comme entrée de la barre latérale. + +Par exemple, pour la structure de fichiers suivante : + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - andromede.md + - orion.md + - etoiles/ + - betelgeuse.md + +</FileTree> + +La barre latérale suivante sera automatiquement générée : + +<SidebarPreview + config={[ + { + label: 'constellations', + items: [ + { label: 'Andromède', link: '' }, + { label: 'Orion', link: '' }, + ], + }, + { + label: 'etoiles', + items: [{ label: 'Bételgeuse', link: '' }], + }, + ]} +/> + +Pour en savoir plus sur les barres latérales générées automatiquement, consultez la section sur les [groupes générés automatiquement](#groupes-générés-automatiquement). + +## Ajouter des liens et des groupes de liens + +Pour configurer les liens et groupes de liens (dans un en-tête rétractable) de votre barre latérale, utilisez la propriété [`starlight.sidebar`](/fr/reference/configuration/#sidebar) dans le fichier `astro.config.mjs`. + +En combinant les liens et les groupes, vous pouvez créer une grande variété de structures de barre latérale. + +### Liens internes + +Ajoutez un lien vers une page située dans `src/content/docs/` en utilisant un objet avec la propriété `slug`. +Le titre de la page liée sera utilisé comme étiquette par défaut. + +Par exemple, avec la configuration suivante : + +```js "slug:" +starlight({ + sidebar: [ + { slug: 'constellations/andromede' }, + { slug: 'constellations/orion' }, + ], +}); +``` + +Et la structure de fichiers suivante : + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - andromede.md + - orion.md + +</FileTree> + +La barre latérale suivante sera générée : + +<SidebarPreview + config={[ + { label: 'Andromède', link: '' }, + { label: 'Orion', link: '' }, + ]} +/> + +Pour personnaliser les valeurs inférées du frontmatter de la page liée, vous pouvez ajouter les propriétés `label`, [`translations`](#internationalisation) et [`attrs`](#attributs-html-personnalisés). + +Consultez la section [« Personnaliser les liens générés automatiquement dans le frontmatter »](#personnaliser-les-liens-générés-automatiquement-dans-le-frontmatter) pour plus de détails sur comment contrôler l'apparence de la barre latérale à partir du frontmatter de la page. + +#### Syntaxe simplifiée pour les liens internes + +Les liens internes peuvent également être spécifiés en utilisant uniquement une chaîne de caractères comme raccourci pour le slug de la page. + +Par exemple, la configuration suivante est équivalente à la configuration ci-dessus, qui utilisait `slug` : + +```js "slug:" +starlight({ + sidebar: ['constellations/andromede', 'constellations/orion'], +}); +``` + +### Autres liens + +Ajoutez un lien vers une page externe ou ne faisant pas partie de votre documentation en utilisant un objet avec les propriétés `label` et `link`. + +```js "label:" "link:" +starlight({ + sidebar: [ + // Un lien vers une page ne faisant pas partie de la documentation. + { label: 'Boutique de météores', link: '/boutique/' }, + // Un lien externe vers le site de la NASA. + { label: 'NASA', link: 'https://www.nasa.gov/' }, + ], +}); +``` + +La configuration ci-dessus génère la barre latérale suivante : + +<SidebarPreview + config={[ + { label: 'Boutique de météores', link: '' }, + { label: 'NASA', link: 'https://www.nasa.gov/' }, + ]} +/> + +### Groupes + +Vous pouvez donner de la structure à votre barre latérale en regroupant des liens connexes sous un en-tête rétractable. +Les groupes peuvent contenir à la fois des liens et d'autres sous-groupes. + +Ajoutez un groupe en utilisant un objet avec les propriétés `label` et `items`. +Le `label` sera utilisé comme en-tête pour le groupe. +Ajoutez des liens ou des sous-groupes au tableau `items`. + +```js /^\s*(label:|items:)/ +starlight({ + sidebar: [ + // Un groupe de liens avec le label "Constellations". + { + label: 'Constellations', + items: [ + 'constellations/carene', + 'constellations/centaure', + // Un groupe de liens imbriqué pour les constellations saisonnières. + { + label: 'Saisonnières', + items: [ + 'constellations/andromede', + 'constellations/orion', + 'constellations/petite-ourse', + ], + }, + ], + }, + ], +}); +``` + +La configuration ci-dessus génère la barre latérale suivante : + +<SidebarPreview + config={[ + { + label: 'Constellations', + items: [ + { label: 'Carène', link: '' }, + { label: 'Centaure', link: '' }, + { + label: 'Saisonnières', + items: [ + { label: 'Andromède', link: '' }, + { label: 'Orion', link: '' }, + { label: 'Petite Ourse', link: '' }, + ], + }, + ], + }, + ]} +/> + +### Groupes générés automatiquement + +Starlight peut générer automatiquement un groupe dans votre barre latérale en fonction d'un répertoire de votre documentation. +Cela est utile lorsque vous ne souhaitez pas entrer manuellement chaque élément de la barre latérale dans un groupe. + +Par défaut, les pages sont triées par ordre alphabétique selon le [`slug`](/fr/reference/route-data/#slug) du fichier. + +Ajoutez un groupe généré automatiquement en utilisant un objet avec les propriétés `label` et `autogenerate`. La configuration de `autogenerate` doit spécifier le répertoire à utiliser pour les entrées de la barre latérale avec la propriété `directory`. Par exemple, avec la configuration suivante : + +```js "label:" "autogenerate:" +starlight({ + sidebar: [ + { + label: 'Constellations', + // Génère automatiquement un groupe de liens pour le répertoire "constellations". + autogenerate: { directory: 'constellations' }, + }, + ], +}); +``` + +Et la structure de fichiers suivante : + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - carene.md + - centaure.md + - saisonnieres/ + - andromede.md + +</FileTree> + +La barre latérale suivante sera générée : + +<SidebarPreview + config={[ + { + label: 'Constellations', + items: [ + { label: 'Carène', link: '' }, + { label: 'Centaure', link: '' }, + { + label: 'saisonnieres', + items: [{ label: 'Andromède', link: '' }], + }, + ], + }, + ]} +/> + +## Personnaliser les liens générés automatiquement dans le frontmatter + +Utilisez le [champ `sidebar` du frontmatter](/fr/reference/frontmatter/#sidebar) dans différentes pages pour personnaliser les liens générés automatiquement. + +Les options du frontmatter pour la barre latérale vous permettent de définir une [étiquette personnalisée](/fr/reference/frontmatter/#label), d'utiliser des [attributs personnalisés](/fr/reference/frontmatter/#attrs), d'ajouter un [badge](/fr/reference/frontmatter/#badge) à un lien, de [masquer](/fr/reference/frontmatter/#hidden) un lien de la barre latérale, ou de définir une [pondération de tri personnalisée](/fr/reference/frontmatter/#order). + +```md "sidebar:" +--- +# src/content/docs/exemple.md +title: Ma page +sidebar: + # Définit une étiquette personnalisée pour le lien dans la barre latérale + label: Étiquette personnalisée + # Définit un ordre personnalisé pour le lien + # (les nombres plus petits sont affichés plus haut) + order: 2 + # Ajoute un badge au lien + badge: + text: Nouveau + variant: tip +--- +``` + +Un groupe généré automatiquement incluant une page avec le frontmatter ci-dessus générera la barre latérale suivante : + +<SidebarPreview + config={[ + { + label: 'Guides', + items: [ + { label: 'Une page', link: '' }, + { + label: 'Étiquette personnalisée', + link: '', + badge: { text: 'Nouveau', variant: 'tip' }, + }, + { label: 'Une autre page', link: '' }, + ], + }, + ]} +/> + +:::note +La configuration du frontmatter `sidebar` est seulement utilisée pour les liens dans des groupes générés automatiquement et les liens de documentation définis avec la propriété `slug`. +Elle ne s'applique pas aux liens définis avec la propriété `link`. +::: + +## Badges + +Les liens, groupes et groupes générés automatiquement peuvent inclure une propriété `badge` pour afficher un badge à côté de leurs étiquettes. + +```js {9,16} +starlight({ + sidebar: [ + { + label: 'Étoiles', + items: [ + // Un lien avec un badge "Supergéante". + { + slug: 'etoiles/persei', + badge: 'Supergéante', + }, + ], + }, + // Un groupe généré automatiquement avec un badge "Obsolète". + { + label: 'Lunes', + badge: 'Obsolète', + autogenerate: { directory: 'lunes' }, + }, + ], +}); +``` + +La configuration ci-dessus génère la barre latérale suivante : + +<SidebarPreview + config={[ + { + label: 'Étoiles', + items: [ + { + label: 'Persei', + link: '', + badge: { text: 'Supergéante', variant: 'default' }, + }, + ], + }, + { + label: 'Lunes', + badge: { text: 'Obsolète', variant: 'default' }, + items: [ + { + label: 'Io', + link: '', + }, + { + label: 'Europe', + link: '', + }, + { + label: 'Ganymède', + link: '', + }, + ], + }, + ]} +/> + +### Variantes de badges et style personnalisé + +Personnalisez le style du badge en utilisant un objet avec les propriétés `text`, `variant`, et `class`. + +La propriété `text` représente le contenu à afficher (par exemple, "Nouveau"). +Par défaut, le badge utilise la couleur d'accentuation de votre site. Pour utiliser un style de badge intégré, définissez la propriété `variant` à l'une des valeurs suivantes : `note`, `tip`, `danger`, `caution` ou `success`. + +Facultativement, vous pouvez créer un style de badge personnalisé en définissant la propriété `class` à un nom de classe CSS. + +```js {9} +starlight({ + sidebar: [ + { + label: 'Étoiles', + items: [ + // Un lien avec un badge "Ébauche" jaune. + { + slug: 'etoiles/sirius', + badge: { text: 'Ébauche', variant: 'caution' }, + }, + ], + }, + ], +}); +``` + +La configuration ci-dessus génère la barre latérale suivante : + +<SidebarPreview + config={[ + { + label: 'Étoiles', + items: [ + { + label: 'Sirius', + link: '', + badge: { text: 'Ébauche', variant: 'caution' }, + }, + ], + }, + ]} +/> + +En savoir plus sur [l'utilisation et la personnalisation des badges](/fr/components/badges/#utilisation). + +## Attributs HTML personnalisés + +Les liens peuvent aussi inclure une propriété `attrs` pour ajouter des attributs HTML personnalisés à l'élément du lien. + +Dans l'exemple suivant, `attrs` est utilisé pour ajouter un attribut `target="_blank"`, afin que le lien s'ouvre dans un nouvel onglet, et pour appliquer un attribut `style` personnalisé pour mettre en italique l'étiquette du lien : + +```js {10} +starlight({ + sidebar: [ + { + label: 'Ressources', + items: [ + // Un lien externe vers le site de la NASA s'ouvrant dans un nouvel onglet. + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { target: '_blank', style: 'font-style: italic' }, + }, + ], + }, + ], +}); +``` + +La configuration ci-dessus génère la barre latérale suivante : + +<SidebarPreview + config={[ + { + label: 'Ressources', + items: [ + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { + target: '_blank', + style: 'font-style: italic', + }, + }, + ], + }, + ]} +/> + +### Attributs HTML personnalisés pour les liens générés automatiquement + +Personnalisez les attributs HTML de tous les liens dans des [groupes générés automatiquement](#groupes-générés-automatiquement) en définissant la propriété `attrs` dans la configuration `autogenerate`. +Différentes pages peuvent individuellement spécifier des attributs personnalisés en utilisant le [champ `sidebar.attrs` du frontmatter](/fr/reference/frontmatter/#attrs) qui sera fusionné avec la configuration `autogenerate.attrs`. + +Par exemple, avec la configuration suivante : + +```js {9} +starlight({ + sidebar: [ + { + label: 'Constellations', + autogenerate: { + // Génère automatiquement un groupe de liens pour le répertoire "constellations". + directory: 'constellations', + // Met en italique tous les labels de liens dans ce groupe. + attrs: { style: 'font-style: italic' }, + }, + }, + ], +}); +``` + +Et la structure de fichiers suivante : + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - carene.md + - centaure.md + - saisonnieres/ + - andromede.md + +</FileTree> + +La barre latérale suivante sera générée avec tous les liens générés automatiquement en italique : + +<SidebarPreview + config={[ + { + label: 'Constellations', + items: [ + { label: 'Carène', link: '', attrs: { style: 'font-style: italic' } }, + { + label: 'Centaure', + link: '', + attrs: { style: 'font-style: italic' }, + }, + { + label: 'saisonnieres', + items: [ + { + label: 'Andromède', + link: '', + attrs: { style: 'font-style: italic' }, + }, + ], + }, + ], + }, + ]} +/> + +## Internationalisation + +Utilisez la propriété `translations` sur les liens et les groupes pour traduire l'étiquette du lien ou du groupe pour chaque langue prise en charge en spécifiant une étiquette d'identification de langue [BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags), par exemple `"en"`, `"ar"` ou `"zh-CN"`, comme clé et l'étiquette traduite comme valeur. +La propriété `label` sera utilisée pour la langue par défaut et pour les langues sans traduction. + +```js {5-7,11-13,18-20} +starlight({ + sidebar: [ + { + label: 'Constellations', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { + label: 'Andromède', + translations: { + 'pt-BR': 'Andrômeda', + }, + slug: 'constellations/andromede', + }, + { + label: 'Scorpion', + translations: { + 'pt-BR': 'Escorpião', + }, + slug: 'constellations/scorpion', + }, + ], + }, + ], +}); +``` + +Parcourir la documentation en portugais brésilien générera la barre latérale suivante : + +<SidebarPreview + config={[ + { + label: 'Constelação', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +### Internationalisation avec des liens internes + +Les [liens internes](#liens-internes) utiliseront automatiquement les titres de page traduits depuis le frontmatter du contenu par défaut : + +```js {9-10} +starlight({ + sidebar: [ + { + label: 'Constellations', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { slug: 'constellations/andromede' }, + { slug: 'constellations/scorpion' }, + ], + }, + ], +}); +``` + +Parcourir la documentation en portugais brésilien générera la barre latérale suivante : + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +Pour les sites multilingues, la valeur de la propriété `slug` n'inclut pas la portion de langue dans l'URL. +Par exemple, si vous avez des pages à `en/intro` et `pt-br/intro`, le slug est `intro` lors de la configuration de la barre latérale. + +### Internationalisation avec des badges + +Pour les [badges](#badges), la propriété `text` peut être une chaîne de caractères, ou pour les sites multilingues, un objet avec des valeurs pour chaque langue différente. +Lors de l'utilisation de la forme d'objet, les clés doivent être des étiquettes d'identification de langue [BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags) (par exemple, `en`, `ar` ou `zh-CN`) : + +```js {11-16} +starlight({ + sidebar: [ + { + label: 'Constellations', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { + slug: 'constellations/andromeda', + badge: { + text: { + fr: 'Nouveau', + 'pt-BR': 'Novo', + }, + }, + }, + ], + }, + ], +}); +``` + +Parcourir la documentation en portugais brésilien générera la barre latérale suivante : + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { + label: 'Andrômeda', + link: '', + badge: { text: 'Novo', variant: 'default' }, + }, + ], + }, + ]} +/> + +## Groupes rétractables + +Les groupes de liens peuvent être rétractés par défaut en définissant la propriété `collapsed` à `true`. + +```js {5-6} +starlight({ + sidebar: [ + { + label: 'Constellations', + // Rétracte le groupe par défaut. + collapsed: true, + items: ['constellations/andromede', 'constellations/orion'], + }, + ], +}); +``` + +La configuration ci-dessus génère la barre latérale suivante : + +<SidebarPreview + config={[ + { + label: 'Constellations', + collapsed: true, + items: [ + { label: 'Andromède', link: '' }, + { label: 'Orion', link: '' }, + ], + }, + ]} +/> + +Les [groupes générés automatiquement](#groupes-générés-automatiquement) respectent la valeur `collapsed` de leur groupe parent : + +```js {5-7} +starlight({ + sidebar: [ + { + label: 'Constellations', + // Rétracte le groupe et ses sous-groupes générés automatiquement + // par défaut. + collapsed: true, + autogenerate: { directory: 'constellations' }, + }, + ], +}); +``` + +La configuration ci-dessus génère la barre latérale suivante : + +<SidebarPreview + config={[ + { + label: 'Constellations', + collapsed: true, + items: [ + { label: 'Carène', link: '' }, + { label: 'Centaure', link: '' }, + { + label: 'saisonnieres', + collapsed: true, + items: [{ label: 'Andromède', link: '' }], + }, + ], + }, + ]} +/> + +Ce comportement peut être remplacé en définissant la propriété `autogenerate.collapsed`. + +```js {5-7} "collapsed: true" +starlight({ + sidebar: [ + { + label: 'Constellations', + // Ne rétracte pas le groupe "Constellations" mais rétracte ses + // sous-groupes générés automatiquement. + collapsed: false, + autogenerate: { directory: 'constellations', collapsed: true }, + }, + ], +}); +``` + +La configuration ci-dessus génère la barre latérale suivante : + +<SidebarPreview + config={[ + { + label: 'Constellations', + items: [ + { label: 'Carène', link: '' }, + { label: 'Centaure', link: '' }, + { + label: 'saisonnieres', + collapsed: true, + items: [{ label: 'Andromède', link: '' }], + }, + ], + }, + ]} +/> diff --git a/docs/src/content/docs/fr/guides/site-search.mdx b/docs/src/content/docs/fr/guides/site-search.mdx new file mode 100644 index 00000000000..c6ea6294095 --- /dev/null +++ b/docs/src/content/docs/fr/guides/site-search.mdx @@ -0,0 +1,244 @@ +--- +title: Recherche +description: Découvrez les fonctionnalités de recherche intégrées à Starlight et comment les personnaliser. +tableOfContents: + maxHeadingLevel: 4 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +Par défaut, les sites utilisant Starlight incluent une recherche plein texte utilisant [Pagefind](https://pagefind.app/), un outil de recherche rapide et à faible bande passante pour sites statiques. + +Aucune configuration n'est requise pour activer la recherche. Créez et déployez votre site, puis utilisez la barre de recherche dans l'en-tête du site pour trouver du contenu. + +## Cacher du contenu dans les résultats de recherche + +### Exclure une page + +Pour exclure une page de votre index de recherche, ajoutez [`pagefind: false`](/fr/reference/frontmatter/#pagefind) au frontmatter de la page : + +```md title="src/content/docs/sans-recherche.md" ins={3} +--- +title: Contenu à cacher de la recherche +pagefind: false +--- +``` + +### Exclure une partie d'une page + +Pagefind ignorera le contenu à l'intérieur d'un élément avec l'attribut [`data-pagefind-ignore`](https://pagefind.app/docs/indexing/#removing-individual-elements-from-the-index). + +Dans l'exemple suivant, le premier paragraphe s'affichera dans les résultats de recherche, mais le contenu de la `<div>` ne s'affichera pas : + +```md title="src/content/docs/resultats-partiels.md" ins="data-pagefind-ignore" +--- +title: Page partiellement indexée +--- + +Ce texte sera trouvable via la recherche. + +<div data-pagefind-ignore> + +Ce texte sera caché de la recherche. + +</div> +``` + +## Système de recherche alternatif + +### Algolia DocSearch + +Si vous avez accès au [programme DocSearch d'Algolia](https://docsearch.algolia.com/) et que vous souhaitez l'utiliser à la place de Pagefind, vous pouvez utiliser le module d'extension officiel DocSearch de Starlight. + +<Steps> + +1. Installez `@astrojs/starlight-docsearch` : + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-docsearch + ``` + + </TabItem> + + </Tabs> + +2. Ajouter DocSearch à votre configuration [`plugins`](/fr/reference/configuration/#plugins) de Starlight dans le fichier `astro.config.mjs` et spécifiez vos `appId`, `apiKey` et `indexName` d'Algolia : + + ```js ins={4,10-16} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Site avec DocSearch', + plugins: [ + starlightDocSearch({ + appId: 'VOTRE_APP_ID', + apiKey: 'VOTRE_CLE_API_DE_RECHERCHE', + indexName: 'VOTRE_NOM_D_INDEX', + }), + ], + }), + ], + }); + ``` + +</Steps> + +Avec cette configuration mise à jour, la barre de recherche de votre site ouvrira désormais une modale Algolia au lieu de celle par défaut. + +#### Configuration de DocSearch + +Le module d’extension DocSearch de Starlight prend en charge la personnalisation du composant DocSearch avec les options supplémentaires suivantes spécifiées dans la configuration du module d’extension : + +- `maxRecentSearches`: Limite le nombre de résultats affichés pour chaque groupe de recherche. La valeur par défaut est `5`. +- `disableUserPersonalization`: Empêche DocSearch de sauvegarder les recherches récentes et favorites d'un utilisateur localement. La valeur par défaut est `false`. +- `insights`: Active le module d'extension Algolia Insights et envoie les événements liés à toute recherche à votre index DocSearch. La valeur par défaut est `false`. +- `searchParameters`: Un objet personnalisant les [paramètres de recherche Algolia](https://www.algolia.com/doc/api-reference/search-api-parameters/). + +##### Options supplémentaires de DocSearch + +Un fichier de configuration distinct est requis pour passer des options de type fonction comme `transformItems()` ou `resultsFooterComponent()` au composant DocSearch. + +<Steps> + +1. Créez un fichier TypeScript exportant votre configuration DocSearch. + + ```ts + // src/config/docsearch.ts + import type { DocSearchClientOptions } from '@astrojs/starlight-docsearch'; + + export default { + appId: 'VOTRE_APP_ID', + apiKey: 'VOTRE_CLE_API_DE_RECHERCHE', + indexName: 'VOTRE_NOM_D_INDEX', + getMissingResultsUrl({ query }) { + return `https://github.com/algolia/docsearch/issues/new?title=${query}`; + }, + // ... + } satisfies DocSearchClientOptions; + ``` + +2. Utilisez le chemin vers votre fichier de configuration avec le module d’extension DocSearch de Starlight dans `astro.config.mjs`. + + ```js {11-13} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Site avec DocSearch', + plugins: [ + starlightDocSearch({ + clientOptionsModule: './src/config/docsearch.ts', + }), + ], + }), + ], + }); + ``` + +</Steps> + +Consultez la [référence de l'API JavaScript client de DocSearch](https://docsearch.algolia.com/docs/api/) pour obtenir toutes les options prises en charge. + +#### Traduire l'interface utilisateur de DocSearch + +DocSearch fournit seulement des chaînes de l'interface utilisateur en anglais par défaut. +Ajoutez des traductions de l'interface utilisateur de la modale pour votre langue en utilisant le [système d'internationalisation](/fr/guides/i18n/#traduire-linterface-utilisateur-de-starlight) intégré à Starlight. + +<Steps> + +1. Étendez la définition de la collection de contenus `i18n` de Starlight avec le schéma DocSearch dans `src/content/config.ts` : + + ```js ins={5} ins=/{ extend: .+ }/ + // src/content.config.ts + import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; + import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + import { docSearchI18nSchema } from '@astrojs/starlight-docsearch/schema'; + + export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ extend: docSearchI18nSchema() }), + }), + }; + ``` + +2. Ajoutez des traductions à vos fichiers JSON dans `src/content/i18n/`. + + Voici les valeurs par défaut en anglais utilisées par DocSearch : + + ```json title="src/content/i18n/en.json" + { + "docsearch.searchBox.resetButtonTitle": "Clear the query", + "docsearch.searchBox.resetButtonAriaLabel": "Clear the query", + "docsearch.searchBox.cancelButtonText": "Cancel", + "docsearch.searchBox.cancelButtonAriaLabel": "Cancel", + "docsearch.searchBox.searchInputLabel": "Search", + + "docsearch.startScreen.recentSearchesTitle": "Recent", + "docsearch.startScreen.noRecentSearchesText": "No recent searches", + "docsearch.startScreen.saveRecentSearchButtonTitle": "Save this search", + "docsearch.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", + "docsearch.startScreen.favoriteSearchesTitle": "Favorite", + "docsearch.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + + "docsearch.errorScreen.titleText": "Unable to fetch results", + "docsearch.errorScreen.helpText": "You might want to check your network connection.", + + "docsearch.footer.selectText": "to select", + "docsearch.footer.selectKeyAriaLabel": "Enter key", + "docsearch.footer.navigateText": "to navigate", + "docsearch.footer.navigateUpKeyAriaLabel": "Arrow up", + "docsearch.footer.navigateDownKeyAriaLabel": "Arrow down", + "docsearch.footer.closeText": "to close", + "docsearch.footer.closeKeyAriaLabel": "Escape key", + "docsearch.footer.searchByText": "Search by", + + "docsearch.noResultsScreen.noResultsText": "No results for", + "docsearch.noResultsScreen.suggestedQueryText": "Try searching for", + "docsearch.noResultsScreen.reportMissingResultsText": "Believe this query should return results?", + "docsearch.noResultsScreen.reportMissingResultsLinkText": "Let us know." + } + ``` + +</Steps> + +### Systèmes de recherche communautaires + +Les [modules d'extension communautaires](/fr/resources/plugins/#modules-dextension-communautaires) peuvent également fournir des alternatives au système de recherche Pagefind intégré à Starlight. + +#### Typesense DocSearch + +Le module d'extension communautaire [Starlight DocSearch Typesense](https://starlight-docsearch.typesense.org/) fournit une alternative open-source et auto-hébergeable qui intègre l'interface [DocSearch](https://github.com/typesense/typesense-docsearch.js) avec un backend [Typesense](https://typesense.org/). + +Consultez le [guide de démarrage](https://starlight-docsearch.typesense.org/getting-started/) dans la documentation de Starlight DocSearch Typesense pour apprendre comment l’utiliser dans votre projet. diff --git a/docs/src/content/docs/fr/index.mdx b/docs/src/content/docs/fr/index.mdx index a49a29b9866..b265ffdc8e5 100644 --- a/docs/src/content/docs/fr/index.mdx +++ b/docs/src/content/docs/fr/index.mdx @@ -1,61 +1,165 @@ --- title: Starlight 🌟 Construire des sites de documentation avec Astro +head: + - tag: title + content: Starlight 🌟 Construire des sites de documentation avec Astro description: Starlight vous aide à créer de magnifiques sites web de documentation très performants avec Astro. template: splash -banner: - content: | - <span class="ph-banner"> - <span class="ph-houston"><img src="/ph-houston.svg" alt="" width="72" height="72"/></span> - <span class="ph-text"> - <strong>Bienvenue Product Hunters 👋</strong> - <a href="https://www.producthunt.com/posts/starlight-by-astro">Nous sommes en direct !</a> - </span> - </span> +editUrl: false +lastUpdated: false hero: - title: Faites briller vos documents avec Starlight + title: Faites briller vos documentations avec Starlight tagline: Tout ce dont vous avez besoin pour créer un excellent site web de documentation. Rapide, accessible et facile à utiliser. image: - file: ../../../assets/hero-star.webp + file: ~/assets/hero-star.webp actions: - text: Mise en route icon: right-arrow - variant: primary link: /fr/getting-started/ - text: Voir sur GitHub icon: external + variant: minimal link: https://github.com/withastro/starlight --- import { CardGrid, Card } from '@astrojs/starlight/components'; -import AboutAstro from '../../../components/about-astro.astro'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; <CardGrid stagger> <Card title="Une documentation qui enchante" icon="open-book"> Comprend : Navigation dans le site, recherche, internationalisation, - référencement naturel, typographie facile à lire, mise en évidence du code, + référencement naturel, typographie facile à lire, coloration syntaxique, mode sombre, etc. </Card> <Card title="Propulsé par Astro" icon="rocket"> Exploitez toute la puissance et les performances d'Astro. Étendez Starlight avec vos intégrations et bibliothèques Astro préférées. </Card> - <Card title="Markdown, Markdoc, et MDX" icon="document"> - Apportez votre langage de balisage préféré. Starlight vous offre une - validation frontmatter intégrée avec la sécurité de type TypeScript. + <Card title="Markdown, Markdoc et MDX" icon="document"> + Utilisez votre langage de balisage préféré. Starlight vous offre une + validation du frontmatter intégrée avec la sûreté du typage TypeScript. </Card> <Card - title="Apportez vos propres composants d'interface utilisateur" + title="Utilisez vos propres composants d'interface utilisateur" icon="puzzle" > - Starlight est une solution de documentation complète, indépendante du cadre - de travail. Étendez avec React, Vue, Svelte, Solid, et plus encore. + Starlight est une solution de documentation complète et indépendante du + framework utilisé. Étendez-la avec React, Vue, Svelte, Solid et plus encore. </Card> </CardGrid> -<AboutAstro title="Présenté par"> -Astro est le framework web tout-en-un conçu pour la vitesse. -Tirez votre contenu de n'importe où et déployez-le partout, le tout alimenté par vos composants et bibliothèques d'interface utilisateur préférés. +<TestimonialGrid title="Ce que disent les gens"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + L'équipe d'Astro a fait ÉVOLUER la façon dont les documentations peuvent être réalisées et vous pouvez tout obtenir immédiatement avec leur projet Starlight. + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + Le kit de démarrage officiel d'Astro Starlight est un outil vraiment incroyable pour créer un site web de documentation + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + Starlight est notre meilleur exemple d'une bonne expérience de développement (DX) : la rapidité, la facilité et l'attention portée aux détails sont une source d'inspiration. + Il s'occupe de la partie technique et de l'apparence, + pour que vous puissiez vous concentrer sur votre contenu 👏 + + L'équipe de StackBlitz l'adore ! + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + Starlight a changé la donne pour moi, me permettant de me concentrer sur la création de contenu. + + Sa conception intuitive permet non seulement de simplifier ma manière de travailler, mais aussi de réduire le temps d'intégration pour les développeurs de logiciels libres. + + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + J'ai passé un peu plus de temps avec Starlight pour la documentation de Course Builder et cela s'est très bien passé jusqu'à présent. Il y a beaucoup de détails agréables et je peux me concentrer sur l'écriture en Markdown et non sur l'architecture du site. + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + J'ai commencé à jouer avec Starlight. Je dois dire que je suis très impressionné par ses performances. + + 💯💯💯💯 + + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + Starlight est la meilleure façon de démarrer une documentation, entre la puissance et la rapidité d'Astro et les outils de Starlight, c'est une combinaison parfaite. + + C'est mon outil de prédilection depuis un certain temps, et je continue à l'aimer ! + + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + J'ai utilisé Starlight à mon dernier emploi et je l'ai adoré. Excellents composants, conception intuitive + et une communauté super réactive (chaque fois que quelqu'un avait besoin de quelque chose, ils le publiaient rapidement ou proposaient une alternative). + Une expérience très agréable. + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + La documentation de mon site monorepo est plus belle que jamais grâce à Starlight. C'est extrêmement facile à utiliser sans perdre toute la puissance d'Astro. Merci d'y avoir travaillé ! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + Starlight est mon outil de référence pour la documentation. Il m'a permis d'ajouter facilement une documentation à mon site web Astro existant, au lieu d'avoir besoin d'un sous-domaine pour utiliser un autre outil. + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + J'ai reconstruit la documentation de la plateforme WPEngine Atlas. Croyez-moi quand je dis que Starlight a tout ce qu'il faut pour faire une plateforme de documentation 3 étoiles 🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + Essayez Starlight ! + + Je l'utilise pour quelques-uns de mes sites et il est excellent. + + </Testimonial> + +</TestimonialGrid> + +<AboutAstro title="Proposé par"> + Astro est un framework web tout-en-un conçu pour la rapidité. + Extrayez votre contenu de n'importe où et déployez-le partout, le tout alimenté par vos composants et bibliothèques d'interface utilisateur préférés. -[En savoir plus sur Astro](https://astro.build/) +[Découvrez Astro](https://astro.build/) </AboutAstro> diff --git a/docs/src/content/docs/fr/manual-setup.mdx b/docs/src/content/docs/fr/manual-setup.mdx index d1702f005fc..5d63b0defc1 100644 --- a/docs/src/content/docs/fr/manual-setup.mdx +++ b/docs/src/content/docs/fr/manual-setup.mdx @@ -5,7 +5,7 @@ description: Apprendre à configurer Starlight manuellement pour l'ajouter à un import { Tabs, TabItem } from '@astrojs/starlight/components'; -La façon la plus rapide de créer un nouveau site Starlight est d'utiliser `create astro` comme indiqué dans le [guide de démarrage](/fr/getting-started/#creating-a-new-project). +La façon la plus rapide de créer un nouveau site Starlight est d'utiliser `create astro` comme indiqué dans le [guide de démarrage](/fr/getting-started/#créer-un-nouveau-projet). Si vous voulez ajouter Starlight à un projet Astro existant, ce guide vous expliquera comment faire. ## Configurer Starlight @@ -16,7 +16,7 @@ Pour suivre ce guide, vous aurez besoin d'un projet Astro existant. Starlight est une [intégration Astro](https://docs.astro.build/fr/guides/integrations-guide/). Ajoutez-la à votre site en exécutant la commande `astro add` dans le répertoire racine de votre projet : -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh npx astro add starlight @@ -44,7 +44,7 @@ L'intégration Starlight est configurée dans votre fichier `astro.config.mjs`. Ajoutez un titre avec la propriété `title` pour commencer : -```js {7-9} +```js ins={8} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -62,20 +62,24 @@ Retrouvez toutes les options disponibles dans la [référence de configuration S ### Configurer les collections de contenu -Starlight s'appuie sur les [collections de contenu d'Astro](https://docs.astro.build/fr/guides/content-collections/), qui sont configurées dans le fichier `src/content/config.ts`. +Starlight s'appuie sur les [collections de contenu d'Astro](https://docs.astro.build/fr/guides/content-collections/), qui sont configurées dans le fichier `src/content.config.ts`. -Créez ou mettez à jour le fichier de configuration du contenu, en ajoutant une collection `docs` qui utilise le schéma `docsSchema` de Starlight : +Créez ou mettez à jour le fichier de configuration du contenu, en ajoutant une collection `docs` qui utilise [`docsLoader`](/fr/reference/configuration/#docsloader) et [`docsSchema`](/fr/reference/configuration/#docsschema) de Starlight : -```js ins={3,6} -// src/content/config.ts +```js ins={3-4,7} +// src/content.config.ts import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; import { docsSchema } from '@astrojs/starlight/schema'; export const collections = { - docs: defineCollection({ schema: docsSchema() }), + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), }; ``` +Starlight est également compatible avec [l'option `legacy.collections`](https://docs.astro.build/fr/reference/legacy-flags/) où les collections sont gérées en utilisant l'implémentation de collections de contenu héritée. +Celà est utile si vous avez un projet Astro existant et que vous ne pouvez pas apporter de modifications aux collections pour utiliser un chargeur. + ### Ajouter du contenu Starlight est maintenant configuré et il est temps d'ajouter du contenu ! @@ -106,7 +110,7 @@ Pour ajouter toutes les pages Starlight dans un sous-chemin, placez tout votre c Par exemple, si les pages de Starlight doivent toutes commencer par `/guides/`, ajoutez votre contenu dans le répertoire `src/content/docs/guides/` : -import FileTree from '../../../components/file-tree.astro'; +import { FileTree } from '@astrojs/starlight/components'; <FileTree> @@ -121,8 +125,10 @@ import FileTree from '../../../components/file-tree.astro'; </FileTree> -À l'avenir, nous prévoyons de mieux supporter ce cas d'utilisation pour éviter le besoin du répertoire supplémentaire dans `src/content/docs/`. +À l'avenir, nous prévoyons de mieux prendre en charge ce cas d'utilisation pour éviter le besoin du répertoire supplémentaire dans `src/content/docs/`. ### Utiliser Starlight avec SSR -À l'heure actuelle, Starlight ne supporte pas [le déploiement avec rendu côté serveur (SSR)](https://docs.astro.build/fr/guides/server-side-rendering/) en utilisant les adaptateurs de serveur d'Astro. Nous espérons pouvoir le supporter bientôt. +Pour activer le SSR, suivez le guide [« Adaptateurs de rendu à la demande »](https://docs.astro.build/fr/guides/on-demand-rendering/) dans la documentation d'Astro pour ajouter un adaptateur serveur à votre projet Starlight. + +Les pages de documentation générées par Starlight sont pré-rendues par défaut, quel que soit le mode de rendu de votre projet. Pour désactiver le pré-rendu de vos pages Starlight, définissez [l'option de configuration `prerender`](/fr/reference/configuration/#prerender) à `false`. diff --git a/docs/src/content/docs/fr/reference/configuration.md b/docs/src/content/docs/fr/reference/configuration.md deleted file mode 100644 index 9dcaa23e101..00000000000 --- a/docs/src/content/docs/fr/reference/configuration.md +++ /dev/null @@ -1,425 +0,0 @@ ---- -title: Référence de configuration -description: Une vue d'ensemble de toutes les options de configuration prises en charge par Starlight. ---- - -## Configuration de l'intégration `starlight` - -Starlight est une intégration construite sur le framework web [Astro](https://astro.build). Vous pouvez configurer votre projet dans le fichier de configuration `astro.config.mjs` : - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'Mon délicieux site de docs', - }), - ], -}); -``` - -Vous pouvez passer les options suivantes à l'intégration `starlight`. - -### `title` (obligatoire) - -**type:** `string` - -Définissez le titre de votre site web. Il sera utilisé dans les métadonnées et dans le titre de l'onglet du navigateur. - -### `description` - -**type:** `string` - -Définissez la description de votre site web. Utilisée dans les métadonnées partagées avec les moteurs de recherche dans la balise `<meta name="description">` si `description` n'est pas définie dans le frontmatter d'une page. - -### `logo` - -**type:** [`LogoConfig`](#logoconfig) - -Définit une image de logo à afficher dans la barre de navigation à côté ou à la place du titre du site. Vous pouvez soit définir une seule propriété `src`, soit définir des sources d'images séparées pour `light` et `dark`. - -```js -starlight({ - logo: { - src: './src/assets/my-logo.svg', - }, -}); -``` - -#### `LogoConfig` - -```ts -type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( - | { src: string } - | { light: string; dark: string } -); -``` - -### `tableOfContents` - -**type:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` -**default:** `{ minHeadingLevel: 2; maxHeadingLevel: 3; }` - -Configurez la table des matières affichée à droite de chaque page. Par défaut, les titres `<h2>` et `<h3>` seront inclus dans cette table des matières. - -### `editLink` - -**type:** `{ baseUrl: string }` - -Permet d'activer les liens "Modifier cette page" en définissant l'URL de base qu'ils doivent utiliser. Le lien final sera `editLink.baseUrl` + le chemin de la page actuelle. Par exemple, pour permettre l'édition de pages dans le repo `withastro/starlight` sur GitHub : - -```js -starlight({ - editLink: { - baseUrl: 'https://github.com/withastro/starlight/edit/main/', - }, -}); -``` - -Avec cette configuration, une page `/introduction` aurait un lien d'édition pointant vers `https://github.com/withastro/starlight/edit/main/src/docs/introduction.md`. - -### `sidebar` - -**type:** [`SidebarItem[]`](#sidebarittem) - -Configure les éléments de navigation de la barre latérale de votre site. - -Une barre latérale est un tableau de liens et de groupes de liens. -Chaque élément doit comporter un `label` et l'une des propriétés suivantes : - -- `link` — un lien uninque vers une URL spécifique, comme `'/home'` ou `'https://example.com'`. - -- `items` — un tableau contenant plus de liens et des sous-groupes. - -- `autogenerate` — un objet indiquant un répertoire de vos docs dpeuis lequel générer automatiquement un groupe de liens. - -```js -starlight({ - sidebar: [ - // Un lien unique étiqueté “Accueil”. - { label: 'Accueil', link: '/' }, - // Un groupe étiqueté “Débuter ici” contenant deux liens. - { - label: 'Débuter ici', - items: [ - { label: 'Introduction', link: '/intro' }, - { label: 'Prochaines étapes', link: '/next-steps' }, - ], - }, - // Un groupe liant toutes les pages présentes dans le répertoire reference. - { - label: 'Référence', - autogenerate: { directory: 'reference' }, - }, - ], -}); -``` - -#### Tri - -Les groupes de barres latérales générées automatiquement sont triés par nom de fichier et par ordre alphabétique. -Par exemple, une page générée à partir de `astro.md` apparaîtrait au-dessus de la page de `starlight.md`. - -#### Groupes rétractables - -Les groupes de liens sont développés par défaut. Vous pouvez modifier ce comportement en définissant la propriété `collapsed` d'un groupe sur `true`. - -Les sous-groupes générés automatiquement respectent la propriété `collapsed` de leur groupe parent par défaut. Définissez la propriété `autogenerate.collapsed` pour remplacer ce comportement. - -```js -sidebar: [ - // Un groupe rétractable de liens. - { - label: 'Collapsed Links', - collapsed: true, - items: [ - { label: 'Introduction', link: '/intro' }, - { label: 'Next Steps', link: '/next-steps' }, - ], - }, - // Un groupe développé contenant des sous-groupes générés automatiquement rétractés. - { - label: 'Reference', - autogenerate: { - directory: 'reference', - collapsed: true, - }, - }, -], -``` - -#### Traduire les étiquettes - -Si votre site est multilingue, le `label` de chaque élément est considéré comme étant dans la locale par défaut. Vous pouvez définir une propriété `translations` pour fournir des étiquettes pour les autres langues supportées : - -```js -sidebar: [ - // Un exemple de barre latérale avec des étiquettes traduites en anglais. - { - label: 'Commencer ici', - translations: { en: 'Start here' }, - items: [ - { - label: 'Bien démarrer', - translations: { en: 'Getting Started' }, - link: '/getting-started', - }, - { - label: 'Structure du projet', - translations: { en: 'Project Structure' }, - link: '/structure', - }, - ], - }, -]; -``` - -#### `SidebarItem` - -```ts -type SidebarItem = { - label: string; - translations?: Record<string, string>; -} & ( - | { - link: string; - badge?: string | BadgeConfig; - } - | { items: SidebarItem[] } - | { autogenerate: { directory: string } } -); -``` - -#### `BadgeConfig` - -```ts -interface BadgeConfig { - text: string; - variant: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; -} -``` - -### `locales` - -**type:** <code>{ \[dir: string\]: [LocaleConfig](#localeconfig) }</code> - -[Configurez l'internationalisation (i18n)](/fr/guides/i18n/) de votre site en définissant les `locales` supportées. - -Chaque entrée doit utiliser comme clé le répertoire dans lequel les fichiers de cette langue sont sauvegardés. - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'My Site', - // Définit l'anglais comme langue par défaut pour ce site. - defaultLocale: 'en', - locales: { - // Documentations en anglais danse trouve dans `src/content/docs/en/` - en: { - label: 'English', - }, - // Documentations en Chinois simplifié se trouve dans `src/content/docs/zh/` - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - // Documentations en Arabe se trouve dans `src/content/docs/ar/` - ar: { - label: 'العربية', - dir: 'rtl', - }, - }, - }), - ], -}); -``` - -#### `LocaleConfig` - -```ts -interface LocaleConfig { - label: string; - lang?: string; - dir?: 'ltr' | 'rtl'; -} -``` - -Vous pouvez définir les options suivantes pour chaque locale : - -##### `label` (obligatoire) - -**type:** `string` - -L'étiquette de cette langue à afficher aux utilisateurs, par exemple dans le sélecteur de langue. Le plus souvent, il s'agit du nom de la langue tel qu'un utilisateur de cette langue s'attendrait à le lire, par exemple `"English"`, `"العربية"`, ou `"简体中文"`. - -##### `lang` - -**type:** `string` - -L'étiquette d’identification BCP-47 pour cette langue, par exemple `"en"`, `"ar"`, ou `"zh-CN"`. Si elle n'est pas définie, le nom du répertoire de la langue sera utilisé par défaut. Les étiquettes de langue avec des sous-étiquettes régionales (par exemple `"pt-BR"` ou `"en-US"`) utiliseront les traductions de l'interface utilisateur intégrées pour leur langue de base si aucune traduction spécifique à la région n'est trouvée. - -##### `dir` - -**type:** `'ltr' | 'rtl'` - -Le sens d'écriture de cette langue ; `"ltr"` pour gauche à droite (par défaut) ou `"rtl"` pour droite à gauche. - -#### Locale racine - -Vous pouvez servir la langue par défaut sans répertoire `/lang/` en définissant une locale `root` : - -```js -starlight({ - locales: { - root: { - label: 'English', - lang: 'en', - }, - fr: { - label: 'Français', - }, - }, -}); -``` - -Par exemple, cela vous permet de servir `/getting-started/` comme une route anglaise et d'utiliser `/fr/getting-started/` comme la page française équivalente. - -### `defaultLocale` - -**type:** `string` - -Définit la langue par défaut pour ce site. -La valeur doit correspondre à l'une des clés de votre objet [`locales`](#locales). -(Si votre langue par défaut est votre [root locale](#locale-racine), vous pouvez sauter cette étape). - -La locale par défaut sera utilisée pour fournir un contenu de remplacement lorsque les traductions sont manquantes. - -### `social` - -**type:** `Partial<Record<'bitbucket' | 'codeberg' | 'codePen' | 'discord' | 'github' | 'gitlab' | 'gitter' | 'instagram' | 'linkedin' | 'mastodon' | 'microsoftTeams' | 'stackOverflow' | 'threads' | 'twitch' | 'twitter' | 'youtube', string>>` - -Détails optionnels sur les comptes de médias sociaux pour ce site. L'ajout de l'un d'entre eux les affichera sous forme de liens iconiques dans l'en-tête du site. - -```js -starlight({ - social: { - codeberg: 'https://codeberg.org/knut/examples', - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - gitlab: 'https://gitlab.com/delucis', - linkedin: 'https://www.linkedin.com/company/astroinc', - mastodon: 'https://m.webtoo.ls/@astro', - threads: 'https://www.threads.net/@nmoodev', - twitch: 'https://www.twitch.tv/bholmesdev', - twitter: 'https://twitter.com/astrodotbuild', - youtube: 'https://youtube.com/@astrodotbuild', - }, -}); -``` - -### `customCss` - -**type:** `string[]` - -Fournit des fichiers CSS pour personnaliser l'aspect et la convivialité de votre site Starlight. - -Prend en charge les fichiers CSS locaux relatifs à la racine de votre projet, par exemple `'./src/custom.css'`, et les CSS que vous avez installés en tant que module npm, par exemple `'@fontsource/roboto'`. - -```js -starlight({ - customCss: ['./src/custom-styles.css', '@fontsource/roboto'], -}); -``` - -### `head` - -**type:** [`HeadConfig[]`](#headconfig) - -Ajoute des balises personnalisées au `<head>` de votre site Starlight. -Cela peut être utile pour ajouter des analyses et d'autres scripts et ressources tiers. - -```js -starlight({ - head: [ - // Exemple : ajouter un script d'analyse Fathom tag. - { - tag: 'script', - attrs: { - src: 'https://cdn.usefathom.com/script.js', - 'data-site': 'MY-FATHOM-ID', - defer: true, - }, - }, - ], -}); -``` - -#### `HeadConfig` - -```ts -interface HeadConfig { - tag: string; - attrs?: Record<string, string | boolean | undefined>; - content?: string; -} -``` - -### `lastUpdated` - -**type:** `boolean` -**default:** `false` - -Contrôlez si le pied de page affiche la date de la dernière mise à jour de la page. - -Par défaut, cette fonctionnalité s'appuie sur l'historique Git de votre dépôt et peut ne pas être précise sur certaines plateformes de déploiement effectuant des -[clonages superficiels](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt). Une page peut remplacer ce paramètre ou -la date basée sur Git en utilisant [le champ `lastUpdated` du frontmatter](/fr/reference/frontmatter/#lastupdated). - -### `pagination` - -**type:** `boolean` -**default:** `true` - -Définnissez si le pied de page doit inclure des liens vers les pages précédentes et suivantes. - -Une page peut remplacer ce paramètre ou le texte du lien et/ou l'URL en utilisant les champs de frontmatter [`prev`](/fr/reference/frontmatter/#prev) et [`next`](/fr/reference/frontmatter/#next). - -### `favicon` - -**type:** `string` -**default:** `'/favicon.svg'` - -Définnissez le chemin de l'icône par défaut pour votre site Web qui doit être situé dans le répertoire `public/` et être un fichier d'icône valide (`.ico`, `.gif`, `.jpg`, `.png` ou `.svg`). - -```js -starlight({ - favicon: '/images/favicon.svg', -}), -``` - -Si vous avez besoin de définir des variantes supplémentaires ou des icônes de secours, vous pouvez ajouter des balises en utilisant l'option [`head`](#head) : - -```js -starlight({ - favicon: '/images/favicon.svg'. - head: [ - // Ajouter une icône ICO de secours pour Safari. - { - tag: 'link', - attrs: { - rel: 'icon', - href:'/images/favicon.ico', - sizes: '32x32', - }, - }, - ], -}); -``` diff --git a/docs/src/content/docs/fr/reference/configuration.mdx b/docs/src/content/docs/fr/reference/configuration.mdx new file mode 100644 index 00000000000..334050aba0e --- /dev/null +++ b/docs/src/content/docs/fr/reference/configuration.mdx @@ -0,0 +1,817 @@ +--- +title: Référence de configuration +description: Une vue d'ensemble de toutes les options de configuration prises en charge par Starlight. +--- + +## Configuration de l'intégration `starlight` + +Starlight est une intégration basée sur le framework web [Astro](https://astro.build). Vous pouvez configurer votre projet dans le fichier de configuration `astro.config.mjs` : + +```js +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Mon ravissant site de docs', + }), + ], +}); +``` + +Vous pouvez passer les options suivantes à l'intégration `starlight`. + +### `title` (obligatoire) + +**Type :** `string | Record<string, string>` + +Définissez le titre de votre site web. Il sera utilisé dans les métadonnées et dans le titre de l'onglet du navigateur. + +La valeur peut être une chaîne de caractères, ou pour les sites multilingues, un objet avec des valeurs pour chacune des différentes locales. +Lorsque vous utilisez la forme objet, les clés doivent être des étiquettes d'identification BCP-47 (par exemple `fr`, `ar`, ou `zh-CN`) : + +```ts +starlight({ + title: { + fr: 'Mon ravissant site de docs', + de: 'Meine bezaubernde Dokumentationsseite', + }, +}); +``` + +### `description` + +**Type :** `string` + +Définissez la description de votre site web. Utilisée dans les métadonnées partagées avec les moteurs de recherche dans la balise `<meta name="description">` si `description` n'est pas définie dans le frontmatter d'une page. + +### `logo` + +**Type :** [`LogoConfig`](#logoconfig) + +Définit une image de logo à afficher dans la barre de navigation à côté ou à la place du titre du site. Vous pouvez soit définir une seule propriété `src`, soit définir des sources d'images séparées pour `light` et `dark`. + +```js +starlight({ + logo: { + src: './src/assets/my-logo.svg', + }, +}); +``` + +#### `LogoConfig` + +```ts +type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( + | { src: string } + | { light: string; dark: string } +); +``` + +### `tableOfContents` + +**Type :** `false | { minHeadingLevel?: number; maxHeadingLevel?: number }` +**Par défaut :** `{ minHeadingLevel: 2, maxHeadingLevel: 3 }` + +Configurez la table des matières affichée à droite de chaque page. Par défaut, les en-têtes `<h2>` et `<h3>` seront inclus dans cette table des matières. + +### `editLink` + +**Type :** `{ baseUrl: string }` + +Active les liens « Modifier cette page » en définissant l'URL de base qu'ils doivent utiliser. Le lien final sera `editLink.baseUrl` + le chemin de la page actuelle. Par exemple, pour permettre l'édition de pages dans le dépôt `withastro/starlight` sur GitHub : + +```js +starlight({ + editLink: { + baseUrl: 'https://github.com/withastro/starlight/edit/main/', + }, +}); +``` + +Avec cette configuration, une page `/introduction` aurait un lien d'édition pointant vers `https://github.com/withastro/starlight/edit/main/src/content/docs/introduction.md`. + +### `sidebar` + +**Type :** [`SidebarItem[]`](#sidebaritem) + +Configure les éléments de navigation de la barre latérale de votre site. + +Une barre latérale est un tableau de liens et de groupes de liens. +À l'exception des éléments utilisant `slug`, chaque élément doit comporter un `label` et l'une des propriétés suivantes : + +- `link` — un lien vers une URL spécifique, comme `'/home'` ou `'https://example.com'`. + +- `slug` — une référence à une page interne, par exemple `'guides/getting-started'`. + +- `items` — un tableau contenant plus de liens et des sous-groupes. + +- `autogenerate` — un objet spécifiant un répertoire de votre documentation à partir duquel générer automatiquement un groupe de liens. + +Les liens internes peuvent également être spécifiés sous forme de chaîne de caractères au lieu d'un objet avec une propriété `slug`. + +```js +starlight({ + sidebar: [ + // Un lien unique étiqueté « Accueil ». + { label: 'Accueil', link: '/' }, + // Un groupe étiqueté « Débuter ici » contenant quatre liens. + { + label: 'Débuter ici', + items: [ + // Utilisation de `slug` pour les liens internes. + { slug: 'intro' }, + { slug: 'installation' }, + // Ou la forme simplifiée pour les liens internes. + 'tutorial', + 'next-steps', + ], + }, + // Un groupe liant toutes les pages présentes dans le répertoire reference. + { + label: 'Référence', + autogenerate: { directory: 'reference' }, + }, + ], +}); +``` + +#### Tri + +Les groupes de barres latérales générées automatiquement sont triés par nom de fichier et par ordre alphabétique. +Par exemple, une page générée à partir de `astro.md` apparaîtrait au-dessus de la page de `starlight.md`. + +#### Groupes rétractables + +Les groupes de liens sont développés par défaut. Vous pouvez modifier ce comportement en définissant la propriété `collapsed` d'un groupe sur `true`. + +Les sous-groupes générés automatiquement respectent la propriété `collapsed` de leur groupe parent par défaut. Définissez la propriété `autogenerate.collapsed` pour remplacer ce comportement. + +```js {5,13} +sidebar: [ + // Un groupe rétractable de liens. + { + label: 'Liens rétractés', + collapsed: true, + items: ['intro', 'next-steps'], + }, + // Un groupe développé contenant des sous-groupes générés automatiquement rétractés. + { + label: 'Référence', + autogenerate: { + directory: 'reference', + collapsed: true, + }, + }, +], +``` + +#### Traduire les étiquettes + +Si votre site est multilingue, le `label` de chaque élément est considéré comme étant dans la locale par défaut. Vous pouvez définir une propriété `translations` pour fournir des étiquettes pour les autres langues prises en charge : + +```js {5,9,14} +sidebar: [ + // Un exemple de barre latérale avec des étiquettes traduites en portugais brésilien. + { + label: 'Commencer ici', + translations: { 'pt-BR': 'Comece Aqui' }, + items: [ + { + label: 'Bien démarrer', + translations: { 'pt-BR': 'Introdução' }, + link: '/getting-started', + }, + { + label: 'Structure du projet', + translations: { 'pt-BR': 'Estrutura de Projetos' }, + link: '/structure', + }, + ], + }, +]; +``` + +#### `SidebarItem` + +```ts +type SidebarItem = + | string + | ({ + translations?: Record<string, string>; + badge?: string | BadgeConfig; + } & ( + | { + // Lien + link: string; + label: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // Lien interne + slug: string; + label?: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // Groupe de liens + label: string; + items: SidebarItem[]; + collapsed?: boolean; + } + | { + // Groupe de liens généré automatiquement + label: string; + autogenerate: { + directory: string; + collapsed?: boolean; + attrs?: Record<string, string | number | boolean | undefined>; + }; + collapsed?: boolean; + } + )); +``` + +#### `BadgeConfig` + +```ts +interface BadgeConfig { + text: string; + variant?: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; + class?: string; +} +``` + +### `locales` + +**Type :** <code>\{ \[dir: string\]: [LocaleConfig](#localeconfig) \}</code> + +[Configurez l'internationalisation (i18n)](/fr/guides/i18n/) de votre site en définissant les `locales` prises en charge. + +Chaque entrée doit utiliser comme clé le répertoire dans lequel les fichiers de cette langue sont sauvegardés. + +```js +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'My Site', + // Définit l'anglais comme langue par défaut pour ce site. + defaultLocale: 'en', + locales: { + // Documentation en anglais située dans `src/content/docs/en/` + en: { + label: 'English', + }, + // Documentation en Chinois simplifié située dans `src/content/docs/zh-cn/` + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + // Documentation en Arabe située dans `src/content/docs/ar/` + ar: { + label: 'العربية', + dir: 'rtl', + }, + }, + }), + ], +}); +``` + +#### `LocaleConfig` + +```ts +interface LocaleConfig { + label: string; + lang?: string; + dir?: 'ltr' | 'rtl'; +} +``` + +Vous pouvez définir les options suivantes pour chaque locale : + +##### `label` (obligatoire) + +**Type :** `string` + +L'étiquette de cette langue à afficher aux utilisateurs, par exemple dans le sélecteur de langue. Le plus souvent, il s'agit du nom de la langue tel qu'un utilisateur de cette langue s'attendrait à le lire, par exemple `"English"`, `"العربية"`, ou `"简体中文"`. + +##### `lang` + +**Type :** `string` + +L'étiquette d’identification BCP-47 pour cette langue, par exemple `"en"`, `"ar"`, ou `"zh-CN"`. Si elle n'est pas définie, le nom du répertoire de la langue sera utilisé par défaut. Les étiquettes de langue avec des sous-étiquettes régionales (par exemple `"pt-BR"` ou `"en-US"`) utiliseront les traductions de l'interface utilisateur intégrées pour leur langue de base si aucune traduction spécifique à la région n'est trouvée. + +##### `dir` + +**Type :** `'ltr' | 'rtl'` + +Le sens d'écriture de cette langue ; `"ltr"` pour gauche à droite (par défaut) ou `"rtl"` pour droite à gauche. + +#### Locale racine + +Vous pouvez servir la langue par défaut sans répertoire `/lang/` en définissant une locale avec la clé `root` : + +```js {3-6} +starlight({ + locales: { + root: { + label: 'English', + lang: 'en', + }, + fr: { + label: 'Français', + }, + }, +}); +``` + +Par exemple, cela vous permet de servir `/getting-started/` comme une route anglaise et d'utiliser `/fr/getting-started/` comme la page française équivalente. + +### `defaultLocale` + +**Type :** `string` + +Définit la langue par défaut pour ce site. +La valeur doit correspondre à l'une des clés de votre objet [`locales`](#locales). +(Si votre langue par défaut est votre [locale racine](#locale-racine), vous pouvez sauter cette étape). + +La locale par défaut sera utilisée pour fournir un contenu de remplacement lorsque les traductions sont manquantes. + +### `social` + +**Type :** <code>{`Array<{ label: string; icon: `}[StarlightIcon](/fr/reference/icons/){`; href: string }>`}</code> + +Détails optionnels sur les comptes de médias sociaux pour ce site. +Chaque entrée sera affichée sous forme de lien iconisé dans l'en-tête du site. + +```js +starlight({ + social: [ + { icon: 'codeberg', label: 'Codeberg', href: 'https://codeberg.org/knut' }, + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro' }, + { icon: 'gitlab', label: 'GitLab', href: 'https://gitlab.com/delucis' }, + { icon: 'mastodon', label: 'Mastodon', href: 'https://m.webtoo.ls/@astro' }, + ], +}), +``` + +### `customCss` + +**Type :** `string[]` + +Fournit des fichiers CSS pour personnaliser l'aspect et la convivialité de votre site Starlight. + +Prend en charge les fichiers CSS locaux relatifs à la racine de votre projet, par exemple `'./src/custom.css'`, et les CSS que vous avez installés en tant que module npm, par exemple `'@fontsource/roboto'`. + +```js +starlight({ + customCss: ['./src/custom-styles.css', '@fontsource/roboto'], +}); +``` + +### `markdown` + +**Type :** `{ headingLinks?: boolean; processedDirs?: string[] }` +**Par défaut :** `{ headingLinks: true, processedDirs: [] }` + +Configure le traitement de contenu Markdown par Starlight. + +#### `headingLinks` + +**Type :** `boolean` +**Par défaut :** `true` + +Définit si les en-têtes sont affichés avec des liens d'ancrage cliquables ou non. + +```js +starlight({ + markdown: { + // Désactive les liens d'ancrage cliquables pour les en-têtes. + headingLinks: false, + }, +}), +``` + +#### `processedDirs` + +**Type :** `string[]` +**Par défaut :** `[]` + +Définit les répertoires supplémentaires contenant les fichiers qui doivent être ajoutés à la chaîne de traitement Markdown de Starlight. +Par défaut, seuls les contenus Markdown et MDX chargés à l'aide de [`docsLoader()`](/fr/reference/configuration/#docsloader) de Starlight sont traités. +Prend en charge les répertoires locaux relatifs à la racine de votre projet, par exemple `'./src/data/comments/'`. + +Le traitement de Starlight inclut la prise en charge des [liens d'ancrage cliquables des en-têtes](#headinglinks), de la [syntaxe de directive Markdown pour les encarts](/fr/guides/authoring-content/#encarts) et du sens d'écriture RTL dans les blocs de code. +Cette option peut être utile si vous affichez du contenu provenant d'une collection de contenu personnalisée dans une [page personnalisée](/fr/guides/pages/#pages-personnalisées) à l'aide du composant `<StarlightPage>` et que vous vous attendez à ce que le traitement Markdown de Starlight soit également appliqué à ce contenu. + +```js +starlight({ + markdown: { + // Traiter les fichiers Markdown de la collection de contenu `reviews` située dans le + // répertoire `src/data/reviews/`. + processedDirs: ['./src/data/reviews/'], + }, +}), +``` + +### `expressiveCode` + +**Type :** `StarlightExpressiveCodeOptions | boolean` +**Par défaut :** `true` + +Starlight utilise [Expressive Code](https://expressive-code.com) pour afficher les blocs de code et ajouter la prise en charge de la mise en évidence des portions d'exemples de code, de l'ajout de noms de fichiers aux blocs de code, et plus encore. +Consultez le [guide « Blocs de code »](/fr/guides/authoring-content/#blocs-de-code) pour apprendre à utiliser la syntaxe d'Expressive Code dans votre contenu Markdown et MDX. + +Vous pouvez utiliser n'importe laquelle des [options de configuration standard d'Expressive Code](https://expressive-code.com/reference/configuration/) ainsi que certaines propriétés spécifiques à Starlight, en les définissant dans l'option `expressiveCode` de Starlight. +Par exemple, définissez l'option `styleOverrides` d'Expressive Code pour remplacer le CSS par défaut. Cela permet des personnalisations comme donner à vos blocs de code des coins arrondis : + +```js ins={2-4} +starlight({ + expressiveCode: { + styleOverrides: { borderRadius: '0.5rem' }, + }, +}); +``` + +Si vous souhaitez désactiver Expressive Code, définissez `expressiveCode: false` dans votre configuration de Starlight : + +```js ins={2} +starlight({ + expressiveCode: false, +}); +``` + +En plus des options standard d'Expressive Code, vous pouvez également définir les propriétés suivantes spécifiques à Starlight dans votre configuration `expressiveCode` pour personnaliser davantage le comportement du thème pour vos blocs de code : + +#### `themes` + +**Type :** `Array<string | ThemeObject | ExpressiveCodeTheme>` +**Par défaut :** `['starlight-dark', 'starlight-light']` + +Définit les thèmes utilisés pour mettre en forme les blocs de code. +Consultez la [documentation des `themes` d'Expressive Code](https://expressive-code.com/guides/themes/) pour plus de détails sur les formats de thème pris en charge. + +Starlight utilise les variantes claires et sombres du [thème Night Owl](https://github.com/sdras/night-owl-vscode-theme) de Sarah Drasner par défaut. + +Si vous définissez au moins un thème clair et un thème sombre, Starlight gardera automatiquement le thème de bloc de code actif en phase avec le thème actuel du site. +Configurez ce comportement avec l'option [`useStarlightDarkModeSwitch`](#usestarlightdarkmodeswitch). + +#### `useStarlightDarkModeSwitch` + +**Type :** `boolean` +**Par défaut :** `true` + +Lorsque la valeur est `true`, les blocs de code basculent automatiquement entre les thèmes clairs et sombres lorsque le thème du site change. +Lorsque la valeur est `false`, vous devez ajouter manuellement du CSS pour gérer le basculement entre plusieurs thèmes. + +:::note +Quand `themes` est défini, vous devez fournir au moins un thème sombre et un thème clair pour que le changement en mode sombre de Starlight fonctionne. +::: + +#### `useStarlightUiThemeColors` + +**Type :** `boolean` +**Par défaut :** `true` si `themes` n'est pas défini, sinon `false` + +Lorsque la valeur est `true`, les variables CSS de Starlight sont utilisées pour les couleurs des éléments d'interface utilisateur des blocs de code (arrière-plans, boutons, ombres, etc.), uniformément avec le [thème de couleur du site](/fr/guides/css-and-tailwind/#personnalisation-du-thème). +Lorsque la valeur est `false`, les couleurs fournies par le thème de coloration syntaxique actif sont utilisées pour ces éléments. + +:::note +Lorsque des thèmes personnalisés sont utilisés et que cette option est définie à `true`, vous devez fournir au moins un thème sombre et un thème clair pour assurer un contraste de couleur approprié. +::: + +### `pagefind` + +**Type :** <code>boolean | <a href="#pagefindoptions">PagefindOptions</a></code> +**Par défaut :** `false` + +Configure le système de recherche du site par défaut de Starlight, [Pagefind](https://pagefind.app/). + +Utilisez la valeur `false` pour désactiver l'indexation de votre site avec Pagefind. +Cela désactivera également l'interface de recherche par défaut de Starlight si utilisée. + +Pagefind ne peut pas être activé lorsque l'option [`prerender`](#prerender) est définie à `false`. + +Définissez `pagefind` avec un objet pour configurer le client de recherche Pagefind : + +- Consultez [« Personnaliser le classement des résultats de Pagefind »](https://pagefind.app/docs/ranking/) dans la documentation de Pagefind pour plus de détails sur l'utilisation de l'option `pagefind.ranking` pour contrôler comment le classement des résultats de recherche est calculé +- Consultez [« Recherche sur plusieurs sites »](https://pagefind.app/docs/multisite/) dans la documentation de Pagefind pour plus de détails sur l'utilisation de l'option `pagefind.mergeIndex` pour contrôler comment rechercher sur plusieurs sites + +#### `PagefindOptions` + +```ts +interface PagefindOptions { + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + indexWeight?: number; + mergeIndex?: Array<{ + bundlePath: string; + indexWeight?: number; + basePath?: string; + baseUrl?: string; + mergeFilter?: Record<string, string | string[]>; + language?: string; + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + }>; +} +``` + +### `prerender` + +**Type :** `boolean` +**Par défaut :** `true` + +Définit si les pages générées par Starlight doivent être pré-rendues en HTML statique ou rendues à la demande par un [adaptateur SSR](https://docs.astro.build/fr/guides/on-demand-rendering/). + +Les pages Starlight sont pré-rendues par défaut. +Si vous utilisez un adaptateur SSR et que vous souhaitez générer les pages Starlight à la demande, définissez `prerender: false`. + +### `head` + +**Type :** [`HeadConfig[]`](#headconfig) + +Ajoute des balises personnalisées au `<head>` de votre site Starlight. +Cela peut être utile pour ajouter une solution de mesure d'audience ou d'autres ressources et scripts tiers. + +```js +starlight({ + head: [ + // Exemple : ajouter une balise pour le script de suivi de Fathom + { + tag: 'script', + attrs: { + src: 'https://cdn.usefathom.com/script.js', + 'data-site': 'MON-ID-FATHOM', + defer: true, + }, + }, + ], +}); +``` + +Les entrées dans `head` sont converties directement en éléments HTML et ne passent pas par le traitement de [script](https://docs.astro.build/fr/guides/client-side-scripts/#traitement-des-scripts) ou de [style](https://docs.astro.build/fr/guides/styling/#mettre-en-forme-avec-astro) d'Astro. +Si vous avez besoin d'importer des ressources locales comme des scripts, des styles ou des images, [redéfinissez le composant Head](/fr/guides/overriding-components/#réutiliser-un-composant-intégré). + +#### `HeadConfig` + +```ts +interface HeadConfig { + tag: string; + attrs?: Record<string, string | boolean | undefined>; + content?: string; +} +``` + +### `lastUpdated` + +**Type :** `boolean` +**Par défaut :** `false` + +Contrôlez si le pied de page affiche la date de la dernière mise à jour de la page. + +Par défaut, cette fonctionnalité s'appuie sur l'historique Git de votre dépôt et peut ne pas être précise sur certaines plateformes de déploiement effectuant des [clonages superficiels](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt). Une page peut remplacer ce paramètre ou la date basée sur Git en utilisant [le champ `lastUpdated` du frontmatter](/fr/reference/frontmatter/#lastupdated). + +### `pagination` + +**Type :** `boolean` +**Par défaut :** `true` + +Définissez si le pied de page doit inclure des liens vers les pages précédentes et suivantes. + +Une page peut remplacer ce paramètre ou le texte du lien et/ou l'URL en utilisant les champs de frontmatter [`prev`](/fr/reference/frontmatter/#prev) et [`next`](/fr/reference/frontmatter/#next). + +### `favicon` + +**Type :** `string` +**Par défaut :** `'/favicon.svg'` + +Définissez le chemin de l'icône par défaut pour votre site Web qui doit être situé dans le répertoire `public/` et être un fichier d'icône valide (`.ico`, `.gif`, `.jpg`, `.png` ou `.svg`). + +```js +starlight({ + favicon: '/images/favicon.svg', +}), +``` + +Si vous avez besoin de définir des variantes supplémentaires ou des icônes de secours, vous pouvez ajouter des balises en utilisant l'option [`head`](#head) : + +```js +starlight({ + favicon: '/images/favicon.svg', + head: [ + // Ajouter une icône ICO de secours pour Safari. + { + tag: 'link', + attrs: { + rel: 'icon', + href: '/images/favicon.ico', + sizes: '32x32', + }, + }, + ], +}); +``` + +### `titleDelimiter` + +**Type :** `string` +**Par défaut :** `'|'` + +Définit le délimiteur entre le titre de la page et le titre du site dans la balise `<title>` de la page, qui s'affiche dans les onglets du navigateur. + +Par défaut, chaque page a une balise `<title>` contenant `Titre de la page | Titre du site`. +Par example, cette page a pour titre « Référence de configuration » et ce site a pour titre « Starlight », donc la balise `<title>` de cette page contient « Référence de configuration | Starlight ». + +### `disable404Route` + +**Type :** `boolean` +**Par défaut :** `false` + +Désactive l'injection de la [page 404](https://docs.astro.build/fr/basics/astro-pages/#page-derreur-404-personnalis%C3%A9e) par défaut de Starlight. Pour utiliser une route personnalisée `src/pages/404.astro` dans votre projet, définissez cette option à `true`. + +### `routeMiddleware` + +**Type :** `string | string[]` + +Fournit les chemins vers les middlewares de route qui peuvent modifier la manière dont Starlight transforme vos données. +Ces chemins de fichiers ne doivent pas entrer en conflit avec les [middlewares d'Astro](https://docs.astro.build/fr/guides/middleware/). + +Consultez le [guide des données de route](/fr/guides/route-data/#personnalisation-des-données-de-route) pour plus de détails sur la création de middlewares de route. + +### `components` + +**Type :** `Record<string, string>` + +Fournit les chemins vers les composants pour redéfinir les implémentations par défaut de Starlight. + +```js +starlight({ + components: { + SocialLinks: './src/components/MySocialLinks.astro', + }, +}); +``` + +Consultez la [référence des redéfinitions](/fr/reference/overrides/) pour plus de détails sur tous les composants que vous pouvez redéfinir. + +### `plugins` + +**Type :** [`StarlightPlugin[]`](/fr/reference/plugins/#référence-rapide-de-lapi) + +Étendez Starlight avec des modules d'extension personnalisés. +Les modules d'extension appliquent des changements à votre projet pour modifier ou ajouter des fonctionnalités à Starlight. + +Visitez la [vitrine des modules d'extension](/fr/resources/plugins/#modules-dextension) pour voir une liste des modules d'extension disponibles. + +```js +starlight({ + plugins: [starlightPlugin()], +}); +``` + +Consultez la [référence des modules d'extension](/fr/reference/plugins/) pour plus de détails pour créer vos propres modules d'extension. + +### `credits` + +**Type :** `boolean` +**Par défaut :** `false` + +Permet l'affichage d'un lien « Créé avec Starlight » dans le pied de page de votre site. + +```js +starlight({ + credits: true, +}); +``` + +## Configuration des collections de contenu + +Starlight utilise les [collections de contenu d'Astro](https://docs.astro.build/fr/guides/content-collections/) pour charger votre contenu. +Les chargeurs (également connus sous le nom de « loaders » en anglais) et schémas de collection de Starlight aident à configurer les collections comme nécessaire. + +```js +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + // Optionnel : la collection i18n est utilisée pour traduire l'interface + // utilisateur dans les sites multilingues + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), +}; +``` + +### Chargeurs + +Starlight exporte les [chargeurs Astro](https://docs.astro.build/fr/reference/content-loader-reference/) suivants depuis le module `@astrojs/starlight/loaders` pour simplifier la configuration des collections de contenu. + +#### `docsLoader()` + +Le chargeur `docsLoader()` charge les fichiers Markdown, MDX et Markdoc locaux du répertoire `src/content/docs/`. +Les fichiers commençant par un tiret bas (`_`) sont ignorés. + +##### Importation + +```js +import { docsLoader } from '@astrojs/starlight/loaders'; +``` + +##### Options + +###### `generateId()` + +**Type :** `({ entry: string; base: URL; data: Record<string, unknown> }) => string` + +Par défaut, les pages générées en utilisant `docsLoader()` transforment les noms de fichiers en utilisant un générateur de slug qui supprime les caractères spéciaux et met le nom de fichier en minuscules. +Si vous souhaitez remplacer ce comportement par défaut, spécifiez votre propre fonction `generateId()`. + +Par exemple, cela peut être utile pour préserver des caractères spéciaux qui seraient supprimés. +Par défaut, `Exemple.Fichier.md` serait diponible à l'URL `/exemplefichier`. +Si vous souhaitez le rendre disponible à l'URL `/Exemple.Fichier`, vous pouvez le faire en définissant une fonction `generateId()` personnalisée : + +```js +docsLoader({ + // Supprime les extension `.md` ou `.mdx` sans modifier les noms de fichiers. + generateId: ({ entry }) => entry.split('.').slice(0, -1).join('.'), +}), +``` + +Consultez [`generateId()` dans la documentation d'Astro](https://docs.astro.build/fr/reference/content-loader-reference/#generateid) pour plus de détails. + +#### `i18nLoader()` + +Le chargeur `i18nLoader()` charge les fichiers JSON et YAML locaux du répertoire `src/content/i18n/`. +Les fichiers commençant par un tiret bas (`_`) sont ignorés. + +##### Importation + +```js +import { i18nLoader } from '@astrojs/starlight/loaders'; +``` + +##### Options + +Il n'y a pour le moment aucune option pour configurer `i18nLoader()`. + +### Schémas + +Starlight fournit les [schémas de collection de contenu](https://docs.astro.build/fr/guides/content-collections/#d%C3%A9finition-dun-sch%C3%A9ma-de-collection) suivants depuis le module `@astrojs/starlight/schema`. +Ces schémas doivent être utilisés pour les collections `docs` et `i18n` dont Starlight dépend. + +#### `docsSchema()` + +Le chargeur `docsSchema()` analyse (opération également appelée « parse » en anglais) le frontmatter de tout le contenu de la collection `docs`. + +##### Importation + +```js +import { docsSchema } from '@astrojs/starlight/schema'; +``` + +##### Options + +###### `extend` + +**Type :** Schéma Zod ou fonction qui retourne un schéma Zod +**Par défaut :** `z.object({})` + +Étendez le schéma du frontmatter de Starlight avec des champs supplémentaires. +Consultez [« Personnaliser le schéma du frontmatter »](/fr/reference/frontmatter/#personnaliser-le-schéma-du-frontmatter) pour plus de détails sur l'utilisation de l'option `extend`. + +#### `i18nSchema()` + +Le chargeur `i18nSchema()` analyse tous les fichiers de données dans la collection `i18n`. + +##### Importation + +```js +import { i18nSchema } from '@astrojs/starlight/schema'; +``` + +##### Options + +###### `extend` + +**Type :** Objet Zod +**Par défaut :** `z.object({})` + +Étendez le schéma de traduction de Starlight avec des champs supplémentaires. +Consultez [« Étendre le schéma de traduction »](/fr/guides/i18n/#étendre-le-schéma-de-traduction) pour plus de détails sur l'utilisation de l'option `extend`. diff --git a/docs/src/content/docs/fr/reference/frontmatter.md b/docs/src/content/docs/fr/reference/frontmatter.md index 06ca8890c6b..a9d3e1815c5 100644 --- a/docs/src/content/docs/fr/reference/frontmatter.md +++ b/docs/src/content/docs/fr/reference/frontmatter.md @@ -5,8 +5,9 @@ description: Une vue d'ensemble des champs du frontmatter par défaut pris en ch Vous pouvez personnaliser des pages Markdown et MDX individuelles dans Starlight en définissant des valeurs dans leur frontmatter. Par exemple, une page normale peut définir les champs `title` et `description` : -```md +```md {3-4} --- +# src/content/docs/exemple.md title: A propos de ce projet description: En savoir plus sur le projet sur lequel je travaille. --- @@ -18,30 +19,37 @@ Bienvenue sur la page "à propos" ! ### `title` (obligatoire) -**type:** `string` +**Type :** `string` Vous devez fournir un titre pour chaque page. Il sera affiché en haut de la page, dans les onglets du navigateur et dans les métadonnées de la page. ### `description` -**type:** `string` +**Type :** `string` La description de la page est utilisée pour les métadonnées de la page et sera reprise par les moteurs de recherche et dans les aperçus des médias sociaux. +### `slug` + +**type**: `string` + +Remplace le slug de la page. Consultez [« Définition d’identifiants personnalisés »](https://docs.astro.build/fr/guides/content-collections/#définition-didentifiants-personnalisés) dans la documentation d'Astro pour plus de détails. + ### `editUrl` -**type:** `string | boolean` +**Type :** `string | boolean` -Remplace la [configuration globale `editLink`](/fr/reference/configuration/#editlink). Mettez `false` pour désactiver le lien "Modifier cette page" pour une page spécifique ou pour fournir une URL alternative où le contenu de cette page est éditable. +Remplace la [configuration globale `editLink`](/fr/reference/configuration/#editlink). Mettez `false` pour désactiver le lien « Modifier cette page » pour une page spécifique ou pour fournir une URL alternative où le contenu de cette page est éditable. ### `head` -**type:** [`HeadConfig[]`](/fr/reference/configuration/#headconfig) +**Type :** [`HeadConfig[]`](/fr/reference/configuration/#headconfig) Vous pouvez ajouter des balises supplémentaires au champ `<head>` de votre page en utilisant le champ `head` frontmatter. Cela signifie que vous pouvez ajouter des styles personnalisés, des métadonnées ou d'autres balises à une seule page. Similaire à [l'option globale `head`](/fr/reference/configuration/#head). ```md --- +# src/content/docs/exemple.md title: A propos de nous head: # Utiliser une balise <title> personnalisée @@ -52,14 +60,15 @@ head: ### `tableOfContents` -**type:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` +**Type :** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` Remplace la [configuration globale `tableOfContents`](/fr/reference/configuration/#tableofcontents). Personnalisez les niveaux d'en-tête à inclure ou mettez `false` pour cacher la table des matières sur cette page. ```md --- -title: Pagee avec seulement des H2s dans la table des matières +# src/content/docs/exemple.md +title: Page avec seulement des H2 dans la table des matières tableOfContents: minHeadingLevel: 2 maxHeadingLevel: 2 @@ -68,6 +77,7 @@ tableOfContents: ```md --- +# src/content/docs/exemple.md title: Page sans table des matières tableOfContents: false --- @@ -75,16 +85,16 @@ tableOfContents: false ### `template` -**type:** `'doc' | 'splash'` -**default:** `'doc'` +**Type :** `'doc' | 'splash'` +**Par défaut :** `'doc'` Définit le modèle de mise en page pour cette page. Les pages utilisent la mise en page `'doc'`' par défaut. -La valeur `'splash''` permet d'utiliser une mise en page plus large, sans barres latérales, conçue pour les pages d'atterrissage. +La valeur `'splash'` permet d'utiliser une mise en page plus large, sans barres latérales, conçue pour les pages d'atterrissage. ### `hero` -**type:** [`HeroConfig`](#heroconfig) +**Type :** [`HeroConfig`](#heroconfig) Ajoute un composant héros en haut de la page. Fonctionne bien avec `template : splash`. @@ -92,6 +102,7 @@ Par exemple, cette configuration montre quelques options communes, y compris le ```md --- +# src/content/docs/exemple.md title: Ma page d'accueil template: splash hero: @@ -104,10 +115,25 @@ hero: - text: En savoir plus link: /getting-started/ icon: right-arrow - variant: primary - text: Voir sur GitHub link: https://github.com/astronaut/my-project icon: external + variant: minimal + attrs: + rel: me +--- +``` + +Vous pouvez afficher différentes versions de l'image de premier plan en mode clair et sombre. + +```md +--- +# src/content/docs/exemple.md +hero: + image: + alt: Un logo scintillant aux couleurs vives + dark: ../../assets/logo-dark.png + light: ../../assets/logo-light.png --- ``` @@ -117,26 +143,39 @@ hero: interface HeroConfig { title?: string; tagline?: string; - image?: { - alt?: string; - // Chemin relatif vers une image dans votre dépôt. - file?: string; - // HTML brut à utiliser dans l'emplacement de l'image. - // Il peut s'agir d'une balise `<img>` personnalisée ou d'une balise `<svg>` en ligne. - html?: string; - }; + image?: + | { + // Chemin relatif vers une image dans votre dépôt. + file: string; + // Alternative textuelle pour rendre l'image accessible aux technologies d'assistance. + alt?: string; + } + | { + // Chemin relatif vers une image dans votre dépôt à utiliser pour le mode sombre. + dark: string; + // Chemin relatif vers une image dans votre dépôt à utiliser pour le mode clair. + light: string; + // Alternative textuelle pour rendre l'image accessible aux technologies d'assistance. + alt?: string; + } + | { + // HTML brut à utiliser dans le slot de l'image. + // Peut être une balise `<img>` personnalisée ou une balise `<svg>` en ligne. + html: string; + }; actions?: Array<{ text: string; link: string; - variant: 'primary' | 'secondary' | 'minimal'; - icon: string; + variant?: 'primary' | 'secondary' | 'minimal'; + icon?: string; + attrs?: Record<string, string | number | boolean>; }>; } ``` ### `banner` -**type:** `{ content: string }` +**Type :** `{ content: string }` Montrera une bannière d'annonce en haut de cette page. @@ -145,6 +184,7 @@ Par exemple, cette page affiche une bannière comprenant un lien vers `example.c ```md --- +# src/content/docs/exemple.md title: Page avec une bannière banner: content: | @@ -155,12 +195,13 @@ banner: ### `lastUpdated` -**type:** `Date | boolean` +**Type :** `Date | boolean` Remplace la [configuration globale `lastUpdated`](/fr/reference/configuration/#lastupdated). Si une date est spécifiée, elle doit être un [horodatage YAML](https://yaml.org/type/timestamp.html) valide et remplacera la date stockée dans l'historique Git pour cette page. ```md --- +# src/content/docs/exemple.md title: Page avec une date de dernière mise à jour personnalisée lastUpdated: 2022-08-09 --- @@ -168,12 +209,13 @@ lastUpdated: 2022-08-09 ### `prev` -**type:** `boolean | string | { link?: string; label?: string }` +**Type :** `boolean | string | { link?: string; label?: string }` -Remplace la [configuration globale `pagination`](/fr/reference/configuration/#pagination). Si un string est spécifié, le texte du lien généré sera remplacé et si un objet est spécifié, le lien et le texte seront remplacés. +Remplace la [configuration globale `pagination`](/fr/reference/configuration/#pagination). Si une chaîne de caractères est spécifiée, le texte du lien généré sera remplacé et si un objet est spécifié, le lien et le texte seront remplacés. ```md --- +# src/content/docs/exemple.md # Masquer le lien de la page précédente prev: false --- @@ -181,13 +223,15 @@ prev: false ```md --- +# src/content/docs/exemple.md # Remplacer le texte du lien de la page -prev: Poursuivre the tutorial +prev: Poursuivre le tutoriel --- ``` ```md --- +# src/content/docs/exemple.md # Remplacer le lien et le texte de la page prev: link: /unrelated-page/ @@ -197,12 +241,13 @@ prev: ### `next` -**type:** `boolean | string | { link?: string; label?: string }` +**Type :** `boolean | string | { link?: string; label?: string }` La même chose que [`prev`](#prev) mais pour le lien de la page suivante. ```md --- +# src/content/docs/exemple.md # Masquer le lien de la page suivante next: false --- @@ -210,48 +255,81 @@ next: false ### `pagefind` -**type:** `boolean` -**default:** `true` +**Type :** `boolean` +**Par défaut :** `true` Définit si cette page doit être incluse dans l'index de recherche de [Pagefind](https://pagefind.app/). Définissez la valeur à `false` pour exclure une page des résultats de recherche : ```md --- +# src/content/docs/exemple.md # Exclut cette page de l'index de recherche pagefind: false --- ``` +### `draft` + +**Type :** `boolean` +**Par défaut :** `false` + +Définit si cette page doit être considérée comme une ébauche et ne pas être incluse dans les [déploiements en production](https://docs.astro.build/fr/reference/cli-reference/#astro-build). Définissez la valeur à `true` pour marquer une page comme une ébauche et la rendre visible uniquement pendant le développement. + +```md +--- +# src/content/docs/exemple.md +# Exclure cette page des déploiements en production +draft: true +--- +``` + +Puisque les ébauches ne sont pas incluses lors d'un déploiement, vous ne pouvez pas ajouter des ébauches directement à la configuration de la barre latérale de navigation de votre site en utilisant des [slugs](/fr/guides/sidebar/#liens-internes). +Les ébauches situées dans des répertoires utilisés dans des [groupes de barre latérale générés automatiquement](/fr/guides/sidebar/#groupes-générés-automatiquement) sont automatiquement exclues des déploiements en production. + ### `sidebar` -**type:** `{ label?: string; order?: number; hidden?: boolean; badge?: string | BadgeConfig }` +**Type :** [`SidebarConfig`](#sidebarconfig) Contrôler l'affichage de cette page dans la [barre latérale](/fr/reference/configuration/#sidebar), lors de l'utilisation d'un groupe de liens généré automatiquement. +#### `SidebarConfig` + +```ts +interface SidebarConfig { + label?: string; + order?: number; + hidden?: boolean; + badge?: string | BadgeConfig; + attrs?: Record<string, string | number | boolean | undefined>; +} +``` + #### `label` -**type:** `string` -**default:** the page [`title`](#title-required) +**Type :** `string` +**Par défaut :** [`title`](#title-obligatoire) de la page Définir l'étiquette de cette page dans la barre latérale lorsqu'elle est affichée dans un groupe de liens généré automatiquement. ```md --- -title: About this project +# src/content/docs/exemple.md +title: À propos de ce projet sidebar: - label: About + label: À propos --- ``` #### `order` -**type:** `number` +**Type :** `number` Contrôler l'ordre de cette page lors du tri d'un groupe de liens généré automatiquement. Les numéros inférieurs sont affichés plus haut dans le groupe de liens. ```md --- +# src/content/docs/exemple.md title: Page à afficher en premier sidebar: order: 1 @@ -260,13 +338,14 @@ sidebar: #### `hidden` -**type:** `boolean` -**default:** `false` +**Type :** `boolean` +**Par défaut :** `false` Empêche cette page d'être incluse dans un groupe de liens généré automatiquement. ```md --- +# src/content/docs/exemple.md title: Page à masquer de la barre latérale générée automatiquement sidebar: hidden: true @@ -275,14 +354,15 @@ sidebar: #### `badge` -**type:** <code>string | <a href="/fr/reference/configuration/#badgeconfig">BadgeConfig</a></code> +**Type :** <code>string | <a href="/fr/reference/configuration/#badgeconfig">BadgeConfig</a></code> Ajoute un badge à la page dans la barre latérale lorsqu'elle est affichée dans un groupe de liens généré automatiquement. Lors de l'utilisation d'une chaîne de caractères, le badge sera affiché avec une couleur d'accentuation par défaut. -Passez éventuellement un [objet `BadgeConfig`](/fr/reference/configuration/#badgeconfig) avec les propriétés `text` et `variant` pour personnaliser le badge. +Passez éventuellement un [objet `BadgeConfig`](/fr/reference/configuration/#badgeconfig) avec les propriétés `text`, `variant`, et `class` pour personnaliser le badge. ```md --- +# src/content/docs/exemple.md title: Page avec un badge sidebar: # Utilise la variante par défaut correspondant à la couleur d'accentuation de votre site @@ -292,6 +372,7 @@ sidebar: ```md --- +# src/content/docs/exemple.md title: Page avec un badge sidebar: badge: @@ -299,3 +380,94 @@ sidebar: variant: caution --- ``` + +#### `attrs` + +**Type :** `Record<string, string | number | boolean | undefined>` + +Attributs HTML à ajouter au lien de la page dans la barre latérale lorsqu'il est affiché dans un groupe de liens généré automatiquement. +Si [`autogenerate.attrs`](/fr/guides/sidebar/#attributs-html-personnalisés-pour-les-liens-générés-automatiquement) est défini pour le groupe généré automatiquement auquel cette page appartient, les attributs du frontmatter seront fusionnés avec les attributs du groupe. + +```md +--- +# src/content/docs/exemple.md +title: Page s'ouvrant dans un nouvel onglet +sidebar: + # Ouvre la page dans un nouvel onglet + attrs: + target: _blank +--- +``` + +## Personnaliser le schéma du frontmatter + +Le schéma du frontmatter de la collection de contenus `docs` de Starlight est configuré dans `src/content.config.ts` en utilisant l'utilitaire `docsSchema()` : + +```ts {4,7} +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; +``` + +Consultez [« Définir un schéma de collection de contenus »](https://docs.astro.build/fr/guides/content-collections/#définition-dun-schéma-de-collection) dans la documentation d'Astro pour en savoir plus sur les schémas de collection de contenus. + +`docsSchema()` accepte les options suivantes : + +### `extend` + +**Type :** Schéma Zod ou fonction qui retourne un schéma Zod +**Par défaut :** `z.object({})` + +Étendez le schéma de Starlight avec des champs supplémentaires en définissant `extend` dans les options de `docsSchema()`. +La valeur doit être un [schéma Zod](https://docs.astro.build/fr/guides/content-collections/#définition-des-types-de-données-avec-zod). + +Dans l'exemple suivant, nous définissons un type plus strict pour `description` pour le rendre obligatoire et ajouter un nouveau champ `category` facultatif : + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: z.object({ + // Rend un champ de base obligatoire au lieu de facultatif. + description: z.string(), + // Ajoute un nouveau champ au schéma. + category: z.enum(['tutoriel', 'guide', 'référence']).optional(), + }), + }), + }), +}; +``` + +Pour tirer parti de l'[utilitaire `image()` d'Astro](https://docs.astro.build/fr/guides/images/#images-dans-les-collections-de-contenu), utilisez une fonction qui retourne votre extension de schéma : + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: ({ image }) => { + return z.object({ + // Ajoute un champ qui doit être résolu par une image locale. + cover: image(), + }); + }, + }), + }), +}; +``` diff --git a/docs/src/content/docs/fr/reference/icons.mdx b/docs/src/content/docs/fr/reference/icons.mdx new file mode 100644 index 00000000000..4619a0a6c72 --- /dev/null +++ b/docs/src/content/docs/fr/reference/icons.mdx @@ -0,0 +1,32 @@ +--- +title: Référence des icônes +description: Une vue d'ensemble de tous les icônes disponibles dans Starlight. +--- + +Starlight fournit un ensemble d'icônes intégrées que vous pouvez afficher dans votre contenu en utilisant le composant `<Icon>`. + +## Utiliser les icônes + +Les icônes peuvent être affichées en utilisant le composant [`<Icon>`](/fr/components/icons/). +Elles sont également souvent utilisées dans d'autres composants, comme les [cartes](/fr/components/cards/) ou des paramètres comme les [actions de la section d'en-tête](/fr/reference/frontmatter/#hero). + +## Type `StarlightIcon` + +Utilisez le type TypeScript `StarlightIcon` pour référencer les noms des [icônes disponibles avec Starlight](#toutes-les-icônes). + +```ts {2} /icon: (StarlightIcon)/ +// src/icon.ts +import type { StarlightIcon } from '@astrojs/starlight/types'; + +function getIconLabel(icon: StarlightIcon) { + // … +} +``` + +## Toutes les icônes + +Une liste de toutes les icônes disponibles est affichée ci-dessous avec leurs noms associés. Cliquez sur une icône pour copier son nom dans votre presse-papiers. + +import IconsList from '~/components/icons-list.astro'; + +<IconsList labels={{ copied: 'Copié !' }} /> diff --git a/docs/src/content/docs/fr/reference/overrides.md b/docs/src/content/docs/fr/reference/overrides.md new file mode 100644 index 00000000000..cf7b1f760a9 --- /dev/null +++ b/docs/src/content/docs/fr/reference/overrides.md @@ -0,0 +1,261 @@ +--- +title: Référence des redéfinitions +description: Une vue d'ensemble de tous les composants et les props des composants compatibles avec les redéfinitions de Starlight. +tableOfContents: + maxHeadingLevel: 4 +--- + +Vous pouvez redéfinir les composants intégrés à Starlight en spécifiant des chemins vers des composants de remplacement avec l'option de configuration [`components`](/fr/reference/configuration/#components) de Starlight. +Cette page répertorie tous les composants disponibles qui peuvent être redéfinis et fournit des liens vers leurs implémentations par défaut sur GitHub. + +Pour en savoir plus, consultez le [guide des redéfinitions de composants](/fr/guides/overriding-components/). + +## Composants + +### Métadonnées + +Ces composants sont utilisés dans l'élément `<head>` de chaque page. +Ils ne doivent inclure que des [éléments autorisés à l'intérieur de `<head>`](https://developer.mozilla.org/fr/docs/Web/HTML/Element/head). + +#### `Head` + +**Composant par défaut :** [`Head.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Head.astro) + +Composant utilisé à l'intérieur de l'élément `<head>` de chaque page. + +Redéfinissez ce composant en dernier recours. +Préférez [l'option de configuration `head`](/fr/reference/configuration/#head), le [champ `head` du frontmatter](/fr/reference/frontmatter/#head), ou un [middleware de données de route](/fr/guides/route-data/#personnalisation-des-données-de-route) pour personnaliser les données de route affichées par le composant par défaut si possible. + +#### `ThemeProvider` + +**Composant par défaut :** [`ThemeProvider.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeProvider.astro) + +Composant utilisé à l'intérieur de l'élément `<head>` qui configure la prise en charge du thème sombre/clair. +L'implémentation par défaut inclut un script en ligne et un élément `<template>` utilisé par le script situé dans [`<ThemeSelect />`](#themeselect). + +--- + +### Accessibilité + +#### `SkipLink` + +**Composant par défaut :** [`SkipLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SkipLink.astro) + +Composant utilisé comme premier élément à l'intérieur du `<body>` qui relie au contenu principal de la page pour des raisons d'accessibilité. +L'implémentation par défaut est masquée jusqu'à ce qu'il reçoive le focus d'un utilisateur utilisant la navigation au clavier. + +--- + +### Mise en page + +Ces composants sont responsables de la mise en page des composants de Starlight et de la gestion des vues pour différents points d'arrêt. +Redéfinir ceux-ci implique une complexité significative. +Lorsque cela est possible, préférez redéfinir un composant de plus bas niveau. + +#### `PageFrame` + +**Composant par défaut :** [`PageFrame.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageFrame.astro) +**Slots nommés :** `header`, `sidebar` + +Composant de mise en page contenant la plupart du contenu de la page. +L'implémentation par défaut configure la mise en page de l'en-tête, de la barre latérale et du contenu principal et inclut des slots nommés `header` et `sidebar` en plus du slot par défaut pour le contenu principal. +Il affiche également [`<MobileMenuToggle />`](#mobilemenutoggle) qui prend en charge l'affichage de la barre latérale de navigation sur petits écrans (mobiles). + +#### `MobileMenuToggle` + +**Composant par défaut :** [`MobileMenuToggle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuToggle.astro) + +Composant utilisé à l'intérieur de [`<PageFrame>`](#pageframe) qui est responsable de l'affichage de la barre latérale de navigation sur petits écrans (mobiles). + +#### `TwoColumnContent` + +**Composant par défaut :** [`TwoColumnContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TwoColumnContent.astro) +**Slot nommé :** `right-sidebar` + +Composant de mise en page enveloppant le contenu principal de la page et la barre latérale de droite (table des matières). +L'implémentation par défaut prend en charge le changement entre une mise en page à une seule colonne pour petits écrans et une mise en page à deux colonnes pour écrans plus larges. + +--- + +### En-tête + +Ces composants affichent la barre de navigation supérieure de Starlight. + +#### `Header` + +**Composant par défaut :** [`Header.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Header.astro) + +Composant d'en-tête affiché en haut de chaque page. +L'implémentation par défaut affiche [`<SiteTitle />`](#sitetitle), [`<Search />`](#search), [`<SocialIcons />`](#socialicons), [`<ThemeSelect />`](#themeselect) et [`<LanguageSelect />`](#languageselect). + +#### `SiteTitle` + +**Composant par défaut :** [`SiteTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SiteTitle.astro) + +Composant utilisé au début de l'en-tête du site pour afficher le titre du site. +L'implémentation par défaut inclut la logique pour afficher les logos définis dans la configuration de Starlight. + +#### `Search` + +**Composant par défaut :** [`Search.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Search.astro) + +Composant utilisé pour afficher l'interface de recherche de Starlight. +L'implémentation par défaut inclut le bouton dans l'en-tête et le code pour afficher une fenêtre modale de recherche lorsqu'il est cliqué et charger [l'interface utilisateur de Pagefind](https://pagefind.app/). + +Lorsque [`pagefind`](/fr/reference/configuration/#pagefind) est désactivé, le composant de recherche par défaut ne sera pas affiché. +Cependant, si vous redéfinissez `Search`, votre composant personnalisé sera toujours affiché même si l'option de configuration `pagefind` est `false`. +Cela vous permet d'ajouter une interface de recherche alternative lorsque vous désactivez Pagefind. + +#### `SocialIcons` + +**Composant par défaut :** [`SocialIcons.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SocialIcons.astro) + +Composant utilisé dans l'en-tête du site qui inclut des liens avec des icônes vers différents médias sociaux. +L'implémentation par défaut utilise l'option [`social`](/fr/reference/configuration/#social) de la configuration de Starlight pour afficher les icônes et les liens. + +#### `ThemeSelect` + +**Composant par défaut :** [`ThemeSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeSelect.astro) + +Composant utilisé dans l'en-tête du site qui permet aux utilisateurs de sélectionner leur thème de couleur préféré. + +#### `LanguageSelect` + +**Composant par défaut :** [`LanguageSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LanguageSelect.astro) + +Component utilisé dans l'en-tête du site qui permet aux utilisateurs de changer de langue. + +--- + +### Barre latérale globale + +La barre latérale globale de Starlight contient la navigation principale du site. +Sur des écrans peu larges, elle est masquée derrière un menu déroulant. + +#### `Sidebar` + +**Composant par défaut :** [`Sidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Sidebar.astro) + +Composant utilisé avant le contenu de la page qui contient la navigation globale. +L'implémentation par défaut est affichée comme une barre latérale sur des écrans suffisamment larges et à l'intérieur d'un menu déroulant sur des écrans plus petits (mobiles). +Il utilise aussi [`<MobileMenuFooter />`](#mobilemenufooter) pour afficher des éléments supplémentaires dans le menu mobile. + +#### `MobileMenuFooter` + +**Composant par défaut :** [`MobileMenuFooter.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuFooter.astro) + +Composant utilisé à la fin du menu déroulant mobile. +L'implémentation par défaut affiche [`<ThemeSelect />`](#themeselect) et [`<LanguageSelect />`](#languageselect). + +--- + +### Barre latérale de page + +La barre latérale de page de Starlight est responsable d'afficher une table des matières mettant en avant les titres de section de la page courante. +Sur des écrans peu larges, elle est remplacée par un menu déroulant adhérant. + +#### `PageSidebar` + +**Composant par défaut :** [`PageSidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageSidebar.astro) + +Composant affiché avant le contenu de la page et contenant la table des matières. +L'implémentation par défaut affiche [`<TableOfContents />`](#tableofcontents) et [`<MobileTableOfContents />`](#mobiletableofcontents). + +#### `TableOfContents` + +**Composant par défaut :** [`TableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TableOfContents.astro) + +Composant qui affiche la table des matières de la page courante sur des écrans suffisamment larges. + +#### `MobileTableOfContents` + +**Composant par défaut :** [`MobileTableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileTableOfContents.astro) + +Composant qui affiche la table des matières de la page courante sur des petits écrans (mobiles). + +--- + +### Contenu + +Ces composants sont utilisés dans la colonne principale de contenu de la page. + +#### `Banner` + +**Composant par défaut :** [`Banner.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Banner.astro) + +Composant représentant une bannière affichée en haut de chaque page. +L'implémentation par défaut utilise la valeur du champ [`banner`](/fr/reference/frontmatter/#banner) du frontmatter de la page pour décider de l'affichage ou non. + +#### `ContentPanel` + +**Composant par défaut :** [`ContentPanel.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ContentPanel.astro) + +Composant de mise en page utilisé pour envelopper les section de la colonne principale de contenu. + +#### `PageTitle` + +**Composant par défaut :** [`PageTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageTitle.astro) + +Composant contenant l'élement `<h1>` de la page courante. + +Les implémentations personnalisées doivent s'assurer qu'elles définissent `id="_top"` sur l'élément `<h1>` comme dans l'implémentation par défaut. + +#### `DraftContentNotice` + +**Composant par défaut :** [`DraftContentNotice.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/DraftContentNotice.astro) + +Note affichée aux utilisateurs durant le développement lorsque la page actuelle est marquée comme une ébauche. + +#### `FallbackContentNotice` + +**Composant par défaut :** [`FallbackContentNotice.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/FallbackContentNotice.astro) + +Note affichée aux utilisateurs sur les pages où une traduction pour la langue courante n'est pas disponible. +Utilisé uniquement sur les sites multilingues. + +#### `Hero` + +**Composant par défaut :** [`Hero.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Hero.astro) + +Composant affiché en haut de la page lorsque le champ [`hero`](/fr/reference/frontmatter/#hero) est défini dans le frontmatter. +L'implémentation par défaut affiche un large titre, une accroche et des liens d'appel à l'action à côté d'une image facultative. + +#### `MarkdownContent` + +**Composant par défaut :** [`MarkdownContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MarkdownContent.astro) + +Composant affiché autour du contenu principal de chaque page. +L'implémentation par défaut définit les styles de base à appliquer au contenu Markdown. + +Les styles de contenu Markdown sont également exposés dans `@astrojs/starlight/style/markdown.css` avec une portée limitée à la classe CSS `.sl-markdown-content`. + +--- + +### Pied de page + +Ces composants sont affichés en bas de la colonne principale de contenu de la page. + +#### `Footer` + +**Composant par défaut :** [`Footer.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Footer.astro) + +Composant pied de page affiché en bas de chaque page. +L'implémentation par défaut affiche [`<LastUpdated />`](#lastupdated), [`<Pagination />`](#pagination) et [`<EditLink />`](#editlink). + +#### `LastUpdated` + +**Composant par défaut :** [`LastUpdated.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LastUpdated.astro) + +Composant utilisé dans le pied de page pour afficher la date de dernière mise à jour de la page. + +#### `EditLink` + +**Composant par défaut :** [`EditLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/EditLink.astro) + +Composant utilisé dans le pied de page pour afficher un lien vers l'emplacement où la page peut être modifiée. + +#### `Pagination` + +**Composant par défaut :** [`Pagination.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Pagination.astro) + +Composant utilisé dans le pied de page pour afficher des flèches de navigation entre les pages précédentes/suivantes. diff --git a/docs/src/content/docs/fr/reference/plugins.md b/docs/src/content/docs/fr/reference/plugins.md new file mode 100644 index 00000000000..a9239cc0776 --- /dev/null +++ b/docs/src/content/docs/fr/reference/plugins.md @@ -0,0 +1,375 @@ +--- +title: Référence des modules d'extension +description: Une vue d'ensemble de l'API des modules d'extension Starlight. +tableOfContents: + maxHeadingLevel: 4 +--- + +Les modules d'extension Starlight peuvent personnaliser la configuration, l'interface utilisateur et le comportement de Starlight, tout en étant faciles à partager et à réutiliser. +Cette page de référence documente l'API à laquelle ces modules d'extension ont accès. + +Consultez la [référence de configuration](/fr/reference/configuration/#plugins) pour en savoir plus sur l'utilisation d'un module d'extension Starlight ou visitez la [vitrine des modules d'extension](/fr/resources/plugins/) pour voir une liste de modules d'extension disponibles. + +## Référence rapide de l'API + +Un module d'extension Starlight a la forme suivante. +Voir ci-dessous pour plus de détails sur les différentes propriétés et paramètres des hooks. + +<!-- prettier-ignore-start --> +```ts +interface StarlightPlugin { + name: string; + hooks: { + 'i18n:setup'?: (options: { + injectTranslations: ( + translations: Record<string, Record<string, string>> + ) => void; + }) => void | Promise<void>; + 'config:setup': (options: { + config: StarlightUserConfig; + updateConfig: (newConfig: StarlightUserConfig) => void; + addIntegration: (integration: AstroIntegration) => void; + addRouteMiddleware: (config: { entrypoint: string; order?: 'pre' | 'post' | 'default' }) => void; + astroConfig: AstroConfig; + command: 'dev' | 'build' | 'preview'; + isRestart: boolean; + logger: AstroIntegrationLogger; + useTranslations: (lang: string) => I18nT; + absolutePathToLang: (path: string) => string; + }) => void | Promise<void>; + }; +} +``` +<!-- prettier-ignore-end --> + +## `name` + +**Type :** `string` + +Un module d'extension doit fournir un nom unique qui le décrit. Le nom est utilisé lors de [l'affichage des messages](#logger) liés à ce module d'extension et peut être utilisé par d'autres modules d'extension pour détecter la présence de ce dernier. + +## `hooks` + +Les hooks sont des fonctions que Starlight appelle pour exécuter le code du module d'extension à des moments spécifiques. + +Pour référencer le type des arguments d'un hook, utilisez le type utilitaire `HookParameters` et passez le nom du hook. +Dans l'exemple suivant, le paramètre `options` est typé pour correspondre aux arguments passés au hook `config:setup` : + +```ts +import type { HookParameters } from '@astrojs/starlight/types'; + +function configSetup(options: HookParameters['config:setup']) { + options.useTranslations('fr'); +} +``` + +### `i18n:setup` + +Fonction de configuration de l'internationalisation du module d'extension appelée lorsque Starlight est initialisé. +Le hook `i18n:setup` peut être utilisé pour injecter des traductions afin que le module d'extension puisse prendre en charge différentes locales. +Ces traductions seront disponibles via [`useTranslations()`](#usetranslations) dans le hook `config:setup` et dans les composants d'interface utilisateur via [`Astro.locals.t()`](/fr/guides/i18n/#utiliser-les-traductions-de-linterface-utilisateur). + +Le hook `i18n:setup` est appelé avec les options suivantes : + +#### `injectTranslations` + +**Type :** `(translations: Record<string, Record<string, string>>) => void` + +Une fonction appelée pour ajouter ou mettre à jour des chaînes de traduction utilisées dans les [API de localisation](/fr/guides/i18n/#utiliser-les-traductions-de-linterface-utilisateur) de Starlight. + +Dans l'exemple suivant, un module d'extension injecte des traductions pour une chaîne d'interface utilisateur personnalisée nommée `myPlugin.doThing` pour les locales `en` et `fr` : + +```ts {6-13} /(injectTranslations)[^(]/ +// plugin.ts +export default { + name: 'plugin-avec-traductions', + hooks: { + 'i18n:setup'({ injectTranslations }) { + injectTranslations({ + en: { + 'myPlugin.doThing': 'Do the thing', + }, + fr: { + 'myPlugin.doThing': 'Faire le truc', + }, + }); + }, + }, +}; +``` + +Pour utiliser les traductions injectées dans l'interface utilisateur de votre module d'extension, suivez le [guide « Utiliser les traductions de l'interface utilisateur »](/fr/guides/i18n/#utiliser-les-traductions-de-linterface-utilisateur). +Si vous avez besoin d'accéder aux traductions dans le contexte du hook [`config:setup`](#configsetup) de votre module d'extension, vous pouvez utiliser la fonction [`useTranslations()`](#usetranslations). + +Le typage des chaînes de traduction injectées pour un module d'extension est généré automatiquement dans le projet d'un utilisateur, mais n'est pas encore disponible lors du développement dans le code source de votre module d'extension. +Pour typer l'objet `locals.t` dans le contexte de votre module d'extension, déclarez les espaces de noms globaux suivants dans un fichier de déclaration TypeScript : + +```ts +// env.d.ts +declare namespace App { + type StarlightLocals = import('@astrojs/starlight').StarlightLocals; + // Definit l'objet `locals.t` dans le contexte d'un module d'extension. + interface Locals extends StarlightLocals {} +} + +declare namespace StarlightApp { + // Define les traductions supplémentaires du module d'extension dans l'interface `I18n`. + interface I18n { + 'myPlugin.doThing': string; + } +} +``` + +Vous pouvez également inférer le typage de l'interface `StarlightApp.I18n` à partir d'un fichier source si vous avez un objet contenant vos traductions. + +Par exemple, étant donné le fichier source suivant : + +```ts title="ui-strings.ts" +export const UIStrings = { + en: { 'myPlugin.doThing': 'Do the thing' }, + fr: { 'myPlugin.doThing': 'Faire le truc' }, +}; +``` + +La déclaration suivante inférerait le typage à partir des clés anglaises dans le fichier source : + +```ts title="env.d.ts" +declare namespace StarlightApp { + type UIStrings = typeof import('./ui-strings').UIStrings.en; + interface I18n extends UIStrings {} +} +``` + +### `config:setup` + +La fonction de configuration du module d'extension appelée lorsque Starlight est initialisé (pendant le hook [`astro:config:setup`](https://docs.astro.build/fr/reference/integrations-reference/#astroconfigsetup) de l'intégration). +Le hook `config:setup` peut être utilisé pour mettre à jour la configuration de Starlight ou ajouter des intégrations Astro. + +Ce hook est appelé avec les options suivantes : + +#### `config` + +**Type :** `StarlightUserConfig` + +Une copie en lecture seule de la [configuration de Starlight](/fr/reference/configuration/) fournie par l'utilisateur. +Cette configuration peut avoir été mise à jour par d'autres modules d'extension configurés avant celui en cours. + +#### `updateConfig` + +**Type :** `(newConfig: StarlightUserConfig) => void` + +Une fonction de rappel pour mettre à jour la [configuration de Starlight](/fr/reference/configuration/) fournie par l'utilisateur. +Spécifiez les clés de configuration de niveau racine que vous souhaitez remplacer. +Pour mettre à jour des valeurs de configuration imbriquées, vous devez fournir l'objet imbriqué entier. + +Pour étendre une option de configuration existante sans la remplacer, étendez la valeur existante dans votre nouvelle valeur. +Dans l'exemple suivant, un nouveau compte de média [`social`](/fr/reference/configuration/#social) est ajouté à la configuration existante en étendant `config.social` dans le nouveau tableau `social` : + +```ts {6-15} +// module-extension.ts +export default { + name: 'ajout-twitter-plugin', + hooks: { + 'config:setup'({ config, updateConfig }) { + updateConfig({ + social: [ + ...config.social, + { + icon: 'twitter', + label: 'Twitter', + href: 'https://twitter.com/astrodotbuild', + }, + ], + }); + }, + }, +}; +``` + +#### `addIntegration` + +**Type :** `(integration: AstroIntegration) => void` + +Une fonction de rappel pour ajouter une [intégration Astro](https://docs.astro.build/fr/reference/integrations-reference/) requise par le module d'extension. + +Dans l'exemple suivant, le module d'extension vérifie d'abord si [l'intégration React d'Astro](https://docs.astro.build/fr/guides/integrations-guide/react/) est configurée et, si ce n'est pas le cas, utilise `addIntegration()` pour l'ajouter : + +```ts {14} "addIntegration," +// module-extension.ts +import react from '@astrojs/react'; + +export default { + name: 'plugin-utilisant-react', + hooks: { + 'config:setup'({ addIntegration, astroConfig }) { + const isReactLoaded = astroConfig.integrations.find( + ({ name }) => name === '@astrojs/react' + ); + + // Ajoute seulement l'intégration React si elle n'est pas déjà chargée. + if (!isReactLoaded) { + addIntegration(react()); + } + }, + }, +}; +``` + +#### `addRouteMiddleware` + +**Type :** `(config: { entrypoint: string; order?: 'pre' | 'post' | 'default' }) => void` + +Une fonction appelée pour ajouter un [middleware de route](/fr/guides/route-data/) pour le site. + +La propriété `entrypoint` doit être un spécificateur de module pour le fichier middleware de votre module d'extension qui exporte une fonction `onRequest`. + +Dans l'exemple suivant, un module d'extension publié sous `@exemple/starlight-module-extension` ajoute un middleware de route utilisant un spécificateur de module npm : + +```js {6-9} +// module-extension.ts +export default { + name: '@exemple/starlight-module-extension', + hooks: { + 'config:setup'({ addRouteMiddleware }) { + addRouteMiddleware({ + entrypoint: '@exemple/starlight-module-extension/route-middleware', + }); + }, + }, +}; +``` + +##### Contrôle de l'ordre d'exécution + +Par défaut, le middleware du module d'extension s'exécute dans l'ordre d'ajout des modules d'extension. + +Utilisez la propriété `order` facultative si vous avez besoin de plus de contrôle sur le moment où votre middleware s'exécute. +Définissez `order: "pre"` pour s'exécuter avant le middleware d'un utilisateur. +Définissez `order: "post"` pour s'exécuter après tout autre middleware. + +Si deux modules d'extension ajoutent un middleware avec la même valeur `order`, le module d'extension ajouté en premier s'exécutera en premier. + +#### `astroConfig` + +**Type :** `AstroConfig` + +Une copie en lecture seule de la [configuration d'Astro](https://docs.astro.build/fr/reference/configuration-reference/) fournie par l'utilisateur. + +#### `command` + +**Type :** `'dev' | 'build' | 'preview'` + +La commande utilisée pour exécuter Starlight : + +- `dev` - Le projet est exécuté avec `astro dev` +- `build` - Le projet est exécuté avec `astro build` +- `preview` - Le projet est exécuté avec `astro preview` + +#### `isRestart` + +**Type :** `boolean` + +`false` lorsque le serveur de développement démarre, `true` lorsqu'un rechargement est déclenché. +Les raisons courantes d'un redémarrage incluent un utilisateur qui modifie son fichier `astro.config.mjs` pendant que le serveur de développement est en cours d'exécution. + +#### `logger` + +**Type :** `AstroIntegrationLogger` + +Une instance du [journaliseur (logger) d'intégration Astro](https://docs.astro.build/fr/reference/integrations-reference/#astrointegrationlogger) que vous pouvez utiliser pour écrire des messages de journalisation. +Tous les messages seront préfixés par le nom du module d'extension. + +```ts {6} +// module-extension.ts +export default { + name: 'plugin-long-processus', + hooks: { + 'config:setup'({ logger }) { + logger.info("Démarrage d'un long processus…"); + // Un long processus… + }, + }, +}; +``` + +L'exemple ci-dessus affichera un message qui inclut le message d'information fourni : + +```plaintext frame="terminal" +[plugin-long-processus] Démarrage d'un long processus… +``` + +#### `useTranslations` + +**Type :** `(lang: string) => I18nT` + +Appelez `useTranslations()` avec une étiquette de langue BCP-47 pour générer une fonction utilitaire qui fournit l'accès aux chaînes d'interface utilisateur pour cette langue. +`useTranslations()` retourne une fonction équivalente à l'API `Astro.locals.t()` disponible dans les composants Astro. +Pour en savoir plus sur les APIs disponibles, consultez le [guide « Utiliser les traductions de l'interface utilisateur »](/fr/guides/i18n/#utiliser-les-traductions-de-linterface-utilisateur). + +```ts {6} +// module-extension.ts +export default { + name: 'plugin-utilisant-traductions', + hooks: { + 'config:setup'({ useTranslations, logger }) { + const t = useTranslations('zh-CN'); + logger.info(t('builtWithStarlight.label')); + }, + }, +}; +``` + +L'exemple ci-dessus affichera un message qui inclut une chaîne d'interface utilisateur intégrée pour la langue chinoise simplifiée : + +```shell +[plugin-utilisant-traductions] 基于 Starlight 构建 +``` + +#### `absolutePathToLang` + +**Type :** `(path: string) => string` + +Appelez `absolutePathToLang()` avec un chemin de fichier absolu pour obtenir la langue de ce fichier. + +Cela peut être particulièrement utile lors de l'ajout de [modules d'extension remark ou rehype](https://docs.astro.build/fr/guides/markdown-content/#modules-dextension-markdown) pour traiter les fichiers Markdown ou MDX. +Le [format de fichier virtuel](https://github.com/vfile/vfile) utilisé par ces modules d'extension inclut le [chemin absolu](https://github.com/vfile/vfile#filepath) du fichier en cours de traitement, qui peut être utilisé avec `absolutePathToLang()` pour déterminer la langue du fichier. +La langue retournée peut être utilisé avec l'utilitaire [`useTranslations()`](#usetranslations) pour obtenir des chaînes d'interface utilisateur pour cette langue. + +Par exemple, étant donné la configuration de Starlight suivante : + +```js +starlight({ + title: 'Ma documentation', + defaultLocale: 'fr', + locales: { + // Documentation en anglais dans `src/content/docs/en/` + en: { label: 'English' }, + // Documentation en français dans `src/content/docs/fr/` + fr: { label: 'Français', lang: 'fr' }, + }, +}); +``` + +Un module d'extension peut déterminer la langue d'un fichier en utilisant son chemin absolu : + +```ts {6-8} //(en)// +// module-extension.ts +export default { + name: 'plugin-utilisant-traductions', + hooks: { + 'config:setup'({ absolutePathToLang, useTranslations, logger }) { + const lang = absolutePathToLang( + '/chemin/absolu/vers/projet/src/content/docs/en/index.mdx' + ); + const t = useTranslations(lang); + logger.info(t('aside.tip')); + }, + }, +}; +``` + +L'exemple ci-dessus affichera un message qui inclut une chaîne d'interface utilisateur intégrée pour la langue anglaise : + +```shell +[plugin-utilisant-traductions] Tip +``` diff --git a/docs/src/content/docs/fr/reference/route-data.mdx b/docs/src/content/docs/fr/reference/route-data.mdx new file mode 100644 index 00000000000..ff75ab1c517 --- /dev/null +++ b/docs/src/content/docs/fr/reference/route-data.mdx @@ -0,0 +1,204 @@ +--- +title: Référence des données de route +description: La documentation de référence complète pour l'objet de données de route de Starlight. +--- + +L'objet de données de route de Starlight contient des informations sur la page courante. +Apprenez-en plus sur le fonctionnement du modèle de données de Starlight dans le [guide « Données de route »](/fr/guides/route-data/). + +Dans les composants Astro, accédez aux données de route à partir de `Astro.locals.starlightRoute` : + +```astro {4} +--- +// src/components/Custom.astro + +const { hasSidebar } = Astro.locals.starlightRoute; +--- +``` + +Dans un [middleware de route](/fr/guides/route-data/#personnalisation-des-données-de-route), accédez aux données de route à partir de l'objet de contexte passé à votre fonction middleware : + +```ts {5} +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + const { hasSidebar } = context.locals.starlightRoute; +}); +``` + +## `starlightRoute` + +L'objet `starlightRoute` contient les propriétés suivantes : + +### `dir` + +**Type :** `'ltr' | 'rtl'` + +Le sens d’écriture de la page. + +### `lang` + +**Type :** `string` + +L'étiquette d'identification BCP-47 pour la langue de la page, par exemple `en`, `zh-CN` ou `pt-BR`. + +### `locale` + +**Type :** `string | undefined` + +Le chemin de base utilisé pour servir une langue. `undefined` pour les slugs de la locale racine. + +### `siteTitle` + +**Type :** `string` + +Le titre du site pour la langue de cette page. + +### `siteTitleHref` + +**Type :** `string` + +La valeur de l'attribut `href` du titre du site, renvoyant à la page d'accueil, par exemple `/`. +Pour les sites multilingues, cette valeur inclura la locale actuelle, par exemple `/fr/` ou `/zh-cn/`. + +### `slug` + +**Type :** `string` + +Le slug de la page généré à partir du nom du fichier du contenu. + +Cette propriété est dépréciée et sera supprimée dans une version future de Starlight. +Migrez vers la nouvelle API Content Layer en utilisant le [`docsLoader` de Starlight](/fr/manual-setup/#configurer-les-collections-de-contenu) et utilisez la propriété [`id`](#id) à la place. + +### `id` + +**Type :** `string` + +Le slug de cette page ou l'identifiant unique de cette page basé sur le nom du fichier du contenu si l'option [`legacy.collections`](https://docs.astro.build/fr/reference/legacy-flags/#collections) est utilisée. + +### `isFallback` + +**Type :** `boolean | undefined` + +`true` si cette page n'est pas traduite dans la langue actuelle et utilise le contenu de la langue par défaut en tant que repli. +Utilisé uniquement dans les sites multilingues. + +### `entryMeta` + +**Type :** `{ dir: 'ltr' | 'rtl'; lang: string }` + +Métadonnées de la locale pour le contenu de la page. Peut être différent des valeurs de locale de premier niveau lorsque la page utilise un contenu de repli. + +### `entry` + +L'entrée de la collection de contenu Astro pour la page courante. +Inclut les valeurs du frontmatter pour la page courante dans `entry.data`. + +```ts +entry: { + data: { + title: string; + description: string | undefined; + // etc. + } +} +``` + +Pour en savoir plus sur le format de cet objet, consultez la [référence du type d'entrée de collection](https://docs.astro.build/fr/reference/modules/astro-content/#collectionentry). + +### `sidebar` + +**Type :** `SidebarEntry[]` + +Les entrées de la barre latérale de navigation du site pour cette page. + +### `hasSidebar` + +**Type :** `boolean` + +Indique si la barre latérale est affichée sur cette page. + +### `pagination` + +**Type :** `{ prev?: Link; next?: Link }` + +Liens vers la page précédente et suivante dans la barre latérale si celle-ci est activée. + +### `toc` + +**Type :** `{ minHeadingLevel: number; maxHeadingLevel: number; items: TocItem[] } | undefined` + +Table des matières de la page courante si celle-ci est activée. + +### `headings` + +**Type :** `{ depth: number; slug: string; text: string }[]` + +Un tableau de toutes les en-têtes Markdown extraites de la page courante. +Utilisez [`toc`](#toc) à la place si vous souhaitez construire un composant de table des matières qui respecte les options de configuration de Starlight. + +### `lastUpdated` + +**Type :** `Date | undefined` + +Un objet JavaScript de type `Date` représentant la date de dernière mise à jour de cette page si cette fonctionnalité est activée. + +### `editUrl` + +**Type :** `URL | undefined` + +Un objet `URL` de l'adresse où cette page peut être modifiée si cette fonctionnalité est activée. + +### `head` + +**Type :** [`HeadConfig[]`](/fr/reference/configuration/#headconfig) + +Tableau de toutes les balises à inclure à l’intérieur de l’élément `<head>` de la page courante. +Inclut des balises importantes comme `<title>` et `<meta charset="utf-8">`. + +## Utilitaires + +### `defineRouteMiddleware()` + +Utilisez l'utilitaire `defineRouteMiddleware()` pour vous aider à typer votre module de middleware de route : + +```ts "defineRouteMiddleware" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + // ... +}); +``` + +### Type `StarlightRouteData` + +Si vous écrivez du code qui utilise les données de route de Starlight, vous pouvez importer le type `StarlightRouteData` qui correspond au format de `Astro.locals.starlightRoute`. + +Dans l'exemple suivant, une fonction `usePageTitleInTOC()` met à jour les données de route pour utiliser le titre de la page courante comme libellé du premier élément de la table des matières, remplaçant le libellé par défaut « Sur cette page ». +Le type `StarlightRouteData` vous permet de vérifier si les modifications des données de route sont valides. + +```ts "StarlightRouteData" +// src/route-utils.ts +import type { StarlightRouteData } from '@astrojs/starlight/route-data'; + +export function usePageTitleInTOC(starlightRoute: StarlightRouteData) { + const overviewLink = starlightRoute.toc?.items[0]; + if (overviewLink) { + overviewLink.text = starlightRoute.entry.data.title; + } +} +``` + +Cette fonction peut ensuite être appelée à partir d'un middleware de route : + +```ts {3,6} +// src/route-middleware.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; +import { usePageTitleInTOC } from './route-utils'; + +export const onRequest = defineRouteMiddleware((context) => { + usePageTitleInTOC(context.locals.starlightRoute); +}); +``` diff --git a/docs/src/content/docs/fr/resources/community-content.mdx b/docs/src/content/docs/fr/resources/community-content.mdx new file mode 100644 index 00000000000..741a01cb6d1 --- /dev/null +++ b/docs/src/content/docs/fr/resources/community-content.mdx @@ -0,0 +1,252 @@ +--- +title: Contenu communautaire +description: Découvrez les guides, articles et vidéos produits par la communauté pour vous aider à apprendre et à créer avec Starlight ! +--- + +:::tip[Ajoutez le vôtre !] +Avez-vous produit du contenu sur Starlight ? +Ouvrez une PR ajoutant un lien à cette page ! +::: + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +## Articles et revues + +Voici une collection de publications et d'articles pour en apprendre plus sur Starlight et les expériences d'autres personnes : + +<CardGrid> + <LinkCard + href="https://devm.io/open-source/starlight-astro" + title="Génération de sites statiques avec Starlight" + description="« Aucune idée n'est trop grande ou trop petite lors de la conception de composants » — une entrevue avec Chris Swithinbank, responsable de Starlight" + /> + <LinkCard + href="https://frontendatscale.com/blog/hybrid-frontend-architecture/" + title="Une architecture frontend hybride avec Astro et Starlight" + description="Maxi Ferreira et Ben Holmes construisent un site de documentation avec Starlight, TinaCMS et une aire de test interactive avec authentification pour une API." + /> + <LinkCard + href="https://www.olets.dev/posts/comparing-docs-site-builders-vuepress-vs-starlight/" + title="Comparaison des générateurs de sites de documentation : VuePress contre Starlight" + description="Comment les deux frameworks se comparent-ils ?" + /> + <LinkCard + href="https://astro.build/case-studies/wp-engine/" + title="Étude de cas : Réduction des coûts de développement" + description="Comment WP Engine a réduit ses coûts de développement par plus de 50 % avec Astro Starlight." + /> + <LinkCard + href="https://maciekpalmowski.dev/blog/building-a-documentation-site-using-astro-starlight/" + title="Construction d'un site de documentation avec Astro Starlight" + description="Maciek Palmowski décrit comment Patchstack a migré sa documentation vers Starlight" + /> + <LinkCard + href="https://blog.cloudflare.com/open-source-all-the-way-down-upgrading-our-developer-documentation/" + title="Open source du début à la fin" + description="Comment Cloudflare a utilisé Starlight pour mettre à jour sa documentation pour les développeurs." + /> + <LinkCard + href="https://starlight-changelog.netlify.app/" + title="Starlight Changelog" + description="Consulter l'ensemble des versions du paquet @astrojs/starlight sur une seule magnifique page." + /> + <LinkCard + href="https://hideoo.dev/notes/contributing-to-starlight" + title="Contribuer à Starlight" + description="Mon expérience personnelle et mes suggestions pour contribuer à des projets open source comme Starlight." + /> +</CardGrid> + +## Recettes et guides + +Les recettes sont généralement des guides courts et ciblés qui guident un lecteur à travers l'exécution d'un exemple de travail pour une tâche spécifique. Les recettes sont un excellent moyen d'ajouter de nouvelles fonctionnalités ou un nouveau comportement à votre projet Starlight en suivant des instructions étape par étape ! D'autres guides peuvent expliquer des concepts liés à un domaine spécifique, comme l'utilisation d'images ou l'utilisation de MDX. + +Explorez le contenu communautaire produit par les utilisateurs de Starlight : + +<CardGrid> + <LinkCard + href="https://www.webpro.nl/scraps/versioned-docs-with-starlight-and-vercel" + title="Documentation versionnée avec Starlight et Vercel" + description="Un guide pour mettre en place des versions séparées d'une documentation pour chaque version majeure d'un projet." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-heading-links" + title="Ajouter des liens aux titres de Starlight" + description="Un guide pour utiliser un module d'extension rehype pour partager des liens vers des sections spécifiques de votre documentation." + /> + <LinkCard + href="https://blog.otterlord.dev/posts/starlight-sponsors/" + title="Ajouter des sponsors à votre site Starlight" + description="Un guide pour mettre en place un composant de sponsors personnalisé dans la barre latérale de votre documentation." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images" + title="Ajouter des images Open Graph à Starlight" + description="Un guide pour générer des images sociales et les balises de métadonnées correspondantes pour vos pages." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-third-party-icon-sets" + title="Utiliser des ensembles d'icônes tiers dans Starlight" + description="Un guide pour utiliser unplugin-icons pour étendre la sélection d'icônes disponibles pour Starlight." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-html-head" + title="Éditer l'en-tête HTML des pages Starlight" + description="Apprenez à ajouter du contenu d'en-tête commun tel que des analyses d'audience Web, des polices et des scripts." + /> + <LinkCard + href="https://dev.to/mrrobot/publishing-documentation-with-astro-starlight-691" + title="Publier une documentation avec Astro Starlight" + description="Démarrer une documentation avec Starlight." + /> + <LinkCard + href="https://events-3bg.pages.dev/jotter/starlight/" + title="Utiliser les transitions de vue (view transitions)" + description="Ajoutez la prise en charge des transitions de vue, du routage côté client et de la navigation monopage (SPA) à votre site de documentation Starlight." + /> + <LinkCard + href="https://jamcomments.com/posts/structured-data-with-starlight" + title="Ajout de données structurées aux pages Starlight" + description="Apprenez à créer des données structurées JSON-LD dynamiques pour vos pages de documentation." + /> + <LinkCard + href="https://starlight-examples.netlify.app/" + title="Exemples Starlight" + description="Collection de ressources StackBlitz démontrant par la pratique comment mettre en place diverses fonctionnalités dans des sites de documentation Starlight." + /> + <LinkCard + href="https://hideoo.dev/notebooks/starlight-plugins-by-example" + title="Modules d'extension Starlight par l'exemple" + description="Une collection de notes et d'exemples sur les modules d'extension Starlight et techniques couramment utilisées pour les construire." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-progress-indicator/" + title="Ajouter un indicateur de progression de lecture" + description="Découvrez comment ajouter une barre de progression de lecture horizontale à votre site Starlight." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-sidebar-whitespace/" + title="Appliquer des styles personnalisés à votre barre latérale Starlight" + description="En utilisant un peu de CSS pour ajuster les polices, les couleurs et d'autres éléments de la barre latérale de Starlight." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-dropdown-and-list-together/" + title="Starlight Topics : menu déroulant de rubriques sur mobile, liste sur ordinateur" + description="Combinez deux modules d'extension pour profiter du meilleur des deux mondes sur ordinateur et appareils mobiles." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-autogenerate-whole-sidebar/" + title="Agencement de la barre latérale de Starlight avec un middleware" + description="Utilisez un middleware de routage pour contrôler l'agencement de la barre latérale et les étiquettes de groupe, inspiré des conventions de Nuxt Content." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-social-links" + title="Ajouter des liens vers les réseaux sociaux avec des icônes personnalisées à Starlight" + description="Découvrez comment utiliser des icônes personnalisées pour les liens vers les réseaux sociaux dans l'en-tête de votre site web Starlight." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-paste-images-with-visual-studio-code" + title="Coller des images dans les pages Starlight avec Visual Studio Code" + description="Améliorez votre manière de travailler avec Starlight en collant des images dans vos pages de documentation à l'aide de Visual Studio Code." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-add-diagrams-using-d2" + title="Ajouter des diagrammes à votre documentation Starlight à l'aide de D2" + description="Apprenez à utiliser D2 pour ajouter des diagrammes à votre documentation Starlight." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images-cloudinary-astro-sdk" + title="Générer des images Open Graph pour Starlight à l'aide du SDK Astro de Cloudinary" + description="Découvrez comment utiliser le SDK Astro de Cloudinary pour générer des images Open Graph pour votre site web de documentation Starlight." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-list-recent-github-releases" + title="Lister les dernières versions publiées sur GitHub dans Starlight à l'aide de l'API Content Layer d'Astro" + description="Découvrez comment utiliser l'API Content Layer d'Astro pour lister les dernières versions publiées sur GitHub d'un projet Starlight." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-sitewide-banner" + title="Ajouter une bannière pour l'ensemble du site avec Starlight" + description="Découvrez comment créer une bannière pour l'ensemble du site grâce à la fonctionnalité intégrée de bannière par page de Starlight." + /> + <LinkCard + href="https://lirantal.com/blog/customizing-astro-starlight-sidebar-gated-content-auth" + title="Personnalisation de la barre latérale de Starlight pour du contenu protégé par authentification" + description="Sécurisez votre matériel de cours en utilisant Clerk et SSR pour afficher dynamiquement des chapitres dans la barre latérale de Starlight quand l'utilisateur est connecté." + /> +</CardGrid> + +## Contenu vidéo + +Découvrez des vidéos et des chaînes avec du contenu Starlight, y compris des flux en direct et du contenu éducatif. + +import YouTubeGrid from '~/components/youtube-grid.astro'; + +### Vidéos officielles + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=5u0Ds7wzUeI', + title: 'Starlight par Astro', + description: 'Regardez la vidéo de lancement officielle de Starlight', + }, + { + href: 'https://www.youtube.com/watch?v=j8K-ESJF814', + title: 'Un an de Starlight !', + description: + "Sarah parle du thème de documentation communautaire d'Astro", + }, + ]} +/> + +### Vidéos et flux communautaires + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/shorts/zjOWezSzd18', + title: '🌟 MOINS DE 1 MINUTE', + description: + "Regardez Ben créer un nouveau site Starlight en moins d'une minute !", + }, + { + href: 'https://www.youtube.com/watch?v=sF6UcV3moZg', + title: 'Construire une documentation avec Starlight et Astro', + description: + 'Regardez Chris et Alex plonger au cœur de Starlight dans Coder avec CodingCat.dev', + }, + { + href: 'https://www.youtube.com/watch?v=sWkkHbwDeQc', + title: 'Astro Starlight', + description: 'Introduction à Starlight en moins de une minute', + }, + { + href: 'https://www.youtube.com/watch?v=-Ki-1E5gNCk', + title: + "Modèle de documentation Astro Starlight (créer des documentations personnalisées d'application !)", + description: + "Créez un nouveau site Starlight prêt à l'emploi en environ 5 minutes", + }, + { + href: 'https://www.youtube.com/watch?v=12o7WxjAxjM', + title: + 'Inclure une documentation Starlight dans un projet Next.js avec des proxys', + description: + "Configurer un projet Starlight dans un sous-répertoire au sein d'un site Next.js", + }, + { + href: 'https://www.youtube.com/watch?v=5pq80drDrNs', + title: + "J'ai recréé la documentation de Shadcn en 30 minutes avec cet outil incroyable", + description: + "Dans cette vidéo, je passe en revue ce qui rend Starlight si cool et pourquoi vous voudriez l'essayer avec votre prochain projet.", + }, + { + href: 'https://www.youtube.com/watch?v=Q1E4Gkt63ko', + title: 'Astro Starlight et emoji-blast avec Chris Swithinbank', + description: + "Chris, le créateur du thème de documentation Starlight pour Astro, m'aide à le configurer pour le nouveau site web d'emoji-blast. 🌟 🎇", + }, + ]} +/> diff --git a/docs/src/content/docs/fr/resources/plugins.mdx b/docs/src/content/docs/fr/resources/plugins.mdx new file mode 100644 index 00000000000..76515a8be5a --- /dev/null +++ b/docs/src/content/docs/fr/resources/plugins.mdx @@ -0,0 +1,305 @@ +--- +title: Modules d'extension et outils +description: Découvrez les outils communautaires comme des modules d'extension et intégrations qui étendent Starlight ! +sidebar: + order: 1 +--- + +:::tip[Ajoutez le vôtre !] +Avez-vous construit un module d'extension ou un outil pour Starlight ? +Ouvrez une PR ajoutant un lien à cette page ! +::: + +## Modules d'extension + +Les [modules d'extension](/fr/reference/plugins/) peuvent personnaliser la configuration, l'interface utilisateur et le comportement de Starlight, tout en étant faciles à partager et à réutiliser. +Étendez votre site avec des modules d'extension officiels maintenus par l'équipe Starlight et des modules d'extension communautaires maintenus par les utilisateurs de Starlight. + +### Modules d'extension officiels + +<CardGrid> + <LinkCard + href="/fr/guides/site-search/#algolia-docsearch" + title="Algolia DocSearch" + description="Remplacer Pagefind, le système de recherche par défaut, par Algolia DocSearch." + /> +</CardGrid> + +### Modules d'extension communautaires + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-links-validator" + title="starlight-links-validator" + description="Vérifier la validité des liens dans vos pages Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-typedoc" + title="starlight-typedoc" + description="Générer des pages Starlight à partir de TypeScript en utilisant TypeDoc." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-blog" + title="starlight-blog" + description="Ajouter un blogue à votre site de documentation." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-openapi" + title="starlight-openapi" + description="Créer des pages de documentation à partir de spécifications OpenAPI/Swagger." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-obsidian" + title="starlight-obsidian" + description="Publier vos coffres (vaults) Obsidian sur votre site Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-image-zoom" + title="starlight-image-zoom" + description="Ajouter des fonctionnalités de zoom aux images de votre documentation." + /> + <LinkCard + href="https://github.com/lorenzolewis/starlight-utils" + title="starlight-utils" + description="Étendre Starlight avec une collection d'utilitaires courants." + /> + <LinkCard + href="https://github.com/trueberryless/starlight-view-modes" + title="starlight-view-modes" + description="Ajouter différents modes d'affichage à votre site web de documentation." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-versions" + title="starlight-versions" + description="Versionner vos pages de documentation Starlight." + /> + <LinkCard + href="https://inox-tools.fryuni.dev/star-warp" + title="star-warp" + description="Accéder aux résultats de recherche de votre documentation à la vitesse de la lumière." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-heading-badges" + title="starlight-heading-badges" + description="Ajouter des badges à vos en-têtes Markdown et MDX." + /> + <LinkCard + href="https://github.com/Fevol/starlight-site-graph" + title="starlight-site-graph" + description="Ajouter un graphe interactif de votre site dans la barre latérale de votre page." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-sidebar-topics" + title="starlight-sidebar-topics" + description="Diviser votre documentation en différentes sections, chacune ayant sa propre barre latérale." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-cooler-credit" + title="starlight-cooler-credit" + description="Ajouter de jolis crédits pour Starlight ou Astro en bas de la table des matières." + /> + <LinkCard + href="https://github.com/dragomano/starlight-giscus" + title="starlight-giscus" + description="Ajouter des commentaires via Giscus à votre site de documentation." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-videos" + title="starlight-videos" + description="Enrichir votre documentation avec des guides et des cours au format vidéo." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-kbd" + title="starlight-kbd" + description="Documenter facilement des raccourcis clavier." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-auto-sidebar" + title="starlight-auto-sidebar" + description="Modifier vos groupes de barre latérale générés automatiquement." + /> + <LinkCard + href="https://github.com/delucis/starlight-llms-txt" + title="starlight-llms-txt" + description="Ajouter des fichiers llms.txt à votre site de documentation basé sur llmstxt.org." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-toc-overview-customizer" + title="starlight-toc-overview-customizer" + description="Personnaliser la table des matières de Starlight avec un libellé de vue d'ensemble personnalisable." + /> + <LinkCard + href="https://delucis.github.io/starlight-markdown-blocks/" + title="starlight-markdown-blocks" + description="Étendre la syntaxe Markdown des encarts de Starlight avec des types de blocs personnalisés." + /> + <LinkCard + href="https://github.com/WindMillCode/starlight-fullview-mode" + title="starlight-fullview-mode" + description="Réduire les barres latérales et élargir le contenu pour une expérience plein écran." + /> + <LinkCard + href="https://github.com/frostybee/starlight-scroll-to-top" + title="starlight-scroll-to-top" + description="Ajouter un bouton de retour en haut de page à votre site de documentation." + /> + <LinkCard + href="https://github.com/frostybee/starlight-codeblock-fullscreen" + title="starlight-codeblock-fullscreen" + description="Ajouter la fonctionnalité de basculement en plein écran aux blocs Expressive Code de votre documentation." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-auto-drafts" + title="starlight-auto-drafts" + description="Ajuster le comportement par défaut des ébauches et supprimer automatiquement de la barre latérale les liens vers les ébauches en mode production." + /> + <LinkCard + href="https://github.com/corsfix/starlight-contextual-menu" + title="starlight-contextual-menu" + description="Ajouter un menu contextuel à votre documentation Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-changelogs" + title="starlight-changelogs" + description="Afficher les journaux des modifications au côté de la documentation de votre projet." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-github-alerts" + title="starlight-github-alerts" + description="Afficher les alertes GitHub sous forme d'encarts Starlight." + /> + <LinkCard + href="https://github.com/dlcastillop/starlight-page-actions" + title="starlight-page-actions" + description="Ajoute des boutons d'action aux pages de votre documentation." + /> + <LinkCard + href="https://github.com/typesense/starlight-docsearch-typesense" + title="starlight-docsearch-typesense" + description="Une alternative au module d'extension officiel Algolia DocSearch reposant sur Typesense." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-swipe/" + title="starlight-sidebar-swipe" + description="Rendre la barre latérale gauche accessible par glissement sur les appareils mobiles comme sur Discord Mobile." + /> + <LinkCard + href="https://github.com/Rettend/starlight-plugin-icons" + title="starlight-plugin-icons" + description="Ajouter des icônes à Astro Starlight : barre latérale, blocs de code, arborescence de fichiers." + /> + <LinkCard + href="https://github.com/dlcastillop/starlight-ui-tweaks" + title="starlight-ui-tweaks" + description="Étend les composants natifs avec des liens de navigation personnalisés, des publicités, des pieds de page axés marketing et un bouton de thème plus épuré." + /> + <LinkCard + href="https://frostybee.github.io/starlight-tags/" + title="starlight-tags" + description="Ajouter des étiquettes aux pages de votre documentation Starlight pour organiser et faciliter la recherche de contenu." + /> + <LinkCard + href="https://github.com/dionysuzx/starlight-copy-button" + title="starlight-copy-button" + description="Copier une page de documentation complète au format Markdown à l'aide d'un élégant bouton dans le titre de la page." + /> + <LinkCard + href="https://frostybee.github.io/starlight-telescope/" + title="starlight-telescope" + description="Accéder rapidement à n'importe quelle page de votre documentation Starlight grâce à la recherche approximative et à la navigation au clavier." + /> + <LinkCard + href="https://frostybee.github.io/starlight-announcement/" + title="starlight-announcement" + description="Ajouter des bannières d'annonce améliorées incluant la possibilité de les fermer, des variantes, une planification et un ciblage de page pour votre documentation Starlight." + /> +</CardGrid> + +## Outils et intégrations communautaires + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +Ces outils et intégrations communautaires peuvent être utilisés pour ajouter des fonctionnalités à votre site Starlight. + +<CardGrid> + <LinkCard + href="https://www.feelback.dev/blog/new-astro-starlight-integration/" + title="FeelBack" + description="Ajouter un système de retour d'expérience utilisateur à vos pages de documentation." + /> + <LinkCard + href="https://github.com/val-town/notion-to-astro" + title="notion-to-astro" + description="Convertir des exports Notion en documentation Astro Starlight" + /> + <LinkCard + href="https://github.com/mattjennings/astro-live-code" + title="astro-live-code" + description="Afficher vos blocs de code MDX sous forme de composants interactifs" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-i18n" + title="starlight-i18n" + description="Extension Visual Studio Code pour aider à traduire les pages Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-package-managers" + title="starlight-package-managers" + description="Affiche rapidement les commandes liées à npm pour plusieurs gestionnaires de paquets." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-showcases" + title="starlight-showcases" + description="Ensemble de composants Starlight permettant de créer des pages vitrines." + /> + <LinkCard + href="https://github.com/HiDeoo/generator-starlight-plugin" + title="@hideoo/starlight-plugin" + description="Un générateur pour rapidement créer des modules d'extension Starlight." + /> + <LinkCard + href="https://github.com/Linkerin/starlight-to-pdf" + title="starlight-to-pdf" + description="Un outil en ligne de commande pour convertir des sites web Starlight en fichiers PDF." + /> + <LinkCard + href="https://github.com/joesaby/astro-plantuml" + title="astro-plantuml" + description="Générer le contenu PlantUML dans les blocs de code Markdown." + /> + <LinkCard + href="https://github.com/joesaby/astro-mermaid" + title="astro-mermaid" + description="Générer du contenu Mermaid côté client dans des blocs de code Markdown." + /> + <LinkCard + href="https://github.com/HiDeoo/astro-d2" + title="astro-d2" + description="Transformer des blocs de code Markdown utilisant D2 en diagrammes." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-links" + title="starlight-links" + description="Extension Visual Studio Code fournissant IntelliSense pour les liens présents dans les contenus Markdown et MDX de Starlight." + /> + <LinkCard + href="https://docs.contentisland.net/templates/starlight/" + title="contentisland-cli" + description="Connecter et synchroniser votre projet Starlight avec le CMS headless Content Island pour modifier et gérer votre documentation." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown" + title="starlight-sidebar-topics-dropdown" + description="Diviser vos pages de documentation en plusieurs sous-pages et passer de l'une à l'autre à l'aide d'un menu déroulant dans la barre latérale." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-save-file-component" + title="starlight-save-file-component" + description="Afficher rapidement un lien vers une ressource téléchargeable sur votre site Starlight." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-contributor-list" + title="starlight-contributor-list" + description="Afficher la liste de tous les contributeurs de votre projet." + /> +</CardGrid> diff --git a/docs/src/content/docs/fr/resources/showcase.mdx b/docs/src/content/docs/fr/resources/showcase.mdx new file mode 100644 index 00000000000..aeb6b53c539 --- /dev/null +++ b/docs/src/content/docs/fr/resources/showcase.mdx @@ -0,0 +1,21 @@ +--- +title: Vitrine Starlight +description: Découvrez les sites construits avec Starlight ! +sidebar: + label: Vitrine des sites +--- + +:::tip[Ajoutez le vôtre !] +Avez-vous construit un site Starlight ? +[Ouvrez une PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#showcase) ajoutant un lien à cette page ! +::: + +## Sites + +import ShowcaseSites from '~/components/showcase-sites.astro'; + +Starlight est déjà utilisé en production. Voici quelques sites sur le web : + +<ShowcaseSites /> + +Voir tous les [dépôts publics de projets utilisant Starlight sur GitHub](https://github.com/withastro/starlight/network/dependents). diff --git a/docs/src/content/docs/fr/resources/themes.mdx b/docs/src/content/docs/fr/resources/themes.mdx new file mode 100644 index 00000000000..2b72f1162f5 --- /dev/null +++ b/docs/src/content/docs/fr/resources/themes.mdx @@ -0,0 +1,129 @@ +--- +title: Thèmes +description: Modifiez l'apparence visuelle de votre documentation avec un thème communautaire pour Starlight +tableOfContents: false +sidebar: + order: 2 +head: + - tag: style + content: | + body { --sl-content-width: 66.75rem; } +--- + +import ThemeGrid from '~/components/theme-grid.astro'; + +Un thème est un module d'extension Starlight qui modifie l'apparence visuelle d'un site avec du [CSS personnalisé](/fr/guides/css-and-tailwind/), des [redéfinitions de composants](/fr/guides/overriding-components/), ou d'autres nouvelles fonctionnalités. + +### Thèmes communautaires + +Installez un thème créé par la communauté pour personnaliser rapidement l'apparence de votre site. + +Découvrez ci-dessous un aperçu de tous les thèmes ou essayez-les de manière interactive sur le [site de démonstration de Starlight Themes](https://starlight-themes.netlify.app/). + +<ThemeGrid + labels={{ + /** Accessible label for the theme toggle. */ + legend: 'Aperçu', + /** Accessible label for the dark color scheme variant. */ + dark: 'Sombre', + /** Accessible label for the light color scheme variant. */ + light: 'Clair', + }} + themes={[ + { + title: 'Starlight Rapide', + description: + 'Thème Starlight inspiré du thème Vitesse pour Visual Studio Code.', + href: 'https://starlight-theme-rapide.vercel.app/', + previews: { light: 'rapide-light.png', dark: 'rapide-dark.png' }, + }, + { + title: 'Starlight Obsidian', + description: + "Thème Starlight inspiré par le style des sites d'Obsidian Publish.", + href: 'https://fevol.github.io/starlight-theme-obsidian/', + previews: { light: 'obsidian-light.png', dark: 'obsidian-dark.png' }, + }, + { + title: 'Catppuccin for Starlight', + description: 'Thème apaisant aux couleurs pastel pour Starlight.', + href: 'https://starlight.catppuccin.com/', + previews: { light: 'catppuccin-light.png', dark: 'catppuccin-dark.png' }, + }, + { + title: 'Ion', + description: 'Un thème élégant et moderne pour Starlight.', + href: 'https://louisescher.github.io/starlight-ion-theme/', + previews: { light: 'ion-light.png', dark: 'ion-dark.png' }, + }, + { + title: 'Starlight Black', + description: 'Thème Starlight inspiré par la doc de shadcn.', + href: 'https://starlight-theme-black.vercel.app/', + previews: { light: 'black-light.png', dark: 'black-dark.png' }, + }, + { + title: 'Starlight Flexoki', + description: + 'Un thème chaleureux et convivial basé sur la palette de couleurs Flexoki.', + href: 'https://delucis.github.io/starlight-theme-flexoki/', + previews: { light: 'flexoki-light.png', dark: 'flexoki-dark.png' }, + }, + { + title: 'Starlight Nova', + description: 'Un superbe thème moderne pour Starlight.', + href: 'https://starlight-theme-nova.pages.dev/', + previews: { light: 'nova-light.png', dark: 'nova-dark.png' }, + }, + { + title: 'Starlight Next.js', + description: 'Thème Starlight inspiré par la documentation de Next.js.', + href: 'https://starlight-theme-next.trueberryless.org/', + previews: { light: 'nextjs-light.png', dark: 'nextjs-dark.png' }, + }, + { + title: 'Starlight Galaxy', + description: + 'Un thème Astro Starlight conçu pour la publication de documentation et de contenu éducatif.', + href: 'https://frostybee.github.io/starlight-theme-galaxy/', + previews: { light: 'galaxy-light.png', dark: 'galaxy-dark.png' }, + }, + { + title: 'Starlight Page', + description: + 'Un thème Starlight intuitif et moderne avec des animations fluides et de subtiles transitions.', + href: 'https://pelagornis-page.netlify.app/', + previews: { light: 'page-light.png', dark: 'page-dark.png' }, + }, + { + title: 'Starlight Gruvbox', + description: 'Thème groove et rétro pour Starlight', + href: 'https://starlight-theme-gruvbox.otterlord.dev/', + previews: { light: 'gruvbox-light.png', dark: 'gruvbox-dark.png' }, + }, + { + title: 'Starlight Six', + description: 'Thème Starlight épuré et moderne par Six Technology', + href: 'https://six-tech.github.io/Six.StarlightTheme/', + previews: { light: 'six-light.png', dark: 'six-dark.png' }, + }, + { + title: 'Starlight Vintage', + description: + "Un thème Starlight fortement inspiré du design intemporel de l'ancienne documentation d'Astro.", + href: 'https://starlight-theme-vintage.netlify.app/', + previews: { light: 'vintage-light.png', dark: 'vintage-dark.png' }, + }, + { + title: 'Starlight Rosé Pine', + description: 'Ambiance Soho pour Starlight.', + href: 'https://starlight-theme-rose-pine.trueberryless.org/', + previews: { light: 'rose-pine-light.png', dark: 'rose-pine-dark.png' }, + }, + ]} +/> + +:::tip[Ajoutez le vôtre !] +Avez-vous construit un thème pour Starlight ? +[Ouvrez une PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#themes) ajoutant votre thème à cette page ! +::: diff --git a/docs/src/content/docs/fr/showcase.mdx b/docs/src/content/docs/fr/showcase.mdx deleted file mode 100644 index 482871bb6f1..00000000000 --- a/docs/src/content/docs/fr/showcase.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Vitrine Starlight -description: Découvrez les sites construits avec Starlight et les outils communautaires qui étendent Starlight ! ---- - -:::tip[Ajoutez le vôtre !] -Avez-vous construit un site Starlight ou un outil pour Starlight ? -Ouvrez une PR en ajoutant un lien à cette page ! -::: - -## Sites - -import ShowcaseSites from '../../../components/showcase-sites.astro'; - -Starlight est déjà utilisé en production. Voici quelques sites sur le web : - -<ShowcaseSites /> - -Voir tous les [dépôts publics de projets utilisant Starlight sur GitHub](https://github.com/withastro/starlight/network/dependents). - -## Modules d'extension communautaires - -import { CardGrid, LinkCard } from '@astrojs/starlight/components'; - -Ces outils, modules d'extension et intégrations communautaires fonctionnent avec Starlight pour étendre ses fonctionnalités. - -<CardGrid> - <LinkCard - href="https://www.feelback.dev/blog/new-astro-starlight-integration/" - title="FeelBack" - description="Ajouter un système de retour d'expérience utilisateur à vos pages de documentation." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-blog" - title="starlight-blog" - description="Ajouter un blogue à votre site de documentation." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-links-validator" - title="starlight-links-validator" - description="Vérifier la validité des liens dans vos pages Starlight." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-typedoc" - title="starlight-typedoc" - description="Générer des pages Starlight à partir de TypeScript en utilisant TypeDoc." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-openapi" - title="starlight-openapi" - description="Créer des pages de documentation à partir de spécifications OpenAPI/Swagger." - /> -</CardGrid> diff --git a/docs/src/content/docs/getting-started.mdx b/docs/src/content/docs/getting-started.mdx index 827fc086216..3c75622e5ba 100644 --- a/docs/src/content/docs/getting-started.mdx +++ b/docs/src/content/docs/getting-started.mdx @@ -5,17 +5,20 @@ description: Learn how to start building your next documentation site with Starl import { Tabs, TabItem } from '@astrojs/starlight/components'; -## Creating a new project - Starlight is a full-featured documentation theme built on top of the [Astro](https://astro.build) framework. +This guide will help you get started with a new project. +See the [manual setup instructions](/manual-setup/) to add Starlight to an existing Astro project. + +## Quick Start + +### Create a new project -You can create a new Astro + Starlight project using the following command: +Create a new Astro + Starlight project by running the following command in your terminal: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# create a new project with npm npm create astro@latest -- --template starlight ``` @@ -23,7 +26,6 @@ npm create astro@latest -- --template starlight <TabItem label="pnpm"> ```sh -# create a new project with pnpm pnpm create astro --template starlight ``` @@ -31,7 +33,6 @@ pnpm create astro --template starlight <TabItem label="Yarn"> ```sh -# create a new project with yarn yarn create astro --template starlight ``` @@ -45,85 +46,96 @@ Try Starlight in your browser: [open the template on StackBlitz](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). ::: -## Creating content with Starlight +### Start the development server -Starlight is ready for you to add new content, or bring your existing files! +When working locally, [Astro’s development server](https://docs.astro.build/en/reference/cli-reference/#astro-dev) lets you preview your work and automatically refreshes your browser when you make changes. -### File formats +Inside your project directory, run the following command to start the development server: -Starlight supports authoring content in Markdown and MDX. (You can add support for Markdoc by installing the experimental [Astro Markdoc integration](https://docs.astro.build/en/guides/integrations-guide/markdoc/).) +<Tabs syncKey="pkg"> +<TabItem label="npm"> -### Add pages +```sh +npm run dev +``` -Add new pages to your site automatically by creating `.md` or `.mdx` files in `src/content/docs/`. Add sub-folders to organize your files, and to create multiple path segments: +</TabItem> +<TabItem label="pnpm"> +```sh +pnpm dev ``` -src/content/docs/hello-world.md => your-site.com/hello-world -src/content/docs/guides/faq.md => your-site.com/guides/faq + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev ``` -### Type-safe frontmatter +</TabItem> +</Tabs> -All Starlight pages share a customizable [common set of frontmatter properties](/reference/frontmatter/) to control how the page appears: +This will log a message to your terminal with the URL of your local preview. +Open this URL to start browsing your site. -```md ---- -title: Hello, World! -description: This is a page in my Starlight-powered site ---- -``` +### Add content -If you forget anything important, Starlight will let you know. +Starlight is ready for you to add new content, or bring your existing files! -## Deploying your Starlight website +Add new pages to your site by creating Markdown files in the `src/content/docs/` directory. -Once you have created and customized your Starlight website, you can deploy it to a web server or hosting platform of your choice including Netlify, Vercel, GitHub Pages and many more. +Read more about file-based routing and support for MDX and Markdoc files in the [“Pages”](/guides/pages/) guide. -[Learn about deploying an Astro site in the Astro docs.](https://docs.astro.build/en/guides/deploy/) +### Next steps + +- **Configure:** Learn about common options in [“Customizing Starlight”](/guides/customization/). +- **Navigate:** Set up your sidebar with the [“Sidebar Navigation”](/guides/sidebar/) guide. +- **Components:** Discover built-in cards, tabs, and more in the [“Components”](/components/using-components/) guide. +- **Extend:** Explore community add-ons in our [“Plugins”](/resources/plugins/) and [“Themes”](/resources/themes/) catalogs. +- **Deploy:** Publish your work with the [“Deploy your site”](https://docs.astro.build/en/guides/deploy/) guide in the Astro docs. ## Updating Starlight :::tip -Because Starlight is beta software, there will be frequent updates and improvements. Be sure to update Starlight regularly! +Because Starlight is beta software, there will be frequent updates and improvements. +Be sure to update Starlight regularly! ::: -Starlight is an Astro integration, and is updated like any `@astrojs/*` integration: +Starlight is an Astro integration. You can update it and other Astro packages by running the following command in your terminal: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# upgrade Starlight with npm -npm install @astrojs/starlight@latest +npx @astrojs/upgrade ``` </TabItem> <TabItem label="pnpm"> ```sh -# upgrade Starlight with pnpm -pnpm upgrade @astrojs/starlight --latest +pnpm dlx @astrojs/upgrade ``` </TabItem> <TabItem label="Yarn"> ```sh -# upgrade Starlight with yarn -yarn upgrade @astrojs/starlight --latest +yarn dlx @astrojs/upgrade ``` </TabItem> </Tabs> -You can see a full list of the changes made in each release in [the Starlight changelog](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md). +See the [Starlight changelog](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md) for a full list of the changes made in each release. ## Troubleshooting Starlight -Both Starlight [project configuration](/reference/configuration/) and [individual page frontmatter configuration](/reference/frontmatter/) information are available in the Reference section of this site. Use these pages to ensure that your Starlight site is configured and functioning properly. - -See the growing list of guides in the sidebar for help adding content and customizing your Starlight site. +Use the [project configuration](/reference/configuration/) and [individual page frontmatter configuration](/reference/frontmatter/) reference pages to ensure that your Starlight site is configured and functioning properly. +See the guides in the sidebar for help adding content and customizing your Starlight site. -If your answer cannot be found in these docs, please visit the [full Astro Docs](https://docs.astro.build) for complete Astro documentation. Your question may be answered by understanding how Astro works in general, underneath this Starlight theme. +If your answer cannot be found in these docs, please visit the [full Astro Docs](https://docs.astro.build) for complete Astro documentation. +Your question may be answered by understanding how Astro works in general, underneath this Starlight theme. You can also check for any known [Starlight issues on GitHub](https://github.com/withastro/starlight/issues), and get help in the [Astro Discord](https://astro.build/chat/) from our active, friendly community! Post questions in our `#support` forum with the "starlight" tag, or visit our dedicated `#starlight` channel to discuss current development and more! diff --git a/docs/src/content/docs/guides/authoring-content.md b/docs/src/content/docs/guides/authoring-content.md deleted file mode 100644 index 25b9614fb3e..00000000000 --- a/docs/src/content/docs/guides/authoring-content.md +++ /dev/null @@ -1,209 +0,0 @@ ---- -title: Authoring Content in Markdown -description: An overview of the Markdown syntax Starlight supports. ---- - -Starlight supports the full range of [Markdown](https://daringfireball.net/projects/markdown/) syntax in `.md` files as well as frontmatter [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) to define metadata such as a title and description. - -Please be sure to check the [MDX docs](https://mdxjs.com/docs/what-is-mdx/#markdown) or [Markdoc docs](https://markdoc.dev/docs/syntax) if using those file formats, as Markdown support and usage can differ. - -## Inline styles - -Text can be **bold**, _italic_, or ~~strikethrough~~. - -```md -Text can be **bold**, _italic_, or ~~strikethrough~~. -``` - -You can [link to another page](/getting-started/). - -```md -You can [link to another page](/getting-started/). -``` - -You can highlight `inline code` with backticks. - -```md -You can highlight `inline code` with backticks. -``` - -## Images - -Images in Starlight use [Astro’s built-in optimized asset support](https://docs.astro.build/en/guides/assets/). - -Markdown and MDX support the Markdown syntax for displaying images that includes alt-text for screen readers and assistive technology. - -![An illustration of planets and stars featuring the word “astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) - -```md -![An illustration of planets and stars featuring the word “astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) -``` - -Relative image paths are also supported for images stored locally in your project. - -```md -// src/content/docs/page-1.md - -![A rocketship in space](../../assets/images/rocket.svg) -``` - -## Headings - -You can structure content using a heading. Headings in Markdown are indicated by a number of `#` at the start of the line. - -### How to structure page content in Starlight - -Starlight is configured to automatically use your page title as a top-level heading and will include an "Overview" heading at top of each page's table of contents. We recommend starting each page with regular paragraph text content and using on-page headings from `<h2>` and down: - -```md ---- -title: Markdown Guide -description: How to use Markdown in Starlight ---- - -This page describes how to use Markdown in Starlight. - -## Inline Styles - -## Headings -``` - -### Automatic heading anchor links - -Using headings in Markdown will automatically give you anchor links so you can link directly to certain sections of your page: - -```md ---- -title: My page of content -description: How to use Starlight's built-in anchor links ---- - -## Introduction - -I can link to [my conclusion](#conclusion) lower on the same page. - -## Conclusion - -`https://my-site.com/page1/#introduction` navigates directly to my Introduction. -``` - -Level 2 (`<h2>`) and Level 3 (`<h3>`) headings will automatically appear in the page table of contents. - -## Asides - -Asides (also known as “admonitions” or “callouts”) are useful for displaying secondary information alongside a page’s main content. - -Starlight provides a custom Markdown syntax for rendering asides. Aside blocks are indicated using a pair of triple colons `:::` to wrap your content, and can be of type `note`, `tip`, `caution` or `danger`. - -You can nest any other Markdown content types inside an aside, but asides are best suited to short and concise chunks of content. - -### Note aside - -:::note -Starlight is a documentation website toolkit built with [Astro](https://astro.build/). You can get started with this command: - -```sh -npm create astro@latest -- --template starlight -``` - -::: - -````md -:::note -Starlight is a documentation website toolkit built with [Astro](https://astro.build/). You can get started with this command: - -```sh -npm create astro@latest -- --template starlight -``` - -::: -```` - -### Custom aside titles - -You can specify a custom title for the aside in square brackets following the aside type, e.g. `:::tip[Did you know?]`. - -:::tip[Did you know?] -Astro helps you build faster websites with [“Islands Architecture”](https://docs.astro.build/en/concepts/islands/). -::: - -```md -:::tip[Did you know?] -Astro helps you build faster websites with [“Islands Architecture”](https://docs.astro.build/en/concepts/islands/). -::: -``` - -### More aside types - -Caution and danger asides are helpful for drawing a user’s attention to details that may trip them up. -If you find yourself using these a lot, it may also be a sign that the thing you are documenting could benefit from being redesigned. - -:::caution -If you are not sure you want an awesome docs site, think twice before using [Starlight](../../). -::: - -:::danger -Your users may be more productive and find your product easier to use thanks to helpful Starlight features. - -- Clear navigation -- User-configurable colour theme -- [i18n support](/guides/i18n) - -::: - -```md -:::caution -If you are not sure you want an awesome docs site, think twice before using [Starlight](../../). -::: - -:::danger -Your users may be more productive and find your product easier to use thanks to helpful Starlight features. - -- Clear navigation -- User-configurable colour theme -- [i18n support](/guides/i18n) - -::: -``` - -## Blockquotes - -> This is a blockquote, which is commonly used when quoting another person or document. -> -> Blockquotes are indicated by a `>` at the start of each line. - -```md -> This is a blockquote, which is commonly used when quoting another person or document. -> -> Blockquotes are indicated by a `>` at the start of each line. -``` - -## Code blocks - -A code block is indicated by a block with three backticks <code>```</code> at the start and end. You can indicate the programming language being used after the opening backticks. - -```js -// Javascript code with syntax highlighting. -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` - -````md -```js -// Javascript code with syntax highlighting. -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` -```` - -```md -Long, single-line code blocks should not wrap. They should horizontally scroll if they are too long. This line should be long enough to demonstrate this. -``` - -## Other common Markdown features - -Starlight supports all other Markdown authoring syntax, such as lists and tables. See the [Markdown Cheat Sheet from The Markdown Guide](https://www.markdownguide.org/cheat-sheet/) for a quick overview of all the Markdown syntax elements. diff --git a/docs/src/content/docs/guides/authoring-content.mdx b/docs/src/content/docs/guides/authoring-content.mdx new file mode 100644 index 00000000000..d977b17f171 --- /dev/null +++ b/docs/src/content/docs/guides/authoring-content.mdx @@ -0,0 +1,698 @@ +--- +title: Authoring Content in Markdown +description: An overview of the Markdown syntax Starlight supports. +--- + +Starlight supports the full range of [Markdown](https://daringfireball.net/projects/markdown/) syntax in `.md` files as well as frontmatter [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) to define metadata such as a title and description. + +Please be sure to check the [MDX docs](https://mdxjs.com/docs/what-is-mdx/#markdown) or [Markdoc docs](https://markdoc.dev/docs/syntax) if using those file formats, as Markdown support and usage can differ. + +## Frontmatter + +You can customize individual pages in Starlight by setting values in their frontmatter. +Frontmatter is set at the top of your files between `---` separators: + +```md title="src/content/docs/example.md" +--- +title: My page title +--- + +Page content follows the second `---`. +``` + +Every page must include at least a `title`. +See the [frontmatter reference](/reference/frontmatter/) for all available fields and how to add custom fields. + +## Inline styles + +Text can be **bold**, _italic_, or ~~strikethrough~~. + +```md +Text can be **bold**, _italic_, or ~~strikethrough~~. +``` + +You can [link to another page](/getting-started/). + +```md +You can [link to another page](/getting-started/). +``` + +You can highlight `inline code` with backticks. + +```md +You can highlight `inline code` with backticks. +``` + +## Images + +Images in Starlight use [Astro’s built-in optimized asset support](https://docs.astro.build/en/guides/images/). + +Markdown and MDX support the Markdown syntax for displaying images that includes alt-text for screen readers and assistive technology. + +![An illustration of planets and stars featuring the word “astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) + +```md +![An illustration of planets and stars featuring the word “astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) +``` + +Relative image paths are also supported for images stored locally in your project. + +```md +// src/content/docs/page-1.md + +![A rocketship in space](../../assets/images/rocket.svg) +``` + +## Headings + +You can structure content using a heading. Headings in Markdown are indicated by a number of `#` at the start of the line. + +### How to structure page content in Starlight + +Starlight is configured to automatically use your page title as a top-level heading and will include an "Overview" heading at top of each page's table of contents. We recommend starting each page with regular paragraph text content and using on-page headings from `<h2>` and down: + +```md +--- +title: Markdown Guide +description: How to use Markdown in Starlight +--- + +This page describes how to use Markdown in Starlight. + +## Inline Styles + +## Headings +``` + +### Automatic heading anchor links + +Using headings in Markdown will automatically give you anchor links so you can link directly to certain sections of your page: + +```md +--- +title: My page of content +description: How to use Starlight's built-in anchor links +--- + +## Introduction + +I can link to [my conclusion](#conclusion) lower on the same page. + +## Conclusion + +`https://my-site.com/page1/#introduction` navigates directly to my Introduction. +``` + +Level 2 (`<h2>`) and Level 3 (`<h3>`) headings will automatically appear in the page table of contents. + +Learn more about how Astro processes heading `id`s in [the Astro Documentation](https://docs.astro.build/en/guides/markdown-content/#heading-ids) + +## Asides + +Asides (also known as “admonitions” or “callouts”) are useful for displaying secondary information alongside a page’s main content. + +Starlight provides a custom Markdown syntax for rendering asides. Aside blocks are indicated using a pair of triple colons `:::` to wrap your content, and can be of type `note`, `tip`, `caution` or `danger`. + +You can nest any other Markdown content types inside an aside, but asides are best suited to short and concise chunks of content. + +### Note aside + +:::note +Starlight is a documentation website toolkit built with [Astro](https://astro.build/). You can get started with this command: + +```sh +npm create astro@latest -- --template starlight +``` + +::: + +````md +:::note +Starlight is a documentation website toolkit built with [Astro](https://astro.build/). You can get started with this command: + +```sh +npm create astro@latest -- --template starlight +``` + +::: +```` + +### Custom aside titles + +You can specify a custom title for the aside in square brackets following the aside type, e.g. `:::tip[Did you know?]`. + +:::tip[Did you know?] +Astro helps you build faster websites with [“Islands Architecture”](https://docs.astro.build/en/concepts/islands/). +::: + +```md +:::tip[Did you know?] +Astro helps you build faster websites with [“Islands Architecture”](https://docs.astro.build/en/concepts/islands/). +::: +``` + +### Custom aside icons + +You can specify a custom icon for the aside in curly brackets following the aside type or [custom title](#custom-aside-titles), e.g. `:::tip{icon="heart"}` or `:::tip[Did you know?]{icon="heart"}` respectively. +The icon name must be set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons). + +:::tip{icon="heart"} +Astro helps you build faster websites with [“Islands Architecture”](https://docs.astro.build/en/concepts/islands/). +::: + +```md +:::tip{icon="heart"} +Astro helps you build faster websites with [“Islands Architecture”](https://docs.astro.build/en/concepts/islands/). +::: +``` + +### More aside types + +Caution and danger asides are helpful for drawing a user’s attention to details that may trip them up. +If you find yourself using these a lot, it may also be a sign that the thing you are documenting could benefit from being redesigned. + +:::caution +If you are not sure you want an awesome docs site, think twice before using [Starlight](/). +::: + +:::danger +Your users may be more productive and find your product easier to use thanks to helpful Starlight features. + +- Clear navigation +- User-configurable colour theme +- [i18n support](/guides/i18n/) + +::: + +```md +:::caution +If you are not sure you want an awesome docs site, think twice before using [Starlight](/). +::: + +:::danger +Your users may be more productive and find your product easier to use thanks to helpful Starlight features. + +- Clear navigation +- User-configurable colour theme +- [i18n support](/guides/i18n/) + +::: +``` + +## Blockquotes + +> This is a blockquote, which is commonly used when quoting another person or document. +> +> Blockquotes are indicated by a `>` at the start of each line. + +```md +> This is a blockquote, which is commonly used when quoting another person or document. +> +> Blockquotes are indicated by a `>` at the start of each line. +``` + +## Code blocks + +A code block is indicated by a block with three backticks <code>```</code> at the start and end. You can indicate the programming language being used after the opening backticks. + +```js +// Javascript code with syntax highlighting. +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` + +````md +```js +// Javascript code with syntax highlighting. +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` +```` + +### Expressive Code features + +Starlight uses [Expressive Code](https://expressive-code.com/) to extend formatting possibilities for code blocks. +Expressive Code’s text markers and window frames plugins are enabled by default. +Code block rendering can be configured using Starlight’s [`expressiveCode` configuration option](/reference/configuration/#expressivecode). + +#### Text markers + +You can highlight specific lines or parts of your code blocks using [Expressive Code text markers](https://expressive-code.com/key-features/text-markers/) on the opening line of your code block. +Use curly braces (`{ }`) to highlight entire lines, and quotation marks to highlight strings of text. + +There are three highlighting styles: neutral for calling attention to code, green for indicating inserted code, and red for indicating deleted code. +Both text and entire lines can be marked using the default marker, or in combination with `ins=` and `del=` to produce the desired highlighting. + +Expressive Code provides several options for customizing the visual appearance of your code samples. +Many of these can be combined, for highly illustrative code samples. +Please explore the [Expressive Code documentation](https://expressive-code.com/key-features/text-markers/#configuration) for the extensive options available. +Some of the most common examples are shown below: + +- [Mark entire lines & line ranges using the `{ }` marker](https://expressive-code.com/key-features/text-markers/#marking-full-lines--line-ranges): + + ```js {2-3} + function demo() { + // This line (#2) and the next one are highlighted + return 'This is line #3 of this snippet'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js {2-3} + function demo() { + // This line (#2) and the next one are highlighted + return 'This is line #3 of this snippet'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="{2-3}" %} + function demo() { + // This line (#2) and the next one are highlighted + return 'This is line #3 of this snippet'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [Mark selections of text using the `" "` marker or regular expressions](https://expressive-code.com/key-features/text-markers/#marking-individual-text-inside-lines): + + ```js "Individual terms" /Even.*supported/ + // Individual terms can be highlighted, too + function demo() { + return 'Even regular expressions are supported'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "Individual terms" /Even.*supported/ + // Individual terms can be highlighted, too + function demo() { + return 'Even regular expressions are supported'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'Individual terms' /Even.*supported/" %} + // Individual terms can be highlighted, too + function demo() { + return 'Even regular expressions are supported'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [Mark text or lines as inserted or deleted with `ins` or `del`](https://expressive-code.com/key-features/text-markers/#selecting-inline-marker-types-mark-ins-del): + + ```js "return true;" ins="inserted" del="deleted" + function demo() { + console.log('These are inserted and deleted marker types'); + // The return statement uses the default marker type + return true; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "return true;" ins="inserted" del="deleted" + function demo() { + console.log('These are inserted and deleted marker types'); + // The return statement uses the default marker type + return true; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'return true;' ins='inserted' del='deleted'" %} + function demo() { + console.log('These are inserted and deleted marker types'); + // The return statement uses the default marker type + return true; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [Combine syntax highlighting with `diff`-like syntax](https://expressive-code.com/key-features/text-markers/#combining-syntax-highlighting-with-diff-like-syntax): + + ```diff lang="js" + function thisIsJavaScript() { + // This entire block gets highlighted as JavaScript, + // and we can still add diff markers to it! + - console.log('Old code to be removed') + + console.log('New and shiny code!') + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```diff lang="js" + function thisIsJavaScript() { + // This entire block gets highlighted as JavaScript, + // and we can still add diff markers to it! + - console.log('Old code to be removed') + + console.log('New and shiny code!') + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```diff {% meta="lang='js'" %} + function thisIsJavaScript() { + // This entire block gets highlighted as JavaScript, + // and we can still add diff markers to it! + - console.log('Old code to be removed') + + console.log('New and shiny code!') + } + ``` + ```` + + </TabItem> + + </Tabs> + +#### Frames and titles + +Code blocks can be rendered inside a window-like frame. +A frame that looks like a terminal window will be used for shell scripting languages (e.g. `bash` or `sh`). +Other languages display inside a code editor-style frame if they include a title. + +A code block’s optional title can be set either with a `title="..."` attribute following the code block's opening backticks and language identifier, or with a file name comment in the first lines of the code. + +- [Add a file name tab with a comment](https://expressive-code.com/key-features/frames/#code-editor-frames) + + ```js + // my-test-file.js + console.log('Hello World!'); + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js + // my-test-file.js + console.log('Hello World!'); + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````md + ```js + // my-test-file.js + console.log('Hello World!'); + ``` + ```` + + </TabItem> + + </Tabs> + +- [Add a title to a Terminal window](https://expressive-code.com/key-features/frames/#terminal-frames) + + ```bash title="Installing dependencies…" + npm install + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash title="Installing dependencies…" + npm install + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% title="Installing dependencies…" %} + npm install + ``` + ```` + + </TabItem> + + </Tabs> + +- [Disable window frames with `frame="none"`](https://expressive-code.com/key-features/frames/#overriding-frame-types) + + ```bash frame="none" + echo "This is not rendered as a terminal despite using the bash language" + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash frame="none" + echo "This is not rendered as a terminal despite using the bash language" + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% frame="none" %} + echo "This is not rendered as a terminal despite using the bash language" + ``` + ```` + + </TabItem> + + </Tabs> + +## Details + +Details (also known as “disclosures” or “accordions”) are useful to hide content that is not immediately relevant. +Users can click a short summary to expand and view the full content. + +Use the standard HTML [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details) and [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary) elements in your Markdown content to create a disclosure widget. + +You can nest any other Markdown syntax inside a `<details>` element. + +<details> +<summary>Where and when is the Andromeda constellation most visible?</summary> + +The [Andromeda constellation](<https://en.wikipedia.org/wiki/Andromeda_(constellation)>) is most visible in the night sky during the month of November at latitudes between `+90°` and `−40°`. + +</details> + +```md +<details> +<summary>Where and when is the Andromeda constellation most visible?</summary> + +The [Andromeda constellation](<https://en.wikipedia.org/wiki/Andromeda_(constellation)>) is most visible in the night sky during the month of November at latitudes between `+90°` and `−40°`. + +</details> +``` + +## Footnotes + +[Footnotes](https://www.markdownguide.org/extended-syntax/#footnotes) are useful for adding brief references or clarifications without interrupting the flow of your content. They appear as numbered superscript links that jump to referenced text collected at the bottom of the page. + +Define a footnote using square brackets with a caret and numbered reference: + +```md +Here is a footnote[^1] with some additional text after it. + +[^1]: My reference. +``` + +## Other common Markdown features + +Starlight supports all other Markdown authoring syntax, such as lists and tables. See the [Markdown Cheat Sheet from The Markdown Guide](https://www.markdownguide.org/cheat-sheet/) for a quick overview of all the Markdown syntax elements. + +## Advanced Markdown and MDX configuration + +Starlight uses Astro’s Markdown and MDX renderer built on remark and rehype. You can add support for custom syntax and behavior by adding `remarkPlugins` or `rehypePlugins` in your Astro config file. See [“Markdown Plugins”](https://docs.astro.build/en/guides/markdown-content/#markdown-plugins) in the Astro docs to learn more. + +## Markdoc + +Starlight supports authoring content in Markdoc using the experimental [Astro Markdoc integration](https://docs.astro.build/en/guides/integrations-guide/markdoc/) and the Starlight Markdoc preset. + +### Create a new project with Markdoc + +Start a new Starlight project with Markdoc pre-configured using `create astro`: + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight/markdoc +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight/markdoc +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight/markdoc +``` + +</TabItem> +</Tabs> + +### Add Markdoc to an existing project + +If you already have a Starlight site and want to add Markdoc, follow these steps. + +<Steps> + +1. Add Astro’s Markdoc integration: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npx astro add markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm astro add markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn astro add markdoc + ``` + + </TabItem> + + </Tabs> + +2. Install the Starlight Markdoc preset: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-markdoc + ``` + + </TabItem> + + </Tabs> + +3. Create a Markdoc configuration file at `markdoc.config.mjs` and use the Starlight Markdoc preset: + + ```js + import { defineMarkdocConfig } from '@astrojs/markdoc/config'; + import starlightMarkdoc from '@astrojs/starlight-markdoc'; + + export default defineMarkdocConfig({ + extends: [starlightMarkdoc()], + }); + ``` + +</Steps> + +To learn more about the Markdoc syntax and features, see the [Markdoc documentation](https://markdoc.dev/docs/syntax) or the [Astro Markdoc integration guide](https://docs.astro.build/en/guides/integrations-guide/markdoc/). + +### Configuring the Markdoc preset + +The `starlightMarkdoc()` preset accepts the following configuration options: + +#### `headingLinks` + +**type:** `boolean` +**default:** `true` + +Controls whether or not headings are rendered with a clickable anchor link. +Equivalent to the [`markdown.headingLinks`](/reference/configuration/#markdown) option, which applies to Markdown and MDX files. + +```js "headingLinks: false" +export default defineMarkdocConfig({ + // Disable the default heading anchor link support + extends: [starlightMarkdoc({ headingLinks: false })], +}); +``` diff --git a/docs/src/content/docs/guides/components.mdx b/docs/src/content/docs/guides/components.mdx deleted file mode 100644 index ee12879528a..00000000000 --- a/docs/src/content/docs/guides/components.mdx +++ /dev/null @@ -1,189 +0,0 @@ ---- -title: Components -description: Using components in MDX with Starlight. ---- - -Components let you easily reuse a piece of UI or styling consistently. -Examples might include a link card or a YouTube embed. -Starlight supports the use of components in [MDX](https://mdxjs.com/) files and provides some common components for you to use. - -[Learn more about building components in the Astro Docs](https://docs.astro.build/en/core-concepts/astro-components/). - -## Using a component - -You can use a component by importing it into your MDX file and then rendering it as a JSX tag. -These look like HTML tags but start with an uppercase letter matching the name in your `import` statement: - -```mdx ---- -# src/content/docs/index.mdx -title: Welcome to my docs ---- - -import SomeComponent from '../../components/SomeComponent.astro'; -import AnotherComponent from '../../components/AnotherComponent.astro'; - -<SomeComponent prop="something" /> - -<AnotherComponent> - Components can also contain **nested content**. -</AnotherComponent> -``` - -Because Starlight is powered by Astro, you can add support for components built with any [supported UI framework (React, Preact, Svelte, Vue, Solid, Lit, and Alpine)](https://docs.astro.build/en/core-concepts/framework-components/) in your MDX files. -Learn more about [using components in MDX](https://docs.astro.build/en/guides/markdown-content/#using-components-in-mdx) in the Astro docs. - -### Compatibility with Starlight’s styles - -Starlight applies default styling to your Markdown content, for example adding margin between elements. -If these styles conflict with your component’s appearance, set the `not-content` class on your component to disable them. - -```astro ---- -// src/components/Example.astro ---- - -<div class="not-content"> - <p>Not impacted by Starlight’s default content styling.</p> -</div> -``` - -## Built-in components - -Starlight provides some built-in components for common documentation use cases. -These components are available from the `@astrojs/starlight/components` package. - -### Tabs - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -You can display a tabbed interface using the `<Tabs>` and `<TabItem>` components. -Each `<TabItem>` must have a `label` to display to users. - -```mdx -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -<Tabs> - <TabItem label="Stars">Sirius, Vega, Betelgeuse</TabItem> - <TabItem label="Moons">Io, Europa, Ganymede</TabItem> -</Tabs> -``` - -The code above generates the following tabs on the page: - -<Tabs> - <TabItem label="Stars">Sirius, Vega, Betelgeuse</TabItem> - <TabItem label="Moons">Io, Europa, Ganymede</TabItem> -</Tabs> - -### Cards - -import { Card, CardGrid } from '@astrojs/starlight/components'; - -You can display content in a box matching Starlight’s styles using the `<Card>` component. -Wrap multiple cards in the `<CardGrid>` component to display cards side-by-side when there’s enough space. - -A `<Card>` requires a `title` and can optionally include an `icon` attribute set to the name of [one of Starlight’s built-in icons](#all-icons). - -```mdx -import { Card, CardGrid } from '@astrojs/starlight/components'; - -<Card title="Check this out">Interesting content you want to highlight.</Card> - -<CardGrid> - <Card title="Stars" icon="star"> - Sirius, Vega, Betelgeuse - </Card> - <Card title="Moons" icon="moon"> - Io, Europa, Ganymede - </Card> -</CardGrid> -``` - -The code above generates the following on the page: - -<Card title="Check this out">Interesting content you want to highlight.</Card> - -<CardGrid> - <Card title="Stars" icon="star"> - Sirius, Vega, Betelgeuse - </Card> - <Card title="Moons" icon="moon"> - Io, Europa, Ganymede - </Card> -</CardGrid> - -:::tip -Use a card grid on your home page to display your project’s key features. -Add the `stagger` attribute to shift the second column of cards vertically and add visual interest: - -```astro -<CardGrid stagger> - <!-- cards --> -</CardGrid> -``` - -::: - -### Link Cards - -Use the `<LinkCard>` component to link prominently to different pages. - -A `<LinkCard>` requires a `title` and an [`href`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#href) attribute. You can optionally include a short `description` or other link attributes such as `target`. - -Group multiple `<LinkCard>` components in `<CardGrid>` to display cards side-by-side when there’s enough space. - -```mdx -import { LinkCard, CardGrid } from '@astrojs/starlight/components'; - -<LinkCard - title="Customizing Starlight" - description="Learn how to make your Starlight site your own with custom styles, fonts, and more." - href="/guides/customization/" -/> - -<CardGrid> - <LinkCard title="Authoring Markdown" href="/guides/authoring-content/" /> - <LinkCard title="Components" href="/guides/components/" /> -</CardGrid> -``` - -The above code generates the following on the page: - -import { LinkCard } from '@astrojs/starlight/components'; - -<LinkCard - title="Customizing Starlight" - description="Learn how to make your Starlight site your own with custom styles, fonts, and more." - href="/guides/customization/" -/> - -<CardGrid> - <LinkCard title="Authoring Markdown" href="/guides/authoring-content/" /> - <LinkCard title="Components" href="/guides/components/" /> -</CardGrid> - -### Icon - -import { Icon } from '@astrojs/starlight/components'; -import IconsList from '../../../components/icons-list.astro'; - -Starlight provides a set of common icons that you can display in your content using the `<Icon>` component. - -Each `<Icon>` requires a [`name`](#all-icons) and can optionally include a `label`, `size`, and `color` attribute. - -```mdx -import { Icon } from '@astrojs/starlight/components'; - -<Icon name="star" color="goldenrod" size="2rem" /> -``` - -The code above generates the following on the page: - -<Icon name="star" color="goldenrod" size="2rem" /> - -#### All icons - -A list of all available icons is shown below with their associated names. Click an icon to copy the component code for it. - -<IconsList /> diff --git a/docs/src/content/docs/guides/css-and-tailwind.mdx b/docs/src/content/docs/guides/css-and-tailwind.mdx index f159e936d75..cacd22014be 100644 --- a/docs/src/content/docs/guides/css-and-tailwind.mdx +++ b/docs/src/content/docs/guides/css-and-tailwind.mdx @@ -3,12 +3,18 @@ title: CSS & Styling description: Learn how to style your Starlight site with custom CSS or integrate with Tailwind CSS. --- +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + You can style your Starlight site with custom CSS files or use the Starlight Tailwind plugin. +For a quick way to change the default style of your site, check out [community themes](/resources/themes/). + ## Custom CSS styles Customize the styles applied to your Starlight site by providing additional CSS files to modify or extend Starlight’s default styles. +<Steps> + 1. Add a CSS file to your `src/` directory. For example, you could set a wider default column width and larger text size for page titles: @@ -22,7 +28,7 @@ Customize the styles applied to your Starlight site by providing additional CSS 2. Add the path to your CSS file to Starlight’s `customCss` array in `astro.config.mjs`: - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -32,34 +38,50 @@ Customize the styles applied to your Starlight site by providing additional CSS starlight({ title: 'Docs With Custom CSS', customCss: [ - // Relative path to your custom CSS file - './src/styles/custom.css', + + // Relative path to your custom CSS file + + './src/styles/custom.css', ], }), ], }); ``` +</Steps> + You can see all the CSS custom properties used by Starlight that you can set to customize your site in the [`props.css` file on GitHub](https://github.com/withastro/starlight/blob/main/packages/starlight/style/props.css). +### Cascade layers + +Starlight uses [cascade layers](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers) internally to manage the order of its styles. +This ensures a predictable CSS order and allows for simpler overrides. +Any custom unlayered CSS will override the default Starlight styles. + +If you are using cascade layers, you can use [`@layer`](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) in your custom CSS to define the order of precedence for different layers relative to styles from the `starlight` layer: + +```css "starlight" +/* src/styles/custom.css */ +@layer my-reset, starlight, my-overrides; +``` + +The example above defines a custom layer named `my-reset`, applied before all Starlight layers, and another named `my-overrides`, applied after all Starlight layers. +Any styles in the `my-overrides` layer would take precedence over Starlight’s styles, but Starlight could still change styles set in the `my-reset` layer. + ## Tailwind CSS -Tailwind CSS support in Astro projects is provided by the [Astro Tailwind integration](https://docs.astro.build/en/guides/integrations-guide/tailwind/). -Starlight provides a complementary Tailwind plugin to help configure Tailwind for compatibility with Starlight’s styles. +Tailwind CSS v4 support in Astro projects is provided by the [Tailwind Vite plugin](https://tailwindcss.com/docs/installation/using-vite). +Starlight provides complementary CSS to help configure Tailwind for compatibility with Starlight’s styles. -The Starlight Tailwind plugin applies the following configuration: +The Starlight Tailwind CSS applies the following configuration: - Configures Tailwind’s `dark:` variants to work with Starlight’s dark mode. - Uses Tailwind [theme colors and fonts](#styling-starlight-with-tailwind) in Starlight’s UI. -- Disables Tailwind’s [Preflight](https://tailwindcss.com/docs/preflight) reset styles while selectively restoring essential parts of Preflight required for Tailwind’s border utility classes. +- Restores essential parts of Tailwind’s Preflight reset styles. ### Create a new project with Tailwind -import { Tabs, TabItem } from '@astrojs/starlight/components'; - Start a new Starlight project with Tailwind CSS pre-configured using `create astro`: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh @@ -87,9 +109,11 @@ yarn create astro --template starlight/tailwind If you already have a Starlight site and want to add Tailwind CSS, follow these steps. -1. Add Astro’s Tailwind integration: +<Steps> + +1. Set up Tailwind in your project by running the following command and following the instructions in your terminal: - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -117,9 +141,9 @@ If you already have a Starlight site and want to add Tailwind CSS, follow these </Tabs> -2. Install the Starlight Tailwind plugin: +2. Install Starlight’s Tailwind compatibility package: - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -132,7 +156,7 @@ If you already have a Starlight site and want to add Tailwind CSS, follow these <TabItem label="pnpm"> ```sh - pnpm install @astrojs/starlight-tailwind + pnpm add @astrojs/starlight-tailwind ``` </TabItem> @@ -147,22 +171,27 @@ If you already have a Starlight site and want to add Tailwind CSS, follow these </Tabs> -3. Create a CSS file for Tailwind’s base styles, for example at `src/tailwind.css`: +3. Replace the contents of the `src/styles/global.css` file scaffolded by Astro for compatibility with Starlight: ```css - /* src/tailwind.css */ - @tailwind base; - @tailwind components; - @tailwind utilities; + /* src/styles/global.css */ + @layer base, starlight, theme, components, utilities; + + @import '@astrojs/starlight-tailwind'; + @import 'tailwindcss/theme.css' layer(theme); + @import 'tailwindcss/utilities.css' layer(utilities); ``` -4. Update your Astro config file to use your Tailwind base styles and disable the default base styles: + This Tailwind theme config defines Starlight's [cascade layers](#cascade-layers) order, imports Starlight’s Tailwind complementary CSS, and imports Tailwind’s theme and utility styles. + If your project requires additional Tailwind configuration, check out the [“Use multiple Tailwind configurations”](#use-multiple-tailwind-configurations) section. + +4. Update the Starlight config to add the Tailwind CSS file as the first item in the `customCss` array: - ```js {11-12,16-17} + ```js ins={11-12} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; - import tailwind from '@astrojs/tailwind'; + import tailwindcss from '@tailwindcss/vite'; export default defineConfig({ integrations: [ @@ -170,69 +199,95 @@ If you already have a Starlight site and want to add Tailwind CSS, follow these title: 'Docs with Tailwind', customCss: [ // Path to your Tailwind base styles: - './src/tailwind.css', + './src/styles/global.css', ], }), - tailwind({ - // Disable the default base styles: - applyBaseStyles: false, - }), ], + vite: { plugins: [tailwindcss()] }, }); ``` -5. Add the Starlight Tailwind plugin to `tailwind.config.cjs`: +</Steps> - ```js ins={2,7} - // tailwind.config.cjs - const starlightPlugin = require('@astrojs/starlight-tailwind'); +### Styling Starlight with Tailwind - /** @type {import('tailwindcss').Config} */ - module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - plugins: [starlightPlugin()], - }; - ``` +When [creating a new Starlight project with Tailwind](#create-a-new-project-with-tailwind), or when [adding Tailwind to an existing Starlight project](#add-tailwind-to-an-existing-project), Starlight will use values from your [Tailwind theme config](https://tailwindcss.com/docs/theme) located in the `src/styles/global.css` file to style its UI. + +If set, the following CSS custom properties will override Starlight’s default styles: + +- `--color-accent-*` — used for links and current item highlighting +- `--color-gray-*` — used for background colors and borders +- `--font-sans` — used for UI and content text +- `--font-mono` — used for code examples + +```css {9,11,13,25} +/* src/styles/global.css */ +@layer base, starlight, theme, components, utilities; + +@import '@astrojs/starlight-tailwind'; +@import 'tailwindcss/theme.css' layer(theme); +@import 'tailwindcss/utilities.css' layer(utilities); + +@theme { + /* Your preferred text font. Starlight uses a system font stack by default. */ + --font-sans: 'Atkinson Hyperlegible'; + /* Your preferred code font. Starlight uses system monospace fonts by default. */ + --font-mono: 'IBM Plex Mono'; + /* Your preferred accent color. Indigo is closest to Starlight’s defaults. */ + --color-accent-50: var(--color-indigo-50); + --color-accent-100: var(--color-indigo-100); + --color-accent-200: var(--color-indigo-200); + --color-accent-300: var(--color-indigo-300); + --color-accent-400: var(--color-indigo-400); + --color-accent-500: var(--color-indigo-500); + --color-accent-600: var(--color-indigo-600); + --color-accent-700: var(--color-indigo-700); + --color-accent-800: var(--color-indigo-800); + --color-accent-900: var(--color-indigo-900); + --color-accent-950: var(--color-indigo-950); + /* Your preferred gray scale. Zinc is closest to Starlight’s defaults. */ + --color-gray-50: var(--color-zinc-50); + --color-gray-100: var(--color-zinc-100); + --color-gray-200: var(--color-zinc-200); + --color-gray-300: var(--color-zinc-300); + --color-gray-400: var(--color-zinc-400); + --color-gray-500: var(--color-zinc-500); + --color-gray-600: var(--color-zinc-600); + --color-gray-700: var(--color-zinc-700); + --color-gray-800: var(--color-zinc-800); + --color-gray-900: var(--color-zinc-900); + --color-gray-950: var(--color-zinc-950); +} +``` -### Styling Starlight with Tailwind +### Use multiple Tailwind configurations -Starlight will use values from your [Tailwind theme config](https://tailwindcss.com/docs/theme) in its UI. - -If set, the following options will override Starlight’s default styles: - -- `colors.accent` — used for links and current item highlighting -- `colors.gray` — used for background colors and borders -- `fontFamily.sans` — used for UI and content text -- `fontFamily.mono` — used for code examples - -```js {12,14,18,20} -// tailwind.config.cjs -const starlightPlugin = require('@astrojs/starlight-tailwind'); -const colors = require('tailwindcss/colors'); - -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: { - colors: { - // Your preferred accent color. Indigo is closest to Starlight’s defaults. - accent: colors.indigo, - // Your preferred gray scale. Zinc is closest to Starlight’s defaults. - gray: colors.zinc, - }, - fontFamily: { - // Your preferred text font. Starlight uses a system font stack by default. - sans: ['"Atkinson Hyperlegible"'], - // Your preferred code font. Starlight uses system monospace fonts by default. - mono: ['"IBM Plex Mono"'], - }, - }, - }, - plugins: [starlightPlugin()], -}; +Multiple Tailwind configurations can be used to apply different styles to different parts of your site, e.g. when [using Starlight at a subpath](/manual-setup/#use-starlight-at-a-subpath) or when adding [custom pages](/guides/pages/#custom-pages) to your site. +For example, you may want to use Tailwind’s Preflight reset styles in your custom pages, while still applying Starlight’s compatibility layer to Starlight pages. + +The following Tailwind CSS configuration sets up Tailwind without any plugins or extra configuration and can be used as a starting point for non-Starlight pages: + +```css title="src/styles/custom-pages-tailwind.css" +/* Load Tailwind without any of Starlight's complementary CSS. */ +@import 'tailwindcss'; ``` +<Steps> + +1. For Starlight pages, apply your preferred Tailwind CSS configuration by following [“Add Tailwind to an existing project”](#add-tailwind-to-an-existing-project). + +2. For other pages, apply your preferred Tailwind CSS configuration by importing it in those pages. This is often done in a layout component so that Tailwind styles can be used on all pages sharing that layout. + ```astro + --- + // src/layouts/CustomPageLayout.astro + import '../styles/custom-pages-tailwind.css'; + --- + ``` + +</Steps> + +To learn more about Tailwind theme configurations, check out the [Tailwind CSS documentation](https://tailwindcss.com/docs/theme). + ## Theming Starlight’s color theme can be controlled by overriding its default custom properties. @@ -243,9 +298,11 @@ These variables are used throughout the UI with a range of gray shades used for Use the sliders below to modify Starlight’s accent and gray color palettes. The dark and light preview areas will show the resulting colors, and the whole page will also update to preview your changes. +Use the Contrast Level option to specify which of the Web Content Accessibility Guideline [colour contrast standards](https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast) to meet. + When you’re happy with your changes, copy the CSS or Tailwind code below and use it in your project. -import ThemeDesigner from '../../../components/theme-designer.astro'; +import ThemeDesigner from '~/components/theme-designer.astro'; <ThemeDesigner labels={{ @@ -258,6 +315,9 @@ import ThemeDesigner from '../../../components/theme-designer.astro'; default: 'Default', random: 'Random', }, + contrast: { + label: 'Contrast Level', + }, editor: { accentColor: 'Accent', grayColor: 'Gray', @@ -281,8 +341,7 @@ import ThemeDesigner from '../../../components/theme-designer.astro'; file](#custom-css-styles) to apply this theme to your site. </Fragment> <Fragment slot="tailwind-docs"> - The example [Tailwind config file](#styling-starlight-with-tailwind) below - includes generated `accent` and `gray` color palettes to use in the - `theme.extend.colors` configuration object. + Add the following CSS variables to the `@theme` block in your [Tailwind CSS + file](#styling-starlight-with-tailwind) to apply this theme to your site. </Fragment> </ThemeDesigner> diff --git a/docs/src/content/docs/guides/customization.mdx b/docs/src/content/docs/guides/customization.mdx index e605372cdb7..c53fa0ba982 100644 --- a/docs/src/content/docs/guides/customization.mdx +++ b/docs/src/content/docs/guides/customization.mdx @@ -3,8 +3,7 @@ title: Customizing Starlight description: Learn how to make your Starlight site your own with your logo, custom fonts, landing page design and more. --- -import { Tabs, TabItem } from '@astrojs/starlight/components'; -import FileTree from '../../../components/file-tree.astro'; +import { Tabs, TabItem, FileTree, Steps } from '@astrojs/starlight/components'; Starlight provides sensible default styling and features, so you can get started quickly with no configuration needed. When you want to start customizing the look and feel of your Starlight site, this guide has you covered. @@ -13,6 +12,8 @@ When you want to start customizing the look and feel of your Starlight site, thi Adding a custom logo to the site header is a quick way to add your individual branding to a Starlight site. +<Steps> + 1. Add your logo image file to the `src/assets/` directory: <FileTree> @@ -27,7 +28,7 @@ Adding a custom logo to the site header is a quick way to add your individual br 2. Add the path to your logo as Starlight’s [`logo.src`](/reference/configuration/#logo) option in `astro.config.mjs`: - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -37,18 +38,20 @@ Adding a custom logo to the site header is a quick way to add your individual br starlight({ title: 'Docs With My Logo', logo: { - src: './src/assets/my-logo.svg', + + src: './src/assets/my-logo.svg', }, }), ], }); ``` +</Steps> + By default, the logo will be displayed alongside your site’s `title`. If your logo image already includes the site title, you can visually hide the title text by setting the `replacesTitle` option. The `title` text will still be included for screen readers so that the header remains accessible. -```js +```js {5} starlight({ title: 'Docs With My Logo', logo: { @@ -62,6 +65,8 @@ starlight({ You can display different versions of your logo in light and dark modes. +<Steps> + 1. Add an image file for each variant to `src/assets/`: <FileTree> @@ -77,21 +82,23 @@ You can display different versions of your logo in light and dark modes. 2. Add the path to your logo variants as the `light` and `dark` options instead of `src` in `astro.config.mjs`: - ```js + ```diff lang="js" starlight({ title: 'Docs With My Logo', logo: { - light: './src/assets/light-logo.svg', - dark: './src/assets/dark-logo.svg', + + light: './src/assets/light-logo.svg', + + dark: './src/assets/dark-logo.svg', }, }), ``` +</Steps> + ## Enable sitemap Starlight has built-in support for generating a sitemap. Enable sitemap generation by setting your URL as `site` in `astro.config.mjs`: -```js +```js {4} // astro.config.mjs export default defineConfig({ @@ -100,6 +107,8 @@ export default defineConfig({ }); ``` +Learn how to [add a sitemap link to `robots.txt`](https://docs.astro.build/en/guides/integrations-guide/sitemap/#sitemap-link-in-robotstxt) in the Astro Docs. + ## Page layout By default, Starlight pages use a layout with a global navigation sidebar and a table of contents that shows the current page headings. @@ -107,7 +116,7 @@ By default, Starlight pages use a layout with a global navigation sidebar and a You can apply a wider page layout without sidebars by setting [`template: splash`](/reference/frontmatter/#template) in a page’s frontmatter. This works particularly well for landing pages and you can see it in action on the [homepage of this site](/). -```md +```md {5} --- # src/content/docs/index.md @@ -123,10 +132,10 @@ You can customize — or even disable — the table of contents globally in the By default, `<h2>` and `<h3>` headings are included in the table of contents. Change which headings levels to include site-wide using the `minHeadingLevel` and `maxHeadingLevel` options in your [global `tableOfContents`](/reference/configuration/#tableofcontents). Override these defaults on an individual page by adding the corresponding [frontmatter `tableOfContents`](/reference/frontmatter/#tableofcontents) properties: -<Tabs> +<Tabs syncKey="config-type"> <TabItem label="Frontmatter"> -```md +```md {4-6} --- # src/content/docs/example.md title: Page with only H2s in the table of contents @@ -139,13 +148,13 @@ tableOfContents: </TabItem> <TabItem label="Global config"> -```js +```js {7} // astro.config.mjs defineConfig({ integrations: [ starlight({ - title: '', + title: 'Docs with custom table of contents config', tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 2 }, }), ], @@ -157,10 +166,10 @@ defineConfig({ Disable the table of contents entirely by setting the `tableOfContents` option to `false`: -<Tabs> +<Tabs syncKey="config-type"> <TabItem label="Frontmatter"> -```md +```md {4} --- # src/content/docs/example.md title: Page without a table of contents @@ -171,7 +180,7 @@ tableOfContents: false </TabItem> <TabItem label="Global config"> -```js +```js {7} // astro.config.mjs defineConfig({ @@ -191,10 +200,15 @@ defineConfig({ Starlight has built-in support for adding links to your social media accounts to the site header via the [`social`](/reference/configuration/#social) option in the Starlight integration. -Currently, links to Bitbucket, Codeberg, CodePen, Discord, GitHub, GitLab, Gitter, Instagram, LinkedIn, Mastodon, Microsoft Teams, Stack Overflow, Threads, Twitch, Twitter, and Youtube are supported. -Let us know on GitHub or Discord if you need support for another service! +Each entry in the `social` array must be an object with three properties: + +- `icon`: one of Starlight’s [built-in icons](/reference/icons/), e.g. `"github"`. +- `label`: an accessible label for the link, e.g. `"GitHub"`. +- `href`: the URL for the link, e.g. `"https://github.com/withastro/starlight"`. + +The following example adds links to the Astro Discord chat and the Starlight GitHub repository: -```js +```js {9-16} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -203,10 +217,14 @@ export default defineConfig({ integrations: [ starlight({ title: 'Docs With Social Links', - social: { - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - }, + social: [ + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { + icon: 'github', + label: 'GitHub', + href: 'https://github.com/withastro/starlight', + }, + ], }), ], }); @@ -230,7 +248,7 @@ If your Starlight project is not in the root of your repository, include the pat This example shows the edit link configured for the Starlight docs, which live in the `docs/` subdirectory on the `main` branch of the `withastro/starlight` repository on GitHub: -```js +```js {9-11} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -265,8 +283,9 @@ You can customize this by adding a `404.md` (or `404.mdx`) file to your `src/con You can use all of Starlight’s page layout and customization techniques in your 404 page. For example, the default 404 page uses the [`splash` template](#page-layout) and [`hero`](/reference/frontmatter/#hero) component in frontmatter: -```md +```md {4,6-8} --- +# src/content/docs/404.md title: '404' template: splash editUrl: false @@ -276,6 +295,25 @@ hero: --- ``` +### Disabling the default 404 page + +If your project requires an entirely customized 404 layout, you can create a `src/pages/404.astro` route and set the [`disable404Route`](/reference/configuration/#disable404route) config option to disable Starlight’s default route: + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Docs With Custom 404', + disable404Route: true, + }), + ], +}); +``` + ## Custom fonts By default, Starlight uses sans-serif fonts available on a user’s local device for all text. @@ -290,6 +328,8 @@ To use Google Fonts, follow the [Fontsource set-up guide](#set-up-a-fontsource-f #### Set up local font files +<Steps> + 1. Add your font files to a `src/fonts/` directory and create an empty `font-face.css` file: <FileTree> @@ -321,7 +361,7 @@ To use Google Fonts, follow the [Fontsource set-up guide](#set-up-a-fontsource-f 3. Add the path to your `font-face.css` file to Starlight’s `customCss` array in `astro.config.mjs`: - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -331,26 +371,30 @@ To use Google Fonts, follow the [Fontsource set-up guide](#set-up-a-fontsource-f starlight({ title: 'Docs With a Custom Typeface', customCss: [ - // Relative path to your @font-face CSS file. - './src/fonts/font-face.css', + + // Relative path to your @font-face CSS file. + + './src/fonts/font-face.css', ], }), ], }); ``` +</Steps> + #### Set up a Fontsource font The [Fontsource](https://fontsource.org/) project simplifies using Google Fonts and other open-source fonts. It provides npm modules you can install for the fonts you want to use and includes ready-made CSS files to add to your project. +<Steps> + 1. Find the font you want to use in [Fontsource’s catalog](https://fontsource.org/). This example will use [IBM Plex Serif](https://fontsource.org/fonts/ibm-plex-serif). 2. Install the package for your chosen font. You can find the package name by clicking “Install” on the Fontsource font page. - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -363,7 +407,7 @@ It provides npm modules you can install for the fonts you want to use and includ <TabItem label="pnpm"> ```sh - pnpm install @fontsource/ibm-plex-serif + pnpm add @fontsource/ibm-plex-serif ``` </TabItem> @@ -380,7 +424,7 @@ It provides npm modules you can install for the fonts you want to use and includ 3. Add Fontsource CSS files to Starlight’s `customCss` array in `astro.config.mjs`: - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -390,9 +434,9 @@ It provides npm modules you can install for the fonts you want to use and includ starlight({ title: 'Docs With a Custom Typeface', customCss: [ - // Fontsource files for to regular and semi-bold font weights. - '@fontsource/ibm-plex-serif/400.css', - '@fontsource/ibm-plex-serif/600.css', + + // Fontsource files for to regular and semi-bold font weights. + + '@fontsource/ibm-plex-serif/400.css', + + '@fontsource/ibm-plex-serif/600.css', ], }), ], @@ -401,6 +445,8 @@ It provides npm modules you can install for the fonts you want to use and includ Fontsource ships multiple CSS files for each font. See the [Fontsource documentation](https://fontsource.org/docs/getting-started/install#4-weights-and-styles) on including different weights and styles to understand which to use. +</Steps> + ### Use fonts To apply the font you set up to your site, use your chosen font’s name in a [custom CSS file](/guides/css-and-tailwind/#custom-css-styles). diff --git a/docs/src/content/docs/guides/i18n.mdx b/docs/src/content/docs/guides/i18n.mdx index ec8086b060b..e305de8a336 100644 --- a/docs/src/content/docs/guides/i18n.mdx +++ b/docs/src/content/docs/guides/i18n.mdx @@ -3,15 +3,17 @@ title: Internationalization (i18n) description: Learn how to configure your Starlight site to support multiple languages. --- -import FileTree from '../../../components/file-tree.astro'; +import { FileTree, Steps } from '@astrojs/starlight/components'; Starlight provides built-in support for multilingual sites, including routing, fallback content, and full right-to-left (RTL) language support. ## Configure i18n +<Steps> + 1. Tell Starlight about the languages you support by passing [`locales`](/reference/configuration/#locales) and [`defaultLocale`](/reference/configuration/#defaultlocale) to the Starlight integration: - ```js + ```js {9-26} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -27,8 +29,8 @@ Starlight provides built-in support for multilingual sites, including routing, f en: { label: 'English', }, - // Simplified Chinese docs in `src/content/docs/zh/` - zh: { + // Simplified Chinese docs in `src/content/docs/zh-cn/` + 'zh-cn': { label: '简体中文', lang: 'zh-CN', }, @@ -55,7 +57,7 @@ Starlight provides built-in support for multilingual sites, including routing, f - docs/ - ar/ - en/ - - zh/ + - zh-cn/ </FileTree> @@ -63,13 +65,17 @@ Starlight provides built-in support for multilingual sites, including routing, f For example, create `ar/index.md` and `en/index.md` to represent the homepage for Arabic and English respectively. +</Steps> + +For more advanced i18n scenarios, Starlight also supports configuring internationalization using the [Astro’s `i18n` config](https://docs.astro.build/en/guides/internationalization/#configure-i18n-routing) option. + ### Use a root locale You can use a “root” locale to serve a language without any i18n prefix in its path. For example, if English is your root locale, an English page path would look like `/about` instead of `/en/about`. To set a root locale, use the `root` key in your `locales` config. If the root locale is also the default locale for your content, remove `defaultLocale` or set it to `'root'`. -```js +```js {9,11-14} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -84,7 +90,7 @@ export default defineConfig({ label: 'English', lang: 'en', // lang is required for root locales }, - zh: { + 'zh-cn': { label: '简体中文', lang: 'zh-CN', }, @@ -102,7 +108,7 @@ When using a `root` locale, keep pages for that language directly in `src/conten - content/ - docs/ - **index.md** - - zh/ + - zh-cn/ - **index.md** </FileTree> @@ -111,7 +117,7 @@ When using a `root` locale, keep pages for that language directly in `src/conten By default, Starlight is a monolingual (English) site. To create a single language site in another language, set it as the `root` in your `locales` config: -```js +```diff lang="js" {10-13} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -139,24 +145,60 @@ Starlight expects you to create equivalent pages in all your languages. For exam If a translation is not yet available for a language, Starlight will show readers the content for that page in the default language (set via `defaultLocale`). For example, if you have not yet created a French version of your About page and your default language is English, visitors to `/fr/about` will see the English content from `/en/about` with a notice that this page has not yet been translated. This helps you add content in your default language and then progressively translate it when your translators have time. +## Translate the site title + +By default, Starlight will use the same site title for all languages. +If you need to customize the title for each locale, you can pass an object to [`title`](/reference/configuration/#title-required) in Starlight’s options: + +```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' }, + }, + }), + ], +}); +``` + ## Translate Starlight's UI +import LanguagesList from '~/components/languages-list.astro'; +import UIStringsList from '~/components/ui-strings-list.astro'; + In addition to hosting translated content files, Starlight allows you to translate the default UI strings (e.g. the "On this page" heading in the table of contents) so that your readers can experience your site entirely in the selected language. -English, Czech, French, German, Italian, Japanese, Portuguese, Dutch, Danish, Spanish, Turkish, Arabic, Norwegian, Farsi, Hebrew, Simplified Chinese, Korean, Indonesian, Russian, and Swedish translated UI strings are provided out of the box, and we welcome [contributions to add more default languages](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md). +<LanguagesList startsSentence /> translated UI strings are provided out of the +box, and we welcome [contributions to add more default +languages](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md). You can provide translations for additional languages you support — or override our default labels — via the `i18n` data collection. -1. Configure the `i18n` data collection in `src/content/config.ts` if it isn’t configured already: +<Steps> + +1. Configure the `i18n` data collection in `src/content.config.ts` if it isn’t configured already: - ```js - // src/content/config.ts + ```diff lang="js" ins=/, (i18nLoader|i18nSchema)/ + // src/content.config.ts import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; export const collections = { - docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), }; ``` @@ -177,27 +219,16 @@ You can provide translations for additional languages you support — or overrid These are the English defaults of the existing strings Starlight ships with: + <UIStringsList /> + + Starlight’s code blocks are powered by the [Expressive Code](https://expressive-code.com/) library. + You can set translations for its UI strings in the same JSON file using `expressiveCode` keys: + ```json { - "skipLink.label": "Skip to content", - "search.label": "Search", - "search.shortcutLabel": "(Press / to Search)", - "search.cancelLabel": "Cancel", - "search.devWarning": "Search is only available in production builds. \nTry building and previewing the site to test it out locally.", - "themeSelect.accessibleLabel": "Select theme", - "themeSelect.dark": "Dark", - "themeSelect.light": "Light", - "themeSelect.auto": "Auto", - "languageSelect.accessibleLabel": "Select language", - "menuButton.accessibleLabel": "Menu", - "sidebarNav.accessibleLabel": "Main", - "tableOfContents.onThisPage": "On this page", - "tableOfContents.overview": "Overview", - "i18n.untranslatedContent": "This content is not available in your language yet.", - "page.editLink": "Edit page", - "page.lastUpdated": "Last updated:", - "page.previousLink": "Next", - "page.nextLink": "Previous" + "expressiveCode.copyButtonCopied": "Copied!", + "expressiveCode.copyButtonTooltip": "Copy to clipboard", + "expressiveCode.terminalWindowFallbackTitle": "Terminal window" } ``` @@ -218,3 +249,161 @@ You can provide translations for additional languages you support — or overrid "pagefind.searching": "Searching for [SEARCH_TERM]..." } ``` + + </Steps> + +### Extend translation schema + +Add custom keys to your site’s translation dictionaries by setting `extend` in the `i18nSchema()` options. +In the following example, a new, optional `custom.label` key is added to the default keys: + +```diff lang="js" +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ ++ extend: z.object({ ++ 'custom.label': z.string().optional(), ++ }), + }), + }), +}; +``` + +Learn more about content collection schemas in [“Defining a collection schema”](https://docs.astro.build/en/guides/content-collections/#defining-the-collection-schema) in the Astro docs. + +## Using UI translations + +You can access Starlight’s [built-in UI strings](/guides/i18n/#translate-starlights-ui) as well as [user-defined](/guides/i18n/#extend-translation-schema), and [plugin-provided](/reference/plugins/#injecttranslations) UI strings through a unified API powered by [i18next](https://www.i18next.com/). +This includes support for features like [interpolation](https://www.i18next.com/translation-function/interpolation) and [pluralization](https://www.i18next.com/translation-function/plurals). + +In Astro components, this API is available as part of the [global `Astro` object](https://docs.astro.build/en/reference/api-reference/#locals) as `Astro.locals.t`: + +```astro title="example.astro" +<p dir={Astro.locals.t.dir()}> + {Astro.locals.t('404.text')} +</p> +``` + +You can also use the API in [endpoints](https://docs.astro.build/en/guides/endpoints/), where the `locals` object is available as part of the [endpoint context](https://docs.astro.build/en/reference/api-reference/#locals): + +```ts title="src/pages/404.ts" +export const GET = (context) => { + return new Response(context.locals.t('404.text')); +}; +``` + +In the context of a Starlight plugin, you can use the [`useTranslations()`](/reference/plugins/#usetranslations) helper to access this API for a specific language. +See the [plugins reference](/reference/plugins/) for more information. + +### Rendering a UI string + +Render UI strings using the `locals.t()` function. +This is an instance of i18next’s `t()` function, which takes a UI string key as its first argument and returns the corresponding translation for the current language. + +For example, given a custom translation file with the following content: + +```json title="src/content/i18n/en.json" +{ + "link.astro": "Astro documentation", + "link.astro.custom": "Astro documentation for {{feature}}" +} +``` + +The first UI string can be rendered by passing `'link.astro'` to the `t()` function: + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/"> + {Astro.locals.t('link.astro')} +</a> +<!-- Renders: <a href="...">Astro documentation</a> --> +``` + +The second UI string uses i18next’s [interpolation syntax](https://www.i18next.com/translation-function/interpolation) for the `{{feature}}` placeholder. +The value for `feature` must be set in an options object passed as the second argument to `t()`: + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/en/guides/astro-db/"> + {Astro.locals.t('link.astro.custom', { feature: 'Astro DB' })} +</a> +<!-- Renders: <a href="...">Astro documentation for Astro DB</a> --> +``` + +See the [i18next documentation](https://www.i18next.com/overview/api#t) for more information on how to use the `t()` function with interpolation, formatting, and more. + +### Advanced APIs + +#### `t.all()` + +The `locals.t.all()` function returns an object containing all UI strings available for the current locale. + +```astro +--- +// src/components/Example.astro +const allStrings = Astro.locals.t.all(); +// ^ +// { +// "skipLink.label": "Skip to content", +// "search.label": "Search", +// … +// } +--- +``` + +#### `t.exists()` + +To check if a translation key exists, use the `locals.t.exists()` function with the translation key as first argument. +Pass an optional second argument if you need to check if a translation exists for a specific locale. + +```astro +--- +// src/components/Example.astro +const keyExists = Astro.locals.t.exists('a.key'); +// ^ true +const keyExistsInFrench = Astro.locals.t.exists('other.key', { lngs: ['fr'] }); +// ^ false +--- +``` + +See the [`exists()` reference in the i18next documentation](https://www.i18next.com/overview/api#exists) for more information. + +#### `t.dir()` + +The `locals.t.dir()` function returns the text direction of the current or a specific locale. + +```astro +--- +// src/components/Example.astro +const currentDirection = Astro.locals.t.dir(); +// ^ +// 'ltr' +const arabicDirection = Astro.locals.t.dir('ar'); +// ^ +// 'rtl' +--- +``` + +See the [`dir()` reference in the i18next documentation](https://www.i18next.com/overview/api#dir) for more information. + +## Accessing the current locale + +You can use [`Astro.currentLocale`](https://docs.astro.build/en/reference/api-reference/#currentlocale) to read the current locale in `.astro` components. + +The following example reads the current locale and uses it with the [`getRelativeLocaleUrl()`](https://docs.astro.build/en/reference/modules/astro-i18n/#getrelativelocaleurl) helper to generate a link to an about page in the current language: + +```astro +--- +// src/components/AboutLink.astro +import { getRelativeLocaleUrl } from 'astro:i18n'; +--- + +<a href={getRelativeLocaleUrl(Astro.currentLocale ?? 'en', 'about')}>About</a> +``` diff --git a/docs/src/content/docs/guides/overriding-components.mdx b/docs/src/content/docs/guides/overriding-components.mdx new file mode 100644 index 00000000000..c2fbfec0105 --- /dev/null +++ b/docs/src/content/docs/guides/overriding-components.mdx @@ -0,0 +1,152 @@ +--- +title: Overriding Components +description: Learn how to override Starlight’s built-in components to add custom elements to your documentation site’s UI. +--- + +import { Steps } from '@astrojs/starlight/components'; + +Starlight’s default UI and configuration options are designed to be flexible and work for a range of content. Much of Starlight's default appearance can be customized with [CSS](/guides/css-and-tailwind/) and [configuration options](/guides/customization/). + +When you need more than what’s possible out of the box, Starlight supports building your own custom components to extend or override (completely replace) its default components. + +## When to override + +Overriding Starlight’s default components can be useful when: + +- You want to change how a part of Starlight’s UI looks in a way not possible with [custom CSS](/guides/css-and-tailwind/). +- You want to change how a part of Starlight’s UI behaves. +- You want to add some additional UI alongside Starlight’s existing UI. + +## How to override + +<Steps> + +1. Choose the Starlight component you want to override. + You can find a full list of components in the [Overrides Reference](/reference/overrides/). + + :::tip + Not sure which component you need to override? Use the [interactive Starlight Overrides Map](https://starlight-overrides-map.netlify.app/) to discover the names of Starlight's UI components. + ::: + + This example will override Starlight’s [`SocialIcons`](/reference/overrides/#socialicons) component in the page nav bar. + +2. Create an Astro component to replace the Starlight component with. + This example renders a contact link. + + ```astro + --- + // src/components/EmailLink.astro + + const email = 'houston@example.com'; + --- + + <a href=`mailto:${email}`>E-mail Me</a> + ``` + +3. Tell Starlight to use your custom component in the [`components`](/reference/configuration/#components) configuration option in `astro.config.mjs`: + + ```js {9-12} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'My Docs with Overrides', + components: { + // Override the default `SocialIcons` component. + SocialIcons: './src/components/EmailLink.astro', + }, + }), + ], + }); + ``` + +</Steps> + +## Reuse a built-in component + +You can build with Starlight’s default UI components just as you would with your own: importing and rendering them in your own custom components. This allows you to keep all of Starlight's basic UI within your design, while adding extra UI alongside them. + +The example below shows a custom component that renders an e-mail link along with the default `SocialIcons` component: + +```astro {3,7} +--- +// src/components/EmailLink.astro +import Default from '@astrojs/starlight/components/SocialIcons.astro'; +--- + +<a href="mailto:houston@example.com">E-mail Me</a> +<Default><slot /></Default> +``` + +When rendering a built-in component inside a custom component add a [`<slot />`](https://docs.astro.build/en/basics/astro-components/#slots) inside the default component. This makes sure that if the component is passed any child elements, Astro knows where to render them. + +If you are reusing the [`PageFrame`](/reference/overrides/#pageframe) or [`TwoColumnContent`](/reference/overrides/#twocolumncontent) components which contain [named slots](https://docs.astro.build/en/basics/astro-components/#named-slots), you also need to [transfer](https://docs.astro.build/en/basics/astro-components/#transferring-slots) these slots as well. + +The example below shows a custom component that reuses the `TwoColumnContent` component which contains an additional `right-sidebar` named slot that needs to be transferred: + +```astro {8} +--- +// src/components/CustomContent.astro +import Default from '@astrojs/starlight/components/TwoColumnContent.astro'; +--- + +<Default> + <slot /> + <slot name="right-sidebar" slot="right-sidebar" /> +</Default> +``` + +## Use page data + +When overriding a Starlight component, you can access the global [`starlightRoute` object](/guides/route-data/) containing all the data for the current page. +This allows you to use these values to control how your component template renders. + +In the following example, a replacement [`PageTitle`](/reference/overrides/#pagetitle) component displays the current page’s title as set in the content’s frontmatter: + +```astro {4} "{title}" +--- +// src/components/Title.astro + +const { title } = Astro.locals.starlightRoute.entry.data; +--- + +<h1 id="_top">{title}</h1> + +<style> + h1 { + font-family: 'Comic Sans'; + } +</style> +``` + +Learn more about all the available properties in the [Route Data Reference](/reference/route-data/). + +### Only override on specific pages + +Component overrides apply to all pages. However, you can conditionally render using values from `starlightRoute` to determine when to show your custom UI, when to show Starlight’s default UI, or even when to show something entirely different. + +In the following example, a component overriding Starlight's [`Footer`](/reference/overrides/#footer-1) displays "Built with Starlight 🌟" on the homepage only, and otherwise shows the default footer on all other pages: + +```astro +--- +// src/components/ConditionalFooter.astro +import Default from '@astrojs/starlight/components/Footer.astro'; + +const isHomepage = Astro.locals.starlightRoute.id === ''; +--- + +{ + isHomepage ? ( + <footer>Built with Starlight 🌟</footer> + ) : ( + <Default> + <slot /> + </Default> + ) +} +``` + +Learn more about conditional rendering in [Astro’s Template Syntax guide](https://docs.astro.build/en/basics/astro-syntax/#dynamic-html). diff --git a/docs/src/content/docs/guides/pages.mdx b/docs/src/content/docs/guides/pages.mdx new file mode 100644 index 00000000000..5d9f8ff95ff --- /dev/null +++ b/docs/src/content/docs/guides/pages.mdx @@ -0,0 +1,228 @@ +--- +title: Pages +description: Learn how to create and manage your documentation site’s pages with Starlight. +sidebar: + order: 1 +tableOfContents: + maxHeadingLevel: 4 +--- + +Starlight generates your site’s HTML pages based on your content, with flexible options provided via Markdown frontmatter. +In addition, Starlight projects have full access to [Astro’s powerful page generation tools](https://docs.astro.build/en/basics/astro-pages/). +This guide shows how page generation works in Starlight. + +## Content pages + +### File formats + +Starlight supports authoring content in Markdown and MDX with no configuration required. +You can add support for Markdoc by following the [“Markdoc” guide](/guides/authoring-content/#markdoc). + +### Add pages + +Add new pages to your site by creating `.md` or `.mdx` files in `src/content/docs/`. +Use sub-folders to organize your files and to create multiple path segments. + +For example, the following file structure will generate pages at `example.com/hello-world` and `example.com/reference/faq`: + +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - reference/ + - faq.md + +</FileTree> + +### Type-safe frontmatter + +All Starlight pages share a customizable [common set of frontmatter properties](/reference/frontmatter/) to control how the page appears: + +```md +--- +title: Hello, World! +description: This is a page in my Starlight-powered site +--- +``` + +If you forget anything important, Starlight will let you know. + +## Custom pages + +For advanced use cases, you can add custom pages by creating a `src/pages/` directory. +The `src/pages/` directory uses [Astro's file-based routing](https://docs.astro.build/en/basics/astro-pages/#file-based-routing) and includes support for `.astro` files amongst other page formats. +This is helpful if you need to build pages with a completely custom layout or generate a page from an alternative data source. + +For example, this project mixes Markdown content in `src/content/docs/` with Astro and HTML routes in `src/pages/`: + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - pages/ + - custom.astro + - archived.html + +</FileTree> + +Read more in the [“Pages” guide in the Astro docs](https://docs.astro.build/en/basics/astro-pages/). + +### Using Starlight’s design in custom pages + +To use the Starlight layout in custom pages, wrap your page content with the [`<StarlightPage>` component](#starlightpage-component). +This can be helpful if you are generating content dynamically but still want to use Starlight’s design. + +To add anchor links to headings that match Starlight’s Markdown anchor link styles, you can use the [`<AnchorHeading>` component](#anchorheading-component) in your custom pages. + +```astro +--- +// src/pages/custom-page/example.astro +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +import CustomComponent from './CustomComponent.astro'; +--- + +<StarlightPage frontmatter={{ title: 'My custom page' }}> + <p>This is a custom page with a custom component:</p> + <CustomComponent /> + + <AnchorHeading level="2" id="learn-more">Learn more</AnchorHeading> + <p> + <a href="https://starlight.astro.build/">Read more in the Starlight docs</a> + </p> +</StarlightPage> +``` + +#### `<StarlightPage>` component + +The `<StarlightPage />` component renders a full page of content using Starlight’s layout and styles. + +```astro +--- +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +--- + +<StarlightPage frontmatter={{ title: 'My custom page' }}> + <!-- Custom page content --> +</StarlightPage> +``` + +The `<StarlightPage />` component accepts the following props. + +##### `frontmatter` + +**required** +**type:** `StarlightPageFrontmatter` + +Set the [frontmatter properties](/reference/frontmatter/) for this page, similar to frontmatter in Markdown pages. +The [`title`](/reference/frontmatter/#title-required) property is required and all other properties are optional. + +The following properties differ from Markdown frontmatter: + +- The [`slug`](/reference/frontmatter/#slug) property is not supported and is automatically set based on the custom page’s URL. +- The [`editUrl`](/reference/frontmatter/#editurl) option requires a URL to display an edit link. +- The [`sidebar`](/reference/frontmatter/#sidebar) frontmatter property for customizing how the page appears in [autogenerated link groups](/reference/configuration/#sidebar) is not available. Pages using the `<StarlightPage />` component are not part of a collection and cannot be added to an autogenerated sidebar group. +- The [`draft`](/reference/frontmatter/#draft) option only displays a [notice](/reference/overrides/#draftcontentnotice) that the page is a draft but does not automatically exclude it from production builds. + +##### `sidebar` + +**type:** [`SidebarItem[]`](/reference/configuration/#sidebaritem) +**default:** the sidebar generated based on the [global `sidebar` config](/reference/configuration/#sidebar) + +Provide a custom site navigation sidebar for this page. +If not set, the page will use the default global sidebar. + +For example, the following page overrides the default sidebar with a link to the homepage and a group of links to various other custom pages. + +```astro {3-13} +<StarlightPage + frontmatter={{ title: 'Orion' }} + sidebar={[ + { label: 'Home', link: '/' }, + { + label: 'Constellations', + items: [ + { label: 'Andromeda', link: '/andromeda/' }, + { label: 'Orion', link: '/orion/' }, + { label: 'Ursa Minor', link: '/ursa-minor/', badge: 'Stub' }, + ], + }, + ]} +> + Example content. +</StarlightPage> +``` + +See the [“Sidebar Navigation”](/guides/sidebar/) guide to learn more about the available options for customizing the sidebar. + +##### `hasSidebar` + +**type:** `boolean` +**default:** `false` if [`frontmatter.template`](/reference/frontmatter/#template) is `'splash'`, otherwise `true` + +Control whether or not the sidebar should be displayed on this page. + +##### `headings` + +**type:** `{ depth: number; slug: string; text: string }[]` +**default:** `[]` + +Provide an array of all the headings on this page. +Starlight will generate the page table of contents from these headings if provided. + +##### `dir` + +**type:** `'ltr' | 'rtl'` +**default:** the writing direction for the current locale + +Set the writing direction for this page’s content. + +##### `lang` + +**type:** `string` +**default:** the language of the current locale + +Set the BCP-47 language tag for this page’s content, e.g. `en`, `zh-CN`, or `pt-BR`. + +##### `isFallback` + +**type:** `boolean` +**default:** `false` + +Indicate if this page is using [fallback content](/guides/i18n/#fallback-content) because there is no translation for the current language. + +#### `<AnchorHeading>` component + +The `<AnchorHeading />` component renders an HTML heading element with a clickable anchor link that matches Starlight’s Markdown styles. + +```astro +--- +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +--- + +<AnchorHeading level="2" id="sub-heading">Sub heading</AnchorHeading> +``` + +It accepts the following props as well as any other valid [global HTML attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes). + +##### `level` + +**required** +**type:** `1 | 2 | 3 | 4 | 5 | 6` + +The heading level to render. +For example, `level="1"` would render an `<h1>` element. + +##### `id` + +**required** +**type:** `string` + +The unique ID for this heading. +This will be used as the `id` attribute of the rendered heading and the anchor icon will link to it. diff --git a/docs/src/content/docs/guides/project-structure.mdx b/docs/src/content/docs/guides/project-structure.mdx index 850724839cf..02dc4789d1d 100644 --- a/docs/src/content/docs/guides/project-structure.mdx +++ b/docs/src/content/docs/guides/project-structure.mdx @@ -5,12 +5,12 @@ description: Learn how to organize files in your Starlight project. This guide will show you how a Starlight project is organized and what the different files in your project do. -Starlight projects generally follow the same file and directory structure as other Astro projects. See [Astro’s project structure documentation](https://docs.astro.build/en/core-concepts/project-structure/) for more detail. +Starlight projects generally follow the same file and directory structure as other Astro projects. See [Astro’s project structure documentation](https://docs.astro.build/en/basics/project-structure/) for more detail. ## Files and directories - `astro.config.mjs` — The Astro configuration file; includes the Starlight integration and configuration. -- `src/content/config.ts` — Content collections configuration file; adds Starlight’s frontmatter schemas to your project. +- `src/content.config.ts` — Content collections configuration file; adds Starlight’s frontmatter schemas to your project. - `src/content/docs/` — Content files. Starlight turns each `.md`, `.mdx` or `.mdoc` file in this directory into a page on your site. - `src/content/i18n/` (optional) — Translation data to support [internationalization](/guides/i18n/). - `src/` — Other source code and files (components, styles, images, etc.) for your project. @@ -20,7 +20,7 @@ Starlight projects generally follow the same file and directory structure as oth A Starlight project directory might look like this: -import FileTree from '../../../components/file-tree.astro'; +import { FileTree } from '@astrojs/starlight/components'; <FileTree> @@ -39,8 +39,7 @@ import FileTree from '../../../components/file-tree.astro'; - 01-getting-started.md - 02-advanced.md - index.mdx - - config.ts - - env.d.ts + - content.config.ts - astro.config.mjs - package.json - tsconfig.json diff --git a/docs/src/content/docs/guides/route-data.mdx b/docs/src/content/docs/guides/route-data.mdx new file mode 100644 index 00000000000..5214b61f636 --- /dev/null +++ b/docs/src/content/docs/guides/route-data.mdx @@ -0,0 +1,139 @@ +--- +title: Route Data +description: Learn how Starlight’s page data model is used to render your pages and how you can customize it. +--- + +import { Steps } from '@astrojs/starlight/components'; + +When Starlight renders a page in your documentation, it first creates a route data object to represent what is on that page. +This guide explains how route data is generated, how to use it, and how you can customize it to modify Starlight’s default behavior. + +See the [“Route Data Reference”](/reference/route-data/) for a full list of the available properties. + +## What is route data? + +Starlight route data is an object containing all the information required to render a single page. +It includes information for the current page as well as data generated from your Starlight configuration. + +## Using route data + +All of Starlight’s components use route data to decide what to render for each page. +For example, the [`siteTitle`](/reference/route-data/#sitetitle) string is used to display the site title and the [`sidebar`](/reference/route-data/#sidebar) array is used to render the global sidebar navigation. + +You can access this data from the `Astro.locals.starlightRoute` global in Astro components: + +```astro title="example.astro" {2} +--- +const { siteTitle } = Astro.locals.starlightRoute; +--- + +<p>The title of this site is “{siteTitle}”</p> +``` + +This can be useful for example when building [component overrides](/guides/overriding-components/) to customize what you display. + +## Customizing route data + +Starlight’s route data works out of the box and does not require any configuration. +However, for advanced use cases, you may want to customize route data for some or all pages to modify how your site displays. + +This is a similar concept to [component overrides](/guides/overriding-components/), but instead of modifying how Starlight renders your data, you modify the data Starlight renders. + +### When to customize route data + +Customizing route data can be useful when you want to modify how Starlight processes your data in a way not possible with existing configuration options. + +For example, you may want to filter sidebar items or customize titles for specific pages. +Changes like this do not require modifying Starlight’s default components, only the data passed to those components. + +### How to customize route data + +You can customize route data using a special form of “middleware”. +This is a function that is called every time Starlight renders a page and can modify values in the route data object. + +<Steps> + +1. Create a new file exporting an `onRequest` function using Starlight’s `defineRouteMiddleware()` utility: + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware(() => {}); + ``` + +2. Tell Starlight where your route data middleware file is located in `astro.config.mjs`: + + ```js ins={9} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'My delightful docs site', + routeMiddleware: './src/routeData.ts', + }), + ], + }); + ``` + +3. Update your `onRequest` function to modify route data. + + The first argument your middleware will receive is [Astro’s `context` object](https://docs.astro.build/en/reference/api-reference/). + This contains full information about the current page render, including the current URL and `locals`. + + In this example, we are going to make our docs more exciting by adding an exclamation mark to the end of every page’s title. + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware((context) => { + // Get the content collection entry for this page. + const { entry } = context.locals.starlightRoute; + // Update the title to add an exclamation mark. + entry.data.title = entry.data.title + '!'; + }); + ``` + +</Steps> + +#### Multiple route middleware + +Starlight also supports providing multiple middleware. +Set `routeMiddleware` to an array of paths to add more than one middleware handler: + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'My site with multiple middleware', + routeMiddleware: ['./src/middleware-one.ts', './src/middleware-two.ts'], + }), + ], +}); +``` + +#### Waiting for later route middleware + +To wait for middleware later in the stack to run before executing your code, you can await the `next()` callback passed as the second argument to your middleware function. +This can be useful to wait for a plugin’s middleware to run before making changes for example. + +```ts "next" "await next();" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware(async (context, next) => { + // Wait for later middleware to run. + await next(); + // Modify route data. + const { entry } = context.locals.starlightRoute; + entry.data.title = entry.data.title + '!'; +}); +``` diff --git a/docs/src/content/docs/guides/sidebar.mdx b/docs/src/content/docs/guides/sidebar.mdx index f1b508b56f1..270eabaf15f 100644 --- a/docs/src/content/docs/guides/sidebar.mdx +++ b/docs/src/content/docs/guides/sidebar.mdx @@ -1,12 +1,10 @@ --- title: Sidebar Navigation description: Learn how to set up and customize your Starlight site’s sidebar navigation links. -sidebar: - badge: New --- -import FileTree from '../../../components/file-tree.astro'; -import SidebarPreview from '../../../components/sidebar-preview.astro'; +import { FileTree } from '@astrojs/starlight/components'; +import SidebarPreview from '~/components/sidebar-preview.astro'; A well-organized sidebar is key to a good documentation as it is one of the main ways users will navigate your site. Starlight provides a complete set of options to customize your sidebar layout and content. @@ -21,11 +19,11 @@ For example, given the following file structure: - src/ - content/ - docs/ - - guides/ - - components.md - - i18n.md - - reference/ - - configuration.md + - constellations/ + - andromeda.md + - orion.md + - stars/ + - betelgeuse.md </FileTree> @@ -34,17 +32,15 @@ The following sidebar will be automatically generated: <SidebarPreview config={[ { - label: 'guides', + label: 'constellations', items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, + { label: 'Andromeda', link: '' }, + { label: 'Orion', link: '' }, ], }, { - label: 'reference', - items: [ - { label: 'Configuration Reference', link: '/reference/configuration/' }, - ], + label: 'stars', + items: [{ label: 'Betelgeuse', link: '' }], }, ]} /> @@ -53,21 +49,75 @@ Learn more about autogenerated sidebars in the [autogenerated groups](#autogener ## Add links and link groups -To configure your sidebar [links](#links) and [groups of links](#groups) (within a collapsible header), use the [`starlight.sidebar`](/reference/configuration/#sidebar) property in `astro.config.mjs`. +To configure your sidebar links and groups of links (within a collapsible header), use the [`starlight.sidebar`](/reference/configuration/#sidebar) property in `astro.config.mjs`. By combining links and groups, you can create a wide variety of sidebar layouts. -### Links +### Internal links + +Add a link to a page in `src/content/docs/` using an object with the `slug` property. +The linked page’s title will be used as the label by default. + +For example, with the following configuration: + +```js "slug:" +starlight({ + sidebar: [ + { slug: 'constellations/andromeda' }, + { slug: 'constellations/orion' }, + ], +}); +``` + +And the following file structure: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - andromeda.md + - orion.md + +</FileTree> + +The following sidebar will be generated: + +<SidebarPreview + config={[ + { label: 'Andromeda', link: '' }, + { label: 'Orion', link: '' }, + ]} +/> + +To override the values inferred from a linked page’s frontmatter, you can add `label`, [`translations`](#internationalization), and [`attrs`](#custom-html-attributes) properties. + +See ["Customizing autogenerated links"](#customizing-autogenerated-links-in-frontmatter) for more details about controlling the sidebar appearance from page frontmatter. + +#### Shorthand for internal links + +Internal links can also be specified by providing only a string for the page slug as a shorthand. + +For example, the following configuration is equivalent to the configuration above, which used `slug`: + +```js "slug:" +starlight({ + sidebar: ['constellations/andromeda', 'constellations/orion'], +}); +``` + +### Other links -Add a link to an internal or external page using an object with `label` and `link` properties. +Add a link to an external or non-docs page using an object with `label` and `link` properties. -```js +```js "label:" "link:" starlight({ sidebar: [ - // A link to the CSS & Styling guide. - { label: 'CSS & Styling', link: '/guides/css-and-tailwind/' }, - // An external link to the Astro website. - { label: 'Astro', link: 'https://astro.build/' }, + // A link to a non-docs page on this site. + { label: 'Meteor Store', link: '/shop/' }, + // An external link to the NASA website. + { label: 'NASA', link: 'https://www.nasa.gov/' }, ], }); ``` @@ -76,8 +126,8 @@ The configuration above generates the following sidebar: <SidebarPreview config={[ - { label: 'CSS & Styling', link: '/guides/css-and-tailwind/' }, - { label: 'Astro', link: 'https://astro.build/' }, + { label: 'Meteor Store', link: '' }, + { label: 'NASA', link: 'https://www.nasa.gov/' }, ]} /> @@ -90,22 +140,22 @@ Add a group using an object with `label` and `items` properties. The `label` will be used as the heading for the group. Add links or subgroups to the `items` array. -```js +```js /^\s*(label:|items:)/ starlight({ sidebar: [ - // A group of links labelled "Guides". + // A group of links labelled "Constellations". { - label: 'Guides', + label: 'Constellations', items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, - // A nested group of links. + 'constellations/carina', + 'constellations/centaurus', + // A nested group of links for seasonal constellations. { - label: 'Styling', + label: 'Seasonal', items: [ - { label: 'CSS', link: '/guides/css-and-tailwind/' }, - { label: 'Tailwind', link: '/guides/css-and-tailwind/' }, - { label: 'Shiki', link: '/guides/css-and-tailwind/' }, + 'constellations/andromeda', + 'constellations/orion', + 'constellations/ursa-minor', ], }, ], @@ -119,16 +169,16 @@ The configuration above generates the following sidebar: <SidebarPreview config={[ { - label: 'Guides', + label: 'Constellations', items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, + { label: 'Carina', link: '' }, + { label: 'Centaurus', link: '' }, { - label: 'Styling', + label: 'Seasonal', items: [ - { label: 'CSS', link: '/guides/css-and-tailwind/' }, - { label: 'Tailwind', link: '/guides/css-and-tailwind/' }, - { label: 'Shiki', link: '/guides/css-and-tailwind/' }, + { label: 'Andromeda', link: '' }, + { label: 'Orion', link: '' }, + { label: 'Ursa Minor', link: '' }, ], }, ], @@ -140,17 +190,18 @@ The configuration above generates the following sidebar: Starlight can automatically generate a group in your sidebar based on a directory of your docs. This is helpful when you do not want to manually enter each sidebar item in a group. -Pages will be sorted alphabetically by filename by default. + +By default, pages are sorted in alphabetical order according to the file [`slug`](/reference/route-data/#slug). Add an autogenerated group using an object with `label` and `autogenerate` properties. Your `autogenerate` configuration must specify the `directory` to use for sidebar entries. For example, with the following configuration: -```js +```js "label:" "autogenerate:" starlight({ sidebar: [ { - label: 'Guides', - // Autogenerate a group of links for the 'guides' directory. - autogenerate: { directory: 'guides' }, + label: 'Constellations', + // Autogenerate a group of links for the 'constellations' directory. + autogenerate: { directory: 'constellations' }, }, ], }); @@ -163,11 +214,11 @@ And the following file structure: - src/ - content/ - docs/ - - guides/ - - components.md - - i18n.md - - advanced/ - - project-structure.md + - constellations/ + - carina.md + - centaurus.md + - seasonal/ + - andromeda.md </FileTree> @@ -176,29 +227,28 @@ The following sidebar will be generated: <SidebarPreview config={[ { - label: 'Guides', + label: 'Constellations', items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, + { label: 'Carina', link: '' }, + { label: 'Centaurus', link: '' }, { - label: 'advanced', - items: [ - { label: 'Project Structure', link: '/guides/project-structure/' }, - ], + label: 'seasonal', + items: [{ label: 'Andromeda', link: '' }], }, ], }, ]} /> -#### Customizing autogenerated links in frontmatter +## Customizing autogenerated links in frontmatter Use the [`sidebar` frontmatter field](/reference/frontmatter/#sidebar) in individual pages to customize autogenerated links. -Sidebar frontmatter options allow you to set a [custom label](/reference/frontmatter/#label) or add a [badge](/reference/frontmatter/#badge) to a link, [hide](/reference/frontmatter/#hidden) a link from the sidebar, or define a [custom sort weighting](/reference/frontmatter/#order). +Sidebar frontmatter options allow you to set a [custom label](/reference/frontmatter/#label), use [custom attributes](/reference/frontmatter/#attrs), add a [badge](/reference/frontmatter/#badge) to a link, [hide](/reference/frontmatter/#hidden) a link from the sidebar, or define a [custom sort weighting](/reference/frontmatter/#order). -```md +```md "sidebar:" --- +# src/content/docs/example.md title: My page sidebar: # Set a custom label for the link @@ -219,40 +269,45 @@ An autogenerated group including a page with the frontmatter above will generate { label: 'Guides', items: [ - { label: 'A page', link: '#' }, + { label: 'A page', link: '' }, { label: 'Custom sidebar label', - link: '#', + link: '', badge: { text: 'New', variant: 'tip' }, }, - { label: 'Another page', link: '#' }, + { label: 'Another page', link: '' }, ], }, ]} /> :::note -The `sidebar` frontmatter configuration is only used for autogenerated links and will be ignored for manually defined links. +The `sidebar` frontmatter configuration is only used for links in autogenerated groups and docs links defined with the `slug` property. It does not apply to links defined with the `link` property. ::: ## Badges -Links can also include a `badge` property to display a badge next to the link label. +Links, groups, and autogenerated groups can also include a `badge` property to display a badge next to their label. -```js +```js {9,16} starlight({ sidebar: [ { - label: 'Guides', + label: 'Stars', items: [ - // A link with a "New" badge. + // A link with a "Supergiant" badge. { - label: 'Components', - link: '/guides/components/', - badge: 'New', + slug: 'stars/persei', + badge: 'Supergiant', }, ], }, + // An autogenerated group with an "Outdated" badge. + { + label: 'Moons', + badge: 'Outdated', + autogenerate: { directory: 'moons' }, + }, ], }); ``` @@ -262,36 +317,55 @@ The configuration above generates the following sidebar: <SidebarPreview config={[ { - label: 'Guides', + label: 'Stars', items: [ { - label: 'Components', - link: '/guides/components/', - badge: { text: 'New', variant: 'default' }, + label: 'Persei', + link: '', + badge: { text: 'Supergiant', variant: 'default' }, + }, + ], + }, + { + label: 'Moons', + badge: { text: 'Outdated', variant: 'default' }, + items: [ + { + label: 'Io', + link: '', + }, + { + label: 'Europa', + link: '', + }, + { + label: 'Ganymede', + link: '', }, ], }, ]} /> -### Badge variants +### Badge variants and custom styling -Customize the badge styling using an object with `text` and `variant` properties. +Customize the badge styling using an object with `text`, `variant`, and `class` properties. The `text` represents the content to display (e.g. "New"). -Override the `default` styling, which uses the accent color of your site, by setting the `variant` property to one of the following values: `note`, `tip`, `danger`, `caution` or `success`. +By default, the badge will use the accent color of your site. To use a built-in badge style, set the `variant` property to one of the following values: `note`, `tip`, `danger`, `caution` or `success`. + +Optionally, you can create a custom badge style by setting the `class` property to a CSS class name. -```js +```js {9} starlight({ sidebar: [ { - label: 'Guides', + label: 'Stars', items: [ - // A link with a yellow "Experimental" badge. + // A link with a yellow "Stub" badge. { - label: 'Components', - link: '/guides/components/', - badge: { text: 'Experimental', variant: 'caution' }, + slug: 'stars/sirius', + badge: { text: 'Stub', variant: 'caution' }, }, ], }, @@ -304,12 +378,124 @@ The configuration above generates the following sidebar: <SidebarPreview config={[ { - label: 'Guides', + label: 'Stars', items: [ { - label: 'Components', - link: '/guides/components/', - badge: { text: 'Experimental', variant: 'caution' }, + label: 'Sirius', + link: '', + badge: { text: 'Stub', variant: 'caution' }, + }, + ], + }, + ]} +/> + +Learn more about [using and customizing badges](/components/badges/#usage). + +## Custom HTML attributes + +Links can also include an `attrs` property to add custom HTML attributes to the link element. + +In the following example, `attrs` is used to add a `target="_blank"` attribute, so that the link opens in a new tab, and to apply a custom `style` attribute to italicize the link label: + +```js {10} +starlight({ + sidebar: [ + { + label: 'Resources', + items: [ + // An external link to the NASA website opening in a new tab. + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { target: '_blank', style: 'font-style: italic' }, + }, + ], + }, + ], +}); +``` + +The configuration above generates the following sidebar: + +<SidebarPreview + config={[ + { + label: 'Resources', + items: [ + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { + target: '_blank', + style: 'font-style: italic', + }, + }, + ], + }, + ]} +/> + +### Custom HTML attributes for autogenerated links + +Customize HTML attributes of all links in [autogenerated groups](#autogenerated-groups) by defining the `attrs` property in the `autogenerate` configuration. +Individual pages can specify custom attributes using the [`sidebar.attrs` frontmatter field](/reference/frontmatter/#attrs) which will be merged with the `autogenerate.attrs` configuration. + +For example, with the following configuration: + +```js {9} +starlight({ + sidebar: [ + { + label: 'Constellations', + autogenerate: { + // Autogenerate a group of links for the 'constellations' directory. + directory: 'constellations', + // Italicize all link labels in this group. + attrs: { style: 'font-style: italic' }, + }, + }, + ], +}); +``` + +And the following file structure: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - carina.md + - centaurus.md + - seasonal/ + - andromeda.md + +</FileTree> + +The following sidebar will be generated with all autogenerated links italicized: + +<SidebarPreview + config={[ + { + label: 'Constellations', + items: [ + { label: 'Carina', link: '', attrs: { style: 'font-style: italic' } }, + { + label: 'Centaurus', + link: '', + attrs: { style: 'font-style: italic' }, + }, + { + label: 'seasonal', + items: [ + { + label: 'Andromeda', + link: '', + attrs: { style: 'font-style: italic' }, + }, + ], }, ], }, @@ -318,31 +504,112 @@ The configuration above generates the following sidebar: ## Internationalization -Use the `translations` property on link and group entries to translate the link or group label for each supported language. +Use the `translations` property on link and group entries to translate the link or group label for each supported language by specifying a [BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags) language tag, e.g. `"en"`, `"ar"`, or `"zh-CN"`, as the key and the translated label as the value. The `label` property will be used for the default locale and for languages without a translation. -```js +```js {5-7,11-13,18-20} starlight({ sidebar: [ { - label: 'Guides', + label: 'Constellations', translations: { - es: 'Guías', + 'pt-BR': 'Constelações', }, items: [ { - label: 'Components', + label: 'Andromeda', translations: { - es: 'Componentes', + 'pt-BR': 'Andrômeda', }, - link: '/guides/components/', + slug: 'constellations/andromeda', }, { - label: 'Internationalization (i18n)', + label: 'Scorpius', translations: { - es: 'Internacionalización (i18n)', + 'pt-BR': 'Escorpião', + }, + slug: 'constellations/scorpius', + }, + ], + }, + ], +}); +``` + +Browsing the documentation in Brazilian Portuguese will generate the following sidebar: + +<SidebarPreview + config={[ + { + label: 'Constelação', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +### Internationalization with internal links + +[Internal links](#internal-links) will automatically use translated page titles from content frontmatter by default: + +```js {9-10} +starlight({ + sidebar: [ + { + label: 'Constellations', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { slug: 'constellations/andromeda' }, + { slug: 'constellations/scorpius' }, + ], + }, + ], +}); +``` + +Browsing the documentation in Brazilian Portuguese will generate the following sidebar: + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +In multilingual sites, the value of `slug` does not include the language portion of the URL. +For example, if you have pages at `en/intro` and `pt-br/intro`, the slug is `intro` when configuring the sidebar. + +### Internationalization with badges + +For [badges](#badges), the `text` property can be a string, or for multilingual sites, an object with values for each different locale. +When using the object form, the keys must be [BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags) tags (e.g. `en`, `ar`, or `zh-CN`): + +```js {11-16} +starlight({ + sidebar: [ + { + label: 'Constellations', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { + slug: 'constellations/andromeda', + badge: { + text: { + en: 'New', + 'pt-BR': 'Novo', + }, }, - link: '/guides/i18n/', }, ], }, @@ -350,15 +617,18 @@ starlight({ }); ``` -Browsing the documentation in Spanish will generate the following sidebar: +Browsing the documentation in Brazilian Portuguese will generate the following sidebar: <SidebarPreview config={[ { - label: 'Guías', + label: 'Constelações', items: [ - { label: 'Componentes', link: '/guides/components/' }, - { label: 'Internacionalización (i18n)', link: '/guides/i18n/' }, + { + label: 'Andrômeda', + link: '', + badge: { text: 'Novo', variant: 'default' }, + }, ], }, ]} @@ -368,17 +638,14 @@ Browsing the documentation in Spanish will generate the following sidebar: Groups of links can be collapsed by default by setting the `collapsed` property to `true`. -```js +```js {5-6} starlight({ sidebar: [ { - label: 'Guides', + label: 'Constellations', // Collapse the group by default. collapsed: true, - items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, - ], + items: ['constellations/andromeda', 'constellations/orion'], }, ], }); @@ -389,11 +656,11 @@ The configuration above generates the following sidebar: <SidebarPreview config={[ { - label: 'Guides', + label: 'Constellations', collapsed: true, items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, + { label: 'Andromeda', link: '' }, + { label: 'Orion', link: '' }, ], }, ]} @@ -401,14 +668,14 @@ The configuration above generates the following sidebar: [Autogenerated groups](#autogenerated-groups) respect the `collapsed` value of their parent group: -```js +```js {5-6} starlight({ sidebar: [ { - label: 'Guides', + label: 'Constellations', // Collapse the group and its autogenerated subgroups by default. collapsed: true, - autogenerate: { directory: 'guides' }, + autogenerate: { directory: 'constellations' }, }, ], }); @@ -419,17 +686,15 @@ The configuration above generates the following sidebar: <SidebarPreview config={[ { - label: 'Guides', + label: 'Constellations', collapsed: true, items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, + { label: 'Carina', link: '' }, + { label: 'Centaurus', link: '' }, { - label: 'advanced', + label: 'seasonal', collapsed: true, - items: [ - { label: 'Project Structure', link: '/guides/project-structure/' }, - ], + items: [{ label: 'Andromeda', link: '' }], }, ], }, @@ -438,15 +703,15 @@ The configuration above generates the following sidebar: This behavior can be overridden by defining the `autogenerate.collapsed` property. -```js +```js {5-7} "collapsed: true" starlight({ sidebar: [ { - label: 'Guides', - // Do not collapse the "Guides" group but collapse its + label: 'Constellations', + // Do not collapse the "Constellations" group but collapse its // autogenerated subgroups. collapsed: false, - autogenerate: { directory: 'guides', collapsed: true }, + autogenerate: { directory: 'constellations', collapsed: true }, }, ], }); @@ -457,16 +722,14 @@ The configuration above generates the following sidebar: <SidebarPreview config={[ { - label: 'Guides', + label: 'Constellations', items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, + { label: 'Carina', link: '' }, + { label: 'Centaurus', link: '' }, { - label: 'advanced', + label: 'seasonal', collapsed: true, - items: [ - { label: 'Project Structure', link: '/guides/project-structure/' }, - ], + items: [{ label: 'Andromeda', link: '' }], }, ], }, diff --git a/docs/src/content/docs/guides/site-search.mdx b/docs/src/content/docs/guides/site-search.mdx new file mode 100644 index 00000000000..96011b5d419 --- /dev/null +++ b/docs/src/content/docs/guides/site-search.mdx @@ -0,0 +1,244 @@ +--- +title: Site Search +description: Learn about Starlight’s built-in site search features and how to customize them. +tableOfContents: + maxHeadingLevel: 4 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +By default, Starlight sites include full-text search powered by [Pagefind](https://pagefind.app/), which is a fast and low-bandwidth search tool for static sites. + +No configuration is required to enable search. Build and deploy your site, then use the search bar in the site header to find content. + +## Hide content in search results + +### Exclude a page + +To exclude a page from your search index, add [`pagefind: false`](/reference/frontmatter/#pagefind) to the page’s frontmatter: + +```md title="src/content/docs/not-indexed.md" ins={3} +--- +title: Content to hide from search +pagefind: false +--- +``` + +### Exclude part of a page + +Pagefind will ignore content inside an element with the [`data-pagefind-ignore`](https://pagefind.app/docs/indexing/#removing-individual-elements-from-the-index) attribute. + +In the following example, the first paragraph will display in search results, but the contents of the `<div>` will not: + +```md title="src/content/docs/partially-indexed.md" ins="data-pagefind-ignore" +--- +title: Partially indexed page +--- + +This text will be discoverable via search. + +<div data-pagefind-ignore> + +This text will be hidden from search. + +</div> +``` + +## Alternative search providers + +### Algolia DocSearch + +If you have access to [Algolia’s DocSearch program](https://docsearch.algolia.com/) and want to use it instead of Pagefind, you can use the official Starlight DocSearch plugin. + +<Steps> + +1. Install `@astrojs/starlight-docsearch`: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-docsearch + ``` + + </TabItem> + + </Tabs> + +2. Add DocSearch to your Starlight [`plugins`](/reference/configuration/#plugins) config in `astro.config.mjs` and pass it your Algolia `appId`, `apiKey`, and `indexName`: + + ```js ins={4,10-16} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Site with DocSearch', + plugins: [ + starlightDocSearch({ + appId: 'YOUR_APP_ID', + apiKey: 'YOUR_SEARCH_API_KEY', + indexName: 'YOUR_INDEX_NAME', + }), + ], + }), + ], + }); + ``` + +</Steps> + +With this updated configuration, the search bar on your site will now open an Algolia modal instead of the default search modal. + +#### DocSearch configuration + +The Starlight DocSearch plugin supports customizing the DocSearch component with the following inline options: + +- `maxResultsPerGroup`: Limit the number of results displayed for each search group. Default is `5`. +- `disableUserPersonalization`: Prevent DocSearch from saving a user’s recent searches and favorites to local storage. Default is `false`. +- `insights`: Enable the Algolia Insights plugin and send search events to your DocSearch index. Default is `false`. +- `searchParameters`: An object customizing the [Algolia Search Parameters](https://www.algolia.com/doc/api-reference/search-api-parameters/). + +##### Additional DocSearch options + +A separate configuration file is required to pass function options like `transformItems()` or `resultsFooterComponent()` to the DocSearch component. + +<Steps> + +1. Create a TypeScript file exporting your DocSearch configuration. + + ```ts + // src/config/docsearch.ts + import type { DocSearchClientOptions } from '@astrojs/starlight-docsearch'; + + export default { + appId: 'YOUR_APP_ID', + apiKey: 'YOUR_SEARCH_API_KEY', + indexName: 'YOUR_INDEX_NAME', + getMissingResultsUrl({ query }) { + return `https://github.com/algolia/docsearch/issues/new?title=${query}`; + }, + // ... + } satisfies DocSearchClientOptions; + ``` + +2. Pass the path to your configuration file to the Starlight DocSearch plugin in `astro.config.mjs`. + + ```js {11-13} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Site with DocSearch', + plugins: [ + starlightDocSearch({ + clientOptionsModule: './src/config/docsearch.ts', + }), + ], + }), + ], + }); + ``` + +</Steps> + +See the [DocSearch JavaScript client API Reference](https://docsearch.algolia.com/docs/api/) for all supported options. + +#### Translating the DocSearch UI + +DocSearch only provides English UI strings by default. +Add translations of the modal UI for your language using Starlight’s built-in [internationalization system](/guides/i18n/#translate-starlights-ui). + +<Steps> + +1. Extend Starlight’s `i18n` content collection definition with the DocSearch schema in `src/content.config.ts`: + + ```js ins={5} ins=/{ extend: .+ }/ + // src/content.config.ts + import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; + import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + import { docSearchI18nSchema } from '@astrojs/starlight-docsearch/schema'; + + export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ extend: docSearchI18nSchema() }), + }), + }; + ``` + +2. Add translations to your JSON files in `src/content/i18n/`. + + These are the English defaults used by DocSearch: + + ```json title="src/content/i18n/en.json" + { + "docsearch.searchBox.resetButtonTitle": "Clear the query", + "docsearch.searchBox.resetButtonAriaLabel": "Clear the query", + "docsearch.searchBox.cancelButtonText": "Cancel", + "docsearch.searchBox.cancelButtonAriaLabel": "Cancel", + "docsearch.searchBox.searchInputLabel": "Search", + + "docsearch.startScreen.recentSearchesTitle": "Recent", + "docsearch.startScreen.noRecentSearchesText": "No recent searches", + "docsearch.startScreen.saveRecentSearchButtonTitle": "Save this search", + "docsearch.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", + "docsearch.startScreen.favoriteSearchesTitle": "Favorite", + "docsearch.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + + "docsearch.errorScreen.titleText": "Unable to fetch results", + "docsearch.errorScreen.helpText": "You might want to check your network connection.", + + "docsearch.footer.selectText": "to select", + "docsearch.footer.selectKeyAriaLabel": "Enter key", + "docsearch.footer.navigateText": "to navigate", + "docsearch.footer.navigateUpKeyAriaLabel": "Arrow up", + "docsearch.footer.navigateDownKeyAriaLabel": "Arrow down", + "docsearch.footer.closeText": "to close", + "docsearch.footer.closeKeyAriaLabel": "Escape key", + "docsearch.footer.searchByText": "Search by", + + "docsearch.noResultsScreen.noResultsText": "No results for", + "docsearch.noResultsScreen.suggestedQueryText": "Try searching for", + "docsearch.noResultsScreen.reportMissingResultsText": "Believe this query should return results?", + "docsearch.noResultsScreen.reportMissingResultsLinkText": "Let us know." + } + ``` + +</Steps> + +### Community search providers + +[Community plugins](/resources/plugins/#community-plugins) can also provide alternatives to Starlight’s built-in Pagefind search provider. + +#### Typesense DocSearch + +The [Starlight DocSearch Typesense](https://starlight-docsearch.typesense.org/) community plugin provides an open-source and self-hostable alternative that integrates the [DocSearch](https://github.com/typesense/typesense-docsearch.js) interface with a [Typesense](https://typesense.org/) backend. + +See the [“Getting Started”](https://starlight-docsearch.typesense.org/getting-started/) guide in the Starlight DocSearch Typesense documentation to learn how to use it in your project. diff --git a/docs/src/content/docs/hi/404.md b/docs/src/content/docs/hi/404.md new file mode 100644 index 00000000000..3aadf79ca29 --- /dev/null +++ b/docs/src/content/docs/hi/404.md @@ -0,0 +1,14 @@ +--- +title: पेज नहीं मिला +template: splash +editUrl: false +lastUpdated: false +hero: + title: '404' + tagline: <strong>Houston, हमें एक समस्या है।</strong> हमें वह पेज नहीं मिला.<br> URL जांचें या खोज बार का उपयोग करने का प्रयास करें। + actions: + - text: अवतरण पेज पर वापस आये + icon: right-arrow + link: /hi/ + variant: primary +--- diff --git a/docs/src/content/docs/hi/environmental-impact.md b/docs/src/content/docs/hi/environmental-impact.md new file mode 100644 index 00000000000..4828e2ec55f --- /dev/null +++ b/docs/src/content/docs/hi/environmental-impact.md @@ -0,0 +1,142 @@ +--- +title: पर्यावरण-अनुकूल दस्तावेज़ +description: जानें कि कैसे Starlight आपको हरित दस्तावेज़ीकरण साइट बनाने और आपके कार्बन निशान को कम करने में मदद कर सकता है। +--- + +वेब उद्योग के जलवायु प्रभाव का अनुमान वैश्विक कार्बन उत्सर्जन के [2%][sf] से [4% के बीच][bbc] है, जो लगभग एयरलाइन उद्योग के उत्सर्जन के बराबर है। +किसी वेबसाइट के पारिस्थितिक प्रभाव की गणना करने में कई जटिल कारक होते हैं, लेकिन इस मार्गदर्शिका में आपके दस्तावेज़ साइट के पर्यावरणीय पदचिह्न को कम करने के लिए कुछ युक्तियां शामिल हैं। + +अच्छी खबर यह है कि Starlight को चुनना एक बेहतरीन शुरुआत है। +Website Carbon Calculator के अनुसार, यह साइट [परीक्षण किए गए 99% वेब पेजों की तुलना में अधिक स्वच्छ है][sl-carbon], जो प्रति पेज भेंट में 0.01 ग्राम CO₂ का उत्पादन करती है। + +## पेज का वजन + +एक वेब पेज जितना अधिक डेटा स्थानांतरित करता है, उसे उतने ही अधिक शक्ति संसाधनों की आवश्यकता होती है। +एप्रिल 2023 में, [HTTP आर्काइव के डेटा][http] के अनुसार, औसत वेब पेज के लिए उपयोगकर्ता को 2,000 KB से अधिक डाउनलोड करने की आवश्यकता थी + +Starlight ऐसे पेज बनाता है जो यथासंभव हल्के होते हैं। +उदाहरण के लिए, पहले दर्शन पर, एक उपयोगकर्ता 50 KB से कम संपीड़ित डेटा डाउनलोड करेगा - HTTP संग्रह माध्य का केवल 2.5%। +एक अच्छी कैशिंग रणनीति के साथ, बाद के नेविगेशन कम से कम 10 KB तक डाउनलोड हो सकते हैं। + +### छवियाँ + +जबकि Starlight एक अच्छी आधार रेखा प्रदान करता है, आपके द्वारा अपने दस्तावेज़ पेजों में जोड़ी गई छवियां आपके पेज का वजन तेजी से बढ़ा सकती हैं। +Starlight आपके Markdown और MDX फ़ाइलों में स्थानीय छवियों को अनुकूलित करने के लिए Astro के [अनुकूलित संपत्ति समर्थन][assets] का उपयोग करता है। + +### UI अवयव + +React या Vue जैसे UI फ्रेमवर्क के साथ निर्मित अवयव आसानी से एक पेज पर बड़ी मात्रा में Javascript जोड़ सकते हैं। +क्योंकि Starlight Astro पर बनाया गया है, [Astro द्वीप समूह][islands] की बदौलत इन जैसे अवयव डिफ़ॉल्ट रूप से **शून्य client-side Jacascript** लोड करते हैं। + +### कैशिंग + +कैशिंग का उपयोग यह नियंत्रित करने के लिए किया जाता है कि कोई ब्राउज़र पहले से डाउनलोड किए गए डेटा को कितनी देर तक संग्रहीत कर सकता है और उसका पुन: उपयोग करता है। +एक अच्छी कैशिंग रणनीति यह सुनिश्चित करती है कि उपयोगकर्ता को नई सामग्री बदलने पर जल्द से जल्द मिल जाए, लेकिन जब सामग्री नहीं बदली है तो उसे बार-बार डाउनलोड करने से भी बचा जा सकता है। + +कैशिंग को कॉन्फ़िगर करने का सबसे आम तरीका [`Cache-Control` HTTP header][cache] है। +Starlight का उपयोग करते समय, आप `/_astro/` निर्देशिका में हर चीज़ के लिए एक लंबा cache समय निर्धारित कर सकते हैं। +इस निर्देशिका में CSS, JavaScript और अन्य बंडल संपत्तियां शामिल हैं जिन्हें अनावश्यक डाउनलोड को कम करते हुए हमेशा के लिए सुरक्षित रूप से cache किया जा सकता है: + +``` +Cache-Control: public, max-age=604800, immutable +``` + +कैशिंग को कैसे कॉन्फ़िगर करें यह आपके वेब होस्ट पर निर्भर करता है। उदाहरण के लिए, Vercel बिना किसी कॉन्फ़िगरेशन की आवश्यकता के आपके लिए इस कैशिंग रणनीति को लागू करता है, जबकि आप अपने परियोजना में `public/_headers` फ़ाइल जोड़कर [नेटलिफाई के लिए कस्टम हेडर][ntl-headers] सेट कर सकते हैं: + +``` +/_astro/* + Cache-Control: public + Cache-Control: max-age=604800 + Cache-Control: immutable +``` + +[cache]: https://csswizardry.com/2019/03/cache-control-for-civilians/ +[ntl-headers]: https://docs.netlify.com/routing/headers/ + +## शक्ति की खपत + +एक वेब पेज कैसे बनाया जाता है यह उपयोगकर्ता के उपकरण पर चलने में लगने वाली शक्ति को प्रभावित कर सकता है। +न्यूनतम Javascript का उपयोग करके, Starlight उपयोगकर्ता के फोन, टैबलेट या कंप्यूटर को पेजो को लोड करने और प्रस्तुत करने के लिए आवश्यक प्रसंस्करण शक्ति की मात्रा को कम कर देता है। + +वैश्लेषिकी ट्रैकिंग स्क्रिप्ट या वीडियो एम्बेड जैसी JavaScript-भारी सामग्री सुविधाएं जोड़ते समय सावधान रहें क्योंकि ये पेज शक्ति उपयोग को बढ़ा सकते हैं। +यदि आपको विश्लेषण की आवश्यकता है, तो [Cabin][cabin], [Fathom][fathom] या [Plausible][plausible] जैसे हल्के विकल्प चुनने पर विचार करें। +[उपयोगकर्ता इंटरैक्शन पर वीडियो लोड][lazy-video] होने की प्रतीक्षा करके YouTube और Vimeo वीडियो जैसे एंबेड को बेहतर बनाया जा सकता है। +[`astro-embed`][embed] जैसे पैकेज सामान्य सेवाओं के लिए मदद कर सकते हैं। + +:::tip[क्या आप जानते हैं?] +JavaScript को पार्स करना और संकलित करना ब्राउज़र द्वारा किए जाने वाले सबसे महंगे कार्यों में से एक है। +समान आकार की JPEG छवि प्रस्तुत करने की तुलना में, [JavaScript को संसाधित होने में 30 गुना से अधिक समय लग सकता है][cost-of-js]। +::: + +[cabin]: https://withcabin.com/ +[fathom]: https://usefathom.com/ +[plausible]: https://plausible.io/ +[lazy-video]: https://web.dev/iframe-lazy-loading/ +[embed]: https://www.npmjs.com/package/astro-embed +[cost-of-js]: https://medium.com/dev-channel/the-cost-of-javascript-84009f51e99e + +## होस्टिंग + +जहां एक वेब पेज होस्ट किया गया है, उसका इस बात पर बड़ा प्रभाव पड़ सकता है कि आपकी दस्तावेज़ीकरण साइट पर्यावरण के अनुकूल कितनी है। +डेटा सेंटर और सर्वर फ़ार्म का बड़ा पारिस्थितिक प्रभाव हो सकता है, जिसमें उच्च बिजली की खपत और पानी का गहन उपयोग शामिल है। + +नवीकरणीय शक्ति का उपयोग करने वाले होस्ट को चुनने का मतलब आपकी साइट के लिए कम कार्बन उत्सर्जन होगा। [Green Web Directory][gwb] एक उपकरण है जो आपको होस्टिंग कंपनियों को ढूंढने में मदद कर सकता है। + +[gwb]: https://www.thegreenwebfoundation.org/directory/ + +## तुलना + +क्या आप जानना चाहते हैं कि अन्य दस्तावेज़ीकरण फ्रेमवर्क की तुलना कैसे की जाती है? +[Website Carbon Calculator][wcc] के साथ ये परीक्षण विभिन्न उपकरणों के साथ बनाए गए समान पृष्ठों की तुलना करते हैं। + +| फ्रेमवर्क | प्रति पृष्ठ विज़िट CO₂ | रेटिंग | +| --------------------------- | ---------------------- | :----: | +| [Starlight][sl-carbon] | 0.01g | A+ | +| [Read the Docs][rtd-carbon] | 0.05g | A+ | +| [Sphinx][sx-carbon] | 0.06g | A+ | +| [VitePress][vp-carbon] | 0.07g | A+ | +| [Docus][dc-carbon] | 0.09g | A+ | +| [docsify][dy-carbon] | 0.10g | A | +| [Nextra][nx-carbon] | 0.11g | A | +| [MkDocs][mk-carbon] | 0.19g | B | +| [Docusaurus][ds-carbon] | 0.21g | B | +| [GitBook][gb-carbon] | 0.43g | C | +| [Mintlify][mt-carbon] | 1.22g | F | + +<small>डेटा 22 जुलाई 2024 को एकत्र किया गया। नवीनतम आंकड़े देखने के लिए लिंक पर क्लिक करें।</small> + +[sl-carbon]: https://www.websitecarbon.com/website/starlight-astro-build-getting-started/ +[vp-carbon]: https://www.websitecarbon.com/website/vitepress-dev-guide-what-is-vitepress/ +[dc-carbon]: https://www.websitecarbon.com/website/docus-dev-introduction-getting-started/ +[sx-carbon]: https://www.websitecarbon.com/website/sphinx-doc-org-en-master-usage-quickstart-html/ +[mk-carbon]: https://www.websitecarbon.com/website/mkdocs-org-getting-started/ +[nx-carbon]: https://www.websitecarbon.com/website/nextra-site-docs-docs-theme-start/ +[dy-carbon]: https://www.websitecarbon.com/website/docsify-js-org/ +[ds-carbon]: https://www.websitecarbon.com/website/docusaurus-io-docs/ +[rtd-carbon]: https://www.websitecarbon.com/website/docs-readthedocs-io-en-stable-index-html/ +[gb-carbon]: https://www.websitecarbon.com/website/docs-gitbook-com/ +[mt-carbon]: https://www.websitecarbon.com/website/mintlify-com-docs-quickstart/ + +## और अधिक संसाधन + +### उपकरण + +- [Website Carbon Calculator][wcc] +- [GreenFrame](https://greenframe.io/) +- [Ecograder](https://ecograder.com/) +- [WebPageTest Carbon Control](https://www.webpagetest.org/carbon-control/) +- [Ecoping](https://ecoping.earth/) + +### लेख और वार्ता + +- [“Building a greener web”](https://youtu.be/EfPoOt7T5lg), Michelle Barker द्वारा वार्ता +- [“Sustainable Web Development Strategies Within An Organization”](https://www.smashingmagazine.com/2022/10/sustainable-web-development-strategies-organization/), Michelle Barker का लेख +- [“A sustainable web for everyone”](https://2021.stateofthebrowser.com/speakers/tom-greenwood/), Tom Greenwood द्वारा वार्ता +- [“How Web Content Can Affect Power Usage”](https://webkit.org/blog/8970/how-web-content-can-affect-power-usage/), Benjamin Poulain और Simon Fraser का लेख + +[sf]: https://www.sciencefocus.com/science/what-is-the-carbon-footprint-of-the-internet/ +[bbc]: https://www.bbc.com/future/article/20200305-why-your-internet-habits-are-not-as-clean-as-you-think +[http]: https://httparchive.org/reports/state-of-the-web +[assets]: https://docs.astro.build/hi/guides/assets/ +[islands]: https://docs.astro.build/hi/concepts/islands/ +[wcc]: https://www.websitecarbon.com/ diff --git a/docs/src/content/docs/hi/getting-started.mdx b/docs/src/content/docs/hi/getting-started.mdx new file mode 100644 index 00000000000..f770982e2de --- /dev/null +++ b/docs/src/content/docs/hi/getting-started.mdx @@ -0,0 +1,139 @@ +--- +title: पहले कदम +description: जानें कि Astro द्वारा Starlight के साथ अपना अगला अगली दस्तावेज़ीकरण साइट का निर्माण कैसे शुरू करें। +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +Starlight [Astro](https://astro.build) फ्रेमवर्क के शीर्ष पर निर्मित एक पूर्ण-विशेषीकृत दस्तावेज़ीकरण थीम है। +यह मार्गदर्शिका आपको एक नई परियोजना शुरू करने में मदद करेगी। +मौजूदा Astro परियोजना में Starlight जोड़ने के लिए [मैन्युअल सेटअप निर्देश](/hi/manual-setup/) देखें। + +## जल्दी शुरुआत करें + +### एक नयी परियोजना बनाएं + +अपने टर्मिनल में निम्नलिखित आदेश चलाकर एक नयी Astro + Starlight परियोजना बनाएं: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight +``` + +</TabItem> +</Tabs> + +यह आपकी साइट के लिए सभी आवश्यक फ़ाइलों और कॉन्फ़िगरेशन के साथ एक नई [परियोजना निर्देशिका](/hi/guides/project-structure/) बनाएगा। + +:::tip[इसे क्रियान्वित करके देखें] +अपने ब्राउज़र में Starlight आज़माएँ: +[StackBlitz पर टेम्पलेट खोलें](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). +::: + +### विकास सर्वर शुरू करें + +स्थानीय स्तर पर काम करते समय, [Astro का विकास सर्वर](https://docs.astro.build/hi/reference/cli-reference/#astro-dev) आपको अपने काम का पूर्वावलोकन करने देता है और जब आप परिवर्तन करते हैं तो स्वचालित रूप से आपके ब्राउज़र को रीफ्रेश करता है। + +अपनी परियोजना निर्देशिका के अंदर, विकास सर्वर शुरू करने के लिए निम्नलिखित आदेश चलाएँ: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm run dev +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm dev +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev +``` + +</TabItem> +</Tabs> + +यह आपके स्थानीय पूर्वावलोकन के URL के साथ आपके टर्मिनल पर एक संदेश लॉग करेगा। +अपनी साइट ब्राउज़ करने के लिए इस URL को खोलें। + +### सामग्री जोड़ें + +Starlight आपके लिए नई सामग्री जोड़ने, या अपनी मौजूदा फ़ाइलें लाने के लिए तैयार है! + +`src/content/docs/` निर्देशिका में Markdown फ़ाइलें बनाकर अपनी साइट पर नए पेज जोड़ें। + +["पेज"](/hi/guides/pages/) गाइड में MDX और Markdoc फाइलों के लिए फ़ाइल-आधारित रूटिंग और समर्थन के बारे में और पढ़ें। + +### अगले कदम + +- **कॉन्फ़िगर:** ["कस्टमाइज़िंग स्टारलाइट"](/hi/guides/customization/) में सामान्य विकल्पों के बारे में जानें। +- **नेविगेट:** ["साइडबार नेविगेशन"](/hi/guides/sidebar/) गाइड के साथ अपना साइडबार सेट करें। +- **अवयवों:** ["अवयवों"](/hi/components/using-components/) मार्गदर्शिका में अंतर्निहित कार्ड, टैब और बहुत कुछ खोजें। +- **डिप्लॉय:** Astro Docs में ["अपनी साइट परिनियोजित करें"](https://docs.astro.build/hi/guides/deploy/) मार्गदर्शिका के साथ अपना कार्य प्रकाशित करें। + +## Starlight को अद्यतन करें + +:::tip +क्योंकि Starlight बीटा सॉफ्टवेयर है, इसमें लगातार अपडेट और सुधार होते रहेंगे। Starlight को नियमित रूप से अपडेट करना सुनिश्चित रखे! +::: + +Starlight एक Astro एकीकरण है। आप अपने टर्मिनल में निम्नलिखित आदेश चलाकर इसे और अन्य Astro पैकेज का अद्यतन कर सकते हैं: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npx @astrojs/upgrade +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm dlx @astrojs/upgrade +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dlx @astrojs/upgrade +``` + +</TabItem> +</Tabs> + +प्रत्येक रिलीज़ में किए गए परिवर्तनों की पूरी सूची के लिए [Starlight चेंजलॉग](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md) देखें। + +## समस्या निवारण Starlight में + +यह सुनिश्चित करने के लिए कि आपकी Starlight साइट कॉन्फ़िगर है और ठीक से काम कर रही है, [परियोजना कॉन्फ़िगरेशन](/hi/reference/configuration/) और [व्यक्तिगत पेज फ्रंटमैटर कॉन्फ़िगरेशन](/hi/reference/frontmatter/) संदर्भ पेजो का उपयोग करें। +सामग्री जोड़ने और अपनी स्टारलाइट साइट को अनुकूलित करने में सहायता के लिए साइडबार में मार्गदर्शिकाएँ देखें। + +यदि आपका उत्तर इन दस्तावेज़ों में नहीं मिल सकता है, तो संपूर्ण Astro दस्तावेज़ीकरण के लिए कृपया [Astro दस्तावेज़](https://docs.astro.build/hi) देखें। +आपके प्रश्न का उत्तर यह समझकर दिया जा सकता है कि इस Starlight थीम के तहत Astro सामान्य रूप से कैसे काम करता है। + +आप [GitHub पर किसी ज्ञात Starlight समस्या](https://github.com/withastro/starlight/issues) की भी जांच कर सकते हैं, और हमारे सक्रिय, मैत्रीपूर्ण समुदाय से [Astro Discord](https://astro.build/chat/) में सहायता प्राप्त कर सकते हैं! हमारे `#support` फोरम में "Starlight" टैग के साथ प्रश्न पोस्ट करें, या वर्तमान विकास और अधिक पर चर्चा करने के लिए हमारे समर्पित `#Starlight` चैनल पर जाएँ! diff --git a/docs/src/content/docs/hi/index.mdx b/docs/src/content/docs/hi/index.mdx new file mode 100644 index 00000000000..6f6374ffe6c --- /dev/null +++ b/docs/src/content/docs/hi/index.mdx @@ -0,0 +1,156 @@ +--- +title: Starlight 🌟 दस्तावेज़ीकरण साइटें बनाएं Astro के साथ +head: + - tag: title + content: Starlight 🌟 दस्तावेज़ीकरण साइटें बनाएं Astro के साथ +description: Starlight आपको Astro के साथ सुंदर, उच्च प्रदर्शन वाली दस्तावेज़ीकरण वेबसाइट बनाने में मदद करता है। +template: splash +editUrl: false +lastUpdated: false +hero: + title: अपने दस्तावेज़ों को Starlight से चमकाएँ + tagline: एक तारकीय दस्तावेज़ीकरण वेबसाइट बनाने के लिए आपको जो कुछ भी चाहिए वह सब कुछ इधर हैं। तेज़, अभिगम्य और उपयोग में आसान। + image: + file: ~/assets/hero-star.webp + actions: + - text: शुरू हो जाओ + icon: right-arrow + link: /hi/getting-started/ + - text: GitHub पर देखें + icon: external + variant: minimal + link: https://github.com/withastro/starlight +--- + +import { CardGrid, Card } from '@astrojs/starlight/components'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; + +<CardGrid stagger> + <Card title="दस्तावेज़ीकरण जो आनंदित करता है" icon="open-book"> + इसमें शामिल हैं: साइट मार्गदर्शन, खोज, अंतर्राष्ट्रीयकरण, SEO, पढ़ने में + आसान Typography, कोड हाइलाइटिंग, डार्क मोड और बहुत कुछ। + </Card> + <Card title="Astro द्वारा संचालित" icon="rocket"> + Astro की पूरी शक्ति और प्रदर्शन का लाभ उठाएं। विस्तार करें Starlight का अपने + पसंदीदा Astro एकीकरण और लाइब्रेरी का उपयोग करके। + </Card> + <Card title="Markdown, Markdoc, और MDX" icon="document"> + अपनी पसंदीदा Markup भाषा लाएँ। Starlight आपको बिल्ट-इन फ्रंटमैटर मान्यकरण के + साथ TypeScript प्रकार-सुरक्षा देता है । + </Card> + <Card title="अपने स्वयं के UI अवयवों लाएँ" icon="puzzle"> + Starlight एक फ्रेमवर्क-अज्ञेयवादी, संपूर्ण दस्तावेज़ समाधान के रूप में + उपलब्ध है। React, Vue, Svelte, Solid और अन्य के साथ विस्तार करें। + </Card> +</CardGrid> + +<TestimonialGrid title="जानिए लोग क्या कह रहे हैं"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + Astro टीम ने विकसित किया है कैसे दस्तावेज़ बनाए जा सकते हैं और उनके Starlight परियोजना के साथ यह सब विशेषताएं सामने से उपलब्ध हैं आपके लिए + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + Astro की आधिकारिक स्टार्टर किट Starlight दस्तावेज़ीकरण वेबसाइट बनाने के लिए वास्तव में एक अविश्वसनीय उपकरण है + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + Starlight एक बेहतरीन DX का हमारा पसंदीदा उदाहरण है: गति, सुविधा और विस्तार पर ध्यान प्रेरणादायक है। यह प्रौद्योगिकी और दिखाव का ख्याल रखता है, ताकि आप अपनी सामग्री पर ध्यान केंद्रित कर सकें 👏 + + StackBlitz टीम को यह बिल्कुल पसंद है! + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + Starlight मेरे लिए गेम-चेंजर रही है, जिससे मुझे सामग्री निर्माण पर ध्यान केंद्रित करने का मौका मिला है। + + इसका सहज डिज़ाइन न केवल मेरे कार्य प्रवाह को सुव्यवस्थित करता है बल्कि ओपन-स्त्रोत डेवलपर्स के लिए ज्ञानप्राप्ति समय को भी कम करता है। + + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + Course Builder दस्तावेज़ के लिए Starlight के साथ कुछ और समय बिताया और यह अब तक बहुत अच्छा रहा है। बहुत सारे अच्छे स्पर्श और Markdown में लिखने पर ध्यान केंद्रित किया जा सकता है न कि साइट के साथ खिलवाड़ करने पर। + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + मेने Starlight के साथ खेलना शुरू किया. कहना होगा कि मैं इसके हटकर प्रदर्शन से बहुत प्रभावित हूं। + + 💯💯💯💯 + + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + Astro की शक्ति और गति और Starlight के टूलींग के बीच, दस्तावेज़ीकरण के साथ शुरुआत करने के लिए Starlight सबसे अच्छा तरीका है, यह स्वर्ग में एक जोड़ी है। + + पिछले कुछ समय से में यहाँ जा रहा हु और मुझे यह बहुत पसंद है! + + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + मैंने अपने आखिरी नौकरी में Starlight का उपयोग किया और मुझे यह बहुत पसंद आया। बेहतरीन अवयव, सहज ज्ञान युक्त डिजाइन और अति संवेदनशील समुदाय (जब भी किसी को कुछ चाहिए होता है, तो वे इसे तुरंत भेज देंगे या आपको समाधान बताएंगे)। बहुत ही सुखद अनुभव। + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + Starlight की बदौलत मेरी मोनोरेपो साइट के दस्तावेज़ पहले से कहीं बेहतर दिखते हैं। Astro की सारी शक्ति खोए बिना इसका उपयोग करना बेहद आसान है। इस पर काम करने के लिए धन्यवाद! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + दस्तावेज़ीकरण के लिए Starlight मेरा पसंदीदा उपकरण है। इससे मेरी मौजूदा Astro उत्पाद वेबसाइट पर दस्तावेज़ जोड़ना बहुत आसान हो गया, बजाय किसी अन्य टूल के साथ उपयोग करने के लिए उपडोमेन की आवश्यकता होती है। + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + मैं WPEngine Atlas Platform दस्तावेज़ों का पुनर्निर्माण कर रहा हूँ। जब मैं कहता हूं कि Starlight में वह सब कुछ है जो आपको A+ दस्तावेज़ प्लेटफॉर्म बनाने के लिए चाहिए, तो मुझ पर विश्वास करें 🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + Starlight को आज़माएं! + + हम इसे अपनी कुछ साइटों के लिए उपयोग करते हैं और यह बहुत बढ़िया है। + + </Testimonial> +</TestimonialGrid> + +<AboutAstro title="आप तक लाने वाले हैं"> +Astro गति के लिए डिज़ाइन किया गया ऑल-इन-वन वेब फ्रेमवर्क है। +अपने कंटेंट को कहीं से भी खींचें और हर जगह डिप्लॉय करें, यह सब आपके पसंदीदा UI अवयवों और लाइब्रेरीज़ द्वारा संचालित है। + +[Astro के बारे में जानें](https://astro.build/) + +</AboutAstro> diff --git a/docs/src/content/docs/id/404.md b/docs/src/content/docs/id/404.md index 3889b618876..a0affebc9b3 100644 --- a/docs/src/content/docs/id/404.md +++ b/docs/src/content/docs/id/404.md @@ -2,6 +2,7 @@ title: Halaman tidak ditemukan template: splash editUrl: false +lastUpdated: false hero: title: '404' tagline: <strong>Houston, kita ada masalah.</strong> Halaman yang kita cari tidak ada.<br>Tolong cek kolom URL atau gunakan fitur pencarian. diff --git a/docs/src/content/docs/id/environmental-impact.md b/docs/src/content/docs/id/environmental-impact.md new file mode 100644 index 00000000000..46bd7fce68f --- /dev/null +++ b/docs/src/content/docs/id/environmental-impact.md @@ -0,0 +1,137 @@ +--- +title: Dokumentasi yang ramah lingkungan +description: Pelajari bagaimana Starlight bisa membantu Anda membangun website dokumentasi yang lebih ramah lingkungan dan mengurangi jejak karbon Anda. +--- + +Estimasi dampak dari industri web terhadap iklim berkisar antara [2%][sf] hingga [4% dari emisi karbon global ][bbc], kira-kira setara dengan emisi industri penerbangan. Ada banyak faktor kompleks dalam menghitung dampak ekologis sebuah website, namun panduan ini mencakup beberapa tips untuk mengurangi jejak lingkungan dari website dokumentasi Anda. + +Berita baiknya adalah, memilih Starlight adalah awal yang baik. Menurut Website Carbon Calculator, website ini [lebih bersih daripada 99% website-website yang telah diuji][sl-carbon], menghasilkan 0,01g CO₂ per kunjungan halaman. + +## Berat halaman + +Semakin banyak data yang ditransfer oleh sebuah halaman web, semakin banyak sumber daya energi yang diperlukan. +Pada bulan April 2023, nilai median dari banyaknya data yang harus di-_download_ user ketika mengakses sebuah halaman website adalah lebih dari 2.000 KB berdasarkan [data dari HTTP Archive][http]. + +Starlight membangun halaman-halaman yang seringan mungkin. Sebagai contoh, pada kunjungan pertama, pengguna hanya perlu mengunduh kurang dari 50 KB data yang telah dikompresi — hanya 2,5% dari nilai median HTTP Archive. Dengan strategi caching yang baik, kunjungan selanjutnya dapat mengunduh hanya sekitar 10 KB. + +### Gambar + +Meskipun Starlight memberikan basis yang baik, gambar yang Anda tambahkan ke halaman dokumentasi Anda dapat dengan cepat meningkatkan berat halaman Anda. +Starlight menggunakan [dukungan aset yang dioptimalkan][assets] dari Astro untuk mengoptimalkan gambar lokal dalam file Markdown dan MDX Anda. + +### Komponen UI + +Komponen yang dibangun dengan _UI frameworks_ seperti React atau Vue dapat dengan mudah menambahkan banyak JavaScript ke halaman. +Karena Starlight dibangun di atas Astro, komponen seperti ini secara default tidak memuat JavaScript di sisi klien berkat [Astro Islands][islands]. + +### Caching + +_Caching_ digunakan untuk mengontrol berapa lama browser menyimpan dan menggunakan kembali data yang telah diunduh sebelumnya. +Strategi caching yang baik memastikan bahwa pengguna mendapatkan konten baru sesegera mungkin ketika ada perubahan, tetapi juga menghindari pengunduhan yang tidak perlu dari konten yang sama berulang kali ketika konten tersebut tidak mengalami perubahan. + +Cara paling umum untuk mengonfigurasi caching adalah dengan menggunakan [`Cache-Control` HTTP header][cache]. +Ketika menggunakan Starlight, Anda dapat mengatur waktu _cache_ yang lama untuk semua yang ada di direktori /\_astro/. +Direktori ini berisi CSS, JavaScript, dan aset lainnya yang dapat di-cache secara permanen, mengurangi pengunduhan yang tidak perlu: + +``` +Cache-Control: public, max-age=604800, immutable +``` + +Cara mengkonfigurasi caching tergantung pada penyedia hosting website Anda. Misalnya, Vercel menerapkan strategi caching ini untuk Anda tanpa ada konfigurasi yang diperlukan, sementara Anda dapat mengatur [header kustom untuk Netlify][ntl-headers] dengan menambahkan file `public/_headers` ke proyek Anda: + +``` +/_astro/* + Cache-Control: public + Cache-Control: max-age=604800 + Cache-Control: immutable +``` + +[cache]: https://csswizardry.com/2019/03/cache-control-for-civilians/ +[ntl-headers]: https://docs.netlify.com/routing/headers/ + +## Konsumsi daya + +Cara sebuah halaman web dibangun dapat mempengaruhi besarnya daya yang dibutuhkan untuk menjalankannya di perangkat pengguna. +Dengan menggunakan JavaScript yang minimal, Starlight mengurangi jumlah daya pemrosesan yang dibutuhkan oleh telepon, tablet, atau komputer pengguna untuk memuat dan merender halaman. + +Perhatikan saat menambahkan fitur seperti skrip pelacakan analitik atau konten yang kaya akan JavaScript seperti video yang disematkan, karena hal ini dapat meningkatkan penggunaan daya halaman. +Jika Anda memerlukan analitik, pertimbangkan untuk memilih opsi yang lebih ringan seperti [Cabin][cabin], [Fathom][fathom], atau [Plausible][plausible]. +Penyisipan video seperti YouTube dan Vimeo dapat ditingkatkan dengan menunggu [pemuatan video saat ada interaksi pengguna][lazy-video]. +_Package_ seperti [astro-embed][embed] dapat membantu untuk layanan umum. + +:::tip[Tahukah Anda?] +_Parsing_ dan kompilasi JavaScript adalah salah satu tugas yang paling mahal bagi browser. +Dibandingkan dengan merender gambar JPEG dengan ukuran yang sama, [pemrosesan JavaScript dapat memakan waktu lebih dari 30 kali lebih lama][cost-of-js]. +::: + +[cabin]: https://withcabin.com/ +[fathom]: https://usefathom.com/ +[plausible]: https://plausible.io/ +[lazy-video]: https://web.dev/iframe-lazy-loading/ +[embed]: https://www.npmjs.com/package/astro-embed +[cost-of-js]: https://medium.com/dev-channel/the-cost-of-javascript-84009f51e99e + +## Hosting + +Dimana website di-_hosting_ dapat memiliki dampak besar terhadap seberapa ramah lingkungan website dokumentasi Anda. +Pusat data dan rumah server dapat memiliki dampak ekologis yang besar, termasuk konsumsi listrik yang tinggi dan penggunaan air yang intensif. + +Memilih penyedia hosting yang menggunakan energi terbarukan berarti emisi karbon yang lebih rendah untuk website Anda. [Green Web Directory][gwb] adalah salah satu alat yang dapat membantu Anda menemukan perusahaan hosting yang ramah lingkungan. + +[gwb]: https://www.thegreenwebfoundation.org/directory/ + +## Perbandingan + +Tertarik bagaimana perbandingannya dengan _framework_ dokumentasi lainnya? Tes ini dengan [Website Carbon Calculator][wcc] membandingkan halaman-halaman serupa yang dibangun dengan _tool_ yang berbeda. + +| Framework | CO₂ per kunjungan halaman | Peringkat | +| --------------------------- | ------------------------- | :-------: | +| [Starlight][sl-carbon] | 0.01g | A+ | +| [Read the Docs][rtd-carbon] | 0.05g | A+ | +| [Sphinx][sx-carbon] | 0.06g | A+ | +| [VitePress][vp-carbon] | 0.07g | A+ | +| [Docus][dc-carbon] | 0.09g | A+ | +| [docsify][dy-carbon] | 0.10g | A | +| [Nextra][nx-carbon] | 0.11g | A | +| [MkDocs][mk-carbon] | 0.19g | B | +| [Docusaurus][ds-carbon] | 0.21g | B | +| [GitBook][gb-carbon] | 0.43g | C | +| [Mintlify][mt-carbon] | 1.22g | F | + +<small>Data dikumpulkan pada 22 Juli 2024. Klik link untuk melihat angka terkini.</small> + +[sl-carbon]: https://www.websitecarbon.com/website/starlight-astro-build-getting-started/ +[vp-carbon]: https://www.websitecarbon.com/website/vitepress-dev-guide-what-is-vitepress/ +[dc-carbon]: https://www.websitecarbon.com/website/docus-dev-introduction-getting-started/ +[sx-carbon]: https://www.websitecarbon.com/website/sphinx-doc-org-en-master-usage-quickstart-html/ +[mk-carbon]: https://www.websitecarbon.com/website/mkdocs-org-getting-started/ +[nx-carbon]: https://www.websitecarbon.com/website/nextra-site-docs-docs-theme-start/ +[dy-carbon]: https://www.websitecarbon.com/website/docsify-js-org/ +[ds-carbon]: https://www.websitecarbon.com/website/docusaurus-io-docs/ +[rtd-carbon]: https://www.websitecarbon.com/website/docs-readthedocs-io-en-stable-index-html/ +[gb-carbon]: https://www.websitecarbon.com/website/docs-gitbook-com/ +[mt-carbon]: https://www.websitecarbon.com/website/mintlify-com-docs-quickstart/ + +## Sumber Tambahan + +### Tools + +- [Website Carbon Calculator][wcc] +- [GreenFrame](https://greenframe.io/) +- [Ecograder](https://ecograder.com/) +- [WebPageTest Carbon Control](https://www.webpagetest.org/carbon-control/) +- [Ecoping](https://ecoping.earth/) + +### Articles and presentasi + +- [“Building a greener web”](https://youtu.be/EfPoOt7T5lg), talk by Michelle Barker +- [“Sustainable Web Development Strategies Within An Organization”](https://www.smashingmagazine.com/2022/10/sustainable-web-development-strategies-organization/), article by Michelle Barker +- [“A sustainable web for everyone”](https://2021.stateofthebrowser.com/speakers/tom-greenwood/), talk by Tom Greenwood +- [“How Web Content Can Affect Power Usage”](https://webkit.org/blog/8970/how-web-content-can-affect-power-usage/), article by Benjamin Poulain and Simon Fraser + +[sf]: https://www.sciencefocus.com/science/what-is-the-carbon-footprint-of-the-internet/ +[bbc]: https://www.bbc.com/future/article/20200305-why-your-internet-habits-are-not-as-clean-as-you-think +[http]: https://httparchive.org/reports/state-of-the-web +[assets]: https://docs.astro.build/en/guides/assets/ +[islands]: https://docs.astro.build/en/concepts/islands/ +[wcc]: https://www.websitecarbon.com/ diff --git a/docs/src/content/docs/id/getting-started.mdx b/docs/src/content/docs/id/getting-started.mdx index 45b53ce181b..f1a45cb6509 100644 --- a/docs/src/content/docs/id/getting-started.mdx +++ b/docs/src/content/docs/id/getting-started.mdx @@ -1,21 +1,24 @@ --- title: Memulai -description: Pelajari cara membuat situs dokumentasi baru Anda dengan Starlight oleh Astro. +description: Pelajari cara membuat website dokumentasi baru Anda dengan Starlight oleh Astro. --- import { Tabs, TabItem } from '@astrojs/starlight/components'; -## Membuat Proyek Baru +Starlight adalah tema dokumentasi berfitur lengkap yang dibangun di atas _framework_ [Astro](https://astro.build). +Panduan ini akan membantu Anda memulai proyek baru. +Lihat [petunjuk penyiapan manual](/id/manual-setup/) untuk menambahkan Starlight ke proyek Astro yang sudah ada. -Starlight adalah tema dokumentasi berfitur lengkap berbasis [Astro](https://astro.build). +## Mulai Cepat -Anda dapat membuat proyek Astro + Starlight baru menggunakan perintah berikut ini: +### Membuat proyek baru + +Buat proyek Astro + Starlight baru dengan menjalankan perintah berikut di terminal Anda: <Tabs> <TabItem label="npm"> ```sh -# membuat proyek baru dengan npm npm create astro@latest -- --template starlight ``` @@ -23,7 +26,6 @@ npm create astro@latest -- --template starlight <TabItem label="pnpm"> ```sh -# membuat proyek baru dengan pnpm pnpm create astro --template starlight ``` @@ -31,69 +33,80 @@ pnpm create astro --template starlight <TabItem label="Yarn"> ```sh -# membuat proyek baru dengan yarn yarn create astro --template starlight ``` </TabItem> </Tabs> -Perintah tersebut akan membuat [direktori proyek](/guides/project-structure/) baru beserta seluruh file dan konfigurasi untuk situs Anda. +Perintah tersebut akan membuat [direktori proyek](/id/guides/project-structure/) baru berisikan seluruh file dan konfigurasi yang diperlukan untuk website Anda. -:::tip[Coba dulu] -Cobalah Starlight di browser: +:::tip[Lihat itu beraksi] +Cobalah Starlight di browser Anda: [buka dengan StackBlitz](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). ::: -## Membuat konten dengan Starlight +### Mulai server pengembangan -Starlight sudah siap untuk ditambahkan konten baru, atau pindahkan konten lama Anda! +Ketika bekerja secara lokal, [server pengembangan Astro](https://docs.astro.build/en/reference/cli-reference/#astro-dev) memungkinkan Anda melihat pratinjau pekerjaan Anda dan secara otomatis me-_refresh_ peramban ketika Anda membuat perubahan. -### Format file +Di dalam direktori proyek Anda, jalankan perintah berikut untuk memulai server pengembangan: -Starlight mendukung pembuatan konten dalam Markdown and MDX. (Tambahkan dukungan Markdoc dengan menginstall integrasi eksperimental [Astro Markdoc](https://docs.astro.build/en/guides/integrations-guide/markdoc/).) +<Tabs> +<TabItem label="npm"> -### Tambah halaman baru +```sh +npm run dev +``` -Tambah halaman baru dengan cara membuat file `.md` or `.mdx` di `src/content/docs/`. Tambahkan folder untuk mengorganisasikan konten Anda, dan membuat segmen _path_ bertingkat: +</TabItem> +<TabItem label="pnpm"> +```sh +pnpm dev ``` -src/content/docs/hello-world.md => your-site.com/hello-world -src/content/docs/guides/faq.md => your-site.com/guides/faq + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev ``` -### _Frontmatter_ dengan _type-safety_ yang aman +</TabItem> +</Tabs> + +Ini akan mencatat pesan ke terminal Anda dengan URL pratinjau lokal Anda. +Buka URL tersebut untuk mulai menjelajahi situs Anda. -Semua halaman Starlight terdiri dari [properti _frontmatter_ umum](/id/reference/frontmatter/) yang dapat dikostumisasi untuk mengontrol tampilan setiap halaman: +### Tambahkan konten -```md ---- -title: Hello, World! -description: This is a page in my Starlight-powered site ---- -``` +Starlight siap untuk ditambahkan konten baru, atau pindahkan konten Anda yang sudah ada! -Jika ada properti yang terlewat, Starlight akan memberitahu Anda. +Tambahkan halaman baru ke website anda dengan membuat file Markdown di direktori `src/content/docs/`. -## _Deploy_ situs Starlight Anda +Baca selengkapnya tentang perutean berbasis file serta dukungan untuk MDX dan Markdoc di panduan [“Halaman”](/id/guides/pages/). -Setelah Anda membuat dan mengkostumisasi situs Starlight anda, anda dapat men-_deploy_ situs anda ke web server atau platform hosting pilihan Anda, termasuk Netlify, Vercel, GitHub Pages dan lain sebagainya. +### Langkah selanjutnya -[Pelajari cara men-_deploy_ situs Astro di dokumentasi Astro.](https://docs.astro.build/en/guides/deploy/) +- **Mengkonfigurasi:** Pelajari tentang opsi umum dalam ["Menyesuaikan Starlight”](/id/guides/customization/). +- **Navigasi:** Siapkan sidebar Anda dengan panduan ["Navigasi Sidebar”](/id/guides/sidebar/). +- **Komponen:** Temukan kartu, tab dan bawaan lainnya di dalam panduan ["Komponen”](/id/components/using-components/). +- **Sebarkan:** Publikasikan karya Anda dengan panduan [“_Deploy_ situs Anda”](https://docs.astro.build/en/guides/deploy/) di dokumentasi Astro. -## Memperbaharui Starlight +## Memperbarui Starlight :::tip -Karena Starlight masih berstatus beta, akan ada pembaruan dan peningkatan yang cukup sering. Pastikan Anda selalu memperbaharui Starlight secara rutin! +Karena Starlight adalah perangkat lunak beta, akan ada pembaruan dan peningkatan yang sering dilakukan. +Pastikan untuk memperbarui Starlight secara teratur! ::: -Starlight adalah integrasi Astro, dan cara memperbaharuinya sama seperti integrasi `@astrojs/*` yang lain: +Starlight adalah integrasi Astro, dan diperbarui seperti integrasi `@astrojs/*` lainnya: <Tabs> <TabItem label="npm"> ```sh -# memperbaharui Starlight dengan npm npm install @astrojs/starlight@latest ``` @@ -101,7 +114,6 @@ npm install @astrojs/starlight@latest <TabItem label="pnpm"> ```sh -# memperbaharui Starlight dengan pnpm pnpm upgrade @astrojs/starlight --latest ``` @@ -109,21 +121,20 @@ pnpm upgrade @astrojs/starlight --latest <TabItem label="Yarn"> ```sh -# memperbaharui Starlight dengan yarn yarn upgrade @astrojs/starlight --latest ``` </TabItem> </Tabs> -Anda dapat membaca semua histori pembaruan Starlight dalam setiap rilis di [_changelog_](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md). - -## Menyelesaikan masalah pada Starlight +Lihat [_changelog_ Starlight](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md) untuk daftar lengkap perubahan yang dibuat dalam setiap rilis. -[Konfigurasi proyek](/id/reference/configuration/) dan [konfigurasi _frontmatter_](/id/reference/frontmatter/) tersedia di bagian Referensi pada situs ini. Rujuklah halaman tersebut untuk memastikan situs Starlight anda terkonfigurasi dengan benar dan berfungsi dengan baik. +## Troubleshooting Starlight -Anda juga dapat merujuk kepada panduan di _sidebar_ untuk membantu Anda dalam menambah konten dan mengkustomisasi situs Starlight anda. +Gunakan [konfigurasi proyek](/id/reference/configuration/) dan halaman referensi [konfigurasi _frontmatter_ halaman individual](/id/reference/frontmatter/) untuk memastikan bahwa situs Starlight Anda telah dikonfigurasi dan berfungsi dengan baik. +Lihat panduan di _sidebar_ untuk bantuan menambahkan konten dan menyesuaikan situs Starlight Anda. -Jika Anda tidak menemukan jawaban di dokumentasi ini, silahkan merujuk kepada [dokumentasi lengkap Astro](https://docs.astro.build). Pertanyaan Anda biasanya akan terjawab dengan memahami bagaimana umumnya Astro bekerja, sebagai basis dari Starlight. +Jika jawaban Anda tidak dapat ditemukan dalam dokumentasi ini, silakan kunjungi [Dokumentasi Astro](https://docs.astro.build) untuk dokumentasi lengkap Astro. +Pertanyaan Anda mungkin terjawab dengan memahami cara kerja Astro secara umum, di bawah tema Starlight ini. -Anda juga dapat merujuk kepada [isu-isu yang diketahui di GitHub](https://github.com/withastro/starlight/issues), dan mendapatka bantuan melalui [Astro Discord](https://astro.build/chat/) oleh komunitas kami yang ramah dan sangat aktif! Silahkan bertanya di forum `#support` menggunakan tag "starlight" tag, atau kunjungi channel `#starlight` untuk mendiskusikan pengembangan Starlight, dan lain-lain! +Anda juga dapat memeriksa masalah Starlight yang diketahui di [GitHub](https://github.com/withastro/starlight/issues), dan dapatkan bantuan di [Astro Discord](https://astro.build/chat/) dari komunitas kami yang aktif dan ramah! Kirimkan pertanyaan di forum `#support` kami dengan tag "starlight", atau kunjungi kanal `#starlight` khusus kami untuk mendiskusikan perkembangan terkini dan banyak lagi! diff --git a/docs/src/content/docs/id/index.mdx b/docs/src/content/docs/id/index.mdx index c75ef9d0dd1..7edcbe7f57b 100644 --- a/docs/src/content/docs/id/index.mdx +++ b/docs/src/content/docs/id/index.mdx @@ -1,42 +1,40 @@ --- -title: Starlight 🌟 Wujudkan situs dokumentasi dengan Astro -description: Starlight membantu mewujudkan situs web dokumentasi yang menawan dan berperforma tinggi dengan Astro. +title: Starlight 🌟 Membangun website dokumentasi dengan Astro +head: + - tag: title + content: Starlight 🌟 Membangun website dokumentasi dengan Astro +description: Starlight membantu membangun website dokumentasi yang menawan dan berperforma tinggi dengan Astro. template: splash -banner: - content: | - <span class="ph-banner"> - <span class="ph-houston"><img src="/ph-houston.svg" alt="" width="72" height="72"/></span> - <span class="ph-text"> - <strong>Halo Product Hunters 👋</strong> - <a href="https://www.producthunt.com/posts/starlight-by-astro">Kami sedang live sekarang!</a> - </span> - </span> +editUrl: false +lastUpdated: false hero: title: Buat dokumentasi yang bersinar dengan Starlight - tagline: Semua yang Anda butuhkan untuk mewujudkan situs dokumentasi yang luar biasa. Cepat, ramah pengguna, dan sangat mudah digunakan. + tagline: Semua yang Anda butuhkan untuk membangun website dokumentasi yang luar biasa. Cepat, ramah pengguna, dan sangat mudah digunakan. image: - file: ../../../assets/hero-star.webp + file: ~/assets/hero-star.webp actions: - text: Memulai icon: right-arrow - variant: primary link: /id/getting-started/ - text: Lihat di GitHub icon: external + variant: minimal link: https://github.com/withastro/starlight --- import { CardGrid, Card } from '@astrojs/starlight/components'; -import AboutAstro from '../../../components/about-astro.astro'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; <CardGrid stagger> <Card title="Dokumentasi yang menawan" icon="open-book"> - Sudah termasuk: Navigasi situs, pencarian, terjemahan, SEO, tipografi yang + Sudah termasuk: Navigasi website, pencarian, terjemahan, SEO, tipografi yang mudah dibaca, _code highlighting_, mode gelap, dan masih banyak lagi. </Card> - <Card title="Ditenagai oleh Astro" icon="rocket"> + <Card title="Berbasis Astro" icon="rocket"> Manfaatkan kekuatan penuh dan performa Astro. Kembangkan Starlight dengan - pustaka dan integrasi Astro favorit Anda. + _library_ dan integrasi Astro favorit Anda. </Card> <Card title="Markdown, Markdoc, and MDX" icon="document"> Gunakan bahasa markup favorit Anda. Starlight menyediakan validasi @@ -48,10 +46,118 @@ import AboutAstro from '../../../components/about-astro.astro'; </Card> </CardGrid> +<TestimonialGrid title="Apa yang orang katakan"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + Tim Astro telah MERUBAH cara pembuatan dokumentasi dan Anda bisa mendapatkan semuanya langsung dengan proyek Starlight mereka. + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + Astros _starter kit_ resmi Starlight adalah alat yang benar-benar luar biasa untuk membangun situs web dokumentasi + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + Starlight adalah contoh terbaik DX yang hebat: kecepatan, kenyamanan, dan + perhatian terhadap detailnya sangat menginspirasi. Ia memperhatikan teknologi dan tampilan, + sehingga Anda dapat fokus pada konten Anda 👏 + + Tim StackBlitz sangat menyukainya! + + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + Starlight telah mengubah permainan bagi saya, memungkinkan saya untuk fokus pada pembuatan konten. + + Desainnya yang intuitif tidak hanya menyederhanakan alur kerja saya tetapi juga mengurangi waktu orientasi bagi pengembang _open-source_. + + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + Menghabiskan lebih banyak waktu dengan Starlight untuk dokumentasi Course Builder dan sejauh ini hasilnya sangat bagus. Banyak sentuhan yang bagus dan dapat fokus menulis dalam Markdown dan tidak mengutak-atik situs. + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + Mulai bermain dengan Starlight. Harus saya akui saya sangat terkesan dengan kinerjanya saat pertama kali digunakan. + + 💯💯💯💯 + + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + Starlight adalah cara terbaik untuk memulai dokumentasi, antara + kekuatan dan kecepatan Astro, dan fitur dari Starlight, ini adalah pilihan yang + tepat. + + Ini telah menjadi pilihan saya untuk beberapa waktu sekarang, dan saya terus menyukainya! + + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + Saya menggunakan Starlight pada pekerjaan terakhir saya dan menyukainya. Komponen yang hebat, + desain yang intuitif, dan komunitas yang sangat responsif (kapan pun seseorang membutuhkan sesuatu, + mereka akan segera mengirimkannya atau memberi tahu Anda solusinya). Pengalaman yang sangat menyenangkan. + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + Dokumen di situs monorepo saya terlihat lebih baik dari sebelumnya berkat Starlight. Sangat mudah digunakan tanpa kehilangan semua kelebihan Astro. Terima kasih telah mengerjakannya! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + Starlight adalah alat andalan saya untuk dokumentasi. Alat ini memudahkan saya menambahkan dokumen ke situs web produk Astro saya yang sudah ada, dibanding menggunakan subdomain untuk digunakan dengan alat lain. + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + Saya sedang membangun kembali dokumentasi WPEngine Atlas Platform. Percayalah ketika saya mengatakan Starlight memiliki semua yang Anda butuhkan untuk membuat platform dokumentasi A+ 🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + Cobalah Starlight! + + Saya menggunakannya untuk beberapa situs saya dan hasilnya bagus. + + </Testimonial> +</TestimonialGrid> + <AboutAstro title="Dipersembahkan oleh"> -Astro adalah _framework_ web serbaguna didesain untuk web yang cepat. +Astro adalah _web framework_ serbaguna yang didesain untuk kecepatan. Gunakan konten Anda dari sumber mana saja dan _deploy_ di mana saja, -semua ditenagai dengan pustaka dan komponen UI favorit Anda. +semuanya didukung oleh _library_ dan komponen UI favorit Anda. [Pelajari tentang Astro](https://astro.build/) diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index 6545ca7ad5b..d1dee8feeea 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -1,33 +1,31 @@ --- title: Starlight 🌟 Build documentation sites with Astro +head: + - tag: title + content: Starlight 🌟 Build documentation sites with Astro description: Starlight helps you build beautiful, high-performance documentation websites with Astro. template: splash -banner: - content: | - <span class="ph-banner"> - <span class="ph-houston"><img src="/ph-houston.svg" alt="" width="72" height="72"/></span> - <span class="ph-text"> - <strong>Welcome Product Hunters 👋</strong> - <a href="https://www.producthunt.com/posts/starlight-by-astro">We are live right now!</a> - </span> - </span> +editUrl: false +lastUpdated: false hero: title: Make your docs shine with Starlight tagline: Everything you need to build a stellar documentation website. Fast, accessible, and easy-to-use. image: - file: ../../assets/hero-star.webp + file: ~/assets/hero-star.webp actions: - text: Get started icon: right-arrow - variant: primary link: /getting-started/ - text: View on GitHub icon: external + variant: minimal link: https://github.com/withastro/starlight --- import { CardGrid, Card } from '@astrojs/starlight/components'; -import AboutAstro from '../../components/about-astro.astro'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; <CardGrid stagger> <Card title="Documentation that delights" icon="open-book"> @@ -48,6 +46,114 @@ import AboutAstro from '../../components/about-astro.astro'; </Card> </CardGrid> +<TestimonialGrid title="What people are saying"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + The Astro team have EVOLVED how docs can be done and you can get it all out of the box with their Starlight project. + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + Astro’s official starter kit Starlight is a truly incredible tool for building a documentation website + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + Starlight is our go-to example of a great DX: the speed, convenience, and + attention to details is inspiring. It takes care of the tech and the looks, + so you can focus on your content 👏 + + StackBlitz team absolutely loves it! + + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + Starlight has been a game-changer for me, allowing me to focus on content creation. + + Its intuitive design not only streamlines my workflow but also reduces onboarding time for open-source developers. + + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + Spent some more time with Starlight for the Course Builder docs and it’s been great so far. Lots of nice touches and can focus on writing in Markdown and not fiddling with the site. + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + Started playing with Starlight. Gotta say I’m very impressed with the performance out of the box. + + 💯💯💯💯 + + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + Starlight is the best way to get started with documentation, between the + power and speed of Astro, and the tooling from Starlight, it’s a match in + heaven. + + It has been my go to for a while now, and I keep on loving it! + + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + I used Starlight in my last job and loved it. Great components, intuitive + design, and super-responsive community (whenever anyone needed something, + they’d ship it soonish or tell you a workaround). Very pleasant experience. + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + The docs on my monorepo site look better than ever thanks to Starlight. It’s extremely easy to use without losing all the power of Astro. Thank you for working on it! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + Starlight is my go-to tool for documentation. It made it super easy to add docs to my existing Astro product website, vs needing a subdomain to use with another tool. + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + I’ve been rebuilding the WPEngine Atlas Platform docs. Trust me when I say Starlight has everything you need to make an A+ docs platform 🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + Give Starlight a try! + + I use it for a few of my sites and it’s great. + + </Testimonial> +</TestimonialGrid> + <AboutAstro title="Brought to you by"> Astro is the all-in-one web framework designed for speed. Pull your content from anywhere and deploy everywhere, all powered by your favorite UI components and libraries. diff --git a/docs/src/content/docs/it/404.md b/docs/src/content/docs/it/404.md index 9129fe113b6..600702c3c25 100644 --- a/docs/src/content/docs/it/404.md +++ b/docs/src/content/docs/it/404.md @@ -2,6 +2,7 @@ title: Non trovato template: splash editUrl: false +lastUpdated: false hero: title: '404' tagline: <strong>Houston, abbiamo un problema.</strong> Non siamo riusciti a trovare quella pagina.<br>Controlla l'URL o prova a utilizzare la barra di ricerca. diff --git a/docs/src/content/docs/it/environmental-impact.md b/docs/src/content/docs/it/environmental-impact.md index 5cd0964146c..3995855e190 100644 --- a/docs/src/content/docs/it/environmental-impact.md +++ b/docs/src/content/docs/it/environmental-impact.md @@ -89,20 +89,21 @@ Scegliere un host che usi energia da fonti rinnovabili significa ridurre le emis Curioso di come altri framework per documentazioni si comparano? Questi test eseguiti con [Website Carbon Calculator][wcc] confrontano pagine simili costruite con diversi framework. -| Framework | CO₂ per visita | -| --------------------------- | -------------- | -| [Starlight][sl-carbon] | 0,01 g | -| [VitePress][vp-carbon] | 0,05 g | -| [Docus][dc-carbon] | 0,05 g | -| [Sphinx][sx-carbon] | 0,07 g | -| [MkDocs][mk-carbon] | 0,10 g | -| [Nextra][nx-carbon] | 0,11 g | -| [docsify][dy-carbon] | 0,11 g | -| [Docusaurus][ds-carbon] | 0,24 g | -| [Read the Docs][rtd-carbon] | 0,24 g | -| [GitBook][gb-carbon] | 0,71 g | - -<small>Dati collezionati il 14 Maggio 2023. Clicca i link per vedere i dati aggiornati.</small> +| Framework | CO₂ per visita | Voto | +| --------------------------- | -------------- | :--: | +| [Starlight][sl-carbon] | 0.01g | A+ | +| [Read the Docs][rtd-carbon] | 0.05g | A+ | +| [Sphinx][sx-carbon] | 0.06g | A+ | +| [VitePress][vp-carbon] | 0.07g | A+ | +| [Docus][dc-carbon] | 0.09g | A+ | +| [docsify][dy-carbon] | 0.10g | A | +| [Nextra][nx-carbon] | 0.11g | A | +| [MkDocs][mk-carbon] | 0.19g | B | +| [Docusaurus][ds-carbon] | 0.21g | B | +| [GitBook][gb-carbon] | 0.43g | C | +| [Mintlify][mt-carbon] | 1.22g | F | + +<small>Dati collezionati il 22 Luglio 2024. Clicca i link per vedere i dati aggiornati.</small> [sl-carbon]: https://www.websitecarbon.com/website/starlight-astro-build-getting-started/ [vp-carbon]: https://www.websitecarbon.com/website/vitepress-dev-guide-what-is-vitepress/ @@ -114,6 +115,7 @@ Questi test eseguiti con [Website Carbon Calculator][wcc] confrontano pagine sim [ds-carbon]: https://www.websitecarbon.com/website/docusaurus-io-docs/ [rtd-carbon]: https://www.websitecarbon.com/website/docs-readthedocs-io-en-stable-index-html/ [gb-carbon]: https://www.websitecarbon.com/website/docs-gitbook-com/ +[mt-carbon]: https://www.websitecarbon.com/website/mintlify-com-docs-quickstart/ ## Altre risorse diff --git a/docs/src/content/docs/it/getting-started.mdx b/docs/src/content/docs/it/getting-started.mdx index 49feb43e56f..2eab7a4f3bb 100644 --- a/docs/src/content/docs/it/getting-started.mdx +++ b/docs/src/content/docs/it/getting-started.mdx @@ -1,21 +1,24 @@ --- -title: Iniziamo -description: Impara come iniziare a costruire il tuo prossimo sito per documentazione con Starlight per Astro. +title: Come iniziare +description: Scopri come iniziare a costruire il tuo prossimo sito di documentazione con Starlight di Astro. --- import { Tabs, TabItem } from '@astrojs/starlight/components'; -## Creare un nuovo progetto +Starlight è un tema di documentazione completo di funzionalità costruito sulla base del framework [Astro](https://astro.build/it/). +Questa guida ti aiuterà a iniziare con un nuovo progetto. +Consulta le [istruzioni di configurazione manuale](/it/manual-setup/) per aggiungere Starlight a un progetto Astro esistente. -Starlight è un tema per documentazione completo di funzionalità costruito su [Astro](https://astro.build). +## Avvio Rapido -Puoi creare un nuovo progetto Astro + Starlight usando il comando: +### Crea un nuovo progetto -<Tabs> +Crea un nuovo progetto Astro + Starlight eseguendo il seguente comando nel tuo terminale: + +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# crea un nuovo progetto con npm npm create astro@latest -- --template starlight ``` @@ -23,7 +26,6 @@ npm create astro@latest -- --template starlight <TabItem label="pnpm"> ```sh -# crea un nuovo progetto con pnpm pnpm create astro --template starlight ``` @@ -31,99 +33,108 @@ pnpm create astro --template starlight <TabItem label="Yarn"> ```sh -# crea un nuovo progetto con yarn yarn create astro --template starlight ``` </TabItem> </Tabs> -Questo creerà una nuova [cartella del progetto](/it/guides/project-structure/) con tutti i file e configurazioni necessarie per il tuo sito. +Questo creerà una nuova [directory di progetto](/it/guides/project-structure/) con tutti i file e le configurazioni necessari per il tuo sito. -:::tip[Guardalo in azione] -Prova Starlight nel browser: -[apri il template su StackBlitz](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). +:::tip[Vedilo in azione] +Prova Starlight nel tuo browser: +[apri il modello su StackBlitz](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). ::: -## Creare contenuti con Starlight +### Avvia il server di sviluppo -Starlight è pronto per aggiungere nuovi contenuti, compresi i tuoi file! +Quando lavori in locale, il [server di sviluppo di Astro](https://docs.astro.build/it/reference/cli-reference/#astro-dev) ti consente di visualizzare in anteprima il tuo lavoro e aggiorna automaticamente il browser quando apporti modifiche. -### Formati dei file +All'interno della directory del progetto, esegui il seguente comando per avviare il server di sviluppo: -Starlight supporta la creazione di contenuti in Markdown e MDX. (Puoi aggiungere il supporto per Markdoc installando l'integrazione sperimentale [Astro Markdoc](https://docs.astro.build/en/guides/integrations-guide/markdoc/)). +<Tabs syncKey="pkg"> +<TabItem label="npm"> -### Aggiungere pagine +```sh +npm run dev +``` -Aggiungi pagine automaticamente creando file `.md` o `.mdx` in `src/content/docs/`. Aggiungi sotto-cartelle per organizzare i file e creare percorsi multipli: +</TabItem> +<TabItem label="pnpm"> +```sh +pnpm dev ``` -src/content/docs/hello-world.md => il-tuo-sito.com/hello-world -src/content/docs/guides/faq.md => il-tuo-sito.com/guides/faq + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev ``` -### Type-safe frontmatter +</TabItem> +</Tabs> -Tutte le pagine Starlight condividono un [insieme comune di proprietà](/fr/reference/frontmatter/) personalizzabile per controllare come la pagina deve apparire: +Questo registrerà un messaggio nel tuo terminale con l'URL dell'anteprima locale. +Apri questo URL per iniziare a navigare nel tuo sito. -```md ---- -title: Ciao Mondo! -description: Questa è una pagina nel mio sito Starlight. ---- -``` +### Aggiungi contenuti -Se dovessi dimenticare qualcosa di importante, Starlight te lo farà sapere. +Starlight è pronto per aggiungere nuovi contenuti o portare i tuoi file esistenti! -## Pubblicare il sito Starlight +Aggiungi nuove pagine al tuo sito creando file Markdown nella directory `src/content/docs/`. -Una volta creato e personalizzato il tuo sito Starlight, puoi pubblicarlo in una piattaforma a tua scelta, inclusi Netlify, Vercel, GitHub Pages e molti altri. +Leggi di più sulla navigazione basata su file e sul supporto per i file MDX e Markdoc nella guida [“Pagine”](/it/guides/pages/). -[Impara come pubblicare un sito nella documentazione Astro](https://docs.astro.build/en/guides/deploy/) +### Prossimi passi -## Aggiornare Starlight +- **Configura:** scopri le opzioni comuni in ["Personalizzazione di Starlight"](/it/guides/customization/). +- **Naviga:** configura la tua barra laterale con la guida ["Navigazione laterale"](/it/guides/sidebar/). +- **Componenti:** scopri schede incorporate, tabulazioni e altro nella guida ["Componenti"](/it/components/using-components/). +- **Distribuisci:** pubblica il tuo lavoro con la guida ["Distribuisci il tuo sito"](https://docs.astro.build/it/guides/deploy/) nella documentazione di Astro. -:::tip[Suggerimento] -Siccome Starlight è un software ancora beta, ci sarano frequentemente aggiornamenti e miglioramenti. Ricordati di aggiornare regolarmente! +## Aggiorna Starlight + +:::tip +Poiché Starlight è un software beta, ci saranno frequenti aggiornamenti e miglioramenti. +Assicurati di aggiornare regolarmente Starlight! ::: -Starlight è un'integrazione per Astro, si aggiorna come qualsiasi integrazione `@astrojs/*`: +Starlight è un'integrazione Astro. Puoi aggiornarlo e aggiornare altri pacchetti Astro eseguendo il seguente comando nel tuo terminale: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# aggiorna Starlight con npm -npm install @astrojs/starlight@latest +npx @astrojs/upgrade ``` </TabItem> <TabItem label="pnpm"> ```sh -# aggiorna Starlight con pnpm -pnpm upgrade @astrojs/starlight --latest +pnpm dlx @astrojs/upgrade ``` </TabItem> <TabItem label="Yarn"> ```sh -# aggiorna Starlight con yarn -yarn upgrade @astrojs/starlight --latest +yarn dlx @astrojs/upgrade ``` </TabItem> </Tabs> -Puoi esplorare tutte le modifiche effettuate in ogni aggiornamento nel [changelog Starlight](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md). - -## Risoluzione dei problemi relativi a Starlight +Consulta il [changelog di Starlight](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md) per un elenco completo delle modifiche apportate in ogni versione. -Sia le informazioni sulla [configurazione del progetto](/reference/configuration/) che sulla [configurazione del frontmatter della singola pagina](/reference/frontmatter/) di Starlight sono disponibili nella sezione Riferimenti di questo sito. Utilizza queste pagine per assicurarti che il tuo sito Starlight sia configurato e funzioni correttamente. +## Risoluzione dei problemi di Starlight -Consulta l'elenco crescente di guide nella barra laterale per ricevere assistenza nell'aggiunta di contenuti e nella personalizzazione del tuo sito Starlight. +Usa le pagine di riferimento della [configurazione del progetto](/it/reference/configuration/) e della [configurazione frontmatter della singola pagina](/it/reference/frontmatter/) per assicurarti che il tuo sito Starlight sia configurato e funzionante correttamente. +Consulta le guide nella barra laterale per aiutarti ad aggiungere contenuti e personalizzare il tuo sito Starlight. -Se non è possibile trovare la risposta in questi documenti, visitare la [documentazione completa di Astro](https://docs.astro.build) per la documentazione completa di Astro. È possibile rispondere alla tua domanda comprendendo come funziona Astro in generale, sotto questo tema Starlight. +Se la tua risposta non può essere trovata in questa documentazione, visita la [documentazione completa di Astro](https://docs.astro.build/it/) per la documentazione completa di Astro. +La tua domanda potrebbe trovare risposta comprendendo il funzionamento generale di Astro, sotto questo tema Starlight. -Puoi anche verificare eventuali [problemi di Starlight noti su GitHub](https://github.com/withastro/starlight/issues) e ottenere assistenza nella sezione [Astro Discord](https://astro.build/chat/) dalla nostra comunità attiva e amichevole! Pubblica domande nel nostro forum `#support` con il tag "starlight" o visita il nostro canale dedicato `#starlight` per discutere dello sviluppo attuale e altro ancora! +Puoi anche controllare eventuali [problemi noti di Starlight su GitHub](https://github.com/withastro/starlight/issues) e ottenere aiuto nel [Discord di Astro](https://astro.build/chat/) dalla nostra comunità attiva e amichevole! Pubblica domande nel nostro forum `#support` con il tag "starlight" o visita il nostro canale dedicato `#starlight` per discutere degli sviluppi attuali e di altro ancora! diff --git a/docs/src/content/docs/it/guides/authoring-content.md b/docs/src/content/docs/it/guides/authoring-content.md deleted file mode 100644 index a857e9eec80..00000000000 --- a/docs/src/content/docs/it/guides/authoring-content.md +++ /dev/null @@ -1,210 +0,0 @@ ---- -title: Creazione di contenuti in Markdown -description: Una panoramica della sintassi Markdown supportata da Starlight. ---- - -Starlight supporta l'intera sintassi [Markdown](https://daringfireball.net/projects/markdown/) nei file `.md` insieme al frontmatter [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) per definire metadati come il titolo e la descrizione. - -Assicurarsi di guardare la [documentazione MDX](https://mdxjs.com/docs/what-is-mdx/#markdown) o la [documentazione Markdoc](https://markdoc.dev/docs/syntax) se si vogliono usare questi formati, dato che il supporto Markdown può variare. - -## Stili in linea - -Il testo può essere **grassetto**, _corsivo_, o ~~barrato~~. - -```md -Il testo può essere **grassetto**, _corsivo_, o ~~barrato~~. -``` - -Puoi [aggiungere un link ad un'altra pagina](/it/getting-started/). - -```md -Puoi [aggiungere un link ad un'altra pagina](/it/getting-started/). -``` - -Puoi evidenziare `codice in linea` con apici inversi. - -```md -Puoi evidenziare `codice in linea` con apici inversi. -``` - -## Immagini - -Le immagini in Starlight utilizzano [l'ottimizzazione degli asset di Astro](https://docs.astro.build/it/guides/assets/). - -Markdown e MDX supportano la sintassi Markdown per rappresentare immagini che includono testo alternativo per le tecnologie assistive. - -![Un'illustrazione di pianeti e stelle con la scritta "astro"](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) - -```md -![Un'illustrazione di pianeti e stelle con la scritta "astro"](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) -``` - -I percorsi relativi sono supportati per immagini salvate localmente nel tuo progetto. - -```md -// src/content/docs/page-1.md - -![Un'astronave nello spazio](../../assets/images/rocket.svg) -``` - -## Titoli - -Puoi strutturare i contenuti utilizzando dei titoli. In Markdown sono indicati dal numero di `#` all'inizio della linea. - -### Come strutturare i contenuti della pagina in Starlight - -Starlight è configurato per utilizzare automaticamente il titolo della pagina come intestazione e includerà una "Panoramica" in alto per ogni tabella dei contenuti. Si raccomanda di iniziare ogni pagina con un paragrafo e di usare titoli a partire da `<h2>`: - -```md ---- -title: Guida Markdown -description: Come utilizzare Markdown in Starlight ---- - -Questa pagina descrive come utilizzare Markdown in Starlight. - -## Stili in linea - -## Titoli -``` - -### Link titoli automatici - -Utilizzando titoli in Markdown verranno generati automaticamente i rispettivi link per navigare velocemente in certe sezioni della tua pagina: - -```md ---- -title: La mia pagina dei contenuti -description: Come utilizzare i link automatici di Starlight ---- - -## Introduzione - -Posso collegarmi alla [mia conclusione](#conclusione) che si trova più in basso. - -## Conclusione - -`https://my-site.com/page1/#introduzione` porta direttamente all'introduzione. -``` - -Titoli di livello 2 (`<h2>`) e di livello 3 (`<h3>`) verranno inclusi automaticamente nella tabella dei contenuti. - -## Aside - -Gli aside (conosciuti anche come "ammonizioni" o "richiami") sono utili per indicare contenuti secondari insieme ai contenuti principali. - -Starlight fornisce una sintassi Markdown personalizzata per indicarli. I blocchi aside sono indicati da `:::` per racchiudere i contenuti e possono essere di tipo `note`, `tip`, `caution` o `danger`. - -Dentro un "aside" puoi inserire qualsiasi altro contenuto Markdown anche se sono più indicati per contenere poche informazioni. - -### Note aside - -:::note -Starlight è uno strumento per siti da documentazione con [Astro](https://astro.build/). Puoi iniziare con questo comando: - -```sh -npm run create astro@latest -- --template starlight -``` - -::: - -````md -:::note -Starlight è uno strumento per siti da documentazione con [Astro](https://astro.build/). -Puoi iniziare con questo comando: - -```sh -npm run create astro@latest -- --template starlight -``` - -::: -```` - -### Titoli aside personalizzati - -Si può specificare un titolo personalizzato per gli aside in parentesi quadre dopo aver specificato il tipo di aside, per esempio `:::tip[Lo sapevi?]`. - -:::tip[Lo sapevi?] -Astro ti aiuta a costruire siti più veloci con ["Islands Architecture"](https://docs.astro.build/en/concepts/islands/). -::: - -```md -:::tip[Lo sapevi?] -Astro ti aiuta a costruire siti più veloci con ["Islands Architecture"](https://docs.astro.build/en/concepts/islands/). -::: -``` - -### Altri tipi di aside - -Gli aside caution e danger sono d'aiuto per richiamare l'attenzione dell'utente a dettagli che potrebbero sorprenderli. -Se ti ritrovi ad usarli spesso, potrebbe essere segno che quelo che stai documentando potrebbe trarre beneficio da una riprogettazione. - -:::caution -Se non sei sicuro di voler un sito per documentazione fantastico, pensaci due volte prima di usare [Starlight](../../../). -::: - -:::danger -Gli utenti potrebbero essere più produttivi e trovare il tuo prodotto più facile da usare grazie alle utili funzioni di Starlight. - -- Navigazione chiara -- Temi configurabili dall'utente -- [Supporto per i18n](/it/guides/i18n) - -::: - -```md -:::caution -Se non sei sicuro di voler un sito per documentazione fantastico, pensaci due volte prima di usare [Starlight](../../../). -::: - -:::danger -Gli utenti potrebbero essere più produttivi e trovare il tuo prodotto più facile da usare grazie alle utili funzioni di Starlight. - -- Navigazione chiara -- Temi configurabili dall'utente -- [Supporto per i18n](/it/guides/i18n) - -::: -``` - -## Citazioni - -> Questo è un blockquote, che di solito viene utilizzato per citazioni di persone o documenti. -> -> I blockquote sono indicati da `>` all'inizio di ogni riga. - -```md -> Questo è un blockquote, che di solito viene utilizzato per citazioni di persone o documenti. -> -> I blockquote sono indicati da `>` all'inizio di ogni riga. -``` - -## Blocchi codice - -Un blocco di codice è indicato da tre backtick <code>```</code> all'inizio e alla fine. Puoi indicare il linguaggio di programmazione dopo i primi backtick. - -```js -// Codice JavaScript con sintassi evidenziata. -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` - -````md -```js -// Codice JavaScript con sintassi evidenziata. -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` -```` - -```md -I blocchi lunghi su una linea sola non vanno a capo. Se sono troppo lunghi si può scrollare orizzontalmente. Questo dovrebbe essere abbastanza lungo per dimostrarlo. -``` - -## Altre funzionalità Markdown utili - -Starlight supporta tutte le altre funzionalità Markdown, come liste e tabelle. Guarda la [Markdown Cheat Sheet da The Markdown Guide](https://www.markdownguide.org/cheat-sheet/) per una panoramica veloce su tutte le funzionalità Markdown. diff --git a/docs/src/content/docs/it/guides/components.mdx b/docs/src/content/docs/it/guides/components.mdx deleted file mode 100644 index 07c6952a075..00000000000 --- a/docs/src/content/docs/it/guides/components.mdx +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: Componenti -description: Utilizzo dei componenti in MDX con Starlight. ---- - -I componenti permettono di riutilizzare un elemento UI o altro ripetutamente. -Degli esempi potrebbero essere delle sezioni di link o un video YouTube integrato. -Starlight supporta l'utilizzo di questi nei file [MDX](https://mdxjs.com/) e fornisce dei componenti per te già pronti. - -[Vedi di più sulla costruzione di componenti nella documentazione Astro](https://docs.astro.build/en/core-concepts/astro-components/). - -## Utilizzare un componente - -Puoi usare un componente importandolo nel tuo file MDX e poi visualizzarlo come un tag JSX. -Questi possono ricordare dei tag HTML ma iniziano con una maiuscola: - -```mdx ---- -# src/content/docs/index.mdx -title: Benvenuto nella mia documentazione ---- - -import SomeComponent from '../../components/SomeComponent.astro'; -import AnotherComponent from '../../components/AnotherComponent.astro'; - -<SomeComponent prop="something" /> - -<AnotherComponent> - I componenti possono avere **contenuti interni**. -</AnotherComponent> -``` - -Siccome Starlight è integrato con Astro, puoi aggiungere componenti costruiti con qualsiasi [UI framework supportato (React, Preact, Svelte, Vue, Solid, Lit, and Alpine)](https://docs.astro.build/en/core-concepts/framework-components/). -Vedi di più su come [usare componenti in MDX](https://docs.astro.build/en/guides/markdown-content/#using-components-in-mdx) nella documentazione Astro. - -## Componenti integrati - -Starlight fornisce dei componenti per casi comuni in una documentazione. -Questi sono disponibili nel pacchetto `@astrojs/starlight/components`. - -### Tabs - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -Puoi rappresentare contenuti con un'interfaccia a schede con i componenti `<Tabs>` e `<TabItem>`. -Ogni `<TabItem>` deve avere un `label` per indicare la scheda corrispondente. - -```mdx -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -<Tabs> - <TabItem label="Stelle">Sirius, Vega, Betelgeuse</TabItem> - <TabItem label="Lune">Io, Europa, Ganymede</TabItem> -</Tabs> -``` - -<Tabs> - <TabItem label="Stelle">Sirius, Vega, Betelgeuse</TabItem> - <TabItem label="Lune">Io, Europa, Ganymede</TabItem> -</Tabs> - -### Card - -import { Card, CardGrid } from '@astrojs/starlight/components'; - -Puoi rappresentare i contenuti in un riquadro che rispecchia il tema Starlight usando il componente `<Card>`. -Racchiudi più card in `<CardGrid>` per visualizzarle fianco a fianco se c'è abbastanza spazio. - -Una `<Card>` necessita di `title` e può avere eventualmente un attributo `icon` impostato ad [una delle icone Starlight](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Icons.ts). - -```mdx -import { Card, CardGrid } from '@astrojs/starlight/components'; - -<Card title="Guarda qui">Contenuti interessanti da evidenziare.</Card> - -<CardGrid> - <Card title="Stelle" icon="star"> - Sirius, Vega, Betelgeuse - </Card> - <Card title="Lune" icon="moon"> - Io, Europa, Ganymede - </Card> -</CardGrid> -``` - -<Card title="Guarda qui">Contenuti interessanti da evidenziare.</Card> - -<CardGrid> - <Card title="Stelle" icon="star"> - Sirius, Vega, Betelgeuse - </Card> - <Card title="Lune" icon="moon"> - Io, Europa, Ganymede - </Card> -</CardGrid> - -:::tip[Suggerimento] -Usa la griglia nella pagina principale per evidenziare le funzionalità chiave del progetto. -Aggiungi l'attributo `stagger` per rappresentare la seconda colonna più in basso per rendere il tutto più interessante: - -```astro -<CardGrid stagger> - <!-- cards --> -</CardGrid> -``` - -::: - -### LinkCard - -Utilizza il componente `<LinkCard>` per collegare in modo visibile pagine diverse. - -Una `<LinkCard>` richiede un `title` e un attributo [`href`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#href). Facoltativamente puoi includere una breve `description` o altri attributi del collegamento come `target`. - -Raggruppa più componenti `<LinkCard>` in `<CardGrid>` per visualizzare le schede una accanto all'altra quando c'è spazio sufficiente. - -```mdx -import { LinkCard, CardGrid } from '@astrojs/starlight/components'; - -<LinkCard - title="Customizing Starlight" - description="Learn how to make your Starlight site your own with custom styles, fonts, and more." - href="/guides/customization/" -/> - -<CardGrid> - <LinkCard title="Authoring Markdown" href="/guides/authoring-content/" /> - <LinkCard title="Components" href="/guides/components/" /> -</CardGrid> -``` - -Il codice precedente genera quanto segue nella pagina: - -import { LinkCard } from '@astrojs/starlight/components'; - -<LinkCard - title="Customizing Starlight" - description="Learn how to make your Starlight site your own with custom styles, fonts, and more." - href="/guides/customization/" -/> - -<CardGrid> - <LinkCard title="Authoring Markdown" href="/guides/authoring-content/" /> - <LinkCard title="Components" href="/guides/components/" /> -</CardGrid> - -### Icon - -import { Icon } from '@astrojs/starlight/components'; -import IconsList from '../../../../components/icons-list.astro'; - -Starlight fornisce una serie di icone comuni che puoi visualizzare nei tuoi contenuti utilizzando il componente `<Icon>`. - -Ogni `<Icon>` richiede un [`name`](#all-icons) e può facoltativamente includere un attributo `label`, `size` e `color`. - -```mdx -import { Icon } from '@astrojs/starlight/components'; - -<Icon name="star" color="goldenrod" size="2rem" /> -``` - -Il codice sopra genera quanto segue nella pagina: - -<Icon name="star" color="goldenrod" size="2rem" /> - -#### All icons - -Di seguito è riportato un elenco di tutte le icone disponibili con i nomi associati. Fare clic su un'icona per copiarne il codice componente. - -<IconsList /> diff --git a/docs/src/content/docs/it/guides/css-and-tailwind.mdx b/docs/src/content/docs/it/guides/css-and-tailwind.mdx deleted file mode 100644 index 8fc7a825812..00000000000 --- a/docs/src/content/docs/it/guides/css-and-tailwind.mdx +++ /dev/null @@ -1,290 +0,0 @@ ---- -title: CSS e stile -description: Scopri come personalizzare lo stile del tuo sito Starlight con CSS personalizzati o integrarlo con Tailwind CSS. ---- - -Puoi modellare il tuo sito Starlight con file CSS personalizzati o utilizzare il plug-in Starlight Tailwind. - -## Stili CSS personalizzati - -Personalizza gli stili applicati al tuo sito Starlight fornendo file CSS aggiuntivi per modificare o estendere gli stili predefiniti di Starlight. - -1. Aggiungi un file CSS alla tua directory `src/`. - Ad esempio, potresti impostare una larghezza predefinita della colonna più ampia e una dimensione del testo più grande per i titoli delle pagine: - - ```css - /* src/styles/custom.css */ - :root { - --sl-content-width: 50rem; - --sl-text-5xl: 3.5rem; - } - ``` - -2. Aggiungi il percorso del tuo file CSS all'array `customCss` di Starlight in `astro.config.mjs`: - - ```js - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - - export default defineConfig({ - integrations: [ - starlight({ - title: 'Docs With Custom CSS', - customCss: [ - // Percorso relativo al tuo file CSS personalizzato - './src/styles/custom.css', - ], - }), - ], - }); - ``` - -Puoi vedere tutte le proprietà personalizzate CSS utilizzate da Starlight che puoi impostare per personalizzare il tuo sito nel [file `props.css` su GitHub](https://github.com/withastro/starlight/blob/main/packages/starlight/style/props.css). - -## CSS Tailwind - -Il supporto CSS Tailwind nei progetti Astro è fornito dall'[integrazione Astro Tailwind](https://docs.astro.build/en/guides/integrations-guide/tailwind/). -Starlight fornisce un plug-in Tailwind complementare per aiutare a configurare Tailwind per la compatibilità con gli stili di Starlight. - -Il plugin Starlight Tailwind applica la seguente configurazione: - -- Configura le varianti `dark:` di Tailwind per funzionare con la modalità dark di Starlight. -- Utilizza Tailwind [colori e caratteri del tema](#styling-di-starlight-con-tailwind) nell'interfaccia utente di Starlight. -- Disabilita gli stili di ripristino [Preflight](https://tailwindcss.com/docs/preflight) di Tailwind ripristinando selettivamente le parti essenziali di Preflight richieste per le classi di utilità sui bordi di Tailwind. - -### Crea un nuovo progetto con Tailwind - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -Avvia un nuovo progetto Starlight con Tailwind CSS preconfigurato utilizzando `create astro`: - -<Tabs> -<TabItem label="npm"> - -```sh -npm create astro@latest -- --template starlight/tailwind -``` - -</TabItem> -<TabItem label="pnpm"> - -```sh -pnpm create astro --template starlight/tailwind -``` - -</TabItem> -<TabItem label="Yarn"> - -```sh -yarn create astro --template starlight/tailwind -``` - -</TabItem> -</Tabs> - -### Aggiungi Tailwind a un progetto esistente - -Se hai già un sito Starlight e desideri aggiungere Tailwind CSS, segui questi passaggi. - -1. Aggiungi l'integrazione Tailwind di Astro: - - <Tabs> - - <TabItem label="npm"> - - ```sh - npx astro add tailwind - ``` - - </TabItem> - - <TabItem label="pnpm"> - - ```sh - pnpm astro add tailwind - ``` - - </TabItem> - - <TabItem label="Yarn"> - - ```sh - yarn astro add tailwind - ``` - - </TabItem> - - </Tabs> - -2. Installa il plugin Starlight Tailwind: - - <Tabs> - - <TabItem label="npm"> - - ```sh - npm install @astrojs/starlight-tailwind - ``` - - </TabItem> - - <TabItem label="pnpm"> - - ```sh - pnpm install @astrojs/starlight-tailwind - ``` - - </TabItem> - - <TabItem label="Yarn"> - - ```sh - yarn add @astrojs/starlight-tailwind - ``` - - </TabItem> - - </Tabs> - -3. Crea un file CSS per gli stili di base di Tailwind, ad esempio in `src/tailwind.css`: - - ```css - /* src/tailwind.css */ - @tailwind base; - @tailwind components; - @tailwind utilities; - ``` - -4. Aggiorna il file di configurazione Astro per utilizzare gli stili di base Tailwind e disabilitare gli stili di base predefiniti: - - ```js {11-12,16-17} - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - import tailwind from '@astrojs/tailwind'; - - export default defineConfig({ - integrations: [ - starlight({ - title: 'Docs with Tailwind', - customCss: [ - // Percorso per gli stili di base di Tailwind - './src/tailwind.css', - ], - }), - tailwind({ - // Disattiva gli stili di base predefiniti - applyBaseStyles: false, - }), - ], - }); - ``` - -5. Aggiungi il plugin Starlight Tailwind a `tailwind.config.cjs`: - - ```js ins={2,7} - // tailwind.config.cjs - const starlightPlugin = require('@astrojs/starlight-tailwind'); - - /** @type {import('tailwindcss').Config} */ - module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - plugins: [starlightPlugin()], - }; - ``` - -### Styling di Starlight con Tailwind - -Starlight utilizzerà i valori della [configurazione del tema Tailwind](https://tailwindcss.com/docs/theme) nella sua interfaccia utente. - -Se impostate, le seguenti opzioni sovrascriveranno gli stili predefiniti di Starlight: - -- `colors.accent` — utilizzato per i collegamenti e per l'evidenziazione dell'elemento corrente -- `colors.gray`: utilizzato per i colori e i bordi dello sfondo -- `fontFamily.sans`: utilizzato per l'interfaccia utente e il testo del contenuto -- `fontFamily.mono` — utilizzato per esempi di codice - -```js {12,14,18,20} -// tailwind.config.cjs -const starlightPlugin = require('@astrojs/starlight-tailwind'); -const colors = require('tailwindcss/colors'); - -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: { - colors: { - // Il tuo colore preferito. Indigo è il più vicino alle impostazioni predefinite di Starlight. - accent: colors.indigo, - // La tua scala di grigi preferita. Lo zinco è il più vicino ai valori predefiniti di Starlight. - gray: colors.zinc, - }, - fontFamily: { - sans: ['"Atkinson Hyperlegible"'], - // Il tuo carattere di testo preferito. Starlight utilizza uno stack di caratteri di sistema per impostazione predefinita. - sans: ['"Atkinson Hyperlegible"'], - // Il tuo carattere di codice preferito. Starlight utilizza i caratteri di sistema a spaziatura fissa per impostazione predefinita. - mono: ['"IBM Plex Mono"'], - }, - }, - }, - plugins: [starlightPlugin()], -}; -``` - -## Temi - -Il tema colore di Starlight può essere controllato sovrascrivendo le sue proprietà personalizzate predefinite. -Queste variabili vengono utilizzate in tutta l'interfaccia utente con una gamma di sfumature di grigio utilizzate per i colori del testo e dello sfondo e un colore in risalto utilizzato per i collegamenti e per evidenziare gli elementi correnti nella navigazione. - -### Editor di temi colore - -Utilizza i dispositivi di scorrimento qui sotto per modificare l'accento di Starlight e le tavolozze dei colori grigi. -Le aree di anteprima scure e chiare mostreranno i colori risultanti e anche l'intera pagina verrà aggiornata per visualizzare in anteprima le modifiche. - -Quando sei soddisfatto delle modifiche, copia il codice CSS o Tailwind di seguito e utilizzalo nel tuo progetto. - -import ThemeDesigner from '../../../../components/theme-designer.astro'; - -<ThemeDesigner - labels={{ - presets: { - label: 'Preimpostazioni', - ocean: 'Oceano', - forest: 'Foresta', - oxide: 'Ossido', - nebula: 'Nebulosa', - default: 'Predefinito', - random: 'Casuale', - }, - editor: { - accentColor: 'Accento', - grayColor: 'Grigio', - hue: 'Tonalità', - chroma: 'Croma', - pickColor: 'Scegli colore', - }, - preview: { - darkMode: 'Modalità scura', - lightMode: 'Modalità chiara', - bodyText: - 'Il corpo del testo viene visualizzato in tonalità grigia con un contrasto elevato con lo sfondo.', - linkText: 'I collegamenti sono colorati.', - dimText: 'Alcuni testi, come il sommario, hanno un contrasto inferiore.', - inlineCode: 'Il codice in linea ha uno sfondo distinto.', - }, - }} -> - <Fragment slot="css-docs"> - Aggiungi il seguente CSS al tuo progetto in un [file custom - CSS](#stili-css-personalizzati) per applicare questo tema al tuo sito. - </Fragment> - <Fragment slot="tailwind-docs"> - L'esempio [file di configurazione di - Tailwind](#styling-di-starlight-con-tailwind) di seguito include tavolozze - di colori `accent` e `gray` generate da utilizzare in Oggetto di - configurazione `theme.extend.colors`. - </Fragment> -</ThemeDesigner> diff --git a/docs/src/content/docs/it/guides/customization.mdx b/docs/src/content/docs/it/guides/customization.mdx deleted file mode 100644 index 236bda3062d..00000000000 --- a/docs/src/content/docs/it/guides/customization.mdx +++ /dev/null @@ -1,429 +0,0 @@ ---- -title: Personalizzazione di Starlight -description: Scopri come personalizzare il tuo sito Starlight con il tuo logo, caratteri personalizzati, design della pagina di destinazione e altro ancora. ---- - -import { Tabs, TabItem } from '@astrojs/starlight/components'; -import FileTree from '../../../../components/file-tree.astro'; - -Starlight fornisce stili e funzionalità predefiniti sensati, così puoi iniziare rapidamente senza bisogno di configurazione. -Se vuoi iniziare a personalizzare l'aspetto del tuo sito Starlight, questa guida fa al caso tuo. - -## Aggiungi il tuo logo - -L'aggiunta di un logo personalizzato all'intestazione del sito è un modo rapido per aggiungere il tuo marchio individuale a un sito Starlight. - -1. Aggiungi il file immagine del tuo logo alla directory `src/assets/`: - - <FileTree> - - - src/ - - assets/ - - **my-logo.svg** - - content/ - - astro.config.mjs - - </FileTree> - -2. Aggiungi il percorso del tuo logo come opzione [`logo.src`](/it/reference/configuration/#logo) di Starlight in `astro.config.mjs`: - - ```js - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - - export default defineConfig({ - integrations: [ - starlight({ - title: 'Documentazione con il mio logo', - logo: { - src: './src/assets/my-logo.svg', - }, - }), - ], - }); - ``` - -Per impostazione predefinita, il logo verrà visualizzato accanto al `title` del tuo sito. -Se l'immagine del tuo logo include già il titolo del sito, puoi nascondere visivamente il testo del titolo impostando l'opzione `replacesTitle`. -Il testo del `title` verrà comunque incluso per gli screen reader in modo che l'intestazione rimanga accessibile. - -```js -starlight({ - title: 'Documentazione con il mio logo', - logo: { - src: './src/assets/my-logo.svg', - replacesTitle: true, - }, -}), -``` - -### Varianti del logo chiaro e scuro - -Puoi visualizzare diverse versioni del tuo logo in modalità chiara e scura. - -1. Aggiungi un file immagine per ciascuna variante a `src/assets/`: - - <FileTree> - - - src/ - - assets/ - - **light-logo.svg** - - **dark-logo.svg** - - content/ - - astro.config.mjs - - </FileTree> - -2. Aggiungi il percorso alle varianti del tuo logo come opzioni `light` e `dark` invece di `src` in `astro.config.mjs`: - - ```js - starlight({ - title: 'Documentazione con il mio logo', - logo: { - light: './src/assets/light-logo.svg', - dark: './src/assets/dark-logo.svg', - }, - }), - ``` - -## Enable sitemap - -Starlight ha il supporto integrato per la generazione di una mappa del sito. Abilita la generazione della mappa del sito impostando il tuo URL come `site` in `astro.config.mjs`: - -```js -// astro.config.mjs - -export default defineConfig({ - site: 'https://stargazers.club/', - integrations: [starlight({ title: 'Sito con mappa del sito' })], -}); -``` - -## Layout della pagina - -Per impostazione predefinita, le pagine Starlight utilizzano un layout con una barra laterale di navigazione globale e un indice dei contenuti che mostra le intestazioni della pagina corrente. - -Puoi applicare un layout di pagina più ampio senza barre laterali impostando [`template: splash`](/it/reference/frontmatter/#template) nel frontmatter di una pagina. -Funziona particolarmente bene per le pagine di destinazione e puoi vederlo in azione sulla [home page di questo sito](/it/). - -```md ---- -# src/content/docs/index.md - -title: La mia pagina di destinazione -template: splash ---- -``` - -## Indice dei contenuti - -Starlight visualizza un indice dei contenuti su ogni pagina per consentire ai lettori di passare più facilmente all'intestazione che stanno cercando. -Puoi personalizzare, o addirittura disabilitare, l'indice dei contenuti a livello globale nell'integrazione Starlight o pagina per pagina in Frontmatter. - -Per impostazione predefinita, le intestazioni `<h2>` e `<h3>` sono incluse nell'indice dei contenuti. Modifica i livelli delle intestazioni da includere in tutto il sito utilizzando le opzioni `minHeadingLevel` e `maxHeadingLevel` nel tuo [global `tableOfContents`](/it/reference/configuration/#tableofcontents). Sostituisci queste impostazioni predefinite su una singola pagina aggiungendo le proprietà [frontmatter `tableOfContents`](/it/reference/frontmatter/#tableofcontents) corrispondenti: - -<Tabs> - <TabItem label="Frontmatter"> - -```md ---- -# src/content/docs/example.md -title: Pagina con solo H2 nell'indice dei contenuti -summary: - minHeadingLevel: 2 - maxHeadingLevel: 2 ---- -``` - - </TabItem> - <TabItem label="Configurazione globale"> - -```js -// astro.config.mjs - -defineConfig({ - integrations: [ - starlight({ - title: '', - tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 2 }, - }), - ], -}); -``` - - </TabItem> -</Tabs> - -Disabilita completamente l'indice dei contenuti impostando l'opzione `tableOfContents` su `false`: - -<Tabs> - <TabItem label="Frontmatter"> - -```md ---- -# src/content/docs/esempio.md -title: Pagina senza indice dei contenuti -tableOfContents: false ---- -``` - - </TabItem> - <TabItem label="Configurazione globale"> - -```js -// astro.config.mjs - -defineConfig({ - integrations: [ - starlight({ - title: - 'Documentazione con indice dei contenuti disabilitato a livello globale', - tableOfContents: false, - }), - ], -}); -``` - - </TabItem> -</Tabs> - -## Collegamenti social - -Starlight dispone del supporto integrato per aggiungere collegamenti ai tuoi account di social media all'intestazione del sito tramite l'opzione [`social`](/it/reference/configuration/#social) nell'integrazione Starlight. - -Attualmente sono supportati i collegamenti a Bitbucket, Codeberg, CodePen, Discord, GitHub, GitLab, Gitter, Instagram, LinkedIn, Mastodon, Microsoft Teams, Stack Overflow, Threads, Twitch, Twitter e Youtube. -Facci sapere su GitHub o Discord se hai bisogno di supporto per un altro servizio! - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'Documentazione con link social', - social: { - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - }, - }), - ], -}); -``` - -## Collegamenti di Modifica - -Starlight può visualizzare un collegamento "Modifica pagina" nel piè di pagina di ciascuna pagina. -Ciò rende più semplice per il lettore trovare il file da modificare per migliorare i tuoi documenti. -Per i progetti open source in particolare, questo può aiutare a incoraggiare i contributi della tua comunità. - -Per abilitare i collegamenti di modifica, imposta [`editLink.baseUrl`](/it/reference/configuration/#editlink) sull'URL utilizzato per modificare il tuo repository nella configurazione dell'integrazione Starlight. -Il valore di `editLink.baseUrl` verrà anteposto al percorso della pagina corrente per formare il collegamento di modifica completo. - -I modelli comuni includono: - -- GitHub: `https://github.com/USER_NAME/REPO_NAME/edit/BRANCH_NAME/` -- GitLab: `https://gitlab.com/USER_NAME/REPO_NAME/-/edit/BRANCH_NAME/` - -Se il tuo progetto Starlight non è nella radice del tuo repository, includi il percorso del progetto alla fine dell'URL di base. - -Questo esempio mostra il collegamento di modifica configurato per i documenti Starlight, che si trovano nella sottodirectory `docs/` sul ramo `main` del repository `withastro/starlight` su GitHub: - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'Documentazione con collegamenti di modifica', - editLink: { - baseUrl: 'https://github.com/withastro/starlight/edit/main/docs/', - }, - }), - ], -}); -``` - -## Pagina 404 personalizzata - -Per impostazione predefinita, i siti Starlight visualizzano una semplice pagina 404. -Puoi personalizzarlo aggiungendo un file `404.md` (o `404.mdx`) alla tua directory `src/content/docs/`: - -<FileTree> - -- src/ - - content/ - - docs/ - - **404.md** - - index.md -- astro.config.mjs - -</FileTree> - -Puoi utilizzare tutto il layout di pagina e le tecniche di personalizzazione di Starlight nella tua pagina 404. Ad esempio, la pagina 404 predefinita utilizza il componente [`splash` template](#page-layout) e [`hero`](/it/reference/frontmatter/#hero) in frontmatter: - -```md ---- -title: '404' -template: splash -editUrl: false -hero: - title: '404' - tagline: Pagina non trovata. Controlla l'URL o prova a utilizzare la barra di ricerca. ---- -``` - -## Caratteri personalizzati - -Per impostazione predefinita, Starlight utilizza i caratteri sans-serif disponibili sul dispositivo locale dell'utente per tutto il testo. -Ciò garantisce che la documentazione venga caricata rapidamente in un carattere familiare a ciascun utente, senza richiedere larghezza di banda aggiuntiva per scaricare file di caratteri di grandi dimensioni. - -Se devi aggiungere un carattere personalizzato al tuo sito Starlight, puoi impostare i caratteri da utilizzare nei file CSS personalizzati o con qualsiasi altra [tecnica di stile Astro](https://docs.astro.build/it/guides/styling/) . - -### Imposta i caratteri - -Se disponi già di file di font, segui la [guida alla configurazione locale](#configura-i-file-dei-caratteri-locali). -Per utilizzare Google Fonts, segui la [guida alla configurazione di Fontsource](#configura-un-font-fontsource). - -#### Configura i file dei caratteri locali - -1. Aggiungi i file dei caratteri a una directory `src/fonts/` e crea un file `font-face.css` vuoto: - - <FileTree> - - - src/ - - content/ - - fonts/ - - **CustomFont.woff2** - - **font-face.css** - - astro.config.mjs - - </FileTree> - -2. Aggiungi una [dichiarazione `@font-face`](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face) per ciascuno dei tuoi caratteri in `src/fonts/font-face.css`. - Utilizza un percorso relativo al file del font nella funzione `url()`. - - ```css - /* src/fonts/font-face.css */ - - @font-face { - font-family: 'Font Personalizzato'; - /* Utilizza un percorso relativo al file del font locale in `url()`. */ - src: url('./CustomFont.woff2') format('woff2'); - font-weight: normal; - font-style: normal; - font-display: swap; - } - ``` - -3. Aggiungi il percorso del tuo file `font-face.css` all'array `customCss` di Starlight in `astro.config.mjs`: - - ```js - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - - export default defineConfig({ - integrations: [ - starlight({ - title: 'Documentazione con font personalizzato', - customCss: [ - // Percorso relativo al file CSS @font-face. - './src/fonts/font-face.css', - ], - }), - ], - }); - ``` - -#### Configura un font Fontsource - -Il progetto [Fontsource](https://fontsource.org/) semplifica l'utilizzo di Google Fonts e altri caratteri open source. -Fornisce moduli npm che puoi installare per i caratteri che desideri utilizzare e include file CSS già pronti da aggiungere al tuo progetto. - -1. Trova il font che desideri utilizzare nel [catalogo di Fontsource](https://fontsource.org/). - Questo esempio utilizzerà [IBM Plex Serif](https://fontsource.org/fonts/ibm-plex-serif). - -2. Installa il pacchetto per il font scelto. - Puoi trovare il nome del pacchetto facendo clic su "Installa" nella pagina dei caratteri Fontsource. - - <Tabs> - - <TabItem label="npm"> - - ```sh - npm install @fontsource/ibm-plex-serif - ``` - - </TabItem> - - <TabItem label="pnpm"> - - ```sh - pnpm install @fontsource/ibm-plex-serif - ``` - - </TabItem> - - <TabItem label="Yarn"> - - ```sh - yarn add @fontsource/ibm-plex-serif - ``` - - </TabItem> - - </Tabs> - -3. Aggiungi i file CSS Fontsource all'array `customCss` di Starlight in `astro.config.mjs`: - - ```js - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - - export default defineConfig({ - integrations: [ - starlight({ - title: 'Docs With a Custom Typeface', - customCss: [ - // File Fontsource per pesi di font regolari e semi-grassetto. - '@fontsource/ibm-plex-serif/400.css', - '@fontsource/ibm-plex-serif/600.css', - ], - }), - ], - }); - ``` - - Fontsource fornisce più file CSS per ciascun font. Consulta la [documentazione Fontsource](https://fontsource.org/docs/getting-started/install#4-weights-and-styles) sull'inclusione di pesi e stili diversi per capire quale utilizzare. - -### Usa i caratteri - -Per applicare il font che hai impostato al tuo sito, utilizza il nome del font scelto in un [file CSS personalizzato](/it/guides/css-and-tailwind/#custom-css-styles). -Ad esempio, per sovrascrivere ovunque il font predefinito di Starlight, imposta la proprietà personalizzata `--sl-font`: - -```css -/* src/styles/custom.css */ - -:root { - --sl-font: 'IBM Plex Serif', serif; -} -``` - -Puoi anche scrivere CSS più mirati se desideri applicare il tuo font in modo più selettivo. -Ad esempio, per impostare un font solo sul contenuto principale, ma non sulle barre laterali: - -```css -/* src/styles/custom.css */ - -main { - font-family: 'IBM Plex Serif', serif; -} -``` - -Segui le [istruzioni CSS personalizzate](/it/guides/css-and-tailwind/#custom-css-styles) per aggiungere i tuoi stili al tuo sito. diff --git a/docs/src/content/docs/it/guides/i18n.mdx b/docs/src/content/docs/it/guides/i18n.mdx deleted file mode 100644 index c9ce07965e1..00000000000 --- a/docs/src/content/docs/it/guides/i18n.mdx +++ /dev/null @@ -1,201 +0,0 @@ ---- -title: Internazionalizzazione (i18n) -description: Impara come configurare il tuo sito Starlight per supportare più lingue. ---- - -import FileTree from '../../../../components/file-tree.astro'; - -Starlight offre il supporto per siti multilingua, compreso di indirizzamento, contenuti fallback e completo supporto per lingue scritte da destra a sinistra (RTL). - -## Configurare i18n - -1. Indicare a Starlight le lingue che si vuole supportare passando [`locales`](/it/reference/configuration/#locales) e [`defaultLocale`](/it/reference/configuration/#defaultlocale) all'integrazione Starlight: - - ```js - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - - export default defineConfig({ - integrations: [ - starlight({ - title: 'My Docs', - // Indica l'inglese come lingua predefinita. - defaultLocale: 'en', - locales: { - // La documentazione in inglese si trova in `src/content/docs/en/` - en: { - label: 'English', - }, - // La documentazione in cinese semplificato si trova in `src/content/docs/zh/` - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - // La documentazione in arabo si trova in `src/content/docs/ar/` - ar: { - label: 'العربية', - dir: 'rtl', - }, - }, - }), - ], - }); - ``` - - Il `defaultLocale` sarà utilizzato come fallback per contenuti ed interfaccia, quindi scegli il linguaggio per cui c'è più probabilità di iniziare a scrivere o già hai contenuti. - -2. Creare una cartella per ogni lingua in `src/content/docs/`. - Per esempio, per la configurazione di sopra: - - <FileTree> - - - src/ - - content/ - - docs/ - - ar/ - - en/ - - zh/ - - </FileTree> - -3. Puoi ora aggiungere file nelle cartelle. Usa file con lo stesso nome per associare pagine tra i linguaggi e sfruttare le funzionalità di Starlight per i18n, compresi i contenuti di fallback, avvisi di traduzione e altro. - - Per esempio, crea `ar/index.md` e `en/index.md` per rappresentare la homepage rispettivamente in arabo e inglese. - -### Utilizzare una lingua principale - -Puoi utilizzare una lingua principale per non avere il prefisso i18n nel percorso. Per esempio, se l'inglese è la lingua principale, un indirizzo sarà del tipo `/about` invece che `/en/about`. - -Per fare questo, utilizza la chiave `root` nella configurazione `locales`. Se la lingua principale è anche la lingua di default rimuovi `defaultLocale` o impostala a `'root'`. - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'My Docs', - defaultLocale: 'root', // opzionale - locales: { - root: { - label: 'English', - lang: 'en', // necessario per root - }, - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - }, - }), - ], -}); -``` - -Quando si usa una lingua `root`, metti le pagine direttamente in `src/content/docs/` invece che in una cartella dedicata alla lingua. Per esempio, qui si trovano i file delle pagine per inglese e cinese quando si utilizza la configurazione precedente: - -<FileTree> - -- src/ - - content/ - - docs/ - - **index.md** - - zh/ - - **index.md** - -</FileTree> - -#### Siti monolingua - -Per default, Starlight è un sito monolingua (inglese). Per creare un sito monolingua in un'altra, impostala come `root` in `locales`: - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'My Docs', - locales: { - root: { - label: '简体中文', - lang: 'zh-CN', - }, - }, - }), - ], -}); -``` - -Questo ti permette di sovrascrivere le impostazione predefinite di Starlight per la lingua senza abilitare l'internazionalizzazione. - -## Contenuti fallback - -Starlight si aspetta che crei pagine equivalenti per tutte le lingue impostate. Per esempio, se hai un file `en/about.md`, crea un `about.md` per ogni altra lingua impostata. Questo permette a Starlight di avere contenuti fallback per le pagine che non hai ancora tradotto. - -Se una traduzione non è ancora disponibile per una lingua, Starlight mostrerà ai lettori i contenuti per quella pagina nel linguaggio predefinito (impostato da `defaultLocale`). Per esempio, se non hai ancora creato una versione italiana della pagina About e la lingua predefinita è inglese, gli utenti per `/it/about` vedranno i contenuti in inglese di `/en/about` con un avviso che la pagina non è stata ancora tradotta. - -## Tradurre l'interfaccia Starlight - -In aggiunta alla possibilità di avere pagine multilingua, Starlight permette di tradurre le scritte dell'interfaccia (per esempio l'intestazione "In questa pagina" nella tabella dei contenuti) in modo che i lettori possano vedere il sito interamente nella lingua selezionata. - -Le stringhe dell'interfaccia utente tradotte in inglese, ceco, francese, tedesco, italiano, giapponese, portoghese, olandese, danese, spagnolo, turco, arabo, norvegese, farsi, ebraico, cinese semplificato, coreano, indonesiano, russo e svedese sono disponibili di default e accettiamo [contributi per aggiungere altre lingue predefinite](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md). - -Puoi fornire traduzioni per lingue aggiuntive — o sovrascrivere i valori predefiniti — con la collezione `i18n`. - -1. Configura la collezione `i18n` in `src/content/config.ts` se non lo è già: - - ```js - // src/content/config.ts - import { defineCollection } from 'astro:content'; - import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; - - export const collections = { - docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), - }; - ``` - -2. Crea un file JSON in `src/content/i18n/` per ogni lingua di cui si vuole fornire la traduzione all'interfaccia. - Per esempio, questo aggiungerebbe traduzioni per arabo e cinese semplificato: - - <FileTree> - - - src/ - - content/ - - i18n/ - - ar.json - - zh-CN.json - - </FileTree> - -3. Aggiungere traduzioni per le chiavi che vuoi tradurre. Traduci solo i valori, le chiavi non devono essere modificate (per esempio `"search.label": "Buscar"`). - - Queste sono le traduzioni di default per l'inglese: - - ```json - { - "skipLink.label": "Skip to content", - "search.label": "Search", - "search.shortcutLabel": "(Press / to Search)", - "search.cancelLabel": "Cancel", - "themeSelect.accessibleLabel": "Select theme", - "themeSelect.dark": "Dark", - "themeSelect.light": "Light", - "themeSelect.auto": "Auto", - "languageSelect.accessibleLabel": "Select language", - "menuButton.accessibleLabel": "Menu", - "sidebarNav.accessibleLabel": "Main", - "tableOfContents.onThisPage": "On this page", - "tableOfContents.overview": "Overview", - "i18n.untranslatedContent": "This content is not available in your language yet.", - "page.editLink": "Edit page", - "page.lastUpdated": "Last updated:", - "page.previousLink": "Next", - "page.nextLink": "Previous" - } - ``` diff --git a/docs/src/content/docs/it/guides/project-structure.mdx b/docs/src/content/docs/it/guides/project-structure.mdx deleted file mode 100644 index 3bd2dca22b8..00000000000 --- a/docs/src/content/docs/it/guides/project-structure.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Struttura del progetto -description: Impara come organizzare i file nel tuo progetto Starlight. ---- - -Questa guida ti mostrerà come un progetto Starlight è organizzato e cosa i file nel progetto fanno. - -I progetti Starlight seguono generalmente la stessa struttura di file e cartelle come altri progetti Astro. Vedi [la documentazione sulla struttura dei progetti Astro](https://docs.astro.build/en/core-concepts/project-structure/) per più dettagli. - -## File e cartelle - -- `astro.config.mjs` — Il file di configurazione di Astro; include l'integrazione Starlight e la sua configurazione. -- `src/content/config.ts` — File di configurazione delle collezioni; aggiunge il frontmatter di Starlight al tuo progetto. -- `src/content/docs/` — File dei contenuti. Starlight trasforma i file `.md`, `.mdx` o `.mdoc` in questa cartella in una pagina del tuo sito. -- `src/content/i18n/` (opzionale) — Supporto all'[internazionalizzazione](/it/guides/i18n/). -- `src/` — Altri file (componenti, stili, immagini, ecc.) che aggiungi al progetto. -- `public/` — Asset statici (font, favicon, PDF, etc.) che non saranno processati da Astro. - -## Esempio struttura di un progetto - -La struttura di un progetto Starlight potrebbe essere questa: - -import FileTree from '../../../../components/file-tree.astro'; - -<FileTree> - -- public/ - - favicon.svg -- src/ - - assets/ - - logo.svg - - screenshot.jpg - - components/ - - CustomButton.astro - - InteractiveWidget.jsx - - content/ - - docs/ - - guides/ - - 01-getting-started.md - - 02-advanced.md - - index.mdx - - config.ts - - env.d.ts -- astro.config.mjs -- package.json -- tsconfig.json - -</FileTree> diff --git a/docs/src/content/docs/it/guides/sidebar.mdx b/docs/src/content/docs/it/guides/sidebar.mdx deleted file mode 100644 index b5d6570d9c2..00000000000 --- a/docs/src/content/docs/it/guides/sidebar.mdx +++ /dev/null @@ -1,480 +0,0 @@ ---- -title: Navigazione nella barra laterale -description: Scopri come impostare e personalizzare i collegamenti di navigazione della barra laterale del tuo sito Starlight. -sidebar: - badge: Nuovo ---- - -import FileTree from '../../../../components/file-tree.astro'; -import SidebarPreview from '../../../../components/sidebar-preview.astro'; - -Una barra laterale ben organizzata è fondamentale per una buona documentazione poiché è uno dei modi principali in cui gli utenti navigheranno nel tuo sito. Starlight fornisce un set completo di opzioni per personalizzare il layout e il contenuto della barra laterale. - -## Barra laterale predefinita - -Per impostazione predefinita, Starlight genererà automaticamente una barra laterale in base alla struttura del file system della documentazione, utilizzando la proprietà `title` di ciascun file come voce della barra laterale. - -Ad esempio, data la seguente struttura di file: - -<FileTree> - -- src/ - - content/ - - docs/ - - guides/ - - components.md - - i18n.md - - reference/ - - configuration.md - -</FileTree> - -Verrà generata automaticamente la seguente barra laterale: - -<SidebarPreview - config={[ - { - label: 'guides', - items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, - ], - }, - { - label: 'reference', - items: [ - { label: 'Configuration Reference', link: '/reference/configuration/' }, - ], - }, - ]} -/> - -Scopri di più sulle barre laterali generate automaticamente nella sezione [gruppi generati automaticamente](#gruppi-generati-automaticamente). - -## Aggiungi collegamenti e gruppi di collegamenti - -Per configurare i [link](#link) e i [gruppi di link](#gruppi) della barra laterale (all'interno di un'intestazione comprimibile), utilizza la proprietà [`starlight.sidebar`](/it/reference/configuration/#sidebar) in `astro.config.mjs`. - -Combinando collegamenti e gruppi, puoi creare un'ampia varietà di layout della barra laterale. - -### Collegamenti - -Aggiungi un collegamento a una pagina interna o esterna utilizzando un oggetto con le proprietà `label` e `link`. - -```js -starlight({ - sidebar: [ - // Un collegamento alla guida CSS e stile. - { label: 'CSS e stile', link: '/guides/css-and-tailwind/' }, - // Un collegamento esterno al sito web di Astro. - { label: 'Astro', link: 'https://astro.build/' }, - ], -}); -``` - -La configurazione sopra genera la seguente barra laterale: - -<SidebarPreview - config={[ - { label: 'CSS e stile', link: '/guides/css-and-tailwind/' }, - { label: 'Astro', link: 'https://astro.build/' }, - ]} -/> - -### Gruppi - -Puoi aggiungere struttura alla barra laterale raggruppando i collegamenti correlati sotto un'intestazione comprimibile. -I gruppi possono contenere sia collegamenti che altri sottogruppi. - -Aggiungi un gruppo utilizzando un oggetto con le proprietà `label` e `items`. -`label` verrà utilizzato come intestazione del gruppo. -Aggiungi collegamenti o sottogruppi all'array `items`. - -```js -starlight({ - sidebar: [ - // Un gruppo di collegamenti etichettati "Guide". - { - label: 'Guide', - items: [ - { label: 'Componenti', link: '/guides/components/' }, - { label: 'Internazionalizzazione (i18n)', link: '/guides/i18n/' }, - // Un gruppo nidificato di collegamenti. - { - label: 'Stile', - items: [ - { label: 'CSS', link: '/guides/css-and-tailwind/' }, - { label: 'Tailwind', link: '/guides/css-and-tailwind/' }, - { label: 'Shiki', link: '/guides/css-and-tailwind/' }, - ], - }, - ], - }, - ], -}); -``` - -La configurazione sopra genera la seguente barra laterale: - -<SidebarPreview - config={[ - { - label: 'Guide', - items: [ - { label: 'Componenti', link: '/guides/components/' }, - { label: 'Internazionalizzazione (i18n)', link: '/guides/i18n/' }, - { - label: 'Stile', - items: [ - { label: 'CSS', link: '/guides/css-and-tailwind/' }, - { label: 'Tailwind', link: '/guides/css-and-tailwind/' }, - { label: 'Shiki', link: '/guides/css-and-tailwind/' }, - ], - }, - ], - }, - ]} -/> - -### Gruppi generati automaticamente - -Starlight può generare automaticamente un gruppo nella barra laterale in base a una directory dei tuoi documenti. -Ciò è utile quando non desideri inserire manualmente ciascun elemento della barra laterale in un gruppo. -Per impostazione predefinita, le pagine verranno ordinate alfabeticamente in base al nome del file. - -Aggiungi un gruppo generato automaticamente utilizzando un oggetto con le proprietà `label` e `autogenerate`. La tua configurazione di `autogenerate` deve specificare quale `directory` da utilizzare per le voci della barra laterale. Ad esempio, con la seguente configurazione: - -```js -starlight({ - sidebar: [ - { - label: 'Guides', - // Genera automaticamente un gruppo di collegamenti per la directory 'guides'. - autogenerate: { directory: 'guides' }, - }, - ], -}); -``` - -E la seguente struttura di file: - -<FileTree> - -- src/ - - content/ - - docs/ - - guides/ - - components.md - - i18n.md - - advanced/ - - project-structure.md - -</FileTree> - -Verrà generata la seguente barra laterale: - -<SidebarPreview - config={[ - { - label: 'Guides', - items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, - { - label: 'advanced', - items: [ - { label: 'Project Structure', link: '/guides/project-structure/' }, - ], - }, - ], - }, - ]} -/> - -#### Personalizzazione dei collegamenti generati automaticamente nel frontmatter - -Utilizza il [campo frontmatter `sidebar`](/it/reference/frontmatter/#sidebar) nelle singole pagine per personalizzare i collegamenti generati automaticamente. - -Le opzioni frontmatter della barra laterale ti consentono di impostare un'[etichetta personalizzata](/it/reference/frontmatter/#label) o aggiungere un [badge](/it/reference/frontmatter/#badge) a un collegamento, [nascondi](/it/reference/frontmatter/#hidden) un collegamento dalla barra laterale o definire un [ponderazione dell'ordinamento personalizzato](/it/reference/frontmatter/#order). - -```md ---- -title: La mia pagina -sidebar: - # Imposta un'etichetta personalizzata per il collegamento - label: etichetta personalizzata della barra laterale - # Imposta un ordine personalizzato per il collegamento (i numeri inferiori vengono visualizzati più in alto) - order: 2 - # Aggiungi un badge al collegamento - badge: - text: Nuovo - variant: tip ---- -``` - -Un gruppo generato automaticamente che include una pagina con il frontmatter sopra genererà la seguente barra laterale: - -<SidebarPreview - config={[ - { - label: 'Guide', - items: [ - { label: 'Una pagina', link: '#' }, - { - label: 'Etichetta barra laterale personalizzata', - link: '#', - badge: { text: 'Nuono', variant: 'tip' }, - }, - { label: "Un'altra pagina", link: '#' }, - ], - }, - ]} -/> - -:::note -La configurazione del frontmatter `sidebar` viene utilizzata solo per i collegamenti generati automaticamente e verrà ignorata per i collegamenti definiti manualmente. -::: - -## Badge - -I collegamenti possono anche includere una proprietà `badge` per visualizzare un badge accanto all'etichetta del collegamento. - -```js -starlight({ - sidebar: [ - { - label: 'Guide', - items: [ - // Un collegamento con un badge "Nuovo". - { - label: 'Componenti', - link: '/guides/components/', - badge: 'Nuovo', - }, - ], - }, - ], -}); -``` - -La configurazione sopra genera la seguente barra laterale: - -<SidebarPreview - config={[ - { - label: 'Guide', - items: [ - { - label: 'Componenti', - link: '/guides/components/', - badge: { text: 'Nuovo', variant: 'default' }, - }, - ], - }, - ]} -/> - -### Varianti del badge - -Personalizza lo stile del badge utilizzando un oggetto con proprietà `text` e `variant`. - -Il `text` rappresenta il contenuto da visualizzare (ad esempio "Nuovo"). -Sostituisci lo stile `default`, che utilizza il colore in risalto del tuo sito, impostando la proprietà `variant` su uno dei seguenti valori: `note`, `tip`, `danger`, `caution` o `success`. - -```js -starlight({ - sidebar: [ - { - label: 'Guide', - items: [ - // Un collegamento con un badge giallo "Sperimentale". - { - label: 'Componenti', - link: '/guides/components/', - badge: { text: 'Sperimentale', variant: 'caution' }, - }, - ], - }, - ], -}); -``` - -La configurazione sopra genera la seguente barra laterale: - -<SidebarPreview - config={[ - { - label: 'Guide', - items: [ - { - label: 'Componenti', - link: '/guides/components/', - badge: { text: 'Sperimentale', variant: 'caution' }, - }, - ], - }, - ]} -/> - -## Internazionalizzazione - -Utilizza la proprietà `translations` sulle voci dei collegamenti e dei gruppi per tradurre il collegamento o l'etichetta del gruppo per ciascuna lingua supportata. -La proprietà `label` verrà utilizzata per la locale predefinita e per le lingue senza traduzione. - -```js -starlight({ - sidebar: [ - { - label: 'Guide', - translations: { - es: 'Guías', - }, - items: [ - { - label: 'Componenti', - translations: { - es: 'Componentes', - }, - link: '/guides/components/', - }, - { - label: 'Internazionalizzazione (i18n)', - translations: { - es: 'Internacionalización (i18n)', - }, - link: '/guides/i18n/', - }, - ], - }, - ], -}); -``` - -La navigazione della documentazione in spagnolo genererà la seguente barra laterale: - -<SidebarPreview - config={[ - { - label: 'Guías', - items: [ - { label: 'Componentes', link: '/guides/components/' }, - { label: 'Internacionalización (i18n)', link: '/guides/i18n/' }, - ], - }, - ]} -/> - -## Gruppi che si riducono - -I gruppi di collegamenti possono essere compressi per impostazione predefinita impostando la proprietà `collapsed` su `true`. - -```js -starlight({ - sidebar: [ - { - label: 'Guide', - // Comprimi il gruppo per impostazione predefinita. - collapsed: true, - items: [ - { label: 'Componenti', link: '/guides/components/' }, - { label: 'Internazionalizzazione (i18n)', link: '/guides/i18n/' }, - ], - }, - ], -}); -``` - -La configurazione sopra genera la seguente barra laterale: - -<SidebarPreview - config={[ - { - label: 'Guide', - collapsed: true, - items: [ - { label: 'Componenti', link: '/guides/components/' }, - { label: 'Internazionalizzazione (i18n)', link: '/guides/i18n/' }, - ], - }, - ]} -/> - -[I gruppi generati automaticamente](#gruppi-generati-automaticamente) rispettano il valore `collapsed` del gruppo principale: - -```js -starlight({ - sidebar: [ - { - label: 'Guide', - // Comprimi il gruppo e i relativi sottogruppi generati automaticamente per impostazione predefinita. - collapsed: true, - autogenerate: { directory: 'guides' }, - }, - ], -}); -``` - -La configurazione sopra genera la seguente barra laterale: - -<SidebarPreview - config={[ - { - label: 'Guide', - collapsed: true, - items: [ - { label: 'Componenti', link: '/guides/components/' }, - { label: 'Internazionalizzazione (i18n)', link: '/guides/i18n/' }, - { - label: 'avanzato', - collapsed: true, - items: [ - { - label: 'Struttura del progetto', - link: '/guides/project-structure/', - }, - ], - }, - ], - }, - ]} -/> - -Questo comportamento può essere ignorato definendo la proprietà `autogenerate.collapsed`. - -```js -starlight({ - sidebar: [ - { - label: 'Guide', - // Non comprimere il gruppo "Guide", ma comprimerlo - // sottogruppi generati automaticamente. - collapsed: false, - autogenerate: { directory: 'guides', collapsed: true }, - }, - ], -}); -``` - -La configurazione sopra genera la seguente barra laterale: - -<SidebarPreview - config={[ - { - label: 'Guide', - items: [ - { label: 'Componenti', link: '/guides/components/' }, - { label: 'Internazionalizzazione (i18n)', link: '/guides/i18n/' }, - { - label: 'advanced', - collapsed: true, - items: [ - { - label: 'Struttura del progetto', - link: '/guides/project-structure/', - }, - ], - }, - ], - }, - ]} -/> diff --git a/docs/src/content/docs/it/index.mdx b/docs/src/content/docs/it/index.mdx index 61bb8c07344..d71d282628e 100644 --- a/docs/src/content/docs/it/index.mdx +++ b/docs/src/content/docs/it/index.mdx @@ -1,45 +1,42 @@ --- title: Starlight 🌟 Costruire siti per documentazione con Astro +head: + - tag: title + content: Starlight 🌟 Costruire siti per documentazione con Astro description: Starlight ti aiuta a creare siti belli e performanti con Astro. template: splash -banner: - content: | - <span class="ph-banner"> - <span class="ph-houston"><img src="/ph-houston.svg" alt="" width="72" height="72"/></span> - <span class="ph-text"> - <strong>Benvenuti Product Hunters 👋</strong> - <a href="https://www.producthunt.com/posts/starlight-by-astro">Siamo live ora!</a> - </span> - </span> +editUrl: false +lastUpdated: false hero: title: Fai brillare la tua documentazione con Starlight tagline: Tutto quello di cui hai bisogno per creare documentazione stellare. Veloce, accessibile e facile da usare. image: - file: ../../../assets/hero-star.webp + file: ~/assets/hero-star.webp actions: - text: Inizia icon: right-arrow - variant: primary link: /it/getting-started/ - text: Vedi su GitHub icon: external + variant: minimal link: https://github.com/withastro/starlight --- import { CardGrid, Card } from '@astrojs/starlight/components'; -import AboutAstro from '../../../components/about-astro.astro'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; <CardGrid stagger> <Card title="Documentazione che delizia" icon="open-book"> - Include: Navigazione, ricerca, internazionalizzazione, ottimizzazione del - motore di ricerca, caratteri facili da leggere, evidenziazione del codice, - tema scuro e altro. + Include: Navigazione, ricerca, internazionalizzazione, SEO, caratteri facili + da leggere, evidenziazione del codice, tema scuro e altro. </Card> <Card title="Basato su Astro" icon="rocket"> Sfrutta la potenza di Astro. Estendi Starlight con le tue integrazioni e librerie preferite. </Card> - <Card title="Markdown, Markdoc, e MDX" icon="document"> + <Card title="Markdown, Markdoc e MDX" icon="document"> Utilizza il tuo linguaggio markup preferito. Starlight fornisce validazione frontmatter con TypeScript. </Card> @@ -49,10 +46,117 @@ import AboutAstro from '../../../components/about-astro.astro'; </Card> </CardGrid> +<TestimonialGrid title="Cosa dicono le persone"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + Il team di Astro ha FATTO EVOLVERE il modo in cui la documentazione può essere realizzata e puoi ottenerla tutta out-of-the-box con il loro progetto Starlight. + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + Lo starter kit ufficiale di Astro Starlight è uno strumento davvero incredibile per costruire un sito web di documentazione + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + Starlight è il nostro esempio di riferimento di una grande esperienza utente: la velocità, la comodità e + l'attenzione ai dettagli è fonte di ispirazione. Si occupa della parte tecnica e dell'aspetto, + in modo che tu possa concentrarti sui tuoi contenuti 👏 + + Il team di StackBlitz lo adora assolutamente! + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + Starlight è stato un game changer per me, permettendomi di concentrarmi sulla creazione di contenuti. + + Il suo design intuitivo non solo ottimizza il mio flusso di lavoro ma riduce anche il tempo di onboarding per gli sviluppatori open source. + + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + Ho trascorso un po' più di tempo con Starlight per la documentazione di Course Builder ed è stato ottimo finora. Molte funzionalità utili e in più posso concentrarmi sulla scrittura in Markdown e non smanettare con il sito. + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + Ho iniziato a giocare con Starlight. Devo dire che sono molto colpito dalle prestazioni out-of-the-box. + + 💯💯💯💯 + + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + Starlight è il modo migliore per iniziare con la documentazione, tra + la potenza e la velocità di Astro, e gli strumenti di Starlight, è un match in + paradiso. + + È stato il mio riferimento per un po' di tempo, e continuo ad amarlo! + + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + Ho usato Starlight nel mio ultimo lavoro e mi è piaciuto molto. Ottimi componenti, design + intuitivo e community super-reattiva (ogni volta che qualcuno aveva bisogno di qualcosa, + loro lo avrebbero implementato quasi subito oppure ti avrebbero detto una soluzione alternativa). Esperienza molto piacevole. + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + La documentazione sul mio sito monorepo sembra migliore che mai grazie a Starlight. È estremamente facile da usare senza perdere tutta la potenza di Astro. Grazie per averci lavorato! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + Starlight è il mio strumento di riferimento per la documentazione. Ha reso super facile aggiungere la documentazione al mio sito web di prodotto fatto con Astro, rispetto alla necessità di usare un sottodominio con un altro strumento. + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + Sto ricostruendo la documentazione della piattaforma WPEngine Atlas. Credimi quando dico che Starlight ha tutto ciò di cui hai bisogno per creare una piattaforma di documentazione di classe A 🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + Prova Starlight! + + Lo uso per alcuni dei miei siti ed è fantastico. + + </Testimonial> +</TestimonialGrid> + <AboutAstro title="Sviluppato da"> -Astro è il framework completo progettato per essere veloce. +Astro è un framework completo progettato per essere veloce. Prendi i tuoi contenuti da dove preferisci e pubblica dove vuoi, il tutto con i tuoi componenti UI e librerie preferite. -[Impara Astro](https://astro.build/) +[Impara di più su Astro](https://astro.build/) </AboutAstro> diff --git a/docs/src/content/docs/it/manual-setup.mdx b/docs/src/content/docs/it/manual-setup.mdx deleted file mode 100644 index 8791ce0df6b..00000000000 --- a/docs/src/content/docs/it/manual-setup.mdx +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: Configurazione manuale -description: Scopri come configurare manualmente Starlight per aggiungerlo a un progetto Astro esistente. ---- - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -Il modo più rapido per creare un nuovo sito Starlight è utilizzare `create astro` come mostrato nella [guida introduttiva](/it/getting-started/#creating-a-new-project). -Se desideri aggiungere Starlight a un progetto Astro esistente, questa guida spiegherà come. - -## Configura Starlight - -Per seguire questa guida, avrai bisogno di un progetto Astro esistente. - -### Aggiungi l'integrazione Starlight - -Starlight è un'[integrazione Astro](https://docs.astro.build/it/guides/integrations-guide/). Aggiungilo al tuo sito eseguendo il comando `astro add` nella directory principale del tuo progetto: - -<Tabs> - <TabItem label="npm"> - ```sh - npx astro add starlight - ``` - - </TabItem> - <TabItem label="pnpm"> - ```sh - pnpm astro add starlight - ``` - </TabItem> - <TabItem label="Yarn"> - ```sh - yarn astro add starlight - ``` - </TabItem> - -</Tabs> - -Questo installerà le dipendenze richieste e aggiungerà Starlight all'array `integrations` nel tuo file di configurazione Astro. - -### Configura l'integrazione - -L'integrazione Starlight è configurata nel file `astro.config.mjs`. - -Aggiungi un `title` per iniziare: - -```js {7-9} -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'Il mio meraviglioso sito di documentazione', - }), - ], -}); -``` - -Trova tutte le opzioni disponibili nel [riferimento per la configurazione di Starlight](/it/reference/configuration/). - -### Configura raccolte di contenuti - -Starlight si basa sulle [raccolte di contenuti](https://docs.astro.build/it/guides/content-collections/) di Astro, che sono configurate nel file `src/content/config.ts`. - -Crea o aggiorna il file di configurazione del contenuto, aggiungendo una raccolta `docs` che utilizza `docsSchema` di Starlight: - -```js ins={3,6} -// src/content/config.ts -import { defineCollection } from 'astro:content'; -import { docsSchema } from '@astrojs/starlight/schema'; - -export const collections = { - docs: defineCollection({ schema: docsSchema() }), -}; -``` - -### Aggiungi contenuto - -Starlight è ora configurato ed è ora di aggiungere alcuni contenuti! - -Crea una directory `src/content/docs/` e inizia aggiungendo un file `index.md`. -Questa sarà la home page del tuo nuovo sito: - -```md ---- -# src/content/docs/index.md -title: I miei documenti -description: Scopri di più sul mio progetto in questo sito di documenti creato con Starlight. ---- - -Benvenuti nel mio progetto! -``` - -Starlight utilizza il routing basato su file, il che significa che ogni file Markdown, MDX o Markdoc in `src/content/docs/` verrà trasformato in una pagina sul tuo sito. I metadati di Frontmatter (i campi `title` e `description` nell'esempio sopra) possono modificare il modo in cui viene visualizzata ciascuna pagina. -Vedi tutte le opzioni disponibili nel [riferimento frontmatter](/it/reference/frontmatter/). - -## Suggerimenti per i siti esistenti - -Se hai un progetto Astro esistente, puoi utilizzare Starlight per aggiungere rapidamente una sezione di documentazione al tuo sito. - -### Usa Starlight in un sottopercorso - -Per aggiungere tutte le pagine Starlight in un sottopercorso, posiziona tutto il contenuto dei tuoi documenti in una sottodirectory di `src/content/docs/`. - -Ad esempio, se le pagine Starlight dovessero iniziare tutte con `/guides/`, aggiungi il contenuto nella directory `src/content/docs/guides/`: - -import FileTree from '../../../components/file-tree.astro'; - -<FileTree> - -- src/ - - content/ - - docs/ - - **guides/** - - guide.md - - index.md - - pages/ -- astro.config.mjs - -</FileTree> - -In futuro, prevediamo di supportare meglio questo caso d'uso per evitare la necessità di una directory all'interno di una directory aggiuntiva in `src/content/docs/`. - -### Usa Starlight con SSR - -Attualmente, Starlight non supporta [distribuzione SSR](https://docs.astro.build/it/guides/server-side-rendering/) utilizzando gli adattatori server di Astro. Speriamo di poterlo supportare presto. diff --git a/docs/src/content/docs/it/reference/configuration.md b/docs/src/content/docs/it/reference/configuration.md deleted file mode 100644 index 950e7cf0106..00000000000 --- a/docs/src/content/docs/it/reference/configuration.md +++ /dev/null @@ -1,426 +0,0 @@ ---- -title: Riferimenti configurazione -description: Una panoramica sulle configurazione supportate da Starlight. ---- - -## Configurare l'integrazione `starlight` - -Starlight è un'integrazione costruita sul framework [Astro](https://astro.build). Puoi configurare il tuo progetto nel file `astro.config.mjs` : - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'Il mio delizioso sito per documentazione', - }), - ], -}); -``` - -Puoi configurare le seguenti opzioni nell'integrazione `starlight`. - -### `title` (obbligatorio) - -**type:** `string` - -Definisce il titolo del tuo sito. Sarà usato nei metadati e nel titolo della finestra. - -### `description` - -**type:** `string` - -Definisce la descrizione del tuo sito. Sarà usato nei metadati condivisi con le engine di ricerca nel tag `<meta name="description">` se `description` non è specificato nell'intestazione della pagina. - -### `logo` - -**type:** [`LogoConfig`](#logoconfig) - -Definisce il logo da rappresentare nella barra di navigazione con o al posto del nome del sito. Puoi definire un singolo `src` o indicare due separate immagini per `light` e `dark`. - -```js -starlight({ - logo: { - src: './src/assets/my-logo.svg', - }, -}); -``` - -#### `LogoConfig` - -```ts -type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( - | { src: string } - | { light: string; dark: string } -); -``` - -### `tableOfContents` - -**type:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` -**default:** `{ minHeadingLevel: 2; maxHeadingLevel: 3; }` - -Configura la tabella dei contenuti vista a destra di ogni pagina. Per predefinite, i titoli `<h2>` e `<h3>` saranno incluse in essa. - -### `editLink` - -**type:** `{ baseUrl: string }` - -Abilita il link "Modifica questa pagina" definendo l'URL base da usare. Il link finale sarà `editLink.baseUrl` + il percorso corrente. Per esempio, per abilitare la possibilità di modificare la repository `withastro/starlight` su GitHub: - -```js -starlight({ - editLink: { - baseUrl: 'https://github.com/withastro/starlight/edit/main/', - }, -}); -``` - -Con questa configurazione, una pagina `/introduction` avrà un link di modifica a `https://github.com/withastro/starlight/edit/main/src/docs/introduction.md`. - -### `sidebar` - -**type:** [`SidebarGroup[]`](#sidebargroup) - -Configura la barra laterale di navigazione del tuo sito. - -Una barra laterale è un array di collegamenti e gruppi di collegamenti. -Ogni elemento avente un `label` e una delle seguenti proprietà: - -- `link` — un singolo colelgamento a uno specifico URL, ad es. `'/home'` o `'https://example.com'`. - -- `items` — an aray contenente più collegamenti della barra laterale e sottogruppi. - -- `autogenerate` — un oggetto indicante una cartella dei tuoi documenti di cui generare automaticamente i collegamenti. - -```js -starlight({ - sidebar: [ - // Un singolo elemento chiamato “Home”. - { label: 'Home', link: '/' }, - // Un gruppo intitolato "Inizia qui" contenente due link. - { - label: 'Inizia qui', - items: [ - { label: 'Introduzione', link: '/intro' }, - { label: 'Prossimi passi', link: '/next-steps' }, - ], - }, - // Un gruppo che si riferisce a tutte le pagine nella cartella reference. - { - label: 'Riferimenti', - autogenerate: { directory: 'reference' }, - }, - ], -}); -``` - -#### Ordinamento - -I gruppi generati automaticamente sono ordinati alfabeticamente. -Per esempio, una pagina generata da `astro.md` apparirà sopra a quella generata da `starlight.md`. - -#### Gruppi comprimibili - -I gruppi di collegamenti vengono espansi per impostazione predefinita. Puoi modificare questo comportamento impostando la proprietà `collapsed` di un gruppo su `true`. - -I sottogruppi generati automaticamente rispettano la proprietà `collapsed` del gruppo principale per impostazione predefinita. Imposta la proprietà `autogenerate.collapsed` per sovrascriverla. - -```js -sidebar: [ - // Un gruppo di collegamenti compresso. - { - label: 'Collegamenti compressi', - collapsed: true, - items: [ - { label: 'Introduzione', link: '/intro' }, - { label: 'Prossimi passi', link: '/next-steps' }, - ], - }, - // An expanded group containing collapsed autogenerated subgroups. - { - label: 'Riferimenti', - autogenerate: { - directory: 'reference', - collapsed: true, - }, - }, -], -``` - -#### Tradurre i titoli - -Se il tuo sito è multilingua, ogni elemento di `label` è considerato come appartenente alla lingua di default. Puoi definire `translations` per fornire i titoli per le altre lingue: - -```js -sidebar: [ - // Un esempio di barra laterale con traduzioni in italiano. - { - label: 'Start here', - translations: { it: 'Inizia qui' }, - items: [ - { - label: 'Getting Started', - translations: { it: 'Iniziamo' }, - link: '/getting-started', - }, - { - label: 'Project Structure', - translations: { it: 'Struttura del progetto' }, - link: '/structure', - }, - ], - }, -], -``` - -#### `SidebarItem` - -```ts -type SidebarItem = { - label: string; - translations?: Record<string, string>; -} & ( - | { - link: string; - badge?: string | BadgeConfig; - } - | { items: SidebarItem[]; collapsed?: boolean } - | { - autogenerate: { directory: string; collapsed?: boolean }; - collapsed?: boolean; - } -); -``` - -#### `BadgeConfig` - -```ts -interface BadgeConfig { - text: string; - variant: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; -} -``` - -### `locales` - -**type:** <code>{ \[dir: string\]: [LocaleConfig](#localeconfig) }</code> - -[Configura l'internazionalizzazione (i18n)](/it/guides/i18n/) del sito impostando quali `locales` sono supportati. - -Ogni elemento deve utilizzare come chiave la cartella dove i file della lingua associata si trovano. - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'My Site', - // Imposta inglese come il linguaggio predefinito. - defaultLocale: 'en', - locales: { - // La documentazione in inglese si trova in `src/content/docs/en/` - en: { - label: 'English', - }, - // La documentazione in cinese semplificato si trova in `src/content/docs/zh/` - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - // La documentazione in arabo si trova in `src/content/docs/ar/` - ar: { - label: 'العربية', - dir: 'rtl', - }, - }, - }), - ], -}); -``` - -#### `LocaleConfig` - -```ts -interface LocaleConfig { - label: string; - lang?: string; - dir?: 'ltr' | 'rtl'; -} -``` - -Puoi impostare le seguenti opzioni per ogni locale: - -##### `label` (obbligatorio) - -**type:** `string` - -L'etichetta per questa lingua da rappresentare agli utenti, per esempio nel selettore di lingue. Spesso vorrai usare il nome della lingua per come l'utente si aspetta di leggere, per esempio `"English"`, `"العربية"`, o `"简体中文"`. - -##### `lang` - -**type:** `string` - -Il tag BCP-47 per la lingua, per esempio `"en"`, `"ar"`, o `"zh-CN"`. Se non lo imposti sarà utilizzato il nome della cartella. - -##### `dir` - -**type:** `'ltr' | 'rtl'` - -Il verso di scrittura della lingua; `"ltr"` per sinistra a destra (predefinita) e `"rtl"` per destra a sinistra. - -#### Lingua principale - -Puoi definire un linguaggio principale senza una cartella `/lang/` definendo `root`: - -```js -starlight({ - locales: { - root: { - label: 'English', - lang: 'en', - }, - it: { - label: 'Italiano', - }, - }, -}); -``` - -Per esempio, questo ti permette di fornire `/getting-started/` come un percorso in inglese e `/it/getting-started/` come quello equivalente in italiano. - -### `defaultLocale` - -**type:** `string` - -Definisce la lingua predefinita del sito. -Il valore deve corrispondere ad una chiave di [`locales`](#locales). -(Se la lingua predefinita è il [root](#lingua-principale), non è necessario). - -Verrà utilizzato come fallback per le pagine non tradotte. - -### `social` - -**type:** `Partial<Record<'bitbucket' | 'codeberg' | 'codePen' | 'discord' | 'github' | 'gitlab' | 'gitter' | 'instagram' | 'linkedin' | 'mastodon' | 'microsoftTeams' | 'stackOverflow' | 'threads' | 'twitch' | 'twitter' | 'youtube', string>>` - -Dettagli opzionali per gli account social del sito. Se vengono aggiunti apparirà l'icona corrispondente nella barra superiore. - -```js -starlight({ - social: { - codeberg: 'https://codeberg.org/knut/examples', - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - gitlab: 'https://gitlab.com/delucis', - linkedin: 'https://www.linkedin.com/company/astroinc', - mastodon: 'https://m.webtoo.ls/@astro', - threads: 'https://www.threads.net/@nmoodev', - twitch: 'https://www.twitch.tv/bholmesdev', - twitter: 'https://twitter.com/astrodotbuild', - youtube: 'https://youtube.com/@astrodotbuild', - }, -}); -``` - -### `customCss` - -**type:** `string[]` - -Utilizza file CSS aggiuntivi per personalizzare il sito Starlight. - -Supporta file CSS locali relativi alla cartella principale del progetto, ad esempio `'/src/custom.css'`, e CSS installato come modulo npm, per esempio `'@fontsource/roboto'`. - -```js -starlight({ - customCss: ['/src/custom-styles.css', '@fontsource/roboto'], -}); -``` - -### `head` - -**type:** [`HeadConfig[]`](#headconfig) - -Aggiunge tag all'`<head>` del sito Starlight. -Può essere utile per aggiungere script e risorse di terze parti. - -```js -starlight({ - head: [ - // Esempio : aggiunge Fathom analytics. - { - tag: 'script', - attrs: { - src: 'https://cdn.usefathom.com/script.js', - 'data-site': 'MY-FATHOM-ID', - defer: true, - }, - }, - ], -}); -``` - -#### `HeadConfig` - -```ts -interface HeadConfig { - tag: string; - attrs?: Record<string, string | boolean | undefined>; - content?: string; -} -``` - -### `lastUpdated` - -**type:** `boolean` -**default:** `false` - -Controlla se il piè di pagina mostra quando è stata aggiornata l'ultima volta la pagina. - -Per impostazione predefinita, questa funzionalità si basa sulla cronologia Git del repository e potrebbe non essere accurata su alcune piattaforme di distribuzione che eseguono [cloni superficiali](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt). Una pagina può sovrascrivere questa impostazione o la data basata su Git utilizzando il [campo frontmatter `lastUpdated`](/it/reference/frontmatter/#lastupdated). - -### `pagination` - -**type:** `boolean` -**default:** `true` - -Definisci se il piè di pagina deve includere i collegamenti alla pagina precedente e successiva. - -Una pagina può sovrascrivere questa impostazione o il testo del collegamento e/o l'URL utilizzando i campi frontmatter [`prev`](/it/reference/frontmatter/#prev) e [`next`](/it/reference/frontmatter/#next). - -### `favicon` - -**type:** `string` -**default:** `'/favicon.svg'` - -Imposta il percorso della favicon predefinita per il tuo sito web che dovrebbe trovarsi nella directory `public/` ed essere valido (`.ico`, `.gif`, `.jpg`, `.png` o `.svg`) file di icone. - -```js -starlight({ - favicon: '/images/favicon.svg', -}), -``` - -Se devi impostare varianti aggiuntive o favicon di fallback, puoi aggiungere tag utilizzando l'[opzione`head`](#head): - -```js -starlight({ - favicon: '/images/favicon.svg'. - head: [ - // Aggiungi il fallback della favicon ICO per Safari. - { - tag: 'link', - attrs: { - rel: 'icon', - href:'/images/favicon.ico', - sizes: '32x32', - }, - }, - ], -}); -``` diff --git a/docs/src/content/docs/it/reference/frontmatter.md b/docs/src/content/docs/it/reference/frontmatter.md deleted file mode 100644 index 3a76d172498..00000000000 --- a/docs/src/content/docs/it/reference/frontmatter.md +++ /dev/null @@ -1,301 +0,0 @@ ---- -title: Riferimenti frontmatter -description: Una panoramica sui campi predefiniti del frontmatter Starlight. ---- - -Puoi personalizzare pagine Markdown e MDX in Starlight definendo i valori nel frontmatter. Per esempio, una pagina potrebbe definire `title` e `description` : - -```md ---- -title: A proposito del progetto -description: Scopri di più sul progetto a cui sto lavorando. ---- - -Benvenuto alla pagina "a proposito del progetto"! -``` - -## Campi del frontmatter - -### `title` (obbligatorio) - -**type:** `string` - -Devi fornire un titolo ad ogni pagina. Questo sarà usato in testa alla pagina, nelle finestre del browser e nei metadati della pagina. - -### `description` - -**type:** `string` - -La descrizione è utilizzata nei metadati e sarà utilizzata dai motori di ricerca e nelle anteprime nei social. - -### `editUrl` - -**type:** `string | boolean` - -Sovrascrive la [configurazione globale `editLink`](/it/reference/configuration/#editlink). Metti a `false` per disabilitare "Modifica la pagina" per quella pagina specifica oppure fornisci un link alternativo. - -### `head` - -**type:** [`HeadConfig[]`](/it/reference/configuration/#headconfig) - -Puoi aggiungere tag aggiuntivi nell'`<head>` della pagina utilizzando la chiave `head` nel frontmatter. Questo significa che puoi aggiungere stili personalizzati, metadati o altri tag in una pagina. Il funzionamento è simile [all'opzione globale `head`](/it/reference/configuration/#head). - -```md ---- -title: Chi siamo -head: - # Utilizza un <title> personalizzato - - tag: title - content: Titolo personalizzato ---- -``` - -### `tableOfContents` - -**type:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` - -Sovrascrive la [configurazione globale `tableOfContents`](/it/reference/configuration/#tableofcontents). -Cambia i livelli di titoli inclusi o, se messo a `false`, nasconde la tabella dei contenuti della pagina. - -```md ---- -title: Pagina con solo H2 nella tabella dei contenuti della pagina -tableOfContents: - minHeadingLevel: 2 - maxHeadingLevel: 2 ---- -``` - -```md ---- -title: Pagina senza tabella dei contenuti della pagina -tableOfContents: false ---- -``` - -### `template` - -**type:** `'doc' | 'splash'` -**default:** `'doc'` - -Definisce il layout per la pagina. -Le pagine utilizzano `'doc'` come predefinita. -Se valorizzato a `'splash'` viene utilizzato un layout senza barre laterali ottimale per la pagina iniziale. - -### `hero` - -**type:** [`HeroConfig`](#heroconfig) - -Aggiunge un componente hero all'inizio della pagina. Funziona bene con `template: splash`. - -Per esempio, questa configurazione illustra comuni opzioni, incluso il caricamento di un'immagine. - -```md ---- -title: La mia pagina principale -template: splash -hero: - title: 'Il mio progetto: Stellar Stuff Sooner' - tagline: Porta le tue cose sulla Luna e torna indietro in un battito d'occhio. - image: - alt: Un logo brillante e luminoso - file: ../../assets/logo.png - actions: - - text: Dimmi di più - link: /getting-started/ - icon: right-arrow - variant: primary - - text: Vedi su GitHub - link: https://github.com/astronaut/my-project - icon: external ---- -``` - -#### `HeroConfig` - -```ts -interface HeroConfig { - title?: string; - tagline?: string; - image?: { - alt?: string; - // Percorso relativo ad un’immagine dentro il tuo progetto. - file?: string; - // HTML non elaborato da utilizzare al posto dell'immagine. - // Potrebbe essere un tag personalizzato `<img>` o `<svg>` in linea. - html?: string; - }; - actions?: Array<{ - text: string; - link: string; - variant: 'primary' | 'secondary' | 'minimal'; - icon: string; - }>; -} -``` - -### `banner` - -**type:** `{ content: string }` - -Visualizza un banner di annuncio nella parte superiore di questa pagina. - -Il valore `content` può includere HTML per collegamenti o altri contenuti. -Ad esempio, questa pagina visualizza un banner che include un collegamento a `example.com`. - -```md ---- -title: Pagina con un banner -banner: - content: | - Abbiamo appena lanciato qualcosa di interessante! - <a href="https://example.com">Dai un'occhiata</a> ---- -``` - -### `lastUpdated` - -**type:** `Date | boolean` - -Sostituisce l'[opzione globale `lastUpdated`](/it/reference/configuration/#lastupdated). Se viene specificata una data, deve essere un [timestamp YAML](https://yaml.org/type/timestamp.html) valido e sovrascriverà la data archiviata nella cronologia Git per questa pagina. - -```md ---- -title: Pagina con una data di ultimo aggiornamento personalizzata -lastUpdated: 2022-08-09 ---- -``` - -### `prev` - -**type:** `boolean | string | { link?: string; label?: string }` - -Sostituisce l'[opzione globale `paginazione`](/it/reference/configuration/#pagination). Se viene specificata una stringa, il testo del collegamento generato verrà sostituito e se viene specificato un oggetto, sia il collegamento che il testo verranno sovrascritti. - -```md ---- -# Nascondi il collegamento alla pagina precedente -prev: false ---- -``` - -```md ---- -# Sostituisci il testo del collegamento della pagina precedente -prev: Continua il tutorial ---- -``` - -```md ---- -# Sostituisci sia il collegamento che il testo della pagina precedente -prev: - link: /pagina-non-correlata/ - label: Dai un'occhiata a quest'altra pagina ---- -``` - -### `next` - -**type:** `boolean | string | { link?: string; label?: string }` - -Uguale a [`prev`](#prev) ma per il collegamento alla pagina successiva. - -```md ---- -# Nascondi il collegamento alla pagina successiva -next: false ---- -``` - -### `pagefind` - -**type:** `boolean` -**default:** `true` - -Imposta se questa pagina deve essere inclusa nell'indice di ricerca [Pagefind](https://pagefind.app/). Imposta su `false` per escludere una pagina dai risultati di ricerca: - -```md ---- -# Nascondi questa pagina dai risultati di ricerca -pagefind: false ---- -``` - -### `sidebar` - -**type:** `{ label?: string; order?: number; hidden?: boolean; badge?: string | BadgeConfig }` - -Controlla il modo in cui questa pagina viene visualizzata nella [barra laterale](/it/reference/configuration/#sidebar), quando si utilizza un gruppo di collegamenti generato automaticamente. - -#### `label` - -**type:** `string` -**default:** the page [`title`](#title-required) - -Imposta l'etichetta per questa pagina nella barra laterale quando viene visualizzata in un gruppo di collegamenti generato automaticamente. - -```md ---- -title: Informazioni su questo progetto -sidebar: - label: Informazioni ---- -``` - -#### `order` - -**type:** `number` - -Controlla l'ordine di questa pagina quando ordini un gruppo di collegamenti generato automaticamente. -I numeri più bassi vengono visualizzati più in alto nel gruppo di collegamenti. - -```md ---- -title: Pagina da visualizzare per prima -sidebar: - order: 1 ---- -``` - -#### `hidden` - -**type:** `boolean` -**default:** `false` - -Impedisce che questa pagina venga inclusa in un gruppo della barra laterale generato automaticamente. - -```md ---- -title: Pagina da nascondere dalla barra laterale generata automaticamente -sidebar: - hidden: vero ---- -``` - -#### `badge` - -**type:** <code>string | <a href="/reference/configuration/#badgeconfig">BadgeConfig</a></code> - -Aggiungi un badge alla pagina nella barra laterale quando viene visualizzata in un gruppo di collegamenti generato automaticamente. -Quando si utilizza una stringa, il badge verrà visualizzato con un colore in risalto predefinito. -Facoltativamente, passa un [oggetto `BadgeConfig`](/it/reference/configuration/#badgeconfig) con i campi `text` e `variant` per personalizzare il badge. - -```md ---- -title: Pagina con un badge -sidebar: - # Utilizza la variante predefinita corrispondente al colore principale del tuo sito - badge: nuovo ---- -``` - -```md ---- -title: Pagina con un badge -sidebar: - badge: - text: Sperimentale - variant: caution ---- -``` diff --git a/docs/src/content/docs/it/resources/community-content.mdx b/docs/src/content/docs/it/resources/community-content.mdx new file mode 100644 index 00000000000..1bfa7187adb --- /dev/null +++ b/docs/src/content/docs/it/resources/community-content.mdx @@ -0,0 +1,160 @@ +--- +title: Contenuti della community +description: Scopri guide, articoli e video prodotti dalla community per imparare e costruire con Starlight! +--- + +:::tip[Aggiungi il tuo!] +Hai prodotto dei contenuti su Starlight? +Apri una PR aggiungendo un link a questa pagina! +::: + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +## Articoli e recensioni + +Qui trovi una raccolta di post e articoli per saperne di più su Starlight e le esperienze di altre persone: + +<CardGrid> + <LinkCard + href="https://devm.io/open-source/starlight-astro" + title="Generazione di siti statici con Starlight" + description="“Nessuna idea è troppo grande o troppo piccola quando si progettano componenti” — intervista con Chris Swithinbank, leader di Starlight" + /> + <LinkCard + href="https://frontendatscale.com/blog/hybrid-frontend-architecture/" + title="Architettura frontend ibrida con Astro e Starlight" + description="Maxi Ferreira e Ben Holmes costruiscono un sito di documentazione con Starlight, TinaCMS e un Playground API interattivo con autenticazione." + /> + <LinkCard + href="https://www.olets.dev/posts/comparing-docs-site-builders-vuepress-vs-starlight/" + title="Confronto tra generatori di siti di documentazione: VuePress vs Starlight" + description="Come si confrontano i due framework?" + /> +</CardGrid> + +## Ricette e guide + +Le ricette sono tipicamente brevi guide pratiche che guidano il lettore attraverso il completamento di un esempio funzionante per uno specifico compito. Le ricette sono un ottimo modo per aggiungere nuove funzionalità o comportamenti al tuo progetto Starlight seguendo istruzioni passo passo! Altre guide potrebbero spiegare concetti specifici, come l'uso di immagini o come si lavora con MDX. + +Esplora i contenuti prodotti dalla community e gestiti dagli utenti di Starlight: + +<CardGrid> + <LinkCard + href="https://www.webpro.nl/scraps/versioned-docs-with-starlight-and-vercel" + title="Documentazione versionata con Starlight e Vercel" + description="Una guida all'implementazione di versioni separate della documentazione per ogni versione principale di un progetto" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-heading-links" + title="Aggiungi link agli heading di Starlight" + description="Una guida all'uso di un plugin rehype per condividere link a sezioni specifiche della tua documentazione" + /> + <LinkCard + href="https://blog.otterlord.dev/posts/starlight-sponsors/" + title="Aggiungi sponsor al tuo sito Starlight" + description="Una guida per implementare un componente sponsor personalizzato nella sidebar della tua documentazione" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images" + title="Aggiungi immagini Open Graph a Starlight" + description="Una guida alla generazione di immagini social e dei tag meta corrispondenti per le tue pagine" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-third-party-icon-sets" + title="Usa set di icone di terze parti in Starlight" + description="Una guida all'uso di unplugin-icons per espandere la selezione di icone disponibili per Starlight" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-html-head" + title="Modifica l'HTML head delle pagine di Starlight" + description="Scopri come aggiungere contenuti comuni per l'head come analytics web, font e script" + /> + <LinkCard + href="https://dev.to/mrrobot/publishing-documentation-with-astro-starlight-691" + title="Pubblicare documentazione con Astro Starlight" + description="Come iniziare con la documentazione Starlight" + /> + <LinkCard + href="https://events-3bg.pages.dev/jotter/starlight/guide/" + title="Abilita le Transizioni di Vista" + description="Ottieni quell'aspetto e sensazione simile a SPA con il supporto alle transizioni di vista di Bag of Tricks" + /> + <LinkCard + href="https://jamcomments.com/posts/structured-data-with-starlight" + title="Aggiungere Dati Strutturati alle Pagine Starlight" + description="Impara come costruire dati strutturati JSON-LD dinamici per le tue pagine di documentazione." + /> + <LinkCard + href="https://starlight-examples.netlify.app/" + title="Esempi Starlight" + description="Una raccolta di embed StackBlitz che dimostrano modi pratici di fare cose nei siti di documentazione Starlight." + /> +</CardGrid> + +## Contenuti video + +Scopri video e canali con contenuti Starlight, incluse live streaming e contenuti educativi. + +import YouTubeGrid from '~/components/youtube-grid.astro'; + +### Video di Astro + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=5u0Ds7wzUeI', + title: 'Starlight by Astro', + description: 'Guarda il video di lancio ufficiale di Starlight', + }, + { + href: 'https://www.youtube.com/shorts/zjOWezSzd18', + title: '🌟 ESECUZIONE IN MENO DI 1 MINUTO', + description: + 'Guarda Ben lanciare un nuovo sito Starlight in meno di un minuto!', + }, + ]} +/> + +### Video e Streaming della Community + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=sF6UcV3moZg', + title: 'Costruire documentazione con Starlight e Astro', + description: + 'Guarda Chris e Alex immergersi in Starlight su Code with CodingCat.dev', + }, + { + href: 'https://www.youtube.com/watch?v=sWkkHbwDeQc', + title: 'Astro Starlight', + description: 'Introduzione a Starlight in meno di un minuto.', + }, + { + href: 'https://www.youtube.com/watch?v=-Ki-1E5gNCk', + title: + 'Template di Documentazione Astro Starlight (costruisci documentazione per app personalizzate!)', + description: 'Metti in piedi un nuovo sito Starlight in circa 5 minuti', + }, + { + href: 'https://www.youtube.com/watch?v=12o7WxjAxjM', + title: + 'Includere documentazione Starlight in un progetto Next.js con proxy', + description: + "Configura Starlight come progetto in una sotto-directory all'interno di un sito web Next.js", + }, + { + href: 'https://www.youtube.com/watch?v=5pq80drDrNs', + title: + 'Ho Ricreato la Documentazione di Shadcn in 30 Minuti Con Questo Fantastico Strumento', + description: + 'In questo video spiego cosa rende Starlight così cool e perché potresti volerlo provare nel tuo prossimo progetto.', + }, + { + href: 'https://www.youtube.com/watch?v=Q1E4Gkt63ko', + title: 'Astro Starlight ed emoji-blast con Chris Swithinbank', + description: + 'In cui Chris, il creatore del framework-su-framework Starlight di Astro, mi guida attraverso la sua configurazione per un nuovo sito web emoji-blast. 🌟 🎇', + }, + ]} +/> diff --git a/docs/src/content/docs/it/resources/plugins.mdx b/docs/src/content/docs/it/resources/plugins.mdx new file mode 100644 index 00000000000..a02ff19cfe8 --- /dev/null +++ b/docs/src/content/docs/it/resources/plugins.mdx @@ -0,0 +1,137 @@ +--- +title: Plugin e integrazioni +description: Scopri strumenti della community come plugin e integrazioni che estendono Starlight! +sidebar: + order: 1 +--- + +:::tip[Aggiungi il tuo!] +Hai costruito un plugin o uno strumento per Starlight? +Apri una PR aggiungendo un link a questa pagina! +::: + +## Plugins + +[I plugin](/it/reference/plugins/) possono personalizzare la configurazione, interfaccia utente e comportamento di Starlight, rendendo allo stesso tempo facile la condivisione e il riutilizzo. +Estendi il tuo sito con plugin ufficiali supportati dal team Starlight e plugin della community gestiti dagli utenti Starlight. + +### Plugin ufficiali + +<CardGrid> + <LinkCard + href="/it/guides/site-search/#algolia-docsearch" + title="Algolia DocSearch" + description="Sostituisci Pagefind, il provider di ricerca predefinito, con Algolia DocSearch." + /> +</CardGrid> + +### Plugin della community + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-links-validator" + title="starlight-links-validator" + description="Controlla i link rotti nelle tue pagine Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-typedoc" + title="starlight-typedoc" + description="Genera pagine Starlight da TypeScript usando TypeDoc." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-blog" + title="starlight-blog" + description="Aggiungi un blog alla tua documentazione." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-openapi" + title="starlight-openapi" + description="Crea pagine di documentazione dalle specificazioni OpenAPI/Swagger." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-obsidian" + title="starlight-obsidian" + description="Pubblica i tuoi vault Obsidian nel tuo sito Starlight." + /> + <LinkCard + href="https://astro-ghostcms.xyz/intro/starlight/install/" + title="starlight-ghostcms" + description="Aggiungi i tuoi post del blog GhostCMS insieme alla tua documentazione Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-image-zoom" + title="starlight-image-zoom" + description="Aggiungi la possibilità di ingrandire le immagini della tua documentazione." + /> + <LinkCard + href="https://github.com/lorenzolewis/starlight-utils" + title="starlight-utils" + description="Estendi Starlight con una collezione di utilità comuni." + /> + <LinkCard + href="https://github.com/trueberryless/starlight-view-modes" + title="starlight-view-modes" + description="Aggiungi capacità di diverse modalità di visualizzazione al tuo sito di documentazione." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-versions" + title="starlight-versions" + description="Versiona le tue pagine di documentazione Starlight." + /> + <LinkCard + href="https://inox-tools.fryuni.dev/star-warp" + title="star-warp" + description="Accedi ai risultati di ricerca per la tua documentazione alla velocità della luce." + /> +</CardGrid> + +### Temi della comunità + +Un tema è un plugin di Starlight che modifica l'aspetto visivo di un sito con sostituzioni di componenti, CSS personalizzato o altre nuove funzionalità. + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-theme-rapide" + title="starlight-theme-rapide" + description="Tema Starlight ispirato al tema Vitesse di Visual Studio Code." + /> +</CardGrid> + +## Strumenti e integrazioni della community + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +Questi strumenti e integrazioni della community possono essere utilizzati per aggiungere funzionalità al tuo sito Starlight. + +<CardGrid> + <LinkCard + href="https://www.feelback.dev/blog/new-astro-starlight-integration/" + title="FeelBack" + description="Aggiungi un sistema di feedback utente alle tue pagine di documentazione." + /> + <LinkCard + href="https://github.com/val-town/notion-to-astro" + title="notion-to-astro" + description="Converti la tua documentazione da Notion a Starlight" + /> + <LinkCard + href="https://github.com/mattjennings/astro-live-code" + title="astro-live-code" + description="Rendi interattivi i blocchi di codice MDX" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-i18n" + title="starlight-i18n" + description="Estensione di Visual Studio Code che ti aiuta a tradurre le pagine Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-package-managers" + title="starlight-package-managers" + description="Visualizza rapidamente i comandi relativi a npm per diversi gestori di pacchetti." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-showcases" + title="starlight-showcases" + description="Set di componenti Starlight per creare pagine di showcase." + /> +</CardGrid> diff --git a/docs/src/content/docs/it/resources/showcase.mdx b/docs/src/content/docs/it/resources/showcase.mdx new file mode 100644 index 00000000000..4850a69e290 --- /dev/null +++ b/docs/src/content/docs/it/resources/showcase.mdx @@ -0,0 +1,21 @@ +--- +title: Vetrina Starlight +description: Scopri i siti creati con Starlight! +sidebar: + label: Vetrina siti +--- + +:::tip[Aggiungi il tuo!] +Hai creato un sito con Starlight? +[Apri una PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#showcase) così da aggiungere un link a questa pagina! +::: + +## Siti + +import ShowcaseSites from '~/components/showcase-sites.astro'; + +Starlight è già utilizzato in produzione. Questi sono alcuni dei siti che lo usano: + +<ShowcaseSites /> + +Vedi tutte le [repository di progetti pubblici che usano Starlight su GitHub](https://github.com/withastro/starlight/network/dependents). diff --git a/docs/src/content/docs/it/showcase.mdx b/docs/src/content/docs/it/showcase.mdx deleted file mode 100644 index a3351f3f87c..00000000000 --- a/docs/src/content/docs/it/showcase.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Vetrina Starlight -description: Scopri i siti realizzati con Starlight e gli strumenti della community che estendono Starlight! ---- - -:::tip[Aggiungi il tuo!] -Hai creato un sito Starlight o uno strumento per Starlight? -Apri una PR aggiungendo un link a questa pagina! -::: - -## Sites - -import ShowcaseSites from '../../../components/showcase-sites.astro'; - -Starlight è già utilizzato nella produzione. Questi sono alcuni dei siti presenti sul web: - -<ShowcaseSites /> - -Visualizza tutti i [repository di progetti pubblici che utilizzano Starlight su GitHub](https://github.com/withastro/starlight/network/dependents). - -## Community plugins - -import { CardGrid, LinkCard } from '@astrojs/starlight/components'; - -Questi strumenti della community, plug-in e integrazioni lavorano insieme a Starlight per estenderne le funzionalità. - -<CardGrid> - <LinkCard - href="https://www.feelback.dev/blog/new-astro-starlight-integration/" - title="FeelBack" - description="Aggiungi un sistema di feedback degli utenti alle tue pagine di documenti." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-blog" - title="starlight-blog" - description="Aggiungi un blog al tuo sito di documentazione." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-links-validator" - title="starlight-links-validator" - description="Verifica la presenza di collegamenti interrotti nelle tue pagine Starlight." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-typedoc" - title="starlight-typedoc" - description="Genera pagine Starlight da TypeScript utilizzando TypeDoc." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-openapi" - title="starlight-openapi" - description="Crea pagine di documentazione dalle specifiche OpenAPI/Swagger." - /> -</CardGrid> diff --git a/docs/src/content/docs/ja/404.md b/docs/src/content/docs/ja/404.md index bc32a8baec0..f471d6d1b8f 100644 --- a/docs/src/content/docs/ja/404.md +++ b/docs/src/content/docs/ja/404.md @@ -2,6 +2,7 @@ title: 見つかりませんでした template: splash editUrl: false +lastUpdated: false hero: title: '404' tagline: <strong>Houston、問題が生じました。</strong>ページが見つかりませんでした。<br>URLを確認するか、検索バーを使用してみてください。 diff --git a/docs/src/content/docs/ja/components/asides.mdx b/docs/src/content/docs/ja/components/asides.mdx new file mode 100644 index 00000000000..f9b07263c23 --- /dev/null +++ b/docs/src/content/docs/ja/components/asides.mdx @@ -0,0 +1,192 @@ +--- +title: 補足情報 +description: Starlightで補足情報を使用して、ページのメインコンテンツの横に補足情報を表示する方法を学びます。 +--- + +import { Aside } from '@astrojs/starlight/components'; + +ページのメインコンテンツの横に補足情報を表示するには、`<Aside>`コンポーネントを使用します。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> +<Aside slot="preview"> + `<Aside>`に重要ではない補足情報を含めます。 +</Aside> +</Preview> + +## インポート + +```tsx +import { Aside } from '@astrojs/starlight/components'; +``` + +## 使用方法 + +`<Aside>`コンポーネントを使用して補足情報(「アドモニション」や「コールアウト」とも呼ばれる)を表示します。 + +`<Aside>`にはオプションの[`type`](#type)属性があり、これによって補足情報の色、アイコン、およびデフォルトのタイトルが制御されます。 + +<Preview> + +````mdx +import { Aside } from '@astrojs/starlight/components'; + +<Aside>補足情報のコンテンツ。</Aside> + +<Aside type="caution">注意が必要なコンテンツ。</Aside> + +<Aside type="tip"> + +補足情報には他のコンテンツも対応しています。 + +```js +// たとえば、コードスニペットなど。 +``` + +</Aside> + +<Aside type="danger">パスワードを誰にも教えないでください。</Aside> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% aside %} +補足情報のコンテンツ。 +{% /aside %} + +{% aside type="caution" %} +注意が必要なコンテンツ。 +{% /aside %} + +{% aside type="tip" %} +補足情報には他のコンテンツも対応しています。 + +```js +// たとえば、コードスニペットなど。 +``` +{% /aside %} + +{% aside type="danger" %} +パスワードを誰にも教えないでください。 +{% /aside %} +```` + +</Fragment> + +<Fragment slot="preview"> + + <Aside>補足情報のコンテンツ。</Aside> + + <Aside type="caution">注意が必要なコンテンツ。</Aside> + + <Aside type="tip"> + + 補足情報には他のコンテンツも対応しています。 + + ```js + // たとえば、コードスニペットなど。 + ``` + </Aside> + + <Aside type="danger">パスワードを誰にも教えないでください。</Aside> + +</Fragment> + +</Preview> + +Starlightは、`<Aside>`コンポーネントの代替として、MarkdownとMDXで補足情報をレンダリングするためのカスタム構文も提供しています。 +カスタム構文の詳細については、["MarkdownでのContent作成"](/ja/guides/authoring-content/#補足情報)ガイドを参照してください。 + +### カスタムタイトルの使用 + +[`title`](#title)属性を使用して、デフォルトの補足情報タイトルを上書きできます。 + +<Preview> + +```mdx 'title="注意してください!"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="caution" title="注意してください!"> + カスタムタイトル*付きの*警告補足情報。 +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'title="注意してください!"' +{% aside type="caution" title="注意してください!" %} +カスタムタイトル*付きの*警告補足情報。 +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="caution" title="注意してください!"> + カスタムタイトル*付きの*警告補足情報。 +</Aside> + +</Preview> + +### カスタムアイコンの使用 + +[`icon`](#icon)属性を使用して、デフォルトの補足情報アイコンを上書きできます。 +値には、[Starlightの組み込みアイコン](/ja/reference/icons/#すべてのアイコン)の名前を指定します。 + +<Preview> + +```mdx 'icon="starlight"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="tip" icon="starlight"> + カスタムアイコン*付きの*ヒント補足情報。 +</Aside> +``` + + <Fragment slot="markdoc"> + +```markdoc 'icon="starlight"' +{% aside type="tip" icon="starlight" %} +カスタムアイコン*付きの*ヒント補足情報。 +{% /aside %} +``` + + </Fragment> + +<Aside slot="preview" type="tip" icon="starlight"> + カスタムアイコン*付きの*ヒント補足情報。 +</Aside> + +</Preview> + +## `<Aside>` プロパティ + +**実装:** [`Aside.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Aside.astro) + +`<Aside>`コンポーネントは以下のプロパティを受け入れます: + +### `type` + +**型:** `'note' | 'tip' | 'caution' | 'danger'` +**デフォルト:** `'note'` + +表示する補足情報のタイプ: + +- `note`補足情報(デフォルト)は青色で、情報アイコンを表示します。 +- `tip`補足情報は紫色で、ロケットアイコンを表示します。 +- `caution`補足情報は黄色で、三角形の警告アイコンを表示します。 +- `danger`補足情報は赤色で、八角形の警告アイコンを表示します。 + +### `title` + +**型:** `string` + +補足情報に表示するタイトル。 +`title`が設定されていない場合、現在の補足情報に`type`のデフォルトタイトルが使用されます。 + +### `icon` + +**型:** [`StarlightIcon`](/ja/reference/icons/#starlighticon-型) + +補足情報に`icon`属性を設定して、[Starlightの組み込みアイコン](/ja/reference/icons/#すべてのアイコン)の名前を指定できます。 diff --git a/docs/src/content/docs/ja/components/badges.mdx b/docs/src/content/docs/ja/components/badges.mdx new file mode 100644 index 00000000000..82edfce2c93 --- /dev/null +++ b/docs/src/content/docs/ja/components/badges.mdx @@ -0,0 +1,150 @@ +--- +title: バッジ +description: Starlightでバッジを使用して追加の情報を表示する方法を学びましょう。 +--- + +import { Badge } from '@astrojs/starlight/components'; + +ステータスやカテゴリーのような小さな情報を表示するには、`<Badge>`コンポーネントを使用します。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Badge slot="preview" text="新着" /> + +</Preview> + +## インポート + +```tsx +import { Badge } from '@astrojs/starlight/components'; +``` + +## 使用方法 + +バッジを表示するには、`<Badge>`コンポーネントを使用し、表示したい内容を[`text`](#text)属性に渡します。 + +デフォルトでは、バッジはサイトのテーマのアクセントカラーを使用します。 +組み込みのバッジカラーを使用するには、[`variant`](#variant)属性をサポートされている値のいずれかに設定します。 + +<Preview> + +```mdx +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="ノート" variant="note" /> +- <Badge text="成功" variant="success" /> +- <Badge text="ヒント" variant="tip" /> +- <Badge text="注意" variant="caution" /> +- <Badge text="危険" variant="danger" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +- {% badge text="ノート" variant="note" /%} +- {% badge text="危険" variant="success" /%} +- {% badge text="ヒント" variant="tip" /%} +- {% badge text="注意" variant="caution" /%} +- {% badge text="危険" variant="danger" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="ノート" variant="note" /> + - <Badge text="成功" variant="success" /> + - <Badge text="ヒント" variant="tip" /> + - <Badge text="注意" variant="caution" /> + - <Badge text="危険" variant="danger" /> +</Fragment> + +</Preview> + +### 異なるサイズの使用 + +[`size`](#size)属性を使用してバッジのテキストサイズを制御します。 + +<Preview> + +```mdx /size="\w+"/ +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="新着" size="small" /> +- <Badge text="新着かつ改良" size="medium" /> +- <Badge text="新着、改良、もっと大きく" size="large" /> +``` + +<Fragment slot="markdoc"> + +```markdoc /size="\w+"/ +- {% badge text="新着" size="small" /%} +- {% badge text="新着かつ改良" size="medium" /%} +- {% badge text="新着、改良、もっと大きく" size="large" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="新着" size="small" /> + - <Badge text="新着かつ改良" size="medium" /> + - <Badge text="新着、改良、もっと大きく" size="large" /> +</Fragment> + +</Preview> + +### バッジのカスタマイズ + +カスタムCSSを使用して、`class`や`style`などの他の`<span>`属性を使用してバッジをカスタマイズします。 + +<Preview> + +```mdx "style={{ fontStyle: 'italic' }}" +import { Badge } from '@astrojs/starlight/components'; + +<Badge text="カスタム" variant="success" style={{ fontStyle: 'italic' }} /> +``` + +<Fragment slot="markdoc"> + +```markdoc 'style="font-style: italic;"' +{% badge text="カスタム" variant="success" style="font-style: italic;" /%} +``` + +</Fragment> + +<Badge + slot="preview" + text="カスタム" + variant="success" + style={{ fontStyle: 'italic' }} +/> + +</Preview> + +## `<Badge>` プロパティ + +**実装:** [`Badge.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Badge.astro) + +`<Badge>`コンポーネントは、以下のプロパティおよびその他の[`<span>`要素の属性](https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes)を受け付けます。 + +### `text` + +**必須** +**型:** `string` + +バッジに表示するテキスト内容。 + +### `variant` + +**型:** `'note' | 'danger' | 'success' | 'caution' | 'tip' | 'default'` +**デフォルト:** `'default'` + +使用するバッジのカラーバリアント: `note` (青), `tip` (紫), `danger` (赤), `caution` (オレンジ), `success` (緑), または `default` (テーマのアクセントカラー)。 + +### `size` + +**型:** `'small' | 'medium' | 'large'` + +表示するバッジのサイズを定義します。 diff --git a/docs/src/content/docs/ja/components/card-grids.mdx b/docs/src/content/docs/ja/components/card-grids.mdx new file mode 100644 index 00000000000..0fa6ad512ac --- /dev/null +++ b/docs/src/content/docs/ja/components/card-grids.mdx @@ -0,0 +1,173 @@ +--- +title: カードグリッド +description: Starlightで複数のカードをグリッドにラップする方法を学びます。 +sidebar: + order: 4 +--- + +import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; + +複数の[`<Card>`](/ja/components/cards/)または[`<LinkCard>`](/ja/components/link-cards/)コンポーネントをグリッドにラップするには、`<CardGrid>`コンポーネントを使用します。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<CardGrid slot="preview"> + <Card title="恒星" icon="star"> + シリウス、ベガ、ベテルギウス + </Card> + <Card title="衛星" icon="moon"> + イオ、エウロパ、ガニメデ + </Card> +</CardGrid> + +</Preview> + +## インポート + +```tsx +import { CardGrid } from '@astrojs/starlight/components'; +``` + +## 使用方法 + +### カードをグループ化する + +`<CardGrid>`コンポーネントを使用してグループ化することで、十分なスペースがある場合に複数の[`<Card>`](/ja/components/cards/)コンポーネントを並べて表示します。 + +<Preview> + +```mdx {3,10} +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <Card title="これをチェック" icon="open-book"> + 強調したい興味深いコンテンツ。 + </Card> + <Card title="その他の機能" icon="information"> + 共有したいその他の情報。 + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,9} +{% cardgrid %} +{% card title="これをチェック" icon="open-book" %} +強調したい興味深いコンテンツ。 +{% /card %} + +{% card title="その他の機能" icon="information" %} +共有したいその他の情報。 +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <Card title="これをチェック" icon="open-book"> + 強調したい興味深いコンテンツ。 + </Card> + <Card title="その他の機能" icon="information"> + 共有したいその他の情報。 + </Card> +</CardGrid> + +</Preview> + +### リンクカードをグループ化する + +`<CardGrid>`コンポーネントを使用してグループ化することで、十分なスペースがある場合に複数の[`<LinkCard>`](/ja/components/link-cards/)コンポーネントを並べて表示します。 + +<Preview> + +```mdx {3,6} +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <LinkCard title="Markdownの作成" href="/ja/guides/authoring-content/" /> + <LinkCard title="コンポーネント" href="/ja/components/using-components/" /> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,5} +{% cardgrid %} +{% linkcard title="Markdownの作成" href="/ja/guides/authoring-content/" /%} + +{% linkcard title="コンポーネント" href="/ja/components/using-components/" /%} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <LinkCard title="Markdownの作成" href="/ja/guides/authoring-content/" /> + <LinkCard title="コンポーネント" href="/ja/components/using-components/" /> +</CardGrid> + +</Preview> + +### カードをずらす + +視覚的な興味を加えるために、`<CardGrid>`コンポーネントに[`stagger`](#カードをずらす)属性を追加してグリッドの2列目を垂直方向にずらします。 + +この属性は、プロジェクトの主要な機能を表示するホームページで便利です。 + +<Preview> + +```mdx "stagger" +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid stagger> + <Card title="これをチェック" icon="open-book"> + 強調したい興味深いコンテンツ。 + </Card> + <Card title="その他の機能" icon="information"> + 共有したいその他の情報。 + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc "stagger=true" +{% cardgrid stagger=true %} +{% card title="これをチェック" icon="open-book" %} +強調したい興味深いコンテンツ。 +{% /card %} + +{% card title="その他の機能" icon="information" %} +共有したいその他の情報。 +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview" stagger> + <Card title="これをチェック" icon="open-book"> + 強調したい興味深いコンテンツ。 + </Card> + <Card title="その他の機能" icon="information"> + 共有したいその他の情報。 + </Card> +</CardGrid> + +</Preview> + +## `<CardGrid>` プロパティ + +**実装:** [`CardGrid.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/CardGrid.astro) + +`<CardGrid>`コンポーネントは以下のプロパティを受け入れます: + +### `stagger` + +**型:** `boolean` + +グリッド内のカードをずらすかどうかを定義します。 diff --git a/docs/src/content/docs/ja/components/cards.mdx b/docs/src/content/docs/ja/components/cards.mdx new file mode 100644 index 00000000000..ef4557bd8e1 --- /dev/null +++ b/docs/src/content/docs/ja/components/cards.mdx @@ -0,0 +1,106 @@ +--- +title: カード +description: Starlightでコンテンツをボックス内に表示するためのカードの使用方法を学びます。 +sidebar: + order: 2 +--- + +import { Card } from '@astrojs/starlight/components'; + +Starlightのスタイルに合わせてコンテンツをボックス内に表示するには、`<Card>`コンポーネントを使用します。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + <Card slot="preview" title="衛星" icon="moon"> + イオ、エウロパ、ガニメデ + </Card> +</Preview> + +## インポート + +```tsx +import { Card } from '@astrojs/starlight/components'; +``` + +## 使用方法 + +`<Card>`コンポーネントを使用してカードを表示し、カードの[`title`](#title)を提供します。 + +<Preview> + +```mdx +import { Card } from '@astrojs/starlight/components'; + +<Card title="これをチェック">強調したい興味深いコンテンツ。</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% card title="これをチェック" %} +強調したい興味深いコンテンツ。 +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="これをチェック"> + 強調したい興味深いコンテンツ。 +</Card> + +</Preview> + +### カードにアイコンを追加する + +[Starlightの組み込みアイコン](/ja/reference/icons/#すべてのアイコン)の名前を[`icon`](#icon)属性に設定して、カードにアイコンを含めることができます。 + +<Preview> + +```mdx 'icon="star"' +import { Card } from '@astrojs/starlight/components'; + +<Card title="恒星" icon="star"> + シリウス、ベガ、ベテルギウス +</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="star"' +{% card title="恒星" icon="star" %} +シリウス、ベガ、ベテルギウス +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="恒星" icon="star"> + シリウス、ベガ、ベテルギウス +</Card> + +</Preview> + +### カードをグループ化する + +[`<CardGrid>`](/ja/components/card-grids/)コンポーネントを使用してグループ化することで、十分なスペースがある場合に複数のカードを並べて表示できます。 +例については、["カードのグループ化"](/ja/components/card-grids/#カードをグループ化する)ガイドを参照してください。 + +## `<Card>` プロパティ + +**実装:** [`Card.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Card.astro) + +`<Card>`コンポーネントは以下のプロパティを受け入れます: + +### `title` + +**必須** +**型:** `string` + +表示するカードのタイトル。 + +### `icon` + +**型:** `string` + +カードには[Starlightの組み込みアイコン](/ja/reference/icons/#すべてのアイコン)の名前に設定された`icon`属性を含めることができます。 diff --git a/docs/src/content/docs/ja/components/code.mdx b/docs/src/content/docs/ja/components/code.mdx new file mode 100644 index 00000000000..4c775e70d26 --- /dev/null +++ b/docs/src/content/docs/ja/components/code.mdx @@ -0,0 +1,103 @@ +--- +title: コード +description: StarlightでMarkdownのコードブロックを使わずにシンタックスハイライトされたコードを表示する方法を学びましょう。 +--- + +import { Code } from '@astrojs/starlight/components'; + +`<Code>`コンポーネントは、シンタックスハイライトされたコードをレンダリングします。 +これは、[Markdownのコードブロック](/ja/guides/authoring-content/#コードブロック)を使用できない場合、例えば、ファイルやデータベース、APIから取得したデータを表示する場合に便利です。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Code + slot="preview" + code={`## ようこそ + +**宇宙**からこんにちは!`} +lang="md" +title="example.md" +ins={3} +/> + +</Preview> + +## インポート + +```tsx +import { Code } from '@astrojs/starlight/components'; +``` + +## 使用方法 + +外部ソースから取得したコードを表示する場合などに、`<Code>`コンポーネントを使用してシンタックスハイライトされたコードをレンダリングします。 + +完全な使用方法と利用可能なプロパティのリストについては、[Expressive Codeの「Codeコンポーネント」ドキュメント](https://expressive-code.com/key-features/code-component/)を参照してください。 + +<Preview> + +```mdx +import { Code } from '@astrojs/starlight/components'; + +export const exampleCode = `console.log('これはファイルやCMSから来る可能性がある!');`; +export const fileName = 'example.js'; +export const highlights = ['ファイル', 'CMS']; + +<Code code={exampleCode} lang="js" title={fileName} mark={highlights} /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% code + code="console.log('これはファイルやCMSから来る可能性がある!');" + lang="js" + title="example.js" + meta="'ファイル' 'CMS'" /%} +``` + +</Fragment> + +export const exampleCode = `console.log('これはファイルやCMSから来る可能性がある!');`; +export const fileName = 'example.js'; +export const highlights = ['ファイル', 'CMS']; + +<Code + slot="preview" + code={exampleCode} + lang="js" + title={fileName} + mark={highlights} +/> + +</Preview> + +### インポートしたコードを表示する + +MDXファイルやAstroコンポーネント内で、[Viteの`?raw`インポートサフィックス](https://ja.vite.dev/guide/assets#importing-asset-as-string)を使用して、任意のコードファイルを文字列としてインポートできます。 +その後、このインポートした文字列を`<Code>`コンポーネントに渡して、ページにコードを表示することができます。 + +<Preview> + +```mdx "?raw" +# src/content/docs/example.mdx + +import { Code } from '@astrojs/starlight/components'; +import importedCode from '/tsconfig.json?raw'; + +<Code code={importedCode} lang="json" title="tsconfig.json" /> +``` + +import importedCode from '../../../../../../examples/basics/tsconfig.json?raw'; + +<Code slot="preview" code={importedCode} lang="json" title="tsconfig.json" /> + +</Preview> + +## `<Code>` プロパティ + +**実装:** [`Code.astro`](https://github.com/expressive-code/expressive-code/blob/main/packages/astro-expressive-code/components/Code.astro) + +`<Code>`コンポーネントは、[Expressive Codeの「Codeコンポーネント」ドキュメント](https://expressive-code.com/key-features/code-component/#available-props)に記載されているすべてのプロパティを受け付けます。 diff --git a/docs/src/content/docs/ja/components/file-tree.mdx b/docs/src/content/docs/ja/components/file-tree.mdx new file mode 100644 index 00000000000..2e04a424cfb --- /dev/null +++ b/docs/src/content/docs/ja/components/file-tree.mdx @@ -0,0 +1,222 @@ +--- +title: ファイルツリー +description: Starlightでファイルアイコンや折りたたみ可能なサブディレクトリを使ってディレクトリ構造を表示する方法を学びましょう。 +--- + +import { FileTree } from '@astrojs/starlight/components'; + +ファイルアイコンや折りたたみ可能なサブディレクトリを使ってディレクトリ構造を表示するには、`<FileTree>`コンポーネントを使用します。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<FileTree slot="preview"> + +- astro.config.mjs **重要な**ファイル +- package.json +- README.md +- src + - components + - **Header.astro** + - … +- pages/ + +</FileTree> + +</Preview> + +## インポート + +```tsx +import { FileTree } from '@astrojs/starlight/components'; +``` + +## 使用方法 + +`<FileTree>`コンポーネントを使用して、ファイルアイコンや折りたたみ可能なサブディレクトリを含むファイルツリーを表示します。 + +ファイルやディレクトリの構造を指定するには、[Markdownの箇条書きリスト](https://www.markdownguide.org/basic-syntax/#unordered-lists)を`<FileTree>`の内部で使用します。サブディレクトリを作成するには、ネストしたリストを作成するか、リスト項目の末尾に `/` を追加して、特定の内容を持たないディレクトリとして表示します。 + +<Preview> + +```mdx +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% filetree %} +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> + +</Preview> + +### エントリを強調表示する + +ファイルやディレクトリの名前を太字にして目立たせることができます。例: `**README.md**`。 + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - **Header.astro** + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> + +</Preview> + +### コメントを追加する + +ファイルやディレクトリにコメントを追加するには、名前の後にテキストを追加します。コメントには、太字や斜体などのMarkdownのインライン形式がサポートされています。 + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro **重要な**ファイル + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - Header.astro **重要な**ファイル + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro **重要な**ファイル + - Title.astro + +</FileTree> + +</Preview> + +### プレースホルダーを追加する + +`...`または`…`を名前として使用することで、プレースホルダーファイルやディレクトリを追加できます。これは、フォルダがさらに多くのアイテムを含むことが期待されていることを読者に示しながら、それらをすべて明示的に指定する必要がない場合に便利です。 + +<Preview> + +```mdx {8} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro + - … + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {5} +{% filetree %} +- src + - components + - Header.astro + - … +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro + - … + +</FileTree> + +</Preview> + +## `<FileTree>` プロパティ + +**実装:** [`FileTree.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/FileTree.astro) + +`<FileTree>`コンポーネントはプロパティを受け付けません。 diff --git a/docs/src/content/docs/ja/components/icons.mdx b/docs/src/content/docs/ja/components/icons.mdx new file mode 100644 index 00000000000..447e05d2784 --- /dev/null +++ b/docs/src/content/docs/ja/components/icons.mdx @@ -0,0 +1,124 @@ +--- +title: アイコン +description: Starlightでアイコンを表示する方法を学びましょう。 +--- + +import { Icon } from '@astrojs/starlight/components'; + +Starlightの[組み込みアイコンセット](/ja/reference/icons/#すべてのアイコン)からアイコンを表示するには、`<Icon>`コンポーネントを使用します。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Icon + slot="preview" + name="open-book" + color="var(--sl-color-text-accent)" + size="4rem" +/> + +</Preview> + +## インポート + +```tsx +import { Icon } from '@astrojs/starlight/components'; +``` + +## 使用方法 + +`<Icon>`コンポーネントを使用してアイコンを表示します。アイコンには[`name`](#name)が必要で、これは[Starlightの組み込みアイコン](/ja/reference/icons/#すべてのアイコン)のいずれかに設定されます。また、オプションでスクリーンリーダー向けに[`label`](#label)を追加して文脈を提供することができます。 + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" /> +<Icon name="starlight" label="Starlightのロゴ" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" /%} +{% icon name="starlight" label="Starlightのロゴ" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" /> + <Icon name="starlight" label="Starlightのロゴ" /> +</Fragment> + +</Preview> + +### アイコンのカスタマイズ + +[`size`](#size)や[`color`](#color)属性を使用して、CSS単位やカラーバリューを使ってアイコンの外観を調整できます。また、[`class`](#class)属性を使用してカスタムCSSクラスをアイコンに追加することができます。 + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" color="goldenrod" size="2rem" /> +<Icon name="rocket" color="var(--sl-color-text-accent)" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" color="goldenrod" size="2rem" /%} +{% icon name="rocket" color="var(--sl-color-text-accent)" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" color="goldenrod" size="2rem" /> + <Icon name="rocket" color="var(--sl-color-text-accent)" /> +</Fragment> + +</Preview> + +## `<Icon>` プロパティ + +**実装:** [`Icon.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Icon.astro) + +`<Icon>`コンポーネントは以下のプロパティを受け付けます。 + +### `name` + +**必須** +**型:** [`StarlightIcon`](/ja/reference/icons/#starlighticon-型) + +表示するアイコンの名前を[Starlightの組み込みアイコン](/ja/reference/icons/#すべてのアイコン)の1つに設定します。 + +### `label` + +**型:** `string` + +スクリーンリーダーなどの支援技術に文脈を提供するためのオプションのラベル。 + +`label`が設定されていない場合、アイコンは支援技術から完全に隠されます。この場合、アイコンがなくても文脈が理解できることを確認してください。例えば、アイコンのみが含まれるリンクには、アクセシビリティを確保するために`label`属性が**必ず**含まれている必要がありますが、リンクにテキストが含まれ、アイコンが純粋に装飾的なものである場合は、`label`を省略することが理にかなっています。 + +### `size` + +**型:** `string` + +CSS単位でアイコンのサイズを指定します。 + +### `color` + +**型:** `string` + +CSSカラーバリューを使用してアイコンの色を指定します。 + +### `class` + +**型:** `string` + +アイコンにカスタムCSSクラスを追加します。 diff --git a/docs/src/content/docs/ja/components/link-buttons.mdx b/docs/src/content/docs/ja/components/link-buttons.mdx new file mode 100644 index 00000000000..64215448360 --- /dev/null +++ b/docs/src/content/docs/ja/components/link-buttons.mdx @@ -0,0 +1,145 @@ +--- +title: リンクボタン +description: 視覚的に目立つコールトゥアクションリンクをStarlightで作成する方法を学びましょう。 +--- + +import { LinkButton } from '@astrojs/starlight/components'; + +視覚的に目立つコールトゥアクションリンクを表示するには、`<LinkButton>`コンポーネントを使用します。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkButton slot="preview" href="/ja/getting-started/"> + ドキュメントを読む +</LinkButton> + +</Preview> + +## インポート + +```tsx +import { LinkButton } from '@astrojs/starlight/components'; +``` + +## 使用方法 + +`<LinkButton>`コンポーネントを使用して、視覚的に目立つコールトゥアクションリンクを表示します。 +リンクボタンは、ユーザーを最も関連性の高いコンテンツやアクションにつなげるために便利で、ランディングページなどでよく使用されます。 + +`<LinkButton>`には[`href`](#href)属性が必要です。 +オプションとして、[`variant`](#variant)属性を使用して、ボタンの外観をカスタマイズできます。`variant`属性には`primary`(デフォルト)、`secondary`、`minimal`のいずれかを指定できます。 + +<Preview> + +```mdx +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton href="/ja/getting-started/">始めましょう</LinkButton> +<LinkButton href="/ja/reference/configuration/" variant="secondary"> + 設定リファレンス +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkbutton href="/ja/getting-started/" %}始めましょう{% /linkbutton %} + +{% linkbutton href="/ja/reference/configuration/" variant="secondary" %} +設定リファレンス +{% /linkbutton %} +``` + +</Fragment> + +<Fragment slot="preview"> + <LinkButton href="/ja/getting-started/">始めましょう</LinkButton> + <LinkButton href="/ja/reference/configuration/" variant="secondary"> + 設定リファレンス + </LinkButton> +</Fragment> + +</Preview> + +### リンクボタンにアイコンを追加する + +[`icon`](#icon)属性を使用して、リンクボタンにアイコンを追加できます。これは、[Starlightの組み込みアイコン](/ja/reference/icons/#すべてのアイコン)の名前を指定します。 + +[`iconPlacement`](#iconplacement)属性を使用すると、アイコンをテキストの前に配置することができ、デフォルトでは`end`(後ろ)ですが、`start`(前)に設定できます。 + +<Preview> + +```mdx {6-7} +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton + href="https://docs.astro.build/ja/" + variant="secondary" + icon="external" + iconPlacement="start" +> + Astroに関連するドキュメント +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc {4-5} +{% linkbutton + href="https://docs.astro.build/ja/" + variant="secondary" + icon="external" + iconPlacement="start" %} +Astroに関連するドキュメント +{% /linkbutton %} +``` + +</Fragment> + +<LinkButton + slot="preview" + href="https://docs.astro.build/ja/" + variant="secondary" + icon="external" + iconPlacement="start" +> + Astroに関連するドキュメント +</LinkButton> + +</Preview> + +## `<LinkButton>` プロパティ + +**実装:** [`LinkButton.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkButton.astro) + +`<LinkButton>`コンポーネントは以下のプロパティを受け付け、[他の`<a>`要素の属性](https://developer.mozilla.org/ja/docs/Web/HTML/Element/a)も使用できます。 + +### `href` + +**必須** +**型:** `string` + +リンクボタンが指すURL。 + +### `variant` + +**型:** `'primary' | 'secondary' | 'minimal'` +**デフォルト:** `'primary'` + +リンクボタンの外観。 +`primary`はテーマのアクセントカラーを使用して目立つコールトゥアクションリンクを作成し、`secondary`はそれほど目立たないリンク、`minimal`は最小限のスタイルのリンクを作成します。 + +### `icon` + +**型:** `string` + +リンクボタンにアイコンを含めるための属性。これは[Starlightの組み込みアイコン](/ja/reference/icons/#すべてのアイコン)の名前を指定します。 + +### `iconPlacement` + +**型:** `'start' | 'end'` +**デフォルト:** `'end'` + +アイコンの配置をテキストの前後どちらにするかを指定します。 diff --git a/docs/src/content/docs/ja/components/link-cards.mdx b/docs/src/content/docs/ja/components/link-cards.mdx new file mode 100644 index 00000000000..28abf82b7e3 --- /dev/null +++ b/docs/src/content/docs/ja/components/link-cards.mdx @@ -0,0 +1,124 @@ +--- +title: リンクカード +description: Starlightでリンクを目立つカードとして表示する方法を学びます。 +sidebar: + order: 3 +--- + +import { LinkCard } from '@astrojs/starlight/components'; + +異なるページへのリンクを目立たせて表示するには、`<LinkCard>`コンポーネントを使用します。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + <LinkCard + slot="preview" + title="Starlightのカスタマイズ" + description="カスタムスタイル、フォントなどを使用して、Starlightサイトを自分のものにする方法を学びます。" + href="/ja/guides/customization/" + /> +</Preview> + +## インポート + +```tsx +import { LinkCard } from '@astrojs/starlight/components'; +``` + +## 使用方法 + +`<LinkCard>`コンポーネントを使用して、リンクを目立たせて表示します。 +各`<LinkCard>`には[`title`](#title)と[`href`](#href)属性が必要です。 + +<Preview> + +```mdx +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard title="Markdownの作成" href="/ja/guides/authoring-content/" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkcard title="Markdownの作成" href="/ja/guides/authoring-content/" /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="Markdownの作成" + href="/ja/guides/authoring-content/" +/> + +</Preview> + +### リンクの説明を追加する + +[`description`](#description)属性を使用して、リンクカードに短い説明を追加します。 + +<Preview> + +```mdx {6} +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard + title="国際化" + href="/ja/guides/i18n/" + description="複数の言語をサポートするようにStarlightを設定します。" +/> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% linkcard + title="国際化" + href="/ja/guides/i18n/" + description="複数の言語をサポートするようにStarlightを設定します。" /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="国際化" + href="/ja/guides/i18n/" + description="複数の言語をサポートするようにStarlightを設定します。" +/> + +</Preview> + +### リンクカードをグループ化する + +[`<CardGrid>`](/ja/components/card-grids/)コンポーネントを使用してグループ化することで、十分なスペースがある場合に複数のリンクカードを並べて表示できます。 + +例については、["リンクカードのグループ化"](/ja/components/card-grids/#リンクカードをグループ化する)ガイドを参照してください。 + +## `<LinkCard>` プロパティ + +**実装:** [`LinkCard.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkCard.astro) + +`<LinkCard>`コンポーネントは、以下のプロパティおよび他のすべての[`<a>`要素の属性](https://developer.mozilla.org/ja/docs/Web/HTML/Element/a)を受け入れます: + +### `title` + +**必須** +**型:** `string` + +表示するリンクカードのタイトル。 + +### `href` + +**必須** +**型:** `string` + +カードが操作されたときにリンクするURL。 + +### `description` + +**型:** `string` + +タイトルの下に表示するオプションの説明。 diff --git a/docs/src/content/docs/ja/components/steps.mdx b/docs/src/content/docs/ja/components/steps.mdx new file mode 100644 index 00000000000..c12cf810e74 --- /dev/null +++ b/docs/src/content/docs/ja/components/steps.mdx @@ -0,0 +1,120 @@ +--- +title: ステップ +description: Starlightでタスクの番号付きリストをスタイル設定してステップバイステップのガイドを作成する方法を学びましょう。 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +タスクの番号付きリストをスタイル設定してステップバイステップのガイドを作成するには、`<Steps>`コンポーネントを使用します。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Steps slot="preview"> + +1. 新しいStarlightプロジェクトを作成します: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm create astro@latest -- --template starlight + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm create astro --template starlight + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn create astro --template starlight + ``` + + </TabItem> + + </Tabs> + +2. 最初のドキュメントページを書きます。 + +</Steps> + +</Preview> + +## インポート + +```tsx +import { Steps } from '@astrojs/starlight/components'; +``` + +## 使用方法 + +`<Steps>`コンポーネントを使用して、タスクの番号付きリストをスタイル設定します。 +各ステップを明確に強調する必要がある、より複雑なステップバイステップガイドに役立ちます。 + +`<Steps>`で標準のMarkdownの順序付きリストを囲みます。 +通常のMarkdown構文はすべて`<Steps>`内で適用されます。 + +<Preview> + +````mdx +import { Steps } from '@astrojs/starlight/components'; + +<Steps> + +1. コンポーネントをMDXファイルにインポートします: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. 順序付きリストのアイテムを`<Steps>`で囲みます。 + +</Steps> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% steps %} + +1. コンポーネントをMDXファイルにインポートします: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. 順序付きリストのアイテムを`<Steps>`で囲みます。 + +{% /steps %} +```` + +</Fragment> + +<Steps slot="preview"> + +1. コンポーネントをMDXファイルにインポートします: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. 順序付きリストのアイテムを`<Steps>`で囲みます。 + +</Steps> + +</Preview> + +## `<Steps>` プロパティ + +**実装:** [`Steps.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Steps.astro) + +`<Steps>`コンポーネントはプロパティを受け付けません。 diff --git a/docs/src/content/docs/ja/components/tabs.mdx b/docs/src/content/docs/ja/components/tabs.mdx new file mode 100644 index 00000000000..8149149584a --- /dev/null +++ b/docs/src/content/docs/ja/components/tabs.mdx @@ -0,0 +1,221 @@ +--- +title: タブ +description: Starlightで同等の情報をグループ化するためのタブインターフェースを作成する方法を学びましょう。 +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +タブインターフェースを作成するには、`<Tabs>`と`<TabItem>`コンポーネントを使用します。 +タブは、ユーザーが複数のオプションのうち1つだけを見る必要がある場合に、同等の情報をグループ化するのに便利です。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Tabs slot="preview"> + <TabItem label="星">シリウス、ベガ、ベテルギウス</TabItem> + <TabItem label="衛星">イオ、エウロパ、ガニメデ</TabItem> +</Tabs> + +</Preview> + +## インポート + +```tsx +import { Tabs, TabItem } from '@astrojs/starlight/components'; +``` + +## 使用方法 + +`<Tabs>`と`<TabItem>`コンポーネントを使用してタブインターフェースを表示します。 +各`<TabItem>`には、ユーザーに表示される[`label`](#label)が必要です。 + +<Preview> + +```mdx +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="星">シリウス、ベガ、ベテルギウス</TabItem> + <TabItem label="衛星">イオ、エウロパ、ガニメデ</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% tabs %} +{% tabitem label="星" %} +シリウス、ベガ、ベテルギウス +{% /tabitem %} + +{% tabitem label="衛星" %} +イオ、エウロパ、ガニメデ +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="星">シリウス、ベガ、ベテルギウス</TabItem> + <TabItem label="衛星">イオ、エウロパ、ガニメデ</TabItem> +</Tabs> + +</Preview> + +### タブを同期させる + +複数のタブグループを同期させるには、[`syncKey`](#synckey)属性を追加します。 + +ページ上のすべての`<Tabs>`に同じ`syncKey`値を設定すると、同じアクティブなラベルが表示されます。 +これにより、読者は一度選択(例: オペレーティングシステムやパッケージマネージャー)すると、その選択がページを移動しても保持されます。 + +関連するタブを同期させるには、各`<Tabs>`コンポーネントに同じ`syncKey`プロパティを追加し、同じ`<TabItem>`ラベルを使用してください。 + +<Preview> + +```mdx 'syncKey="constellations"' +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +_いくつかの星:_ + +<Tabs syncKey="constellations"> + <TabItem label="オリオン座">ベラトリックス、リゲル、ベテルギウス</TabItem> + <TabItem label="ふたご座">ポルックス、カストルA、カストルB</TabItem> +</Tabs> + +_いくつかのエキソプラネット:_ + +<Tabs syncKey="constellations"> + <TabItem label="オリオン座">HD 34445 b、グリーゼ 179 b、Wasp-82 b</TabItem> + <TabItem label="ふたご座">ポルックスb、HAT-P-24b、HD 50554 b</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc 'syncKey="constellations"' +_いくつかの星:_ + +{% tabs syncKey="constellations" %} +{% tabitem label="オリオン座" %} +ベラトリックス、リゲル、ベテルギウス +{% /tabitem %} + +{% tabitem label="ふたご座" %} +ポルックス、カストルA、カストルB +{% /tabitem %} +{% /tabs %} + +_いくつかのエキソプラネット:_ + +{% tabs syncKey="constellations" %} +{% tabitem label="オリオン座" %} +HD 34445 b、グリーゼ 179 b、Wasp-82 b +{% /tabitem %} + +{% tabitem label="ふたご座" %} +ポルックスb、HAT-P-24b、HD 50554 b +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Fragment slot="preview"> + +_いくつかの星:_ + +<Tabs syncKey="constellations"> + <TabItem label="オリオン座">ベラトリックス、リゲル、ベテルギウス</TabItem> + <TabItem label="ふたご座">ポルックス、カストルA、カストルB</TabItem> +</Tabs> + +_いくつかのエキソプラネット:_ + +<Tabs syncKey="constellations"> + <TabItem label="オリオン座">HD 34445 b、グリーゼ 179 b、Wasp-82 b</TabItem> + <TabItem label="ふたご座">ポルックスb、HAT-P-24b、HD 50554 b</TabItem> +</Tabs> + +</Fragment> + +</Preview> + +### タブにアイコンを追加する + +[`icon`](#icon)属性を使用してタブ項目にアイコンを追加し、[Starlightの組み込みアイコン](/ja/reference/icons/#すべてのアイコン)の名前を指定して、ラベルの横にアイコンを表示します。 + +<Preview> + +```mdx /icon="\w+"/ +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="星" icon="star"> + シリウス、ベガ、ベテルギウス + </TabItem> + <TabItem label="衛星" icon="moon"> + イオ、エウロパ、ガニメデ + </TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc /icon="\w+"/ +{% tabs %} +{% tabitem label="星" icon="star" %} +シリウス、ベガ、ベテルギウス +{% /tabitem %} + +{% tabitem label="衛星" icon="moon" %} +イオ、エウロパ、ガニメデ +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="星" icon="star"> + シリウス、ベガ、ベテルギウス + </TabItem> + <TabItem label="衛星" icon="moon"> + イオ、エウロパ、ガニメデ + </TabItem> +</Tabs> + +</Preview> + +## `<Tabs>` プロパティ + +**実装:** [`Tabs.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Tabs.astro) + +`<Tabs>`コンポーネントは複数の`<TabItem>`コンポーネントをグループ化し、以下のプロパティを受け付けます。 + +### `syncKey` + +**型:** `string` + +複数のページにわたってタブグループを同期させるためのキー。 + +## `<TabItem>` プロパティ + +**実装:** [`TabItem.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/TabItem.astro) + +タブは複数のタブ項目から構成され、それぞれ以下のプロパティを持ちます。 + +### `label` + +**必須** +**型:** `string` + +タブ項目には、タブに表示されるテキストを指定する`label`属性が必要です。 + +### `icon` + +**型:** `string` + +各タブ項目には、ラベルの横に表示される[Starlightに組み込まれたアイコン](/ja/reference/icons/#すべてのアイコン)を指定する`icon`属性を設定できます。 diff --git a/docs/src/content/docs/ja/components/using-components.mdx b/docs/src/content/docs/ja/components/using-components.mdx new file mode 100644 index 00000000000..cc92e60e64d --- /dev/null +++ b/docs/src/content/docs/ja/components/using-components.mdx @@ -0,0 +1,87 @@ +--- +title: コンポーネントの使用 +description: StarlightでMDXとMarkdocにコンポーネントを組み込む。 +sidebar: + order: 1 +--- + +コンポーネントを使用すると、UIの一部やスタイリングを一貫して簡単に再利用できます。例えば、リンクカードやYouTube埋め込みなどが挙げられます。Starlightは[MDX](https://mdxjs.com/)と[Markdoc](https://markdoc.dev/)ファイルでのコンポーネントの使用をサポートしており、またよく使う共通コンポーネントも複数提供しています。 + +[Astro Docsでコンポーネントの作成方法についてさらに学ぶ](https://docs.astro.build/ja/basics/astro-components/)。 + +## MDXでコンポーネントを使用する + +コンポーネントを使用するには、MDXファイルにインポートし、JSXタグとしてレンダリングします。見た目はHTMLタグに似ていますが、`import`文で指定した名前に合わせて先頭が大文字で始まります。 + +```mdx +--- +# src/content/docs/example.mdx +title: 私のドキュメントへようこそ +--- + +import { Icon } from '@astrojs/starlight/components'; +import CustomCard from '../../components/CustomCard.astro'; + +<Icon name="open-book" /> + +<CustomCard> + コンポーネントには**ネストされたコンテンツ**も含められます。 +</CustomCard> +``` + +StarlightはAstroを基盤としているため、MDXファイルでは、[AstroがサポートしているUIフレームワーク(React、Preact、Svelte、Vue、Solid、Alpine)](https://docs.astro.build/ja/guides/framework-components/)で作成したコンポーネントを利用できます。詳しくは、Astroドキュメントの[MDXでコンポーネントを使用する](https://docs.astro.build/ja/guides/integrations-guide/mdx/#mdxでコンポーネントを使用する)を参照してください。 + +## Markdocでコンポーネントを使用する + +[Markdocのセットアップガイド](/ja/guides/authoring-content/#markdoc)に従って、Markdocでコンテンツを作成するためのサポートを追加してください。 + +Starlight Markdocプリセットを使用すると、Markdocの`{% %}`タグ構文でStarlightの組み込みコンポーネントを使用できます。MDXとは異なり、Markdocではコンポーネントをインポートする必要がありません。以下の例では、MarkdocファイルでStarlightの[カードコンポーネント](/ja/components/cards/)をレンダリングしています。 + +```markdoc +--- +# src/content/docs/example.mdoc +title: 私のドキュメントへようこそ +--- + +{% card title="星" icon="star" %} +シリウス、ベガ、ベテルギウス +{% /card %} +``` + +Markdocファイルでのコンポーネントの使用方法についての詳細は、[AstroのMarkdocインテグレーションドキュメント](https://docs.astro.build/ja/guides/integrations-guide/markdoc/#コンポーネントのレンダリング)を参照してください。 + +## 組み込みコンポーネント + +Starlightは、一般的なドキュメントのユースケースに対応した組み込みコンポーネントを提供しています。これらのコンポーネントは、MDXファイルでは`@astrojs/starlight/components`パッケージから、Markdocファイルでは[Starlight Markdocプリセット](/ja/guides/authoring-content/#markdoc)から利用できます。 + +利用可能なコンポーネントの一覧と使用方法については、サイドバーを参照してください。 + +## Starlightのスタイルとの互換性 + +Starlightは、Markdownコンテンツにデフォルトのスタイリングを適用します。例えば、要素間にマージンを追加します。これらのスタイルがコンポーネントの外観と競合する場合は、`not-content`クラスをコンポーネントに設定して無効化できます。 + +```astro 'class="not-content"' +--- +// src/components/Example.astro +--- + +<div class="not-content"> + <p>Starlightのデフォルトのコンテンツスタイリングの影響を受けません。</p> +</div> +``` + +## コンポーネントのprops + +`astro/types`の[`ComponentProps`](https://docs.astro.build/ja/guides/typescript/#component-props)型を使用すると、コンポーネント自体が`Props`をエクスポートしていない場合でも、コンポーネントが受け取れる`Props`を参照できます。これは、既存のコンポーネントをラップしたり拡張したりする際に便利です。 + +以下の例では、`ComponentProps`を使用してStarlight組み込みの`Badge`コンポーネントが受け取るpropsの型を取得しています。 + +```astro +--- +// src/components/Example.astro +import type { ComponentProps } from 'astro/types'; +import { Badge } from '@astrojs/starlight/components'; + +type BadgeProps = ComponentProps<typeof Badge>; +--- +``` diff --git a/docs/src/content/docs/ja/environmental-impact.md b/docs/src/content/docs/ja/environmental-impact.md index 3c9f36d38a8..66372e547f7 100644 --- a/docs/src/content/docs/ja/environmental-impact.md +++ b/docs/src/content/docs/ja/environmental-impact.md @@ -5,7 +5,7 @@ description: Starlightがどのように環境に優しいドキュメントサ ウェブ産業が気候に与える影響は、世界の炭素排出量の[2%][sf]から[4%][bbc]であり、航空業界の排出量にほぼ匹敵すると推定されています。ウェブサイトの生態学的影響の計算には多くの複雑な要因がありますが、このガイドではドキュメントサイトの環境への負荷を減らすためのいくつかのヒントを紹介します。 -幸いなことに、Starlightを選ぶことは素晴らしいスタートです。Website Carbon Calculatorによると、このサイトは[テスト対象のウェブページの99%よりもクリーン][sl-carbon]であり、ページ訪問あたり0.01gのCO₂を生成します。 +幸いなことに、Starlightを選ぶことは素晴らしいスタートです。Website Carbon Calculatorによると、このサイトは[テスト対象のウェブページの98%よりもクリーン][sl-carbon]であり、ページ訪問あたり0.01gのCO₂を生成します。 ## ページの重さ @@ -72,31 +72,37 @@ JavaScriptの解析とコンパイルは、ブラウザが実行する最も高 他のドキュメントフレームワークとの比較に興味がありますか?[Website Carbon Calculator][wcc]を用いた以下のテストでは、異なるツールで作成された類似のページを比較しています。 -| フレームー枠 | ページ訪問ごとのCO₂ | -| --------------------------- | ------------------- | -| [Starlight][sl-carbon] | 0.01g | -| [VitePress][vp-carbon] | 0.05g | -| [Docus][dc-carbon] | 0.05g | -| [Sphinx][sx-carbon] | 0.07g | -| [MkDocs][mk-carbon] | 0.10g | -| [Nextra][nx-carbon] | 0.11g | -| [docsify][dy-carbon] | 0.11g | -| [Docusaurus][ds-carbon] | 0.24g | -| [Read the Docs][rtd-carbon] | 0.24g | -| [GitBook][gb-carbon] | 0.71g | - -<small>データは2023年5月14日に収集されたものです。リンクをクリックすると、最新の数値が表示されます。</small> +| フレームワーク | ページ訪問ごとのCO₂ | レート | +| --------------------------- | ------------------- | :----: | +| [Starlight][sl-carbon] | 0.01g | A+ | +| [Sphinx][sx-carbon] | 0.01g | A+ | +| [Read the Docs][rtd-carbon] | 0.03g | A+ | +| [VitePress][vp-carbon] | 0.04g | A | +| [docsify][dy-carbon] | 0.05g | A | +| [mdBook][md-carbon] | 0.05g | A | +| [Nextra][nx-carbon] | 0.05g | A | +| [MkDocs][mk-carbon] | 0.07g | A | +| [Fumadocs][fs-carbon] | 0.07g | A | +| [Docusaurus][ds-carbon] | 0.10g | B | +| [Docus][dc-carbon] | 0.11g | B | +| [GitBook][gb-carbon] | 0.42g | F | +| [Mintlify][mt-carbon] | 0.48g | F | + +<small>データは2025年8月7日に収集されたものです。リンクをクリックすると、最新の数値が表示されます。</small> [sl-carbon]: https://www.websitecarbon.com/website/starlight-astro-build-getting-started/ [vp-carbon]: https://www.websitecarbon.com/website/vitepress-dev-guide-what-is-vitepress/ -[dc-carbon]: https://www.websitecarbon.com/website/docus-dev-introduction-getting-started/ +[dc-carbon]: https://www.websitecarbon.com/website/docus-dev-en-getting-started-project-structure/ [sx-carbon]: https://www.websitecarbon.com/website/sphinx-doc-org-en-master-usage-quickstart-html/ [mk-carbon]: https://www.websitecarbon.com/website/mkdocs-org-getting-started/ +[md-carbon]: https://www.websitecarbon.com/website/rust-lang-github-io-mdbook/ [nx-carbon]: https://www.websitecarbon.com/website/nextra-site-docs-docs-theme-start/ +[fs-carbon]: https://www.websitecarbon.com/website/fumadocs-dev-docs-ui/ [dy-carbon]: https://www.websitecarbon.com/website/docsify-js-org/ [ds-carbon]: https://www.websitecarbon.com/website/docusaurus-io-docs/ [rtd-carbon]: https://www.websitecarbon.com/website/docs-readthedocs-io-en-stable-index-html/ -[gb-carbon]: https://www.websitecarbon.com/website/docs-gitbook-com/ +[gb-carbon]: https://www.websitecarbon.com/website/gitbook-com-docs/ +[mt-carbon]: https://www.websitecarbon.com/website/mintlify-com-docs-quickstart/ ## その他のリソース @@ -118,6 +124,6 @@ JavaScriptの解析とコンパイルは、ブラウザが実行する最も高 [sf]: https://www.sciencefocus.com/science/what-is-the-carbon-footprint-of-the-internet/ [bbc]: https://www.bbc.com/future/article/20200305-why-your-internet-habits-are-not-as-clean-as-you-think [http]: https://httparchive.org/reports/state-of-the-web -[assets]: https://docs.astro.build/ja/guides/assets/ +[assets]: https://docs.astro.build/ja/guides/images/ [islands]: https://docs.astro.build/ja/concepts/islands/ [wcc]: https://www.websitecarbon.com/ diff --git a/docs/src/content/docs/ja/getting-started.mdx b/docs/src/content/docs/ja/getting-started.mdx index c38f6c14c1b..560aa7d6a55 100644 --- a/docs/src/content/docs/ja/getting-started.mdx +++ b/docs/src/content/docs/ja/getting-started.mdx @@ -5,17 +5,18 @@ description: AstroのStarlightで新しいドキュメントサイトを作成 import { Tabs, TabItem } from '@astrojs/starlight/components'; -## 新しいプロジェクトを作成する +Starlightは、[Astro](https://astro.build)の上に構築された、フル機能のドキュメント向けテーマです。このガイドは、あなたが新しいプロジェクトを始める手助けをします。既存のAstroプロジェクトにStarlightを追加するには、[手動セットアップの手順](/ja/manual-setup/)を参照してください。 -Starlightは、[Astro](https://astro.build)の上に構築された、フル機能のドキュメント向けテーマです。 +## クイックスタート -以下のコマンドにより、Astro + Starlightの新しいプロジェクトを作成できます。 +### 新しいプロジェクトの作成 -<Tabs> +ターミナルで以下のコマンドを実行し、Astro + Starlightの新しいプロジェクトを作成します。 + +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# npmで新しいプロジェクトを作成する npm create astro@latest -- --template starlight ``` @@ -23,7 +24,6 @@ npm create astro@latest -- --template starlight <TabItem label="pnpm"> ```sh -# pnpmで新しいプロジェクトを作成する pnpm create astro --template starlight ``` @@ -31,7 +31,6 @@ pnpm create astro --template starlight <TabItem label="Yarn"> ```sh -# yarnで新しいプロジェクトを作成する yarn create astro --template starlight ``` @@ -44,41 +43,53 @@ yarn create astro --template starlight Starlightをブラウザで試すには、[StackBlitzでテンプレートを開きます](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics)。 ::: -## Starlightでコンテンツを作成する +### 開発用サーバーの起動 -以上で、Starlightに新しいコンテンツを追加したり、既存のファイルを持ち込んだりする準備ができました! +ローカルで作業する場合、[Astroの開発サーバー](https://docs.astro.build/ja/reference/cli-reference/#astro-dev)により作業内容のプレビューができ、また変更を加えるとブラウザが自動的に更新されます。 -### ファイルフォーマット +プロジェクトのディレクトリ内で以下のコマンドを実行して、開発サーバーを起動します。 -Starlightでは、MarkdownとMDXでコンテンツを作成できます。(Markdocのサポートは、実験的な[AstroのMarkdocインテグレーション](https://docs.astro.build/ja/guides/integrations-guide/markdoc/)をインストールして追加できます。) +<Tabs syncKey="pkg"> +<TabItem label="npm"> -### ページの追加 +```sh +npm run dev +``` -`src/content/docs/`に`.md`または`.mdx`ファイルを作成して、サイトに新しいページを自動で追加できます。ファイルを整理するためにサブフォルダを追加し、複数のパスセグメントを作成することもできます。 +</TabItem> +<TabItem label="pnpm"> +```sh +pnpm dev ``` -src/content/docs/hello-world.md => your-site.com/hello-world -src/content/docs/guides/faq.md => your-site.com/guides/faq + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev ``` -### 型安全なフロントマター +</TabItem> +</Tabs> -Starlightのページは、ページの表示方法を制御するための、カスタマイズ可能な[共通のフロントマタープロパティ](/ja/reference/frontmatter/)を認識します。 +ターミナルにローカルプレビューのURLが表示されます。このURLを開くと、サイトを閲覧できます。 -```md ---- -title: こんにちは、世界! -description: これはStarlightで作成されたサイトのページです ---- -``` +### コンテンツの追加 -何か重要なことを忘れてしまっていても、Starlightが教えてくれます。 +Starlightに新しいコンテンツを追加したり、既存のファイルを追加したりする準備ができました! -## Starlightサイトをデプロイする +`src/content/docs/`ディレクトリにMarkdownファイルを作成することで、サイトに新しいページを追加できます。 -Starlightサイトの作成とカスタマイズが完了したら、Netlify、Vercel、GitHub Pages、その他多くのお好みのウェブサーバーやホスティングプラットフォームにデプロイできます。 +ファイルベースのルーティングや、MDXとMarkdocファイルのサポートについて、詳しくは[「ページ」](/ja/guides/pages/)ガイドを参照してください。 -[Astroサイトのデプロイについては、Astroのドキュメントを参照してください。](https://docs.astro.build/ja/guides/deploy/) +### 次のステップ + +- **設定:** [「Starlightのカスタマイズ」](/ja/guides/customization/)で、よく使われるオプションについて学びましょう。 +- **ナビゲーション:** [「サイドバーのナビゲーション」](/ja/guides/sidebar/)ガイドで、サイドバーを設定しましょう。 +- **コンポーネント:** [「コンポーネント」](/ja/components/using-components/)ガイドで、カードやタブなどの組み込みコンポーネントを確認しましょう。 +- **拡張:** [「プラグイン」](/ja/resources/plugins/)や[「テーマ」](/ja/resources/themes/)のカタログで、コミュニティ製のアドオンを探してみましょう。 +- **デプロイ:** Astroドキュメントの[「サイトのデプロイ」](https://docs.astro.build/ja/guides/deploy/)ガイドを参考に、あなたの作品を公開しましょう。 ## Starlightを更新する @@ -86,43 +97,38 @@ Starlightサイトの作成とカスタマイズが完了したら、Netlify、V Starlightはベータ版のソフトウェアであるため、頻繁に更新や改善がおこなわれます。Starlightを定期的に更新してください! ::: -StarlightはAstroインテグレーションであり、他の`@astrojs/*`インテグレーションと同様に更新できます。 +StarlightはAstroインテグレーションです。ターミナルで以下のコマンドを実行すると、他のAstroパッケージと一緒にStarlightを更新できます。 -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# npmでStarlightをアップグレードする -npm install @astrojs/starlight@latest +npx @astrojs/upgrade ``` </TabItem> <TabItem label="pnpm"> ```sh -# pnpmでStarlightをアップグレードする -pnpm upgrade @astrojs/starlight --latest +pnpm dlx @astrojs/upgrade ``` </TabItem> <TabItem label="Yarn"> ```sh -# yarnでStarlightをアップグレードする -yarn upgrade @astrojs/starlight --latest +yarn dlx @astrojs/upgrade ``` </TabItem> </Tabs> -各リリースでおこなわれた変更の全リストは、[Starlightのチェンジログ](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md)で確認できます。 +[Starlightのチェンジログ](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md)から、各リリースでおこなわれた変更の全リストを確認できます。 ## Starlightのトラブルシューティング -Starlightの[プロジェクト設定](/ja/reference/configuration/)と[個別ページのフロントマターの設定](/ja/reference/frontmatter/)に関する情報は、このサイトのリファレンスセクションにあります。これらのページを利用して、Starlightサイトが正しく設定され、正常に動作していることを確認してください。 - -コンテンツの追加やStarlightサイトのカスタマイズについては、サイドバーにあるガイドのリストを参照してください。 +[プロジェクト設定](/ja/reference/configuration/)と[個別ページのフロントマターの設定](/ja/reference/frontmatter/)のリファレンスページを確認して、Starlightサイトが正しく設定され、正常に動作していることを確認してください。コンテンツの追加やStarlightサイトのカスタマイズについては、サイドバーにあるガイドを参照してください。 -これらのドキュメントで答えが見つからない場合は、Astroに関してより詳細な記述がある[Astroドキュメント](https://docs.astro.build)を参照してください。Starlightテーマの下でAstroがどのように動作しているかを理解することで、疑問が解消されるかもしれません。 +これらのドキュメントで答えが見つからない場合は、Astroに関してより詳細に記述されている[Astroドキュメント](https://docs.astro.build)を参照してください。Starlightテーマの下でAstroがどのように動作しているかを理解することで、疑問が解消されるかもしれません。 -また、[GithHub上のStarlightのIssue](https://github.com/withastro/starlight/issues)を確認したり、[AstroのDiscord](https://astro.build/chat/)で活発でフレンドリーなコミュニティに助けを求めることもできます!`#support`フォーラムに「starlight」タグを付けて質問を投稿したり、`#starlight`専用のチャンネルにアクセスして、現在の開発などについて議論しましょう! +また、[GitHub上でStarlightのIssue](https://github.com/withastro/starlight/issues)を確認したり、[AstroのDiscord](https://astro.build/chat/)で活発でフレンドリーなコミュニティに助けを求めることもできます!`#support`フォーラムに「starlight」タグを付けて質問を投稿したり、`#starlight`専用のチャンネルにアクセスして、現在の開発などについて議論しましょう! diff --git a/docs/src/content/docs/ja/guides/authoring-content.md b/docs/src/content/docs/ja/guides/authoring-content.md deleted file mode 100644 index 0367e7a1ea7..00000000000 --- a/docs/src/content/docs/ja/guides/authoring-content.md +++ /dev/null @@ -1,208 +0,0 @@ ---- -title: Markdownでのコンテンツ作成 -description: StarlightがサポートするMarkdown構文の概要。 ---- - -Starlightでは、`.md`ファイルにおいて[Markdown](https://daringfireball.net/projects/markdown/)構文のすべての機能を利用できます。また、タイトルや説明文(description)などのメタデータを定義するためのフロントマター[YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f)もサポートしています。 - -MDXやMarkdocを使用する場合、サポートされるMarkdownの機能や使用方法が異なることがあるため、[MDXドキュメント](https://mdxjs.com/docs/what-is-mdx/#markdown)や[Markdocドキュメント](https://markdoc.dev/docs/syntax)を必ず確認してください。 - -## インラインスタイル - -テキストは**太字**、_斜体_、または~~取り消し線~~にできます。 - -```md -テキストは**太字**、_斜体_、または~~取り消し線~~にできます。 -``` - -[別のページにリンク](/ja/getting-started/)できます。 - -```md -[別のページにリンク](/ja/getting-started/)できます。 -``` - -バックティックで`インラインコード`を強調できます。 - -```md -バックティックで`インラインコード`を強調できます。 -``` - -## 画像 - -Starlightは、[Astro組み込みのアセット最適化機能](https://docs.astro.build/ja/guides/assets/)を使用して画像を表示します。 - -MarkdownとMDXは、スクリーンリーダーや支援技術のための代替テキストを含む画像を表示するためのMarkdown構文をサポートしています。 - -![「astro」という単語を中心に据えた惑星と恒星のイラスト](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) - -```md -![「astro」という単語を中心に据えた惑星と恒星のイラスト](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) -``` - -プロジェクトにローカルに保存されている画像についても、相対パスを使用して表示できます。 - -```md -// src/content/docs/page-1.md - -![宇宙空間に浮かぶロケット](../../assets/images/rocket.svg) -``` - -## 見出し - -見出しによりコンテンツを構造化できます。Markdownの見出しは、行の先頭にある`#`の数で示されます。 - -### ページコンテンツを構造化する方法 - -Starlightは、ページタイトルをトップレベルの見出しとして自動的に使用し、また各ページの目次の先頭に「概要」という見出しを含めます。各ページを通常のテキストコンテンツで開始し、ページ上の見出しは`<h2>`以下を使用することをおすすめします。 - -```md ---- -title: Markdownガイド -description: StarlightでのMarkdownの使い方 ---- - -このページでは、StarlightでMarkdownを使用する方法について説明します。 - -## インラインスタイル - -## 見出し -``` - -### 見出しの自動アンカーリンク - -Markdownで見出しを使用するとアンカーリンクが自動的に付与されるため、ページの特定のセクションに直接リンクできます。 - -```md ---- -title: 私のページコンテンツ -description: Starlightの組み込みアンカーリンクの使い方 ---- - -## はじめに - -同じページの下部にある[結論](#結論)にリンクできます。 - -## 結論 - -`https://my-site.com/page1/#はじめに`は、「はじめに」に直接移動します。 -``` - -レベル2(`<h2>`)とレベル3(`<h3>`)の見出しは、ページの目次に自動的に表示されます。 - -## 補足情報 - -補足情報(「警告」や「吹き出し」とも呼ばれます)は、ページのメインコンテンツと並べて補助的な情報を表示するのに便利です。 - -Starlightは、補足情報をレンダリングするためのカスタムMarkdown構文を提供しています。補足情報のブロックは、コンテンツを囲む3つのコロン`:::`によって示し、`note`(注釈)、`tip`(ヒント)、`caution`(注意)、`danger`(危険)というタイプに設定できます。 - -他のMarkdownコンテンツを補足情報の中にネストできますが、補足情報は短く簡潔なコンテンツに最も適しています。 - -### 注釈 - -:::note -Starlightは、[Astro](https://astro.build/)製のドキュメントサイト用ツールキットです。次のコマンドではじめられます。 - -```sh -npm create astro@latest -- --template starlight -``` - -::: - -````md -:::note -Starlightは、[Astro](https://astro.build/)製のドキュメントサイト用ツールキットです。次のコマンドではじめられます。 - -```sh -npm create astro@latest -- --template starlight -``` - -::: -```` - -### カスタムのタイトル - -補足情報のカスタムタイトルを、補足情報のタイプの後ろに角括弧で囲んで指定できます。たとえば`:::tip[ご存知でしたか?]`のようにできます。 - -:::tip[ご存知でしたか?] -Astroでは[「アイランドアーキテクチャ」](https://docs.astro.build/ja/concepts/islands/)を使用して、より高速なWebサイトを構築できます。 -::: - -```md -:::tip[ご存知でしたか?] -Astroでは[「アイランドアーキテクチャ」](https://docs.astro.build/ja/concepts/islands/)を使用して、より高速なWebサイトを構築できます。 -::: -``` - -### その他のタイプ - -注意(Caution)と危険(Danger)の補足は、ユーザーがつまずく可能性のある細かい点に注意を向けさせるのに役立ちます。もしこれらを多用しているとすれば、それはあなたがドキュメントを書いている対象の設計を見直す余地があることのサインかもしれません。 - -:::caution -もしあなたが素晴らしいドキュメントサイトを望んでいないのであれば、[Starlight](../../)は不要かもしれません。 -::: - -:::danger -Starlightの便利な機能のおかげで、ユーザーはより生産的になり、プロダクトはより使いやすくなるかもしれません。 - -- わかりやすいナビゲーション -- ユーザーが設定可能なカラーテーマ -- [国際化機能](/ja/guides/i18n) - -::: - -```md -:::caution -もしあなたが素晴らしいドキュメントサイトを望んでいないのであれば、[Starlight](../../)は不要かもしれません。 -::: - -:::danger -Starlightの便利な機能のおかげで、ユーザーはより生産的になり、プロダクトはより使いやすくなるかもしれません。 - -- わかりやすいナビゲーション -- ユーザーが設定可能なカラーテーマ -- [国際化機能](/ja/guides/i18n) - -::: -``` - -## 引用 - -> これは引用です。他の人の言葉やドキュメントを引用するときによく使われます。 -> -> 引用は、各行の先頭に`>`を付けることで示されます。 - -```md -> これは引用です。他の人の言葉やドキュメントを引用するときによく使われます。 -> -> 引用は、各行の先頭に`>`を付けることで示されます。 -``` - -## コード - -コードのブロックは、先頭と末尾に3つのバックティック<code>```</code>を持つブロックで示されます。コードブロックを開始するバックティックの後ろに、使用されているプログラミング言語を指定できます。 - -```js -// シンタックスハイライトされたJavascriptコード。 -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` - -````md -```js -// シンタックスハイライトされたJavascriptコード。 -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` -```` - -```md -長い1行のコードブロックは折り返されません。長すぎる場合は、水平方向にスクロールする必要があります。この行は、このことを示すのに十分な長さであるはずです。 -``` - -## その他のMarkdown機能 - -Starlightは、リストやテーブルなど、その他のMarkdown記法をすべてサポートしています。Markdownのすべての構文要素の概要については、[The Markdown GuideのMarkdownチートシート](https://www.markdownguide.org/cheat-sheet/)を参照してください。 diff --git a/docs/src/content/docs/ja/guides/authoring-content.mdx b/docs/src/content/docs/ja/guides/authoring-content.mdx new file mode 100644 index 00000000000..1b061d59893 --- /dev/null +++ b/docs/src/content/docs/ja/guides/authoring-content.mdx @@ -0,0 +1,683 @@ +--- +title: Markdownでのコンテンツ作成 +description: StarlightがサポートするMarkdown構文の概要。 +--- + +Starlightでは、`.md`ファイルにおいて[Markdown](https://daringfireball.net/projects/markdown/)構文のすべての機能を利用できます。また、タイトルや説明文(description)などのメタデータを定義するためのフロントマター[YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f)もサポートしています。 + +MDXやMarkdocを使用する場合、サポートされるMarkdownの機能や使用方法が異なることがあるため、[MDXドキュメント](https://mdxjs.com/docs/what-is-mdx/#markdown)や[Markdocドキュメント](https://markdoc.dev/docs/syntax)を必ず確認してください。 + +## フロントマター + +フロントマターに値を設定して、Starlightの個々のページをカスタマイズできます。フロントマターは、ファイル先頭の`---`によって区切られた区間に設定します。 + +```md title="src/content/docs/example.md" +--- +title: ページのタイトル +--- + +ページのコンテンツは、2つ目の`---`の後に続きます。 +``` + +すべてのページには、少なくとも`title`が必要です。利用可能なすべてのフィールドと、カスタムフィールドの追加方法については、[フロントマターのリファレンス](/ja/reference/frontmatter/)を参照してください。 + +## インラインスタイル + +テキストは**太字**、_斜体_、または~~取り消し線~~にできます。 + +```md +テキストは**太字**、_斜体_、または~~取り消し線~~にできます。 +``` + +[別のページにリンク](/ja/getting-started/)できます。 + +```md +[別のページにリンク](/ja/getting-started/)できます。 +``` + +バックティックで`インラインコード`を強調できます。 + +```md +バックティックで`インラインコード`を強調できます。 +``` + +## 画像 + +Starlightは、[Astro組み込みのアセット最適化機能](https://docs.astro.build/ja/guides/images/)を使用して画像を表示します。 + +MarkdownとMDXは、スクリーンリーダーや支援技術のための代替テキストを含む画像を表示するためのMarkdown構文をサポートしています。 + +![「astro」という単語を中心に据えた惑星と恒星のイラスト](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) + +```md +![「astro」という単語を中心に据えた惑星と恒星のイラスト](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) +``` + +プロジェクトにローカルに保存されている画像についても、相対パスを使用して表示できます。 + +```md +// src/content/docs/page-1.md + +![宇宙空間に浮かぶロケット](../../assets/images/rocket.svg) +``` + +## 見出し + +見出しによりコンテンツを構造化できます。Markdownの見出しは、行の先頭にある`#`の数で示されます。 + +### ページコンテンツを構造化する方法 + +Starlightは、ページタイトルをトップレベルの見出しとして自動的に使用し、また各ページの目次の先頭に「概要」という見出しを含めます。各ページを通常のテキストコンテンツで開始し、ページ上の見出しは`<h2>`以下を使用することをおすすめします。 + +```md +--- +title: Markdownガイド +description: StarlightでのMarkdownの使い方 +--- + +このページでは、StarlightでMarkdownを使用する方法について説明します。 + +## インラインスタイル + +## 見出し +``` + +### 見出しの自動アンカーリンク + +Markdownで見出しを使用するとアンカーリンクが自動的に付与されるため、ページの特定のセクションに直接リンクできます。 + +```md +--- +title: 私のページコンテンツ +description: Starlightの組み込みアンカーリンクの使い方 +--- + +## はじめに + +同じページの下部にある[結論](#結論)にリンクできます。 + +## 結論 + +`https://my-site.com/page1/#はじめに`は、「はじめに」に直接移動します。 +``` + +レベル2(`<h2>`)とレベル3(`<h3>`)の見出しは、ページの目次に自動的に表示されます。 + +Astroが見出しの`id`をどのように処理するかについて、詳しくは[Astroドキュメント](https://docs.astro.build/ja/guides/markdown-content/#見出しid)を参照してください。 + +## 補足情報 + +補足情報(「警告」や「吹き出し」とも呼ばれます)は、ページのメインコンテンツと並べて補助的な情報を表示するのに便利です。 + +Starlightは、補足情報をレンダリングするためのカスタムMarkdown構文を提供しています。補足情報のブロックは、コンテンツを囲む3つのコロン`:::`によって示し、`note`(注釈)、`tip`(ヒント)、`caution`(注意)、`danger`(危険)というタイプに設定できます。 + +他のMarkdownコンテンツを補足情報の中にネストできますが、補足情報は短く簡潔なコンテンツに最も適しています。 + +### 注釈 + +:::note +Starlightは、[Astro](https://astro.build/)製のドキュメントサイト用ツールキットです。次のコマンドではじめられます。 + +```sh +npm create astro@latest -- --template starlight +``` + +::: + +````md +:::note +Starlightは、[Astro](https://astro.build/)製のドキュメントサイト用ツールキットです。次のコマンドではじめられます。 + +```sh +npm create astro@latest -- --template starlight +``` + +::: +```` + +### カスタムのタイトル + +補足情報のカスタムタイトルを、補足情報のタイプの後ろに角括弧で囲んで指定できます。たとえば`:::tip[ご存知でしたか?]`のようにできます。 + +:::tip[ご存知でしたか?] +Astroでは[「アイランドアーキテクチャ」](https://docs.astro.build/ja/concepts/islands/)を使用して、より高速なWebサイトを構築できます。 +::: + +```md +:::tip[ご存知でしたか?] +Astroでは[「アイランドアーキテクチャ」](https://docs.astro.build/ja/concepts/islands/)を使用して、より高速なWebサイトを構築できます。 +::: +``` + +### カスタムの補足アイコン + +補足情報のタイプまたは[カスタムタイトル](#カスタムのタイトル)の後ろに波括弧でカスタムアイコンを指定できます。たとえば`:::tip{icon="heart"}`や`:::tip[ご存知でしたか?]{icon="heart"}`のようにできます。アイコン名は、[Starlightの組み込みアイコン](/ja/reference/icons/#すべてのアイコン)の名前に設定する必要があります。 + +:::tip{icon="heart"} +Astroでは[「アイランドアーキテクチャ」](https://docs.astro.build/ja/concepts/islands/)を使用して、高速なWebサイトを構築できます。 +::: + +```md +:::tip{icon="heart"} +Astroでは[「アイランドアーキテクチャ」](https://docs.astro.build/ja/concepts/islands/)を使用して、高速なWebサイトを構築できます。 +::: +``` + +### その他のタイプ + +注意(Caution)と危険(Danger)の補足は、ユーザーがつまずく可能性のある細かい点に注意を向けさせるのに役立ちます。もしこれらを多用しているとすれば、それはあなたがドキュメントを書いている対象の設計を見直す余地があることのサインかもしれません。 + +:::caution +もしあなたが素晴らしいドキュメントサイトを望んでいないのであれば、[Starlight](/ja/)は不要かもしれません。 +::: + +:::danger +Starlightの便利な機能のおかげで、ユーザーはより生産的になり、プロダクトはより使いやすくなるかもしれません。 + +- わかりやすいナビゲーション +- ユーザーが設定可能なカラーテーマ +- [国際化機能](/ja/guides/i18n/) + +::: + +```md +:::caution +もしあなたが素晴らしいドキュメントサイトを望んでいないのであれば、[Starlight](/ja/)は不要かもしれません。 +::: + +:::danger +Starlightの便利な機能のおかげで、ユーザーはより生産的になり、プロダクトはより使いやすくなるかもしれません。 + +- わかりやすいナビゲーション +- ユーザーが設定可能なカラーテーマ +- [国際化機能](/ja/guides/i18n/) + +::: +``` + +## 引用 + +> これは引用です。他の人の言葉やドキュメントを引用するときによく使われます。 +> +> 引用は、各行の先頭に`>`を付けることで示されます。 + +```md +> これは引用です。他の人の言葉やドキュメントを引用するときによく使われます。 +> +> 引用は、各行の先頭に`>`を付けることで示されます。 +``` + +## コードブロック + +コードのブロックは、先頭と末尾に3つのバックティック<code>```</code>を持つブロックで示されます。コードブロックを開始するバックティックの後ろに、使用されているプログラミング言語を指定できます。 + +```js +// シンタックスハイライトされたJavascriptコード。 +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` + +````md +```js +// シンタックスハイライトされたJavascriptコード。 +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` +```` + +### Expressive Codeの機能 + +Starlightは、コードブロックのフォーマットを拡張するために[Expressive Code](https://expressive-code.com/)を使用しています。Expressive Codeのテキストマーカーとウィンドウフレームプラグインはデフォルトで有効になっています。コードブロックのレンダリングは、Starlightの[`expressiveCode`設定オプション](/ja/reference/configuration/#expressivecode)により設定できます。 + +#### テキストマーカー + +[Expressive Codeのテキストマーカー](https://expressive-code.com/key-features/text-markers/)をコードブロックの先頭で使うことで、コードブロックの特定の行や部分をハイライトできます。波括弧(`{ }`)を使って行全体をハイライトし、引用符を使ってテキストの文字列をハイライトします。 + +ハイライトのスタイルは3つあります。コードに注意を向けるための中立的なスタイル、挿入されたコードを示す緑色のスタイル、削除されたコードを示す赤色のスタイルです。テキストと行全体の両方を、デフォルトのマーカー、または`ins=`と`del=`を組み合わせてマークし、目的のハイライトを生成できます。 + +Expressive Codeには、コードサンプルの外観をカスタマイズするためのさまざまなオプションが用意されています。これらの多くは組み合わせることができ、非常に明快なコードサンプルを作成できます。利用可能な多くのオプションについては、[Expressive Codeのドキュメント](https://expressive-code.com/key-features/text-markers/#configuration)を確認してください。最も一般的な例をいくつか以下に示します。 + +- [行全体と行の範囲を`{ }`マーカーを使ってマークする](https://expressive-code.com/key-features/text-markers/#marking-full-lines--line-ranges): + + ```js {2-3} + function demo() { + // この行(2行目)と次の行はハイライトされます + return 'このスニペットの3行目です'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js {2-3} + function demo() { + // この行(2行目)と次の行はハイライトされます + return 'このスニペットの3行目です'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="{2-3}" %} + function demo() { + // この行(2行目)と次の行はハイライトされます + return 'このスニペットの3行目です'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [`" "`マーカーまたは正規表現を使って選択されたテキストをマークする](https://expressive-code.com/key-features/text-markers/#marking-individual-text-inside-lines): + + ```js "個別の用語" /正規表現.*います/ + // 個別の用語もハイライトできます + function demo() { + return '正規表現もサポートされています'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "個別の用語" /正規表現.*います/ + // 個別の用語もハイライトできます + function demo() { + return '正規表現もサポートされています'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'個別の用語' /正規表現.*います/" %} + // 個別の用語もハイライトできます + function demo() { + return '正規表現もサポートされています'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [追加、削除されたテキストや行を、`ins`と`del`でマークする](https://expressive-code.com/key-features/text-markers/#selecting-inline-marker-types-mark-ins-del): + + ```js "return true;" ins="挿入" del="削除" + function demo() { + console.log('これらは挿入と削除のマーカーです'); + // return文はデフォルトのマーカータイプを使用します + return true; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "return true;" ins="挿入" del="削除" + function demo() { + console.log('これらは挿入と削除のマーカーです'); + // return文はデフォルトのマーカータイプを使用します + return true; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'return true;' ins='挿入' del='削除'" %} + function demo() { + console.log('これらは挿入と削除のマーカーです'); + // return文はデフォルトのマーカータイプを使用します + return true; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [構文ハイライトと`diff`風の構文を組み合わせる](https://expressive-code.com/key-features/text-markers/#combining-syntax-highlighting-with-diff-like-syntax): + + ```diff lang="js" + function thisIsJavaScript() { + // このブロック全体はJavaScriptとしてハイライトされますが、 + // diffマーカーの追加も可能です! + - console.log('削除される古いコード') + + console.log('新しいキラキラコード!') + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```diff lang="js" + function thisIsJavaScript() { + // このブロック全体はJavaScriptとしてハイライトされますが、 + // diffマーカーの追加も可能です! + - console.log('削除される古いコード') + + console.log('新しいキラキラコード!') + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```diff {% meta="lang='js'" %} + function thisIsJavaScript() { + // このブロック全体はJavaScriptとしてハイライトされますが、 + // diffマーカーの追加も可能です! + - console.log('削除される古いコード') + + console.log('新しいキラキラコード!') + } + ``` + ```` + + </TabItem> + + </Tabs> + +#### フレームとタイトル + +コードブロックをウィンドウのようなフレームの中にレンダリングできます。シェルスクリプト言語(`bash`や`sh`など)には、ターミナルウィンドウのようなフレームが使用されます。その他の言語は、タイトルを含んでいる場合、コードエディタスタイルのフレーム内に表示されます。 + +`title="..."`属性を、コードブロックの開始を表わすバックティックと言語識別子の後ろに続けて記述するか、コードの最初の行にファイル名コメントを記述することで、コードブロックにオプションでタイトルを設定できます。 + +- [コメントによりファイル名タブを追加する](https://expressive-code.com/key-features/frames/#code-editor-frames) + + ```js + // my-test-file.js + console.log('Hello World!'); + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js + // my-test-file.js + console.log('Hello World!'); + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````md + ```js + // my-test-file.js + console.log('Hello World!'); + ``` + ```` + + </TabItem> + + </Tabs> + +- [Terminalウィンドウにタイトルを追加する](https://expressive-code.com/key-features/frames/#terminal-frames) + + ```bash title="依存関係のインストール中…" + npm install + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash title="依存関係のインストール中…" + npm install + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% title="依存関係のインストール中…" %} + npm install + ``` + ```` + + </TabItem> + + </Tabs> + +- [`frame="none"`によりウィンドウフレームを無効化する](https://expressive-code.com/key-features/frames/#overriding-frame-types) + + ```bash frame="none" + echo "bash言語を使用していますが、これはターミナルとしてレンダリングされません" + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash frame="none" + echo "bash言語を使用していますが、これはターミナルとしてレンダリングされません" + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% frame="none" %} + echo "bash言語を使用していますが、これはターミナルとしてレンダリングされません" + ``` + ```` + + </TabItem> + + </Tabs> + +## Details + +Details(「ディスクロージャー」や「アコーディオン」とも呼ばれます)は、すぐには必要ないコンテンツを非表示にするのに便利です。ユーザーは短い要約をクリックして、コンテンツ全体を展開・表示できます。 + +Markdownコンテンツ内で標準のHTML要素[`<details>`](https://developer.mozilla.org/ja/docs/Web/HTML/Element/details)と[`<summary>`](https://developer.mozilla.org/ja/docs/Web/HTML/Element/summary)を使用して、ディスクロージャーウィジェットを作成できます。 + +`<details>`要素の中には、他のMarkdown構文をネストできます。 + +<details> +<summary>アンドロメダ座が最もよく見えるのはいつ、どこ?</summary> + +[アンドロメダ座](https://ja.wikipedia.org/wiki/アンドロメダ座)は、北緯`+90°`から南緯`-40°`の間の緯度で、11月の夜空に最もよく見えます。 + +</details> + +```md +<details> +<summary>アンドロメダ座が最もよく見えるのはいつ、どこ?</summary> + +[アンドロメダ座](https://ja.wikipedia.org/wiki/アンドロメダ座)は、北緯`+90°`から南緯`-40°`の間の緯度で、11月の夜空に最もよく見えます。 + +</details> +``` + +## 脚注 + +[脚注](https://www.markdownguide.org/extended-syntax/#footnotes)は、コンテンツの流れを中断することなく、簡潔な参照や補足を追加するのに便利です。脚注は、ページの下部に集められた参照テキストへジャンプする、番号付きの上付きリンクとして表示されます。 + +脚注は、角括弧とキャレット、番号付き参照を使用して定義します。 + +```md +ここに脚注[^1]があり、その後にテキストが続きます。 + +[^1]: 参照内容。 +``` + +## その他の一般的なMarkdown機能 + +Starlightは、リストやテーブルなど、その他のMarkdown記法をすべてサポートしています。Markdownのすべての構文要素の概要については、[The Markdown GuideのMarkdownチートシート](https://www.markdownguide.org/cheat-sheet/)を参照してください。 + +## 高度なMarkdownとMDXの設定 + +Starlightは、remarkとrehypeをベースとした、AstroのMarkdown・MDXレンダラーを使用しています。Astroの設定ファイルに`remarkPlugins`または`rehypePlugins`を追加することで、カスタム構文や動作をサポートできます。詳しくは、Astroドキュメントの[「Markdownプラグイン」](https://docs.astro.build/ja/guides/markdown-content/#markdown-plugins)を参照してください。 + +## Markdoc + +Starlightは、実験的な[Astro Markdoc統合](https://docs.astro.build/ja/guides/integrations-guide/markdoc/)とStarlight Markdocプリセットを使用して、Markdocでのコンテンツ作成をサポートしています。 + +### Markdocで新しいプロジェクトを作成する + +`create astro`を使用して、Markdocが事前設定された新しいStarlightプロジェクトを開始します。 + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight/markdoc +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight/markdoc +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight/markdoc +``` + +</TabItem> +</Tabs> + +### 既存のプロジェクトにMarkdocを追加する + +既にStarlightサイトがあり、Markdocを追加したい場合は、以下の手順に従ってください。 + +<Steps> + +1. AstroのMarkdoc統合を追加します。 + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npx astro add markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm astro add markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn astro add markdoc + ``` + + </TabItem> + + </Tabs> + +2. Starlight Markdocプリセットをインストールします。 + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-markdoc + ``` + + </TabItem> + + </Tabs> + +3. `markdoc.config.mjs`にMarkdoc設定ファイルを作成し、Starlight Markdocプリセットを使用します。 + + ```js + import { defineMarkdocConfig } from '@astrojs/markdoc/config'; + import starlightMarkdoc from '@astrojs/starlight-markdoc'; + + export default defineMarkdocConfig({ + extends: [starlightMarkdoc()], + }); + ``` + +</Steps> + +Markdocの構文と機能についてさらに学ぶには、[Markdocのドキュメント](https://markdoc.dev/docs/syntax)または[Astro Markdoc統合ガイド](https://docs.astro.build/ja/guides/integrations-guide/markdoc/)を参照してください。 + +### Markdocプリセットの設定 + +`starlightMarkdoc()`プリセットは、以下の設定オプションを受け付けます。 + +#### `headingLinks` + +**type:** `boolean` +**default:** `true` + +見出しにクリック可能なアンカーリンクを付けてレンダリングするかどうかを制御します。MarkdownおよびMDXファイルに適用される[`markdown.headingLinks`](/ja/reference/configuration/#markdown)オプションと同等です。 + +```js "headingLinks: false" +export default defineMarkdocConfig({ + // デフォルトの見出しアンカーリンクのサポートを無効にする + extends: [starlightMarkdoc({ headingLinks: false })], +}); +``` diff --git a/docs/src/content/docs/ja/guides/components.mdx b/docs/src/content/docs/ja/guides/components.mdx deleted file mode 100644 index 229d4c639fa..00000000000 --- a/docs/src/content/docs/ja/guides/components.mdx +++ /dev/null @@ -1,186 +0,0 @@ ---- -title: コンポーネント -description: StarlightにおけるMDXでのコンポーネントの利用。 ---- - -コンポーネントにより、UI やスタイリングの一部を一貫性を保って簡単に再利用できます。例として、リンクカードやYouTubeの埋め込みなどが考えられます。Starlightは[MDX](https://mdxjs.com/)ファイルでのコンポーネントの使用をサポートしており、すぐに使える一般的なコンポーネントもいくつか提供しています。 - -[コンポーネントの作り方について、詳しくはAstroドキュメントを参照してください](https://docs.astro.build/ja/core-concepts/astro-components/)。 - -## コンポーネントを使う - -コンポーネントは、MDXファイルにインポートしてJSXタグとしてレンダリングすることで使用できます。HTMLタグのように見えますが、`import`文の名前と同じ大文字で始まります。 - -```mdx ---- -# src/content/docs/index.mdx -title: Welcome to my docs ---- - -import SomeComponent from '../../components/SomeComponent.astro'; -import AnotherComponent from '../../components/AnotherComponent.astro'; - -<SomeComponent prop="何か" /> - -<AnotherComponent> - コンポーネントには**ネストされたコンテンツ**を含められます。 -</AnotherComponent> -``` - -StarlightはAstro製であるため、[サポート対象のUIフレームワーク(React、Preact、Svelte、Vue、Solid、Lit、Alpine)](https://docs.astro.build/ja/core-concepts/framework-components/)で作成されたコンポーネントであればMDXファイルで使用できます。[MDXでのコンポーネントの使用](https://docs.astro.build/ja/guides/markdown-content/#using-components-in-mdx)について、詳しくはAstroドキュメントを参照してください。 - -### Starlightのスタイルとの互換性 - -Starlightは、Markdownコンテンツにデフォルトのスタイルを適用します。たとえば、要素間にマージンを追加します。これらのスタイルがコンポーネントの見た目と競合する場合は、`not-content`クラスをコンポーネントに設定してスタイルを無効化してください。 - -```astro ---- -// src/components/Example.astro ---- - -<div class="not-content"> - <p>Starlightのデフォルトのコンテンツスタイルに影響を受けません。</p> -</div> -``` - -## 組み込みのコンポーネント - -Starlightは、一般的なドキュメントのユースケースに対して組み込みのコンポーネントをいくつか提供しています。これらのコンポーネントは、`@astrojs/starlight/components`パッケージから利用できます。 - -### タブ - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -`<Tabs>`と`<TabItem>`コンポーネントを使用して、タブインターフェースを表示できます。各`<TabItem>`は、ユーザーに表示する`label`を必要とします。 - -```mdx -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -<Tabs> - <TabItem label="恒星">シリウス、ベガ、ペテルギウス</TabItem> - <TabItem label="衛星">イオ、エウロパ、ガニメデ</TabItem> -</Tabs> -``` - -上のコードは、ページに以下のタブを生成します。 - -<Tabs> - <TabItem label="恒星">シリウス、ベガ、ペテルギウス</TabItem> - <TabItem label="衛星">イオ、エウロパ、ガニメデ</TabItem> -</Tabs> - -### カード - -import { Card, CardGrid } from '@astrojs/starlight/components'; - -`<Card>`コンポーネントを使用すると、Starlightのスタイルに合わせたボックス内にコンテンツを表示できます。十分なスペースがある場合は、複数のカードを`<CardGrid>`コンポーネントで囲むことで、カードを並べて表示できます。 - -`<Card>`は`title`を必須とし、また任意で[Starlightの組み込みアイコンの1つ](#すべてのアイコン)を名前に設定した`icon`属性を含められます。 - -```mdx -import { Card, CardGrid } from '@astrojs/starlight/components'; - -<Card title="確認しよう">強調したい興味深いコンテンツ。</Card> - -<CardGrid> - <Card title="恒星" icon="star"> - シリウス、ベガ、ペテルギウス - </Card> - <Card title="衛星" icon="moon"> - イオ、エウロパ、ガニメデ - </Card> -</CardGrid> -``` - -上のコードにより、ページに以下が生成されます。 - -<Card title="確認しよう">強調したい興味深いコンテンツ。</Card> - -<CardGrid> - <Card title="恒星" icon="star"> - シリウス、ベガ、ペテルギウス - </Card> - <Card title="衛星" icon="moon"> - イオ、エウロパ、ガニメデ - </Card> -</CardGrid> - -:::tip[ヒント] -プロジェクトの主要な機能を示すために、ホームページでカードグリッドを使いましょう。`stagger`属性を追加すると、カードの2番目の列を垂直方向にシフトして、視覚的な面白さを引き出します。 - -```astro -<CardGrid stagger> - <!-- カード --> -</CardGrid> -``` - -::: - -### リンクカード - -`<LinkCard>`を使用すると、他のページへのリンクを目立たせることができます。 - -`<LinkCard>`は`title`と[`href`](https://developer.mozilla.org/ja/docs/Web/HTML/Element/a#href)属性を必須とします。短い`description`や、`target`など他のリンク属性も指定できます。 - -十分なスペースがある場合、`<CardGrid>`により複数の`<LinkCard>`をグループ化して、カードを並べて表示できます。 - -```mdx -import { LinkCard, CardGrid } from '@astrojs/starlight/components'; - -<LinkCard - title="Starlightのカスタマイズ" - description="Starlightサイトをカスタマイズして、独自のスタイル、フォントなどを追加する方法について学びます。" - href="/ja/guides/customization/" -/> - -<CardGrid> - <LinkCard - title="Markdownでのコンテンツ作成" - href="/ja/guides/authoring-content/" - /> - <LinkCard title="コンポーネント" href="/ja/guides/components/" /> -</CardGrid> -``` - -上のコードにより、ページに以下が生成されます。 - -import { LinkCard } from '@astrojs/starlight/components'; - -<LinkCard - title="Starlightのカスタマイズ" - description="Starlightサイトをカスタマイズして、独自のスタイル、フォントなどを追加する方法について学びます。" - href="/ja/guides/customization/" -/> - -<CardGrid> - <LinkCard - title="Markdownでのコンテンツ作成" - href="/ja/guides/authoring-content/" - /> - <LinkCard title="コンポーネント" href="/ja/guides/components/" /> -</CardGrid> - -### アイコン - -import { Icon } from '@astrojs/starlight/components'; -import IconsList from '../../../../components/icons-list.astro'; - -Starlightは、`<Icon>`コンポーネントを通じてコンテンツ内に表示可能な、一般的なアイコンのセットを提供しています。 - -`<Icon>`は[`name`](#すべてのアイコン)を必須とし、任意で`label`、`size`、`color`属性を含められます。 - -```mdx -import { Icon } from '@astrojs/starlight/components'; - -<Icon name="star" color="goldenrod" size="2rem" /> -``` - -上のコードにより、ページに以下が生成されます。 - -<Icon name="star" color="goldenrod" size="2rem" /> - -#### すべてのアイコン - -以下に、利用可能なすべてのアイコンとその名前を示します。アイコンをクリックすると、対応するコンポーネントのコードをコピーできます。 - -<IconsList /> diff --git a/docs/src/content/docs/ja/guides/css-and-tailwind.mdx b/docs/src/content/docs/ja/guides/css-and-tailwind.mdx index e19f4072209..a63258965e3 100644 --- a/docs/src/content/docs/ja/guides/css-and-tailwind.mdx +++ b/docs/src/content/docs/ja/guides/css-and-tailwind.mdx @@ -3,12 +3,18 @@ title: CSSとスタイリング description: カスタムCSSやTailwind CSSを使用して、Starlightサイトをスタイリングする方法を学びます。 --- +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + カスタムCSSファイルやStarlightのTailwindプラグインを使用して、Starlightサイトをスタイリングできます。 +サイトのデフォルトスタイルを手軽に変更するには、[コミュニティテーマ](/ja/resources/themes/)を確認してください。 + ## カスタムCSSスタイル Starlightサイトに適用されるスタイルをカスタマイズするには、追加のCSSファイルを作成し、Starlightのデフォルトスタイルを変更または拡張します。 +<Steps> + 1. `src/`ディレクトリにCSSファイルを追加します。たとえば、以下ではデフォルトのカラム幅を広げ、ページタイトルのテキストサイズを大きくしています。 ```css @@ -21,7 +27,7 @@ Starlightサイトに適用されるスタイルをカスタマイズするに 2. `astro.config.mjs`で、Starlightの`customCss`配列にCSSファイルへのパスを追加します。 - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -31,33 +37,46 @@ Starlightサイトに適用されるスタイルをカスタマイズするに starlight({ title: 'カスタムCSSを設定したドキュメント', customCss: [ - // カスタムCSSファイルへの相対パス - './src/styles/custom.css', + + // カスタムCSSファイルへの相対パス + + './src/styles/custom.css', ], }), ], }); ``` +</Steps> + [GitHub上の`props.css`ファイル](https://github.com/withastro/starlight/blob/main/packages/starlight/style/props.css)で、サイトをカスタマイズするために設定可能な、Starlightが使用しているすべてのカスタムCSSプロパティを確認できます。 +### カスケードレイヤー + +Starlightは内部で[カスケードレイヤー](https://developer.mozilla.org/ja/docs/Learn/CSS/Building_blocks/Cascade_layers)を使用して、スタイルの適用順序を管理しています。これにより、CSSの適用順序が予測可能になり、またスタイルの上書きが容易になります。レイヤーに属さないカスタムCSSは、Starlightのスタイルを上書きします。 + +カスケードレイヤーを使用する場合は、カスタムCSSで[`@layer`](https://developer.mozilla.org/ja/docs/Web/CSS/@layer)を使用して、`starlight`レイヤーのスタイルに対する各レイヤーの優先順位を定義できます。 + +```css "starlight" +/* src/styles/custom.css */ +@layer my-reset, starlight, my-overrides; +``` + +上の例では、`my-reset`というカスタムレイヤーはすべてのStarlightレイヤーの前に適用され、`my-overrides`というカスタムレイヤーはすべてのStarlightレイヤーの後に適用されます。`my-overrides`レイヤー内のスタイルはStarlightのスタイルよりも優先されますが、`my-reset`レイヤーに設定されたスタイルはStarlightによって変更される可能性があります。 + ## Tailwind CSS -AstroプロジェクトでのTailwind CSSのサポートは、[AstroのTailwindインテグレーション](https://docs.astro.build/ja/guides/integrations-guide/tailwind/)によって提供されています。また、Starlightは、Starlightのスタイルとの互換性を保ちつつTailwindを設定するのに役立つ、補完的なTailwindプラグインを提供しています。 +AstroプロジェクトでのTailwind CSS v4のサポートは、[TailwindのViteプラグイン](https://tailwindcss.com/docs/installation/using-vite)によって提供されています。また、Starlightは、Starlightのスタイルとの互換性を保ちつつTailwindを設定するのに役立つ、補完的なCSSを提供しています。 -StarlightのTailwindプラグインは、以下の設定を適用します。 +StarlightのTailwind CSSは、以下の設定を適用します。 - Tailwindの`dark:`バリアントをStarlightのダークモードと連携するように設定します。 -- UStarlightのUIでTailwindの[テーマカラーとフォント](#starlightをtailwindでスタイリングする)を使用します。 -- Tailwindの[Preflight](https://tailwindcss.com/docs/preflight)リセットスタイルを無効化した上で、Tailwindのボーダーユーティリティクラスに必要なPreflightの必須部分のみ有効化します。 +- StarlightのUIでTailwindの[テーマカラーとフォント](#starlightをtailwindでスタイリングする)を使用します。 +- TailwindのPreflightリセットスタイルのうち、必要な部分を復元します。 ### Tailwindを使用して新しいプロジェクトを作成する -import { Tabs, TabItem } from '@astrojs/starlight/components'; - `create astro`を使用して、Tailwind CSSが組み込まれた新しいStarlightプロジェクトを開始します。 -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh @@ -85,9 +104,11 @@ yarn create astro --template starlight/tailwind 既存のStarlightサイトにTailwind CSSを追加する場合は、以下の手順に従ってください。 -1. AstroのTailwindインテグレーションを追加します。 +<Steps> + +1. 以下のコマンドを実行し、ターミナルの指示に従って、プロジェクトにTailwindをセットアップします。 - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -115,9 +136,9 @@ yarn create astro --template starlight/tailwind </Tabs> -2. StarlightのTailwindプラグインをインストールします。 +2. StarlightのTailwind互換パッケージをインストールします。 - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -130,7 +151,7 @@ yarn create astro --template starlight/tailwind <TabItem label="pnpm"> ```sh - pnpm install @astrojs/starlight-tailwind + pnpm add @astrojs/starlight-tailwind ``` </TabItem> @@ -145,22 +166,26 @@ yarn create astro --template starlight/tailwind </Tabs> -3. Tailwindのベーススタイル用のCSSファイルを、`src/tailwind.css`などの場所に作成します。 +3. Astroによって生成された`src/styles/global.css`ファイルの内容を、Starlightとの互換性のために以下のように置き換えます。 ```css - /* src/tailwind.css */ - @tailwind base; - @tailwind components; - @tailwind utilities; + /* src/styles/global.css */ + @layer base, starlight, theme, components, utilities; + + @import '@astrojs/starlight-tailwind'; + @import 'tailwindcss/theme.css' layer(theme); + @import 'tailwindcss/utilities.css' layer(utilities); ``` -4. 上で作成したTailwindのベーススタイルを使用し、またデフォルトのベーススタイルを無効とするように、Astroの設定ファイルを更新します。 + このTailwindテーマの設定は、Starlightの[カスケードレイヤー](#カスケードレイヤー)の順序を定義し、StarlightのTailwind補完CSSをインポートし、Tailwindのテーマとユーティリティスタイルをインポートします。プロジェクトで追加のTailwindの設定が必要な場合は、[「Tailwindの設定を複数使用する」](#tailwindの設定を複数使用する)セクションを参照してください。 + +4. Starlightの設定を更新して、`customCss`配列の最初のアイテムとしてTailwind CSSのファイルを追加します。 - ```js {11-12,16-17} + ```js ins={11-12} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; - import tailwind from '@astrojs/tailwind'; + import tailwindcss from '@tailwindcss/vite'; export default defineConfig({ integrations: [ @@ -168,69 +193,94 @@ yarn create astro --template starlight/tailwind title: 'Tailwindを使ったドキュメント', customCss: [ // Tailwindのベーススタイルへのパス - './src/tailwind.css', + './src/styles/global.css', ], }), - tailwind({ - // デフォルトのベーススタイルを無効にする - applyBaseStyles: false, - }), ], + vite: { plugins: [tailwindcss()] }, }); ``` -5. StarlightのTailwindプラグインを`tailwind.config.cjs`に追加します。 +</Steps> - ```js ins={2,7} - // tailwind.config.cjs - const starlightPlugin = require('@astrojs/starlight-tailwind'); +### StarlightをTailwindでスタイリングする - /** @type {import('tailwindcss').Config} */ - module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - plugins: [starlightPlugin()], - }; - ``` +[Tailwindを使用して新しいStarlightプロジェクトを作成した](#tailwindを使用して新しいプロジェクトを作成する)場合、または[既存のStarlightプロジェクトにTailwindを追加した](#tailwindを既存のプロジェクトに追加する)場合、Starlightは`src/styles/global.css`ファイルにある[Tailwindテーマの設定値](https://tailwindcss.com/docs/theme)を使用してUIをスタイリングします。 + +以下のCSSカスタムプロパティが設定されている場合、Starlightのデフォルトスタイルが上書きされます。 + +- `--color-accent-*` — リンクと現在のアイテムのハイライトに使用されます +- `--color-gray-*` — 背景色とボーダーに使用されます +- `--font-sans` — UIとコンテンツのテキストに使用されます +- `--font-mono` — コード例に使用されます + +```css {9,11,13,25} +/* src/styles/global.css */ +@layer base, starlight, theme, components, utilities; + +@import '@astrojs/starlight-tailwind'; +@import 'tailwindcss/theme.css' layer(theme); +@import 'tailwindcss/utilities.css' layer(utilities); + +@theme { + /* 好みのテキストフォント。Starlightはデフォルトでシステムフォントスタックを使用します。 */ + --font-sans: 'Atkinson Hyperlegible'; + /* 好みのコードフォント。Starlightはデフォルトでシステムの等幅フォントを使用します。 */ + --font-mono: 'IBM Plex Mono'; + /* 好みのアクセントカラー。インディゴはStarlightのデフォルトに最も近い色です。 */ + --color-accent-50: var(--color-indigo-50); + --color-accent-100: var(--color-indigo-100); + --color-accent-200: var(--color-indigo-200); + --color-accent-300: var(--color-indigo-300); + --color-accent-400: var(--color-indigo-400); + --color-accent-500: var(--color-indigo-500); + --color-accent-600: var(--color-indigo-600); + --color-accent-700: var(--color-indigo-700); + --color-accent-800: var(--color-indigo-800); + --color-accent-900: var(--color-indigo-900); + --color-accent-950: var(--color-indigo-950); + /* 好みのグレースケール。ZincはStarlightのデフォルトに最も近い色です。 */ + --color-gray-50: var(--color-zinc-50); + --color-gray-100: var(--color-zinc-100); + --color-gray-200: var(--color-zinc-200); + --color-gray-300: var(--color-zinc-300); + --color-gray-400: var(--color-zinc-400); + --color-gray-500: var(--color-zinc-500); + --color-gray-600: var(--color-zinc-600); + --color-gray-700: var(--color-zinc-700); + --color-gray-800: var(--color-zinc-800); + --color-gray-900: var(--color-zinc-900); + --color-gray-950: var(--color-zinc-950); +} +``` -### StarlightをTailwindでスタイリングする +### Tailwindの設定を複数使用する -Starlightは、[Tailwindのテーマ](https://tailwindcss.com/docs/theme)の設定値をUIで使用します。 - -以下のオプションが設定されている場合、Starlightのデフォルトスタイルが上書きされます。 - -- `colors.accent` — リンクと現在のアイテムのハイライトに使用されます -- `colors.gray` — バックグラウンドカラーとボーダーに使用されます -- `fontFamily.sans` — UIとコンテンツのテキストに使用されます -- `fontFamily.mono` — コード例に使用されます - -```js {12,14,18,20} -// tailwind.config.cjs -const starlightPlugin = require('@astrojs/starlight-tailwind'); -const colors = require('tailwindcss/colors'); - -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: { - colors: { - // 好みのアクセントカラー。インディゴはStarlightのデフォルトに最も近い色です。 - accent: colors.indigo, - // 好みのグレースケール。ZincはStarlightのデフォルトに最も近い色です。 - gray: colors.zinc, - }, - fontFamily: { - // 好みのテキストフォント。Starlightはデフォルトでシステムフォントスタックを使用します。 - sans: ['"Atkinson Hyperlegible"'], - // 好みのコードフォント。Starlightはデフォルトでシステムの等幅フォントを使用します。 - mono: ['"IBM Plex Mono"'], - }, - }, - }, - plugins: [starlightPlugin()], -}; +Tailwindの設定を複数使用することで、サイトの各部分に異なるスタイルを適用できます。[Starlightをサブパスで使用する](/ja/manual-setup/#サブパスへのstarlightの追加)場合や、サイトに[カスタムページ](/ja/guides/pages/#カスタムページ)を追加する場合などに便利です。たとえば、カスタムページではTailwindのPreflightリセットスタイルを使用しつつ、StarlightページにはStarlightの互換レイヤーを適用したい場合があるでしょう。 + +以下のTailwind CSSの設定は、プラグインや追加設定なしでTailwindをセットアップするもので、非Starlightのページの出発点として使用できます。 + +```css title="src/styles/custom-pages-tailwind.css" +/* StarlightのCSSなしでTailwindを読み込む */ +@import 'tailwindcss'; ``` +<Steps> + +1. Starlightページには、[「Tailwindを既存のプロジェクトに追加する」](#tailwindを既存のプロジェクトに追加する)に従って、好みのTailwind CSSの設定を適用します。 + +2. その他のページには、好みのTailwind CSSの設定をインポートして適用します。これは通常、レイアウトコンポーネントで行われ、そのレイアウトを共有するすべてのページでTailwindのスタイルを使用できるようになります。 + ```astro + --- + // src/layouts/CustomPageLayout.astro + import '../styles/custom-pages-tailwind.css'; + --- + ``` + +</Steps> + +Tailwindテーマの設定について詳しくは、[Tailwind CSSのドキュメント](https://tailwindcss.com/docs/theme)を参照してください。 + ## テーマの設定 Starlightのカラーテーマは、デフォルトのカスタムプロパティを上書きしてコントロールできます。これらの変数はUI全体で使用されます。テキストと背景色にはグレーシェードが使用され、リンクとナビゲーションの現在のアイテムをハイライトするためにはアクセントカラーが使用されます。 @@ -239,9 +289,11 @@ Starlightのカラーテーマは、デフォルトのカスタムプロパテ 以下のスライダーを使用して、Starlightのアクセントカラーとグレーカラーのパレットを変更してみましょう。ダークとライトのプレビューエリアには、結果となる色の組み合わせが表示されます。また、このページ自体も合わせて更新されるため、変更内容をプレビューできます。 +コントラストレベルオプションで、WCAGによる[色のコントラスト基準](https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast)から満たしたいものを指定します。 + 変更内容に満足できたら、以下のCSSまたはTailwindコードをコピーしてプロジェクトで使用します。 -import ThemeDesigner from '../../../../components/theme-designer.astro'; +import ThemeDesigner from '~/components/theme-designer.astro'; <ThemeDesigner labels={{ @@ -254,6 +306,9 @@ import ThemeDesigner from '../../../../components/theme-designer.astro'; default: 'デフォルト', random: 'ランダム', }, + contrast: { + label: 'コントラストレベル', + }, editor: { accentColor: 'アクセント', grayColor: 'グレー', @@ -276,6 +331,7 @@ import ThemeDesigner from '../../../../components/theme-designer.astro'; 以下のCSSを[カスタムCSSファイル](#カスタムcssスタイル)に追加して、このテーマをサイトに適用します。 </Fragment> <Fragment slot="tailwind-docs"> - 以下の[Tailwindの設定ファイル](#starlightをtailwindでスタイリングする)の例には、`theme.extend.colors`の設定で使用するために生成された`accent`と`gray`のカラーパレットが含まれています。 + 以下のCSS変数を[Tailwind + CSSファイル](#starlightをtailwindでスタイリングする)の`@theme`ブロックに追加して、このテーマをサイトに適用します。 </Fragment> </ThemeDesigner> diff --git a/docs/src/content/docs/ja/guides/customization.mdx b/docs/src/content/docs/ja/guides/customization.mdx index fafe669206a..315e7161f70 100644 --- a/docs/src/content/docs/ja/guides/customization.mdx +++ b/docs/src/content/docs/ja/guides/customization.mdx @@ -3,8 +3,7 @@ title: Starlightのカスタマイズ description: Starlightサイトをカスタマイズして、ロゴ、カスタムフォント、ランディングページのデザインなどを追加する方法について学びます。 --- -import { Tabs, TabItem } from '@astrojs/starlight/components'; -import FileTree from '../../../../components/file-tree.astro'; +import { Tabs, TabItem, FileTree, Steps } from '@astrojs/starlight/components'; Starlightには標準的なスタイルと機能がデフォルトで用意されているため、設定不要ですぐに使い始めることができますが、Starlightサイトの見た目をカスタマイズしたくなった場合は、このガイドを参照してください。 @@ -12,6 +11,8 @@ Starlightには標準的なスタイルと機能がデフォルトで用意さ カスタムロゴをサイトヘッダーに設定して、Starlightサイトに個別のブランディングを追加することができます。 +<Steps> + 1. ロゴ画像のファイルを`src/assets/`ディレクトリに追加します。 <FileTree> @@ -26,7 +27,7 @@ Starlightには標準的なスタイルと機能がデフォルトで用意さ 2. `astro.config.mjs`で、Starlightの[`logo.src`](/ja/reference/configuration/#logo)オプションにロゴのパスを指定します。 - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -36,16 +37,18 @@ Starlightには標準的なスタイルと機能がデフォルトで用意さ starlight({ title: 'ロゴを設定したドキュメント', logo: { - src: './src/assets/my-logo.svg', + + src: './src/assets/my-logo.svg', }, }), ], }); ``` +</Steps> + デフォルトでは、ロゴはサイトの`title`と一緒に表示されます。ロゴ画像にサイトタイトルが含まれている場合は、`replacesTitle`オプションを設定して、タイトルテキストを非表示にすることができます。`title`テキストはスクリーンリーダーのために残されるので、ヘッダーはアクセシブルなままです。 -```js +```js {5} starlight({ title: 'ロゴを設定したドキュメント', logo: { @@ -59,6 +62,8 @@ starlight({ ライトモードとダークモードで異なるバージョンのロゴを表示することができます。 +<Steps> + 1. `src/assets/`に各バージョンの画像ファイルを追加します。 <FileTree> @@ -74,21 +79,23 @@ starlight({ 2. `astro.config.mjs`で、`src`ではなく`light`と`dark`オプションにロゴのパスを指定します。 - ```js + ```diff lang="js" starlight({ title: 'ロゴを設定したドキュメント', logo: { - light: './src/assets/light-logo.svg', - dark: './src/assets/dark-logo.svg', + + light: './src/assets/light-logo.svg', + + dark: './src/assets/dark-logo.svg', }, }), ``` +</Steps> + ## サイトマップを有効化する Starlightにはサイトマップ生成機能が組み込まれています。`astro.config.mjs`の`site`にURLを設定すると、サイトマップの生成が有効になります。 -```js +```js {4} // astro.config.mjs export default defineConfig({ @@ -97,13 +104,15 @@ export default defineConfig({ }); ``` +Astroドキュメントで[`robots.txt`にサイトマップへのリンクを追加する方法](https://docs.astro.build/ja/guides/integrations-guide/sitemap/#sitemap-link-in-robotstxt)について確認してください。 + ## ページレイアウト Starlightのページはデフォルトで、グローバルなナビゲーションサイドバーと、現在のページの見出しを表示する目次を配置したレイアウトを使用します。 ページのフロントマターで[`template: splash`](/ja/reference/frontmatter/#template)を設定することで、サイドバーのない、より広いページレイアウトを適用できます。これはランディングページに特に適しており、[このサイトのホームページ](/ja/)で確認することができます。 -```md +```md {5} --- # src/content/docs/index.md @@ -118,10 +127,10 @@ Starlightは、目当ての見出しに読者が簡単にジャンプできる デフォルトでは、目次には`<h2>`と`<h3>`の見出しが含まれます。目次に含める見出しレベルをサイト全体で変更するには、[グローバルな`tableOfContents`](/ja/reference/configuration/#tableofcontents)の`minHeadingLevel`と`maxHeadingLevel`オプションを使用します。個々のページでこれらのデフォルト値を上書きするには、対応する[フロントマターの`tableOfContents`](/ja/reference/frontmatter/#tableofcontents)プロパティを追加します。 -<Tabs> +<Tabs syncKey="config-type"> <TabItem label="フロントマター"> -```md +```md {4-6} --- # src/content/docs/example.md title: 目次にH2のみを表示するページ @@ -134,13 +143,13 @@ tableOfContents: </TabItem> <TabItem label="グローバルな設定"> -```js +```js {7} // astro.config.mjs defineConfig({ integrations: [ starlight({ - title: '', + title: '目次の設定をカスタマイズしたドキュメント', tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 2 }, }), ], @@ -152,10 +161,10 @@ defineConfig({ `tableOfContents`オプションを`false`に設定することで、目次を完全に無効にできます。 -<Tabs> +<Tabs syncKey="config-type"> <TabItem label="フロントマター"> -```md +```md {4} --- # src/content/docs/example.md title: 目次のないページ @@ -166,7 +175,7 @@ tableOfContents: false </TabItem> <TabItem label="グローバルな設定"> -```js +```js {7} // astro.config.mjs defineConfig({ @@ -186,9 +195,15 @@ defineConfig({ Starlightは、Starlightインテグレーションの[`social`](/ja/reference/configuration/#social)オプションを使用して、サイトヘッダーにソーシャルメディアアカウントへのリンクを追加する機能を備えています。 -現在、Bitbucket、Codeberg、CodePen、Discord、GitHub、GitLab、Gitter、Instagram、LinkedIn、Mastodon、Microsoft Teams、Stack Overflow、Threads、Twitch、Twitter、YouTubeへのリンクがサポートされています。他のサービスのサポートが必要な場合は、GitHubまたはDiscordでお知らせください! +`social`配列の各エントリは、以下の3つのプロパティをもつオブジェクトです。 + +- `icon`: Starlightの[組み込みアイコン](/ja/reference/icons/)のいずれか。たとえば`"github"`。 +- `label`: リンクのアクセシブルなラベル。たとえば`"GitHub"`。 +- `href`: リンクのURL。たとえば`"https://github.com/withastro/starlight"`。 + +以下の例では、AstroのDiscordチャットとStarlightのGitHubリポジトリへのリンクを追加しています。 -```js +```js {9-16} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -197,10 +212,14 @@ export default defineConfig({ integrations: [ starlight({ title: 'ソーシャルリンクを設定したドキュメント', - social: { - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - }, + social: [ + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { + icon: 'github', + label: 'GitHub', + href: 'https://github.com/withastro/starlight', + }, + ], }), ], }); @@ -221,7 +240,7 @@ Starlightプロジェクトがリポジトリのルートにない場合は、 以下の例では、GitHub上にある`withastro/starlight`リポジトリの`main`ブランチの`docs/`サブディレクトリに置かれている、Starlightドキュメントの編集リンクを設定しています。 -```js +```js {9-11} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -255,8 +274,9 @@ Starlightサイトは、デフォルトでシンプルな404ページを表示 404ページでは、Starlightのページレイアウトとカスタマイズ機能をすべて使用できます。たとえば、デフォルトの404ページは、フロントマターで[`splash`テンプレート](#ページレイアウト)と[`hero`](/ja/reference/frontmatter/#hero)コンポーネントを使用しています。 -```md +```md {4,6-8} --- +# src/content/docs/404.md title: '404' template: splash editUrl: false @@ -266,6 +286,25 @@ hero: --- ``` +### デフォルトの404ページを無効にする + +完全にカスタマイズされた404レイアウトがプロジェクトに必要な場合は、`src/pages/404.astro`ルートを作成し、Starlightのデフォルトルートを無効にするために[`disable404Route`](/ja/reference/configuration/#disable404route)オプションを設定します。 + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: '404をカスタマイズしたドキュメント', + disable404Route: true, + }), + ], +}); +``` + ## カスタムフォント デフォルトでは、Starlightはユーザーのローカルデバイスで利用可能なサンセリフフォントをすべてのテキストに使用します。これにより、大きなフォントファイルをダウンロードするための余分な帯域幅を必要とせず、各ユーザーに馴染みのあるフォントでドキュメントを高速に読み込むことができます。 @@ -278,6 +317,8 @@ Starlightサイトにカスタムフォントを追加する必要がある場 #### ローカルフォントファイルの設定 +<Steps> + 1. `src/fonts/`ディレクトリにフォントファイルを追加し、空の`font-face.css`ファイルを作成します。 <FileTree> @@ -308,7 +349,7 @@ Starlightサイトにカスタムフォントを追加する必要がある場 3. `astro.config.mjs`で、Starlightの`customCss`配列に`font-face.css`ファイルへのパスを追加します。 - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -318,23 +359,27 @@ Starlightサイトにカスタムフォントを追加する必要がある場 starlight({ title: 'カスタムフォントを設定したドキュメント', customCss: [ - // @font-face CSSファイルへの相対パス - './src/fonts/font-face.css', + + // @font-face CSSファイルへの相対パス + + './src/fonts/font-face.css', ], }), ], }); ``` +</Steps> + #### Fontsourceフォントの設定 [Fontsource](https://fontsource.org/)プロジェクトは、Google Fontsやその他のオープンソースフォントの使用を容易にします。使いたいフォントのnpmモジュールをインストールすることができ、プロジェクトに追加するためのCSSファイルも用意されています。 +<Steps> + 1. [Fontsourceのカタログ](https://fontsource.org/)で使用したいフォントを見つけます。この例では、[IBM Plex Serif](https://fontsource.org/fonts/ibm-plex-serif)を使用します。 2. 使いたいフォントのパッケージをインストールします。Fontsourceのフォントページで「Install」をクリックすると、パッケージ名が表示されます。 - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -347,7 +392,7 @@ Starlightサイトにカスタムフォントを追加する必要がある場 <TabItem label="pnpm"> ```sh - pnpm install @fontsource/ibm-plex-serif + pnpm add @fontsource/ibm-plex-serif ``` </TabItem> @@ -364,7 +409,7 @@ Starlightサイトにカスタムフォントを追加する必要がある場 3. `astro.config.mjs`で、FontsourceのCSSファイルをStarlightの`customCss`配列に追加します。 - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -374,9 +419,9 @@ Starlightサイトにカスタムフォントを追加する必要がある場 starlight({ title: 'カスタムフォントを設定したドキュメント', customCss: [ - // 標準とセミボールドのフォントウェイト用のFontsourceファイル。 - '@fontsource/ibm-plex-serif/400.css', - '@fontsource/ibm-plex-serif/600.css', + + // 標準とセミボールドのフォントウェイト用のFontsourceファイル。 + + '@fontsource/ibm-plex-serif/400.css', + + '@fontsource/ibm-plex-serif/600.css', ], }), ], @@ -385,6 +430,8 @@ Starlightサイトにカスタムフォントを追加する必要がある場 Fontsourceは、各フォント用に複数のCSSファイルを同梱しています。異なるウェイトやスタイルを含める方法については、[Fontsourceのドキュメント](https://fontsource.org/docs/getting-started/install#4-weights-and-styles)を参照してください。 +</Steps> + ### フォントを使う 設定したフォントをサイトに適用するには、選択したフォントの名前を[カスタムCSSファイル](/ja/guides/css-and-tailwind/#カスタムcssスタイル)で指定します。たとえば、Starlightのデフォルトフォントをすべての場所で上書きするには、`--sl-font`カスタムプロパティを設定します。 diff --git a/docs/src/content/docs/ja/guides/i18n.mdx b/docs/src/content/docs/ja/guides/i18n.mdx index e0ae32fc525..e001603f8d9 100644 --- a/docs/src/content/docs/ja/guides/i18n.mdx +++ b/docs/src/content/docs/ja/guides/i18n.mdx @@ -3,15 +3,17 @@ title: 国際化(i18n) description: 複数言語をサポートするためにStarlightサイトを設定する方法について学びます。 --- -import FileTree from '../../../../components/file-tree.astro'; +import { FileTree, Steps } from '@astrojs/starlight/components'; Starlightは、ルーティング、フォールバックコンテンツ、右横書き(right-to-left、RTL)言語へのフルサポートなど、複数言語サイトを構築するための機能を組み込みで提供します。 ## i18nの設定 +<Steps> + 1. [`locales`](/ja/reference/configuration/#locales)と[`defaultLocale`](/ja/reference/configuration/#defaultlocale)をStarlightインテグレーションに渡すことで、サポートする言語についてStarlightに伝えます。 - ```js + ```js {9-26} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -27,8 +29,8 @@ Starlightは、ルーティング、フォールバックコンテンツ、右 en: { label: 'English', }, - // 簡体字中国語のドキュメントは`src/content/docs/zh/`に置きます。 - zh: { + // 簡体字中国語のドキュメントは`src/content/docs/zh-cn/`に置きます。 + 'zh-cn': { label: '简体中文', lang: 'zh-CN', }, @@ -54,7 +56,7 @@ Starlightは、ルーティング、フォールバックコンテンツ、右 - docs/ - ar/ - en/ - - zh/ + - zh-cn/ </FileTree> @@ -62,13 +64,17 @@ Starlightは、ルーティング、フォールバックコンテンツ、右 たとえば、`ar/index.md`と`en/index.md`は、アラビア語版と英語版のホームページをそれぞれ表わします。 +</Steps> + +より高度なi18nシナリオの場合、[Astroの`i18n`設定](https://docs.astro.build/ja/guides/internationalization/#configure-i18n-routing)オプションを使用した国際化の設定も可能です。 + ### ルートロケールを使用する 「ルート」ロケールを使用すると、パスにi18nプレフィックスを付けずにある言語を提供できます。たとえば英語をルートロケールとすると、英語のページパスは`/en/about`ではなく`/about`のようになります。 ルートロケールを設定するには、`locales`の`root`キーを使用します。ルートロケールがコンテンツのデフォルトロケールでもある場合は、`defaultLocale`を削除するか、`'root'`に設定します。 -```js +```js {9,11-14} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -83,7 +89,7 @@ export default defineConfig({ label: 'English', lang: 'en', // langはルートロケールに必要です }, - zh: { + 'zh-cn': { label: '简体中文', lang: 'zh-CN', }, @@ -101,7 +107,7 @@ export default defineConfig({ - content/ - docs/ - **index.md** - - zh/ + - zh-cn/ - **index.md** </FileTree> @@ -110,10 +116,11 @@ export default defineConfig({ デフォルトでは、Starlightは単一言語(英語)のサイトです。他の言語で単一言語のサイトを作成するには、その言語を`locales`において`root`に設定します。 -```js +```diff lang="js" {10-13} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; + export default defineConfig({ integrations: [ starlight({ @@ -137,24 +144,58 @@ Starlightは、すべての言語で同等のページが作成されること ある言語の翻訳がまだである場合、Starlightはそのページのコンテンツを(`defaultLocale`で設定する)デフォルト言語で表示します。たとえば、概要(about)ページのフランス語版をまだ作成していない場合、デフォルト言語が英語であれば、`/fr/about`を訪れた人には未翻訳であるという通知とともに英語のコンテンツが表示されます。これにより、まずデフォルト言語にコンテンツを追加し、そして翻訳者が時間を掛けて徐々に翻訳していくことが可能となります。 +## サイトタイトルを翻訳する + +デフォルトでは、Starlightはすべての言語で同じサイトタイトルを使用します。各ロケールのタイトルをカスタマイズする必要がある場合は、Starlightのオプションで[`title`](/ja/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'; +import UIStringsList from '~/components/ui-strings-list.astro'; + Starlightでは、読者が選択した言語でサイト全体を体験できるように、翻訳されたコンテンツファイルをホストするだけでなく、デフォルトUIの文字列(たとえば目次に表示されている「目次」という見出し)も翻訳できるようになっています。 -英語、チェコ語、フランス語、ドイツ語、イタリア語、日本語、ポルトガル語、オランダ語、デンマーク語、スペイン語、トルコ語、アラビア語、ノルウェー語、ペルシア語、ヘブライ語、簡体字中国語、韓国語、インドネシア語、ロシア語、スウェーデン語の翻訳済みUI文字列がすでに用意されていますが、[デフォルト言語をさらに追加するための貢献](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md)も歓迎します。 +{/* prettier-ignore */} +<LanguagesList startsSentence />の翻訳済みUI文字列がすでに用意されていますが、[デフォルト言語をさらに追加するための貢献](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md)も歓迎します。 `18n`データコレクションを使用すると、サポートしたい言語の翻訳を追加したり、デフォルトのラベルを上書きしたりできます。 -1. 設定がまだであれば、`src/content/config.ts`で`i18n`データコレクションを設定します。 +<Steps> - ```js - // src/content/config.ts +1. 現状が未設定の場合は、`src/content.config.ts`で`i18n`データコレクションを設定します。 + + ```diff lang="js" ins=/, (i18nLoader|i18nSchema)/ + // src/content.config.ts import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; export const collections = { - docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), }; ``` @@ -174,27 +215,15 @@ Starlightでは、読者が選択した言語でサイト全体を体験でき 以下は、Starlightが英語版のデフォルトとして使用している文字列です。 + <UIStringsList /> + + Starlightのコードブロックは、[Expressive Code](https://expressive-code.com/)ライブラリによって動作しています。`expressiveCode`キーを使用して、同じJSONファイルでUI文字列の翻訳について設定できます。 + ```json { - "skipLink.label": "Skip to content", - "search.label": "Search", - "search.shortcutLabel": "(Press / to Search)", - "search.cancelLabel": "Cancel", - "search.devWarning": "Search is only available in production builds. \nTry building and previewing the site to test it out locally.", - "themeSelect.accessibleLabel": "Select theme", - "themeSelect.dark": "Dark", - "themeSelect.light": "Light", - "themeSelect.auto": "Auto", - "languageSelect.accessibleLabel": "Select language", - "menuButton.accessibleLabel": "Menu", - "sidebarNav.accessibleLabel": "Main", - "tableOfContents.onThisPage": "On this page", - "tableOfContents.overview": "Overview", - "i18n.untranslatedContent": "This content is not available in your language yet.", - "page.editLink": "Edit page", - "page.lastUpdated": "Last updated:", - "page.previousLink": "Next", - "page.nextLink": "Previous" + "expressiveCode.copyButtonCopied": "Copied!", + "expressiveCode.copyButtonTooltip": "Copy to clipboard", + "expressiveCode.terminalWindowFallbackTitle": "Terminal window" } ``` @@ -214,3 +243,155 @@ Starlightでは、読者が選択した言語でサイト全体を体験でき "pagefind.searching": "Searching for [SEARCH_TERM]..." } ``` + +</Steps> + +### 翻訳スキーマを拡張する + +`i18nSchema()`オプションの`extend`を設定することで、サイトの翻訳辞書にカスタムキーを追加できます。以下の例では、オプションの`custom.label`キーが新たにデフォルトのキーに追加されています。 + +```diff lang="js" +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ ++ extend: z.object({ ++ 'custom.label': z.string().optional(), ++ }), + }), + }), +}; +``` + +コンテンツコレクションのスキーマについて詳しくは、Astroドキュメントの[「コレクションスキーマの定義」](https://docs.astro.build/ja/guides/content-collections/#defining-the-collection-schema)を参照してください。 + +## UI翻訳を使用する + +Starlightの[組み込みUI文字列](/ja/guides/i18n/#starlightのuiを翻訳する)、[ユーザー定義のUI文字列](/ja/guides/i18n/#翻訳スキーマを拡張する)、および[プラグインが提供するUI文字列](/ja/reference/plugins/#injecttranslations)には、[i18next](https://www.i18next.com/)を利用した共通のAPIを通じてアクセスできます。この共通のAPIは、[文字列補間](https://www.i18next.com/translation-function/interpolation)や[複数形対応](https://www.i18next.com/translation-function/plurals)などの機能もサポートしています。 + +Astroコンポーネントにおいて、この共通のAPIは[グローバル`Astro`オブジェクト](https://docs.astro.build/ja/reference/api-reference/#locals)の一部として`Astro.locals.t`から利用できます。 + +```astro title="example.astro" +<p dir={Astro.locals.t.dir()}> + {Astro.locals.t('404.text')} +</p> +``` + +[エンドポイント](https://docs.astro.build/ja/guides/endpoints/)でもこの共通のAPIを使用できます。`locals`オブジェクトは[エンドポイントコンテキスト](https://docs.astro.build/ja/reference/api-reference/#locals)の一部として利用できます。 + +```ts title="src/pages/404.ts" +export const GET = (context) => { + return new Response(context.locals.t('404.text')); +}; +``` + +Starlightプラグインのコンテキストでは、[`useTranslations()`](/ja/reference/plugins/#usetranslations)ヘルパーを使用して、特定の言語に対するこの共通のAPIにアクセスできます。詳しくは、[プラグインリファレンス](/ja/reference/plugins/)を参照してください。 + +### UI文字列をレンダリングする + +`locals.t()`関数を使用してUI文字列をレンダリングします。これはi18nextの`t()`関数のインスタンスで、最初の引数としてUI文字列のキーを受け取り、現在の言語に対応する翻訳を返します。 + +たとえば、以下の内容のカスタム翻訳ファイルがあるとします。 + +```json title="src/content/i18n/en.json" +{ + "link.astro": "Astro documentation", + "link.astro.custom": "Astro documentation for {{feature}}" +} +``` + +最初のUI文字列は、`t()`関数に`'link.astro'`を渡すことでレンダリングできます。 + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/"> + {Astro.locals.t('link.astro')} +</a> +<!-- レンダリング結果: <a href="...">Astro documentation</a> --> +``` + +2番目のUI文字列は、`{{feature}}`のプレースホルダーにi18nextの[補間構文](https://www.i18next.com/translation-function/interpolation)を使用しています。`feature`の値は、`t()`の第2引数として渡すオプションオブジェクトで設定する必要があります。 + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/en/guides/astro-db/"> + {Astro.locals.t('link.astro.custom', { feature: 'Astro DB' })} +</a> +<!-- レンダリング結果: <a href="...">Astro documentation for Astro DB</a> --> +``` + +補間やフォーマットなどの`t()`関数の使い方について詳しくは、[i18nextのドキュメント](https://www.i18next.com/overview/api#t)を参照してください。 + +### 高度なAPI + +#### `t.all()` + +`locals.t.all()`関数は、現在のロケールで利用可能なすべてのUI文字列を含むオブジェクトを返します。 + +```astro +--- +// src/components/Example.astro +const allStrings = Astro.locals.t.all(); +// ^ +// { +// "skipLink.label": "Skip to content", +// "search.label": "Search", +// … +// } +--- +``` + +#### `t.exists()` + +翻訳キーが存在するかどうかを確認するには、`locals.t.exists()`関数の最初の引数に翻訳キーを渡します。特定のロケールに対する翻訳が存在するかどうかを確認する必要がある場合は、オプションの第2引数を渡します。 + +```astro +--- +// src/components/Example.astro +const keyExists = Astro.locals.t.exists('a.key'); +// ^ true +const keyExistsInFrench = Astro.locals.t.exists('other.key', { lngs: ['fr'] }); +// ^ false +--- +``` + +詳しくは、[i18nextドキュメントの`exists()`リファレンス](https://www.i18next.com/overview/api#exists)を参照してください。 + +#### `t.dir()` + +`locals.t.dir()`関数は、現在のロケールまたは指定したロケールのテキスト方向を返します。 + +```astro +--- +// src/components/Example.astro +const currentDirection = Astro.locals.t.dir(); +// ^ +// 'ltr' +const arabicDirection = Astro.locals.t.dir('ar'); +// ^ +// 'rtl' +--- +``` + +詳しくは、[i18nextドキュメントの`dir()`リファレンス](https://www.i18next.com/overview/api#dir)を参照してください。 + +## 現在のロケールにアクセスする + +`.astro`コンポーネントで現在のロケールを読み取るためには、[`Astro.currentLocale`](https://docs.astro.build/ja/reference/api-reference/#currentlocale)を使用できます。 + +以下の例では、現在のロケールを読み取り、[`getRelativeLocaleUrl()`](https://docs.astro.build/ja/reference/modules/astro-i18n/#getrelativelocaleurl)ヘルパーと組み合わせて、現在の言語での概要ページへのリンクを生成しています。 + +```astro +--- +// src/components/AboutLink.astro +import { getRelativeLocaleUrl } from 'astro:i18n'; +--- + +<a href={getRelativeLocaleUrl(Astro.currentLocale ?? 'en', 'about')}>About</a> +``` diff --git a/docs/src/content/docs/ja/guides/overriding-components.mdx b/docs/src/content/docs/ja/guides/overriding-components.mdx new file mode 100644 index 00000000000..03219925fee --- /dev/null +++ b/docs/src/content/docs/ja/guides/overriding-components.mdx @@ -0,0 +1,149 @@ +--- +title: コンポーネントのオーバーライド +description: Starlightの組み込みコンポーネントをオーバーライドして、ドキュメントサイトのUIにカスタム要素を追加する方法を学びます。 +--- + +import { Steps } from '@astrojs/starlight/components'; + +StarlightのデフォルトのUIと設定オプションは、柔軟に設計されており、さまざまなコンテンツで機能します。Starlightのデフォルトの見た目の大部分は、[CSS](/ja/guides/css-and-tailwind/)と[設定オプション](/ja/guides/customization/)によりカスタマイズできます。 + +デフォルトの内容に満足できない場合には、デフォルトのコンポーネントを拡張したり、オーバーライドしたり(完全に置き換えたり)するためのカスタムコンポーネントを作成することも可能です。 + +## いつオーバーライドするか + +以下の場合、Starlightのデフォルトコンポーネントをオーバーライドすると便利です。 + +- [カスタムCSS](/ja/guides/css-and-tailwind/)では不可能な方法で、StarlightのUIの見た目を部分的に変更したい場合。 +- StarlightのUIの動作を部分的に変更したい場合。 +- Starlightの既存のUIに別のUIを追加したい場合。 + +## オーバーライドの方法 + +<Steps> + +1. オーバーライドしたいStarlightコンポーネントを選択します。コンポーネントの完全なリストは、[オーバーライドリファレンス](/ja/reference/overrides/)にあります。 + + :::tip + どのコンポーネントをオーバーライドすればいいかわからない場合は、[Starlight Overrides Map](https://starlight-overrides-map.netlify.app/)を使用して、StarlightのUIコンポーネントの名前をインタラクティブに調べることができます。 + ::: + + この例では、ページのナビゲーションバーに表示される、Starlightの[`SocialIcons`](/ja/reference/overrides/#socialicons)コンポーネントをオーバーライドします。 + +2. Starlightのコンポーネントを置き換えるAstroコンポーネントを作成します。この例では、連絡先のリンクをレンダリングします。 + + ```astro + --- + // src/components/EmailLink.astro + + const email = 'houston@example.com'; + --- + + <a href=`mailto:${email}`>メールしてね</a> + ``` + +3. `astro.config.mjs`の[`components`](/ja/reference/configuration/#components)設定オプションで、カスタムコンポーネントを使用するようStarlightに指示します。 + + ```js {9-12} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'オーバーライドを設定したドキュメント', + components: { + // デフォルトの`SocialIcons`コンポーネントをオーバーライドします。 + SocialIcons: './src/components/EmailLink.astro', + }, + }), + ], + }); + ``` + +</Steps> + +## 組み込みコンポーネントを再利用する + +StarlightのデフォルトのUIコンポーネントを、自分で作ったものと同じように使うことができます。これにより、Starlightの基本的なUIをデザインとしてすべて保持しながら、そこに別のUIを追加することができます。 + +以下の例は、デフォルトの`SocialIcons`コンポーネントと一緒に、メールリンクをレンダリングするカスタムコンポーネントです。 + +```astro {3,7} +--- +// src/components/EmailLink.astro +import Default from '@astrojs/starlight/components/SocialIcons.astro'; +--- + +<a href="mailto:houston@example.com">メールしてね</a> +<Default><slot /></Default> +``` + +カスタムコンポーネント内で組み込みコンポーネントをレンダリングする場合は、デフォルトコンポーネント内に[`<slot />`](https://docs.astro.build/ja/basics/astro-components/#スロット)を追加します。これにより、コンポーネントに子要素が渡された場合、Astroがそれらをどこにレンダリングするかを知ることができます。 + +[名前付きスロット](https://docs.astro.build/ja/basics/astro-components/#名前付きスロット)を含む[`PageFrame`](/ja/reference/overrides/#pageframe)や[`TwoColumnContent`](/ja/reference/overrides/#twocolumncontent)コンポーネントを再利用する場合は、これらのスロットを[受け渡す](https://docs.astro.build/ja/basics/astro-components/#スロットの受け渡し)必要があります。 + +以下の例は、受け渡しが必要な`right-sidebar`という名前付きスロットを含む`TwoColumnContent`コンポーネントを再利用するカスタムコンポーネントです。 + +```astro {8} +--- +// src/components/CustomContent.astro +import Default from '@astrojs/starlight/components/TwoColumnContent.astro'; +--- + +<Default> + <slot /> + <slot name="right-sidebar" slot="right-sidebar" /> +</Default> +``` + +## ページデータを使用する + +Starlightコンポーネントをオーバーライドすると、現在のページのすべてのデータを含むグローバルな[`starlightRoute`オブジェクト](/ja/guides/route-data/)にアクセスできます。これらの値を使用して、コンポーネントテンプレートのレンダリング方法を制御することができます。 + +以下の例では、[`PageTitle`](/ja/reference/overrides/#pagetitle)の代替コンポーネントが、コンテンツのフロントマターに設定された現在のページのタイトルを表示します。 + +```astro {4} "{title}" +--- +// src/components/Title.astro + +const { title } = Astro.locals.starlightRoute.entry.data; +--- + +<h1 id="_top">{title}</h1> + +<style> + h1 { + font-family: 'Comic Sans'; + } +</style> +``` + +利用可能なすべてのプロパティについて、詳しくは[ルートデータリファレンス](/ja/reference/route-data/)を参照してください。 + +### 特定ページのみでのオーバーライド + +コンポーネントのオーバーライドはすべてのページに適用されます。ただし、`starlightRoute`の値を使用して条件に応じてレンダリングすることで、カスタムUIを表示するタイミング、StarlightのデフォルトUIを表示するタイミング、あるいはまったく別のものを表示するタイミングを決定することができます。 + +以下は、Starlightの[`Footer`](/ja/reference/overrides/#footer)をオーバーライドするコンポーネントの例です。ホームページでのみ「Starlightで作成 🌟」と表示し、それ以外のすべてのページではデフォルトのフッターを表示します。 + +```astro +--- +// src/components/ConditionalFooter.astro +import Default from '@astrojs/starlight/components/Footer.astro'; + +const isHomepage = Astro.locals.starlightRoute.id === ''; +--- + +{ + isHomepage ? ( + <footer>Starlightで作成 🌟</footer> + ) : ( + <Default> + <slot /> + </Default> + ) +} +``` + +条件付きレンダリングについて、詳しくは[Astroのテンプレート構文ガイド](https://docs.astro.build/ja/basics/astro-syntax/#動的html)を参照してください。 diff --git a/docs/src/content/docs/ja/guides/pages.mdx b/docs/src/content/docs/ja/guides/pages.mdx new file mode 100644 index 00000000000..87266964c38 --- /dev/null +++ b/docs/src/content/docs/ja/guides/pages.mdx @@ -0,0 +1,218 @@ +--- +title: ページ +description: Starlightでドキュメントサイトのページを作成し管理する方法を学びます。 +sidebar: + order: 1 +tableOfContents: + maxHeadingLevel: 4 +--- + +Starlightは、Markdownのフロントマターにより提供される柔軟なオプションを使用して、コンテンツに基づいてサイトのHTMLページを生成します。さらにStarlightプロジェクトは、[Astroの強力なページ生成ツール](https://docs.astro.build/ja/basics/astro-pages/)に完全にアクセスできます。このガイドでは、Starlightのページ生成の仕組みについて説明します。 + +## コンテンツページ + +### ファイルフォーマット + +Starlightは、設定なしでMarkdownとMDXによってコンテンツを作成できます。Markdocのサポートを追加するには、[Markdocガイド](/ja/guides/authoring-content/#markdoc)に従ってください。 + +### ページの追加 + +`.md`または`.mdx`ファイルを`src/content/docs/`に作成することで、サイトに新しいページを追加できます。サブフォルダを使用してファイルを整理し、複数のパスセグメントを作成できます。 + +たとえば次のファイル構造は、`example.com/hello-world`と`example.com/reference/faq`にページを生成します。 + +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - reference/ + - faq.md + +</FileTree> + +### 型安全なフロントマター + +すべてのStarlightページは、ページの表示方法を制御するためのカスタマイズ可能な[共通のフロントマタープロパティ](/ja/reference/frontmatter/)を共有しています。 + +```md +--- +title: こんにちは、世界! +description: これは私のStarlight製サイトのページです +--- +``` + +何か重要なことを忘れてしまっていても、Starlightがあなたに教えてくれるでしょう。 + +## カスタムページ + +発展的なユースケースとしては、`src/pages/`ディレクトリを作成しておこなうカスタムページの追加があります。`src/pages/`ディレクトリは[Astroのファイルベースルーティング](https://docs.astro.build/ja/basics/astro-pages/#ファイルベースルーティング)を使用しており、他のページフォーマットに加えて`.astro`ファイルをサポートしています。これは、完全にカスタムのレイアウトでページを作成したり、異なるデータソースからページを生成する必要がある場合に役立ちます。 + +たとえば以下のプロジェクトは、`src/content/docs/`のMarkdownコンテンツと、`src/pages/`のAstroとHTMLルートを混在させています。 + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - pages/ + - custom.astro + - archived.html + +</FileTree> + +詳しくは[Astroドキュメントの「ページ」ガイド](https://docs.astro.build/ja/basics/astro-pages/)を参照してください。 + +### カスタムページでStarlightのデザインを使用する + +カスタムページでStarlightのデザインを使用するには、ページコンテンツを[`<StarlightPage>`コンポーネント](#starlightpageコンポーネント)でラップします。これは、コンテンツを動的に生成したいものの、Starlightのデザインも使用したいような場合に役立ちます。 + +StarlightのMarkdownアンカーリンクのスタイルと同じアンカーリンクを見出しに追加するには、カスタムページで[`<AnchorHeading>`コンポーネント](#anchorheadingコンポーネント)を使用します。 + +```astro +--- +// src/pages/custom-page/example.astro +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +import CustomComponent from './CustomComponent.astro'; +--- + +<StarlightPage frontmatter={{ title: '私のカスタムページ' }}> + <p>これはカスタムコンポーネントを用いたカスタムページです:</p> + <CustomComponent /> + + <AnchorHeading level="2" id="learn-more">詳しく学ぶ</AnchorHeading> + <p> + <a href="https://starlight.astro.build/"> + Starlightのドキュメントで詳しく読む + </a> + </p> +</StarlightPage> +``` + +#### `<StarlightPage>`コンポーネント + +`<StarlightPage />`コンポーネントは、Starlightのレイアウトとスタイルを使用してページ全体のコンテンツをレンダリングします。 + +```astro +--- +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +--- + +<StarlightPage frontmatter={{ title: '私のカスタムページ' }}> + <!-- カスタムページのコンテンツ --> +</StarlightPage> +``` + +`<StarlightPage />`コンポーネントは以下のpropsを受け付けます。 + +##### `frontmatter` + +**必須** +**type:** `StarlightPageFrontmatter` + +ページの[フロントマタープロパティ](/ja/reference/frontmatter/)を設定します。これは、Markdownページのフロントマターと同様です。[`title`](/ja/reference/frontmatter/#title必須)プロパティは必須ですが、その他のプロパティは任意です。 + +以下のプロパティはMarkdownのフロントマターと異なります。 + +- [`slug`](/ja/reference/frontmatter/#slug)プロパティはサポートされておらず、カスタムページのURLに基づいて自動的に設定されます。 +- [`editUrl`](/ja/reference/frontmatter/#editurl)オプションは、編集リンクを表示するためのURLが必要です。 +- [自動生成されるリンクグループ](/ja/reference/configuration/#sidebar)にページを表示する方法をカスタマイズするための[`sidebar`](/ja/reference/frontmatter/#sidebar)フロントマタープロパティは利用できません。`<StarlightPage />`コンポーネントを使用するページはコレクションの一部ではなく、自動生成されるサイドバーグループには追加できません。 +- [`draft`](/ja/reference/frontmatter/#draft)オプションは、ページがドラフトであることを[通知](/ja/reference/overrides/#draftcontentnotice)するだけで、自動的に本番ビルドから除外されるわけではありません。 + +##### `sidebar` + +**type:** [`SidebarItem[]`](/ja/reference/configuration/#sidebaritem) +**default:** [グローバルな`sidebar`設定値](/ja/reference/configuration/#sidebar)に基づき生成されるサイドバー + +ページにカスタムのサイトナビゲーションサイドバーを設定します。未設定の場合、ページはデフォルトのグローバルサイドバーを使用します。 + +たとえば以下のページは、ホームページへのリンクとその他のカスタムページへのリンクグループにより、デフォルトのサイドバーをオーバーライドします。 + +```astro {3-13} +<StarlightPage + frontmatter={{ title: 'オリオン座' }} + sidebar={[ + { label: 'ホーム', link: '/' }, + { + label: '星座', + items: [ + { label: 'アンドロメダ座', link: '/andromeda/' }, + { label: 'オリオン座', link: '/orion/' }, + { label: 'こぐま座', link: '/ursa-minor/', badge: 'スタブ' }, + ], + }, + ]} +> + 何らかのコンテンツ。 +</StarlightPage> +``` + +サイドバーをカスタマイズするための利用可能なオプションについては、[「サイドバーのナビゲーション」](/ja/guides/sidebar/)ガイドを参照してください。 + +##### `hasSidebar` + +**type:** `boolean` +**default:** [`frontmatter.template`](/ja/reference/frontmatter/#template)が`'splash'`の場合は`false`、それ以外の場合は`true` + +ページにサイドバーを表示するかどうかを制御します。 + +##### `headings` + +**type:** `{ depth: number; slug: string; text: string }[]` +**default:** `[]` + +ページのすべての見出しの配列を指定します。指定された場合、Starlightはこれらの見出しからページの目次を生成します。 + +##### `dir` + +**type:** `'ltr' | 'rtl'` +**default:** 現在のロケールの記述方向 + +ページのコンテンツを記述する方向を設定します。 + +##### `lang` + +**type:** `string` +**default:** 現在のロケールの言語 + +`en`や`zh-CN`、`pt-BR`など、ページのBCP-47言語タグを設定します。 + +##### `isFallback` + +**type:** `boolean` +**default:** `false` + +現在の言語に対する翻訳がない結果、ページが[フォールバックコンテンツ](/ja/guides/i18n/#フォールバックコンテンツ)を使用しているかどうかを示します。 + +#### `<AnchorHeading>`コンポーネント + +`<AnchorHeading />`コンポーネントは、StarlightのMarkdownスタイルと同じクリック可能なアンカーリンク付きのHTML見出し要素をレンダリングします。 + +```astro +--- +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +--- + +<AnchorHeading level="2" id="sub-heading">小見出し</AnchorHeading> +``` + +このコンポーネントは、以下のpropsに加えて、任意の有効な[グローバルHTML属性](https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes)を受け付けます。 + +##### `level` + +**必須** +**type:** `1 | 2 | 3 | 4 | 5 | 6` + +レンダリングする見出しレベルを指定します。たとえば、`level="1"`は`<h1>`要素をレンダリングします。 + +##### `id` + +**必須** +**type:** `string` + +この見出しのユニークなIDを指定します。レンダリングされる見出しの`id`属性として使用され、アンカーアイコンはこのIDにリンクします。 diff --git a/docs/src/content/docs/ja/guides/project-structure.mdx b/docs/src/content/docs/ja/guides/project-structure.mdx index 78fc677817a..ebe4529877b 100644 --- a/docs/src/content/docs/ja/guides/project-structure.mdx +++ b/docs/src/content/docs/ja/guides/project-structure.mdx @@ -5,12 +5,12 @@ description: Starlightプロジェクトでファイルをどのように配置 このガイドでは、Starlightプロジェクトの構成と、プロジェクト内のさまざまなファイルの役割について説明します。 -Starlightプロジェクトは、基本的に他のAstroプロジェクトと同じファイル・ディレクトリ構成に従います。詳細については、[Astroのディレクトリ構成のドキュメント](https://docs.astro.build/ja/core-concepts/project-structure/)を参照してください。 +Starlightプロジェクトは、基本的に他のAstroプロジェクトと同じファイル・ディレクトリ構成に従います。詳細については、[Astroのディレクトリ構成のドキュメント](https://docs.astro.build/ja/basics/project-structure/)を参照してください。 ## ファイルとディレクトリ - `astro.config.mjs` — Astroの設定ファイルで、ここにStarlightのインテグレーションや設定を記述します。 -- `src/content/config.ts` — コンテンツコレクションの設定ファイルで、Starlightのフロントマタースキーマをプロジェクトに追加します。 +- `src/content.config.ts` — コンテンツコレクションの設定ファイルで、Starlightのフロントマタースキーマをプロジェクトに追加します。 - `src/content/docs/` — コンテンツのファイルが置かれます。Starlightは、このディレクトリ内の各`.md`、`.mdx`、`.mdoc`ファイルを、サイトのページへと変換します。 - `src/content/i18n/`(任意) — [国際化](/ja/guides/i18n/)をサポートするための翻訳データが置かれます。 - `src/` — プロジェクトの他のソースコードやファイル(コンポーネント、スタイル、画像など)が置かれます。 @@ -20,7 +20,7 @@ Starlightプロジェクトは、基本的に他のAstroプロジェクトと同 Starlightプロジェクトのディレクトリは、次のようになります。 -import FileTree from '../../../../components/file-tree.astro'; +import { FileTree } from '@astrojs/starlight/components'; <FileTree> @@ -39,8 +39,7 @@ import FileTree from '../../../../components/file-tree.astro'; - 01-getting-started.md - 02-advanced.md - index.mdx - - config.ts - - env.d.ts + - content.config.ts - astro.config.mjs - package.json - tsconfig.json diff --git a/docs/src/content/docs/ja/guides/route-data.mdx b/docs/src/content/docs/ja/guides/route-data.mdx new file mode 100644 index 00000000000..c653db7976a --- /dev/null +++ b/docs/src/content/docs/ja/guides/route-data.mdx @@ -0,0 +1,139 @@ +--- +title: ルートデータ +description: Starlight のページデータモデルがどのようにページをレンダリングするか、またそのカスタマイズ方法について学びましょう。 +--- + +import { Steps } from '@astrojs/starlight/components'; + +Starlight がドキュメント内のページをレンダリングするとき、まずそのページ上の内容を表すルートデータオブジェクトを作成します。 +このガイドでは、ルートデータがどのように生成され、どのように使用されるか、また Starlight の既定の動作を変更するためにカスタマイズする方法を説明します。 + +利用可能なすべてのプロパティ一覧については、[「ルートデータリファレンス」](/ja/reference/route-data/) を参照してください。 + +## ルートデータとは? + +Starlight のルートデータは、1 ページをレンダリングするために必要なすべての情報を含むオブジェクトです。 +これは、現在のページに関する情報に加え、Starlight の設定から生成されるデータも含みます。 + +## ルートデータの使用方法 + +Starlight のすべてのコンポーネントは、ルートデータを使用して各ページで何をレンダリングするかを決定します。 +たとえば、[`siteTitle`](/ja/reference/route-data/#sitetitle) 文字列はサイトタイトルの表示に使用され、[`sidebar`](/ja/reference/route-data/#sidebar) 配列はグローバルサイドバーのナビゲーションをレンダリングするために使用されます。 + +このデータは Astro コンポーネント内で `Astro.locals.starlightRoute` グローバルからアクセスできます。 + +```astro title="example.astro" {2} +--- +const { siteTitle } = Astro.locals.starlightRoute; +--- + +<p>このサイトのタイトルは「{siteTitle}」です。</p> +``` + +これは、表示内容をカスタマイズするために [コンポーネントのオーバーライド](/ja/guides/overriding-components/) を作成するときなどに便利です。 + +## ルートデータのカスタマイズ + +Starlight のルートデータは、設定なしでそのまま動作します。 +しかし、高度なユースケースでは、サイトの表示方法を変更するために一部またはすべてのページでルートデータをカスタマイズしたい場合があります。 + +これは [コンポーネントのオーバーライド](/ja/guides/overriding-components/) と似た概念ですが、Starlight がデータを「どのように」レンダリングするかを変更する代わりに、Starlight が「レンダリングするデータ自体」を変更します。 + +### ルートデータをカスタマイズすべき場合 + +既存の設定オプションでは実現できない形で、Starlight がデータを処理する方法を変更したい場合にルートデータのカスタマイズが役立ちます。 + +たとえば、サイドバー項目をフィルタリングしたり、特定のページのタイトルをカスタマイズしたりできます。 +このような変更は、Starlight の既定コンポーネントを変更することなく、これらのコンポーネントに渡すデータを修正するだけで実現できます。 + +### ルートデータをカスタマイズする方法 + +ルートデータは特別な形式の「ミドルウェア」を使ってカスタマイズできます。 +これは Starlight がページをレンダリングするたびに呼び出され、ルートデータオブジェクト内の値を変更できる関数です。 + +<Steps> + +1. Starlight の `defineRouteMiddleware()` ユーティリティを使って、`onRequest` 関数をエクスポートする新しいファイルを作成します。 + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware(() => {}); + ``` + +2. `astro.config.mjs` で、ルートデータミドルウェアファイルの場所を Starlight に指定します。 + + ```js ins={9} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'カスタムルートデータのページ', + routeMiddleware: './src/routeData.ts', + }), + ], + }); + ``` + +3. `onRequest` 関数を更新してルートデータを変更します。 + + ミドルウェアが最初に受け取る引数は [Astro の `context` オブジェクト](https://docs.astro.build/ja/reference/api-reference/) です。 + これには、現在のページレンダリングに関するすべての情報(現在の URL や `locals` など)が含まれています。 + + 次の例では、すべてのページタイトルの末尾に感嘆符を追加して、ドキュメントを少し楽しくします。 + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware((context) => { + // このページのコンテンツコレクションエントリを取得 + const { entry } = context.locals.starlightRoute; + // タイトルの末尾に感嘆符を追加 + entry.data.title = entry.data.title + '!'; + }); + ``` + +</Steps> + +#### 複数のルートミドルウェア + +Starlight は複数のミドルウェアもサポートしています。 +複数のハンドラーを追加する場合は、`routeMiddleware` にパスの配列を設定します。 + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: '複数のミドルウェアのページ', + routeMiddleware: ['./src/middleware-one.ts', './src/middleware-two.ts'], + }), + ], +}); +``` + +#### 後続のルートミドルウェアを待機する + +スタック内の後続ミドルウェアが実行されるのを待ってからコードを実行したい場合、ミドルウェア関数の第 2 引数として渡される `next()` コールバックを `await` することができます。 +これは、たとえばプラグインのミドルウェアが実行された後に変更を加えたい場合に便利です。 + +```ts "next" "await next();" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware(async (context, next) => { + // 後続のミドルウェアが実行されるのを待つ + await next(); + // ルートデータを変更 + const { entry } = context.locals.starlightRoute; + entry.data.title = entry.data.title + '!'; +}); +``` diff --git a/docs/src/content/docs/ja/guides/sidebar.mdx b/docs/src/content/docs/ja/guides/sidebar.mdx new file mode 100644 index 00000000000..f8752d11ddf --- /dev/null +++ b/docs/src/content/docs/ja/guides/sidebar.mdx @@ -0,0 +1,729 @@ +--- +title: サイドバーのナビゲーション +description: Starlightサイトのサイドバーのナビゲーションリンクを設定・カスタマイズする方法を学びます。 +--- + +import { FileTree } from '@astrojs/starlight/components'; +import SidebarPreview from '~/components/sidebar-preview.astro'; + +サイドバーはユーザーがサイト内を移動するための主要な方法の1つであるため、サイドバーを整理することは良いドキュメントの鍵となります。Starlightでは、サイドバーのレイアウトとコンテンツをカスタマイズするためのオプション一式を提供しています。 + +## デフォルトのサイドバー + +Starlightはデフォルトで、ドキュメントのファイルシステム構造に基づいてサイドバーを自動的に生成します。その際、各ファイルの`title`プロパティをサイドバーのエントリとして使用します。 + +たとえば以下のファイル構造があるとします。 + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - andromeda.md + - orion.md + - stars/ + - betelgeuse.md + +</FileTree> + +すると以下のサイドバーが自動的に生成されます。 + +<SidebarPreview + config={[ + { + label: '星座', + items: [ + { label: 'アンドロメダ座', link: '' }, + { label: 'オリオン座', link: '' }, + ], + }, + { + label: '星', + items: [{ label: 'ベテルギウス', link: '' }], + }, + ]} +/> + +自動生成されるサイドバーについては、[自動生成されるグループ](#自動生成されるグループ)のセクションで詳しく説明します。 + +## リンクとリンクグループを追加する + +サイドバーのリンクと(折りたたみ可能なヘッダー内の)リンクグループを設定するには、`astro.config.mjs`で[`starlight.sidebar`](/ja/reference/configuration/#sidebar)プロパティを使用します。 + +リンクとグループを組み合わせることで、さまざまなサイドバーレイアウトを作成できます。 + +### 内部リンク + +`slug`プロパティをもつオブジェクトを使用して、`src/content/docs/`内のページへのリンクを追加します。デフォルトでは、リンク先ページのタイトルがラベルとして使用されます。 + +たとえば、以下の設定があるとします。 + +```js "slug:" +starlight({ + sidebar: [ + { slug: 'constellations/andromeda' }, + { slug: 'constellations/orion' }, + ], +}); +``` + +そして以下のファイル構造であるとします。 + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - andromeda.md + - orion.md + +</FileTree> + +すると以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { label: 'アンドロメダ座', link: '' }, + { label: 'オリオン座', link: '' }, + ]} +/> + +リンク先ページのフロントマターから推測される値をオーバーライドするには、`label`、[`translations`](#国際化)、[`attrs`](#カスタムhtml属性)プロパティを追加します。 + +ページのフロントマターからサイドバーの表示を制御する方法について、詳しくは[「自動生成されるリンクのカスタマイズ」](#自動生成されるリンクをフロントマターでカスタマイズする)を参照してください。 + +#### 内部リンクの省略記法 + +内部リンクは、ページのスラグを文字列として渡すだけの省略記法でも指定できます。 + +たとえば、以下の設定は上記の`slug`を使用した設定と同等です。 + +```js "slug:" +starlight({ + sidebar: ['constellations/andromeda', 'constellations/orion'], +}); +``` + +### その他のリンク + +`label`と`link`プロパティをもつオブジェクトを使用して、外部ページやドキュメント以外のページへのリンクを追加します。 + +```js "label:" "link:" +starlight({ + sidebar: [ + // サイト内のドキュメント以外のページへのリンク。 + { label: '流星商店', link: '/shop/' }, + // NASAのウェブサイトへの外部リンク。 + { label: 'NASA', link: 'https://www.nasa.gov/' }, + ], +}); +``` + +上の設定により、以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { label: '流星商店', link: '' }, + { label: 'NASA', link: 'https://www.nasa.gov/' }, + ]} +/> + +### グループ + +折りたたみ可能な見出しの下に関連するリンクをグループ化することで、サイドバーに構造を追加できます。グループには、リンクと他のサブグループを含められます。 + +`label`と`items`プロパティをもつオブジェクトを使用して、グループを追加します。`label`はグループの見出しとして使用されます。`items`配列にリンクまたはサブグループを追加します。 + +```js /^\s*(label:|items:)/ +starlight({ + sidebar: [ + // 「星座」というラベルのリンクグループ。 + { + label: '星座', + items: [ + 'constellations/carina', + 'constellations/centaurus', + // 季節の星座の入れ子になったリンクグループ。 + { + label: '季節の星座', + items: [ + 'constellations/andromeda', + 'constellations/orion', + 'constellations/ursa-minor', + ], + }, + ], + }, + ], +}); +``` + +上の設定により、以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { + label: '星座', + items: [ + { label: 'りゅうこつ座', link: '' }, + { label: 'ケンタウルス座', link: '' }, + { + label: '季節の星座', + items: [ + { label: 'アンドロメダ座', link: '' }, + { label: 'オリオン座', link: '' }, + { label: 'こぐま座', link: '' }, + ], + }, + ], + }, + ]} +/> + +### 自動生成されるグループ + +Starlightはドキュメントのディレクトリに基づいて、サイドバーのグループを自動的に生成できます。これはグループ内のサイドバー項目を手動で入力したくない場合に便利です。 + +デフォルトでは、ページはファイルの[`slug`](/ja/reference/route-data/#slug)に従ってアルファベット順に並べ替えられます。 + +`label`と`autogenerate`プロパティをもつオブジェクトを使用して、自動生成されるグループを追加します。`autogenerate`の設定には、サイドバーのエントリに使用する`directory`を指定する必要があります。たとえば、以下のように設定したとします。 + +```js "label:" "autogenerate:" +starlight({ + sidebar: [ + { + label: '星座', + // constellationsディレクトリのリンクグループを自動生成します。 + autogenerate: { directory: 'constellations' }, + }, + ], +}); +``` + +そして以下のファイル構造があるとします。 + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - carina.md + - centaurus.md + - seasonal/ + - andromeda.md + +</FileTree> + +すると以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { + label: '星座', + items: [ + { label: 'りゅうこつ座', link: '' }, + { label: 'ケンタウルス座', link: '' }, + { + label: 'seasonal', + items: [{ label: 'アンドロメダ座', link: '' }], + }, + ], + }, + ]} +/> + +## 自動生成されるリンクをフロントマターでカスタマイズする + +個々のページで[`sidebar`フロントマターフィールド](/ja/reference/frontmatter/#sidebar)を使用して、自動生成されるリンクをカスタマイズできます。 + +フロントマターのサイドバーオプションにより、[カスタムラベル](/ja/reference/frontmatter/#label)の設定、[カスタム属性](/ja/reference/frontmatter/#attrs)の使用、リンクへの[バッジ](/ja/reference/frontmatter/#badge)の追加、サイドバーのリンクの[非表示](/ja/reference/frontmatter/#hidden)、[独自のソート順](/ja/reference/frontmatter/#order)の定義が可能です。 + +```md "sidebar:" +--- +title: 私のページ +sidebar: + # このリンクのカスタムラベルを設定します + label: カスタムサイドバーラベル + # このリンクの順番をカスタマイズします(数字が小さいほど上に表示されます) + order: 2 + # このリンクにバッジを追加します + badge: + text: 新規 + variant: tip +--- +``` + +上記のフロントマターを設定したページと一緒に自動生成されるグループは、以下のサイドバーを生成します。 + +<SidebarPreview + config={[ + { + label: 'ガイド', + items: [ + { label: 'ページ', link: '' }, + { + label: 'カスタムサイドバーラベル', + link: '', + badge: { text: '新規', variant: 'tip' }, + }, + { label: '別のページ', link: '' }, + ], + }, + ]} +/> + +:::note +`sidebar`フロントマターの設定は、自動生成されるグループ内のリンクと`slug`プロパティで定義されたドキュメントリンクにのみ使用されます。`link`プロパティで定義されたリンクには適用されません。 +::: + +## バッジ + +リンク、グループ、自動生成されるグループには、ラベルの横にバッジを表示するための`badge`プロパティも含められます。 + +```js {9,16} +starlight({ + sidebar: [ + { + label: '星', + items: [ + // 「超巨星」バッジ付きのリンク。 + { + slug: 'stars/persei', + badge: '超巨星', + }, + ], + }, + // 「要更新」バッジ付きの自動生成されるグループ。 + { + label: '衛星', + badge: '要更新', + autogenerate: { directory: 'moons' }, + }, + ], +}); +``` + +上の設定により、以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { + label: '星', + items: [ + { + label: 'ペルセウス座', + link: '', + badge: { text: '超巨星', variant: 'default' }, + }, + ], + }, + { + label: '衛星', + badge: { text: '要更新', variant: 'default' }, + items: [ + { + label: 'イオ', + link: '', + }, + { + label: 'エウロパ', + link: '', + }, + { + label: 'ガニメデ', + link: '', + }, + ], + }, + ]} +/> + +### バッジのバリアントとカスタムスタイル + +`text`と`variant`、`class`プロパティをもつオブジェクトを使用して、バッジのスタイルをカスタマイズできます。 + +`text`は表示するコンテンツ、たとえば「新規」などを表わします。デフォルトでは、バッジにはサイトのアクセントカラーが使用されます。組み込みのバッジスタイルを使用するには、`variant`プロパティを`note`、`tip`、`danger`、`caution`、`success`のいずれかに設定します。 + +また、`class`プロパティにCSSクラス名を設定することで、カスタムバッジスタイルを作成することも可能です。 + +```js {9} +starlight({ + sidebar: [ + { + label: '星', + items: [ + // 「準備中」バッジ付きのリンク。 + { + slug: 'stars/sirius', + badge: { text: '準備中', variant: 'caution' }, + }, + ], + }, + ], +}); +``` + +上の設定により、以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { + label: '星', + items: [ + { + label: 'シリウス', + link: '', + badge: { text: '準備中', variant: 'caution' }, + }, + ], + }, + ]} +/> + +詳しくは、[バッジの使用とカスタマイズ](/ja/components/badges/#使用方法)を参照してください。 + +## カスタムHTML属性 + +リンク要素にカスタムのHTML属性を追加するには、`attrs`プロパティを使用します。 + +以下の例では、リンクが新しいタブで開かれるよう、`attrs`を使用して`target="_blank"`属性を追加しています。また、リンクのラベルにカスタムの`style`属性を適用して斜体にします。 + +```js {10} +starlight({ + sidebar: [ + { + label: 'リソース', + items: [ + // 新しいタブで開かれる、NASAのウェブサイトへの外部リンク。 + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { target: '_blank', style: 'font-style: italic' }, + }, + ], + }, + ], +}); +``` + +上の設定により、以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { + label: 'リソース', + items: [ + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { + target: '_blank', + style: 'font-style: italic', + }, + }, + ], + }, + ]} +/> + +### 自動生成されるリンクのカスタムHTML属性 + +`autogenerate`設定で`attrs`プロパティを定義することで、[自動生成されるグループ](#自動生成されるグループ)内のすべてのリンクのHTML属性をカスタマイズできます。個々のページでは[`sidebar.attrs`フロントマターフィールド](/ja/reference/frontmatter/#attrs)を使用してカスタム属性を指定でき、これは`autogenerate.attrs`設定とマージされます。 + +たとえば、以下の設定があるとします。 + +```js {9} +starlight({ + sidebar: [ + { + label: '星座', + autogenerate: { + // 'constellations'ディレクトリのリンクグループを自動生成します。 + directory: 'constellations', + // このグループ内のすべてのリンクラベルを斜体にします。 + attrs: { style: 'font-style: italic' }, + }, + }, + ], +}); +``` + +そして以下のファイル構造があるとします。 + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - carina.md + - centaurus.md + - seasonal/ + - andromeda.md + +</FileTree> + +すると、自動生成されるすべてのリンクが斜体になった以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { + label: '星座', + items: [ + { + label: 'りゅうこつ座', + link: '', + attrs: { style: 'font-style: italic' }, + }, + { + label: 'ケンタウルス座', + link: '', + attrs: { style: 'font-style: italic' }, + }, + { + label: 'seasonal', + items: [ + { + label: 'アンドロメダ座', + link: '', + attrs: { style: 'font-style: italic' }, + }, + ], + }, + ], + }, + ]} +/> + +## 国際化 + +リンクやグループのラベルをサポート対象の言語向けに翻訳するには、リンクやグループのエントリに`translations`プロパティを使用します。[BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags)の言語タグ、たとえば`"en"`、`"ar"`、`"zh-CN"`をキーとして、翻訳されたラベルを値として指定します。`label`プロパティは、デフォルトのロケールと、翻訳がない言語に対して使用されます。 + +```js {5-7,11-13,18-20} +starlight({ + sidebar: [ + { + label: '星座', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { + label: 'アンドロメダ座', + translations: { + 'pt-BR': 'Andrômeda', + }, + slug: 'constellations/andromeda', + }, + { + label: 'さそり座', + translations: { + 'pt-BR': 'Escorpião', + }, + slug: 'constellations/scorpius', + }, + ], + }, + ], +}); +``` + +ブラジルポルトガル語でドキュメントを閲覧すると、以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { + label: 'Constelação', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +### 内部リンクの国際化 + +[内部リンク](#内部リンク)は、デフォルトでコンテンツのフロントマターの翻訳されたページタイトルを自動的に使用します。 + +```js {9-10} +starlight({ + sidebar: [ + { + label: '星座', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { slug: 'constellations/andromeda' }, + { slug: 'constellations/scorpius' }, + ], + }, + ], +}); +``` + +ブラジルポルトガル語でドキュメントを閲覧すると、以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +多言語サイトでは、`slug`の値にURLの言語部分は含まれません。たとえば、`en/intro`と`pt-br/intro`にページがある場合、サイドバーを設定する際のスラグは`intro`となります。 + +### バッジの国際化 + +[バッジ](#バッジ)の`text`プロパティは、文字列か、多言語サイトの場合はロケールごとの値をもつオブジェクトを指定できます。オブジェクト形式を使用する場合、キーは[BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags)タグ(`en`、`ar`、`zh-CN`など)である必要があります。 + +```js {11-16} +starlight({ + sidebar: [ + { + label: '星座', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { + slug: 'constellations/andromeda', + badge: { + text: { + ja: '新規', + 'pt-BR': 'Novo', + }, + }, + }, + ], + }, + ], +}); +``` + +ブラジルポルトガル語でドキュメントを閲覧すると、以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { + label: 'Andrômeda', + link: '', + badge: { text: 'Novo', variant: 'default' }, + }, + ], + }, + ]} +/> + +## グループを折りたたむ + +`collapsed`プロパティを`true`に設定することで、リンクのグループをデフォルトで折りたためます。 + +```js {5-6} +starlight({ + sidebar: [ + { + label: '星座', + // デフォルトでグループを折りたたみます。 + collapsed: true, + items: ['constellations/andromeda', 'constellations/orion'], + }, + ], +}); +``` + +上の設定により、以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { + label: '星座', + collapsed: true, + items: [ + { label: 'アンドロメダ座', link: '' }, + { label: 'オリオン座', link: '' }, + ], + }, + ]} +/> + +[自動生成されるグループ](#自動生成されるグループ)は、親グループの`collapsed`値に従います。 + +```js {5-6} +starlight({ + sidebar: [ + { + label: 'Constellations', + // デフォルトでグループと自動生成されるサブグループを折りたたみます。 + collapsed: true, + autogenerate: { directory: 'constellations' }, + }, + ], +}); +``` + +上の設定により、以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { + label: '星座', + collapsed: true, + items: [ + { label: 'りゅうこつ座', link: '' }, + { label: 'ケンタウルス座', link: '' }, + { + label: 'seasonal', + collapsed: true, + items: [{ label: 'アンドロメダ座', link: '' }], + }, + ], + }, + ]} +/> + +この動作は、`autogenerate.collapsed`プロパティを定義することで上書きできます。 + +```js {5-7} "collapsed: true" +starlight({ + sidebar: [ + { + label: '星座', + // 「星座」グループは折りたたみませんが、自動生成されるサブグループは折りたたみます。 + collapsed: false, + autogenerate: { directory: 'constellations', collapsed: true }, + }, + ], +}); +``` + +上の設定により、以下のサイドバーが生成されます。 + +<SidebarPreview + config={[ + { + label: '星座', + items: [ + { label: 'りゅうこつ座', link: '' }, + { label: 'ケンタウルス座', link: '' }, + { + label: 'seasonal', + collapsed: true, + items: [{ label: 'アンドロメダ座', link: '' }], + }, + ], + }, + ]} +/> diff --git a/docs/src/content/docs/ja/guides/site-search.mdx b/docs/src/content/docs/ja/guides/site-search.mdx new file mode 100644 index 00000000000..6cabc564108 --- /dev/null +++ b/docs/src/content/docs/ja/guides/site-search.mdx @@ -0,0 +1,243 @@ +--- +title: サイト内検索 +description: Starlight組み込みのサイト内検索機能と、そのカスタマイズ方法について学びます。 +tableOfContents: + maxHeadingLevel: 4 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +Starlightサイトには、デフォルトで[Pagefind](https://pagefind.app/)による全文検索機能が組み込まれています。Pagefindは、静的サイト向けの高速で通信量が少ない検索ツールです。 + +検索機能を有効にするための設定は必要ありません。サイトをビルドしてデプロイすれば、サイトヘッダーの検索バーを使ってコンテンツを検索できます。 + +## 検索結果からコンテンツを隠す + +### ページを除外する + +検索インデックスからページを除外するには、ページのフロントマターに[`pagefind: false`](/ja/reference/frontmatter/#pagefind)を追加します。 + +```md title="src/content/docs/not-indexed.md" ins={3} +--- +title: 検索結果から隠したいコンテンツ +pagefind: false +--- +``` + +### ページの一部を除外する + +Pagefindは、[`data-pagefind-ignore`](https://pagefind.app/docs/indexing/#removing-individual-elements-from-the-index)属性をもつ要素内のコンテンツを無視します。 + +以下の例では、最初の段落は検索結果に表示されますが、`<div>`の中身は表示されません。 + +```md title="src/content/docs/partially-indexed.md" ins="data-pagefind-ignore" +--- +title: 部分的にインデックスされるページ +--- + +このテキストは検索で見つかります。 + +<div data-pagefind-ignore> + +このテキストは検索結果から隠されます。 + +</div> +``` + +## その他の検索プロバイダ + +### Algolia DocSearch + +[AlgoliaのDocSearchプログラム](https://docsearch.algolia.com/)にアクセスでき、Pagefindの代わりにそれを使いたい場合は、公式のStarlight DocSearchプラグインを使うことができます。 + +<Steps> + +1. `@astrojs/starlight-docsearch`をインストールします。 + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-docsearch + ``` + + </TabItem> + + </Tabs> + +2. `astro.config.mjs`でStarlightの[`plugins`](/ja/reference/configuration/#plugins)設定にDocSearchを追加し、Algoliaの`appId`、`apiKey`、`indexName`を渡します。 + + ```js ins={4,10-16} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'DocSearchを使ったサイト', + plugins: [ + starlightDocSearch({ + appId: 'YOUR_APP_ID', + apiKey: 'YOUR_SEARCH_API_KEY', + indexName: 'YOUR_INDEX_NAME', + }), + ], + }), + ], + }); + ``` + +</Steps> + +このように設定を更新すると、サイトの検索バーはデフォルトの検索モーダルではなく、Algoliaのモーダルを開きます。 + +#### DocSearchの設定 + +Starlight DocSearchプラグインでは、以下のインラインオプションによりDocSearchコンポーネントをカスタマイズできます。 + +- `maxResultsPerGroup`: 各検索グループに表示される結果の最大数を制限します。デフォルトは`5`です。 +- `disableUserPersonalization`: DocSearchがユーザーの最近の検索やお気に入りをローカルストレージに保存しないようにします。デフォルトは`false`です。 +- `insights`: Algolia Insightsプラグインを有効にし、DocSearchインデックスに検索イベントを送信します。デフォルトは`false`です。 +- `searchParameters`: [Algoliaの検索パラメータ](https://www.algolia.com/doc/api-reference/search-api-parameters/)をカスタマイズするオブジェクトです。 + +##### その他のDocSearchオプション + +`transformItems()`や`resultsFooterComponent()`などの関数オプションをDocSearchコンポーネントに渡すには、別の設定ファイルが必要です。 + +<Steps> + +1. DocSearchの設定をエクスポートするTypeScriptファイルを作成します。 + + ```ts + // src/config/docsearch.ts + import type { DocSearchClientOptions } from '@astrojs/starlight-docsearch'; + + export default { + appId: 'YOUR_APP_ID', + apiKey: 'YOUR_SEARCH_API_KEY', + indexName: 'YOUR_INDEX_NAME', + getMissingResultsUrl({ query }) { + return `https://github.com/algolia/docsearch/issues/new?title=${query}`; + }, + // ... + } satisfies DocSearchClientOptions; + ``` + +2. `astro.config.mjs`で、Starlight DocSearchプラグインに設定ファイルのパスを渡します。 + + ```js {11-13} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'DocSearchを使ったサイト', + plugins: [ + starlightDocSearch({ + clientOptionsModule: './src/config/docsearch.ts', + }), + ], + }), + ], + }); + ``` + +</Steps> + +サポートされているすべてのオプションについては、[DocSearchのJavaScriptクライアントAPIリファレンス](https://docsearch.algolia.com/docs/api/)を参照してください。 + +#### DocSearch UIを翻訳する + +DocSearchはデフォルトで英語のUI文字列のみを提供しています。Starlightの組み込みの[国際化の仕組み](/ja/guides/i18n/#starlightのuiを翻訳する)を使って、モーダルのUIを翻訳できます。 + +<Steps> + +1. `src/content.config.ts`で、Starlightの`i18n`コンテンツコレクション定義をDocSearchスキーマにより拡張します。 + + ```js ins={5} ins=/{ extend: .+ }/ + // src/content.config.ts + import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; + import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + import { docSearchI18nSchema } from '@astrojs/starlight-docsearch/schema'; + + export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ extend: docSearchI18nSchema() }), + }), + }; + ``` + +2. `src/content/i18n/`のJSONファイルに翻訳を追加します。 + + 以下はDocSearchで使われる英語のデフォルトです。 + + ```json title="src/content/i18n/en.json" + { + "docsearch.searchBox.resetButtonTitle": "Clear the query", + "docsearch.searchBox.resetButtonAriaLabel": "Clear the query", + "docsearch.searchBox.cancelButtonText": "Cancel", + "docsearch.searchBox.cancelButtonAriaLabel": "Cancel", + "docsearch.searchBox.searchInputLabel": "Search", + + "docsearch.startScreen.recentSearchesTitle": "Recent", + "docsearch.startScreen.noRecentSearchesText": "No recent searches", + "docsearch.startScreen.saveRecentSearchButtonTitle": "Save this search", + "docsearch.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", + "docsearch.startScreen.favoriteSearchesTitle": "Favorite", + "docsearch.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + + "docsearch.errorScreen.titleText": "Unable to fetch results", + "docsearch.errorScreen.helpText": "You might want to check your network connection.", + + "docsearch.footer.selectText": "to select", + "docsearch.footer.selectKeyAriaLabel": "Enter key", + "docsearch.footer.navigateText": "to navigate", + "docsearch.footer.navigateUpKeyAriaLabel": "Arrow up", + "docsearch.footer.navigateDownKeyAriaLabel": "Arrow down", + "docsearch.footer.closeText": "to close", + "docsearch.footer.closeKeyAriaLabel": "Escape key", + "docsearch.footer.searchByText": "Search by", + + "docsearch.noResultsScreen.noResultsText": "No results for", + "docsearch.noResultsScreen.suggestedQueryText": "Try searching for", + "docsearch.noResultsScreen.reportMissingResultsText": "Believe this query should return results?", + "docsearch.noResultsScreen.reportMissingResultsLinkText": "Let us know." + } + ``` + +</Steps> + +### コミュニティ製の検索プロバイダ + +[コミュニティ製プラグイン](/ja/resources/plugins/#コミュニティ製プラグイン)により、Starlight組み込みのPagefind検索プロバイダの代替を利用することもできます。 + +#### Typesense DocSearch + +[Starlight DocSearch Typesense](https://starlight-docsearch.typesense.org/)コミュニティプラグインは、[DocSearch](https://github.com/typesense/typesense-docsearch.js)インターフェースと[Typesense](https://typesense.org/)バックエンドを統合した、オープンソースでセルフホスト可能な代替手段を提供します。 + +プロジェクトでの使用方法については、Starlight DocSearch Typesenseドキュメントの[「Getting Started」](https://starlight-docsearch.typesense.org/getting-started/)ガイドを参照してください。 diff --git a/docs/src/content/docs/ja/index.mdx b/docs/src/content/docs/ja/index.mdx index a4e3babfef3..b76ebdef944 100644 --- a/docs/src/content/docs/ja/index.mdx +++ b/docs/src/content/docs/ja/index.mdx @@ -1,33 +1,31 @@ --- title: Starlight 🌟 Astroでドキュメントサイトを作る +head: + - tag: title + content: Starlight 🌟 Astroでドキュメントサイトを作る description: Starlightは、Astroを使った美しく高性能なドキュメントサイトの構築を支援します。 template: splash -banner: - content: | - <span class="ph-banner"> - <span class="ph-houston"><img src="/ph-houston.svg" alt="" width="72" height="72"/></span> - <span class="ph-text"> - <strong>ようこそ Product Hunters 👋</strong> - <a href="https://www.producthunt.com/posts/starlight-by-astro">ただいまライブ中!</a> - </span> - </span> +editUrl: false +lastUpdated: false hero: title: Starlightでドキュメントを輝かせる tagline: 最高のドキュメントサイトを作るために必要なものがすべて揃っています。高速でアクセシブル、しかも使いやすさも備えます。 image: - file: ../../../assets/hero-star.webp + file: ~/assets/hero-star.webp actions: - text: はじめる icon: right-arrow - variant: primary link: /ja/getting-started/ - text: GitHubで見る icon: external + variant: minimal link: https://github.com/withastro/starlight --- import { CardGrid, Card } from '@astrojs/starlight/components'; -import AboutAstro from '../../../components/about-astro.astro'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; <CardGrid stagger> <Card title="心躍るドキュメント" icon="open-book"> @@ -44,6 +42,108 @@ import AboutAstro from '../../../components/about-astro.astro'; </Card> </CardGrid> +<TestimonialGrid title="人々の声"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + Astroチームは、ドキュメントの作成方法を進化させました。Starlightプロジェクトには、必要なものがすべて揃っています。 + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + Astro公式のスターターキットであるStarlightは、ドキュメントサイトを構築するための本当に素晴らしいツールです。 + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + Starlightは、素晴らしいDXの典型例です。速度、使いやすさ、そして細部へのこだわりは感動的です。技術面とデザインの両方をケアしてくれるので、コンテンツに集中できます 👏 + + StackBlitzチームもとても気に入っています! + + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + Starlightによりコンテンツ作成に集中できるようになりました。私にとってゲームチェンジャーです。 + + 直感的な設計により、ワークフローが効率化されるだけでなく、オープンソース開発者のオンボーディング時間も短縮されています。 + + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + Course BuilderのドキュメントにStarlightを使ってみていますが、素晴らしい体験です。細部まで気が利いており、サイトをいじったりすることなくMarkdownの執筆に集中できます。 + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + Starlightを使い始めました。何もしなくてもパフォーマンスが素晴らしいのには驚きました。 + + 💯💯💯💯 + + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + Starlightはドキュメントを作成するのにベストな選択肢です。Astroのパワーとスピード、そしてStarlightのツールが組み合わさることで、天国のような体験が得られます。 + + しばらく使っていますが、ずっと変わらず愛用しています! + + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + 前職でStarlightを使っており、とても気に入っていました。素晴らしいコンポーネント、直感的なデザイン、そして非常にレスポンシブなコミュニティ(誰かが何かを必要とすると、すぐに対応してくれたり、回避策を教えてくれたりしました)。とても気持ちの良い体験でした。 + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + Starlightのおかげで、私のモノレポサイトのドキュメントがより素晴らしいものとなりました。Astroのパワーはそのままに、非常に使いやすくなっています。開発してくれてありがとう! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + Starlightは、ドキュメント作成に最適なツールです。既存のAstroサイトにドキュメントを追加するのがとても簡単になりました。他のツールを使うためのサブドメインが不要になりました。 + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + WPEngine Atlas Platformのドキュメントを作り直しています。Starlightには、A+のドキュメントプラットフォームを作るために必要なものがすべて揃っています 🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + Starlightを試してみてください! + + 私はいくつかのサイトで使っていますが、素晴らしいですよ。 + + </Testimonial> +</TestimonialGrid> + <AboutAstro title="提供:"> Astroは、速度を重視して設計されたオールインワンのウェブフレームワークです。お気に入りのUIコンポーネントやライブラリを使って、どこからでもコンテンツを取得し、どこにでもデプロイできます。 diff --git a/docs/src/content/docs/ja/manual-setup.mdx b/docs/src/content/docs/ja/manual-setup.mdx index 17478c5b414..2c485500832 100644 --- a/docs/src/content/docs/ja/manual-setup.mdx +++ b/docs/src/content/docs/ja/manual-setup.mdx @@ -5,7 +5,7 @@ description: 既存のAstroプロジェクトにStarlightを追加するため import { Tabs, TabItem } from '@astrojs/starlight/components'; -[入門](/ja/getting-started/#新しいプロジェクトを作成する)で述べたように、新しいStarlightサイトを作成する最も簡単な方法は、`create astro`を使用することです。このガイドでは、既存のAstroプロジェクトにStarlightを追加する方法について説明します。 +[入門](/ja/getting-started/#新しいプロジェクトの作成)で述べたように、新しいStarlightサイトを作成する最も簡単な方法は、`create astro`を使用することです。このガイドでは、既存のAstroプロジェクトにStarlightを追加する方法について説明します。 ## Starlightをセットアップする @@ -15,7 +15,7 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; Starlightは[Astroのインテグレーション](https://docs.astro.build/ja/guides/integrations-guide/)です。プロジェクトのルートディレクトリで`astro add`コマンドを実行してサイトに追加します。 -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh npx astro add starlight @@ -43,7 +43,7 @@ Starlightインテグレーションの設定は、`astro.config.mjs`ファイ まずは`title`を追加してみましょう。 -```js {7-9} +```js ins={8} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -61,20 +61,23 @@ export default defineConfig({ ### コンテンツコレクションの設定 -StarlightはAstroの[コンテンツコレクション](https://docs.astro.build/ja/guides/content-collections/)の上に構築されています。この設定は`src/content/config.ts`ファイルでおこないます。 +StarlightはAstroの[コンテンツコレクション](https://docs.astro.build/ja/guides/content-collections/)の上に構築されています。この設定は`src/content.config.ts`ファイルでおこないます。 -コンテンツの設定ファイルを作成または更新し、Starlightの`docsSchema`を使用する`docs`コレクションを追加します。 +コンテンツの設定ファイルを作成または更新し、Starlightの[`docsLoader`](/ja/reference/configuration/#docsloader)と[`docsSchema`](/ja/reference/configuration/#docsschema)を使用する`docs`コレクションを追加します。 -```js ins={3,6} -// src/content/config.ts +```js ins={3-4,7} +// src/content.config.ts import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; import { docsSchema } from '@astrojs/starlight/schema'; export const collections = { - docs: defineCollection({ schema: docsSchema() }), + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), }; ``` +Starlightは、コレクションがレガシーなコンテンツコレクションの実装で処理される[`legacy.collections`フラグ](https://docs.astro.build/ja/reference/legacy-flags/)もサポートしています。既存のAstroプロジェクトがあり、現時点ではローダーを使用するためにコレクションを変更できない場合に便利です。 + ### コンテンツの追加 以上でStarlightの設定は完了し、コンテンツを追加する準備が整いました! @@ -91,7 +94,7 @@ description: Starlightで作成されたこのドキュメントサイトで、 ようこそ私のプロジェクトへ! ``` -Starlightはファイルベースのルーティングを使用してます。そのため、`src/content/docs/`にあるMarkdown、MDX、Markdocファイルはすべて、サイトのページへと変換されます。フロントマターのメタデータ(上記の例では`title`と`description`フィールド)により、各ページの表示方法を変更できます。利用可能なオプションについては、[フロントマターのリファレンス](/ja/reference/frontmatter/)を参照してください。 +Starlightはファイルベースのルーティングを使用しています。そのため、`src/content/docs/`にあるMarkdown、MDX、Markdocファイルはすべて、サイトのページへと変換されます。フロントマターのメタデータ(上記の例では`title`と`description`フィールド)により、各ページの表示方法を変更できます。利用可能なオプションについては、[フロントマターのリファレンス](/ja/reference/frontmatter/)を参照してください。 ## 既存サイトのためのヒント @@ -103,7 +106,7 @@ Starlightのすべてのページをサブパスに追加するには、ドキ たとえば、Starlightのページがすべて`/guides/`で始まる場合は、コンテンツを`src/content/docs/guides/`ディレクトリに追加します。 -import FileTree from '../../../components/file-tree.astro'; +import { FileTree } from '@astrojs/starlight/components'; <FileTree> @@ -122,4 +125,6 @@ import FileTree from '../../../components/file-tree.astro'; ### StarlightとSSR -現在、StarlightはAstroのサーバーアダプタを使用した[SSRデプロイ](https://docs.astro.build/ja/guides/server-side-rendering/)をサポートしていません。近いうちにサポートできるようにしたいと考えています。 +SSRを有効にするには、Astroドキュメントの「[オンデマンドレンダリングアダプター](https://docs.astro.build/ja/guides/on-demand-rendering/)」ガイドに従い、Starlightプロジェクトにサーバーアダプターを追加します。 + +Starlightによって生成されるドキュメントページは、プロジェクトの出力モードに関係なくデフォルトでプリレンダリングされます。Starlightページのプリレンダリングを無効にするには、[`prerender`設定オプション](/ja/reference/configuration/#prerender)を`false`に設定します。 diff --git a/docs/src/content/docs/ja/reference/configuration.md b/docs/src/content/docs/ja/reference/configuration.md deleted file mode 100644 index 6f492af38ce..00000000000 --- a/docs/src/content/docs/ja/reference/configuration.md +++ /dev/null @@ -1,420 +0,0 @@ ---- -title: 設定方法 -description: Starlightがサポートするすべての設定オプションの概要。 ---- - -## `starlight`インテグレーションの設定 - -Starlightは[Astro](https://astro.build)ウェブフレームワークの上に構築されたインテグレーションです。`astro.config.mjs`設定ファイル内でプロジェクトの設定をおこないます。 - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; -export default defineConfig({ - integrations: [ - starlight({ - title: '私の楽しいドキュメントサイト', - }), - ], -}); -``` - -以下のオプションを`starlight`インテグレーションに設定できます。 - -### `title`(必須) - -**type:** `string` - -ウェブサイトのタイトルを設定します。メタデータとブラウザのタブのタイトルに使用されます。 - -### `description` - -**type:** `string` - -ウェブサイトの説明を設定します。`description`がページのフロントマターに設定されていない場合、`<meta name="description">`タグで検索エンジンに共有するメタデータとして使用されます。 - -### `logo` - -**type:** [`LogoConfig`](#logoconfig) - -ナビゲーションバーにサイトタイトルと並べて、またはその代わりとして表示するロゴ画像を設定します。単一の`src`プロパティを設定するか、`light`と`dark`用に別々の画像ソースを設定できます。 - -```js -starlight({ - logo: { - src: './src/assets/my-logo.svg', - }, -}); -``` - -#### `LogoConfig` - -```ts -type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( - | { src: string } - | { light: string; dark: string } -); -``` - -### `tableOfContents` - -**type:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` -**default:** `{ minHeadingLevel: 2; maxHeadingLevel: 3; }` - -各ページの右側に表示される目次を設定します。デフォルトでは、`<h2>`と`<h3>`の見出しがこの目次に含まれます。 - -### `editLink` - -**type:** `{ baseUrl: string }` - -`editLink.baseUrl`を設定すると、「ページを編集」リンクが有効になります。最終的なリンクは、`editLink.baseUrl` + 現在のページのパスになります。たとえば、GitHubの`withastro/starlight`リポジトリのページを編集するには以下のようにします。 - -```js -starlight({ - editLink: { - baseUrl: 'https://github.com/withastro/starlight/edit/main/', - }, -}); -``` - -この設定により、`/introduction`ページには`https://github.com/withastro/starlight/edit/main/src/docs/introduction.md`を指す編集リンクが表示されます。 - -### `sidebar` - -**type:** [`SidebarItem[]`](#sidebaritem) - -サイトのサイドバーのナビゲーション項目を設定します。 - -サイドバーはリンクとリンクのグループの配列です。各項目は、`label`と以下のプロパティのいずれかが必要です。 - -- `link` — 特定のURL、たとえば`'/home'`や`'https://example.com'`などへの単一のリンク。 - -- `items` — サイドバーの複数のリンクとサブグループを含む配列。 - -- `autogenerate` — リンクのグループを自動的に生成するために、ドキュメントのディレクトリを指定するオブジェクト。 - -```js -starlight({ - sidebar: [ - // 「ホーム」というラベルのついた単一のリンク。 - { label: 'ホーム', link: '/' }, - // 2つのリンクを含む、「ここから始める」というラベルのついたグループ。 - { - label: 'ここから始める', - items: [ - { label: 'はじめに', link: '/intro' }, - { label: '次のステップ', link: '/next-steps' }, - ], - }, - // referenceディレクトリのすべてのページにリンクするグループ。 - { - label: 'リファレンス', - autogenerate: { directory: 'reference' }, - }, - ], -}); -``` - -#### 並び順 - -自動生成されたサイドバーグループは、ファイル名のアルファベット順に並べ替えられます。たとえば、`astro.md`から生成されたページは、`starlight.md`というページの上に表示されます。 - -#### グループの折りたたみ - -リンクのグループはデフォルトで展開されます。`collapsed`プロパティを`true`に設定して、この動作を変更できます。 - -自動生成されたサブグループは、デフォルトでは親グループの`collapsed`プロパティに従います。`autogenerate.collapsed`プロパティを設定して、これを上書きできます。 - -```js -sidebar: [ - // 折りたたまれたリンクのグループ。 - { - label: '折りたたまれたリンク', - collapsed: true, - items: [ - { label: 'はじめに', link: '/intro' }, - { label: '次のステップ', link: '/next-steps' }, - ], - }, - // 自動生成される折りたたまれたサブグループを含む展開されたグループ。 - { - label: '参照', - autogenerate: { - directory: 'reference', - collapsed: true, - }, - }, -], -``` - -#### ラベルの翻訳 - -多言語対応が必要なサイトの場合、各項目の`label`はデフォルトのロケールのものとみなされます。サポート対象の言語のラベルを提供するには、`translations`プロパティを設定します。 - -```js -sidebar: [ - // フランス語に翻訳されたラベルをもつサイドバーの例。 - { - label: 'ここから始める', - translations: { fr: 'Commencez ici' }, - items: [ - { - label: '開始する', - translations: { fr: 'Bien démarrer' }, - link: '/getting-started', - }, - { - label: 'プロジェクトの構造', - translations: { fr: 'Structure du projet' }, - link: '/structure', - }, - ], - }, -], -``` - -#### `SidebarItem` - -```ts -type SidebarItem = { - label: string; - translations?: Record<string, string>; -} & ( - | { - link: string; - badge?: string | BadgeConfig; - } - | { items: SidebarItem[]; collapsed?: boolean } - | { - autogenerate: { directory: string; collapsed?: boolean }; - collapsed?: boolean; - } -); -``` - -#### `BadgeConfig` - -```ts -interface BadgeConfig { - text: string; - variant: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; -} -``` - -### `locales` - -**type:** <code>{ \[dir: string\]: [LocaleConfig](#localeconfig) }</code> - -[サイトの国際化(i18n)をおこなうには](/ja/guides/i18n/)、サポート対象の`locales`を設定します。 - -各エントリは、その言語のファイルが保存されているディレクトリ名をキーとして使用する必要があります。 - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'My Site', - // このサイトのデフォルト言語を英語に設定します。 - defaultLocale: 'en', - locales: { - // 英語のドキュメントは`src/content/docs/en/`にあります。 - en: { - label: 'English', - }, - // 簡体字中国語のドキュメントは`src/content/docs/zh/`にあります。 - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - // アラビア語のドキュメントは`src/content/docs/ar/`にあります。 - ar: { - label: 'العربية', - dir: 'rtl', - }, - }, - }), - ], -}); -``` - -#### `LocaleConfig` - -```ts -interface LocaleConfig { - label: string; - lang?: string; - dir?: 'ltr' | 'rtl'; -} -``` - -各ロケールに対し以下のオプションを設定できます。 - -##### `label`(必須) - -**type:** `string` - -たとえば言語の切替機能などでユーザーに表示する、この言語を表わすラベルです。ほとんどの場合、このラベルは、その言語を使用するユーザーが読みたいと思う言語の名前にすることが望ましいでしょう。たとえば、`"English"`、`"العربية"`、`"简体中文"`などです。 - -##### `lang` - -**type:** `string` - -この言語のBCP-47タグです。たとえば`"en"`、`"ar"`、`"zh-CN"`などです。設定されていない場合、デフォルトでは言語のディレクトリ名が使用されます。`"pt-BR"`や`"en-US"`のように地域タグが含まれる言語タグは、その地域専用の翻訳が見つからない場合、ベース言語の組み込みUI翻訳が使用されます。 - -##### `dir` - -**type:** `'ltr' | 'rtl'` - -この言語を記述する方向です。左から右へ(デフォルト)は`"ltr"`を、右から左へは`"rtl"`を設定します。 - -#### ルートロケール - -`root`ロケールを設定することで、`/lang/`ディレクトリなしでデフォルト言語を提供できます。 - -```js -starlight({ - locales: { - root: { - label: 'English', - lang: 'en', - }, - fr: { - label: 'Français', - }, - }, -}); -``` - -この設定により、たとえば`/getting-started/`を英語のルートとし、対応するフランス語のページを`/fr/getting-started/`として提供することができます。 - -### `defaultLocale` - -**type:** `string` - -このサイトのデフォルト言語を設定します。この値は、[`locales`](#locales)オブジェクトのキーのいずれかと一致する必要があります。(デフォルト言語が[ルートロケール](#ルートロケール)の場合は、この設定をスキップできます。) - -翻訳がない場合には、デフォルトロケールがフォールバックコンテンツとして使用されます。 - -### `social` - -**type:** `Partial<Record<'bitbucket' | 'codeberg' | 'codePen' | 'discord' | 'github' | 'gitlab' | 'gitter' | 'instagram' | 'linkedin' | 'mastodon' | 'microsoftTeams' | 'stackOverflow' | 'threads' | 'twitch' | 'twitter' | 'youtube', string>>` - -このサイトのソーシャルメディアアカウントに関する任意の項目です。これらのいずれかを追加すると、サイトヘッダーにアイコンリンクとして表示されます。 - -```js -starlight({ - social: { - codeberg: 'https://codeberg.org/knut/examples', - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - gitlab: 'https://gitlab.com/delucis', - linkedin: 'https://www.linkedin.com/company/astroinc', - mastodon: 'https://m.webtoo.ls/@astro', - threads: 'https://www.threads.net/@nmoodev', - twitch: 'https://www.twitch.tv/bholmesdev', - twitter: 'https://twitter.com/astrodotbuild', - youtube: 'https://youtube.com/@astrodotbuild', - }, -}); -``` - -### `customCss` - -**type:** `string[]` - -Starlightサイトの見た目をカスタマイズするためのCSSファイルを設定します。 - -プロジェクトのルートからの相対パスで指定したローカルのCSSファイル(`'./src/custom.css'`など)と、npmモジュールとしてインストールしたCSS(`'@fontsource/roboto'`など)に対応しています。 - -```js -starlight({ - customCss: ['./src/custom-styles.css', '@fontsource/roboto'], -}); -``` - -### `head` - -**type:** [`HeadConfig[]`](#headconfig) - -Starlightサイトの`<head>`にカスタムタグを追加します。アナリティクスやその他のサードパーティのスクリプトやリソースを追加するのに便利です。 - -```js -starlight({ - head: [ - // Fathomのアナリティクススクリプトタグを追加する例。 - { - tag: 'script', - attrs: { - src: 'https://cdn.usefathom.com/script.js', - 'data-site': 'MY-FATHOM-ID', - defer: true, - }, - }, - ], -}); -``` - -#### `HeadConfig` - -```ts -interface HeadConfig { - tag: string; - attrs?: Record<string, string | boolean | undefined>; - content?: string; -} -``` - -### `lastUpdated` - -**type:** `boolean` -**default:** `false` - -フッターにページの最終更新日を表示するかどうかを制御します。 - -デフォルトでは、この機能はリポジトリのGit履歴に依存しており、[浅いクローン](https://git-scm.com/docs/git-clone/ja#git-clone---depthltdepthgt)を実行する一部のデプロイプラットフォームでは正確にならない場合があります。[フロントマターの`lastUpdated`フィールド](/ja/reference/frontmatter/#lastupdated)を使用して、各ページでこの設定またはGitを基準とした日付を上書きできます。 - -### `pagination` - -**type:** `boolean` -**default:** `true` - -フッターに前のページと次のページへのリンクを含めるかどうかを定義します。 - -[`prev`](/ja/reference/frontmatter/#prev)と[`next`](/ja/reference/frontmatter/#next)フロントマターフィールドを使用して、この設定、またはリンクテキストとURLをページごとに上書きできます。 - -### `favicon` - -**type:** `string` -**default:** `'/favicon.svg'` - -サイトのデフォルトファビコンのパスを設定します。ファビコンは`public/`ディレクトリに配置され、また有効なアイコンファイル(`.ico`、`.gif`、`.jpg`、`.png`、または`.svg`)である必要があります。 - -```js -starlight({ - favicon: '/images/favicon.svg', -}), -``` - -追加のバリアントやフォールバック用のファビコンを設定する必要がある場合は、[`head`オプション](#head)を使用してタグを追加できます。 - -```js -starlight({ - favicon: '/images/favicon.svg'. - head: [ - // Safari用にICOファビコンのフォールバックを追加します。 - { - tag: 'link', - attrs: { - rel: 'icon', - href:'/images/favicon.ico', - sizes: '32x32', - }, - }, - ], -}); -``` diff --git a/docs/src/content/docs/ja/reference/configuration.mdx b/docs/src/content/docs/ja/reference/configuration.mdx new file mode 100644 index 00000000000..2919267941d --- /dev/null +++ b/docs/src/content/docs/ja/reference/configuration.mdx @@ -0,0 +1,785 @@ +--- +title: 設定方法 +description: Starlightがサポートするすべての設定オプションの概要。 +--- + +## `starlight`インテグレーションの設定 + +Starlightは[Astro](https://astro.build)ウェブフレームワークの上に構築されたインテグレーションです。`astro.config.mjs`設定ファイル内でプロジェクトの設定をおこないます。 + +```js +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: '私の楽しいドキュメントサイト', + }), + ], +}); +``` + +以下のオプションを`starlight`インテグレーションに設定できます。 + +### `title`(必須) + +**type:** `string | Record<string, string>` + +ウェブサイトのタイトルを設定します。メタデータとブラウザのタブのタイトルに使用されます。 + +文字列を設定できますが、多言語サイトの場合は、異なるロケールごとの値をもつオブジェクトも使用できます。オブジェクト形式を使用する場合、キーはBCP-47タグ(`en`、`ar`、`zh-CN`など)である必要があります。 + +```ts +starlight({ + title: { + en: 'My delightful docs site', + de: 'Meine bezaubernde Dokumentationsseite', + }, +}); +``` + +### `description` + +**type:** `string` + +ウェブサイトの説明を設定します。`description`がページのフロントマターに設定されていない場合、`<meta name="description">`タグで検索エンジンに共有するメタデータとして使用されます。 + +### `logo` + +**type:** [`LogoConfig`](#logoconfig) + +ナビゲーションバーにサイトタイトルと並べて、またはその代わりとして表示するロゴ画像を設定します。単一の`src`プロパティを設定するか、`light`と`dark`用に別々の画像ソースを設定できます。 + +```js +starlight({ + logo: { + src: './src/assets/my-logo.svg', + }, +}); +``` + +#### `LogoConfig` + +```ts +type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( + | { src: string } + | { light: string; dark: string } +); +``` + +### `tableOfContents` + +**type:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number }` +**default:** `{ minHeadingLevel: 2, maxHeadingLevel: 3 }` + +各ページの右側に表示される目次を設定します。デフォルトでは、`<h2>`と`<h3>`の見出しがこの目次に含まれます。 + +### `editLink` + +**type:** `{ baseUrl: string }` + +`editLink.baseUrl`を設定すると、「ページを編集」リンクが有効になります。最終的なリンクは、`editLink.baseUrl` + 現在のページのパスになります。たとえば、GitHubの`withastro/starlight`リポジトリのページを編集するには以下のようにします。 + +```js +starlight({ + editLink: { + baseUrl: 'https://github.com/withastro/starlight/edit/main/', + }, +}); +``` + +この設定により、`/introduction`ページには`https://github.com/withastro/starlight/edit/main/src/content/docs/introduction.md`を指す編集リンクが表示されます。 + +### `sidebar` + +**type:** [`SidebarItem[]`](#sidebaritem) + +サイトのサイドバーのナビゲーション項目を設定します。 + +サイドバーはリンクとリンクのグループの配列です。`slug`を使用する場合を除き、各項目は`label`と以下のプロパティのいずれかが必要です。 + +- `link` — 特定のURL、たとえば`'/home'`や`'https://example.com'`などへの単一のリンク。 + +- `slug` — たとえば`'guides/getting-started'`など、内部ページへの参照。 + +- `items` — サイドバーの複数のリンクとサブグループを含む配列。 + +- `autogenerate` — リンクのグループを自動的に生成するために、ドキュメントのディレクトリを指定するオブジェクト。 + +内部リンクは、`slug`プロパティをもつオブジェクトの代わりに文字列として指定することもできます。 + +```js +starlight({ + sidebar: [ + // 「ホーム」というラベルのついた単一のリンク。 + { label: 'ホーム', link: '/' }, + // 4つのリンクを含む、「ここから始める」というラベルのついたグループ。 + { + label: 'ここから始める', + items: [ + // 内部リンクに`slug`を使用する。 + { slug: 'intro' }, + { slug: 'installation' }, + // 内部リンクのための省略形を使用する。 + 'tutorial', + 'next-steps', + ], + }, + // referenceディレクトリのすべてのページにリンクするグループ。 + { + label: 'リファレンス', + autogenerate: { directory: 'reference' }, + }, + ], +}); +``` + +#### 並び順 + +自動生成されたサイドバーグループは、ファイル名のアルファベット順に並べ替えられます。たとえば、`astro.md`から生成されたページは、`starlight.md`というページの上に表示されます。 + +#### グループの折りたたみ + +リンクのグループはデフォルトで展開されます。`collapsed`プロパティを`true`に設定して、この動作を変更できます。 + +自動生成されたサブグループは、デフォルトでは親グループの`collapsed`プロパティに従います。`autogenerate.collapsed`プロパティを設定して、これを上書きできます。 + +```js {5,13} +sidebar: [ + // 折りたたまれたリンクのグループ。 + { + label: '折りたたまれたリンク', + collapsed: true, + items: ['intro', 'next-steps'], + }, + // 自動生成される折りたたまれたサブグループを含む展開されたグループ。 + { + label: '参照', + autogenerate: { + directory: 'reference', + collapsed: true, + }, + }, +], +``` + +#### ラベルの翻訳 + +多言語対応が必要なサイトの場合、各項目の`label`はデフォルトのロケールのものとみなされます。サポート対象の言語のラベルを提供するには、`translations`プロパティを設定します。 + +```js {5,9,14} +sidebar: [ + // ブラジルポルトガル語に翻訳されたラベルをもつサイドバーの例。 + { + label: 'ここから始める', + translations: { 'pt-BR': 'Comece Aqui' }, + items: [ + { + label: '開始する', + translations: { 'pt-BR': 'Introdução' }, + link: '/getting-started', + }, + { + label: 'プロジェクトの構造', + translations: { 'pt-BR': 'Estrutura de Projetos' }, + link: '/structure', + }, + ], + }, +], +``` + +#### `SidebarItem` + +```ts +type SidebarItem = + | string + | ({ + translations?: Record<string, string>; + badge?: string | BadgeConfig; + } & ( + | { + // リンク + link: string; + label: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // 内部リンク + slug: string; + label?: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // リンクのグループ + label: string; + items: SidebarItem[]; + collapsed?: boolean; + } + | { + // 自動生成されたリンクのグループ + label: string; + autogenerate: { + directory: string; + collapsed?: boolean; + attrs?: Record<string, string | number | boolean | undefined>; + }; + collapsed?: boolean; + } + )); +``` + +#### `BadgeConfig` + +```ts +interface BadgeConfig { + text: string; + variant?: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; + class?: string; +} +``` + +### `locales` + +**type:** <code>\{ \[dir: string\]: [LocaleConfig](#localeconfig) \}</code> + +[サイトの国際化(i18n)をおこなうには](/ja/guides/i18n/)、サポート対象の`locales`を設定します。 + +各エントリは、その言語のファイルが保存されているディレクトリ名をキーとして使用する必要があります。 + +```js +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'My Site', + // このサイトのデフォルト言語を英語に設定します。 + defaultLocale: 'en', + locales: { + // 英語のドキュメントは`src/content/docs/en/`にあります。 + en: { + label: 'English', + }, + // 簡体字中国語のドキュメントは`src/content/docs/zh-cn/`にあります。 + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + // アラビア語のドキュメントは`src/content/docs/ar/`にあります。 + ar: { + label: 'العربية', + dir: 'rtl', + }, + }, + }), + ], +}); +``` + +#### `LocaleConfig` + +```ts +interface LocaleConfig { + label: string; + lang?: string; + dir?: 'ltr' | 'rtl'; +} +``` + +各ロケールに対し以下のオプションを設定できます。 + +##### `label`(必須) + +**type:** `string` + +たとえば言語の切替機能などでユーザーに表示する、この言語を表わすラベルです。ほとんどの場合、このラベルは、その言語を使用するユーザーが読みたいと思う言語の名前にすることが望ましいでしょう。たとえば、`"English"`、`"العربية"`、`"简体中文"`などです。 + +##### `lang` + +**type:** `string` + +この言語のBCP-47タグです。たとえば`"en"`、`"ar"`、`"zh-CN"`などです。設定されていない場合、デフォルトでは言語のディレクトリ名が使用されます。`"pt-BR"`や`"en-US"`のように地域タグが含まれる言語タグは、その地域専用の翻訳が見つからない場合、ベース言語の組み込みUI翻訳が使用されます。 + +##### `dir` + +**type:** `'ltr' | 'rtl'` + +この言語を記述する方向です。左から右へ(デフォルト)は`"ltr"`を、右から左へは`"rtl"`を設定します。 + +#### ルートロケール + +`root`ロケールを設定することで、`/lang/`ディレクトリなしでデフォルト言語を提供できます。 + +```js {3-6} +starlight({ + locales: { + root: { + label: 'English', + lang: 'en', + }, + fr: { + label: 'Français', + }, + }, +}); +``` + +この設定により、たとえば`/getting-started/`を英語のルートとし、対応するフランス語のページを`/fr/getting-started/`として提供することができます。 + +### `defaultLocale` + +**type:** `string` + +このサイトのデフォルト言語を設定します。この値は、[`locales`](#locales)オブジェクトのキーのいずれかと一致する必要があります。(デフォルト言語が[ルートロケール](#ルートロケール)の場合は、この設定をスキップできます。) + +翻訳がない場合には、デフォルトロケールがフォールバックコンテンツとして使用されます。 + +### `social` + +**type:** <code>{`Array<{ label: string; icon: `}[StarlightIcon](/ja/reference/icons/){`; href: string }>`}</code> + +このサイトのソーシャルメディアアカウントに関する任意の項目です。各エントリは、サイトヘッダーにアイコンリンクとして表示されます。 + +```js +starlight({ + social: [ + { icon: 'codeberg', label: 'Codeberg', href: 'https://codeberg.org/knut' }, + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro' }, + { icon: 'gitlab', label: 'GitLab', href: 'https://gitlab.com/delucis' }, + { icon: 'mastodon', label: 'Mastodon', href: 'https://m.webtoo.ls/@astro' }, + ], +}), +``` + +### `customCss` + +**type:** `string[]` + +Starlightサイトの見た目をカスタマイズするためのCSSファイルを設定します。 + +プロジェクトのルートからの相対パスで指定したローカルのCSSファイル(`'./src/custom.css'`など)と、npmモジュールとしてインストールしたCSS(`'@fontsource/roboto'`など)に対応しています。 + +```js +starlight({ + customCss: ['./src/custom-styles.css', '@fontsource/roboto'], +}); +``` + +### `markdown` + +**type:** `{ headingLinks?: boolean; processedDirs?: string[] }` +**default:** `{ headingLinks: true, processedDirs: [] }` + +StarlightのMarkdown処理を設定します。 + +#### `headingLinks` + +**type:** `boolean` +**default:** `true` + +見出しにクリック可能なアンカーリンクを付けてレンダリングするかどうかを制御します。 + +```js +starlight({ + markdown: { + // Starlightのクリック可能な見出しアンカーリンクを無効にする。 + headingLinks: false, + }, +}), +``` + +#### `processedDirs` + +**type:** `string[]` +**default:** `[]` + +StarlightのMarkdownパイプラインで処理される追加のディレクトリを定義します。デフォルトでは、Starlightの[`docsLoader()`](/ja/reference/configuration/#docsloader)を使用して読み込まれたMarkdownおよびMDXコンテンツのみが処理されます。プロジェクトのルートからの相対パスでローカルディレクトリを指定できます(例: `'./src/data/comments/'`)。 + +Starlightの処理には、[クリック可能な見出しアンカーリンク](#headinglinks)、[補足情報のMarkdownディレクティブ構文](/ja/guides/authoring-content/#補足情報)、およびコードブロックのRTLサポートが含まれます。このオプションは、[カスタムページ](/ja/guides/pages/#カスタムページ)で`<StarlightPage>`コンポーネントを使用してカスタムコンテンツコレクションのコンテンツをレンダリングしており、そのコンテンツにもStarlightのMarkdown処理を適用したい場合に便利です。 + +```js +starlight({ + markdown: { + // `src/data/reviews/`ディレクトリにある`reviews`コンテンツコレクションの + // Markdownファイルを処理する。 + processedDirs: ['./src/data/reviews/'], + }, +}), +``` + +### `expressiveCode` + +**type:** `StarlightExpressiveCodeOptions | boolean` +**default:** `true` + +Starlightは、[Expressive Code](https://expressive-code.com)を使用して、コードブロックのレンダリングやコード例の一部のハイライト、コードブロックへのファイル名の追加などをおこなっています。MarkdownやMDXのコンテンツでExpressive Code構文を使用する方法については、[「コードブロック」ガイド](/ja/guides/authoring-content/#コードブロック)を参照してください。 + +[Expressive Code標準の設定オプション](https://expressive-code.com/reference/configuration/)はすべて使用できます。また、Starlightの`expressiveCode`オプションを設定することで、Starlight固有のプロパティも使用できます。たとえば、Expressive Codeの`styleOverrides`オプションを設定して、デフォルトのCSSを上書きできます。これにより、コードブロックに角丸を付けるなどのカスタマイズが可能になります。 + +```js ins={2-4} +starlight({ + expressiveCode: { + styleOverrides: { borderRadius: '0.5rem' }, + }, +}); +``` + +Expressive Codeを無効にするには、Starlightの設定で`expressiveCode: false`を設定します。 + +```js ins={2} +starlight({ + expressiveCode: false, +}); +``` + +標準のExpressive Codeオプションに加えて、`expressiveCode`の設定に以下のStarlight固有のプロパティを追加することで、コードブロックのテーマの動作をさらにカスタマイズできます。 + +#### `themes` + +**type:** `Array<string | ThemeObject | ExpressiveCodeTheme>` +**default:** `['starlight-dark', 'starlight-light']` + +コードブロックのスタイルに使用するテーマを設定します。サポートされているテーマのフォーマットの詳細については、[Expressive Codeの`themes`ドキュメント](https://expressive-code.com/guides/themes/)を参照してください。 + +Starlightは、デフォルトでSarah Drasnerの[Night Owlテーマ](https://github.com/sdras/night-owl-vscode-theme)のダークとライトのバリアントを使用します。 + +ダークテーマとライトテーマを少なくとも1つずつ提供すると、Starlightは自動的にアクティブなコードブロックのテーマを現在のサイトテーマと同期します。この動作は[`useStarlightDarkModeSwitch`](#usestarlightdarkmodeswitch)オプションから設定できます。 + +#### `useStarlightDarkModeSwitch` + +**type:** `boolean` +**default:** `true` + +`true`の場合、サイトテーマが変更されると、コードブロックは自動的にライトテーマとダークテーマを切り替えます。`false`の場合、複数のテーマの切り替えをおこなうために、手動でCSSを追加する必要があります。 + +:::note +`themes`を設定する場合、Starlightのダークモードスイッチが機能するように、ダークテーマとライトテーマを少なくとも1つずつ設定する必要があります。 +::: + +#### `useStarlightUiThemeColors` + +**type:** `boolean` +**default:** `themes`が設定されていない場合は`true`、それ以外の場合は`false` + +`true`の場合、コードブロックのUI要素(背景、ボタン、シャドウなど)の色にStarlightのCSS変数が使用され、[サイトのカラーテーマ](/ja/guides/css-and-tailwind/#テーマの設定)と一致させます。`false`の場合、これらの要素には、アクティブなシンタックスハイライトのテーマから提供される色が使用されます。 + +:::note +カスタムテーマを使用し、かつこの値を`true`に設定する場合、適切な色のコントラストを確保するために、ダークテーマとライトテーマを少なくとも1つずつ提供する必要があります。 +::: + +### `pagefind` + +**type:** <code>boolean | <a href="#pagefindoptions">PagefindOptions</a></code> +**default:** `true` + +Starlightのデフォルトのサイト検索プロバイダである[Pagefind](https://pagefind.app/)を設定します。 + +`false`に設定すると、Pagefindによるサイトのインデックス作成はおこなわれません。また、デフォルトの検索UIを使用している場合は、これも非表示になります。 + +[`prerender`](#prerender)オプションが`false`に設定されている場合、Pagefindを有効にすることはできません。 + +Pagefindの検索クライアントを設定するには、`pagefind`にオブジェクトを設定します。 + +- 検索結果のランキングの計算方法を制御する`pagefind.ranking`オプションの使用方法については、Pagefindドキュメントの[「Customize Pagefind's result ranking」](https://pagefind.app/docs/ranking/)を参照してください。 +- 複数サイトの検索方法を制御する`pagefind.mergeIndex`オプションの使用方法については、Pagefindドキュメントの[「Searching multiple sites」](https://pagefind.app/docs/multisite/)を参照してください。 + +#### `PagefindOptions` + +```ts +interface PagefindOptions { + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + indexWeight?: number; + mergeIndex?: Array<{ + bundlePath: string; + indexWeight?: number; + basePath?: string; + baseUrl?: string; + mergeFilter?: Record<string, string | string[]>; + language?: string; + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + }>; +} +``` + +### `prerender` + +**type:** `boolean` +**default:** `true` + +Starlightページが静的HTMLに事前レンダリングされるか、[SSRアダプター](https://docs.astro.build/ja/guides/on-demand-rendering/)によってオンデマンドでレンダリングされるかを設定します。 + +Starlightページはデフォルトで事前レンダリングされます。SSRアダプターを使用してStarlightページをオンデマンドでレンダリングしたい場合は、`prerender: false`に設定します。 + +### `head` + +**type:** [`HeadConfig[]`](#headconfig) + +Starlightサイトの`<head>`にカスタムタグを追加します。アナリティクスやその他のサードパーティのスクリプトやリソースを追加するのに便利です。 + +```js +starlight({ + head: [ + // Fathomのアナリティクススクリプトタグを追加する例。 + { + tag: 'script', + attrs: { + src: 'https://cdn.usefathom.com/script.js', + 'data-site': 'MY-FATHOM-ID', + defer: true, + }, + }, + ], +}); +``` + +`head`のエントリーは直接HTML要素に変換され、Astroの[スクリプト](https://docs.astro.build/ja/guides/client-side-scripts/#スクリプトの処理)や[スタイル](https://docs.astro.build/ja/guides/styling/#astroでのスタイリング)の処理を通過しません。スクリプト、スタイル、または画像などのローカルアセットをインポートする必要がある場合は、[Headコンポーネントをオーバーライド](/ja/guides/overriding-components/#組み込みコンポーネントを再利用する)してください。 + +#### `HeadConfig` + +```ts +interface HeadConfig { + tag: string; + attrs?: Record<string, string | boolean | undefined>; + content?: string; +} +``` + +### `lastUpdated` + +**type:** `boolean` +**default:** `false` + +フッターにページの最終更新日を表示するかどうかを制御します。 + +デフォルトでは、この機能はリポジトリのGit履歴に依存しており、[浅いクローン](https://git-scm.com/docs/git-clone/ja#git-clone---depthltdepthgt)を実行する一部のデプロイプラットフォームでは正確にならない場合があります。[フロントマターの`lastUpdated`フィールド](/ja/reference/frontmatter/#lastupdated)を使用して、各ページでこの設定またはGitを基準とした日付を上書きできます。 + +### `pagination` + +**type:** `boolean` +**default:** `true` + +フッターに前のページと次のページへのリンクを含めるかどうかを定義します。 + +[`prev`](/ja/reference/frontmatter/#prev)と[`next`](/ja/reference/frontmatter/#next)フロントマターフィールドを使用して、この設定、またはリンクテキストとURLをページごとに上書きできます。 + +### `favicon` + +**type:** `string` +**default:** `'/favicon.svg'` + +サイトのデフォルトファビコンのパスを設定します。ファビコンは`public/`ディレクトリに配置され、また有効なアイコンファイル(`.ico`、`.gif`、`.jpg`、`.png`、または`.svg`)である必要があります。 + +```js +starlight({ + favicon: '/images/favicon.svg', +}), +``` + +追加のバリアントやフォールバック用のファビコンを設定する必要がある場合は、[`head`オプション](#head)を使用してタグを追加できます。 + +```js +starlight({ + favicon: '/images/favicon.svg', + head: [ + // Safari用にICOファビコンのフォールバックを追加します。 + { + tag: 'link', + attrs: { + rel: 'icon', + href: '/images/favicon.ico', + sizes: '32x32', + }, + }, + ], +}); +``` + +### `titleDelimiter` + +**type:** `string` +**default:** `'|'` + +ブラウザのタブに表示される、ページの`<title>`タグ内のページタイトルとサイトタイトルの間の区切り文字を設定します。 + +デフォルトでは、すべてのページの`<title>`は`ページタイトル | サイトタイトル`となります。たとえば、このページのタイトルは「設定方法」であり、このサイトのタイトルは「Starlight」なので、このページの`<title>`は「設定方法 | Starlight」となります。 + +### `disable404Route` + +**type:** `boolean` +**default:** `false` + +Starlightのデフォルトの[404ページ](https://docs.astro.build/ja/basics/astro-pages/#カスタム404エラーページ)を無効にします。プロジェクトでカスタムの`src/pages/404.astro`ルートを使用するには、このオプションを`true`に設定します。 + +### `routeMiddleware` + +**type:** `string | string[]` + +Starlightがデータを処理する方法を変更できるルートミドルウェアへのパスを指定します。これらのファイルパスは、[Astroのミドルウェア](https://docs.astro.build/ja/guides/middleware/)と競合してはなりません。 + +ルートミドルウェアの作成方法の詳細については、[ルートデータガイド](/ja/guides/route-data/#ルートデータのカスタマイズ)を参照してください。 + +### `components` + +**type:** `Record<string, string>` + +コンポーネントへのパスを指定して、Starlightのデフォルトの実装をオーバーライドします。 + +```js +starlight({ + components: { + SocialLinks: './src/components/MySocialLinks.astro', + }, +}); +``` + +オーバーライド可能なすべてのコンポーネントの詳細については、[オーバーライドリファレンス](/ja/reference/overrides/)を参照してください。 + +### `plugins` + +**type:** [`StarlightPlugin[]`](/ja/reference/plugins/#api早見表) + +Starlightをカスタムプラグインにより拡張します。プラグインは、Starlightの機能を変更または追加するために、プロジェクトに変更を適用します。 + +利用可能なプラグインの一覧については、[プラグインショーケース](/ja/resources/plugins/#プラグイン)を参照してください。 + +```js +starlight({ + plugins: [starlightPlugin()], +}); +``` + +独自のプラグインを作成する方法の詳細については、[プラグインリファレンス](/ja/reference/plugins/)を参照してください。 + +### `credits` + +**type:** `boolean` +**default:** `false` + +「Starlightで作成」リンクをサイトのフッターに表示します。 + +```js +starlight({ + credits: true, +}); +``` + +## コンテンツコレクションの設定 + +Starlightは、Astroの[コンテンツコレクション](https://docs.astro.build/ja/guides/content-collections/)を使用してコンテンツを読み込みます。Starlightのコンテンツローダーとスキーマにより、必要に応じてコレクションを設定できます。 + +```js +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + // 任意: i18nコレクションは多言語サイトのUI翻訳に使用されます + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), +}; +``` + +### ローダー + +Starlightは、コンテンツコレクションの設定をシンプルにするために、`@astrojs/starlight/loaders`モジュールから以下の[Astroローダー](https://docs.astro.build/ja/reference/content-loader-reference/)をエクスポートしています。 + +#### `docsLoader()` + +`docsLoader()`は、`src/content/docs/`ディレクトリからローカルのMarkdown、MDX、Markdocファイルを読み込みます。アンダースコア(`_`)で始まるファイル名は無視されます。 + +##### インポート + +```js +import { docsLoader } from '@astrojs/starlight/loaders'; +``` + +##### オプション + +###### `generateId()` + +**type:** `({ entry: string; base: URL; data: Record<string, unknown> }) => string` + +デフォルトでは、`docsLoader()`を使用して生成されたページは、ファイル名にスラッグ化処理を施し、特殊文字を削除してファイル名を小文字に変換します。このデフォルトの動作をオーバーライドしたい場合は、独自の`generateId()`関数を指定してください。 + +たとえば、デフォルトでは削除される特殊文字を保持したい場合に便利です。デフォルトでは、`Example.File.md`は`/examplefile`として配信されます。`/Example.File`として配信したい場合は、カスタムの`generateId()`関数を定義することで実現できます。 + +```js +docsLoader({ + // `.md`または`.mdx`拡張子を削除し、それ以外のファイル名は処理しない。 + generateId: ({ entry }) => entry.split('.').slice(0, -1).join('.'), +}), +``` + +詳細については、[Astroドキュメントの`generateId()`](https://docs.astro.build/ja/reference/content-loader-reference/#generateid)を参照してください。 + +#### `i18nLoader()` + +`i18nLoader()`は、`src/content/i18n/`ディレクトリからローカルのJSONおよびYAMLファイルを読み込みます。アンダースコア(`_`)で始まるファイル名は無視されます。 + +##### インポート + +```js +import { i18nLoader } from '@astrojs/starlight/loaders'; +``` + +##### オプション + +現在、`i18nLoader()`に設定可能なオプションはありません。 + +### スキーマ + +Starlightは、`@astrojs/starlight/schema`モジュールから以下の[コンテンツコレクションスキーマ](https://docs.astro.build/ja/guides/content-collections/#defining-the-collection-schema)を提供しています。これらのスキーマは、Starlightが依存する`docs`および`i18n`コレクションに使用する必要があります。 + +#### `docsSchema()` + +`docsSchema()`は、`docs`コレクション内のすべてのコンテンツのフロントマターを解析します。 + +##### インポート + +```js +import { docsSchema } from '@astrojs/starlight/schema'; +``` + +##### オプション + +###### `extend` + +**type:** Zodスキーマ、またはZodスキーマを返す関数 +**default:** `z.object({})` + +Starlightのフロントマタースキーマを追加フィールドで拡張します。`extend`オプションの使用方法の詳細については、[「フロントマタースキーマをカスタマイズする」](/ja/reference/frontmatter/#フロントマタースキーマをカスタマイズする)を参照してください。 + +#### `i18nSchema()` + +`i18nSchema()`は、`i18n`コレクション内のすべてのデータファイルを解析します。 + +##### インポート + +```js +import { i18nSchema } from '@astrojs/starlight/schema'; +``` + +##### オプション + +###### `extend` + +**type:** Zodオブジェクト +**default:** `z.object({})` + +Starlightのi18nスキーマを追加フィールドで拡張します。`extend`オプションの使用方法の詳細については、[「翻訳スキーマを拡張する」](/ja/guides/i18n/#翻訳スキーマを拡張する)を参照してください。 diff --git a/docs/src/content/docs/ja/reference/frontmatter.md b/docs/src/content/docs/ja/reference/frontmatter.md index eb1aa6356a4..536c87ec9a3 100644 --- a/docs/src/content/docs/ja/reference/frontmatter.md +++ b/docs/src/content/docs/ja/reference/frontmatter.md @@ -5,8 +5,9 @@ description: Starlightがデフォルトでサポートするフロントマタ Starlightでは、フロントマターに値を設定することで、MarkdownとMDXのページを個別にカスタマイズできます。たとえば通常のページでは、`title`と`description`フィールドを設定します。 -```md +```md {3-4} --- +# src/content/docs/example.md title: このプロジェクトについて description: 私が取り組んでいるプロジェクトについてもっと知る。 --- @@ -28,6 +29,12 @@ description: 私が取り組んでいるプロジェクトについてもっと ページに関する説明文はページのメタデータとして使用され、また検索エンジンやソーシャルメディアのプレビューでも使用されます。 +### `slug` + +**type**: `string` + +ページのスラグを上書きします。詳しくは、Astroドキュメントの[「カスタムIDの定義」](https://docs.astro.build/ja/guides/content-collections/#defining-custom-ids)を参照してください。 + ### `editUrl` **type:** `string | boolean` @@ -42,6 +49,7 @@ description: 私が取り組んでいるプロジェクトについてもっと ```md --- +# src/content/docs/example.md title: 私たちについて head: # カスタム<title>タグを使う @@ -58,6 +66,7 @@ head: ```md --- +# src/content/docs/example.md title: 目次にH2のみを表示するページ tableOfContents: minHeadingLevel: 2 @@ -67,6 +76,7 @@ tableOfContents: ```md --- +# src/content/docs/example.md title: 目次のないページ tableOfContents: false --- @@ -89,6 +99,7 @@ tableOfContents: false ```md --- +# src/content/docs/example.md title: 私のホームページ template: splash hero: @@ -101,10 +112,25 @@ hero: - text: もっと知りたい link: /getting-started/ icon: right-arrow - variant: primary - text: GitHubで見る link: https://github.com/astronaut/my-project icon: external + variant: minimal + attrs: + rel: me +--- +``` + +ライトモードとダークモードで、異なるバージョンのヒーロー画像を表示できます。 + +```md +--- +# src/content/docs/example.md +hero: + image: + alt: キラリと光る、鮮やかなロゴ + dark: ../../assets/logo-dark.png + light: ../../assets/logo-light.png --- ``` @@ -114,19 +140,32 @@ hero: interface HeroConfig { title?: string; tagline?: string; - image?: { - alt?: string; - // リポジトリ内の画像への相対パス。 - file?: string; - // 画像のスロットに使用する生のHTML。 - // カスタムの`<img>`タグやインラインの`<svg>`などが使えます。 - html?: string; - }; + image?: + | { + // リポジトリ内の画像への相対パス。 + file: string; + // この画像を支援技術からアクセス可能にするための代替テキスト。 + alt?: string; + } + | { + // ダークモードで使用する、リポジトリ内の画像への相対パス。 + dark: string; + // ライトモードで使用する、リポジトリ内の画像への相対パス。 + light: string; + // この画像を支援技術からアクセス可能にするための代替テキスト。 + alt?: string; + } + | { + // 画像のスロットに使用する生のHTML。 + // カスタムの`<img>`タグやインラインの`<svg>`などが使えます。 + html: string; + }; actions?: Array<{ text: string; link: string; - variant: 'primary' | 'secondary' | 'minimal'; - icon: string; + variant?: 'primary' | 'secondary' | 'minimal'; + icon?: string; + attrs?: Record<string, string | number | boolean>; }>; } ``` @@ -141,6 +180,7 @@ interface HeroConfig { ```md --- +# src/content/docs/example.md title: バナーを含むページ banner: content: | @@ -157,6 +197,7 @@ banner: ```md --- +# src/content/docs/example.md title: 最終更新日をカスタマイズしたページ lastUpdated: 2022-08-09 --- @@ -170,6 +211,7 @@ lastUpdated: 2022-08-09 ```md --- +# src/content/docs/example.md # 前のページへのリンクを非表示にする prev: false --- @@ -177,6 +219,7 @@ prev: false ```md --- +# src/content/docs/example.md # 前のページへのリンクテキストを上書きする prev: チュートリアルを続ける --- @@ -184,6 +227,7 @@ prev: チュートリアルを続ける ```md --- +# src/content/docs/example.md # 前のページへのリンクとテキストを上書きする prev: link: /unrelated-page/ @@ -199,6 +243,7 @@ prev: ```md --- +# src/content/docs/example.md # 次のページへのリンクを非表示にする next: false --- @@ -213,17 +258,47 @@ next: false ```md --- +# src/content/docs/example.md # このページを検索インデックスから外す pagefind: false --- ``` +### `draft` + +**type:** `boolean` +**default:** `false` + +このページをドラフトとしてマークし、[本番ビルド](https://docs.astro.build/ja/reference/cli-reference/#astro-build)から除外するかどうかを設定します。ページをドラフトとしてマークし、開発中にのみ表示するには`true`に設定します。 + +```md +--- +# src/content/docs/example.md +# 本番ビルドからこのページを除外します +draft: true +--- +``` + +ドラフトページはビルド出力に含まれないため、[スラグ](/ja/guides/sidebar/#内部リンク)を使用してサイトのサイドバー設定に直接追加することはできません。[自動生成されるサイドバーグループ](/ja/guides/sidebar/#自動生成されるグループ)に使用されるディレクトリ内のドラフトページは、本番ビルドでは自動的に除外されます。 + ### `sidebar` -**type:** `{ label?: string; order?: number; hidden?: boolean; badge?: string | BadgeConfig }` +**type:** [`SidebarConfig`](#sidebarconfig) 自動生成されるリンクのグループを使用している際に、[サイドバー](/ja/reference/configuration/#sidebar)にページをどのように表示するかを設定します。 +#### `SidebarConfig` + +```ts +interface SidebarConfig { + label?: string; + order?: number; + hidden?: boolean; + badge?: string | BadgeConfig; + attrs?: Record<string, string | number | boolean | undefined>; +} +``` + #### `label` **type:** `string` @@ -233,6 +308,7 @@ pagefind: false ```md --- +# src/content/docs/example.md title: このプロジェクトについて sidebar: label: 概要 @@ -247,6 +323,7 @@ sidebar: ```md --- +# src/content/docs/example.md title: 最初に表示するページ sidebar: order: 1 @@ -262,6 +339,7 @@ sidebar: ```md --- +# src/content/docs/example.md title: 自動生成されるサイドバーで非表示にするページ sidebar: hidden: true @@ -272,10 +350,11 @@ sidebar: **type:** <code>string | <a href="/ja/reference/configuration/#badgeconfig">BadgeConfig</a></code> -自動生成されるリンクのグループに表示されたとき、サイドバーのページにバッジを追加します。文字列を使用すると、バッジはデフォルトのアクセントカラーで表示されます。オプションで、`text`と`variant`フィールドをもつ[`BadgeConfig`オブジェクト](/ja/reference/configuration/#badgeconfig)を渡してバッジをカスタマイズできます。 +自動生成されるリンクのグループに表示されたとき、サイドバーのページにバッジを追加します。文字列を使用すると、バッジはデフォルトのアクセントカラーで表示されます。オプションで、`text`と`variant`、`class`フィールドをもつ[`BadgeConfig`オブジェクト](/ja/reference/configuration/#badgeconfig)を渡してバッジをカスタマイズできます。 ```md --- +# src/content/docs/example.md title: バッジを含むページ sidebar: # サイトのアクセントカラーに合わせたデフォルトのバリアントを使用します @@ -285,6 +364,7 @@ sidebar: ```md --- +# src/content/docs/example.md title: バッジを含むページ sidebar: badge: @@ -292,3 +372,92 @@ sidebar: variant: caution --- ``` + +#### `attrs` + +**type:** `Record<string, string | number | boolean | undefined>` + +自動生成されるリンクのグループ内に表示されるサイドバーのページリンクに追加するHTML属性。このページが属する自動生成グループに[`autogenerate.attrs`](/ja/guides/sidebar/#自動生成されるリンクのカスタムhtml属性)が設定されている場合、フロントマターの属性はグループの属性とマージされます。 + +```md +--- +# src/content/docs/example.md +title: 新しいタブで開くページ +sidebar: + # 新しいタブでページを開きます + attrs: + target: _blank +--- +``` + +## フロントマタースキーマをカスタマイズする + +Starlightの`docs`コンテンツコレクションのフロントマタースキーマは、`docsSchema()`ヘルパーを使用して`src/content.config.ts`で設定されています。 + +```ts {4,7} +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; +``` + +コンテンツコレクションのスキーマについて詳しくは、Astroドキュメントの[「コレクションスキーマの定義」](https://docs.astro.build/ja/guides/content-collections/#defining-the-collection-schema)を参照してください。 + +`docsSchema()`は以下のオプションを受け取ります。 + +### `extend` + +**type:** ZodスキーマまたはZodスキーマを返す関数 +**default:** `z.object({})` + +`docsSchema()`のオプションで`extend`を設定すると、Starlightのスキーマを追加のフィールドで拡張できます。値は[Zodスキーマ](https://docs.astro.build/ja/guides/content-collections/#zodによるデータ型の定義)である必要があります。 + +次の例では、`description`を必須にするために厳し目の型を指定し、さらにオプションの`category`フィールドを新規追加しています。 + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: z.object({ + // 組み込みのフィールドをオプションから必須に変更します。 + description: z.string(), + // 新しいフィールドをスキーマに追加します。 + category: z.enum(['tutorial', 'guide', 'reference']).optional(), + }), + }), + }), +}; +``` + +[Astroの`image()`ヘルパー](https://docs.astro.build/ja/guides/images/#コンテンツコレクションと画像)を利用するには、拡張したスキーマを返す関数を使用します。 + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: ({ image }) => { + return z.object({ + // ローカルの画像へと解決されるフィールドを追加します。 + cover: image(), + }); + }, + }), + }), +}; +``` diff --git a/docs/src/content/docs/ja/reference/icons.mdx b/docs/src/content/docs/ja/reference/icons.mdx new file mode 100644 index 00000000000..293c273a37e --- /dev/null +++ b/docs/src/content/docs/ja/reference/icons.mdx @@ -0,0 +1,31 @@ +--- +title: アイコン +description: Starlightで利用可能なすべてのアイコンの概要。 +--- + +Starlightには、`<Icon>`コンポーネントを使用してコンテンツに表示できる、組み込みのアイコンセットが用意されています。 + +## アイコンの使用 + +アイコンは[`<Icon>`](/ja/components/icons/)コンポーネントを使用して表示できます。また、[カード](/ja/components/cards/)や[ヒーローアクション](/ja/reference/frontmatter/#hero)の設定など、他のコンポーネントでもよく使用されます。 + +## `StarlightIcon` 型 + +TypeScriptの`StarlightIcon`型を使用して、[Starlightの組み込みアイコン](#すべてのアイコン)の名前を参照できます。 + +```ts {2} /icon: (StarlightIcon)/ +// src/icon.ts +import type { StarlightIcon } from '@astrojs/starlight/types'; + +function getIconLabel(icon: StarlightIcon) { + // … +} +``` + +## すべてのアイコン + +利用可能なすべてのアイコンとその関連名が以下にリストされています。アイコンをクリックすると、その名前がクリップボードにコピーされます。 + +import IconsList from '~/components/icons-list.astro'; + +<IconsList labels={{ copied: 'コピー完了!' }} /> diff --git a/docs/src/content/docs/ja/reference/overrides.md b/docs/src/content/docs/ja/reference/overrides.md new file mode 100644 index 00000000000..d33d11c8014 --- /dev/null +++ b/docs/src/content/docs/ja/reference/overrides.md @@ -0,0 +1,234 @@ +--- +title: オーバーライド +description: Starlightのオーバーライドでサポートされているコンポーネントとコンポーネントプロパティの概要。 +tableOfContents: + maxHeadingLevel: 4 +--- + +Starlightの[`components`](/ja/reference/configuration/#components)設定オプションに置き換え対象のコンポーネントへのパスを指定することで、Starlightの組み込みコンポーネントをオーバーライドできます。このページでは、オーバーライド可能なすべてのコンポーネントと、GitHub上にあるコンポーネントのデフォルト実装へのリンクの一覧を記載しています。 + +[コンポーネントのオーバーライドガイド](/ja/guides/overriding-components/)も参照してください。 + +## コンポーネント + +### ヘッド + +以下のコンポーネントは、各ページの`<head>`要素内にレンダリングされます。[`<head>`内に配置可能な要素](https://developer.mozilla.org/ja/docs/Web/HTML/Element/head#関連情報)のみを含めるようにしてください。 + +#### `Head` + +**デフォルトコンポーネント:** [`Head.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Head.astro) + +各ページの`<head>`内にレンダリングされるコンポーネント。 + +このコンポーネントをオーバーライドするのは最後の手段としてください。可能であれば、[`head`設定オプション](/ja/reference/configuration/#head)、[`head`フロントマターフィールド](/ja/reference/frontmatter/#head)、または[ルートデータミドルウェア](/ja/guides/route-data/#ルートデータのカスタマイズ)を使用して、デフォルトコンポーネントがレンダリングするルートデータをカスタマイズすることをおすすめします。 + +#### `ThemeProvider` + +**デフォルトコンポーネント:** [`ThemeProvider.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeProvider.astro) + +ダーク/ライトテーマのサポートを設定するための、`<head>`内にレンダリングされるコンポーネント。デフォルトの実装では、インラインスクリプトと[`<ThemeSelect />`](#themeselect)で使用される`<template>`が含まれています。 + +--- + +### アクセシビリティ + +#### `SkipLink` + +**デフォルトコンポーネント:** [`SkipLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SkipLink.astro) + +アクセシビリティのために`<body>`内の最初の要素としてレンダリングされる、メインページコンテンツへのリンクのコンポーネント。デフォルトの実装では、ユーザーがキーボードでタブを押してフォーカスするまで非表示となります。 + +--- + +### レイアウト + +以下のコンポーネントは、Starlightのコンポーネントのレイアウトと、異なるブレークポイント間のビューの管理を担当します。これらをオーバーライドすると著しく複雑になるため、可能な限り、より低レベルのコンポーネントをオーバーライドすることをおすすめします。 + +#### `PageFrame` + +**デフォルトコンポーネント:** [`PageFrame.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageFrame.astro) +**名前付きスロット:** `header`, `sidebar` + +ページコンテンツの大部分をラップするレイアウトコンポーネント。デフォルトの実装では、ヘッダー・サイドバー・メインのレイアウトをセットし、`header`と`sidebar`の名前付きスロットと、メインコンテンツのデフォルトスロットを含みます。また、小さな(モバイル)ビューポートでのサイドバーナビゲーションの切り替えをサポートするために、[`<MobileMenuToggle />`](#mobilemenutoggle)をレンダリングします。 + +#### `MobileMenuToggle` + +**デフォルトコンポーネント:** [`MobileMenuToggle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuToggle.astro) + +小さな(モバイル)ビューポートでのサイドバーナビゲーションの切り替えを担当する、[`<PageFrame>`](#pageframe)内にレンダリングされるコンポーネント。 + +#### `TwoColumnContent` + +**デフォルトコンポーネント:** [`TwoColumnContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TwoColumnContent.astro) +**名前付きスロット:** `right-sidebar` + +メインコンテンツのカラムと右サイドバー(目次)をラップするレイアウトコンポーネント。デフォルトの実装では、1カラムの小さなビューポート向けレイアウトと、2カラムの大きなビューポート向けレイアウトの切り替えをおこないます。 + +--- + +### ヘッダー + +以下のコンポーネントは、Starlightのトップナビゲーションバーをレンダリングします。 + +#### `Header` + +**デフォルトコンポーネント:** [`Header.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Header.astro) + +すべてのページの上部に表示されるヘッダーコンポーネント。デフォルトの実装では、[`<SiteTitle />`](#sitetitle)、[`<Search />`](#search)、[`<SocialIcons />`](#socialicons)、[`<ThemeSelect />`](#themeselect)、[`<LanguageSelect />`](#languageselect)を表示します。 + +#### `SiteTitle` + +**デフォルトコンポーネント:** [`SiteTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SiteTitle.astro) + +サイトタイトルをレンダリングするためにサイトヘッダーの先頭にレンダリングされるコンポーネント。デフォルトの実装では、Starlightの設定で定義されたロゴをレンダリングするためのロジックが含まれています。 + +#### `Search` + +**デフォルトコンポーネント:** [`Search.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Search.astro) + +Starlightの検索UIをレンダリングするために使用されるコンポーネント。デフォルトの実装では、ヘッダー内のボタンと、クリックされたときに検索モーダルを表示し、[PagefindのUI](https://pagefind.app/)をロードするためのコードが含まれています。 + +[`pagefind`](/ja/reference/configuration/#pagefind)が無効になっている場合、デフォルトの検索コンポーネントはレンダリングされません。ただし、`Search`をオーバーライドすると、`pagefind`設定オプションが`false`であっても常にカスタムコンポーネントがレンダリングされます。これにより、Pagefindを無効にしたときに、代替となる検索プロバイダーのUIを追加できます。 + +#### `SocialIcons` + +**デフォルトコンポーネント:** [`SocialIcons.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SocialIcons.astro) + +ソーシャルアイコンへのリンクを含む、サイトヘッダーにレンダリングされるコンポーネント。デフォルトの実装では、Starlightの設定の[`social`](/ja/reference/configuration/#social)オプションを使用して、アイコンとリンクをレンダリングします。 + +#### `ThemeSelect` + +**デフォルトコンポーネント:** [`ThemeSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeSelect.astro) + +ユーザーが好みのカラースキームを選択できるようにするための、サイトヘッダーにレンダリングされるコンポーネント。 + +#### `LanguageSelect` + +**デフォルトコンポーネント:** [`LanguageSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LanguageSelect.astro) + +ユーザーが別の言語に切り替えられるようにするための、サイトヘッダーにレンダリングされるコンポーネント。 + +--- + +### グローバルサイドバー + +Starlightのグローバルサイドバーには、メインのサイトナビゲーションが含まれます。小さなビューポートでは、これはドロップダウンメニューの背後に隠されます。 + +#### `Sidebar` + +**デフォルトコンポーネント:** [`Sidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Sidebar.astro) + +グローバルナビゲーションを含んだ、ページコンテンツの前にレンダリングされるコンポーネント。デフォルトの実装では、十分に広いビューポートではサイドバーとして、小さな(モバイル)ビューポートではドロップダウンメニューの内側に表示されます。また、モバイルメニュー内に追加のアイテムを表示するために、[`<MobileMenuFooter />`](#mobilemenufooter)をレンダリングします。 + +#### `MobileMenuFooter` + +**デフォルトコンポーネント:** [`MobileMenuFooter.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuFooter.astro) + +モバイルドロップダウンメニューの下部にレンダリングされるコンポーネント。デフォルトの実装では、[`<ThemeSelect />`](#themeselect)と[`<LanguageSelect />`](#languageselect)をレンダリングします。 + +--- + +### ページサイドバー + +Starlightのページサイドバーは、現在のページの見出しを列挙する目次の表示を担当しています。小さなビューポートでは、これは固定されたドロップダウンメニューへと折りたたまれます。 + +#### `PageSidebar` + +**デフォルトコンポーネント:** [`PageSidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageSidebar.astro) + +目次を表示するために、メインページのコンテンツの前にレンダリングされるコンポーネント。デフォルトの実装では、[`<TableOfContents />`](#tableofcontents)と[`<MobileTableOfContents />`](#mobiletableofcontents)をレンダリングします。 + +#### `TableOfContents` + +**デフォルトコンポーネント:** [`TableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TableOfContents.astro) + +現在のページの目次を、大きめのビューポートにおいてレンダリングするコンポーネント。 + +#### `MobileTableOfContents` + +**デフォルトコンポーネント:** [`MobileTableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileTableOfContents.astro) + +現在のページの目次を、小さな(モバイル)ビューポートにおいてレンダリングするコンポーネント。 + +--- + +### コンテンツ + +以下のコンポーネントは、ページコンテンツのメインカラムにレンダリングされます。 + +#### `Banner` + +**デフォルトコンポーネント:** [`Banner.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Banner.astro) + +各ページの上部にレンダリングされるバナーコンポーネント。デフォルトの実装では、ページの[`banner`](/ja/reference/frontmatter/#banner)フロントマターの値を使用して、レンダリングするかどうかを決定します。 + +#### `ContentPanel` + +**デフォルトコンポーネント:** [`ContentPanel.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ContentPanel.astro) + +メインコンテンツカラムのセクションをラップするために使用されるレイアウトコンポーネント。 + +#### `PageTitle` + +**デフォルトコンポーネント:** [`PageTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageTitle.astro) + +現在のページの`<h1>`要素を含むコンポーネント。 + +デフォルトの実装と同様に、`<h1>`要素に`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) + +現在の言語の翻訳が利用できないページにおいて、ユーザーに表示される通知。多言語サイトでのみ使用されます。 + +#### `Hero` + +**デフォルトコンポーネント:** [`Hero.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Hero.astro) + +フロントマターで[`hero`](/ja/reference/frontmatter/#hero)が設定されている場合に、ページの上部にレンダリングされるコンポーネント。デフォルトの実装では、大きなタイトル、タグライン、コールトゥアクション(call-to-action)リンク、オプションの画像を表示します。 + +#### `MarkdownContent` + +**デフォルトコンポーネント:** [`MarkdownContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MarkdownContent.astro) + +各ページのメインコンテンツの周囲にレンダリングされるコンポーネント。デフォルトの実装では、Markdownコンテンツに適用する基本的なスタイルをセットします。 + +Markdownコンテンツのスタイルは`@astrojs/starlight/style/markdown.css`にも公開されており、`.sl-markdown-content`CSSクラスにスコープされています。 + +--- + +### フッター + +以下のコンポーネントは、ページコンテンツのメインカラムの下部にレンダリングされます。 + +#### `Footer` + +**デフォルトコンポーネント:** [`Footer.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Footer.astro) + +各ページの下部に表示されるフッターコンポーネント。デフォルトの実装では、[`<LastUpdated />`](#lastupdated)、[`<Pagination />`](#pagination)、[`<EditLink />`](#editlink)を表示します。 + +#### `LastUpdated` + +**デフォルトコンポーネント:** [`LastUpdated.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LastUpdated.astro) + +最終更新日を表示するために、ページフッターにレンダリングされるコンポーネント。 + +#### `EditLink` + +**デフォルトコンポーネント:** [`EditLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/EditLink.astro) + +ページを編集できる場所へのリンクを表示するために、ページフッターにレンダリングされるコンポーネント。 + +#### `Pagination` + +**デフォルトコンポーネント:** [`Pagination.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Pagination.astro) + +前のページと次のページとの間にナビゲーション用矢印を表示するために、ページフッターにレンダリングされるコンポーネント。 diff --git a/docs/src/content/docs/ja/reference/plugins.md b/docs/src/content/docs/ja/reference/plugins.md new file mode 100644 index 00000000000..539437203f6 --- /dev/null +++ b/docs/src/content/docs/ja/reference/plugins.md @@ -0,0 +1,356 @@ +--- +title: プラグイン +description: StarlightのプラグインAPIの概要。 +tableOfContents: + maxHeadingLevel: 4 +--- + +Starlightのプラグインにより、Starlightの設定、UI、および動作をカスタマイズできます。このリファレンスページでは、プラグインがアクセス可能なAPIについて説明します。 + +Starlightのプラグインを使用する方法について、詳しくは[設定方法のリファレンス](/ja/reference/configuration/#plugins)を参照してください。また、利用可能なプラグインの一覧については、[プラグインショーケース](/ja/resources/plugins/#プラグイン)を確認してください。 + +## API早見表 + +Starlightのプラグインは次の構造をもちます。各プロパティとフックパラメータの詳細については、以下を参照してください。 + +<!-- prettier-ignore-start --> +```ts +interface StarlightPlugin { + name: string; + hooks: { + 'i18n:setup'?: (options: { + injectTranslations: ( + translations: Record<string, Record<string, string>> + ) => void; + }) => void | Promise<void>; + 'config:setup': (options: { + config: StarlightUserConfig; + updateConfig: (newConfig: StarlightUserConfig) => void; + addIntegration: (integration: AstroIntegration) => void; + addRouteMiddleware: (config: { entrypoint: string; order?: 'pre' | 'post' | 'default' }) => void; + astroConfig: AstroConfig; + command: 'dev' | 'build' | 'preview'; + isRestart: boolean; + logger: AstroIntegrationLogger; + useTranslations: (lang: string) => I18nT; + absolutePathToLang: (path: string) => string; + }) => void | Promise<void>; + }; +} +``` +<!-- prettier-ignore-end --> + +## `name` + +**type:** `string` + +プラグインには、自身を説明する一意の名前を指定する必要があります。名前は、このプラグインに関連する[ログメッセージ](#logger)を出力するときに使用されます。また、あるプラグインの存在を検出するために使用される場合もあります。 + +## `hooks` + +フックは、Starlightが特定のタイミングでプラグインコードを実行するために呼び出す関数です。 + +フックの引数の型を取得するには、`HookParameters`ユーティリティ型を使用し、フック名を渡します。以下の例では、`options`パラメータは`config:setup`フックに渡される引数に一致するように型付けされています。 + +```ts +import type { HookParameters } from '@astrojs/starlight/types'; + +function configSetup(options: HookParameters['config:setup']) { + options.useTranslations('en'); +} +``` + +### `i18n:setup` + +Starlightが初期化されるときに呼び出される、プラグインの国際化向けのセットアップ関数です。`i18n:setup`フックは、プラグインがさまざまなロケールをサポートできるように翻訳文字列を登録するために使用できます。これらの翻訳は、`config:setup`フックの[`useTranslations()`](#usetranslations)や、UIコンポーネントの[`Astro.locals.t()`](/ja/guides/i18n/#ui翻訳を使用する)を通じて利用できます。 + +`i18n:setup`フックは、以下のオプションとともに呼び出されます。 + +#### `injectTranslations` + +**type:** `(translations: Record<string, Record<string, string>>) => void` + +Starlightの[ローカライズAPI](/ja/guides/i18n/#ui翻訳を使用する)で使用される翻訳文字列を追加または更新するためのコールバック関数です。 + +以下の例では、プラグインが`en`と`fr`ロケールの`myPlugin.doThing`というカスタムUI文字列の翻訳を登録しています。 + +```ts {6-13} /(injectTranslations)[^(]/ +// plugin.ts +export default { + name: 'plugin-with-translations', + hooks: { + 'i18n:setup'({ injectTranslations }) { + injectTranslations({ + en: { + 'myPlugin.doThing': 'Do the thing', + }, + fr: { + 'myPlugin.doThing': 'Faire le truc', + }, + }); + }, + }, +}; +``` + +登録した翻訳をプラグインUIで使用するには、[“UI翻訳の使用“ガイド](/ja/guides/i18n/#ui翻訳を使用する)に従ってください。プラグインの[`config:setup`](#configsetup)フックのコンテキストでUI文字列を使用する必要がある場合は、[`useTranslations()`](#usetranslations)コールバックを使用できます。 + +プラグインが登録する翻訳文字列の型は、ユーザーのプロジェクトで自動的に生成されますが、プラグインのコードベースで作業中はまだ利用できません。プラグインのコンテキストで`locals.t`オブジェクトを型付けするには、TypeScript宣言ファイルで以下のグローバル名前空間を宣言します。 + +```ts +// env.d.ts +declare namespace App { + type StarlightLocals = import('@astrojs/starlight').StarlightLocals; + // プラグインのコンテキストで`locals.t`オブジェクトを定義します。 + interface Locals extends StarlightLocals {} +} + +declare namespace StarlightApp { + // `I18n`インターフェースにプラグインの追加の翻訳を定義します。 + interface I18n { + 'myPlugin.doThing': string; + } +} +``` + +翻訳を含むオブジェクトがあるソースファイルから、`StarlightApp.I18n`インターフェースの型を推論することもできます。 + +たとえば、以下のソースファイルがあるとします。 + +```ts title="ui-strings.ts" +export const UIStrings = { + en: { 'myPlugin.doThing': 'Do the thing' }, + fr: { 'myPlugin.doThing': 'Faire le truc' }, +}; +``` + +以下の宣言は、ソースファイルの英語キーから型を推論します。 + +```ts title="env.d.ts" +declare namespace StarlightApp { + type UIStrings = typeof import('./ui-strings').UIStrings.en; + interface I18n extends UIStrings {} +} +``` + +### `config:setup` + +プラグインの設定セットアップ関数は、Starlightが初期化される際に呼び出されます([`astro:config:setup`](https://docs.astro.build/ja/reference/integrations-reference/#astroconfigsetup)インテグレーションフック内)。`config:setup`フックは、Starlightの設定を更新したり、Astroのインテグレーションを追加したりするために使用できます。 + +このフックは、以下のオプションとともに呼び出されます。 + +#### `config` + +**type:** `StarlightUserConfig` + +ユーザーが提供した[Starlightの設定](/ja/reference/configuration/)の、読み取り専用の複製です。この設定は、現在のプラグインより前に置かれた他のプラグインによって更新されている可能性があります。 + +#### `updateConfig` + +**type:** `(newConfig: StarlightUserConfig) => void` + +ユーザーが提供した[Starlightの設定](/ja/reference/configuration/)を更新するためのコールバック関数です。上書きしたいルートレベルの設定キーを指定します。ネストされた設定値を更新するには、ネストされたオブジェクトの全体を指定する必要があります。 + +既存の設定オプションをオーバーライドせず拡張するには、既存の値を新しい値へと展開します。以下の例では、`config.social`を新しい`social`配列に展開し、既存の設定に新しい[`social`](/ja/reference/configuration/#social)メディアアカウントを追加しています。 + +```ts {6-15} +// plugin.ts +export default { + name: 'add-twitter-plugin', + hooks: { + 'config:setup'({ config, updateConfig }) { + updateConfig({ + social: [ + ...config.social, + { + icon: 'twitter', + label: 'Twitter', + href: 'https://twitter.com/astrodotbuild', + }, + ], + }); + }, + }, +}; +``` + +#### `addIntegration` + +**type:** `(integration: AstroIntegration) => void` + +プラグインが必要とする[Astroのインテグレーション](https://docs.astro.build/ja/reference/integrations-reference/)を追加するためのコールバック関数です。 + +以下の例では、プラグインはまず[AstroのReactインテグレーション](https://docs.astro.build/ja/guides/integrations-guide/react/)が設定されているかどうかを確認し、設定されていない場合は`addIntegration()`を使用して追加します。 + +```ts {14} "addIntegration," +// plugin.ts +import react from '@astrojs/react'; + +export default { + name: 'plugin-using-react', + hooks: { + 'config:setup'({ addIntegration, astroConfig }) { + const isReactLoaded = astroConfig.integrations.find( + ({ name }) => name === '@astrojs/react' + ); + + // Reactインテグレーションがまだ読み込まれていない場合のみ追加します。 + if (!isReactLoaded) { + addIntegration(react()); + } + }, + }, +}; +``` + +#### `addRouteMiddleware` + +**type:** `(config: { entrypoint: string; order?: 'pre' | 'post' | 'default' }) => void` + +サイトに[ルートミドルウェアハンドラー](/ja/guides/route-data/)を追加するためのコールバック関数です。 + +`entrypoint`プロパティは、`onRequest`ハンドラーをエクスポートするプラグインのミドルウェアファイルのモジュール指定子である必要があります。 + +以下の例では、`@example/starlight-plugin`として公開されたプラグインが、npmモジュール指定子を使用してルートミドルウェアを追加しています。 + +```js {6-9} +// plugin.ts +export default { + name: '@example/starlight-plugin', + hooks: { + 'config:setup'({ addRouteMiddleware }) { + addRouteMiddleware({ + entrypoint: '@example/starlight-plugin/route-middleware', + }); + }, + }, +}; +``` + +##### 実行順序の制御 + +デフォルトでは、プラグインミドルウェアはプラグインが追加された順序で実行されます。 + +ミドルウェアの実行タイミングをより細かく制御する必要がある場合は、オプションの`order`プロパティを使用します。 +ユーザーのミドルウェアより前に実行するには`order: "pre"`を設定します。他のすべてのミドルウェアの後に実行するには`order: "post"`を設定します。 + +同じ`order`値を持つミドルウェアを2つのプラグインが追加した場合、最初に追加されたプラグインが先に実行されます。 + +#### `astroConfig` + +**type:** `AstroConfig` + +ユーザーが提供した[Astroの設定](https://docs.astro.build/ja/reference/configuration-reference/)の、読み取り専用の複製です。 + +#### `command` + +**type:** `'dev' | 'build' | 'preview'` + +Starlightを実行するために使用されたコマンドです。 + +- `dev` - プロジェクトは`astro dev`により実行されています +- `build` - プロジェクトは`astro build`により実行されています +- `preview` - プロジェクトは`astro preview`により実行されています + +#### `isRestart` + +**type:** `boolean` + +開発サーバーが起動したときは`false`、リロードがトリガーされたときは`true`となります。再起動が発生するよくある理由としては、開発サーバーが実行されている間にユーザーが`astro.config.mjs`を編集した場合などがあります。 + +#### `logger` + +**type:** `AstroIntegrationLogger` + +ログを書き込むために使用する[Astroインテグレーションロガー](https://docs.astro.build/ja/reference/integrations-reference/#astrointegrationlogger)のインスタンスです。すべてのログメッセージは、プラグイン名が接頭辞として付加されます。 + +```ts {6} +// plugin.ts +export default { + name: 'long-process-plugin', + hooks: { + 'config:setup'({ logger }) { + logger.info('時間が掛かる処理を開始します…'); + // 何らかの時間が掛かる処理… + }, + }, +}; +``` + +上記の例では、指定した`info`レベルのメッセージを含むログが出力されます。 + +```shell +[long-process-plugin] 時間が掛かる処理を開始します… +``` + +#### `useTranslations` + +**type:** `(lang: string) => I18nT` + +BCP-47言語タグを指定して`useTranslations()`を呼び出すと、その言語のUI文字列にアクセスするためのユーティリティ関数が生成されます。`useTranslations()`は、Astroコンポーネントで利用可能な`Astro.locals.t()`APIと同等のものを返します。利用可能なAPIの詳細については、[“UI翻訳の使用“](/ja/guides/i18n/#ui翻訳を使用する)ガイドを参照してください。 + +```ts {6} +// plugin.ts +export default { + name: 'plugin-use-translations', + hooks: { + 'config:setup'({ useTranslations, logger }) { + const t = useTranslations('zh-CN'); + logger.info(t('builtWithStarlight.label')); + }, + }, +}; +``` + +上記の例では、中国語簡体字の組み込みUI文字列を含むメッセージがログに出力されます。 + +```shell +[plugin-use-translations] 基于 Starlight 构建 +``` + +#### `absolutePathToLang` + +**type:** `(path: string) => string` + +絶対ファイルパスを指定して`absolutePathToLang()`を呼び出すと、そのファイルの言語を取得できます。 + +これは、MarkdownやMDXファイルを処理する[remarkやrehypeプラグイン](https://docs.astro.build/ja/guides/markdown-content/#markdown-plugins)を追加する際に特に便利です。これらのプラグインが使用する[仮想ファイル形式](https://github.com/vfile/vfile)には、処理中のファイルの[絶対パス](https://github.com/vfile/vfile#filepath)が含まれており、`absolutePathToLang()`と組み合わせてファイルの言語を判定できます。返された言語は、[`useTranslations()`](#usetranslations)ヘルパーと組み合わせて、その言語のUI文字列を取得するために使用できます。 + +たとえば、以下のStarlight設定があるとします。 + +```js +starlight({ + title: 'My Docs', + defaultLocale: 'en', + locales: { + // 英語ドキュメント: `src/content/docs/en/` + en: { label: 'English' }, + // フランス語ドキュメント: `src/content/docs/fr/` + fr: { label: 'Français', lang: 'fr' }, + }, +}); +``` + +プラグインは絶対パスを使用してファイルの言語を判定できます。 + +```ts {6-8} /fr/ +// plugin.ts +export default { + name: 'plugin-use-translations', + hooks: { + 'config:setup'({ absolutePathToLang, useTranslations, logger }) { + const lang = absolutePathToLang( + '/absolute/path/to/project/src/content/docs/fr/index.mdx' + ); + const t = useTranslations(lang); + logger.info(t('aside.tip')); + }, + }, +}; +``` + +上記の例では、フランス語の組み込みUI文字列を含むメッセージがログに出力されます。 + +```shell +[plugin-use-translations] Astuce +``` diff --git a/docs/src/content/docs/ja/reference/route-data.mdx b/docs/src/content/docs/ja/reference/route-data.mdx new file mode 100644 index 00000000000..0da5fb69f19 --- /dev/null +++ b/docs/src/content/docs/ja/reference/route-data.mdx @@ -0,0 +1,196 @@ +--- +title: ルートデータ +description: Starlightのルートデータオブジェクトに関する完全なリファレンスドキュメントです。 +--- + +Starlightのルートデータオブジェクトには、現在のページに関する情報が含まれています。Starlightのデータモデルがどのように機能するかについては、[「ルートデータ」ガイド](/ja/guides/route-data/) を参照してください。 + +Astroコンポーネント内では、`Astro.locals.starlightRoute`からルートデータにアクセスできます。 + +```astro {4} +--- +// src/components/Custom.astro + +const { hasSidebar } = Astro.locals.starlightRoute; +--- +``` + +[ルートミドルウェア](/ja/guides/route-data/#ルートデータのカスタマイズ)内では、ミドルウェア関数に渡されるcontextオブジェクトからルートデータにアクセスします。 + +```ts {5} +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + const { hasSidebar } = context.locals.starlightRoute; +}); +``` + +## `starlightRoute` + +`starlightRoute`オブジェクトは、以下のプロパティをもちます。 + +### `dir` + +**型:** `'ltr' | 'rtl'` + +ページの書字方向。 + +### `lang` + +**型:** `string` + +このページのロケールのBCP-47言語タグ。たとえば`en`、`zh-CN`、`pt-BR`など。 + +### `locale` + +**型:** `string | undefined` + +言語が配信されるベースパス。ルートロケールスラグの場合は`undefined`となります。 + +### `siteTitle` + +**型:** `string` + +このページのロケールのサイトタイトル。 + +### `siteTitleHref` + +**型:** `string` + +サイトタイトルの`href`属性の値。たとえば`/`など、ホームページへのリンクとなります。多言語サイトの場合、たとえば`/en/`や`/zh-cn/`など、現在のロケールが含まれます。 + +### `slug` + +**型:** `string` + +コンテンツファイル名から生成されたページのスラグ。 + +このプロパティは非推奨であり、Starlightの将来のバージョンで削除される予定です。[Starlightの`docsLoader`](/ja/manual-setup/#コンテンツコレクションの設定)を使用して新しいコンテンツレイヤーAPIに移行し、代わりに[`id`](#id)プロパティを使用してください。 + +### `id` + +**型:** `string` + +このページのスラグ。[`legacy.collections`](https://docs.astro.build/ja/reference/legacy-flags/#collections)フラグを使用している場合は、コンテンツファイル名に基づくページの一意のIDとなります。 + +### `isFallback` + +**型:** `boolean | undefined` + +このページが現在の言語で未翻訳であり、デフォルトロケールのフォールバックコンテンツを使用している場合は`true`となります。多言語サイトでのみ使用されます。 + +### `entryMeta` + +**型:** `{ dir: 'ltr' | 'rtl'; lang: string }` + +ページコンテンツのロケールメタデータ。ページがフォールバックコンテンツを使用している場合、トップレベルのロケール値とは異なる場合があります。 + +### `entry` + +現在のページのAstroコンテンツコレクションのエントリー。`entry.data`には、現在のページのフロントマターの値が含まれます。 + +```ts +entry: { + data: { + title: string; + description: string | undefined; + // その他の値 + } +} +``` + +このオブジェクトの構造については、[Astroのコレクションエントリー型](https://docs.astro.build/ja/reference/modules/astro-content/#collectionentry)リファレンスを参照してください。 + +### `sidebar` + +**型:** `SidebarEntry[]` + +ページのサイトナビゲーション用サイドバーのエントリー。 + +### `hasSidebar` + +**型:** `boolean` + +ページにサイドバーを表示するかどうか。 + +### `pagination` + +**型:** `{ prev?: Link; next?: Link }` + +ページネーションの設定が有効な場合にサイドバーに表示される、前のページと次のページへのリンク。 + +### `toc` + +**型:** `{ minHeadingLevel: number; maxHeadingLevel: number; items: TocItem[] } | undefined` + +目次の設定が有効な場合、このページの目次。 + +### `headings` + +**型:** `{ depth: number; slug: string; text: string }[]` + +現在のページから抽出されたすべてのMarkdown見出しの配列。Starlightの設定オプションをもとに目次コンポーネントを作成したい場合は、[`toc`](#toc)を使用してください。 + +### `lastUpdated` + +**型:** `Date | undefined` + +最終更新日の設定が有効な場合、このページが最後に更新された日時を表わすJavaScriptの`Date`オブジェクト。 + +### `editUrl` + +**型:** `URL | undefined` + +ページの編集設定が有効な場合、このページを編集可能なアドレスの`URL`オブジェクト。 + +### `head` + +**型:** [`HeadConfig[]`](/ja/reference/configuration/#headconfig) + +現在のページの`<head>`に含めるすべてのタグの配列。`<title>`や`<meta charset="utf-8">`などの重要なタグが含まれます。 + +## ユーティリティ + +### `defineRouteMiddleware()` + +ルートミドルウェアモジュールに型を付けるには、`defineRouteMiddleware()`ユーティリティを使用します。 + +```ts "defineRouteMiddleware" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + // ... +}); +``` + +### `StarlightRouteData`型 + +Starlightのルートデータを扱うコードを書く場合は、`StarlightRouteData`型をインポートして`Astro.locals.starlightRoute`の型定義に合わせることができます。 + +以下の例では、`usePageTitleInTOC()`関数がルートデータを更新し、目次の最初の項目のラベルとして現在のページのタイトルを使用することで、デフォルトの「概要」ラベルを置き換えます。`StarlightRouteData`型により、ルートデータの変更が正しいかどうかを確認できます。 + +```ts "StarlightRouteData" +// src/route-utils.ts +import type { StarlightRouteData } from '@astrojs/starlight/route-data'; + +export function usePageTitleInTOC(starlightRoute: StarlightRouteData) { + const overviewLink = starlightRoute.toc?.items[0]; + if (overviewLink) { + overviewLink.text = starlightRoute.entry.data.title; + } +} +``` + +この関数は次のようにルートミドルウェアから呼び出すことができます。 + +```ts {3,6} +// src/route-middleware.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; +import { usePageTitleInTOC } from './route-utils'; + +export const onRequest = defineRouteMiddleware((context) => { + usePageTitleInTOC(context.locals.starlightRoute); +}); +``` diff --git a/docs/src/content/docs/ja/resources/community-content.mdx b/docs/src/content/docs/ja/resources/community-content.mdx new file mode 100644 index 00000000000..9d73d7869a8 --- /dev/null +++ b/docs/src/content/docs/ja/resources/community-content.mdx @@ -0,0 +1,244 @@ +--- +title: コミュニティコンテンツ +description: コミュニティ製のガイドや記事、動画をチェックして、Starlightの学習や開発に役立てましょう! +--- + +:::tip[自分のものを追加しよう!] +Starlightに関するコンテンツを作成しましたか?このページにリンクを追加するPRを作成しましょう! +::: + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +## 記事とレビュー + +以下は、Starlightやその開発体験について学ぶための記事のコレクションです。 + +<CardGrid> + <LinkCard + href="https://devm.io/open-source/starlight-astro" + title="Starlightによる静的サイト生成" + description="「コンポーネントの設計において、大きすぎるアイデアも小さすぎるアイデアもありません」- StarlightリードのChris Swithinbankとのインタビュー" + /> + <LinkCard + href="https://frontendatscale.com/blog/hybrid-frontend-architecture/" + title="AstroとStarlightによるハイブリッドフロントエンドアーキテクチャ" + description="Maxi FerreiraとBen Holmesが、Starlight、TinaCMS、認証付きのインタラクティブAPIプレイグラウンドを使用してドキュメントサイトを作成します。" + /> + <LinkCard + href="https://www.olets.dev/posts/comparing-docs-site-builders-vuepress-vs-starlight/" + title="ドキュメントサイトビルダーの比較: VuePressとStarlight" + description="両フレームワークはどのように比較されるのでしょうか?" + /> + <LinkCard + href="https://astro.build/case-studies/wp-engine/" + title="ケーススタディ: 開発コストの大幅削減" + description="WP EngineがAstroのStarlightを活用して開発コストを50%以上削減した方法。" + /> + <LinkCard + href="https://maciekpalmowski.dev/blog/building-a-documentation-site-using-astro-starlight/" + title="Astro Starlightを使ったドキュメントサイトの構築" + description="Maciek Palmowskiが、PatchstackのドキュメントをどのようにStarlightに移行したかを紹介しています。" + /> + <LinkCard + href="https://blog.cloudflare.com/open-source-all-the-way-down-upgrading-our-developer-documentation/" + title="すべてをオープンソースで" + description="Cloudflareが開発者向けドキュメントをStarlightでアップグレードした方法。" + /> + <LinkCard + href="https://starlight-changelog.netlify.app/" + title="Starlight Changelog" + description="@astrojs/starlightパッケージのすべてのリリースを1つの見やすいページで確認できます。" + /> + <LinkCard + href="https://hideoo.dev/notes/contributing-to-starlight" + title="Starlightへのコントリビューション" + description="Starlightのようなオープンソースプロジェクトへのコントリビューションについての個人的な経験とアドバイス。" + /> +</CardGrid> + +## レシピとガイド + +レシピは通常、特定のタスクを読者に具体的に案内する、焦点を絞った短いハウツーガイドです。ステップバイステップの手順に従って、Starlightプロジェクトに新しい機能や動作を追加するための素晴らしい方法といえます!他のガイドでは、画像の使用やMDXの扱い方など、コンテンツの領域に関連する概念も説明しています。 + +Starlightユーザーによってメンテナンスされている、コミュニティ製のコンテンツをチェックしてみましょう。 + +<CardGrid> + <LinkCard + href="https://www.webpro.nl/scraps/versioned-docs-with-starlight-and-vercel" + title="StarlightとVercelでバージョン管理されたドキュメントを作成する" + description="プロジェクトの各メジャーバージョンごとにドキュメントのバージョンを分けて実装する方法についてのガイド。" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-heading-links" + title="Starlightの見出しにリンクを追加する" + description="rehypeプラグインを使用して、ドキュメントの特定のセクションへのリンクを共有する方法についてのガイド。" + /> + <LinkCard + href="https://blog.otterlord.dev/posts/starlight-sponsors/" + title="Starlightサイトにスポンサーを追加する" + description="ドキュメントのサイドバーにカスタムスポンサーコンポーネントを実装する方法についてのガイド。" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images" + title="Open Graph画像をStarlightに追加する" + description="ソーシャル画像とそれに対応するメタタグを生成する方法についてのガイド。" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-third-party-icon-sets" + title="サードパーティのアイコンセットをStarlightで使用する" + description="unplugin-iconsを使用して、Starlightで利用可能なアイコンの選択肢を拡張する方法についてのガイド。" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-html-head" + title="StarlightページのHTMLヘッドを編集する" + description="ウェブアナリティクス、フォント、スクリプトなどの共通のヘッドコンテンツを追加する方法について学びます。" + /> + <LinkCard + href="https://dev.to/mrrobot/publishing-documentation-with-astro-starlight-691" + title="AstroのStarlightでドキュメントを公開する" + description="Starlightドキュメントの始め方。" + /> + <LinkCard + href="https://events-3bg.pages.dev/jotter/starlight/" + title="ビュートランジションを有効にする" + description="Starlightドキュメントサイトにビュートランジション、クライアントサイドルーティング、SPAライクなナビゲーションのサポートを追加します。" + /> + <LinkCard + href="https://jamcomments.com/posts/structured-data-with-starlight" + title="Starlightページに構造化データを追加する" + description="ドキュメントページに動的なJSON-LD構造化データを作成する方法を紹介しています。" + /> + <LinkCard + href="https://starlight-examples.netlify.app/" + title="Starlightの実例集" + description="Starlightドキュメントサイトでの実践的な方法を紹介するStackBlitz上のコレクションです。" + /> + <LinkCard + href="https://hideoo.dev/notebooks/starlight-plugins-by-example" + title="実例で学ぶStarlightプラグイン" + description="Starlightプラグインと、その作成における一般的なパターンに関するノートと実例のコレクションです。" + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-progress-indicator/" + title="閲覧の進捗インジケーターを追加する" + description="Starlightサイトに水平方向の閲覧進捗バーを追加する方法を紹介しています。" + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-sidebar-whitespace/" + title="Starlightサイドバーにカスタムスタイルを適用する" + description="少しのCSSでStarlightサイドバーのフォントや色などを調整する方法を紹介しています。" + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-dropdown-and-list-together/" + title="モバイルではドロップダウン、デスクトップではリスト表示" + description="2つのプラグインを組み合わせて、デスクトップとモバイルの両方で最適な表示を実現します。" + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-autogenerate-whole-sidebar/" + title="ミドルウェアでStarlightサイドバーを処理する" + description="Nuxt Contentの規約に着想を得た、ルートミドルウェアによるサイドバーの順序やグループラベルの制御方法を紹介しています。" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-social-links" + title="カスタムアイコン付きのソーシャルリンクをStarlightに追加する" + description="Starlightサイトのヘッダーでソーシャルリンクにカスタムアイコンを使用する方法を紹介しています。" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-paste-images-with-visual-studio-code" + title="Visual Studio CodeでStarlightページに画像を貼り付ける" + description="Visual Studio Codeを使ってドキュメントページに画像を貼り付けることで、Starlightのドキュメント作成ワークフローを改善します。" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-add-diagrams-using-d2" + title="D2を使ってStarlightドキュメントにダイアグラムを追加する" + description="D2を使用してStarlightドキュメントにダイアグラムを追加する方法を紹介しています。" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images-cloudinary-astro-sdk" + title="Cloudinary Astro SDKを使ってStarlightのOpen Graph画像を生成する" + description="Cloudinary Astro SDKを使用して、StarlightドキュメントサイトのOpen Graph画像を生成する方法を紹介しています。" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-list-recent-github-releases" + title="Astro Content Layer APIを使ってStarlightにGitHubの最新リリースを一覧表示する" + description="Astro Content Layer APIを使用して、StarlightプロジェクトにGitHubの最新リリースを一覧表示する方法を紹介しています。" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-sitewide-banner" + title="Starlightにサイト全体で適用されるバナーを追加する" + description="Starlightに組み込まれたページごとのバナー機能を活用して、サイト全体で適用されるバナーを作成する方法を紹介しています。" + /> +</CardGrid> + +## 動画コンテンツ + +ライブストリームや教育コンテンツなど、Starlightに関する動画やチャンネルをチェックしてみましょう。 + +import YouTubeGrid from '~/components/youtube-grid.astro'; + +### 公式動画 + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=5u0Ds7wzUeI', + title: 'AstroによるStarlight', + description: '公式のStarlightローンチ動画をご覧ください。', + }, + { + href: 'https://www.youtube.com/watch?v=j8K-ESJF814', + title: 'Starlight 1周年!', + description: + 'Astroのコミュニティ製ドキュメントテーマについてSarahが語ります。', + }, + ]} +/> + +### コミュニティ製の動画とストリーム + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/shorts/zjOWezSzd18', + title: '🌟 1分で起動チャレンジ', + description: + 'Benが1分以内に新しいStarlightサイトを立ち上げる様子を見てみましょう!', + }, + { + href: 'https://www.youtube.com/watch?v=sF6UcV3moZg', + title: 'StarlightとAstroでドキュメントを作成する', + description: + 'ChrisとAlexが、Code with CodingCat.devでStarlightについて語ります。', + }, + { + href: 'https://www.youtube.com/watch?v=sWkkHbwDeQc', + title: 'Astro Starlight', + description: '1分でStarlightを紹介します。', + }, + { + href: 'https://www.youtube.com/watch?v=-Ki-1E5gNCk', + title: + 'AstroによるStarlightドキュメントテンプレート(アプリのドキュメントを作る!)', + description: '5分で新しいStarlightサイトを立ち上げます。', + }, + { + href: 'https://www.youtube.com/watch?v=12o7WxjAxjM', + title: + 'プロキシを使ってNext.jsプロジェクトにStarlightドキュメントを組み込む', + description: + 'Next.jsウェブサイト内にStarlightをサブディレクトリプロジェクトとしてセットアップします。', + }, + { + href: 'https://www.youtube.com/watch?v=5pq80drDrNs', + title: 'このすごいツールでShadcnのドキュメントを30分で再現してみた', + description: + 'この動画では、Starlightのどこがすごいのか、そしてなぜ次のプロジェクトで試してみる価値があるのかを解説します。', + }, + { + href: 'https://www.youtube.com/watch?v=Q1E4Gkt63ko', + title: 'Chris Swithinbankと学ぶAstro Starlightとemoji-blast', + description: + 'AstroのStarlight生みの親であるChrisが、新しいemoji-blastウェブサイトへのセットアップ方法を一緒に案内してくれます。🌟 🎇', + }, + ]} +/> diff --git a/docs/src/content/docs/ja/resources/plugins.mdx b/docs/src/content/docs/ja/resources/plugins.mdx new file mode 100644 index 00000000000..b36a577a15c --- /dev/null +++ b/docs/src/content/docs/ja/resources/plugins.mdx @@ -0,0 +1,288 @@ +--- +title: プラグインとインテグレーション +description: プラグインやインテグレーションをチェックして、Starlightを拡張しましょう! +sidebar: + order: 1 +--- + +:::tip[自分のものを追加しよう!] +Starlight向けのプラグインやツールを作成しましたか?このページにリンクを追加するPRを作成しましょう! +::: + +## プラグイン + +[プラグイン](/ja/reference/plugins/)により、Starlightの設定やUI、動作をカスタマイズできます。また、プラグインは簡単に共有や再利用ができます。Starlightチームが公式にサポートする公式プラグインと、Starlightユーザーがメンテナンスするコミュニティ製プラグインでサイトを拡張しましょう。 + +### 公式プラグイン + +<CardGrid> + <LinkCard + href="/ja/guides/site-search/#algolia-docsearch" + title="Algolia DocSearch" + description="デフォルトの検索プロバイダーであるPagefindを、Algolia DocSearchに置き換えます。" + /> +</CardGrid> + +### コミュニティ製プラグイン + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-links-validator" + title="starlight-links-validator" + description="Starlightページ内のリンクが壊れていないかをチェックします。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-typedoc" + title="starlight-typedoc" + description="TypeDocにより、TypeScriptコードからStarlightページを生成します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-blog" + title="starlight-blog" + description="ドキュメントサイトにブログを追加します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-openapi" + title="starlight-openapi" + description="OpenAPI/Swaggerの仕様からドキュメントページを作成します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-obsidian" + title="starlight-obsidian" + description="Obsidianの保管庫をStarlightサイトに公開します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-image-zoom" + title="starlight-image-zoom" + description="ドキュメントの画像にズーム機能を追加します。" + /> + <LinkCard + href="https://github.com/lorenzolewis/starlight-utils" + title="starlight-utils" + description="よく使うユーティリティのコレクションでStarlightを拡張します。" + /> + <LinkCard + href="https://github.com/trueberryless/starlight-view-modes" + title="starlight-view-modes" + description="ドキュメントサイトにさまざまな表示モード機能を追加します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-versions" + title="starlight-versions" + description="Starlightのドキュメントページをバージョン管理します。" + /> + <LinkCard + href="https://inox-tools.fryuni.dev/star-warp" + title="star-warp" + description="ドキュメント内の検索結果を高速に移動します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-heading-badges" + title="starlight-heading-badges" + description="MarkdownやMDXの見出しにバッジを追加します。" + /> + <LinkCard + href="https://github.com/Fevol/starlight-site-graph" + title="starlight-site-graph" + description="ページのサイドバーにインタラクティブなサイトグラフを追加します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-sidebar-topics" + title="starlight-sidebar-topics" + description="ドキュメントを、それぞれ独自のサイドバーをもつ複数のセクションに分割します。" + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-cooler-credit" + title="starlight-cooler-credit" + description="目次の下部にStarlightやAstroへのクレジットを表示します。" + /> + <LinkCard + href="https://github.com/dragomano/starlight-giscus" + title="starlight-giscus" + description="ドキュメントサイトにGiscusコメント機能を追加します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-videos" + title="starlight-videos" + description="動画ガイドやコースでドキュメントを充実させます。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-kbd" + title="starlight-kbd" + description="キーボードショートカットを簡単にドキュメント化します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-auto-sidebar" + title="starlight-auto-sidebar" + description="自動生成されたサイドバーグループを調整します。" + /> + <LinkCard + href="https://github.com/delucis/starlight-llms-txt" + title="starlight-llms-txt" + description="llmstxt.orgに基づいて、ドキュメントサイトにllms.txtを追加します。" + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-toc-overview-customizer" + title="starlight-toc-overview-customizer" + description="カスタマイズ可能な概要タイトルでStarlightの目次を調整します。" + /> + <LinkCard + href="https://delucis.github.io/starlight-markdown-blocks/" + title="starlight-markdown-blocks" + description="カスタムブロックタイプでStarlightのMarkdownアサイド構文を拡張します。" + /> + <LinkCard + href="https://github.com/WindMillCode/starlight-fullview-mode" + title="starlight-fullview-mode" + description="サイドバーを折りたたみ、コンテンツを拡大してフルスクリーン表示を実現します。" + /> + <LinkCard + href="https://github.com/frostybee/starlight-scroll-to-top" + title="starlight-scroll-to-top" + description="ドキュメントサイトにページトップへのスクロールボタンを追加します。" + /> + <LinkCard + href="https://github.com/frostybee/starlight-codeblock-fullscreen" + title="starlight-codeblock-fullscreen" + description="ドキュメント内のExpressive Codeブロックにフルスクリーン切り替え機能を追加します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-auto-drafts" + title="starlight-auto-drafts" + description="下書きページのデフォルト動作を調整し、本番モードでは下書きページへのサイドバーリンクを自動的に削除します。" + /> + <LinkCard + href="https://github.com/corsfix/starlight-contextual-menu" + title="starlight-contextual-menu" + description="Starlightドキュメントにコンテキストメニューを追加します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-changelogs" + title="starlight-changelogs" + description="プロジェクトのドキュメントと一緒に変更履歴を表示します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-github-alerts" + title="starlight-github-alerts" + description="GitHubアラートをStarlightのアサイドとしてレンダリングします。" + /> + <LinkCard + href="https://github.com/dlcastillop/starlight-page-actions" + title="starlight-page-actions" + description="ドキュメントにページアクションボタンを追加します。" + /> + <LinkCard + href="https://github.com/typesense/starlight-docsearch-typesense" + title="starlight-docsearch-typesense" + description="公式のAlgolia DocSearchプラグインに代わる、Typesenseを使用した検索プラグインです。" + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-swipe/" + title="starlight-sidebar-swipe" + description="Discord Mobileのように、モバイルデバイスで左サイドバーをスワイプ可能にします。" + /> + <LinkCard + href="https://github.com/Rettend/starlight-plugin-icons" + title="starlight-plugin-icons" + description="Astro Starlightのサイドバー、コードブロック、ファイルツリーにアイコンを追加します。" + /> + <LinkCard + href="https://github.com/dlcastillop/starlight-ui-tweaks" + title="starlight-ui-tweaks" + description="カスタムナビゲーションリンク、広告、マーケティングフッター、よりシンプルなテーマ切り替えでコアUIコンポーネントを拡張します。" + /> + <LinkCard + href="https://frostybee.github.io/starlight-tags/" + title="starlight-tags" + description="コンテンツの整理や検索のために、Starlightドキュメントページにタグを追加します。" + /> +</CardGrid> + +## コミュニティ製ツールとインテグレーション + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +以下のコミュニティ製ツールやインテグレーションにより、Starlightサイトに機能を追加できます。 + +<CardGrid> + <LinkCard + href="https://www.feelback.dev/blog/new-astro-starlight-integration/" + title="FeelBack" + description="ユーザーフィードバックシステムをドキュメントページに追加します。" + /> + <LinkCard + href="https://github.com/val-town/notion-to-astro" + title="notion-to-astro" + description="NotionのエクスポートをAstro Starlightドキュメントに変換します。" + /> + <LinkCard + href="https://github.com/mattjennings/astro-live-code" + title="astro-live-code" + description="MDXコードブロックをインタラクティブなコンポーネントとしてレンダリングします。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-i18n" + title="starlight-i18n" + description="Starlightページの翻訳を支援するVisual Studio Code拡張機能です。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-package-managers" + title="starlight-package-managers" + description="複数のパッケージマネージャーに対応したnpm関連コマンドをすばやく表示します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-showcases" + title="starlight-showcases" + description="ショーケースページを作成するためのStarlightコンポーネントセットです。" + /> + <LinkCard + href="https://github.com/HiDeoo/generator-starlight-plugin" + title="@hideoo/starlight-plugin" + description="Starlightプラグインをすばやく雛形から作成するジェネレーターです。" + /> + <LinkCard + href="https://github.com/Linkerin/starlight-to-pdf" + title="starlight-to-pdf" + description="StarlightサイトをPDFファイルに変換するCLIツールです。" + /> + <LinkCard + href="https://github.com/joesaby/astro-plantuml" + title="astro-plantuml" + description="Markdownコードブロック内のPlantUMLコンテンツをレンダリングします。" + /> + <LinkCard + href="https://github.com/joesaby/astro-mermaid" + title="astro-mermaid" + description="Markdownコードブロック内のMermaidコンテンツをクライアントサイドでレンダリングします。" + /> + <LinkCard + href="https://github.com/HiDeoo/astro-d2" + title="astro-d2" + description="D2のMarkdownコードブロックをダイアグラムに変換します。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-links" + title="starlight-links" + description="StarlightのMarkdownおよびMDXコンテンツリンクにIntelliSenseを提供するVisual Studio Code拡張機能です。" + /> + <LinkCard + href="https://docs.contentisland.net/templates/starlight/" + title="contentisland-cli" + description="StarlightプロジェクトをContent Island Headless CMSに接続・同期して、ドキュメントを編集・管理します。" + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown" + title="starlight-sidebar-topics-dropdown" + description="ドキュメントページを複数のサブページに分割し、サイドバーのドロップダウンメニューで切り替えられるようにします。" + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-save-file-component" + title="starlight-save-file-component" + description="Starlightサイト上にダウンロードアセットへのリンクをすばやく表示します。" + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-contributor-list" + title="starlight-contributor-list" + description="プロジェクトの全コントリビューター一覧を表示します。" + /> +</CardGrid> diff --git a/docs/src/content/docs/ja/resources/showcase.mdx b/docs/src/content/docs/ja/resources/showcase.mdx new file mode 100644 index 00000000000..bc770fa3c9d --- /dev/null +++ b/docs/src/content/docs/ja/resources/showcase.mdx @@ -0,0 +1,20 @@ +--- +title: Starlightショーケース +description: Starlightで作成されたサイトをチェックしましょう! +sidebar: + label: サイト紹介 +--- + +:::tip[自分のものを追加しよう!] +Starlightでサイトを作成しましたか?このページにリンクを追加する[PRを作成](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#showcase)しましょう! +::: + +## サイト + +import ShowcaseSites from '~/components/showcase-sites.astro'; + +Starlightはすでに本番環境で使用されています。以下は、ウェブ上のいくつかのサイトです。 + +<ShowcaseSites /> + +[Starlightを使用しているパブリックなプロジェクトのGitHubリポジトリ](https://github.com/withastro/starlight/network/dependents)を確認してみてください。 diff --git a/docs/src/content/docs/ja/resources/themes.mdx b/docs/src/content/docs/ja/resources/themes.mdx new file mode 100644 index 00000000000..d4f287eca33 --- /dev/null +++ b/docs/src/content/docs/ja/resources/themes.mdx @@ -0,0 +1,117 @@ +--- +title: テーマ +description: Starlightのコミュニティテーマでドキュメントをスタイルできます +tableOfContents: false +sidebar: + order: 2 +head: + - tag: style + content: | + body { --sl-content-width: 66.75rem; } +--- + +import ThemeGrid from '~/components/theme-grid.astro'; + +テーマはStarlightのプラグインで、[カスタムCSS](/ja/guides/css-and-tailwind/)、[コンポーネントのオーバーライド](/ja/guides/overriding-components/)、その他の新機能などによってサイトの見た目を変更します。 + +## コミュニティテーマ + +コミュニティが作成したテーマをインストールすると、サイトの見た目や使い心地を手早くカスタマイズできます。 + +以下のリストですべてのテーマをプレビューできるほか、[Starlightテーマのデモサイト](https://starlight-themes.netlify.app/)でインタラクティブに試すこともできます。 + +<ThemeGrid + labels={{ + /** テーマ切り替えのアクセシブルラベル。*/ + legend: 'プレビュー', + /** ダークカラースキームのアクセシブルラベル。*/ + dark: 'ダーク', + /** ライトカラースキームのアクセシブルラベル。*/ + light: 'ライト', + }} + themes={[ + { + title: 'Starlight Rapide', + description: + 'Visual Studio CodeのVitesseテーマに着想を得たStarlightテーマです。', + href: 'https://starlight-theme-rapide.vercel.app/', + previews: { light: 'rapide-light.png', dark: 'rapide-dark.png' }, + }, + { + title: 'Starlight Obsidian', + description: + 'Obsidian Publishサイトのスタイルに着想を得たStarlightテーマです。', + href: 'https://fevol.github.io/starlight-theme-obsidian/', + previews: { light: 'obsidian-light.png', dark: 'obsidian-dark.png' }, + }, + { + title: 'Catppuccin for Starlight', + description: 'やさしいパステル調のStarlight向けテーマです。', + href: 'https://starlight.catppuccin.com/', + previews: { light: 'catppuccin-light.png', dark: 'catppuccin-dark.png' }, + }, + { + title: 'Ion', + description: '洗練されたモダンなStarlightテーマです。', + href: 'https://louisescher.github.io/starlight-ion-theme/', + previews: { light: 'ion-light.png', dark: 'ion-dark.png' }, + }, + { + title: 'Starlight Black', + description: 'shadcnのドキュメントに着想を得たStarlightテーマです。', + href: 'https://starlight-theme-black.vercel.app/', + previews: { light: 'black-light.png', dark: 'black-dark.png' }, + }, + { + title: 'Starlight Flexoki', + description: + 'Flexokiカラーパレットに基づく、あたたかく親しみやすいテーマです。', + href: 'https://delucis.github.io/starlight-theme-flexoki/', + previews: { light: 'flexoki-light.png', dark: 'flexoki-dark.png' }, + }, + { + title: 'Starlight Nova', + description: 'モダンで美しいStarlightテーマです。', + href: 'https://starlight-theme-nova.pages.dev/', + previews: { light: 'nova-light.png', dark: 'nova-dark.png' }, + }, + { + title: 'Starlight Next.js', + description: 'Next.jsのドキュメントに着想を得たStarlightテーマです。', + href: 'https://starlight-theme-next.trueberryless.org/', + previews: { light: 'nextjs-light.png', dark: 'nextjs-dark.png' }, + }, + { + title: 'Starlight Galaxy', + description: + 'ドキュメントや教育コンテンツの公開に特化したAstro Starlightテーマです。', + href: 'https://frostybee.github.io/starlight-theme-galaxy/', + previews: { light: 'galaxy-light.png', dark: 'galaxy-dark.png' }, + }, + { + title: 'Starlight Page', + description: + 'スムーズなフロートインアニメーションを備えた直感的でモダンなStarlightテーマです。', + href: 'https://pelagornis-page.netlify.app/', + previews: { light: 'page-light.png', dark: 'page-dark.png' }, + }, + { + title: 'Starlight Gruvbox', + description: 'レトロでグルーヴィなStarlightテーマです。', + href: 'https://starlight-theme-gruvbox.otterlord.dev/', + previews: { light: 'gruvbox-light.png', dark: 'gruvbox-dark.png' }, + }, + { + title: 'Starlight Six', + description: + 'Six TechnologyによるクリーンでモダンなStarlightテーマです。', + href: 'https://six-tech.github.io/Six.StarlightTheme/', + previews: { light: 'six-light.png', dark: 'six-dark.png' }, + }, + ]} +/> + +:::tip[あなたのテーマを追加しませんか?] +Starlightテーマを作成しましたか?このページにあなたのテーマを追加するPRを作成してください! +[PRを開く](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#themes) +::: diff --git a/docs/src/content/docs/ja/showcase.mdx b/docs/src/content/docs/ja/showcase.mdx deleted file mode 100644 index 68e1189b794..00000000000 --- a/docs/src/content/docs/ja/showcase.mdx +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Starlightショーケース -description: Starlightで作成されたサイトや、Starlightを拡張したコミュニティツールを見つけましょう! ---- - -:::tip[自分のものを追加しよう!] -StarlightサイトやStarlightのツールを作成しましたか?このページにリンクを追加するPRを開いてみましょう! -::: - -## サイト - -import ShowcaseSites from '../../../components/showcase-sites.astro'; - -Starlightはすでに本番環境で使用されています。以下はウェブ上のサイトの一部です。 - -<ShowcaseSites /> - -[Starlightを使用しているGitHub上のすべてのパブリックプロジェクトのリポジトリ](https://github.com/withastro/starlight/network/dependents)も確認してください。 - -## コミュニティプラグイン - -import { CardGrid, LinkCard } from '@astrojs/starlight/components'; - -以下のコミュニティツール、プラグイン、およびインテグレーションは、Starlightと連携してその機能を拡張します。 - -<CardGrid> - <LinkCard - href="https://www.feelback.dev/blog/new-astro-starlight-integration/" - title="FeelBack" - description="サイトにユーザーフィードバックシステムを追加します。" - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-blog" - title="starlight-blog" - description="ドキュメントサイトにブログを追加します。" - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-links-validator" - title="starlight-links-validator" - description="Starlightページに壊れたリンクがないか確認します。" - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-typedoc" - title="starlight-typedoc" - description="TypeDocを使用してTypeScriptからStarlightページを生成します。" - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-openapi" - title="starlight-openapi" - description="OpenAPI/Swagger specificationからドキュメントページを作成します。" - /> -</CardGrid> diff --git a/docs/src/content/docs/ko/404.md b/docs/src/content/docs/ko/404.md index 41b9765752c..22ab28dd3a1 100644 --- a/docs/src/content/docs/ko/404.md +++ b/docs/src/content/docs/ko/404.md @@ -1,10 +1,11 @@ --- -title: 페이지를 찾을 수 없습니다 +title: 페이지를 찾을 수 없습니다. template: splash editUrl: false +lastUpdated: false hero: title: '404' - tagline: <strong>Houston, 문제가 생겼어요.</strong> 요청한 페이지를 찾을 수 없어요.<br>URL을 다시 한번 확인하거나 검색창을 사용해보세요. + tagline: <strong>Houston, 문제가 생겼어요.</strong> 페이지를 찾을 수 없습니다.<br>URL을 다시 확인해보거나 검색을 사용해보세요. actions: - text: 홈으로 이동 icon: right-arrow diff --git a/docs/src/content/docs/ko/components/asides.mdx b/docs/src/content/docs/ko/components/asides.mdx new file mode 100644 index 00000000000..8c2229c82d9 --- /dev/null +++ b/docs/src/content/docs/ko/components/asides.mdx @@ -0,0 +1,194 @@ +--- +title: 보조 내용 +description: Starlight에서 보조 내용을 사용하여 페이지의 주요 콘텐츠와 함께 보조 정보를 표시하는 방법을 알아보세요. +--- + +import { Aside } from '@astrojs/starlight/components'; + +페이지의 주요 콘텐츠와 함께 보조 정보를 표시하려면 `<Aside>` 컴포넌트를 사용합니다. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Aside slot="preview"> + 필수적이지 않은 보충 정보는 `<Aside>`에 포함하세요. +</Aside> + +</Preview> + +## 가져오기 + +```tsx +import { Aside } from '@astrojs/starlight/components'; +``` + +## 사용 + +`<Aside>` 컴포넌트를 사용하여 보조 내용 (“admonitions” 또는 “callouts”이라고도 함)을 표시합니다. + +`<Aside>`에는 보조 내용의 색상, 아이콘 및 기본 제목을 제어하는 선택적 [`type`](#type) 속성이 있을 수 있습니다. + +<Preview> + +````mdx +import { Aside } from '@astrojs/starlight/components'; + +<Aside>보조 내용의 콘텐츠입니다.</Aside> + +<Aside type="caution">몇 가지 주의해야 할 내용입니다.</Aside> + +<Aside type="tip"> + +보조 내용에는 다른 콘텐츠도 지원됩니다. + +```js +// 예시 코드 스니펫. +``` + +</Aside> + +<Aside type="danger">비밀번호를 다른 사람에게 알려주지 마세요.</Aside> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% aside %} +보조 내용의 콘텐츠입니다. +{% /aside %} + +{% aside type="caution" %} +몇 가지 주의해야 할 내용입니다. +{% /aside %} + +{% aside type="tip" %} +보조 내용에는 다른 콘텐츠도 지원됩니다. + +```js +// 예시 코드 스니펫. +``` +{% /aside %} + +{% aside type="danger" %} +비밀번호를 다른 사람에게 알려주지 마세요. +{% /aside %} +```` + +</Fragment> + +<Fragment slot="preview"> + + <Aside>보조 내용의 콘텐츠입니다.</Aside> + + <Aside type="caution">몇 가지 주의해야 할 내용입니다.</Aside> + + <Aside type="tip"> + + 보조 내용에는 다른 콘텐츠도 지원됩니다. + + ```js + // 예시 코드 스니펫. + ``` + + </Aside> + + <Aside type="danger">비밀번호를 다른 사람에게 알려주지 마세요.</Aside> + +</Fragment> + +</Preview> + +Starlight는 또한 `<Aside>` 컴포넌트의 대안으로 Markdown 및 MDX에서 보조 내용을 렌더링하기 위한 사용자 정의 구문을 제공합니다. +사용자 정의 구문에 대한 자세한 내용은 [“Markdown에서 콘텐츠 작성하기”](/ko/guides/authoring-content/#보조-내용) 가이드를 참조하세요. + +### 사용자 정의 제목 사용 + +[`title`](#title) 속성을 사용하여 보조 내용의 기본 제목을 재정의합니다. + +<Preview> + +```mdx 'title="조심하세요!"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="caution" title="조심하세요!"> + 사용자 정의 제목을 *사용하는* 경고 보조 내용입니다. +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'title="조심하세요!"' +{% aside type="caution" title="조심하세요!" %} +사용자 정의 제목을 *사용하는* 경고 보조 내용입니다. +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="caution" title="조심하세요!"> + 사용자 정의 제목을 *사용하는* 경고 보조 내용입니다. +</Aside> + +</Preview> + +### 사용자 정의 아이콘 사용 + +[Starlight의 기본 제공 아이콘 중 하나](/ko/reference/icons/#모든-아이콘)의 이름으로 설정된 [`icon`](#icon) 속성을 사용하여 기본 아이콘을 재정의합니다. + +<Preview> + +```mdx 'icon="starlight"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="tip" icon="starlight"> + 사용자 정의 아이콘을 *사용하는* 보조 팁입니다. +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="starlight"' +{% aside type="tip" icon="starlight" %} +사용자 정의 아이콘을 *사용하는* 보조 팁입니다. +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="tip" icon="starlight"> + 사용자 정의 아이콘을 *사용하는* 보조 팁입니다. +</Aside> + +</Preview> + +## `<Aside>` 속성 + +**구현:** [`Aside.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Aside.astro) + +`<Aside>` 컴포넌트는 다음과 같은 속성을 허용합니다: + +### `type` + +**타입:** `'note' | 'tip' | 'caution' | 'danger'` +**기본값:** `'note'` + +표시할 보조 내용의 유형입니다: + +- `note` 보조 내용은 파란색이며 정보 아이콘을 표시합니다 (기본값). +- `tip` 보조 내용은 보라색이며 로켓 아이콘을 표시합니다. +- `caution` 보조 내용은 노란색이며 삼각형 경고 아이콘을 표시합니다. +- `danger` 보조 내용은 빨간색이며 팔각형 경고 아이콘을 표시합니다. + +### `title` + +**타입:** `string` + +표시할 보조 내용의 제목입니다. +`title`이 설정되어 있지 않으면 현재 보조 내용의 `type`이 기본 제목으로 사용됩니다. + +### `icon` + +**타입:** [`StarlightIcon`](/ko/reference/icons/#starlighticon-타입) + +보조 내용은 [Starlight의 기본 제공 아이콘 중 하나](/ko/reference/icons/#모든-아이콘)의 이름으로 설정된 `icon` 속성을 포함할 수 있습니다. diff --git a/docs/src/content/docs/ko/components/badges.mdx b/docs/src/content/docs/ko/components/badges.mdx new file mode 100644 index 00000000000..eea0c7ce578 --- /dev/null +++ b/docs/src/content/docs/ko/components/badges.mdx @@ -0,0 +1,150 @@ +--- +title: 배지 +description: Starlight에서 배지를 사용하여 추가 정보를 표시하는 방법을 알아보세요. +--- + +import { Badge } from '@astrojs/starlight/components'; + +상태나 카테고리와 같은 작은 정보를 표시하려면 `<Badge>` 컴포넌트를 사용합니다. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Badge slot="preview" text="새 항목" /> + +</Preview> + +## 가져오기 + +```tsx +import { Badge } from '@astrojs/starlight/components'; +``` + +## 사용 + +`<Badge>` 컴포넌트를 사용하여 배지를 표시하고 표시할 콘텐츠를 `<Badge>` 컴포넌트의 [`text`](#text) 속성에 전달합니다. + +기본적으로 배지는 사이트의 테마 강조 색상을 사용합니다. +기본적으로 제공되는 배지 색상을 사용하려면 [`variant`](#variant) 속성을 지원되는 값 중 하나로 설정하세요. + +<Preview> + +```mdx +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="노트" variant="note" /> +- <Badge text="성공" variant="success" /> +- <Badge text="팁" variant="tip" /> +- <Badge text="주의" variant="caution" /> +- <Badge text="위험" variant="danger" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +- {% badge text="노트" variant="note" /%} +- {% badge text="성공" variant="success" /%} +- {% badge text="팁" variant="tip" /%} +- {% badge text="주의" variant="caution" /%} +- {% badge text="위험" variant="danger" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="노트" variant="note" /> + - <Badge text="성공" variant="success" /> + - <Badge text="팁" variant="tip" /> + - <Badge text="주의" variant="caution" /> + - <Badge text="위험" variant="danger" /> +</Fragment> + +</Preview> + +### 다른 크기 사용 + +[`size`](#size) 속성을 사용하여 배지 텍스트의 크기를 조절할 수 있습니다. + +<Preview> + +```mdx /size="\w+"/ +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="새 항목" size="small" /> +- <Badge text="개선된 새 항목" size="medium" /> +- <Badge text="더 큰 개선된 새 항목" size="large" /> +``` + +<Fragment slot="markdoc"> + +```markdoc /size="\w+"/ +- {% badge text="새 항목" size="small" /%} +- {% badge text="개선된 새 항목" size="medium" /%} +- {% badge text="더 큰 개선된 새 항목" size="large" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="새 항목" size="small" /> + - <Badge text="개선된 새 항목" size="medium" /> + - <Badge text="더 큰 개선된 새 항목" size="large" /> +</Fragment> + +</Preview> + +### 배지 사용자 정의 + +`class` 또는 `style`과 같은 다른 `<span>` 속성을 사용자 정의 CSS와 함께 사용하여 배지를 사용자 정의합니다. + +<Preview> + +```mdx "style={{ fontStyle: 'italic' }}" +import { Badge } from '@astrojs/starlight/components'; + +<Badge text="사용자 정의" variant="success" style={{ fontStyle: 'italic' }} /> +``` + +<Fragment slot="markdoc"> + +```markdoc 'style="font-style: italic;"' +{% badge text="사용자 정의" variant="success" style="font-style: italic;" /%} +``` + +</Fragment> + +<Badge + slot="preview" + text="사용자 정의" + variant="success" + style={{ fontStyle: 'italic' }} +/> + +</Preview> + +## `<Badge>` 속성 + +**구현:** [`Badge.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Badge.astro) + +`<Badge>` 컴포넌트는 다음 속성과 [기타 `<span>` 속성](https://developer.mozilla.org/ko/docs/Web/HTML/Global_attributes)도 허용합니다: + +### `text` + +**필수** +**타입:** `string` + +배지에 표시할 텍스트 콘텐츠입니다. + +### `variant` + +**타입:** `'note' | 'danger' | 'success' | 'caution' | 'tip' | 'default'` +**기본값:** `'default'` + +사용할 배지 색상 변형: `note` (파란색), `tip` (보라색), `danger` (빨간색), `caution` (오렌지색), `success` (초록색), `default` (테마 강조 색상). + +### `size` + +**타입:** `'small' | 'medium' | 'large'` + +표시할 배지의 크기를 정의합니다. diff --git a/docs/src/content/docs/ko/components/card-grids.mdx b/docs/src/content/docs/ko/components/card-grids.mdx new file mode 100644 index 00000000000..7e4743fe5ac --- /dev/null +++ b/docs/src/content/docs/ko/components/card-grids.mdx @@ -0,0 +1,179 @@ +--- +title: 카드 그리드 +description: Starlight에서 여러 카드를 그리드로 묶는 방법을 알아보세요. +sidebar: + order: 4 +--- + +import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; + +여러 개의 [`<Card>`](/ko/components/cards/) 또는 [`<LinkCard>`](/ko/components/link-cards/) 컴포넌트를 그리드에 래핑하려면 `<CardGrid>` 컴포넌트를 사용합니다. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<CardGrid slot="preview"> + <Card title="별" icon="star"> + 시리우스, 베가, 베텔게우스 + </Card> + <Card title="달" icon="moon"> + 이오, 유로파, 가니메데 + </Card> +</CardGrid> + +</Preview> + +## 가져오기 + +```tsx +import { CardGrid } from '@astrojs/starlight/components'; +``` + +## 사용 + +### 카드 그룹화 + +충분한 공간이 있을 때 여러 개의 [`<Card>`](/ko/components/cards/) 컴포넌트를 `<CardGrid>` 컴포넌트로 그룹화하여 나란히 표시합니다. + +<Preview> + +```mdx {3,10} +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <Card title="확인하세요" icon="open-book"> + 강조하고 싶은 흥미로운 콘텐츠. + </Card> + <Card title="기타 기능" icon="information"> + 공유하고 싶은 추가 정보. + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,9} +{% cardgrid %} +{% card title="확인하세요" icon="open-book" %} +강조하고 싶은 흥미로운 콘텐츠. +{% /card %} + +{% card title="기타 기능" icon="information" %} +공유하고 싶은 추가 정보. +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <Card title="확인하세요" icon="open-book"> + 강조하고 싶은 흥미로운 콘텐츠. + </Card> + <Card title="기타 기능" icon="information"> + 공유하고 싶은 추가 정보. + </Card> +</CardGrid> + +</Preview> + +### 링크 카드 그룹화 + +충분한 공간이 있을 때 여러 개의 [`<LinkCard>`](/ko/components/link-cards/) 컴포넌트를 `<CardGrid>` 컴포넌트를 사용하여 그룹화하여 나란히 표시합니다. + +<Preview> + +```mdx {3,6} +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <LinkCard + title="Markdown으로 콘텐츠 작성" + href="/ko/guides/authoring-content/" + /> + <LinkCard title="컴포넌트" href="/ko/components/using-components/" /> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,5} +{% cardgrid %} +{% linkcard title="Markdown으로 콘텐츠 작성" href="/ko/guides/authoring-content/" /%} + +{% linkcard title="컴포넌트" href="/ko/components/using-components/" /%} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <LinkCard + title="Markdown으로 콘텐츠 작성" + href="/ko/guides/authoring-content/" + /> + <LinkCard title="컴포넌트" href="/ko/components/using-components/" /> +</CardGrid> + +</Preview> + +### 카드를 엇갈리게 배치 + +그리드의 두 번째 열을 수직으로 이동하여 시각적 흥미를 더하려면 `<CardGrid>` 컴포넌트에 [`stagger`](#stagger) 속성을 추가합니다. + +이 속성은 홈 페이지에서 프로젝트의 주요 기능을 표시하는 데 유용합니다. + +<Preview> + +```mdx "stagger" +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid stagger> + <Card title="확인하세요" icon="open-book"> + 강조하고 싶은 흥미로운 콘텐츠. + </Card> + <Card title="기타 기능" icon="information"> + 공유하고 싶은 추가 정보. + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc "stagger=true" +{% cardgrid stagger=true %} +{% card title="확인하세요" icon="open-book" %} +강조하고 싶은 흥미로운 콘텐츠. +{% /card %} + +{% card title="기타 기능" icon="information" %} +공유하고 싶은 추가 정보. +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview" stagger> + <Card title="확인하세요" icon="open-book"> + 강조하고 싶은 흥미로운 콘텐츠. + </Card> + <Card title="기타 기능" icon="information"> + 공유하고 싶은 추가 정보. + </Card> +</CardGrid> + +</Preview> + +## `<CardGrid>` 속성 + +**구현:** [`CardGrid.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/CardGrid.astro) + +`<CardGrid>` 컴포넌트는 다음과 같은 속성을 허용합니다: + +### `stagger` + +**타입:** `boolean` + +그리드에 카드를 엇갈리게 배치할지 여부를 정의합니다. diff --git a/docs/src/content/docs/ko/components/cards.mdx b/docs/src/content/docs/ko/components/cards.mdx new file mode 100644 index 00000000000..cb58891aadd --- /dev/null +++ b/docs/src/content/docs/ko/components/cards.mdx @@ -0,0 +1,108 @@ +--- +title: 카드 +description: Starlight에서 카드를 사용하여 상자에 콘텐츠를 표시하는 방법을 알아보세요. +sidebar: + order: 2 +--- + +import { Card } from '@astrojs/starlight/components'; + +Starlight의 스타일과 일치하는 상자에 콘텐츠를 표시하려면 `<Card>` 컴포넌트를 사용합니다. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Card slot="preview" title="달" icon="moon"> + 이오, 유로파, 가니메데 +</Card> + +</Preview> + +## 가져오기 + +```tsx +import { Card } from '@astrojs/starlight/components'; +``` + +## 사용 + +`<Card>` 컴포넌트를 사용하여 카드를 표시하고 카드의 [`title`](#title)을 입력합니다. + +<Preview> + +```mdx +import { Card } from '@astrojs/starlight/components'; + +<Card title="확인하세요">강조하고 싶은 흥미로운 콘텐츠.</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% card title="확인하세요" %} +강조하고 싶은 흥미로운 콘텐츠. +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="확인하세요"> + 강조하고 싶은 흥미로운 콘텐츠. +</Card> + +</Preview> + +### 카드에 아이콘 추가 + +[Starlight 내장 아이콘 중 하나](/ko/reference/icons/#모든-아이콘)의 이름으로 설정된 [`icon`](#icon) 속성을 사용하여 카드에 아이콘을 포함하세요. + +<Preview> + +```mdx 'icon="star"' +import { Card } from '@astrojs/starlight/components'; + +<Card title="별" icon="star"> + 시리우스, 베가, 베텔게우스 +</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="star"' +{% card title="별" icon="star" %} +시리우스, 베가, 베텔게우스 +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="별" icon="star"> + 시리우스, 베가, 베텔게우스 +</Card> + +</Preview> + +### 카드 그룹화 + +[`<CardGrid>`](/ko/components/card-grids/) 컴포넌트를 사용해 카드를 그룹화하여 공간이 충분할 때 여러 카드를 나란히 표시합니다. +예시는 [“카드 그룹화”](/ko/components/card-grids/#카드-그룹화) 가이드를 참조하세요. + +## `<Card>` 속성 + +**구현:** [`Card.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Card.astro) + +`<Card>` 컴포넌트는 다음과 같은 속성을 허용합니다: + +### `title` + +**필수** +**타입:** `string` + +표시할 카드의 제목입니다. + +### `icon` + +**타입:** `string` + +카드에는 [Starlight 내장 아이콘 중 하나](/ko/reference/icons/#모든-아이콘)의 이름으로 설정된 `icon` 속성을 포함할 수 있습니다. diff --git a/docs/src/content/docs/ko/components/code.mdx b/docs/src/content/docs/ko/components/code.mdx new file mode 100644 index 00000000000..8e8ea630cb9 --- /dev/null +++ b/docs/src/content/docs/ko/components/code.mdx @@ -0,0 +1,103 @@ +--- +title: 코드 +description: Markdown 코드 블록 없이 Starlight에서 구문 강조 표시된 코드를 표시하는 방법을 알아보세요. +--- + +import { Code } from '@astrojs/starlight/components'; + +`<Code>` 컴포넌트는 구문이 강조 표시된 코드를 렌더링합니다. +예를 들어 파일, 데이터베이스, API와 같은 외부 소스에서 가져온 데이터를 렌더링할 때와 같이 [Markdown 코드 블록](/ko/guides/authoring-content/#코드-블록)을 사용할 수 없을 때 유용합니다. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Code + slot="preview" + code={`## 환영합니다 + +**우주에서** 하는 인사!`} +lang="md" +title="example.md" +ins={3} +/> + +</Preview> + +## 가져오기 + +```tsx +import { Code } from '@astrojs/starlight/components'; +``` + +## 사용 + +외부 소스에서 가져온 코드를 표시할 때와 같은 상황에서 구문이 강조된 코드를 렌더링하려면 `<Code>` 컴포넌트를 사용합니다. + +[Expressive Code “Code 컴포넌트” 문서](https://expressive-code.com/key-features/code-component/)에서 `<Code>` 컴포넌트 사용 방법과 사용 가능한 속성 목록에 대한 자세한 내용을 확인할 수 있습니다. + +<Preview> + +```mdx +import { Code } from '@astrojs/starlight/components'; + +export const exampleCode = `console.log('이는 파일이나 CMS에서 올 수 있습니다!');`; +export const fileName = 'example.js'; +export const highlights = ['파일', 'CMS']; + +<Code code={exampleCode} lang="js" title={fileName} mark={highlights} /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% code + code="console.log('이는 파일이나 CMS에서 올 수 있습니다!');" + lang="js" + title="example.js" + meta="'파일' 'CMS'" /%} +``` + +</Fragment> + +export const exampleCode = `console.log('이는 파일이나 CMS에서 올 수 있습니다!');`; +export const fileName = 'example.js'; +export const highlights = ['파일', 'CMS']; + +<Code + slot="preview" + code={exampleCode} + lang="js" + title={fileName} + mark={highlights} +/> + +</Preview> + +### 가져온 코드 표시 + +MDX 파일 및 Astro 컴포넌트에서 [Vite의 `?raw` 가져오기 접미사](https://ko.vite.dev/guide/assets#importing-asset-as-string)를 사용하여 코드 파일을 문자열로 가져옵니다. +그런 다음 이 가져온 문자열을 `<Code>` 컴포넌트에 전달하여 페이지에 포함할 수 있습니다. + +<Preview> + +```mdx "?raw" +# src/content/docs/example.mdx + +import { Code } from '@astrojs/starlight/components'; +import importedCode from '/tsconfig.json?raw'; + +<Code code={importedCode} lang="json" title="tsconfig.json" /> +``` + +import importedCode from '../../../../../../examples/basics/tsconfig.json?raw'; + +<Code slot="preview" code={importedCode} lang="json" title="tsconfig.json" /> + +</Preview> + +## `<Code>` 속성 + +**구현:** [`Code.astro`](https://github.com/expressive-code/expressive-code/blob/main/packages/astro-expressive-code/components/Code.astro) + +`<Code>` 컴포넌트는 [Expressive Code “Code 컴포넌트” 문서](https://expressive-code.com/key-features/code-component/#available-props)에 문서화된 모든 속성을 허용합니다. diff --git a/docs/src/content/docs/ko/components/file-tree.mdx b/docs/src/content/docs/ko/components/file-tree.mdx new file mode 100644 index 00000000000..e09665851a6 --- /dev/null +++ b/docs/src/content/docs/ko/components/file-tree.mdx @@ -0,0 +1,265 @@ +--- +title: 파일 트리 +description: Starlight에서 파일 아이콘과 접을 수 있는 하위 디렉터리를 사용하여 디렉터리 구조를 표시하는 방법을 알아보세요. +--- + +import { FileTree } from '@astrojs/starlight/components'; + +파일 아이콘과 접을 수 있는 하위 디렉터리가 있는 디렉터리의 구조를 표시하려면 `<FileTree>` 컴포넌트를 사용하세요. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<FileTree slot="preview"> + +- astro.config.mjs **중요** 파일 +- package.json +- README.md +- src + - components + - **Header.astro** + - … +- pages/ + +</FileTree> + +</Preview> + +## 가져오기 + +```tsx +import { FileTree } from '@astrojs/starlight/components'; +``` + +## 사용 + +`<FileTree>` 컴포넌트를 사용하여 파일 아이콘과 접을 수 있는 하위 디렉터리가 있는 파일 트리를 표시합니다. + +`<FileTree>`에서 [순서가 지정되지 않은 Markdown 목록](https://www.markdownguide.org/basic-syntax/#unordered-lists)을 사용하여 파일 및 디렉터리의 구조를 지정하세요. +중첩된 목록을 사용하여 하위 디렉터리를 생성하거나 목록 항목 끝에 `/`를 추가하여 특정 내용이 없는 디렉터리로 렌더링합니다. + +<Preview> + +```mdx +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% filetree %} +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> + +</Preview> + +### 항목 강조 표시 + +파일이나 디렉터리의 이름을 굵은 글씨로 만들어 눈에 띄게 만드세요 (예: `**README.md**`). + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - **Header.astro** + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> + +</Preview> + +### 주석 추가 + +이름 뒤에 텍스트를 더 추가하여 파일이나 디렉터리에 주석을 추가합니다. +주석에서 굵게 및 기울임꼴과 같은 인라인 Markdown 서식이 지원됩니다. + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro **중요** 파일 + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - Header.astro **중요** 파일 + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro **중요** 파일 + - Title.astro + +</FileTree> + +</Preview> + +### 자리 표시자 추가 + +`...` 또는 `…`을 이름으로 사용하여 자리 표시자 파일과 디렉터리를 추가합니다. +이는 폴더에 더 많은 항목이 포함될 수 있음을 모든 항목을 일일이 명시하지 않고도 독자에게 알려주는 데 유용할 수 있습니다. + +<Preview> + +```mdx {8} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro + - … + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {5} +{% filetree %} +- src + - components + - Header.astro + - … +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro + - … + +</FileTree> + +</Preview> + +### 특수 문자 이스케이프 + +파일 이름에 밑줄 또는 공백과 같은 특수 문자가 포함된 경우, 파일 이름을 코드 백틱으로 감싸서 이스케이프하세요. + +<Preview> + +```mdx +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- `__init__.py` +- `Hello world.txt` +- **`READ ME FIRST.md`** + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% filetree %} +- `__init__.py` +- `Hello world.txt` +- **`READ ME FIRST.md`** +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- `__init__.py` +- `Hello world.txt` +- **`READ ME FIRST.md`** + +</FileTree> + +</Preview> + +## `<FileTree>` 속성 + +**구현:** [`FileTree.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/FileTree.astro) + +`<FileTree>` 컴포넌트는 어떤 속성도 허용하지 않습니다. diff --git a/docs/src/content/docs/ko/components/icons.mdx b/docs/src/content/docs/ko/components/icons.mdx new file mode 100644 index 00000000000..5fde7ec4c9b --- /dev/null +++ b/docs/src/content/docs/ko/components/icons.mdx @@ -0,0 +1,128 @@ +--- +title: 아이콘 +description: Starlight에서 아이콘을 표시하는 방법을 알아보세요. +--- + +import { Icon } from '@astrojs/starlight/components'; + +Starlight의 [기본 제공 아이콘 세트](/ko/reference/icons/#모든-아이콘)의 아이콘을 표시하려면 `<Icon>` 컴포넌트를 사용하세요. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Icon + slot="preview" + name="open-book" + color="var(--sl-color-text-accent)" + size="4rem" +/> + +</Preview> + +## 가져오기 + +```tsx +import { Icon } from '@astrojs/starlight/components'; +``` + +## 사용 + +`<Icon>` 컴포넌트를 사용하여 아이콘을 표시합니다. +아이콘에는 [Starlight의 기본 제공 아이콘 중 하나](/ko/reference/icons/#모든-아이콘)로 설정된 [`name`](#name)이 필요하며, 화면 리더에 컨텍스트를 제공하기 위해 선택적으로 [`label`](#label)을 포함할 수 있습니다. + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" /> +<Icon name="starlight" label="Starlight 로고" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" /%} +{% icon name="starlight" label="Starlight 로고" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" /> + <Icon name="starlight" label="Starlight 로고" /> +</Fragment> + +</Preview> + +### 아이콘 사용자 정의 + +CSS 단위와 색상 값을 사용하여 아이콘의 모양을 조정하는 데 [`size`](#size) 및 [`color`](#color) 속성을 사용할 수 있습니다. +[`class`](#class) 속성을 사용하여 아이콘에 사용자 정의 CSS 클래스를 추가할 수 있습니다. + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" color="goldenrod" size="2rem" /> +<Icon name="rocket" color="var(--sl-color-text-accent)" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" color="goldenrod" size="2rem" /%} +{% icon name="rocket" color="var(--sl-color-text-accent)" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" color="goldenrod" size="2rem" /> + <Icon name="rocket" color="var(--sl-color-text-accent)" /> +</Fragment> + +</Preview> + +## `<Icon>` 속성 + +**구현:** [`Icon.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Icon.astro) + +`<Icon>` 컴포넌트는 다음 속성을 허용합니다: + +### `name` + +**필수** +**타입:** [`StarlightIcon`](/ko/reference/icons/#starlighticon-타입) + +표시할 아이콘의 이름을 [Starlight의 기본 제공 아이콘 중 하나](/ko/reference/icons/#모든-아이콘)로 설정합니다. + +### `label` + +**타입:** `string` + +화면 리더와 같은 보조 기술에 컨텍스트를 제공하기 위한 선택적 레이블입니다. + +`label`을 설정하지 않으면 보조 기술에서 아이콘이 완전히 숨겨집니다. +이 경우 아이콘 없이도 문맥을 이해할 수 있는지 확인하세요. +예를 들어 아이콘만 포함된 링크는 `label` 속성을 **포함해야** 액세스할 수 있지만, 링크에 텍스트가 포함되어 있고 아이콘이 순전히 장식용인 경우에는 `label`을 생략해도 괜찮습니다. + +### `size` + +**타입:** `string` + +CSS 단위를 사용한 아이콘 크기입니다. + +### `color` + +**타입:** `string` + +CSS 색상 값을 사용하는 아이콘의 색상입니다. + +### `class` + +**타입:** `string` + +아이콘에 추가할 사용자 정의 CSS 클래스입니다. diff --git a/docs/src/content/docs/ko/components/link-buttons.mdx b/docs/src/content/docs/ko/components/link-buttons.mdx new file mode 100644 index 00000000000..42df8166dd3 --- /dev/null +++ b/docs/src/content/docs/ko/components/link-buttons.mdx @@ -0,0 +1,145 @@ +--- +title: 링크 버튼 +description: 시각적으로 뚜렷한 콜투액션 링크를 위해 Starlight에서 링크 버튼을 만드는 방법을 알아보세요. +--- + +import { LinkButton } from '@astrojs/starlight/components'; + +시각적으로 뚜렷한 콜투액션 링크를 표시하려면 `<LinkButton>` 컴포넌트를 사용합니다. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkButton slot="preview" href="/ko/getting-started/"> + 문서 읽기 +</LinkButton> + +</Preview> + +## 가져오기 + +```tsx +import { LinkButton } from '@astrojs/starlight/components'; +``` + +## 사용 + +시각적으로 구분되는 콜투액션 링크를 표시하려면 `<LinkButton>` 컴포넌트를 사용합니다. +링크 버튼은 가장 관련성이 높거나 실행 가능한 콘텐츠로 사용자를 안내하는 데 유용하며 랜딩 페이지에서 자주 사용됩니다. + +`<LinkButton>`에는 [`href`](#href) 속성이 필요합니다. +선택적으로 `primary` (기본값), `secondary`, `minimal`로 설정할 수 있는 [`variant`](#variant) 속성을 사용하여 링크 버튼의 모양을 사용자 정의합니다. + +<Preview> + +```mdx +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton href="/ko/getting-started/">시작하기</LinkButton> +<LinkButton href="/ko/reference/configuration/" variant="secondary"> + 구성 참조 +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkbutton href="/ko/getting-started/" %}시작하기{% /linkbutton %} + +{% linkbutton href="/ko/reference/configuration/" variant="secondary" %} +구성 참조 +{% /linkbutton %} +``` + +</Fragment> + +<Fragment slot="preview"> + <LinkButton href="/ko/getting-started/">시작하기</LinkButton> + <LinkButton href="/ko/reference/configuration/" variant="secondary"> + 구성 참조 + </LinkButton> +</Fragment> + +</Preview> + +### 링크 버튼에 아이콘 추가 + +[Starlight의 내장 아이콘 중 하나](/ko/reference/icons/#모든-아이콘)의 이름으로 설정된 [`icon`](#icon) 속성을 사용하여 링크 버튼에 아이콘을 포함시킵니다. + +텍스트 앞에 아이콘을 배치하기 위해 [`iconPlacement`](#iconplacement) 속성을 `start`로 설정할 수 있습니다 (기본값은 `end`). + +<Preview> + +```mdx {6-7} +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton + href="https://docs.astro.build/ko" + variant="secondary" + icon="external" + iconPlacement="start" +> + 관련: Astro +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc {4-5} +{% linkbutton + href="https://docs.astro.build/ko" + variant="secondary" + icon="external" + iconPlacement="start" %} +관련: Astro +{% /linkbutton %} +``` + +</Fragment> + +<LinkButton + slot="preview" + href="https://docs.astro.build/ko" + variant="secondary" + icon="external" + iconPlacement="start" +> + 관련: Astro +</LinkButton> + +</Preview> + +## `<LinkButton>` 속성 + +**구현:** [`LinkButton.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkButton.astro) + +`<LinkButton>` 컴포넌트는 다음 속성과 [기타 `<a>` 속성](https://developer.mozilla.org/ko/docs/Web/HTML/Element/a)도 허용합니다: + +### `href` + +**필수** +**타입:** `string` + +링크 버튼이 가리키는 URL입니다. + +### `variant` + +**타입:** `'primary' | 'secondary' | 'minimal'` +**기본값:** `'primary'` + +링크 버튼의 모양입니다. +테마 강조 색상을 사용하여 눈에 잘 띄는 콜투액션 링크를 만들려면 `primary`, 덜 눈에 띄는 링크를 만들려면 `secondary`, 최소한의 스타일을 적용한 링크를 만들려면 `minimal`로 설정합니다. + +### `icon` + +**타입:** `string` + +링크 버튼에는 [Starlight의 기본 제공 아이콘 중 하나](/ko/reference/icons/#모든-아이콘)의 이름으로 설정된 `icon` 속성을 포함할 수 있습니다. + +### `iconPlacement` + +**타입:** `'start' | 'end'` +**기본값:** `'end'` + +링크 버튼 텍스트에 상대적인 아이콘의 위치를 결정합니다. diff --git a/docs/src/content/docs/ko/components/link-cards.mdx b/docs/src/content/docs/ko/components/link-cards.mdx new file mode 100644 index 00000000000..c4099553a87 --- /dev/null +++ b/docs/src/content/docs/ko/components/link-cards.mdx @@ -0,0 +1,128 @@ +--- +title: 링크 카드 +description: Starlight에서 링크를 카드로 눈에 잘 띄게 표시하는 방법을 알아보세요. +sidebar: + order: 3 +--- + +import { LinkCard } from '@astrojs/starlight/components'; + +다른 페이지로 연결되는 링크를 눈에 잘 띄게 표시하려면 `<LinkCard>` 컴포넌트를 사용하세요. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkCard + slot="preview" + title="Starlight 사용자 정의" + description="사용자 정의 스타일, 글꼴 등을 사용하여 스타라이트 사이트를 나만의 사이트로 만드는 방법을 알아보세요." + href="/ko/guides/customization/" +/> + +</Preview> + +## 가져오기 + +```tsx +import { LinkCard } from '@astrojs/starlight/components'; +``` + +## 사용 + +`<LinkCard>` 컴포넌트를 사용하여 링크를 눈에 잘 띄게 표시합니다. +각 `<LinkCard>`에는 [`title`](#title) 및 [`href`](#href) 속성이 필요합니다. + +<Preview> + +```mdx +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard + title="Markdown으로 콘텐츠 작성" + href="/ko/guides/authoring-content/" +/> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkcard title="Markdown으로 콘텐츠 작성" href="/ko/guides/authoring-content/" /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="Markdown으로 콘텐츠 작성" + href="/ko/guides/authoring-content/" +/> + +</Preview> + +### 링크 설명 추가 + +[`description`](#description) 속성을 사용하여 링크 카드에 간단한 설명을 추가합니다. + +<Preview> + +```mdx {6} +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard + title="국제화" + href="/ko/guides/i18n/" + description="여러 언어를 지원하도록 Starlight를 구성합니다." +/> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% linkcard + title="국제화" + href="/ko/guides/i18n/" + description="여러 언어를 지원하도록 Starlight를 구성합니다." /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="국제화" + href="/ko/guides/i18n/" + description="여러 언어를 지원하도록 Starlight를 구성합니다." +/> + +</Preview> + +### 링크 카드 그룹화 + +[`<CardGrid>`](/ko/components/card-grids/) 컴포넌트를 사용해 여러 개의 링크 카드를 그룹화하여 충분한 공간이 있을 때 나란히 표시합니다. +예시는 [“링크 카드 그룹화”](/ko/components/card-grids/#링크-카드-그룹화) 가이드를 참조하세요. + +## `<LinkCard>` 속성 + +**구현:** [`LinkCard.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkCard.astro) + +`<LinkCard>` 컴포넌트는 다음 속성과 기타 [`<a>` 요소의 속성](https://developer.mozilla.org/ko/docs/Web/HTML/Element/a)도 허용합니다: + +### `title` + +**필수** +**타입:** `string` + +표시할 링크 카드의 제목입니다. + +### `href` + +**필수** +**타입:** `string` + +카드와 상호 작용할 때 연결할 URL입니다. + +### `description` + +**타입:** `string` + +제목 아래에 표시할 설명 (선택 사항)입니다. diff --git a/docs/src/content/docs/ko/components/steps.mdx b/docs/src/content/docs/ko/components/steps.mdx new file mode 100644 index 00000000000..5072faad64e --- /dev/null +++ b/docs/src/content/docs/ko/components/steps.mdx @@ -0,0 +1,120 @@ +--- +title: 단계 +description: Starlight에서 단계별 가이드를 만들기 위해 작업의 번호가 매겨진 목록에 스타일을 지정하는 방법을 알아보세요. +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +번호가 매겨진 작업 목록에 스타일을 지정하여 단계별 가이드를 만들려면 `<Steps>` 컴포넌트를 사용하세요. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Steps slot="preview"> + +1. 새 Starlight 프로젝트를 만듭니다: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm create astro@latest -- --template starlight + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm create astro --template starlight + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn create astro --template starlight + ``` + + </TabItem> + + </Tabs> + +2. 첫 번째 문서 페이지를 작성합니다. + +</Steps> + +</Preview> + +## 가져오기 + +```tsx +import { Steps } from '@astrojs/starlight/components'; +``` + +## 사용 + +`<Steps>` 컴포넌트를 사용하여 번호가 매겨진 작업 목록의 스타일을 지정합니다. +이는 각 단계를 명확하게 강조해야 하는 보다 복잡한 단계별 가이드에 유용합니다. + +표준 Markdown 정렬 목록을 `<Steps>`로 묶습니다. +모든 일반적인 Markdown 구문은 `<Steps>` 내에서 적용 가능합니다. + +<Preview> + +````mdx +import { Steps } from '@astrojs/starlight/components'; + +<Steps> + +1. 컴포넌트를 MDX 파일로 가져옵니다. + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. 순서가 매겨진 목록 항목을 `<Steps>`로 묶습니다. + +</Steps> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% steps %} + +1. 컴포넌트를 MDX 파일로 가져옵니다. + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. 순서가 매겨진 목록 항목을 `<Steps>`로 묶습니다. + +{% /steps %} +```` + +</Fragment> + +<Steps slot="preview"> + +1. 컴포넌트를 MDX 파일로 가져옵니다. + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. 순서가 매겨진 목록 항목을 `<Steps>`로 묶습니다. + +</Steps> + +</Preview> + +## `<Steps>` 속성 + +**구현:** [`Steps.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Steps.astro) + +`<Steps>` 컴포넌트는 어떤 속성도 허용하지 않습니다. diff --git a/docs/src/content/docs/ko/components/tabs.mdx b/docs/src/content/docs/ko/components/tabs.mdx new file mode 100644 index 00000000000..6ce4becd655 --- /dev/null +++ b/docs/src/content/docs/ko/components/tabs.mdx @@ -0,0 +1,221 @@ +--- +title: 탭 +description: Starlight에서 탭 인터페이스를 만들어 동등한 정보를 그룹화하는 방법을 알아보세요. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +탭 인터페이스를 만들려면 `<Tabs>` 및 `<TabItem>` 컴포넌트를 사용합니다. +탭은 사용자가 여러 옵션 중 하나만 확인해야 하는 경우 동등한 정보를 그룹화하는 데 유용합니다. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Tabs slot="preview"> + <TabItem label="별">시리우스, 베가, 베텔게우스</TabItem> + <TabItem label="달">이오, 유로파, 가니메데</TabItem> +</Tabs> + +</Preview> + +## 가져오기 + +```tsx +import { Tabs, TabItem } from '@astrojs/starlight/components'; +``` + +## 사용 + +탭 인터페이스는 `<Tabs>` 및 `<TabItem>` 컴포넌트를 사용하여 표시합니다. +각 `<TabItem>`에는 사용자에게 표시할 [`label`](#label)이 있어야 합니다. + +<Preview> + +```mdx +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="별">시리우스, 베가, 베텔게우스</TabItem> + <TabItem label="달">이오, 유로파, 가니메데</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% tabs %} +{% tabitem label="별" %} +시리우스, 베가, 베텔게우스 +{% /tabitem %} + +{% tabitem label="달" %} +이오, 유로파, 가니메데 +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="별">시리우스, 베가, 베텔게우스</TabItem> + <TabItem label="달">이오, 유로파, 가니메데</TabItem> +</Tabs> + +</Preview> + +### 탭 동기화 + +[`syncKey`](#synckey) 속성을 추가하여 여러 탭 그룹을 동기화된 상태로 유지합니다. + +`syncKey` 값이 같은 페이지의 모든 `<Tabs>`는 동일한 활성 레이블을 표시합니다. +이렇게 하면 독자가 운영 체제나 패키지 관리자 등을 한 번 선택하면 페이지 탐색 간 선택한 내용이 유지되는 것을 확인할 수 있습니다. + +관련 탭을 동기화하려면 각 `<Tabs>` 컴포넌트에 동일한 `syncKey` 속성을 추가하고 모두 동일한 `<TabItem>` 레이블을 사용하는지 확인하세요. + +<Preview> + +```mdx 'syncKey="별자리"' +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +_별:_ + +<Tabs syncKey="별자리"> + <TabItem label="오리온자리">벨라트릭스, 리겔, 베텔게우스</TabItem> + <TabItem label="쌍둥이자리">폴룩스, 캐스터 A, 캐스터 B</TabItem> +</Tabs>{' '} + +_외계 행성:_ + +<Tabs syncKey="별자리"> + <TabItem label="오리온자리">HD 34445 b, 글리제 179 b, Wasp-82 b</TabItem> + <TabItem label="쌍둥이자리">폴룩스 b, HAT-P-24b, HD 50554 b</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc 'syncKey="별자리"' +_별:_ + +{% tabs syncKey="별자리" %} +{% tabitem label="오리온자리" %} +벨라트릭스, 리겔, 베텔게우스 +{% /tabitem %} + +{% tabitem label="쌍둥이자리" %} +폴룩스, 캐스터 A, 캐스터 B +{% /tabitem %} +{% /tabs %} + +_외계 행성:_ + +{% tabs syncKey="별자리" %} +{% tabitem label="오리온자리" %} +HD 34445 b, 글리제 179 b, Wasp-82 b +{% /tabitem %} + +{% tabitem label="쌍둥이자리" %} +폴룩스 b, HAT-P-24b, HD 50554 b +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Fragment slot="preview"> + +_별:_ + +<Tabs syncKey="별자리"> + <TabItem label="오리온자리">벨라트릭스, 리겔, 베텔게우스</TabItem> + <TabItem label="쌍둥이자리">폴룩스, 캐스터 A, 캐스터 B</TabItem> +</Tabs>{' '} + +_외계 행성:_ + +<Tabs syncKey="별자리"> + <TabItem label="오리온자리">HD 34445 b, 글리제 179 b, Wasp-82 b</TabItem> + <TabItem label="쌍둥이자리">폴룩스 b, HAT-P-24b, HD 50554 b</TabItem> +</Tabs> + +</Fragment> + +</Preview> + +### 탭에 아이콘 추가 + +[Starlight의 내장 아이콘 중 하나](/ko/reference/icons/#모든-아이콘)의 이름으로 설정된 [`icon`](#icon) 속성을 사용하여 탭 항목에 아이콘을 포함하면 레이블 옆에 아이콘이 표시됩니다. + +<Preview> + +```mdx /icon="\w+"/ +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="별" icon="star"> + 시리우스, 베가, 베텔게우스 + </TabItem> + <TabItem label="달" icon="moon"> + 이오, 유로파, 가니메데 + </TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc /icon="\w+"/ +{% tabs %} +{% tabitem label="별" icon="star" %} +시리우스, 베가, 베텔게우스 +{% /tabitem %} + +{% tabitem label="달" icon="moon" %} +이오, 유로파, 가니메데 +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="별" icon="star"> + 시리우스, 베가, 베텔게우스 + </TabItem> + <TabItem label="달" icon="moon"> + 이오, 유로파, 가니메데 + </TabItem> +</Tabs> + +</Preview> + +## `<Tabs>` 속성 + +**구현:** [`Tabs.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Tabs.astro) + +`<Tabs>` 컴포넌트는 여러 개의 `<TabItem>` 컴포넌트를 그룹화하고 다음과 같은 속성을 허용합니다: + +### `syncKey` + +**타입:** `string` + +여러 페이지에서 여러 탭 그룹을 동기화하는 데 사용되는 키입니다. + +## `<TabItem>` 속성 + +**구현:** [`TabItem.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/TabItem.astro) + +탭 세트는 탭 항목으로 구성되며, 각 항목에는 다음과 같은 속성이 있습니다: + +### `label` + +**필수** +**타입:** `string` + +탭 항목에는 탭에 표시될 텍스트로 설정된 `label` 속성이 포함되어야 합니다. + +### `icon` + +**타입:** `string` + +각 탭 항목에는 [Starlight의 내장 아이콘 중 하나](/ko/reference/icons/#모든-아이콘)의 이름으로 설정된 `icon` 속성을 포함하여 레이블 옆에 아이콘을 표시할 수 있습니다. diff --git a/docs/src/content/docs/ko/components/using-components.mdx b/docs/src/content/docs/ko/components/using-components.mdx new file mode 100644 index 00000000000..b7c24243d7f --- /dev/null +++ b/docs/src/content/docs/ko/components/using-components.mdx @@ -0,0 +1,94 @@ +--- +title: 컴포넌트 사용 +description: Starlight와 함께 MDX 및 Markdoc에서 컴포넌트 사용. +sidebar: + order: 1 +--- + +컴포넌트를 사용하면 쉽고 일관되게 UI 조각이나 스타일을 재사용할 수 있습니다. +링크 카드나 YouTube 삽입 등을 예로 들 수 있습니다. +Starlight는 [MDX](https://mdxjs.com/) 및 [Markdoc](https://markdoc.dev/) 파일에서 컴포넌트 사용을 지원하며 사용할 수 있는 몇 가지 공통 컴포넌트를 제공합니다. + +[Astro 문서에서 컴포넌트 구축에 대해 자세히 알아보세요](https://docs.astro.build/ko/basics/astro-components/). + +## MDX에서 컴포넌트 사용 + +MDX 파일에서 컴포넌트를 가져온 다음 JSX 태그로 렌더링하여 사용할 수 있습니다. +이는 HTML 태그처럼 보이지만 `import` 문에 있는 이름과 일치하는 대문자로 시작합니다. + +```mdx +--- +# src/content/docs/example.mdx +title: 내 문서에 오신 것을 환영합니다 +--- + +import { Icon } from '@astrojs/starlight/components'; +import CustomCard from '../../components/CustomCard.astro'; + +<Icon name="open-book" /> + +<CustomCard>컴포넌트에는 **중첩된 콘텐츠**가 포함될 수도 있습니다.</CustomCard> +``` + +Starlight는 Astro로 구동되므로 [지원되는 UI 프레임워크(React, Preact, Svelte, Vue, Solid, Alpine)](https://docs.astro.build/ko/guides/framework-components/)로 빌드된 컴포넌트를 MDX 파일에 추가할 수 있습니다. +Astro 문서에서 [MDX에서 컴포넌트 사용](https://docs.astro.build/ko/guides/integrations-guide/mdx/#mdx에서-컴포넌트-사용)에 대해 자세히 알아보세요. + +## Markdoc에서 컴포넌트 사용 + +[Markdoc 설정 가이드](/ko/guides/authoring-content/#markdoc)에 따라 Markdoc에서 콘텐츠 작성에 대한 지원을 추가하세요. + +Starlight Markdoc 프리셋을 사용하면 Starlight의 내장 컴포넌트를 Markdoc의 `{% %}` 태그 구문과 함께 사용할 수 있습니다. +MDX와 달리 Markdoc에서는 컴포넌트를 가져올 필요가 없습니다. +다음 예시는 Starlight의 [카드 컴포넌트](/ko/components/cards/)를 Markdoc 파일에서 렌더링합니다: + +```markdoc +--- +# src/content/docs/example.mdoc +title: 내 문서에 오신 것을 환영합니다 +--- + +{% card title="별" icon="star" %} +시리우스, 베가, 베텔게우스 +{% /card %} +``` + +Markdoc 파일에서 컴포넌트를 사용하는 방법에 대한 자세한 내용은 [Astro Markdoc 통합 문서](https://docs.astro.build/ko/guides/integrations-guide/markdoc/#컴포넌트-렌더링)를 참조하세요. + +## 내장 컴포넌트 + +Starlight는 일반적인 문서 사용 사례를 위한 내장 컴포넌트를 제공합니다. +이러한 컴포넌트는 MDX 파일의 `@astrojs/starlight/components` 패키지와 Markdoc 파일의 [Starlight Markdoc 프리셋](/ko/guides/authoring-content/#markdoc)에서 사용할 수 있습니다. + +사용 가능한 컴포넌트 목록과 사용 방법은 사이드바를 참조하세요. + +## Starlight 스타일과의 호환성 + +Starlight는 요소 사이에 여백을 추가하는 등 Markdown 콘텐츠에 기본 스타일을 적용합니다. +이러한 스타일이 컴포넌트의 모양과 충돌하는 경우 컴포넌트에 `not-content` 클래스를 추가하여 비활성화하세요. + +```astro 'class="not-content"' +--- +// src/components/Example.astro +--- + +<div class="not-content"> + <p>Starlight의 기본 콘텐츠 스타일링의 영향을 받지 않습니다.</p> +</div> +``` + +## 컴포넌트 속성 + +컴포넌트 자체에서 내보내지 않더라도 컴포넌트에서 허용하는 `Props`를 참조하려면 `astro/types`의 [`ComponentProps`](https://docs.astro.build/ko/guides/typescript/#componentprops-타입) 타입을 사용합니다. +이는 기존 컴포넌트를 래핑하거나 확장할 때 유용할 수 있습니다. + +다음 예시는 `ComponentProps`를 사용하여 Starlight의 내장 `Badge` 컴포넌트가 허용하는 속성의 타입을 가져옵니다: + +```astro +--- +// src/components/Example.astro +import type { ComponentProps } from 'astro/types'; +import { Badge } from '@astrojs/starlight/components'; + +type BadgeProps = ComponentProps<typeof Badge>; +--- +``` diff --git a/docs/src/content/docs/ko/environmental-impact.md b/docs/src/content/docs/ko/environmental-impact.md index df8f40244cd..cd682899247 100644 --- a/docs/src/content/docs/ko/environmental-impact.md +++ b/docs/src/content/docs/ko/environmental-impact.md @@ -3,19 +3,19 @@ title: 친환경 문서 description: Starlight가 어떻게 친환경 문서 사이트를 구축하고 탄소 배출량을 줄이는 데 도움이 되는지 알아보세요. --- -웹 산업이 기후에 미치는 영향에 대한 추정치는 [2%][sf] ~ [전 세계 탄소 배출량의 4%][bbc] 범위이며, 이는 항공 산업의 배출량과 비슷합니다. -웹 사이트의 생태학적 영향을 계산하는 데는 여러 복잡한 요소가 있지만 이 가이드에는 문서 사이트의 환경적 영향을 줄이기 위한 몇 가지 팁이 포함되어 있습니다. +웹 산업이 기후에 미치는 영향에 대한 추정치는 전 세계 탄소 배출량의 [2%][sf] ~ [4%][bbc] 범위이며, 이는 항공 산업의 배출량과 비슷합니다. +웹 사이트의 생태학적 영향을 계산하기 위한 여러 복잡한 요소가 존재하지만, 이 가이드는 문서 사이트의 환경적 영향을 줄이기 위한 몇 가지 팁을 포함합니다. 좋은 소식은 Starlight를 선택하는 것이 좋은 시작이라는 것입니다. -웹사이트 탄소 계산기에 따르면 이 사이트는 [테스트된 웹페이지의 99%보다 깨끗하며][sl-carbon] 페이지 방문당 0.01g의 CO2를 배출합니다. +Website Carbon Calculator에 따르면 이 사이트는 [테스트된 웹페이지의 98%보다 깨끗하며][sl-carbon] 페이지 방문당 0.01g의 CO₂를 배출합니다. ## 페이지 크기 웹페이지가 전송하는 데이터가 많을수록 더 많은 에너지 자원이 필요합니다. -2023년 4월, [HTTP 아카이브의 데이터][http]에 따르면 웹페이지 중앙값은 2,000KB 이상을 다운로드해야 했습니다. +2023년 4월, [HTTP Archive의 데이터][http]에 따르면 웹페이지 중앙값은 2,000KB 이상을 다운로드해야 했습니다. Starlight는 최대한 가벼운 페이지를 구축합니다. -예를 들어, 사용자는 첫 번째 방문 시 50KB 미만의 압축 데이터를 다운로드하게 됩니다. 이는 HTTP 아카이브 중앙값의 2.5%에 불과합니다. +예를 들어, 사용자는 첫 방문 시 50KB 미만의 압축 데이터를 다운로드하게 됩니다. 이는 HTTP Archive 중앙값의 2.5%에 불과합니다. 좋은 캐싱 전략을 사용하면 후속 탐색에서 10KB 정도만 다운로드할 수 있습니다. ### 이미지 @@ -25,8 +25,8 @@ Starlight는 Astro의 [최적화된 자산 지원][assets]을 사용하여 Markd ### UI 컴포넌트 -React 또는 Vue와 같은 UI 프레임워크로 구축된 컴포넌트는 페이지에 많은 양의 JavaScript를 쉽게 추가합니다. -Starlight는 Astro 기반으로 구축되었고, Astro 자체 컴포넌트는 [Astro Islands][islands] 덕분에 **기본적으로 클라이언트 측 JavaScript가 전혀 로드되지 않습니다**. +React 또는 Vue와 같은 UI 프레임워크로 구축된 컴포넌트는 페이지에 많은 양의 JavaScript를 추가합니다. +Starlight는 Astro 기반으로 구축되었고, Astro 자체 컴포넌트는 [Astro 아일랜드][islands] 덕분에 **기본적으로 클라이언트 측 JavaScript가 전혀 로드되지 않습니다**. ### 캐싱 @@ -34,8 +34,8 @@ Starlight는 Astro 기반으로 구축되었고, Astro 자체 컴포넌트는 [A 좋은 캐싱 전략은 콘텐츠가 변경될 때 새 콘텐츠를 최대한 빨리 얻을 수 있도록 하며, 변경되지 않은 동일한 콘텐츠를 무의미하게 반복해서 다운로드하는 것을 방지합니다. 캐싱을 구성하는 가장 일반적인 방법은 [`Cache-Control` HTTP 헤더][cache]를 사용하는 것입니다. -Starlight를 사용할 때 `/_astro/` 디렉토리의 모든 항목에 대해 긴 캐시 시간을 설정할 수 있습니다. -이 디렉토리에는 불필요한 다운로드를 줄여 영원히 안전하게 캐시할 수 있는 CSS, JavaScript 및 기타 번들 자산이 포함되어 있습니다. +Starlight를 사용할 때 `/_astro/` 디렉터리의 모든 항목에 대해 긴 캐시 시간을 설정할 수 있습니다. +이 디렉터리에는 불필요한 다운로드를 줄여 영원히 안전하게 캐시할 수 있는 CSS, JavaScript 및 기타 번들 자산이 포함되어 있습니다. ``` Cache-Control: public, max-age=604800, immutable @@ -58,8 +58,8 @@ Cache-Control: public, max-age=604800, immutable 웹 페이지가 구축되는 방식은 사용자 장치를 실행하는 데 필요한 전력에 영향을 미칠 수 있습니다. Starlight는 최소한의 JavaScript를 사용하여 사용자의 휴대폰, 태블릿 또는 컴퓨터가 페이지를 로드하고 렌더링하는 데 필요한 전력을 감소시킵니다. 분석 추적 스크립트나 동영상 삽입과 같은 JavaScript 중심 콘텐츠를 추가할 때 페이지의 전력 사용량이 증가할 수 있으므로 주의하세요. -분석이 필요한 경우 [Cabin][cabin], [Fathom][fathom] 또는 [Plausible][plausible]과 같은 경량 옵션을 선택하는 것이 좋습니다. -YouTube 및 Vimeo와 같은 동영상 삽입은 [상호 작용 시 동영상 로드][lazy-video]를 기다리면 개선될 수 있습니다. +분석이 필요한 경우 [Cabin][cabin], [Fathom][fathom] 또는 [Plausible][plausible]과 같은 가벼운 옵션을 선택하는 것이 좋습니다. +YouTube 및 Vimeo와 같은 동영상 삽입은 [상호 작용 시 동영상 로드][lazy-video]를 통해 개선될 수 있습니다. [`astro-embed`][embed]와 같은 패키지는 일반적인 서비스에 도움이 될 수 있습니다. :::tip[알고 계셨나요?] @@ -79,7 +79,7 @@ JavaScript를 분석하고 컴파일하는 것은 브라우저가 수행해야 ## 호스팅 웹 페이지가 호스팅되는 위치는 문서 사이트가 얼마나 친환경적인지에 큰 영향을 미칠 수 있습니다. -데이터 센터와 서버 팜은 높은 전력 소비와 물의 집중적 사용 등 생태학적으로 큰 영향을 미칠 수 있습니다. +데이터 센터와 서버 팜은 높은 전력 소비와 물의 집중적 사용 등으로 인해 생태학적으로 큰 영향을 미칠 수 있습니다. 재생 가능 에너지를 사용하는 호스트를 선택하면 사이트의 탄소 배출량이 줄어듭니다. [Green Web Directory][gwb]는 호스팅 회사를 찾는 데 도움이 되는 도구 중 하나입니다. @@ -90,31 +90,37 @@ JavaScript를 분석하고 컴파일하는 것은 브라우저가 수행해야 다른 문서 프레임워크와 어떻게 비교되는지 궁금하십니까? [Website Carbon Calculator][wcc]를 사용한 이러한 테스트는 서로 다른 도구로 작성된 유사한 페이지를 비교합니다. -| 프레임워크 | 페이지 방문당 CO₂ | -| --------------------------- | ----------------- | -| [Starlight][sl-carbon] | 0.01g | -| [VitePress][vp-carbon] | 0.05g | -| [Docus][dc-carbon] | 0.05g | -| [Sphinx][sx-carbon] | 0.07g | -| [MkDocs][mk-carbon] | 0.10g | -| [Nextra][nx-carbon] | 0.11g | -| [docsify][dy-carbon] | 0.11g | -| [Docusaurus][ds-carbon] | 0.24g | -| [Read the Docs][rtd-carbon] | 0.24g | -| [GitBook][gb-carbon] | 0.71g | - -<small>2023년 5월 14일에 수집된 데이터. 최신 수치를 보려면 링크를 클릭하세요.</small> +| 프레임워크 | 페이지 방문당 CO₂ | 등급 | +| --------------------------- | ----------------- | :--: | +| [Starlight][sl-carbon] | 0.01g | A+ | +| [Sphinx][sx-carbon] | 0.01g | A+ | +| [Read the Docs][rtd-carbon] | 0.03g | A+ | +| [VitePress][vp-carbon] | 0.04g | A | +| [docsify][dy-carbon] | 0.05g | A | +| [mdBook][md-carbon] | 0.05g | A | +| [Nextra][nx-carbon] | 0.05g | A | +| [MkDocs][mk-carbon] | 0.07g | A | +| [Fumadocs][fs-carbon] | 0.07g | A | +| [Docusaurus][ds-carbon] | 0.10g | B | +| [Docus][dc-carbon] | 0.11g | B | +| [GitBook][gb-carbon] | 0.42g | F | +| [Mintlify][mt-carbon] | 0.48g | F | + +<small>2025년 8월 7일에 수집된 데이터. 최신 수치를 보려면 링크를 클릭하세요.</small> [sl-carbon]: https://www.websitecarbon.com/website/starlight-astro-build-getting-started/ [vp-carbon]: https://www.websitecarbon.com/website/vitepress-dev-guide-what-is-vitepress/ -[dc-carbon]: https://www.websitecarbon.com/website/docus-dev-introduction-getting-started/ +[dc-carbon]: https://www.websitecarbon.com/website/docus-dev-en-getting-started-project-structure/ [sx-carbon]: https://www.websitecarbon.com/website/sphinx-doc-org-en-master-usage-quickstart-html/ [mk-carbon]: https://www.websitecarbon.com/website/mkdocs-org-getting-started/ +[md-carbon]: https://www.websitecarbon.com/website/rust-lang-github-io-mdbook/ [nx-carbon]: https://www.websitecarbon.com/website/nextra-site-docs-docs-theme-start/ +[fs-carbon]: https://www.websitecarbon.com/website/fumadocs-dev-docs-ui/ [dy-carbon]: https://www.websitecarbon.com/website/docsify-js-org/ [ds-carbon]: https://www.websitecarbon.com/website/docusaurus-io-docs/ [rtd-carbon]: https://www.websitecarbon.com/website/docs-readthedocs-io-en-stable-index-html/ -[gb-carbon]: https://www.websitecarbon.com/website/docs-gitbook-com/ +[gb-carbon]: https://www.websitecarbon.com/website/gitbook-com-docs/ +[mt-carbon]: https://www.websitecarbon.com/website/mintlify-com-docs-quickstart/ ## 더 많은 자료 @@ -136,6 +142,6 @@ JavaScript를 분석하고 컴파일하는 것은 브라우저가 수행해야 [sf]: https://www.sciencefocus.com/science/what-is-the-carbon-footprint-of-the-internet/ [bbc]: https://www.bbc.com/future/article/20200305-why-your-internet-habits-are-not-as-clean-as-you-think [http]: https://httparchive.org/reports/state-of-the-web -[assets]: https://docs.astro.build/ko/guides/assets/ +[assets]: https://docs.astro.build/ko/guides/images/ [islands]: https://docs.astro.build/ko/concepts/islands/ [wcc]: https://www.websitecarbon.com/ diff --git a/docs/src/content/docs/ko/getting-started.mdx b/docs/src/content/docs/ko/getting-started.mdx index 7e5ed1e4374..51b5b8e81aa 100644 --- a/docs/src/content/docs/ko/getting-started.mdx +++ b/docs/src/content/docs/ko/getting-started.mdx @@ -1,21 +1,26 @@ --- title: 시작하기 -description: Astro의 Starlight를 이용해 최신 문서 웹사이트를 만드는 방법을 배워보세요. +description: Astro가 제공하는 Starlight를 사용해 문서 사이트를 만드는 방법을 알아보세요. --- import { Tabs, TabItem } from '@astrojs/starlight/components'; -## 새 프로젝트 시작하기 +## 새 프로젝트 생성 -Starlight는 [Astro](https://astro.build) 프레임워크 위에 구축된 모든 기능을 갖춘 문서 테마입니다. +Starlight는 [Astro](https://astro.build) 프레임워크 위에 구축되었으며, 완전한 기능을 갖춘 문서 테마입니다. +이 가이드는 새 프로젝트를 시작하는 데 도움이 될 것입니다. +기존 Astro 프로젝트에 Starlight를 추가하려면 [수동 설정 지침](/ko/manual-setup/)을 참조하세요. -다음 명령을 사용하여 새로운 Astro + Starlight 프로젝트를 만들 수 있습니다. +## 빠른 시작 -<Tabs> +### 새 프로젝트 생성 + +터미널에서 다음 명령을 실행하여 새 Astro + Starlight 프로젝트를 생성합니다. + +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# npm을 사용해 새로운 프로젝트 생성 npm create astro@latest -- --template starlight ``` @@ -23,7 +28,6 @@ npm create astro@latest -- --template starlight <TabItem label="pnpm"> ```sh -# pnpm을 사용해 새로운 프로젝트 생성 pnpm create astro --template starlight ``` @@ -31,99 +35,109 @@ pnpm create astro --template starlight <TabItem label="Yarn"> ```sh -# yarn을 사용해 새로운 프로젝트 생성 yarn create astro --template starlight ``` </TabItem> </Tabs> -이렇게 하면 웹 사이트에 필요한 파일들과 설정을 갖춘 새로운 [프로젝트 디렉토리](/ko/guides/project-structure/) 가 생성됩니다. +이 명령은 필요한 파일과 구성을 모두 갖춘 새 [프로젝트 디렉터리](/ko/guides/project-structure/)를 생성합니다. -:::tip[시도해보기] -브라우저에서 Starlight 시작하기: -[StackBlitz에서 템플릿 열기](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). +:::tip[시도 해보기] +브라우저에서 Starlight 사용: +[StackBlitz에서 템플릿 열기](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics) ::: -## Starlight로 콘텐츠 생성하기 +### 개발 서버 시작 -Starlight는 새로운 콘텐츠를 추가하거나 기존 파일을 가져올 준비가 되어 있습니다! +로컬에서 작업할 때 [Astro의 개발 서버](https://docs.astro.build/ko/reference/cli-reference/#astro-dev)를 사용하면 작업을 미리 볼 수 있으며 변경 시 자동으로 브라우저를 새로 고칠 수 있습니다. -### 파일 형식 +프로젝트 디렉터리에서 다음 명령을 실행하여 개발 서버를 시작합니다. -Starlight에서는 Markdown 및 MDX를 이용해 콘텐츠를 생성할 수 있습니다. (실험적 기능인 [Astro Markdoc 통합](https://docs.astro.build/ko/guides/integrations-guide/markdoc/)을 설치하여 Markdoc을 사용할 수도 있습니다.) +<Tabs syncKey="pkg"> +<TabItem label="npm"> -### 페이지 추가 +```sh +npm run dev +``` -`src/content/docs/` 에 `.md` 또는 `.mdx` 파일을 추가하여 웹 사이트에 새로운 페이지를 추가할 수 있습니다. 파일을 구성하고 여러 경로 세그먼트를 생성하기 위해 하위 폴더를 추가하세요. +</TabItem> +<TabItem label="pnpm"> +```sh +pnpm dev ``` -src/content/docs/hello-world.md => your-site.com/hello-world -src/content/docs/guides/faq.md => your-site.com/guides/faq + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev ``` -### 타입 안정성을 갖춘 frontmatter +</TabItem> +</Tabs> -모든 Starlight 페이지는 페이지 표시 방법을 제어하기 위해 사용자가 원하는대로 변경 가능한 [공통 frontmatter 속성 세트](/ko/reference/frontmatter/)를 공유합니다. +그러면 로컬 미리보기의 URL이 포함된 메시지가 터미널에 기록됩니다. +사이트 탐색을 시작하려면 이 URL을 여세요. -```md ---- -title: 안녕하세요! -description: Starlight 기반 웹 사이트의 페이지입니다. ---- -``` +### 콘텐츠 추가 -중요한 것을 잊어버렸다면, Starlight가 알려줄 것입니다. +Starlight는 새로운 콘텐츠를 추가하거나 기존 파일을 가져올 준비가 되어 있습니다! -## Starlight 웹사이트 배포하기 +`src/content/docs/` 디렉터리에 Markdown 파일을 생성하여 사이트에 새 페이지를 추가하세요. -Starlight로 웹 사이트를 만들고 모든 설정을 완료한 후에는 웹 서버 또는 Netlify, Vercel, GitHub Pages 등 원하는 호스팅 플랫폼에 배포할 수 있습니다. +[“페이지”](/ko/guides/pages/) 가이드에서 MDX 및 Markdoc 파일에 대한 파일 기반 라우팅 및 지원에 대해 자세히 알아보세요. -[Astro 공식 문서에서 Astro 기반의 웹 사이트를 배포하는 방법에 대해 알아보세요.](https://docs.astro.build/ko/guides/deploy/) +### 다음 단계 + +- **구성:** [“Starlight 사용자 정의”](/ko/guides/customization/)에서 일반적인 옵션에 대해 알아보세요. +- **탐색:** ["사이드바 탐색"](/ko/guides/sidebar/) 가이드를 사용하여 사이드바를 설정하세요. +- **컴포넌트:** ["컴포넌트"](/ko/components/using-components/) 가이드에서 내장된 카드 컴포넌트, 탭 컴포넌트 등을 찾아보세요. +- **확장:** ["플러그인"](/ko/resources/plugins/) 및 ["테마"](/ko/resources/themes/) 카탈로그에서 커뮤니티 애드온을 살펴보세요. +- **배포:** Astro 문서의 [“사이트 배포”](https://docs.astro.build/ko/guides/deploy/) 가이드를 사용하여 작업을 게시하세요. ## Starlight 업데이트 :::tip -Starlight는 베타 소프트웨어이기 때문에 자주 업데이트되고 개선될 것입니다. Starlight를 정기적으로 업데이트하세요! +Starlight는 베타 소프트웨어이기 때문에 업데이트와 개선이 자주 이루어질 것입니다. +정기적으로 Starlight를 업데이트하세요! ::: -Starlight는 Astro 통합이며 `@astrojs/*` 통합처럼 업데이트됩니다. +Starlight는 Astro 통합입니다. 터미널에서 다음 명령을 실행하여 이 패키지와 다른 Astro 패키지를 업데이트할 수 있습니다. -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# npm으로 Starlight 업데이트 -npm install @astrojs/starlight@latest +npx @astrojs/upgrade ``` </TabItem> <TabItem label="pnpm"> ```sh -# pnpm으로 Starlight 업데이트 -pnpm upgrade @astrojs/starlight --latest +pnpm dlx @astrojs/upgrade ``` </TabItem> <TabItem label="Yarn"> ```sh -# yarn으로 Starlight 업데이트 -yarn upgrade @astrojs/starlight --latest +yarn dlx @astrojs/upgrade ``` </TabItem> </Tabs> -각 릴리스의 전체 변경 목록을 확인하기 위해 [Starlight 변경 로그](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md)에 방문하세요. +각 릴리스의 전체 변경 사항 목록은 [Starlight 변경 로그](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md)를 참조하세요. ## Starlight 문제 해결 -Starlight의 [프로젝트 구성](/ko/reference/configuration/) 및 [개별 페이지의 frontmatter](/ko/reference/frontmatter/)에 대한 정보는 모두 이 웹 사이트의 참조 섹션에서 확인할 수 있습니다. 이 페이지를 통해 Starlight 웹 사이트가 제대로 구성되어 작동하는지 확인하세요. - -콘텐츠 추가 및 Starlight 사이트 설정에 대한 도움말은 사이드바의 가이드 섹션에서 확인할 수 있습니다. +[프로젝트 구성](/ko/reference/configuration/) 및 [개별 페이지 프런트매터 구성](/ko/reference/frontmatter/) 참조 페이지를 사용하여 Starlight 사이트가 올바르게 구성되고 작동하는지 확인하세요. +콘텐츠를 추가하고 Starlight 사이트를 사용자 정의하는 데 도움이 필요하면 사이드바의 가이드를 참조하세요. -이 문서에서 답변을 얻을 수 없는 경우, [Astro 공식 문서](https://docs.astro.build/ko/)에 방문하여 완전한 Astro 공식 문서를 확인하세요. 당신의 질문에 대한 답변은 이 Starlight 테마 아래에서 Astro가 어떻게 작동하는지 이해함으로써 얻을 수 있을 것입니다. +이 문서에서 답변을 찾을 수 없다면 완전한 Astro 문서를 확인하기 위해 [Astro 공식 문서](https://docs.astro.build)를 방문하세요. +이 Starlight 테마에서 Astro가 어떻게 작동하는지 이해하는 것은 질문에 대한 해답이 될 것입니다. -[Github issues](https://github.com/withastro/starlight/issues)에서 Starlight의 알려진 문제를 확인할 수 있으며, 활발하고 친근한 커뮤니티인 [Astro Discord](https://astro.build/chat)에서 도음을 받을수도 있습니다! 현재 진행되고 있는 개발이나 다른 주제에 대해 논의하기 위해 `#support` 포럼에서 "starlight" 태그를 사용하여 질문을 게시하거나 `#starlight` 채널을 방문하세요. +[Github issues](https://github.com/withastro/starlight/issues)에서 Starlight의 알려진 문제를 확인할 수 있으며, 활발하고 친근한 커뮤니티인 [Astro Discord](https://astro.build/chat)에서 도음을 받을수도 있습니다! 현재 진행되고 있는 개발 및 기타 주제에 대해 논의하기 위해 `#support` 채널에서 "starlight" 태그를 사용하여 질문을 게시하거나 `#starlight` 채널을 방문하세요. diff --git a/docs/src/content/docs/ko/guides/authoring-content.md b/docs/src/content/docs/ko/guides/authoring-content.md deleted file mode 100644 index 6b002c04374..00000000000 --- a/docs/src/content/docs/ko/guides/authoring-content.md +++ /dev/null @@ -1,210 +0,0 @@ ---- -title: 마크다운으로 콘텐츠 작성 -description: Starlight가 지원하는 Markdown 구문의 개요입니다. ---- - -Starlight는 `.md` 파일에서 제목 및 설명과 같은 메타데이터를 정의하기 위해 [Markdown](https://daringfireball.net/projects/markdown/)의 모든 구문과 frontmatter [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f)을 지원합니다. - -해당 파일 형식을 사용하는 경우 Markdown 지원 및 사용법이 다를 수 있으므로 [MDX 문서](https://mdxjs.com/docs/what-is-mdx/#markdown) 또는 [Markdoc 문서](https://markdoc.dev/docs/syntax)를 확인하세요. - -## 인라인 스타일 - -텍스트는 **굵게**, _기울임꼴_ 또는 ~~취소선~~으로 표시할 수 있습니다. - -```md -텍스트는 **굵게**, _기울임꼴_ 또는 ~~취소선~~으로 표시할 수 있습니다. -``` - -[다른 페이지로 링크](/ko/getting-started)할 수 있습니다. - -```md -[다른 페이지로 링크](/ko/getting-started)할 수 있습니다. -``` - -백틱을 사용하여 `인라인 코드`를 강조 표시할 수 있습니다. - -```md -백틱을 사용하여 `인라인 코드`를 강조 표시할 수 있습니다. -``` - -## 이미지 - -Starlight의 이미지는 [Astro에 내장된 최적화된 자산 지원](https://docs.astro.build/ko/guides/assets/)을 사용합니다. - -Markdown 및 MDX는 스크린 리더 및 보조 기술에서 사용되는 대체 텍스트가 포함된 이미지를 표시하기 위한 Markdown 구문을 지원합니다. - -!["astro"라는 단어가 포함된 행성과 별 그림](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) - -```md -!["astro"라는 단어가 포함된 행성과 별 그림](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) -``` - -프로젝트 내 로컬 이미지 파일에 대한 상대 경로도 지원합니다. - -```md -// src/content/docs/page-1.md - -![우주에 있는 로켓](../../assets/images/rocket.svg) -``` - -## 제목 - -제목을 사용하여 콘텐츠를 구조화할 수 있습니다. Markdown의 제목은 줄 시작 부분에 `#` 개수로 나타냅니다. - -### Starlight에서 페이지 콘텐츠를 구성하는 방법 - -Starlight는 페이지 제목을 최상위 제목으로 사용하도록 구성되어 있으며 각 페이지 목차 상단에 "개요" 제목을 포함합니다. 각 페이지를 일반 단락 텍스트 콘텐츠로 시작하고 `<h2>`부터 아래로 페이지 제목을 사용하는 것이 좋습니다. - -```md ---- -title: Markdown 가이드 -description: Starlight에서 Markdown을 사용하는 방법 ---- - -이 페이지는 Starlight에서 Markdown을 사용하는 방법을 설명합니다. - -## 인라인 스타일 - -## 제목 -``` - -### 제목 링크 - -Markdown에서 제목을 사용하면 자동으로 링크가 제공되므로 페이지의 특정 섹션에 직접 연결할 수 있습니다. - -```md ---- -title: 내 콘텐츠 페이지 -description: Starlight에 내장된 링크를 사용하는 방법 ---- - -## 서론 - -[나의 결론](#결론)은 같은 페이지 하단에 링크될 수 있습니다. - -## 결론 - -`https://my-site.com/page1/#서론` 서론으로 바로 이동합니다. -``` - -레벨 2 (`<h2>`) 및 레벨 3 (`<h3>`) 제목이 페이지 목차에 자동으로 나타납니다. - -## 주석 - -주석은 "admonitions" 또는 "callouts" 라고도 하며, 페이지의 기본 콘텐츠 주변에 보조 정보를 표시하는 데 유용합니다. - -Starlight는 주석 렌더링을 위한 사용자 정의 Markdown 구문을 제공합니다. 주석 블록은 내용을 감싸기 위해 세 개의 콜론 `:::`을 사용하며 `note`, `tip`, `caution` 또는 `danger` 타입일 수 있습니다. - -다른 Markdown 콘텐츠를 주석 안에 중첩시킬 수도 있지만 짧고 간결한 콘텐츠 덩어리에 가장 적합합니다. - -### Note 주석 - -:::note - -Starlight는 [Astro](https://astro.build/)로 구축된 문서 웹사이트 툴킷입니다. 다음 명령으로 시작할 수 있습니다. - -```sh -npm create astro@latest -- --template starlight -``` - -::: - -````md -:::note -Starlight는 [Astro](https://astro.build/)로 구축된 문서 웹사이트 툴킷입니다. 다음 명령으로 시작할 수 있습니다. - -```sh -npm create astro@latest -- --template starlight -``` - -::: -```` - -### 사용자 정의 주석 제목 - -주석 타입 다음에 대괄호를 사용해 주석의 제목을 지정할 수 있습니다. `:::tip[알고 계셨나요?]` - -:::tip[알고 계셨나요?] - -Astro는 ["Islands Architecture"](https://docs.astro.build/ko/concepts/islands/)를 사용하여 더 빠른 웹사이트를 구축할 수 있도록 도와줍니다. -::: - -```md -:::tip[알고 계셨나요?] -Astro는 ["Islands Architecture"](https://docs.astro.build/ko/concepts/islands/)를 사용하여 더 빠른 웹사이트를 구축할 수 있도록 도와줍니다. -::: -``` - -### 더 많은 주석 타입 - -Caution과 Danger 주석은 실수하기 쉬운 세부 사항에 대해 사용자를 집중시키는 데 도움이 됩니다. 이러한 기능을 많이 사용하고 있다면, 문서화중인 내용을 다시 디자인하는 것이 좋습니다. - -:::caution -당신이 멋진 문서 사이트를 원하지 않는다면 [Starlight](../../)는 필요하지 않을 수도 있습니다. -::: - -:::danger -Starlight의 유용한 기능 덕분에 사용자의 생산성이 향상되고 제품을 더 쉽게 사용할 수 있습니다. - -- 쉬운 탐색 -- 사용자 구성 가능한 색상 테마 -- [i18n 지원](/ko/guides/i18n) - -::: - -```md -:::caution -당신이 멋진 문서 사이트를 원하지 않는다면 [Starlight](../../)는 필요하지 않을 수도 있습니다. -::: - -:::danger -Starlight의 유용한 기능 덕분에 사용자의 생산성이 향상되고 제품을 더 쉽게 사용할 수 있습니다. - -- 쉬운 탐색 -- 사용자 구성 가능한 색상 테마 -- [i18n 지원](/ko/guides/i18n) - -::: -``` - -## 인용 - -> 이것은 인용 구문입니다. 다른 사람의 말이나 문서를 인용할 때 자주 사용됩니다. -> -> 인용은 각 줄의 시작 부분에 `>`를 사용하여 나타낼 수 있습니다. - -```md -> 이것은 인용 구문입니다. 다른 사람의 말이나 문서를 인용할 때 자주 사용됩니다. -> -> 인용은 각 줄의 시작 부분에 `>`를 사용하여 나타낼 수 있습니다. -``` - -## 코드 블록 - -코드 블록은 시작과 끝 부분에 세 개의 백틱 <code>```</code>이 있는 블록으로 나타냅니다. 시작하는 백틱 뒤에 프로그래밍 언어를 명시할 수 있습니다. - -```js -// 구문 강조 기능이 있는 Javascript 코드입니다. -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` - -````md -```js -// 구문 강조 기능이 있는 Javascript 코드입니다. -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` -```` - -```md -한 줄의 긴 코드 블록은 줄바꿈되어서는 안됩니다. 너무 길면 가로로 스크롤해야 합니다. 이 줄은 이를 설명할 수 있을 만큼 길어야 합니다. -``` - -## 기타 일반적인 Markdown 기능 - -Starlight는 목록 및 테이블과 같은 다른 모든 Markdown 작성 구문을 지원합니다. 모든 Markdown 구문 요소에 대한 간략한 개요는 [Markdown Guide의 Markdown 치트 시트](https://www.markdownguide.org/cheat-sheet/)를 참조하세요. diff --git a/docs/src/content/docs/ko/guides/authoring-content.mdx b/docs/src/content/docs/ko/guides/authoring-content.mdx new file mode 100644 index 00000000000..9e8db071eb1 --- /dev/null +++ b/docs/src/content/docs/ko/guides/authoring-content.mdx @@ -0,0 +1,694 @@ +--- +title: Markdown으로 콘텐츠 작성 +description: Starlight가 지원하는 Markdown 구문의 개요입니다. +--- + +Starlight는 `.md` 파일에서 제목 및 설명과 같은 메타데이터를 정의하기 위해 [Markdown](https://daringfireball.net/projects/markdown/)의 모든 구문과 프론트매터 [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f)을 지원합니다. + +해당 파일 형식을 사용하는 경우 Markdown 지원 및 사용법이 다를 수 있으므로 [MDX 문서](https://mdxjs.com/docs/what-is-mdx/#markdown) 또는 [Markdoc 문서](https://markdoc.dev/docs/syntax)를 확인하세요. + +## 프런트매터 + +프런트매터의 값을 설정하여 Starlight의 개별 페이지를 사용자 정의할 수 있습니다. +프런트매터는 다음과 같이 파일 상단에 `---` 구분 기호를 사용하여 설정합니다. + +```md title="src/content/docs/example.md" +--- +title: 페이지 제목 +--- + +페이지의 콘텐츠는 두 번째 `---` 뒤에 옵니다. +``` + +모든 페이지에는 최소 하나의 `title`이 포함되어야 합니다. +사용 가능한 모든 필드를 확인하고 사용자 정의 필드를 추가하는 방법을 알아보기 위해 [프런트매터 참조](/ko/reference/frontmatter/)를 확인하세요. + +## 인라인 스타일 + +텍스트는 **굵게**, _기울임꼴_ 또는 ~~취소선~~으로 표시할 수 있습니다. + +```md +텍스트는 **굵게**, _기울임꼴_ 또는 ~~취소선~~으로 표시할 수 있습니다. +``` + +[다른 페이지로 링크](/ko/getting-started/)할 수 있습니다. + +```md +[다른 페이지로 링크](/ko/getting-started/)할 수 있습니다. +``` + +백틱을 사용하여 `인라인 코드`를 강조 표시할 수 있습니다. + +```md +백틱을 사용하여 `인라인 코드`를 강조 표시할 수 있습니다. +``` + +## 이미지 + +Starlight의 이미지는 [Astro에 내장된 최적화된 자산 지원](https://docs.astro.build/ko/guides/images/)을 사용합니다. + +Markdown 및 MDX는 스크린 리더 및 보조 기술에서 사용되는 대체 텍스트가 포함된 이미지를 표시하기 위한 Markdown 구문을 지원합니다. + +!["astro"라는 단어가 포함된 행성과 별 그림](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) + +```md +!["astro"라는 단어가 포함된 행성과 별 그림](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) +``` + +프로젝트 내 로컬 이미지 파일에 대한 상대 경로도 지원합니다. + +```md +// src/content/docs/page-1.md + +![우주에 있는 로켓](../../assets/images/rocket.svg) +``` + +## 제목 + +제목을 사용하여 콘텐츠를 구조화할 수 있습니다. Markdown의 제목은 줄 시작 부분에 `#` 개수로 나타냅니다. + +### Starlight에서 페이지 콘텐츠를 구성하는 방법 + +Starlight는 페이지 제목을 최상위 제목으로 사용하도록 구성되어 있으며 각 페이지 목차 상단에 "개요" 제목을 포함합니다. 각 페이지를 일반 단락 텍스트 콘텐츠로 시작하고 `<h2>`부터 아래로 페이지 제목을 사용하는 것이 좋습니다. + +```md +--- +title: Markdown 가이드 +description: Starlight에서 Markdown을 사용하는 방법 +--- + +이 페이지는 Starlight에서 Markdown을 사용하는 방법을 설명합니다. + +## 인라인 스타일 + +## 제목 +``` + +### 제목 링크 + +Markdown에서 제목을 사용하면 자동으로 링크가 제공되므로 페이지의 특정 섹션에 직접 연결할 수 있습니다. + +```md +--- +title: 내 콘텐츠 페이지 +description: Starlight에 내장된 링크를 사용하는 방법 +--- + +## 서론 + +[나의 결론](#결론)은 같은 페이지 하단에 링크될 수 있습니다. + +## 결론 + +`https://my-site.com/page1/#서론` 서론으로 바로 이동합니다. +``` + +레벨 2 (`<h2>`) 및 레벨 3 (`<h3>`) 제목이 페이지 목차에 자동으로 나타납니다. + +[Astro 공식 문서](https://docs.astro.build/ko/guides/markdown-content/#제목-id)에서 Astro가 제목의 `id`를 처리하는 방법에 대해 자세히 알아보세요. + +## 보조 내용 + +보조 내용은 "admonitions" 또는 "callouts" 라고도 하며, 페이지의 기본 콘텐츠 주변에 보조 정보를 표시하는 데 유용합니다. + +Starlight는 보조 내용 렌더링을 위한 사용자 정의 Markdown 구문을 제공합니다. 보조 내용 블록은 내용을 감싸기 위해 세 개의 콜론 `:::`을 사용하며 `note`, `tip`, `caution` 또는 `danger` 타입일 수 있습니다. + +다른 Markdown 콘텐츠를 보조 내용 안에 중첩시킬 수도 있지만 짧고 간결한 콘텐츠 덩어리에 가장 적합합니다. + +### Note 보조 내용 + +:::note + +Starlight는 [Astro](https://astro.build/)로 구축된 문서 웹사이트 툴킷입니다. 다음 명령으로 시작할 수 있습니다. + +```sh +npm create astro@latest -- --template starlight +``` + +::: + +````md +:::note +Starlight는 [Astro](https://astro.build/)로 구축된 문서 웹사이트 툴킷입니다. 다음 명령으로 시작할 수 있습니다. + +```sh +npm create astro@latest -- --template starlight +``` + +::: +```` + +### 사용자 정의 보조 내용 제목 + +보조 내용 타입 다음에 대괄호를 사용해 보조 내용의 제목을 지정할 수 있습니다. `:::tip[알고 계셨나요?]` + +:::tip[알고 계셨나요?] + +Astro는 ["아일랜드 아키텍처"](https://docs.astro.build/ko/concepts/islands/)를 사용하여 더 빠른 웹사이트를 구축할 수 있도록 도와줍니다. +::: + +```md +:::tip[알고 계셨나요?] +Astro는 ["아일랜드 아키텍처"](https://docs.astro.build/ko/concepts/islands/)를 사용하여 더 빠른 웹사이트를 구축할 수 있도록 도와줍니다. +::: +``` + +### 사용자 정의 보조 내용 아이콘 + +보조 내용 유형 또는 [사용자 정의 제목](#사용자-정의-보조-내용-제목) 뒤에 오는 중괄호에 보조 내용에 대한 사용자 정의 아이콘을 지정할 수 있습니다. (예: `:::tip{icon="heart"}` 또는 `:::tip[알고 계셨나요?]{icon="heart"}`). +아이콘 이름은 [Starlight의 기본 제공 아이콘 중 하나](/ko/reference/icons/#모든-아이콘)의 이름으로 설정해야 합니다. + +:::tip{icon="heart"} +Astro는 ["아일랜드 아키텍처"](https://docs.astro.build/ko/concepts/islands/)를 사용하여 더 빠른 웹사이트를 구축할 수 있도록 도와줍니다. +::: + +```md +:::tip{icon="heart"} +Astro는 ["아일랜드 아키텍처"](https://docs.astro.build/ko/concepts/islands/)를 사용하여 더 빠른 웹사이트를 구축할 수 있도록 도와줍니다. +::: +``` + +### 더 많은 보조 내용 타입 + +Caution과 Danger 보조 내용은 실수하기 쉬운 세부 사항에 대해 사용자를 집중시키는 데 도움이 됩니다. 이러한 기능을 많이 사용하고 있다면, 문서화중인 내용을 다시 디자인하는 것이 좋습니다. + +:::caution +당신이 멋진 문서 사이트를 원하지 않는다면 [Starlight](/ko/)는 필요하지 않을 수도 있습니다. +::: + +:::danger +Starlight의 유용한 기능 덕분에 사용자의 생산성이 향상되고 제품을 더 쉽게 사용할 수 있습니다. + +- 쉬운 탐색 +- 사용자 구성 가능한 색상 테마 +- [i18n 지원](/ko/guides/i18n/) + +::: + +```md +:::caution +당신이 멋진 문서 사이트를 원하지 않는다면 [Starlight](/ko/)는 필요하지 않을 수도 있습니다. +::: + +:::danger +Starlight의 유용한 기능 덕분에 사용자의 생산성이 향상되고 제품을 더 쉽게 사용할 수 있습니다. + +- 쉬운 탐색 +- 사용자 구성 가능한 색상 테마 +- [i18n 지원](/ko/guides/i18n/) + +::: +``` + +## 인용 + +> 이것은 인용 구문입니다. 다른 사람의 말이나 문서를 인용할 때 자주 사용됩니다. +> +> 인용은 각 줄의 시작 부분에 `>`를 사용하여 나타낼 수 있습니다. + +```md +> 이것은 인용 구문입니다. 다른 사람의 말이나 문서를 인용할 때 자주 사용됩니다. +> +> 인용은 각 줄의 시작 부분에 `>`를 사용하여 나타낼 수 있습니다. +``` + +## 코드 블록 + +코드 블록은 시작과 끝 부분에 세 개의 백틱 <code>```</code>이 있는 블록으로 나타냅니다. 시작하는 백틱 뒤에 프로그래밍 언어를 명시할 수 있습니다. + +```js +// 구문 강조 기능이 있는 Javascript 코드입니다. +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` + +````md +```js +// 구문 강조 기능이 있는 Javascript 코드입니다. +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` +```` + +### Expressive Code 기능 + +Starlight는 [Expressive Code](https://expressive-code.com/)를 사용하여 코드 블록의 형식 지정 가능성을 확장합니다. +기본적으로 Expressive Code의 텍스트 마커와 창 프레임 플러그인은 활성화되어 있습니다. +코드 블록 렌더링은 Starlight의 [`expressiveCode` 구성 옵션](/ko/reference/configuration/#expressivecode)을 사용하여 구성할 수 있습니다. + +#### 텍스트 마커 + +코드 블록의 시작 줄에 [Expressive Code 텍스트 마커](https://expressive-code.com/key-features/text-markers/)를 사용하여 코드 블록의 특정 줄이나 부분을 강조 표시할 수 있습니다. 전체 줄을 강조 표시하려면 중괄호(`{ }`)를 사용하고, 텍스트 문자열을 강조 표시하려면 따옴표를 사용하세요. + +세 가지 강조 스타일이 있습니다. 코드에 주의를 환기시키는 중립, 삽입된 코드를 나타내는 녹색, 삭제된 코드를 나타내는 빨간색입니다. +텍스트와 전체 줄 모두 기본 마커를 사용하거나 `ins=` 및 `del=`과 함께 표시하여 원하는 강조 표시를 생성할 수 있습니다. + +Expressive Code는 코드 샘플의 시각적 모습을 사용자 정의하기 위한 여러 옵션을 제공합니다. 이들 중 다수는 예시적인 코드 샘플을 위해 결합될 수 있습니다. 사용 가능한 광범위한 옵션을 보려면 [Expressive Code 문서](https://expressive-code.com/key-features/text-markers/#configuration)를 살펴보세요. 가장 일반적인 예시 중 일부는 다음과 같습니다. + +- [`{ }` 마커를 사용하여 전체 줄과 줄 범위를 표시합니다.](https://expressive-code.com/key-features/text-markers/#marking-full-lines--line-ranges) + + ```js {2-3} + function demo() { + // 이 줄(#2)과 다음 줄이 강조 표시됩니다. + return '이 줄은 이 스니펫의 라인 #3입니다.'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js {2-3} + function demo() { + // 이 줄(#2)과 다음 줄이 강조 표시됩니다. + return '이 줄은 이 스니펫의 라인 #3입니다.'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="{2-3}" %} + function demo() { + // 이 줄(#2)과 다음 줄이 강조 표시됩니다. + return '이 줄은 이 스니펫의 라인 #3입니다.'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [`" "` 마커 또는 정규 표현식을 사용하여 텍스트 선택 항목을 표시합니다.](https://expressive-code.com/key-features/text-markers/#marking-individual-text-inside-lines) + + ```js "개별 용어" /정규.*지원됩니다./ + // 개별 용어도 강조 표시할 수 있습니다. + function demo() { + return '정규 표현식도 지원됩니다.'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "개별 용어" /정규.*지원됩니다./ + // 개별 용어도 강조 표시할 수 있습니다. + function demo() { + return '정규 표현식도 지원됩니다.'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'개별 용어' /정규.*지원됩니다./" %} + // 개별 용어도 강조 표시할 수 있습니다. + function demo() { + return '정규 표현식도 지원됩니다.'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [`ins` 또는 `del`을 사용하여 텍스트나 줄을 삽입 또는 삭제된 것으로 표시합니다.](https://expressive-code.com/key-features/text-markers/#selecting-inline-marker-types-mark-ins-del) + + ```js "return true;" ins="삽입" del="삭제된" + function demo() { + console.log('삽입 및 삭제된 마커 타입입니다.'); + // return 문은 기본 마커 타입을 사용합니다. + return true; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "return true;" ins="삽입" del="삭제된" + function demo() { + console.log('삽입 및 삭제된 마커 타입입니다.'); + // return 문은 기본 마커 타입을 사용합니다. + return true; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'return true;' ins='삽입' del='삭제된'" %} + function demo() { + console.log('삽입 및 삭제된 마커 타입입니다.'); + // return 문은 기본 마커 타입을 사용합니다. + return true; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [구문 강조와 `diff` 유사 구문을 결합합니다.](https://expressive-code.com/key-features/text-markers/#combining-syntax-highlighting-with-diff-like-syntax) + + ```diff lang="js" + function thisIsJavaScript() { + // 이 전체 블록은 JavaScript로 강조표시됩니다. + // 그리고 여전히 diff 마커를 추가할 수 있습니다! + - console.log('제거할 이전 코드') + + console.log('새롭고 빛나는 코드!') + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```diff lang="js" + function thisIsJavaScript() { + // 이 전체 블록은 JavaScript로 강조표시됩니다. + // 그리고 여전히 diff 마커를 추가할 수 있습니다! + - console.log('제거할 이전 코드') + + console.log('새롭고 빛나는 코드!') + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```diff {% meta="lang='js'" %} + function thisIsJavaScript() { + // 이 전체 블록은 JavaScript로 강조표시됩니다. + // 그리고 여전히 diff 마커를 추가할 수 있습니다! + - console.log('제거할 이전 코드') + + console.log('새롭고 빛나는 코드!') + } + ``` + ```` + + </TabItem> + + </Tabs> + +#### Frames 및 titles + +코드 블록은 창과 같은 프레임 내부에서 렌더링될 수 있습니다. +터미널 창처럼 보이는 프레임은 쉘 스크립팅 언어(예: `bash` 또는 `sh`)에 사용됩니다. +title이 포함된 다른 언어는 코드 편집기 스타일의 프레임에 표시됩니다. + +코드 블록의 선택적 제목은 코드 블록을 여는 백틱 및 언어 식별자 뒤에 `title="..."` 속성을 추가하거나 코드 첫 번째 줄에 파일 이름 주석을 추가하여 설정할 수 있습니다. + +- [설명과 함께 파일 이름 탭 추가](https://expressive-code.com/key-features/frames/#code-editor-frames) + + ```js + // my-test-file.js + console.log('안녕하세요!'); + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js + // my-test-file.js + console.log('안녕하세요!'); + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````md + ```js + // my-test-file.js + console.log('안녕하세요!'); + ``` + ```` + + </TabItem> + + </Tabs> + +- [터미널 창에 제목 추가](https://expressive-code.com/key-features/frames/#terminal-frames) + + ```bash title="의존성 설치 중…" + npm install + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash title="의존성 설치 중…" + npm install + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% title="의존성 설치 중…" %} + npm install + ``` + ```` + + </TabItem> + + </Tabs> + +- [`frame="none"`으로 창 프레임 비활성화](https://expressive-code.com/key-features/frames/#overriding-frame-types) + + ```bash frame="none" + echo "bash 언어를 사용해도 터미널로 렌더링되지 않습니다." + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash frame="none" + echo "bash 언어를 사용해도 터미널로 렌더링되지 않습니다." + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% frame="none" %} + echo "bash 언어를 사용해도 터미널로 렌더링되지 않습니다." + ``` + ```` + + </TabItem> + + </Tabs> + +## Details + +Details (“disclosures” 또는 “accordions”이라고도 함)는 즉시 관련이 없는 콘텐츠를 숨기는 데 유용합니다. +사용자는 짧은 요약을 클릭하여 전체 콘텐츠를 확장하고 볼 수 있습니다. + +Markdown 콘텐츠에서 표준 HTML인 [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details) 및 [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary) 요소를 사용하여 공개 위젯을 만듭니다. + +`<details>` 요소에 다른 Markdown 구문을 중첩할 수 있습니다. + +<details> +<summary>안드로메다 별자리는 언제 어디서 가장 잘 보입니까?</summary> + +[안드로메다 별자리](<https://en.wikipedia.org/wiki/Andromeda_(constellation)>)는 11월 밤하늘의 위도 `+90°`에서 `-40°` 사이에서 가장 잘 보입니다. + +</details> + +```md +<details> +<summary>안드로메다 별자리는 언제 어디서 가장 잘 보입니까?</summary> + +[안드로메다 별자리](<https://en.wikipedia.org/wiki/Andromeda_(constellation)>)는 11월 밤하늘의 위도 `+90°`에서 `-40°` 사이에서 가장 잘 보입니다. + +</details> +``` + +## Footnotes + +[각주(Footnotes)](https://www.markdownguide.org/extended-syntax/#footnotes)는 콘텐츠 흐름을 방해하지 않고 간략한 참조나 설명을 추가하는 데 유용합니다. 각주는 페이지 하단에 모아둔 참조 텍스트로 이동하는 번호가 매겨진 위첨자 링크로 나타납니다. + +대괄호와 캐럿, 숫자 참조를 사용하여 각주를 정의합니다. + +```md +여기에 각주[^1]가 있고 그 뒤에 추가 텍스트가 있습니다. + +[^1]: 나의 참조 +``` + +## 기타 일반적인 Markdown 기능 + +Starlight는 목록 및 테이블과 같은 다른 모든 Markdown 작성 구문을 지원합니다. 모든 Markdown 구문 요소에 대한 간략한 개요는 [Markdown Guide의 Markdown 치트 시트](https://www.markdownguide.org/cheat-sheet/)를 참조하세요. + +## 고급 Markdown 및 MDX 구성 + +Starlight는 remark 및 rehype를 기반으로 구축된 Astro의 Markdown 및 MDX 렌더러를 사용합니다. Astro 구성 파일에 `remarkPlugins` 또는 `rehypePlugins`를 추가하여 사용자 정의 구문 및 동작에 대한 지원을 추가할 수 있습니다. 자세한 내용은 Astro 문서의 [Markdown 플러그인](https://docs.astro.build/ko/guides/markdown-content/#markdown-플러그인)을 참조하세요. + +## Markdoc + +Starlight는 실험적인 [Astro Markdoc 통합](https://docs.astro.build/ko/guides/integrations-guide/markdoc/)과 Starlight Markdoc 프리셋을 사용하여 Markdoc으로 콘텐츠를 작성할 수 있도록 지원합니다. + +### Markdoc으로 새 프로젝트 만들기 + +`create astro`를 사용하여 사전 구성된 Markdoc이 포함된 새 Starlight 프로젝트를 시작합니다: + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight/markdoc +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight/markdoc +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight/markdoc +``` + +</TabItem> +</Tabs> + +### 기존 프로젝트에 Markdoc 추가하기 + +이미 Starlight 사이트가 있고 Markdoc을 추가하려는 경우 다음 단계를 따르세요. + +<Steps> + +1. Astro의 Markdoc 통합을 추가하세요: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npx astro add markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm astro add markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn astro add markdoc + ``` + + </TabItem> + + </Tabs> + +2. Starlight Markdoc 프리셋을 설치합니다: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-markdoc + ``` + + </TabItem> + + </Tabs> + +3. `markdoc.config.mjs`에 Markdoc 구성 파일을 만들고 Starlight Markdoc 프리셋을 사용하세요: + + ```js + import { defineMarkdocConfig } from '@astrojs/markdoc/config'; + import starlightMarkdoc from '@astrojs/starlight-markdoc'; + + export default defineMarkdocConfig({ + extends: [starlightMarkdoc()], + }); + ``` + +</Steps> + +Markdoc 구문 및 기능에 대한 자세한 내용은 [Markdoc 문서](https://markdoc.dev/docs/syntax) 또는 [Astro Markdoc 통합 가이드](https://docs.astro.build/ko/guides/integrations-guide/markdoc/)를 참조하세요. + +### Markdoc 프리셋 구성 + +다음은 `starlightMarkdoc()` 프리셋이 허용하는 구성 옵션입니다. + +#### `headingLinks` + +**타입:** `boolean` +**기본값:** `true` + +제목이 클릭 가능한 앵커 링크와 함께 렌더링될지 여부를 제어합니다. Markdown 및 MDX 파일에 적용되는 [`markdown.headingLinks`](/ko/reference/configuration/#markdown) 옵션과 동일합니다. + +```js "headingLinks: false" +export default defineMarkdocConfig({ + // 기본 제목 앵커 링크 지원을 비활성화합니다. + extends: [starlightMarkdoc({ headingLinks: false })], +}); +``` diff --git a/docs/src/content/docs/ko/guides/components.mdx b/docs/src/content/docs/ko/guides/components.mdx deleted file mode 100644 index dadb0b2952b..00000000000 --- a/docs/src/content/docs/ko/guides/components.mdx +++ /dev/null @@ -1,196 +0,0 @@ ---- -title: 컴포넌트 -description: Starlight를 이용해 MDX에서 컴포넌트 사용하기. ---- - -컴포넌트를 사용하면 쉽고 일관되게 UI 조각이나 스타일을 재사용할 수 있습니다. -링크 카드나 YouTube 삽입 등을 예로 들 수 있습니다. -Starlight는 [MDX](https://mdxjs.com/) 파일에서 컴포넌트 사용을 지원하며 사용할 수 있는 몇 가지 공통 컴포넌트를 제공합니다. - -[Astro 문서에서 컴포넌트 구축에 대해 자세히 알아보세요](https://docs.astro.build/ko/core-concepts/astro-components/). - -## 컴포넌트 사용 - -MDX 파일에서 컴포넌트를 가져온 다음 JSX 태그로 렌더링하여 사용할 수 있습니다. -이는 HTML 태그처럼 보이지만 `import` 문에 있는 이름과 일치하는 대문자로 시작합니다. - -```mdx ---- -# src/content/docs/index.mdx -title: 내 문서에 오신 것을 환영합니다 ---- - -import SomeComponent from '../../../components/SomeComponent.astro'; -import AnotherComponent from '../../../components/AnotherComponent.astro'; - -<SomeComponent prop="어떤 값" /> - -<AnotherComponent> - 컴포넌트에는 **중첩된 콘텐츠**가 포함될 수도 있습니다. -</AnotherComponent> -``` - -Starlight는 Astro로 구동되므로 [지원되는 UI 프레임워크(React, Preact, Svelte, Vue, Solid, Lit 및 Alpine)](https://docs.astro.build/ko/core-concepts/framework-components/)로 빌드된 컴포넌트를 MDX 파일에 추가할 수 있습니다. -Astro 문서에서 [MDX에서 컴포넌트 사용](https://docs.astro.build/ko/guides/markdown-content/#using-comComponents-in-mdx)에 대해 자세히 알아보세요. - -### Starlight 스타일과의 호환성 - -Starlight는 요소 사이에 여백을 추가하는 등 Markdown 콘텐츠에 기본 스타일을 적용합니다. -이러한 스타일이 컴포넌트의 모양과 충돌하는 경우 컴포넌트에 `not-content` 클래스를 추가하여 비활성화하세요. - -```astro ---- -// src/components/Example.astro ---- - -<div class="not-content"> - <p>Starlight의 기본 콘텐츠 스타일에 영향을 받지 않습니다.</p> -</div> -``` - -## 내장된 컴포넌트 - -Starlight는 일반적인 문서 사용 사례를 위한 몇 가지 내장 컴포넌트를 제공합니다. -이러한 컴포넌트는 `@astrojs/starlight/components` 패키지를 통해 사용할 수 있습니다. - -### 탭 - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -`<Tabs>` 및 `<TabItem>` 컴포넌트를 사용하여 탭 인터페이스를 표시할 수 있습니다. -각 `<TabItem>`은 사용자에게 보여줄 `label`을 반드시 포함해야합니다. - -```mdx -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -<Tabs> - <TabItem label="별">시리우스, 베가, 베텔게우스</TabItem> - <TabItem label="달">이오, 유로파, 가니메데</TabItem> -</Tabs> -``` - -위 코드는 페이지에 아래와 같은 탭을 생성합니다. - -<Tabs> - <TabItem label="별">시리우스, 베가, 베텔게우스</TabItem> - <TabItem label="달">이오, 유로파, 가니메데</TabItem> -</Tabs> - -### 카드 - -import { Card, CardGrid } from '@astrojs/starlight/components'; - -`<Card>` 컴포넌트를 사용하면 Starlight 스타일의 상자에 콘텐츠를 표시할 수 있습니다. -공간이 충분할 때 카드를 나란히 표시하려면 `<CardGrid>` 컴포넌트로 여러 카드를 감싸세요. - -`<Card>` 컴포넌트에는 `title` 속성이 반드시 필요하며 선택적으로 [Starlight 내장 아이콘 중 하나](#모든-아이콘)의 이름으로 설정된 `icon` 속성을 포함할 수 있습니다. - -```mdx -import { Card, CardGrid } from '@astrojs/starlight/components'; - -<Card title="확인">강조하고 싶은 흥미로운 콘텐츠.</Card> - -<CardGrid> - <Card title="별" icon="star"> - 시리우스, 베가, 베텔게우스 - </Card> - <Card title="달" icon="moon"> - 이오, 유로파, 가니메데 - </Card> -</CardGrid> -``` - -위 코드는 페이지에 아래와 같은 요소들을 생성합니다. - -<Card title="확인">강조하고 싶은 흥미로운 콘텐츠.</Card> - -<CardGrid> - <Card title="별" icon="star"> - 시리우스, 베가, 베텔게우스 - </Card> - <Card title="달" icon="moon"> - 이오, 유로파, 가니메데 - </Card> -</CardGrid> - -:::tip - -홈 페이지에서 프로젝트의 주요 기능을 보여주기 위해 카드 그리드를 사용하세요. -카드의 두 번째 열을 수직으로 이동시켜 시각적 흥미를 더하려면 `stagger` 속성을 추가하세요. - -```astro -<CardGrid stagger> - <!-- 카드 --> -</CardGrid> -``` - -::: - -### 링크 카드 - -다른 페이지로 이동하는 눈에 띄는 링크를 만들기 위해 `<LinkCard>` 컴포넌트를 사용하세요. - -`<LinkCard>` 컴포넌트에는 `title`과 [`href`](https://developer.mozilla.org/ko/docs/Web/HTML/Element/a#attr-href) 속성이 필요합니다. 짧은 `description`이나 `target`과 같은 기타 링크 속성을 선택적으로 포함할 수 있습니다. - -공간이 충분할 때, 카드를 나란히 표시하기 위해 여러 `<LinkCard>` 컴포넌트를 `<CardGrid>`에 그룹화하세요. - -```mdx -import { LinkCard, CardGrid } from '@astrojs/starlight/components'; - -<LinkCard - title="Starlight 사용자 정의" - description="사용자 정의 스타일, 글꼴 등을 사용하여 나만의 Starlight 사이트를 만드는 방법을 알아보세요." - href="/ko/guides/customization/" -/> - -<CardGrid> - <LinkCard - title="마크다운으로 콘텐츠 작성" - href="/ko/guides/authoring-content/" - /> - <LinkCard title="컴포넌트" href="/ko/guides/components/" /> -</CardGrid> -``` - -위 코드는 페이지에 아래와 같은 요소들을 생성합니다. - -import { LinkCard } from '@astrojs/starlight/components'; - -<LinkCard - title="Starlight 사용자 정의" - description="사용자 정의 스타일, 글꼴 등을 사용하여 나만의 Starlight 사이트를 만드는 방법을 알아보세요." - href="/ko/guides/customization/" -/> - -<CardGrid> - <LinkCard - title="마크다운으로 콘텐츠 작성" - href="/ko/guides/authoring-content/" - /> - <LinkCard title="컴포넌트" href="/ko/guides/components/" /> -</CardGrid> - -### 아이콘 - -import { Icon } from '@astrojs/starlight/components'; -import IconsList from '../../../../components/icons-list.astro'; - -Starlight는 `<Icon>` 컴포넌트를 사용하여 콘텐츠에 표시할 수 있는 공통 아이콘 세트를 제공합니다. - -각 `<Icon>` 컴포넌트에는 [`name`](#모든-아이콘) 속성이 필요하며 선택적으로 `label`, `size` 및 `color` 속성을 포함할 수 있습니다. - -```mdx -import { Icon } from '@astrojs/starlight/components'; - -<Icon name="star" color="goldenrod" size="2rem" /> -``` - -위 코드는 페이지에 아래와 같은 아이콘을 생성합니다. - -<Icon name="star" color="goldenrod" size="2rem" /> - -#### 모든 아이콘 - -사용 가능한 모든 아이콘 목록이 관련 이름과 함께 아래에 표시됩니다. 아이콘을 클릭하면 해당 아이콘 컴포넌트의 코드를 복사할 수 있습니다. - -<IconsList /> diff --git a/docs/src/content/docs/ko/guides/css-and-tailwind.mdx b/docs/src/content/docs/ko/guides/css-and-tailwind.mdx index c2acd1913dd..515102fb6d4 100644 --- a/docs/src/content/docs/ko/guides/css-and-tailwind.mdx +++ b/docs/src/content/docs/ko/guides/css-and-tailwind.mdx @@ -3,13 +3,19 @@ title: CSS & 스타일링 description: 맞춤형 CSS로 Starlight 사이트의 스타일을 지정하거나 Tailwind CSS와 통합하는 방법을 알아보세요. --- +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + 사용자 정의 CSS 파일을 사용하여 Starlight 사이트의 스타일을 지정하거나 Starlight Tailwind 플러그인을 사용할 수 있습니다. +사이트의 기본 스타일을 빠르게 변경하려면 [커뮤니티 테마](/ko/resources/themes/)를 확인하세요. + ## 사용자 정의 CSS 스타일 Starlight의 기본 스타일을 수정하거나 확장하기 위한 CSS 파일을 제공하여 사이트에 적용된 스타일을 원하는대로 변경할 수 있습니다. -1. `src/` 디렉토리에 CSS 파일을 추가합니다. 예를 들어, 아래 코드를 통해 페이지 제목을 더 넓게 만들고, 더 큰 텍스트를 사용할 수 있습니다. +<Steps> + +1. `src/` 디렉터리에 CSS 파일을 추가합니다. 예를 들어, 아래 코드를 통해 페이지 제목을 더 넓게 만들고, 더 큰 텍스트를 사용할 수 있습니다. ```css /* src/styles/custom.css */ @@ -19,9 +25,9 @@ Starlight의 기본 스타일을 수정하거나 확장하기 위한 CSS 파일 } ``` -2. `astro.config.mjs`에 있는 Starlight의 `customCss` 배열에 CSS 파일 경로를 추가하세요. +2. `astro.config.mjs` 파일에 있는 Starlight의 `customCss` 배열에 CSS 파일 경로를 추가하세요. - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -31,34 +37,48 @@ Starlight의 기본 스타일을 수정하거나 확장하기 위한 CSS 파일 starlight({ title: '사용자 정의 CSS를 사용한 문서', customCss: [ - // 사용자 정의 CSS 파일의 상대 경로 - './src/styles/custom.css', + + // 사용자 정의 CSS 파일의 상대 경로 + + './src/styles/custom.css', ], }), ], }); ``` +</Steps> + 사이트를 스타일링하기 위해 Starlight에서 사용되는 모든 CSS 속성을 [`props.css` 파일](https://github.com/withastro/starlight/blob/main/packages/starlight/style/props.css)에서 확인할 수 있습니다. +### 캐스케이드 레이어 + +Starlight는 스타일 순서를 관리하기 위해 내부적으로 [캐스케이드 레이어](https://developer.mozilla.org/ko/docs/Learn_web_development/Core/Styling_basics/Cascade_layers)를 사용합니다. 이를 통해 예측 가능한 CSS 순서를 보장하고 더 간단한 재정의를 할 수 있습니다. +레이어가 지정되지 않은 사용자 정의 CSS는 기본 Starlight 스타일을 재정의합니다. + +캐스케이드 레이어를 사용하고 있다면, 사용자 정의 CSS에서 [`@layer`](https://developer.mozilla.org/ko/docs/Web/CSS/@layer)를 사용하여 `starlight` 레이어의 스타일을 기준으로 서로 다른 레이어의 우선순위를 정의할 수 있습니다. + +```css "starlight" +/* src/styles/custom.css */ +@layer my-reset, starlight, my-overrides; +``` + +위 예시는 `my-reset`이라는 사용자 정의 레이어를 정의하며, 이는 모든 Starlight 레이어보다 먼저 적용됩니다. 또 다른 레이어인 `my-overrides`는 모든 Starlight 레이어 이후에 적용됩니다. `my-overrides` 레이어의 모든 스타일은 Starlight의 스타일보다 우선 적용되지만, Starlight는 여전히 `my-reset` 레이어에 설정된 스타일을 변경할 수 있습니다. + ## Tailwind CSS -Astro 프로젝트의 Tailwind CSS 지원은 [Astro Tailwind 통합](https://docs.astro.build/ko/guides/integrations-guide/tailwind/)을 통해 제공됩니다. -Starlight는 Starlight 스타일과 호환되도록 Tailwind를 구성하는 데 도움이 되는 보완 Tailwind 플러그인을 제공합니다. +Astro 프로젝트의 Tailwind CSS v4 지원은 [Tailwind Vite 플러그인](https://tailwindcss.com/docs/installation/using-vite)을 통해 제공됩니다. +Starlight는 Starlight 스타일과 호환되도록 Tailwind를 구성하는 데 도움이 되는 보완 CSS를 제공합니다. -Starlight Tailwind 플러그인은 다음 구성을 적용합니다. +Starlight Tailwind CSS는 다음 구성을 적용합니다. - Starlight의 다크 모드와 작동하도록 Tailwind의 `dark:` 변형을 구성합니다. - Starlight UI에서 Tailwind [테마 색상 및 글꼴](#tailwind로-starlight-스타일링하기)을 사용합니다. -- Tailwind의 [Preflight](https://tailwindcss.com/docs/preflight) 초기화 스타일을 비활성화하는 동시에 Tailwind의 테두리 유틸리티 클래스에 필요한 Preflight의 필수 부분을 선택적으로 복원합니다. +- Tailwind Preflight 리셋 스타일의 필수적인 부분을 복원합니다. ### Tailwind가 포함된 새 프로젝트 만들기 -import { Tabs, TabItem } from '@astrojs/starlight/components'; - `create astro`를 사용하여 Tailwind CSS가 사전 구성된 새 Starlight 프로젝트를 시작하세요. -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh @@ -82,156 +102,188 @@ yarn create astro --template starlight/tailwind </TabItem> </Tabs> -### 기존 프로젝트에 Tailwind 추가 +### 기존 프로젝트에 Tailwind 추가하기 이미 Starlight 사이트가 존재할때, Tailwind CSS를 추가하려면 다음 단계를 따르세요. -1. Astro의 Tailwind 통합 추가 +<Steps> - <Tabs> +1. 다음 명령을 실행하고 터미널의 지침에 따라 프로젝트에 Tailwind를 설정합니다. - <TabItem label="npm"> + <Tabs syncKey="pkg"> - ```sh - npx astro add tailwind - ``` + <TabItem label="npm"> - </TabItem> + ```sh + npx astro add tailwind + ``` - <TabItem label="pnpm"> + </TabItem> - ```sh - pnpm astro add tailwind - ``` + <TabItem label="pnpm"> - </TabItem> + ```sh + pnpm astro add tailwind + ``` - <TabItem label="Yarn"> + </TabItem> - ```sh - yarn astro add tailwind - ``` + <TabItem label="Yarn"> - </TabItem> + ```sh + yarn astro add tailwind + ``` - </Tabs> + </TabItem> -2. Starlight Tailwind 플러그인을 설치하세요. + </Tabs> - <Tabs> +2. Starlight의 Tailwind 호환성 패키지를 설치합니다. - <TabItem label="npm"> + <Tabs syncKey="pkg"> - ```sh - npm install @astrojs/starlight-tailwind - ``` + <TabItem label="npm"> - </TabItem> + ```sh + npm install @astrojs/starlight-tailwind + ``` - <TabItem label="pnpm"> + </TabItem> - ```sh - pnpm install @astrojs/starlight-tailwind - ``` + <TabItem label="pnpm"> - </TabItem> + ```sh + pnpm add @astrojs/starlight-tailwind + ``` - <TabItem label="Yarn"> + </TabItem> - ```sh - yarn add @astrojs/starlight-tailwind - ``` + <TabItem label="Yarn"> - </TabItem> + ```sh + yarn add @astrojs/starlight-tailwind + ``` - </Tabs> + </TabItem> -3. `src/tailwind.css`와 같은 Tailwind의 기본 스타일에 대한 CSS 파일을 만드세요. + </Tabs> - ```css - /* src/tailwind.css */ - @tailwind base; - @tailwind components; - @tailwind utilities; - ``` +3. Astro가 스캐폴딩한 `src/styles/global.css` 파일의 콘텐츠를 Starlight와의 호환성을 위해 다음 코드로 교체합니다. -4. Tailwind 기반 스타일을 사용하고 기본 스타일을 비활성화하려면 Astro 구성 파일을 업데이트하세요. + ```css + /* src/styles/global.css */ + @layer base, starlight, theme, components, utilities; - ```js {11-12,16-17} - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - import tailwind from '@astrojs/tailwind'; + @import '@astrojs/starlight-tailwind'; + @import 'tailwindcss/theme.css' layer(theme); + @import 'tailwindcss/utilities.css' layer(utilities); + ``` - export default defineConfig({ - integrations: [ - starlight({ - title: 'Tailwind를 사용한 문서', - customCss: [ - // Tailwind 기반 스타일 경로 - './src/tailwind.css', - ], - }), - tailwind({ - // 기본 스타일을 비활성화합니다. - applyBaseStyles: false, - }), - ], - }); - ``` + 이 Tailwind 테마 구성은 Starlight의 [캐스케이드 레이어](#캐스케이드-레이어) 순서를 정의하고, Starlight의 Tailwind 보완 CSS와 Tailwind 테마, 유틸리티 스타일을 가져옵니다. 프로젝트에 추가 Tailwind 구성이 필요한 경우 ["여러 Tailwind 구성 사용하기"](#여러-tailwind-구성-사용하기) 섹션을 확인하세요. -5. `tailwind.config.cjs`에 Starlight Tailwind 플러그인을 추가하세요. +4. `customCss` 배열의 첫 번째 항목으로 Tailwind CSS 파일을 추가하도록 Starlight 구성을 업데이트합니다. - ```js ins={2,7} - // tailwind.config.cjs - const starlightPlugin = require('@astrojs/starlight-tailwind'); + ```js ins={11-12} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import tailwindcss from '@tailwindcss/vite'; - /** @type {import('tailwindcss').Config} */ - module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - plugins: [starlightPlugin()], - }; - ``` + export default defineConfig({ + integrations: [ + starlight({ + title: 'Tailwind를 사용한 문서', + customCss: [ + // Tailwind 기본 스타일의 경로입니다. + './src/styles/global.css', + ], + }), + ], + vite: { plugins: [tailwindcss()] }, + }); + ``` + +</Steps> ### Tailwind로 Starlight 스타일링하기 -Starlight는 UI에서 [Tailwind 테마 구성](https://tailwindcss.com/docs/theme) 값을 사용합니다. - -설정된 경우 다음 옵션이 Starlight의 기본 스타일을 재정의합니다. - -- `colors.accent` — 링크 및 현재 항목 강조에 사용됩니다. -- `colors.gray` — 배경색과 테두리에 사용됩니다. -- `fontFamily.sans` — UI 및 콘텐츠 텍스트에 사용됩니다. -- `fontFamily.mono` — 코드 예제에 사용됩니다. - -```js {12,14,18,20} -// tailwind.config.cjs -const starlightPlugin = require('@astrojs/starlight-tailwind'); -const colors = require('tailwindcss/colors'); - -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: { - colors: { - // 선호하는 강조 색상입니다. Indigo는 Starlight의 기본값에 가장 가깝습니다. - accent: colors.indigo, - // 선호하는 회색조입니다. Zinc는 Starlight의 기본값에 가장 가깝습니다. - gray: colors.zinc, - }, - fontFamily: { - // 선호하는 텍스트 글꼴입니다. Starlight는 기본적으로 시스템 글꼴 스택을 사용합니다. - sans: ['"Atkinson Hyperlegible"'], - // 선호하는 코드 글꼴입니다. Starlight는 기본적으로 시스템 고정 폭 글꼴을 사용합니다. - mono: ['"IBM Plex Mono"'], - }, - }, - }, - plugins: [starlightPlugin()], -}; +[Tailwind를 사용하여 새 Starlight 프로젝트를 만들거나](#tailwind가-포함된-새-프로젝트-만들기) [기존 Starlight 프로젝트에 Tailwind를 추가할 때](#기존-프로젝트에-tailwind-추가하기), Starlight는 `src/styles/global.css` 파일에 있는 [Tailwind 테마 구성](https://tailwindcss.com/docs/theme)의 값을 사용하여 UI의 스타일을 지정합니다. + +설정되면 다음 CSS 사용자 정의 속성이 Starlight의 기본 스타일을 재정의합니다. + +- `--color-accent-*` — 링크 및 현재 항목 강조 표시에 사용됩니다. +- `--color-gray-*` — 배경색 및 테두리에 사용됩니다. +- `--font-sans` — UI 및 콘텐츠 텍스트에 사용됩니다. +- `--font-mono` — 코드 예시에 사용됩니다. + +```css {9,11,13,25} +/* src/styles/global.css */ +@layer base, starlight, theme, components, utilities; + +@import '@astrojs/starlight-tailwind'; +@import 'tailwindcss/theme.css' layer(theme); +@import 'tailwindcss/utilities.css' layer(utilities); + +@theme { + /* 선호하는 텍스트 글꼴입니다. Starlight는 기본적으로 시스템 글꼴 스택을 사용합니다. */ + --font-sans: 'Atkinson Hyperlegible'; + /* 선호하는 코드 글꼴입니다. Starlight는 기본적으로 시스템 고정폭 글꼴을 사용합니다. */ + --font-mono: 'IBM Plex Mono'; + /* 선호하는 강조 색상입니다. 남색(indigo)이 Starlight의 기본값과 가장 유사합니다. */ + --color-accent-50: var(--color-indigo-50); + --color-accent-100: var(--color-indigo-100); + --color-accent-200: var(--color-indigo-200); + --color-accent-300: var(--color-indigo-300); + --color-accent-400: var(--color-indigo-400); + --color-accent-500: var(--color-indigo-500); + --color-accent-600: var(--color-indigo-600); + --color-accent-700: var(--color-indigo-700); + --color-accent-800: var(--color-indigo-800); + --color-accent-900: var(--color-indigo-900); + --color-accent-950: var(--color-indigo-950); + /* 선호하는 회색조입니다. 아연색(zinc)이 Starlight의 기본값과 가장 유사합니다. */ + --color-gray-50: var(--color-zinc-50); + --color-gray-100: var(--color-zinc-100); + --color-gray-200: var(--color-zinc-200); + --color-gray-300: var(--color-zinc-300); + --color-gray-400: var(--color-zinc-400); + --color-gray-500: var(--color-zinc-500); + --color-gray-600: var(--color-zinc-600); + --color-gray-700: var(--color-zinc-700); + --color-gray-800: var(--color-zinc-800); + --color-gray-900: var(--color-zinc-900); + --color-gray-950: var(--color-zinc-950); +} ``` +### 여러 Tailwind 구성 사용하기 + +[하위 경로에서 Starlight를 사용](/ko/manual-setup/#하위-경로에서-starlight-사용)하거나 사이트에 [사용자 정의 페이지](/ko/guides/pages/#사용자-정의-페이지)를 추가할 때와 같이 사이트의 여러 부분에 서로 다른 스타일을 적용하기 위해 여러 Tailwind 구성을 사용할 수 있습니다. +예를 들어 사용자 정의 페이지에 Tailwind의 Preflight 재설정 스타일을 사용하면서 Starlight 페이지에는 Starlight의 호환성 레이어를 적용하고 싶을 수 있습니다. + +다음 Tailwind CSS 구성은 플러그인이나 추가 구성 없이 Tailwind를 설정하며, Starlight가 아닌 페이지의 시작점으로 사용할 수 있습니다. + +```css title="src/styles/custom-pages-tailwind.css" +/* Starlight의 보완 CSS 없이 Tailwind를 로드합니다. */ +@import 'tailwindcss'; +``` + +<Steps> + +1. Starlight 페이지의 경우 ["기존 프로젝트에 Tailwind 추가하기"](#기존-프로젝트에-tailwind-추가하기)에 따라 원하는 Tailwind CSS 구성을 적용합니다. + +2. 다른 페이지의 경우 해당 페이지에서 원하는 Tailwind CSS 구성을 가져와서 적용하세요. 이 작업은 레이아웃 컴포넌트에서 수행되는 경우가 많으므로 해당 레이아웃을 공유하는 모든 페이지에서 Tailwind 스타일을 사용할 수 있습니다. + ```astro + --- + // src/layouts/CustomPageLayout.astro + import '../styles/custom-pages-tailwind.css'; + --- + ``` + +</Steps> + +Tailwind 테마 구성에 대해 자세히 알아보려면 [Tailwind CSS 문서](https://tailwindcss.com/docs/theme)를 확인하세요. + ## 테마 기본 사용자 정의 속성을 변경하여 Starlight의 색상 테마를 제어할 수 있습니다. @@ -241,9 +293,11 @@ module.exports = { 아래 슬라이더를 사용하여 Starlight의 강조 및 회색 색상 팔레트를 수정하세요. 어둡고 밝은 미리보기 영역에는 결과 색상이 표시되며 전체 페이지도 업데이트되어 변경 사항을 미리 확인할 수 있습니다. +대비 수준 옵션을 사용하여 웹 콘텐츠 접근성 가이드라인 [색상 대비 표준](https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast) 중 어느 것을 충족할지 지정합니다. + 변경 사항이 만족스러우면 아래 CSS 또는 Tailwind 코드를 복사하여 프로젝트에 사용하세요. -import ThemeDesigner from '../../../../components/theme-designer.astro'; +import ThemeDesigner from '~/components/theme-designer.astro'; <ThemeDesigner labels={{ @@ -256,6 +310,9 @@ import ThemeDesigner from '../../../../components/theme-designer.astro'; default: '기본값', random: '무작위', }, + contrast: { + label: '대비 수준', + }, editor: { accentColor: '강조', grayColor: '회색조', @@ -277,7 +334,7 @@ import ThemeDesigner from '../../../../components/theme-designer.astro'; [사용자 정의 CSS파일](#사용자-정의-css-스타일)에 아래 코드를 추가하여 현재 테마를 프로젝트에 적용하세요. </Fragment> <Fragment slot="tailwind-docs"> - 아래 [Tailwind 구성 파일](#tailwind로-starlight-스타일링하기)의 예시는 `theme.extend.colors`에서 사용할 `accent` 및 `gray` 색상 팔레트를 포함합니다. - </Fragment> + 사이트에 이 테마를 적용하려면 [Tailwind CSS 파일](#tailwind로-starlight-스타일링하기)의 `@theme` 블록에 다음 CSS 변수를 추가하세요. + </Fragment> </ThemeDesigner> diff --git a/docs/src/content/docs/ko/guides/customization.mdx b/docs/src/content/docs/ko/guides/customization.mdx index 1414d587aff..53efe3a1b58 100644 --- a/docs/src/content/docs/ko/guides/customization.mdx +++ b/docs/src/content/docs/ko/guides/customization.mdx @@ -3,8 +3,7 @@ title: Starlight 사용자 정의 description: 로고, 사용자 정의 글꼴, 랜딩 페이지 디자인 등을 사용하여 나만의 Starlight 사이트를 만드는 방법을 알아보세요. --- -import { Tabs, TabItem } from '@astrojs/starlight/components'; -import FileTree from '../../../../components/file-tree.astro'; +import { Tabs, TabItem, FileTree, Steps } from '@astrojs/starlight/components'; Starlight는 합리적인 기본 스타일과 기능을 제공하므로 구성 없이 빠르게 시작할 수 있습니다. Starlight 사이트의 모양과 느낌을 바꾸고 싶다면 이 가이드를 참조하세요. @@ -12,7 +11,9 @@ Starlight는 합리적인 기본 스타일과 기능을 제공하므로 구성 사이트 헤더에 로고를 추가하는 것은 Starlight 사이트에 브랜드를 추가하는 빠른 방법입니다. -1. `src/assets/` 디렉토리에 로고 이미지 파일을 추가합니다. +<Steps> + +1. `src/assets/` 디렉터리에 로고 이미지 파일을 추가합니다. <FileTree> @@ -26,7 +27,7 @@ Starlight는 합리적인 기본 스타일과 기능을 제공하므로 구성 2. `astro.config.mjs` 파일에 있는 [logo.src](/ko/reference/configuration/#logo) 옵션의 값으로 로고 파일의 경로를 추가하세요. - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -36,16 +37,18 @@ Starlight는 합리적인 기본 스타일과 기능을 제공하므로 구성 starlight({ title: '로고를 사용하는 문서', logo: { - src: './src/assets/my-logo.svg', + + src: './src/assets/my-logo.svg', }, }), ], }); ``` +</Steps> + 기본적으로 로고는 사이트의 `title`과 함께 표시됩니다. 이미 로고 이미지에 사이트 제목이 포함되어 있는 경우, `replacementTitle` 옵션을 설정하여 제목 텍스트를 시각적으로 숨길 수 있습니다. `title` 텍스트는 스크린 리더를 위해 남아 있기 때문에 헤더의 접근성은 유지됩니다. -```js +```js {5} starlight({ title: '로고를 사용하는 문서', logo: { @@ -59,7 +62,9 @@ starlight({ 라이트 모드와 다크 모드에서 다른 버전의 로고를 표시할 수 있습니다. -1. `src/assets/`에 각 변형에 대한 이미지 파일을 추가합니다. +<Steps> + +1. `src/assets/` 디렉터리에 각 변형에 대한 이미지 파일을 추가합니다. <FileTree> @@ -74,21 +79,23 @@ starlight({ 2. `astro.config.mjs` 파일에서 `src` 대신 `light` 및 `dark` 옵션을 전달하여 로고 변형에 대한 경로를 추가합니다. - ```js + ```diff lang="js" starlight({ title: '로고를 사용하는 문서', logo: { - light: './src/assets/light-logo.svg', - dark: './src/assets/dark-logo.svg', + + light: './src/assets/light-logo.svg', + + dark: './src/assets/dark-logo.svg', }, }), ``` +</Steps> + ## 사이트맵 활성화 Starlight에는 사이트맵 생성 기능이 내장되어 있습니다. `astro.config.mjs` 파일에 있는 `site` 속성의 값을 URL로 설정하여 사이트맵 생성을 활성화할 수 있습니다. -```js +```js {4} // astro.config.mjs export default defineConfig({ @@ -97,13 +104,15 @@ export default defineConfig({ }); ``` +Astro 문서에서 [`robots.txt`에 사이트맵 링크를 추가](https://docs.astro.build/ko/guides/integrations-guide/sitemap/#robotstxt-내-사이트맵-링크)하는 방법을 알아보세요. + ## 페이지 레이아웃 기본적으로 Starlight 페이지는 전역 탐색 사이드바와 현재 페이지 제목의 목차가 포함된 레이아웃을 사용합니다. -frontmatter에 [`template: splash`](/ko/reference/frontmatter/#template)를 설정하여 사이드바 없이 더 넓은 페이지 레이아웃을 적용할 수 있습니다. 주로 랜딩 페이지에서 사용되며, [이 사이트의 홈페이지](/ko)에서 실제로 작동하는 것을 확인할 수 있습니다. +프론트매터에 [`template: splash`](/ko/reference/frontmatter/#template)를 설정하여 사이드바 없이 더 넓은 페이지 레이아웃을 적용할 수 있습니다. 주로 랜딩 페이지에서 사용되며, [이 사이트의 홈페이지](/ko/)에서 실제로 작동하는 것을 확인할 수 있습니다. -```md +```md {5} --- # src/content/docs/index.md @@ -114,14 +123,14 @@ template: splash ## 목차 -Starlight는 독자가 원하는 제목으로 쉽게 이동할 수 있도록 각 페이지에 목차를 표시합니다. Starlight 통합을 통해 모든 페이지의 목차를 변경하거나 비활성화할 수 있습니다. 또한, frontmatter를 수정하여 각 페이지의 목차를 변경할 수도 있습니다. +Starlight는 독자가 원하는 제목으로 쉽게 이동할 수 있도록 각 페이지에 목차를 표시합니다. Starlight 통합을 통해 모든 페이지의 목차를 변경하거나 비활성화할 수 있습니다. 또한, 프론트매터를 수정하여 각 페이지의 목차를 변경할 수도 있습니다. -기본적으로 `<h2>` 및 `<h3>` 제목이 목차에 포함됩니다. [`tableOfContents`](/ko/reference/configuration/#tableofcontents) 의 `minHeadingLevel` 및 `maxHeadingLevel` 옵션을 사용하여 모든 페이지의 목차를 변경할 수 있습니다. 개별 페이지의 기본 목차를 변경하기 위해서는 [frontmatter에 `tableOfContents`](/ko/reference/frontmatter/#tableofcontents) 속성을 추가하세요. +기본적으로 `<h2>` 및 `<h3>` 제목이 목차에 포함됩니다. [`tableOfContents`](/ko/reference/configuration/#tableofcontents) 의 `minHeadingLevel` 및 `maxHeadingLevel` 옵션을 사용하여 모든 페이지의 목차를 변경할 수 있습니다. 개별 페이지의 기본 목차를 변경하기 위해서는 [프론트매터에 `tableOfContents`](/ko/reference/frontmatter/#tableofcontents) 속성을 추가하세요. -<Tabs> +<Tabs syncKey="config-type"> <TabItem label="개별 페이지 설정"> -```md +```md {4-6} --- # src/content/docs/example.md title: 목차에 H2만 있는 페이지 @@ -134,13 +143,13 @@ tableOfContents: </TabItem> <TabItem label="전역 설정"> -```js +```js {7} // astro.config.mjs defineConfig({ integrations: [ starlight({ - title: '', + title: '맞춤 목차 구성이 포함된 문서', tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 2 }, }), ], @@ -152,10 +161,10 @@ defineConfig({ `tableOfContents` 옵션의 값을 `false`로 설정하여 모든 페이지의 목차를 비활성화 할 수 있습니다. -<Tabs> +<Tabs syncKey="config-type"> <TabItem label="개별 페이지 설정"> -```md +```md {4} --- # src/content/docs/example.md title: 목차가 없는 페이지 @@ -166,7 +175,7 @@ tableOfContents: false </TabItem> <TabItem label="전역 설정"> -```js +```js {7} // astro.config.mjs defineConfig({ @@ -186,9 +195,15 @@ defineConfig({ Starlight에는 [`social`](/ko/reference/configuration/#social) 옵션을 사용하여 사이트 헤더에 소셜 미디어 계정을 링크하는 기능이 내장되어 있습니다. -현재 Bitbucket, Codeberg, CodePen, Discord, GitHub, GitLab, Gitter, Instagram, LinkedIn, Mastodon, Microsoft Teams, Stack Overflow, Threads, Twitch, Twitter 및 Youtube에 대한 링크가 지원됩니다. 다른 서비스에 대한 지원이 필요하면 GitHub나 Discord를 통해 알려주세요! +`social` 배열의 각 항목은 세 가지 속성을 가진 객체여야 합니다: + +- `icon`: Starlight의 [내장 아이콘](/ko/reference/icons/) 중 하나, 예: `"github"` +- `label`: 링크에 대한 접근성이 있는 레이블, 예: `"GitHub"` +- `href`: 해당 링크의 URL, 예: `"https://github.com/withastro/starlight"` + +다음 예시는 Astro Discord 채팅과 Starlight GitHub 리포지토리 링크를 추가합니다: -```js +```js {9-16} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -197,10 +212,14 @@ export default defineConfig({ integrations: [ starlight({ title: '소셜 링크를 사용하는 문서', - social: { - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - }, + social: [ + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { + icon: 'github', + label: 'GitHub', + href: 'https://github.com/withastro/starlight', + }, + ], }), ], }); @@ -219,9 +238,9 @@ Starlight는 각 페이지의 아래에 "페이지 편집" 링크를 표시할 Starlight 프로젝트가 저장소의 루트에 없는 경우 기본 URL 끝에 프로젝트 경로를 포함합니다. -아래 예시는 GitHub `withastro/starlight` 저장소의 `main` 브랜치에 있는 `docs/` 하위 디렉토리에 있는 Starlight 문서에 대해 구성된 편집 링크를 보여줍니다. +아래 예시는 GitHub `withastro/starlight` 저장소의 `main` 브랜치에 있는 `docs/` 디렉터리에 있는 Starlight 문서에 대해 구성된 편집 링크를 보여줍니다. -```js +```js {9-11} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -240,7 +259,7 @@ export default defineConfig({ ## 사용자 정의 404 페이지 -Starlight 사이트는 기본적으로 간단한 404 페이지를 표시합니다. `src/content/docs/` 디렉토리에 `404.md`(또는 `404.mdx`) 파일을 추가하여 이를 변경할 수 있습니다: +Starlight 사이트는 기본적으로 간단한 404 페이지를 표시합니다. `src/content/docs/` 디렉터리에 `404.md`(또는 `404.mdx`) 파일을 추가하여 이를 변경할 수 있습니다: <FileTree> @@ -253,10 +272,11 @@ Starlight 사이트는 기본적으로 간단한 404 페이지를 표시합니 </FileTree> -404 페이지에서 Starlight의 모든 페이지 레이아웃과 사용자 정의 기술을 사용할 수 있습니다. 예를 들어 기본 404 페이지는 frontmatter에서 [`splash` 템플릿](#페이지-레이아웃)과 [`hero`](/ko/reference/frontmatter/#hero) 컴포넌트를 사용합니다. +404 페이지에서 Starlight의 모든 페이지 레이아웃과 사용자 정의 기술을 사용할 수 있습니다. 예를 들어 기본 404 페이지는 프론트매터에서 [`splash` 템플릿](#페이지-레이아웃)과 [`hero`](/ko/reference/frontmatter/#hero) 컴포넌트를 사용합니다. -```md +```md {4,6-8} --- +# src/content/docs/404.md title: '404' template: splash editUrl: false @@ -266,6 +286,25 @@ hero: --- ``` +### 기본 404 페이지 비활성화 + +프로젝트에 완전히 사용자 정의된 404 레이아웃이 필요한 경우 `src/pages/404.astro` 경로를 생성하고 [`disable404Route`](/ko/reference/configuration/#disable404route) 구성 옵션을 설정하여 Starlight의 기본 경로를 비활성화할 수 있습니다. + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: '사용자 정의 404가 포함된 문서', + disable404Route: true, + }), + ], +}); +``` + ## 사용자 정의 글꼴 기본적으로 Starlight는 모든 텍스트에 대해 사용자의 로컬 장치에서 사용할 수 있는 sans-serif 글꼴을 사용합니다. 이를 통해 대용량 글꼴 파일을 다운로드하기 위한 추가 대역폭 없이 각 사용자에게 친숙한 글꼴로 문서를 빠르게 로드할 수 있습니다. @@ -278,7 +317,9 @@ Starlight 사이트에 사용자 정의 글꼴을 추가해야 하는 경우, #### 로컬 글꼴 파일 설정 -1. `src/fonts/` 디렉토리에 글꼴 파일을 추가하고 빈 `font-face.css` 파일을 만드세요. +<Steps> + +1. `src/fonts/` 디렉터리에 글꼴 파일을 추가하고 빈 `font-face.css` 파일을 만드세요. <FileTree> @@ -291,7 +332,7 @@ Starlight 사이트에 사용자 정의 글꼴을 추가해야 하는 경우, </FileTree> -2. `src/fonts/font-face.css`에 각 글꼴에 대한 [`@font-face` 선언](https://developer.mozilla.org/ko/docs/Web/CSS/@font-face)을 추가하세요. `url()` 함수에서 글꼴 파일의 상대 경로를 사용하세요. +2. `src/fonts/font-face.css` 파일에 각 글꼴에 대한 [`@font-face` 선언](https://developer.mozilla.org/ko/docs/Web/CSS/@font-face)을 추가하세요. `url()` 함수에서 글꼴 파일의 상대 경로를 사용하세요. ```css /* src/fonts/font-face.css */ @@ -306,9 +347,9 @@ Starlight 사이트에 사용자 정의 글꼴을 추가해야 하는 경우, } ``` -3. `astro.config.mjs`에 있는 Starlight의 `customCss` 배열에 `font-face.css` 파일의 경로를 추가하세요. +3. `astro.config.mjs` 파일에 있는 Starlight의 `customCss` 배열에 `font-face.css` 파일의 경로를 추가하세요. - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -318,23 +359,27 @@ Starlight 사이트에 사용자 정의 글꼴을 추가해야 하는 경우, starlight({ title: '사용자 정의 글꼴을 사용하는 문서', customCss: [ - // @font-face CSS 파일의 상대 경로입니다. - './src/fonts/font-face.css', + + // @font-face CSS 파일의 상대 경로입니다. + + './src/fonts/font-face.css', ], }), ], }); ``` +</Steps> + #### Fontsource 글꼴 설정 [Fontsource](https://fontsource.org/) 프로젝트는 Google Fonts 및 기타 오픈 소스 글꼴 사용을 단순화합니다. 글꼴을 설치할 수 있는 npm 모듈과 프로젝트에 추가할 CSS 파일을 제공합니다. +<Steps> + 1. [Fontsource 카탈로그](https://fontsource.org/)에서 사용하려는 글꼴을 찾으세요. 예시에서는 [IBM Plex Serif](https://fontsource.org/fonts/ibm-plex-serif)를 사용합니다. 2. 선택한 글꼴에 대한 패키지를 설치합니다. Fontsource 글꼴 페이지에서 “Install”을 클릭하면 패키지 이름을 찾을 수 있습니다. - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -347,7 +392,7 @@ Starlight 사이트에 사용자 정의 글꼴을 추가해야 하는 경우, <TabItem label="pnpm"> ```sh - pnpm install @fontsource/ibm-plex-serif + pnpm add @fontsource/ibm-plex-serif ``` </TabItem> @@ -364,7 +409,7 @@ Starlight 사이트에 사용자 정의 글꼴을 추가해야 하는 경우, 3. `astro.config.mjs`에 있는 Starlight의 `customCss` 배열에 Fontsource CSS 파일을 추가합니다. - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -374,9 +419,9 @@ Starlight 사이트에 사용자 정의 글꼴을 추가해야 하는 경우, starlight({ title: '사용자 정의 글꼴을 사용하는 문서', customCss: [ - // 보통 및 약간 굵은 글꼴 두께에 대한 Fontsource 파일입니다. - '@fontsource/ibm-plex-serif/400.css', - '@fontsource/ibm-plex-serif/600.css', + + // 보통 및 약간 굵은 글꼴 두께에 대한 Fontsource 파일입니다. + + '@fontsource/ibm-plex-serif/400.css', + + '@fontsource/ibm-plex-serif/600.css', ], }), ], @@ -385,6 +430,8 @@ Starlight 사이트에 사용자 정의 글꼴을 추가해야 하는 경우, Fontsource는 각 글꼴에 대해 여러 CSS 파일을 제공합니다. 다른 굵기 및 스타일을 포함하는 방법이 궁금하다면 [Fontsource 문서](https://fontsource.org/docs/getting-started/install#4-weights-and-styles)를 참조하세요. +</Steps> + ### 글꼴 사용 설정한 글꼴을 웹 사이트에 적용하려면 [사용자 정의 CSS 파일](/ko/guides/css-and-tailwind/#사용자-정의-css-스타일)에서 선택한 글꼴 이름을 사용하세요. 예를 들어 Starlight의 기본 글꼴을 변경하려면 사용자 정의 속성인 `--sl-font`를 설정하세요. diff --git a/docs/src/content/docs/ko/guides/i18n.mdx b/docs/src/content/docs/ko/guides/i18n.mdx index a2556746e88..7a6fcc2dde9 100644 --- a/docs/src/content/docs/ko/guides/i18n.mdx +++ b/docs/src/content/docs/ko/guides/i18n.mdx @@ -3,15 +3,17 @@ title: 국제화 (i18n) description: 여러 언어를 지원하도록 Starlight 사이트를 구성하는 방법을 알아보세요. --- -import FileTree from '../../../../components/file-tree.astro'; +import { FileTree, Steps } from '@astrojs/starlight/components'; Starlight는 라우팅, 대체 콘텐츠 및 전체 RTL(오른쪽에서 왼쪽으로) 언어 지원을 포함한 다국어 사이트에 대한 기본 지원을 제공합니다. ## i18n 구성 +<Steps> + 1. Starlight 통합에 [`locales`](/ko/reference/configuration/#locales) 및 [`defaultLocale`](/ko/reference/configuration/#defaultlocale)을 전달하여 사이트가 지원해야 할 언어에 대해 알려주세요. - ```js + ```js {9-26} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -27,8 +29,8 @@ Starlight는 라우팅, 대체 콘텐츠 및 전체 RTL(오른쪽에서 왼쪽 en: { label: 'English', }, - // 중국어 간체 문서는 `src/content/docs/zh/`에 있습니다. - zh: { + // 중국어 간체 문서는 `src/content/docs/zh-cn/`에 있습니다. + 'zh-cn': { label: '简体中文', lang: 'zh-CN', }, @@ -45,7 +47,7 @@ Starlight는 라우팅, 대체 콘텐츠 및 전체 RTL(오른쪽에서 왼쪽 `defaultLocale`은 대체 콘텐츠 및 UI 라벨에 사용되므로 콘텐츠 작성을 시작할 가능성이 가장 높거나 이미 콘텐츠가 있는 언어로 선택하세요. -2. `src/content/docs/`에 각 언어에 대한 디렉토리를 만듭니다. 예를 들어 위에서 사용한 구성의 경우 다음과 같이 디렉토리를 생성할 수 있습니다. +2. `src/content/docs/`에 각 언어에 대한 디렉터리를 만듭니다. 예를 들어 위에서 사용한 구성의 경우 다음과 같이 디렉터리를 생성할 수 있습니다. <FileTree> @@ -54,21 +56,25 @@ Starlight는 라우팅, 대체 콘텐츠 및 전체 RTL(오른쪽에서 왼쪽 - docs/ - ar/ - en/ - - zh/ + - zh-cn/ </FileTree> -3. 이제 언어 디렉토리에 콘텐츠 파일을 추가할 수 있습니다. 여러 언어로 작성된 페이지를 연결하기 위해 같은 이름의 파일을 사용하면 Starlight의 모든 i18n 기능(대체 콘텐츠, 번역 알림 등)을 활용할 수 있습니다. +3. 이제 언어 디렉터리에 콘텐츠 파일을 추가할 수 있습니다. 여러 언어로 작성된 페이지를 연결하기 위해 같은 이름의 파일을 사용하면 Starlight의 모든 i18n 기능(대체 콘텐츠, 번역 알림 등)을 활용할 수 있습니다. 예를 들어, 아랍어와 영어 홈페이지를 각각 나타내려면 `ar/index.md` 및 `en/index.md`를 만듭니다. +</Steps> + +고급 국제화 시나리오를 위해 Starlight는 [Astro의 `i18n` 구성](https://docs.astro.build/ko/guides/internationalization/#i18n-라우팅-구성) 옵션을 사용하는 국제화 구성도 지원합니다. + ### 루트 로케일 사용 경로에 i18n 접두사가 없는 언어를 제공하려면 "루트" 로케일을 사용할 수 있습니다. 예를 들어 영어가 루트 로케일인 경우 영어 페이지 경로는 `/en/about` 대신 `/about`이 됩니다. 루트 로케일을 설정하려면 `locales` 구성에서 `root` 키를 사용하세요. 루트 로케일이 콘텐츠의 기본 로케일이기도 한 경우 `defaultLocale`을 제거하거나 값을 `root`로 설정하세요. -```js +```js {9,11-14} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -83,7 +89,7 @@ export default defineConfig({ label: 'English', lang: 'en', // 루트 로케일은 lang이 반드시 필요합니다. }, - zh: { + 'zh-cn': { label: '简体中文', lang: 'zh-CN', }, @@ -101,7 +107,7 @@ export default defineConfig({ - content/ - docs/ - **index.md** - - zh/ + - zh-cn/ - **index.md** </FileTree> @@ -111,7 +117,7 @@ export default defineConfig({ 기본적으로 Starlight는 단일 언어(영어) 사이트입니다. 다른 언어로 단일 언어 사이트를 만들려면 `locales` 구성에서 `root`를 해당 언어로 설정하세요. -```js +```diff lang="js" {10-13} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -139,24 +145,61 @@ Starlight는 귀하가 모든 언어로 같은 페이지를 생성할 것을 기 특정 언어에 대한 번역이 아직 제공되지 않는 경우 Starlight는 독자에게 해당 페이지의 콘텐츠를 기본 언어(`defaultLocale`을 통해 설정된 언어)로 표시합니다. 예를 들어, About 페이지의 프랑스어 버전을 아직 만들지 않았고 기본 언어가 영어인 경우 `/fr/about`에 방문한 독자는 이 페이지가 아직 번역되지 않았다는 알림과 함께 `/en/about`에 있는 영어 콘텐츠를 보게 됩니다. 이를 통해 기본 언어로 콘텐츠를 추가한 다음 점진적으로 번역할 수 있습니다. +## 사이트 제목 번역 + +기본적으로 Starlight는 모든 언어에 대해 동일한 사이트 제목을 사용합니다. +각 로케일의 제목을 사용자 정의해야 하는 경우 Starlight 옵션의 [`title`](/ko/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: '나의 문서', ++ title: { ++ ko: '나의 문서', ++ 'zh-CN': '我的文档', ++ }, + defaultLocale: 'ko', + locales: { + ko: { label: '한국어' }, + 'zh-cn': { label: '简体中文', lang: 'zh-CN' }, + }, + }), + ], +}); +``` + ## Starlight UI 번역 +import LanguagesList from '~/components/languages-list.astro'; +import UIStringsList from '~/components/ui-strings-list.astro'; + Starlight를 사용하면 번역된 콘텐츠 파일을 호스팅하는 것 외에도 독자가 선택한 언어로 사이트 전체를 경험할 수 있도록 기본 UI 문자열(예를 들어, 목차의 제목인 "목차")을 번역할 수 있습니다. -영어, 체코어, 프랑스어, 독일어, 이탈리아어, 일본어, 포르투갈어, 네덜란드어, 덴마크어, 스페인어, 터키어, 아랍어, 노르웨이어, 페르시아어, 히브리어, 중국어 간체, 한국어, 인도네시아어, 러시아어 및 스웨덴어로 번역된 UI 문자열이 기본적으로 제공됩니다. 그리고 우리는 [더 많은 기본 언어를 추가하는 데 기여](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md)하는걸 환영합니다. +<LanguagesList startsSentence />로 번역된 UI 문자열이 기본적으로 제공됩니다. +그리고 우리는 [더 많은 기본 언어를 추가하는 데 +기여](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md)하는걸 +환영합니다. `i18n` 데이터 컬렉션을 통해 지원하는 추가 언어에 대한 번역을 제공하거나 기본 라벨을 변경할 수 있습니다. -1. 아직 구성되지 않은 경우 `src/content/config.ts`에서 `i18n` 데이터 컬렉션을 구성합니다. +<Steps> + +1. 아직 구성되지 않은 경우 `src/content.config.ts`에서 `i18n` 데이터 컬렉션을 구성합니다. - ```js - // src/content/config.ts + ```diff lang="js" ins=/, (i18nLoader|i18nSchema)/ + // src/content.config.ts import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; export const collections = { - docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), }; ``` @@ -176,27 +219,16 @@ Starlight를 사용하면 번역된 콘텐츠 파일을 호스팅하는 것 외 Starlight와 함께 제공되는 기존 문자열의 영어 기본값은 다음과 같습니다. + <UIStringsList /> + + Starlight의 코드 블록은 [Expressive Code](https://expressive-code.com/) 라이브러리에 의해 구동됩니다. + `expressiveCode` 키를 사용하여 동일한 JSON 파일에서 UI 문자열에 대한 번역을 설정할 수 있습니다. + ```json { - "skipLink.label": "Skip to content", - "search.label": "Search", - "search.shortcutLabel": "(Press / to Search)", - "search.cancelLabel": "Cancel", - "search.devWarning": "Search is only available in production builds. \nTry building and previewing the site to test it out locally.", - "themeSelect.accessibleLabel": "Select theme", - "themeSelect.dark": "Dark", - "themeSelect.light": "Light", - "themeSelect.auto": "Auto", - "languageSelect.accessibleLabel": "Select language", - "menuButton.accessibleLabel": "Menu", - "sidebarNav.accessibleLabel": "Main", - "tableOfContents.onThisPage": "On this page", - "tableOfContents.overview": "Overview", - "i18n.untranslatedContent": "This content is not available in your language yet.", - "page.editLink": "Edit page", - "page.lastUpdated": "Last updated:", - "page.previousLink": "Next", - "page.nextLink": "Previous" + "expressiveCode.copyButtonCopied": "Copied!", + "expressiveCode.copyButtonTooltip": "Copy to clipboard", + "expressiveCode.terminalWindowFallbackTitle": "Terminal window" } ``` @@ -216,3 +248,161 @@ Starlight를 사용하면 번역된 콘텐츠 파일을 호스팅하는 것 외 "pagefind.searching": "Searching for [SEARCH_TERM]..." } ``` + +</Steps> + +### 번역 스키마 확장 + +`i18nSchema()` 옵션에서 `extend`를 설정하여 사이트 번역 사전에 맞춤 키를 추가하세요. +다음 예시에서는 기본 키에 새로운 선택적 `custom.label` 키가 추가됩니다. + +```diff lang="js" +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ ++ extend: z.object({ ++ 'custom.label': z.string().optional(), ++ }), + }), + }), +}; +``` + +Astro 공식문서의 ["컬렉션 스키마 정의"](https://docs.astro.build/ko/guides/content-collections/#컬렉션-스키마-정의)에서 콘텐츠 컬렉션 스키마에 대해 자세히 알아보세요. + +## UI 번역 사용 + +Starlight의 [기본 제공 UI 문자열](/ko/guides/i18n/#starlight-ui-번역)과 [사용자 정의](/ko/guides/i18n/#번역-스키마-확장) 및 [플러그인 제공](/ko/reference/plugins/#injecttranslations) UI 문자열에 액세스할 수 있는 통합 API는 [i18next](https://www.i18next.com/)로 구동됩니다. +여기에는 [보간](https://www.i18next.com/translation-function/interpolation) 및 [복수화](https://www.i18next.com/translation-function/plurals)와 같은 기능에 대한 지원이 포함됩니다. + +Astro 컴포넌트에서 이 API는 [전역 `Astro` 객체](https://docs.astro.build/ko/reference/api-reference/#locals)의 일부인 `Astro.locals.t`로 사용할 수 있습니다: + +```astro title="example.astro" +<p dir={Astro.locals.t.dir()}> + {Astro.locals.t('404.text')} +</p> +``` + +[엔드포인트](https://docs.astro.build/ko/guides/endpoints/)에서도 API를 사용할 수 있으며, 여기서 `locals` 객체는 [엔드포인트 컨텍스트](https://docs.astro.build/ko/reference/api-reference/#locals)의 일부로 사용할 수 있습니다: + +```ts title="src/pages/404.ts" +export const GET = (context) => { + return new Response(context.locals.t('404.text')); +}; +``` + +Starlight 플러그인 컨텍스트에서 [`useTranslations()`](/ko/reference/plugins/#usetranslations) 도우미를 사용하여 특정 언어에 대한 이 API에 접근할 수 있습니다. +자세한 내용은 [플러그인 참조](/ko/reference/plugins/)를 확인하세요. + +### UI 문자열 렌더링 + +`locals.t()` 함수를 사용하여 UI 문자열을 렌더링합니다. +이것은 UI 문자열 키를 첫 번째 인수로 받아 현재 언어에 해당하는 번역을 반환하는 i18next의 `t()` 함수의 인스턴스입니다. + +예를 들어 다음과 같은 콘텐츠가 포함된 사용자 정의 번역 파일이 있다고 가정해 보겠습니다: + +```json title="src/content/i18n/en.json" +{ + "link.astro": "Astro documentation", + "link.astro.custom": "Astro documentation for {{feature}}" +} +``` + +첫 번째 UI 문자열은 `t()` 함수에 `'link.astro'`를 전달하여 렌더링할 수 있습니다: + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/"> + {Astro.locals.t('link.astro')} +</a> +<!-- 렌더링: <a href="...">Astro documentation</a> --> +``` + +두 번째 UI 문자열은 `{{feature}}` 자리 표시자에 i18next의 [보간 구문](https://www.i18next.com/translation-function/interpolation)을 사용합니다. +`feature`의 값은 `t()`의 두 번째 인수로 전달된 옵션 객체에서 설정되어야 합니다: + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/en/guides/astro-db/"> + {Astro.locals.t('link.astro.custom', { feature: 'Astro DB' })} +</a> +<!-- 렌더링: <a href="...">Astro documentation for Astro DB</a> --> +``` + +보간, 서식 지정 등과 함께 `t()` 함수를 사용하는 방법에 대한 자세한 내용은 [i18next 문서](https://www.i18next.com/overview/api#t)를 참조하세요. + +### 고급 API + +#### `t.all()` + +`locals.t.all()` 함수는 현재 로케일에서 사용 가능한 모든 UI 문자열이 포함된 객체를 반환합니다. + +```astro +--- +// src/components/Example.astro +const allStrings = Astro.locals.t.all(); +// ^ +// { +// "skipLink.label": "Skip to content", +// "search.label": "Search", +// … +// } +--- +``` + +#### `t.exists()` + +번역 키가 존재하는지 확인하려면 번역 키를 첫 번째 인수로 전달하여 `locals.t.exists()` 함수를 사용합니다. +특정 로케일에 대한 번역이 존재하는지 확인해야 하는 경우 선택적으로 두 번째 인수를 전달합니다. + +```astro +--- +// src/components/Example.astro +const keyExists = Astro.locals.t.exists('a.key'); +// ^ true +const keyExistsInFrench = Astro.locals.t.exists('other.key', { lngs: ['fr'] }); +// ^ false +--- +``` + +자세한 내용은 [i18next 문서의 `exists()` 참조](https://www.i18next.com/overview/api#exists)를 확인하세요. + +#### `t.dir()` + +`locals.t.dir()` 함수는 현재 또는 특정 로케일의 텍스트 방향을 반환합니다. + +```astro +--- +// src/components/Example.astro +const currentDirection = Astro.locals.t.dir(); +// ^ +// 'ltr' +const arabicDirection = Astro.locals.t.dir('ar'); +// ^ +// 'rtl' +--- +``` + +자세한 내용은 [i18next 문서의 `dir()` 참조](https://www.i18next.com/overview/api#dir)를 확인하세요. + +## 현재 로케일에 액세스 + +[`Astro.currentLocale`](https://docs.astro.build/ko/reference/api-reference/#currentlocale)을 사용하여 `.astro` 컴포넌트의 현재 로케일을 읽을 수 있습니다. + +다음 예시는 현재 로케일을 읽고 이를 [`getRelativeLocaleUrl()`](https://docs.astro.build/ko/reference/modules/astro-i18n/#getrelativelocaleurl) 헬퍼와 함께 사용하여 현재 언어로 된 소개 페이지 링크를 생성합니다: + +```astro +--- +// src/components/AboutLink.astro +import { getRelativeLocaleUrl } from 'astro:i18n'; +--- + +<a href={getRelativeLocaleUrl(Astro.currentLocale ?? 'en', 'about')}>소개</a> +``` diff --git a/docs/src/content/docs/ko/guides/overriding-components.mdx b/docs/src/content/docs/ko/guides/overriding-components.mdx new file mode 100644 index 00000000000..68300635226 --- /dev/null +++ b/docs/src/content/docs/ko/guides/overriding-components.mdx @@ -0,0 +1,153 @@ +--- +title: 컴포넌트 재정의 +description: Starlight 내장 컴포넌트를 재정의하여 문서 사이트 UI에 사용자 정의 요소를 추가하는 방법에 대해 알아보세요. +--- + +import { Steps } from '@astrojs/starlight/components'; + +Starlight의 기본 UI 및 구성 옵션은 유연하고 다양한 콘텐츠에 작동하도록 설계되었습니다. Starlight의 기본 형태는 대부분 [CSS](/ko/guides/css-and-tailwind/) 및 [구성 옵션](/ko/guides/customization/)을 사용하여 변경할 수 있습니다. + +기본적으로 Starlight는 가능한 것보다 더 많은 것이 필요한 경우, 기본 컴포넌트를 확장하거나 재정의(완전히 대체)하기 위한 자체 사용자 정의 컴포넌트 구축을 지원합니다. + +## 재정의가 필요한 경우 + +Starlight의 기본 컴포넌트를 재정의하는 것은 다음과 같은 경우에 유용할 수 있습니다. + +- [사용자 정의 CSS](/ko/guides/css-and-tailwind/)로는 불가능한 방식으로 Starlight UI를 변경하고 싶은 경우. +- Starlight UI의 일부 동작을 변경하고 싶은 경우. +- Starlight의 기존 UI 외 새로운 UI를 추가하고 싶은 경우. + +## 재정의 방법 + +<Steps> + +1. 재정의하려는 Starlight 컴포넌트를 선택합니다. + [재정의 참조](/ko/reference/overrides/)에서 전체 컴포넌트 목록을 확인할 수 있습니다. + + :::tip + 어떤 컴포넌트를 재정의해야 할지 잘 모르겠나요? [상호작용 할 수 있는 Starlight Overrides Map](https://starlight-overrides-map.netlify.app/)에서 Starlight의 UI 컴포넌트 이름을 확인할 수 있습니다. + ::: + + 이 예시는 페이지 탐색 바에 있는 Starlight의 [`SocialIcons`](/ko/reference/overrides/#socialicons) 컴포넌트를 재정의합니다. + +2. Starlight 컴포넌트를 대체할 Astro 컴포넌트를 생성합니다. + 이 예시는 연락처 링크를 렌더링합니다. + + ```astro + --- + // src/components/EmailLink.astro + + const email = 'houston@example.com'; + --- + + <a href=`mailto:${email}`>메일 보내기</a> + ``` + +3. `astro.config.mjs` 파일의 [`components`](/ko/reference/configuration/#components) 구성 옵션에서 사용자 정의 컴포넌트를 사용하기 위한 설정을 추가합니다. + + ```js {9-12} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: '재정의된 문서', + components: { + // 기존 `SocialIcons` 컴포넌트를 재정의합니다. + SocialIcons: './src/components/EmailLink.astro', + }, + }), + ], + }); + ``` + +</Steps> + +## 내장 컴포넌트 재사용 + +Starlight의 기본 UI 컴포넌트를 사용하여 나만의 컴포넌트를 구축할 수 있습니다. 즉, 사용자 정의 컴포넌트에 Starlight UI 컴포넌트를 가져와 렌더링할 수 있습니다. 이를 통해 기존 Starlight UI를 유지하면서 새로운 UI를 추가할 수 있습니다. + +아래 예시는 기존 `SocialIcons` 컴포넌트와 함께 이메일 링크를 렌더링하는 사용자 정의 컴포넌트를 나타냅니다. + +```astro {3,7} +--- +// src/components/EmailLink.astro +import Default from '@astrojs/starlight/components/SocialIcons.astro'; +--- + +<a href="mailto:houston@example.com">메일 보내기</a> +<Default><slot /></Default> +``` + +사용자 정의 컴포넌트 내부에 내장 컴포넌트를 렌더링할 때 기본 컴포넌트 내부에 [`<slot />`](https://docs.astro.build/ko/basics/astro-components/#슬롯)을 추가하세요. 이렇게 하면 컴포넌트에 자식 요소가 전달될 경우 Astro가 해당 요소를 렌더링할 위치를 알 수 있습니다. + +[명명된 슬롯](https://docs.astro.build/ko/basics/astro-components/#명명된-슬롯)이 포함된 [`PageFrame`](/ko/reference/overrides/#pageframe) 또는 [`TwoColumnContent`](/ko/reference/overrides/#twocolumncontent) 컴포넌트를 재사용하는 경우 이러한 슬롯도 [전송](https://docs.astro.build/ko/basics/astro-components/#슬롯-전송)해야 합니다. + +아래 예시는 `TwoColumnContent` 컴포넌트를 재사용하는 사용자 정의 컴포넌트를 보여줍니다. 이 컴포넌트는 `right-sidebar`라는 이름의 추가 슬롯을 포함하여 전송합니다. + +```astro {8} +--- +// src/components/CustomContent.astro +import Default from '@astrojs/starlight/components/TwoColumnContent.astro'; +--- + +<Default> + <slot /> + <slot name="right-sidebar" slot="right-sidebar" /> +</Default> +``` + +## 페이지 데이터 사용 + +Starlight 컴포넌트를 재정의할 때, 현재 페이지의 모든 데이터를 포함하는 전역 [`starlightRoute` 객체](/ko/guides/route-data/)에 접근할 수 있습니다. + +전달받은 값을 사용하여 컴포넌트 템플릿이 렌더링되는 방식을 제어할 수 있습니다. + +다음 예제에서 대체된 [`PageTitle`](/ko/reference/overrides/#pagetitle) 컴포넌트는 콘텐츠 프런트매터에 설정된 현재 페이지의 제목을 표시합니다: + +```astro {4} "{title}" +--- +// src/components/Title.astro + +const { title } = Astro.locals.starlightRoute.entry.data; +--- + +<h1 id="_top">{title}</h1> + +<style> + h1 { + font-family: 'Comic Sans'; + } +</style> +``` + +[경로 데이터 참조](/ko/reference/route-data/)에서 사용 가능한 모든 속성에 대해 자세히 알아보세요. + +### 특정 페이지 재정의 + +컴포넌트 재정의는 모든 페이지에 적용됩니다. 하지만, 사용자 정의 UI, Starlight의 기본 UI, 또는 완전히 다른 무언가가 나타나는 시기를 결정하기 위해 `starlightRoute`의 값을 사용하여 조건부 렌더링이 가능합니다. + +다음 예시에서 Starlight의 [`Footer`](/ko/reference/overrides/#footer)를 재정의하는 컴포넌트는 "Starlight 🌟 를 사용하여 구축"을 홈페이지에만 표시하고, 다른 모든 페이지에는 기본 바닥글만 표시합니다. + +```astro +--- +// src/components/ConditionalFooter.astro +import Default from '@astrojs/starlight/components/Footer.astro'; + +const isHomepage = Astro.locals.starlightRoute.id === ''; +--- + +{ + isHomepage ? ( + <footer>Starlight 🌟 를 사용하여 구축</footer> + ) : ( + <Default> + <slot /> + </Default> + ) +} +``` + +[Astro의 템플릿 구문 가이드](https://docs.astro.build/ko/basics/astro-syntax/#동적-html)에서 조건부 렌더링에 대해 자세히 알아보세요. diff --git a/docs/src/content/docs/ko/guides/pages.mdx b/docs/src/content/docs/ko/guides/pages.mdx new file mode 100644 index 00000000000..c859cfc3e8d --- /dev/null +++ b/docs/src/content/docs/ko/guides/pages.mdx @@ -0,0 +1,230 @@ +--- +title: 페이지 +description: Starlight를 사용하여 문서 사이트의 페이지를 만들고 관리하는 방법을 알아보세요. +sidebar: + order: 1 +tableOfContents: + maxHeadingLevel: 4 +--- + +Starlight는 Markdown Frontmatter를 통해 제공되는 유연한 옵션을 사용하여 콘텐츠를 기반으로 사이트의 HTML 페이지를 생성합니다. +또한 Starlight 프로젝트는 [Astro의 강력한 페이지 생성 도구](https://docs.astro.build/ko/basics/astro-pages/)에 대한 전체 액세스 권한을 갖습니다. +이 가이드에서는 Starlight에서 페이지 생성이 작동하는 방식을 보여줍니다. + +## 콘텐츠 페이지 + +### 파일 형식 + +Starlight는 구성이 필요 없는 Markdown 및 MDX 콘텐츠 작성을 지원합니다. +Markdoc에 대한 지원은 ["Markdoc" 가이드](/ko/guides/authoring-content/#markdoc)를 참조하여 추가할 수 있습니다. + +### 페이지 추가 + +`src/content/docs/`에 `.md` 또는 `.mdx` 파일을 생성하여 사이트에 새 페이지를 추가하세요. +하위 폴더를 사용하여 파일을 정리하고 여러 경로 세그먼트를 생성하세요. + +예를 들어, 다음 파일 구조는 `example.com/hello-world` 및 `example.com/reference/faq`에 페이지를 생성합니다. + +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - reference/ + - faq.md + +</FileTree> + +### 타입 안정성을 갖춘 프론트매터 + +모든 Starlight 페이지는 페이지 표시 방법을 제어하기 위해 사용자 정의 가능한 [공통 프론트매터 속성 세트](/ko/reference/frontmatter/)를 공유합니다. + +```md +--- +title: 안녕하세요! +description: 이것은 내 Starlight 기반 사이트의 페이지입니다. +--- +``` + +중요한 사항을 잊어버리면 Starlight가 알려드립니다. + +## 사용자 정의 페이지 + +고급 사용 사례의 경우 `src/pages/` 디렉터리를 생성하여 사용자 정의 페이지를 추가할 수 있습니다. +`src/pages/` 디렉터리는 [Astro의 파일 기반 라우팅](https://docs.astro.build/ko/basics/astro-pages/#파일-기반-라우팅)을 사용하며 다른 페이지 형식에서 `.astro` 파일에 대한 지원을 포함합니다. +이는 완전히 사용자 정의된 레이아웃으로 페이지를 작성하거나 대체 데이터 소스에서 페이지를 생성해야 하는 경우에 유용합니다. + +예를 들어, 이 프로젝트는 `src/content/docs/`의 Markdown 콘텐츠를 `src/pages/`의 Astro 및 HTML 경로와 혼합합니다. + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - pages/ + - custom.astro + - archived.html + +</FileTree> + +[Astro 문서의 "페이지" 가이드](https://docs.astro.build/ko/basics/astro-pages/)에서 자세한 내용을 읽어보세요. + +### 사용자 정의 페이지에서 Starlight 디자인 사용 + +사용자 정의 페이지에서 Starlight 레이아웃을 사용하려면 [`<StarlightPage>` 컴포넌트](#starlightpage-컴포넌트)로 페이지 콘텐츠를 감싸세요. +이는 콘텐츠를 동적으로 생성하지만 여전히 Starlight의 디자인을 사용하려는 경우 유용할 수 있습니다. + +사용자 정의 페이지에서 [`<AnchorHeading>` 컴포넌트](#anchorheading-컴포넌트)를 사용하여 Starlight의 Markdown 앵커 링크 스타일과 일치하는 앵커 링크를 제목에 추가할 수 있습니다. + +```astro +--- +// src/pages/custom-page/example.astro +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +import CustomComponent from './CustomComponent.astro'; +--- + +<StarlightPage frontmatter={{ title: '사용자 정의 페이지' }}> + <p>사용자 정의 컴포넌트가 있는 사용자 정의 페이지입니다.</p> + <CustomComponent /> + + <AnchorHeading level="2" id="learn-more">자세히 알아보기</AnchorHeading> + <p> + <a href="https://starlight.astro.build/"> + Starlight 문서에서 자세히 알아보기 + </a> + </p> +</StarlightPage> +``` + +#### `<StarlightPage>` 컴포넌트 + +`<StarlightPage />` 컴포넌트는 Starlight의 레이아웃과 스타일을 사용하여 전체 페이지 콘텐츠를 렌더링합니다. + +```astro +--- +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +--- + +<StarlightPage frontmatter={{ title: '사용자 정의 페이지' }}> + <!-- 사용자 정의 페이지 콘텐츠 --> +</StarlightPage> +``` + +`<StarlightPage />` 컴포넌트는 다음 props를 허용합니다. + +##### `frontmatter` + +**필수** +**타입:** `StarlightPageFrontmatter` + +Markdown 페이지의 프론트매터와 유사하게 이 페이지에 대한 [프론트매터 속성](/ko/reference/frontmatter/)을 설정합니다. +[`title`](/ko/reference/frontmatter/#title-필수) 속성은 필수이며 다른 모든 속성은 선택 사항입니다. + +다음 속성은 Markdown 프론트매터와 다릅니다. + +- [`slug`](/ko/reference/frontmatter/#slug) 속성은 지원되지 않으며 사용자 정의 페이지의 URL을 기반으로 자동 설정됩니다. +- [`editUrl`](/ko/reference/frontmatter/#editurl) 옵션에는 편집 링크를 표시하기 위한 URL이 필요합니다. +- [자동 생성된 링크 그룹](/ko/reference/configuration/#sidebar)에서 페이지가 표시되는 방식을 사용자 정의하기 위한 [`sidebar`](/ko/reference/frontmatter/#sidebar) 프론트매터 속성을 사용할 수 없습니다. `<StarlightPage />` 컴포넌트를 사용하는 페이지는 컬렉션의 일부가 아니며 자동 생성된 사이드바 그룹에 추가될 수 없습니다. +- [`draft`](/ko/reference/frontmatter/#draft) 옵션은 페이지가 초안이라는 [알림](/ko/reference/overrides/#draftcontentnotice)만 표시할 뿐 프로덕션 빌드에서 자동으로 제외하지는 않습니다. + +##### `sidebar` + +**타입:** [`SidebarItem[]`](/ko/reference/configuration/#sidebaritem) +**기본값:** [전역 `sidebar` 구성](/ko/reference/configuration/#sidebar)을 기반으로 생성된 사이드바 + +이 페이지에 대한 사용자 정의 사이트 탐색 사이드바를 제공합니다. +설정하지 않으면 페이지에서 기본 전역 사이드바를 사용합니다. + +예를 들어, 다음 페이지는 홈페이지 링크와 다양한 다른 사용자 지정 페이지로 연결되는 링크 그룹으로 기본 사이드바를 재정의합니다. + +```astro {3-13} +<StarlightPage + frontmatter={{ title: '오리온' }} + sidebar={[ + { label: '홈', link: '/' }, + { + label: '별자리', + items: [ + { label: '안드로메다', link: '/andromeda/' }, + { label: '오리온', link: '/orion/' }, + { label: '작은곰자리', link: '/ursa-minor/', badge: 'Stub' }, + ], + }, + ]} +> + 예시 콘텐츠 +</StarlightPage> +``` + +사이드바를 사용자 정의하기 위해 사용할 수 있는 옵션에 대해 자세히 알아보려면 [“사이드바 탐색”](/ko/guides/sidebar/) 가이드를 참조하세요. + +##### `hasSidebar` + +**타입:** `boolean` +**기본값:** [`frontmatter.template`](/ko/reference/frontmatter/#template)의 값이 `'splash'`라면 `false`, 그렇지 않다면 `true` + +이 페이지에 사이드바를 표시할지 여부를 제어합니다. + +##### `headings` + +**타입:** `{ depth: number; slug: string; text: string }[]` +**기본값:** `[]` + +이 페이지의 모든 제목 배열을 제공하세요. +제공된 경우 Starlight는 이 제목에서 페이지 목차를 생성합니다. + +##### `dir` + +**타입:** `'ltr' | 'rtl'` +**기본값:** 현재 로케일의 쓰기 방향 + +이 페이지 콘텐츠의 쓰기 방향을 설정합니다. + +##### `lang` + +**타입:** `string` +**기본값:** 현재 로케일의 언어 + +이 페이지 콘텐츠에 대해 BCP-47 언어 태그를 설정합니다. 예: `en`, `zh-CN` 또는 `pt-BR`. + +##### `isFallback` + +**타입:** `boolean` +**기본값:** `false` + +현재 언어에 대한 번역이 존재하지 않아 이 페이지가 [대체 콘텐츠](/ko/guides/i18n/#대체-콘텐츠)를 사용하고 있는지 표시합니다. + +#### `<AnchorHeading>` 컴포넌트 + +`<AnchorHeading />` 컴포넌트는 Starlight의 Markdown 스타일과 일치하는 클릭 가능한 앵커 링크가 있는 HTML 제목 요소를 렌더링합니다. + +```astro +--- +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +--- + +<AnchorHeading level="2" id="sub-heading">하위 제목</AnchorHeading> +``` + +이 컴포넌트는 다음과 같은 props 뿐만 아니라 다른 유효한 [전역 HTML 속성](https://developer.mozilla.org/ko/docs/Web/HTML/Reference/Global_attributes)도 허용합니다. + +##### `level` + +**필수** +**타입:** `1 | 2 | 3 | 4 | 5 | 6` + +렌더링할 제목 수준입니다. +예를 들어, `level="1"`은 `<h1>` 요소를 렌더링합니다. + +##### `id` + +**필수** +**타입:** `string` + +이 제목의 고유 ID입니다. +이는 렌더링된 제목의 `id` 속성으로 사용되며, 앵커 아이콘은 이 ID로 연결됩니다. diff --git a/docs/src/content/docs/ko/guides/project-structure.mdx b/docs/src/content/docs/ko/guides/project-structure.mdx index 5dcae9f3ff7..04d8c56e950 100644 --- a/docs/src/content/docs/ko/guides/project-structure.mdx +++ b/docs/src/content/docs/ko/guides/project-structure.mdx @@ -5,22 +5,22 @@ description: Starlight 프로젝트에서 파일을 구성하는 방법을 알 이 가이드에서는 Starlight 프로젝트가 구성되는 방법과 프로젝트의 다양한 파일이 수행하는 작업을 보여줍니다. -Starlight 프로젝트는 일반적으로 다른 Astro 프로젝트와 동일한 파일 및 디렉토리 구조를 따릅니다. 자세한 내용은 [Astro의 프로젝트 구조 문서](https://docs.astro.build/ko/core-concepts/project-structure/)를 참조하세요. +Starlight 프로젝트는 일반적으로 다른 Astro 프로젝트와 동일한 파일 및 디렉터리 구조를 따릅니다. 자세한 내용은 [Astro의 프로젝트 구조 문서](https://docs.astro.build/ko/basics/project-structure/)를 참조하세요. -## 파일 및 디렉토리 +## 파일 및 디렉터리 - `astro.config.mjs` — Starlight 통합 및 구성이 포함된 Astro 구성 파일 입니다. -- `src/content/config.ts` — Starlight의 frontmatter 스키마를 프로젝트에 추가하는 콘텐츠 컬렉션 구성 파일입니다. -- `src/content/docs/` — 콘텐츠 파일들이 포함된 디렉토리입니다. Starlight는 이 디렉토리에 있는 `.md`, `.mdx` 또는 `.mdoc` 파일을 사이트의 페이지로 변환합니다. -- `src/content/i18n/` (선택적) — [국제화](/ko/guides/i18n/)를 지원하는 번역 데이터들이 포함된 디렉토리입니다. -- `src/` — 프로젝트의 기타 소스 코드 및 파일(컴포넌트, 스타일, 이미지 등)이 포함된 디렉토리입니다. -- `public/` — Astro에서 처리되지 않는 정적 자산(글꼴, 파비콘, PDF 등)이 포함된 디렉토리입니다. +- `src/content.config.ts` — Starlight의 프론트매터 스키마를 프로젝트에 추가하는 콘텐츠 컬렉션 구성 파일입니다. +- `src/content/docs/` — 콘텐츠 파일들이 포함된 디렉터리입니다. Starlight는 이 디렉터리에 있는 `.md`, `.mdx` 또는 `.mdoc` 파일을 사이트의 페이지로 변환합니다. +- `src/content/i18n/` (선택적) — [국제화](/ko/guides/i18n/)를 지원하는 번역 데이터들이 포함된 디렉터리입니다. +- `src/` — 프로젝트의 기타 소스 코드 및 파일(컴포넌트, 스타일, 이미지 등)이 포함된 디렉터리입니다. +- `public/` — Astro에서 처리되지 않는 정적 자산(글꼴, 파비콘, PDF 등)이 포함된 디렉터리입니다. ## 예시 프로젝트 -Starlight 프로젝트 디렉토리는 다음과 같습니다. +Starlight 프로젝트 디렉터리는 다음과 같습니다. -import FileTree from '../../../../components/file-tree.astro'; +import { FileTree } from '@astrojs/starlight/components'; <FileTree> @@ -39,8 +39,7 @@ import FileTree from '../../../../components/file-tree.astro'; - 01-getting-started.md - 02-advanced.md - index.mdx - - config.ts - - env.d.ts + - content.config.ts - astro.config.mjs - package.json - tsconfig.json diff --git a/docs/src/content/docs/ko/guides/route-data.mdx b/docs/src/content/docs/ko/guides/route-data.mdx new file mode 100644 index 00000000000..f58d1473470 --- /dev/null +++ b/docs/src/content/docs/ko/guides/route-data.mdx @@ -0,0 +1,137 @@ +--- +title: 경로 데이터 +description: Starlight의 페이지 데이터 모델이 페이지를 렌더링하는 데 어떻게 사용되는지, 그리고 이를 어떻게 사용자 정의할 수 있는지 알아보세요. +--- + +import { Steps } from '@astrojs/starlight/components'; + +Starlight가 문서에서 페이지를 렌더링할 때, 먼저 해당 페이지의 내용을 나타내는 경로 데이터 객체를 생성합니다. +이 가이드에서는 경로 데이터가 어떻게 생성되는지, 어떻게 사용하는지, 그리고 Starlight의 기본 동작을 수정하기 위해 어떻게 사용자 정의할 수 있는지 설명합니다. + +사용 가능한 속성의 전체 목록은 ["경로 데이터 참조"](/ko/reference/route-data/)를 확인하세요. + +## 경로 데이터란 무엇인가요? + +Starlight 경로 데이터는 단일 페이지를 렌더링하는 데 필요한 모든 정보를 담고 있는 객체입니다. +여기에는 현재 페이지에 대한 정보뿐만 아니라 Starlight 구성에서 생성된 데이터도 포함됩니다. + +## 경로 데이터 사용하기 + +Starlight의 모든 컴포넌트는 경로 데이터를 사용하여 각 페이지에 무엇을 렌더링할지 결정합니다. 예를 들어, [`siteTitle`](/ko/reference/route-data/#sitetitle) 문자열은 사이트 제목을 표시하는 데 사용되고, [`sidebar`](/ko/reference/route-data/#sidebar) 배열은 전역 사이드바 탐색을 렌더링하는 데 사용됩니다. + +Astro 컴포넌트에서 `Astro.locals.starlightRoute` 전역 변수를 통해 이 데이터에 접근할 수 있습니다. + +```astro title="example.astro" {2} +--- +const { siteTitle } = Astro.locals.starlightRoute; +--- + +<p>The title of this site is “{siteTitle}”</p> +``` + +예를 들어, [컴포넌트 재정의](/ko/guides/overriding-components/)를 구축하여 표시되는 내용을 사용자 정의할 때 유용할 수 있습니다. + +## 경로 데이터 사용자 정의 + +Starlight의 경로 데이터는 별도의 구성 없이 바로 작동합니다. +하지만 고급 사용 사례의 경우, 일부 또는 모든 페이지에 대한 경로 데이터를 사용자 정의하여 사이트 표시 방식을 변경할 수 있습니다. + +이는 [컴포넌트 재정의](/ko/guides/overriding-components/)와 유사한 개념이지만, Starlight가 데이터를 렌더링하는 방식을 수정하는 대신 Starlight가 렌더링하는 데이터를 수정합니다. + +### 경로 데이터 사용자 정의가 필요한 경우 + +경로 데이터 사용자 정의는 Starlight가 데이터를 처리하는 방식을 기존 구성 옵션으로는 불가능한 방식으로 수정하고 싶을 때 유용할 수 있습니다. + +예를 들어, 특정 페이지의 사이드바 항목을 필터링하거나 제목을 사용자 정의할 수 있습니다. 이와 같은 변경 사항은 Starlight의 기본 컴포넌트를 수정할 필요 없이 해당 컴포넌트에 전달되는 데이터만 수정하면 됩니다. + +### 경로 데이터를 사용자 정의하는 방법 + +"미들웨어"의 특수한 형태를 사용하여 경로 데이터를 사용자 정의할 수 있습니다. +이는 Starlight가 페이지를 렌더링할 때마다 호출되는 함수로, 경로 데이터 객체의 값을 수정할 수 있습니다. + +<Steps> + +1. Starlight의 `defineRouteMiddleware()` 유틸리티를 사용하여 `onRequest` 함수를 내보내는 새 파일을 만듭니다. + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware(() => {}); + ``` + +2. `astro.config.mjs`에서 경로 데이터 미들웨어 파일의 위치를 Starlight에 알려줍니다. + + ```js ins={9} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: '나의 즐거운 문서 사이트', + routeMiddleware: './src/routeData.ts', + }), + ], + }); + ``` + +3. `onRequest` 함수를 업데이트하여 경로 데이터를 수정합니다. + + 미들웨어가 받는 첫 번째 인자는 [Astro의 `context` 객체](https://docs.astro.build/ko/reference/api-reference/)입니다. + 여기에는 현재 URL과 `locals`를 포함하여 현재 페이지 렌더링에 대한 모든 정보가 포함되어 있습니다. + + 이 예제에서는 모든 페이지 제목의 끝에 느낌표를 추가하여 문서를 더욱 흥미롭게 만들 것입니다. + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware((context) => { + // 이 페이지의 콘텐츠 컬렉션 항목을 가져옵니다. + const { entry } = context.locals.starlightRoute; + // 제목에 느낌표를 추가하여 업데이트합니다. + entry.data.title = entry.data.title + '!'; + }); + ``` + +</Steps> + +#### 여러 경로 미들웨어 + +Starlight는 여러 개의 미들웨어 제공도 지원합니다. +둘 이상의 미들웨어 핸들러를 추가하려면 `routeMiddleware`를 경로 배열로 설정하세요. + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: '여러 미들웨어가 있는 내 사이트', + routeMiddleware: ['./src/middleware-one.ts', './src/middleware-two.ts'], + }), + ], +}); +``` + +#### 추가된 경로 미들웨어 대기 + +코드 실행 전에 스택에 추가된 미들웨어가 실행될 때까지 기다리려면 미들웨어 함수에 두 번째 인자로 전달되는 `next()` 콜백을 await할 수 있습니다. +예를 들어, 변경하기 전에 플러그인의 미들웨어가 실행될 때까지 기다리는 데 유용할 수 있습니다. + +```ts "next" "await next();" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware(async (context, next) => { + // 추가된 미들웨어가 실행될 때까지 기다립니다. + await next(); + // 경로 데이터를 수정합니다. + const { entry } = context.locals.starlightRoute; + entry.data.title = entry.data.title + '!'; +}); +``` diff --git a/docs/src/content/docs/ko/guides/sidebar.mdx b/docs/src/content/docs/ko/guides/sidebar.mdx index da8d5da39da..28000960c73 100644 --- a/docs/src/content/docs/ko/guides/sidebar.mdx +++ b/docs/src/content/docs/ko/guides/sidebar.mdx @@ -1,12 +1,10 @@ --- title: 사이드바 탐색 description: Starlight 사이트의 사이드바 탐색 링크를 설정하고 사용자 정의하는 방법을 알아보세요. -sidebar: - badge: New --- -import FileTree from '../../../../components/file-tree.astro'; -import SidebarPreview from '../../../../components/sidebar-preview.astro'; +import { FileTree } from '@astrojs/starlight/components'; +import SidebarPreview from '~/components/sidebar-preview.astro'; 잘 구성된 사이드바는 사용자가 사이트를 탐색하는 주요 방법 중 하나이므로 좋은 문서의 핵심입니다. Starlight는 사이드바 레이아웃과 콘텐츠를 변경할 수 있는 완전한 옵션 세트를 제공합니다. @@ -21,11 +19,11 @@ import SidebarPreview from '../../../../components/sidebar-preview.astro'; - src/ - content/ - docs/ - - guides/ - - components.md - - i18n.md - - reference/ - - configuration.md + - constellations/ + - andromeda.md + - orion.md + - stars/ + - betelgeuse.md </FileTree> @@ -34,17 +32,15 @@ import SidebarPreview from '../../../../components/sidebar-preview.astro'; <SidebarPreview config={[ { - label: 'guides', + label: 'constellations', items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, + { label: '안드로메다', link: '' }, + { label: '오리온', link: '' }, ], }, { - label: 'reference', - items: [ - { label: 'Configuration Reference', link: '/reference/configuration/' }, - ], + label: 'stars', + items: [{ label: '베텔게우스', link: '' }], }, ]} /> @@ -53,21 +49,75 @@ import SidebarPreview from '../../../../components/sidebar-preview.astro'; ## 링크 및 링크 그룹 추가 -`astro.config.mjs` 파일의 [`starlight.sidebar`](/ko/reference/configuration/#sidebar) 속성을 사용하여 사이드바 [링크](#링크) 및 [링크 그룹](#그룹) (접이식 헤더 및 하위 항목들)을 구성할 수 있습니다. +`astro.config.mjs` 파일의 [`starlight.sidebar`](/ko/reference/configuration/#sidebar) 속성을 사용하여 사이드바 링크 및 링크 그룹 (접이식 헤더 및 하위 항목들)을 구성할 수 있습니다. 링크와 그룹을 결합하여 다양한 사이드바 레이아웃을 만들 수 있습니다. -### 링크 +### 내부 링크 -`label` 및 `link` 속성이 있는 객체를 사용하여 내부 또는 외부 페이지에 대한 링크를 추가할 수 있습니다. +`src/content/docs/`에서 `slug` 속성이 있는 객체를 사용하여 페이지로 이동하는 링크를 추가합니다. +링크된 페이지의 제목은 기본적으로 라벨로 사용됩니다. -```js +예를 들어, 구성은 다음과 같습니다. + +```js "slug:" starlight({ sidebar: [ - // CSS 및 스타일링 가이드 링크 - { label: 'CSS & 스타일링', link: '/ko/guides/css-and-tailwind/' }, - // Astro 웹사이트로 연결되는 외부 링크 - { label: 'Astro', link: 'https://astro.build/' }, + { slug: 'constellations/andromeda' }, + { slug: 'constellations/orion' }, + ], +}); +``` + +파일 구조는 다음과 같습니다. + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - andromeda.md + - orion.md + +</FileTree> + +다음 사이드바가 생성됩니다. + +<SidebarPreview + config={[ + { label: '안드로메다', link: '' }, + { label: '오리온', link: '' }, + ]} +/> + +링크된 페이지의 프런트매터에서 추론된 값을 재정의하기 위해 `label`, [`translations`](#국제화) 및 [`attrs`](#사용자-정의-html-속성) 속성을 추가할 수 있습니다. + +페이지 프런트매터에서 사이드바 모양을 제어하는 방법에 대한 자세한 내용은 ["자동 생성된 링크 사용자 정의"](#프런트매터에서-자동-생성된-링크-사용자-정의)를 참조하세요. + +#### 내부 링크의 약어 + +페이지 슬러그에 대한 문자열만 약식으로 제공하여 내부 링크를 지정할 수도 있습니다. + +예를 들어, 다음 구성은 `slug`를 사용한 위 구성과 동일합니다. + +```js "slug:" +starlight({ + sidebar: ['constellations/andromeda', 'constellations/orion'], +}); +``` + +### 기타 링크 + +`label` 및 `link` 속성이 있는 객체를 사용하여 외부 또는 문서가 아닌 페이지에 대한 링크를 추가합니다. + +```js "label:" "link:" +starlight({ + sidebar: [ + // 이 사이트에서 문서가 아닌 페이지로 이동하는 링크 + { label: '유성 상점', link: '/shop/' }, + // NASA 웹사이트로 이동하는 외부 링크 + { label: 'NASA', link: 'https://www.nasa.gov/' }, ], }); ``` @@ -76,8 +126,8 @@ starlight({ <SidebarPreview config={[ - { label: 'CSS & 스타일링', link: '/ko/guides/css-and-tailwind/' }, - { label: 'Astro', link: 'https://astro.build/' }, + { label: '유성 상점', link: '/shop/' }, + { label: 'NASA', link: 'https://www.nasa.gov/' }, ]} /> @@ -87,22 +137,22 @@ starlight({ `label` 및 `items` 속성이 있는 객체를 사용하여 그룹을 추가합니다. `label`은 그룹의 제목으로 사용됩니다. `items` 배열에 링크나 하위 그룹을 추가할 수 있습니다. -```js +```js /^\s*(label:|items:)/ starlight({ sidebar: [ - // "가이드" 라벨이 붙은 링크 그룹 + // '별자리' 라벨이 붙은 링크 그룹 { - label: '가이드', + label: '별자리', items: [ - { label: '컴포넌트', link: '/ko/guides/components/' }, - { label: '국제화 (i18n)', link: '/ko/guides/i18n/' }, - // 중첩된 링크 그룹 + 'constellations/carina', + 'constellations/centaurus', + // 계절별 별자리에 대한 중첩된 링크 그룹 { - label: '스타일링', + label: '계절별', items: [ - { label: 'CSS', link: '/ko/guides/css-and-tailwind/' }, - { label: 'Tailwind', link: '/ko/guides/css-and-tailwind/' }, - { label: 'Shiki', link: '/ko/guides/css-and-tailwind/' }, + 'constellations/andromeda', + 'constellations/orion', + 'constellations/ursa-minor', ], }, ], @@ -116,17 +166,16 @@ starlight({ <SidebarPreview config={[ { - label: '가이드', + label: '별자리', items: [ - { label: '컴포넌트', link: '/ko/guides/components/' }, - { label: '국제화 (i18n)', link: '/ko/guides/i18n/' }, - // 중첩된 링크 그룹 + { label: '용골자리', link: '' }, + { label: '켄타우루스', link: '' }, { - label: '스타일링', + label: '계절별', items: [ - { label: 'CSS', link: '/ko/guides/css-and-tailwind/' }, - { label: 'Tailwind', link: '/ko/guides/css-and-tailwind/' }, - { label: 'Shiki', link: '/ko/guides/css-and-tailwind/' }, + { label: '안드로메다', link: '' }, + { label: '오리온', link: '' }, + { label: '작은곰자리', link: '' }, ], }, ], @@ -136,17 +185,19 @@ starlight({ ### 자동 생성 그룹 -Starlight는 문서 디렉토리를 기반해서 자동으로 사이드바에 그룹을 생성할 수 있습니다. 이는 그룹의 각 사이드바 항목을 수동으로 입력하고 싶지 않을 때 유용합니다. 기본적으로 페이지는 파일 이름을 알파벳순으로 정렬하여 사이드바에 표시합니다. +Starlight는 문서 디렉터리를 기반해서 자동으로 사이드바에 그룹을 생성할 수 있습니다. 이는 그룹의 각 사이드바 항목을 수동으로 입력하고 싶지 않을 때 유용합니다. + +기본적으로 페이지는 파일 [`slug`](/ko/reference/route-data/#slug)에 따라 알파벳순으로 정렬됩니다. -`label` 및 `autogenerate` 속성이 있는 객체를 사용하여 자동 생성 그룹을 추가합니다. `autogenerate` 구성은 사이드바 항목에 사용할 디렉토리를 지정해야 합니다. 예를 들어, 다음 구성을 사용할 수 있습니다. +`label` 및 `autogenerate` 속성이 있는 객체를 사용하여 자동 생성 그룹을 추가합니다. `autogenerate` 구성은 사이드바 항목에 사용할 디렉터리를 지정해야 합니다. 예를 들어, 다음 구성을 사용할 수 있습니다. -```js +```js "label:" "autogenerate:" starlight({ sidebar: [ { - label: '가이드', - // 'guides' 디렉토리에 대한 링크 그룹을 자동으로 생성 - autogenerate: { directory: 'guides' }, + label: '별자리', + // '별자리' 디렉토리에 대한 링크 그룹을 자동 생성 + autogenerate: { directory: 'constellations' }, }, ], }); @@ -159,11 +210,11 @@ starlight({ - src/ - content/ - docs/ - - guides/ - - components.md - - i18n.md - - advanced/ - - project-structure.md + - constellations/ + - carina.md + - centaurus.md + - seasonal/ + - andromeda.md </FileTree> @@ -172,32 +223,28 @@ starlight({ <SidebarPreview config={[ { - label: '가이드', + label: '별자리', items: [ - { label: '컴포넌트', link: '/ko/guides/components/' }, - { label: '국제화 (i18n)', link: '/ko/guides/i18n/' }, + { label: '용골자리', link: '' }, + { label: '켄타우루스', link: '' }, { - label: '고급', - items: [ - { - label: '프로젝트 구조', - link: '/ko/guides/project-structure/', - }, - ], + label: 'seasonal', + items: [{ label: '안드로메다', link: '' }], }, ], }, ]} /> -#### Frontmatter에서 자동으로 생성된 링크 변경하기 +## 프런트매터에서 자동 생성된 링크 사용자 정의 -자동으로 생성된 링크를 변경하려면 개별 페이지의 [`sidebar` frontmatter 필드](/ko/reference/frontmatter/#sidebar)를 사용하세요. +자동으로 생성된 링크를 변경하려면 개별 페이지의 [`sidebar` 프런트매터 필드](/ko/reference/frontmatter/#sidebar)를 사용하세요. -frontmatter에서 sidebar 옵션을 사용하면 [사용자 정의 라벨](/ko/reference/frontmatter/#label)을 설정하거나 링크에 [배지](/ko/reference/frontmatter/#badge)를 추가하거나 사이드바에서 링크를 [숨기거나](/ko/reference/frontmatter/#hidden) [사용자 정의 정렬 기준](/ko/reference/frontmatter/#order)을 설정할 수 있습니다. +프런트매터에서 sidebar 옵션을 사용하면 [사용자 정의 라벨](/ko/reference/frontmatter/#label)을 설정, [사용자 정의 속성](/ko/reference/frontmatter/#attrs) 사용, 링크에 [배지](/ko/reference/frontmatter/#badge) 추가, 사이드바에서 링크를 [숨기거나](/ko/reference/frontmatter/#hidden) [사용자 정의 정렬 기준](/ko/reference/frontmatter/#order)을 정의할 수 있습니다. -```md +```md "sidebar:" --- +# src/content/docs/example.md title: 나의 페이지 sidebar: # 링크에 대한 사용자 정의 라벨 설정 @@ -211,46 +258,110 @@ sidebar: --- ``` -위 frontmatter가 있는 페이지를 포함하는 자동 생성 그룹은 다음 사이드바를 생성합니다. +위 프런트매터가 있는 페이지를 포함하는 자동 생성 그룹은 다음 사이드바를 생성합니다. <SidebarPreview config={[ { - label: '가이드', + label: '안내서', items: [ - { label: '홈페이지', link: '#' }, + { label: '페이지', link: '' }, { label: '사용자 정의 사이드바 라벨', - link: '#', + link: '', badge: { text: 'New', variant: 'tip' }, }, - { label: '다른 페이지', link: '#' }, + { label: '기타 페이지', link: '' }, ], }, ]} /> :::note - -`sidebar` frontmatter 구성은 자동으로 생성된 링크에만 사용되며 수동으로 정의된 링크에서는 무시됩니다. - +`sidebar` 프런트매터 구성은 `slug` 속성으로 정의된 자동으로 생성된 그룹의 링크 및 문서 링크에만 사용됩니다. `link` 속성으로 정의된 링크에는 적용되지 않습니다. ::: ## 배지 -링크 라벨 옆에 배지를 표시하기 위해 링크에는 `badge` 속성이 포함될 수도 있습니다. +링크, 그룹, 자동 생성된 그룹은 라벨 옆에 배지를 표시하기 위해 `badge` 속성을 포함할 수도 있습니다. + +```js {9,16} +starlight({ + sidebar: [ + { + label: '별', + items: [ + // "초거성" 배지가 있는 링크 + { + link: '/stars/persei/', + badge: '초거성', + }, + ], + }, + // "Outdated" 배지가 있는 자동 생성된 그룹 + { + label: '위성', + badge: 'Outdated', + autogenerate: { directory: 'moons' }, + }, + ], +}); +``` + +위 구성은 다음 사이드바를 생성합니다. -```js +<SidebarPreview + config={[ + { + label: '별', + items: [ + { + label: '페르세우스', + link: '', + badge: { text: '초거성', variant: 'default' }, + }, + ], + }, + { + label: '위성', + badge: { text: 'Outdated', variant: 'default' }, + items: [ + { + label: '이오', + link: '', + }, + { + label: '유로파', + link: '', + }, + { + label: '가니메데', + link: '', + }, + ], + }, + ]} +/> + +### 배지 변형 및 맞춤 스타일 + +`text`, `variant`, `class` 속성이 있는 객체를 사용하여 배지 스타일을 맞춤설정하세요. + +`text`는 표시할 콘텐츠 (예: "New")를 나타냅니다. +기본적으로 배지는 사이트의 강조 색상을 사용합니다. 내장된 배지 스타일을 사용하려면 `variant` 속성의 값을 `note`, `tip`, `danger`, `caution`, `success` 중 하나로 설정하세요. + +선택적으로 `class` 속성을 CSS 클래스 이름으로 설정하여 사용자 정의 배지 스타일을 만들 수 있습니다. + +```js {9} starlight({ sidebar: [ { - label: '가이드', + label: '별', items: [ - // "New" 배지가 포함된 링크 + // 노란색 "Stub" 배지가 있는 링크 { - label: '컴포넌트', - link: '/ko/guides/components/', - badge: 'New', + link: '/stars/sirius/', + badge: { text: 'Stub', variant: 'caution' }, }, ], }, @@ -263,35 +374,39 @@ starlight({ <SidebarPreview config={[ { - label: '가이드', + label: '별', items: [ { - label: '컴포넌트', - link: '/ko/guides/components/', - badge: { text: 'New', variant: 'default' }, + label: '시리우스', + link: '', + badge: { text: 'Stub', variant: 'caution' }, }, ], }, ]} /> -### 배지 변형 +[배지를 사용하고 사용자 정의하는 방법](/ko/components/badges/#사용)에 대해 자세히 알아보세요. + +## 사용자 정의 HTML 속성 -`text` 및 `variant` 속성이 있는 객체를 사용하여 배지 스타일을 변경할 수 있습니다. +링크에는 사용자 정의 HTML 속성을 추가하기 위한 `attrs` 속성이 포함될 수도 있습니다. -`text`는 표시할 콘텐츠를 나타냅니다(예: "New"). `variant` 속성의 값을 `note`, `tip`, `danger`, `caution`, `success` 중 하나로 설정하여 사이트의 강조 색상을 사용하는 `default` 스타일을 변경하세요. +다음 예에서는 `attrs`를 사용하여 링크가 새 탭에서 열리도록 `target="_blank"` 속성을 추가하고 사용자 정의 스타일 속성을 적용하여 링크 레이블을 기울임꼴로 표시합니다. -```js +다음 예에서는 링크가 새 탭에서 열리도록 `target="_blank` 속성을 추가하고, 사용자 정의 `style` 속성을 적용하여 링크 레이블을 기울임꼴로 표시하기 위해 `attrs`를 사용합니다. + +```js {10} starlight({ sidebar: [ { - label: '가이드', + label: '리소스', items: [ - // 노란색 "실험적 기능" 배지가 포함된 링크 + // 새 탭에서 열리는 NASA 웹사이트로 이동하는 외부 링크 { - label: '컴포넌트', - link: '/ko/guides/components/', - badge: { text: '실험적 기능', variant: 'caution' }, + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { target: '_blank', style: 'font-style: italic' }, }, ], }, @@ -304,12 +419,81 @@ starlight({ <SidebarPreview config={[ { - label: '가이드', + label: '리소스', + items: [ + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { + target: '_blank', + style: 'font-style: italic', + }, + }, + ], + }, + ]} +/> + +### 자동 생성 링크의 사용자 정의 HTML 속성 + +`autogenerate` 구성의 `attrs` 속성을 정의하여 [자동 생성 그룹](#자동-생성-그룹)에 있는 모든 링크의 HTML 속성을 사용자 정의합니다. +개별 페이지에서는 [`sidebar.attrs` 프런트매터 필드](/ko/reference/frontmatter/#attrs)를 사용하여 사용자 정의 속성을 지정할 수 있으며, 이는 `autogenerate.attrs` 구성과 병합됩니다. + +예를 들어, 다음과 같은 구성을 사용할 수 있습니다. + +```js {9} +starlight({ + sidebar: [ + { + label: '별자리', + autogenerate: { + // 'constellations' 디렉터리에 대한 링크 그룹을 자동으로 생성합니다. + directory: 'constellations', + // 이 그룹의 모든 링크 라벨을 이탤릭체로 표시합니다. + attrs: { style: 'font-style: italic' }, + }, + }, + ], +}); +``` + +그리고 파일 구조는 다음과 같습니다. + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - carina.md + - centaurus.md + - seasonal/ + - andromeda.md + +</FileTree> + +다음과 같이 모든 자동 생성 링크가 이탤릭체로 표시된 사이드바가 생성됩니다. + +<SidebarPreview + config={[ + { + label: '별자리', items: [ + { label: '용골자리', link: '', attrs: { style: 'font-style: italic' } }, { - label: '컴포넌트', - link: '/ko/guides/components/', - badge: { text: '실험적 기능', variant: 'caution' }, + label: '켄타우루스', + link: '', + attrs: { style: 'font-style: italic' }, + }, + { + label: 'seasonal', + items: [ + { + label: '안드로메다', + link: '', + attrs: { style: 'font-style: italic' }, + }, + ], }, ], }, @@ -318,31 +502,112 @@ starlight({ ## 국제화 -링크 또는 그룹의 라벨을 지원되는 각 언어로 번역하기 위해 링크 및 그룹 항목에 `translations` 속성을 사용할 수 있습니다. +[BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags) 언어 태그를 지정하여 지원되는 각 언어에 대한 링크 또는 그룹 라벨을 번역하려면 링크 및 그룹 항목의 `translations` 속성을 사용하세요. `"en"`, `"ar"` 또는 `"zh-CN"`을 키로, 번역된 라벨을 값으로 사용합니다. `label` 속성은 기본 언어 및 번역이 제공되지 않는 언어를 위해 사용될 것입니다. -```js +```js {5-7,11-13,18-20} starlight({ sidebar: [ { - label: '가이드', + label: '별자리', translations: { - es: 'Guías', + 'pt-BR': 'Constelações', }, items: [ { - label: '컴포넌트', + label: '안드로메다', translations: { - es: 'Componentes', + 'pt-BR': 'Andrômeda', }, - link: '/ko/guides/components/', + slug: 'constellations/andromeda/', }, { - label: '국제화 (i18n)', + label: '전갈자리', translations: { - es: 'Internacionalización (i18n)', + 'pt-BR': 'Escorpião', + }, + slug: 'constellations/scorpius/', + }, + ], + }, + ], +}); +``` + +브라질 포르투갈어로 문서를 검색하면 다음 사이드바가 생성됩니다. + +<SidebarPreview + config={[ + { + label: 'Constelação', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +### 내부 링크 국제화 + +[내부 링크](#내부-링크)는 기본적으로 콘텐츠 프런트매터의 번역된 페이지 제목을 자동으로 사용합니다. + +```js {9-10} +starlight({ + sidebar: [ + { + label: '별자리', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { slug: 'constellations/andromeda' }, + { slug: 'constellations/scorpius' }, + ], + }, + ], +}); +``` + +브라질 포르투갈어로 문서를 탐색하면 다음 사이드바가 생성됩니다. + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +다국어 사이트에서는 `slug` 값에 URL의 언어 부분이 포함되지 않습니다. +예를 들어 `en/intro` 및 `pt-br/intro`에 페이지가 있는 경우, 사이드바를 구성할 때 슬러그는 `intro`입니다. + +### 배지 국제화 + +[배지](#배지)의 경우 `text` 속성은 문자열이며, 다국어 사이트의 경우 각 로케일별 값이 포함된 객체일 수 있습니다. +객체 양식을 사용하는 경우 키는 [BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags) 태그 (예: `en`, `ar` 또는 `zh-CN`)여야 합니다: + +```js {11-16} +starlight({ + sidebar: [ + { + label: '별자리', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { + slug: 'constellations/andromeda', + badge: { + text: { + ko: '새 항목', + 'pt-BR': 'Novo', + }, }, - link: '/ko/guides/i18n/', }, ], }, @@ -350,15 +615,18 @@ starlight({ }); ``` -스페인어로 문서를 검색하면 다음 사이드바가 생성됩니다. +브라질 포르투갈어로 문서를 검색하면 다음과 같은 사이드바가 생성됩니다: <SidebarPreview config={[ { - label: 'Guías', + label: 'Constelações', items: [ - { label: 'Componentes', link: '/ko/guides/components/' }, - { label: 'Internacionalización (i18n)', link: '/ko/guides/i18n/' }, + { + label: 'Andrômeda', + link: '', + badge: { text: 'Novo', variant: 'default' }, + }, ], }, ]} @@ -368,17 +636,14 @@ starlight({ `collapsed` 속성을 `true`로 설정하면 링크 그룹의 기본 상태를 접힌 상태로 만들 수 있습니다. -```js +```js {5-6} starlight({ sidebar: [ { - label: '가이드', - // 접힌 상태를 기본 상태로 설정 + label: '별자리', + // 기본적으로 그룹을 축소 collapsed: true, - items: [ - { label: '컴포넌트', link: '/ko/guides/components/' }, - { label: '국제화 (i18n)', link: '/ko/guides/i18n/' }, - ], + items: ['constellations/andromeda', 'constellations/orion'], }, ], }); @@ -389,11 +654,11 @@ starlight({ <SidebarPreview config={[ { - label: '가이드', + label: '별자리', collapsed: true, items: [ - { label: '컴포넌트', link: '/ko/guides/components/' }, - { label: '국제화 (i18n)', link: '/ko/guides/i18n/' }, + { label: '안드로메다', link: '' }, + { label: '오리온', link: '' }, ], }, ]} @@ -401,14 +666,14 @@ starlight({ [자동 생성 그룹](#자동-생성-그룹)은 상위 그룹의 `collapsed` 값을 따릅니다. -```js +```js {5-6} starlight({ sidebar: [ { - label: '가이드', + label: '별자리', // 그룹 및 자동으로 생성된 하위 그룹의 기본 상태가 접힌 상태가 됩니다. collapsed: true, - autogenerate: { directory: 'guides' }, + autogenerate: { directory: 'constellations' }, }, ], }); @@ -419,17 +684,15 @@ starlight({ <SidebarPreview config={[ { - label: '가이드', + label: '별자리', collapsed: true, items: [ - { label: '컴포넌트', link: '/ko/guides/components/' }, - { label: '국제화 (i18n)', link: '/ko/guides/i18n/' }, + { label: '용골자리', link: '' }, + { label: '켄타우루스', link: '' }, { - label: '고급', + label: 'seasonal', collapsed: true, - items: [ - { label: '프로젝트 구조', link: '/ko/guides/project-structure/' }, - ], + items: [{ label: '안드로메다', link: '' }], }, ], }, @@ -438,14 +701,14 @@ starlight({ `autogenerate.collapsed` 속성을 정의하여 이 동작을 변경할 수 있습니다. -```js +```js {5-7} "collapsed: true" starlight({ sidebar: [ { - label: '가이드', - // "가이드" 그룹은 축소하지 않고, 자동 생성된 하위 그룹을 축소합니다. + label: '별자리', + // "별자리" 그룹을 축소하지 말고 자동 생성된 하위 그룹을 축소합니다. collapsed: false, - autogenerate: { directory: 'guides', collapsed: true }, + autogenerate: { directory: 'constellations', collapsed: true }, }, ], }); @@ -456,16 +719,14 @@ starlight({ <SidebarPreview config={[ { - label: '가이드', + label: '별자리', items: [ - { label: '컴포넌트', link: '/ko/guides/components/' }, - { label: '국제화 (i18n)', link: '/ko/guides/i18n/' }, + { label: '용골자리', link: '' }, + { label: '켄타우루스', link: '' }, { - label: '고급', + label: 'seasonal', collapsed: true, - items: [ - { label: '프로젝트 구조', link: '/ko/guides/project-structure/' }, - ], + items: [{ label: '안드로메다', link: '' }], }, ], }, diff --git a/docs/src/content/docs/ko/guides/site-search.mdx b/docs/src/content/docs/ko/guides/site-search.mdx new file mode 100644 index 00000000000..5d180c2eaad --- /dev/null +++ b/docs/src/content/docs/ko/guides/site-search.mdx @@ -0,0 +1,244 @@ +--- +title: 사이트 검색 +description: Starlight에 내장된 사이트 검색 기능과 이를 사용자 정의하는 방법에 대해 알아보세요. +tableOfContents: + maxHeadingLevel: 4 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +기본적으로 Starlight 사이트에는 정적 사이트를 위한 빠르고 낮은 대역폭을 갖춘 검색 도구인 [Pagefind](https://pagefind.app/)에서 제공하는 전체 텍스트 검색이 포함되어 있습니다. + +검색을 활성화하는 데 구성이 필요하지 않습니다. 사이트를 구축하고 배포한 다음, 사이트 헤더의 검색창을 사용하여 콘텐츠를 찾을 수 있습니다. + +## 검색결과에서 콘텐츠 숨기기 + +### 페이지 제외 + +검색 색인에서 페이지를 제외하려면 페이지 프런트매터에 [`pagefind: false`](/ko/reference/frontmatter/#pagefind)를 추가하세요. + +```md title="src/content/docs/not-indexed.md" ins={3} +--- +title: 검색에서 숨길 콘텐츠 +pagefind: false +--- +``` + +### 페이지 일부 제외 + +Pagefind는 [`data-pagefind-ignore`](https://pagefind.app/docs/indexing/#removing-individual-elements-from-the-index) 속성이 있는 요소 내부의 콘텐츠를 무시합니다. + +다음 예시에서 첫 번째 단락은 검색 결과에 표시되지만 `<div>`의 내용은 표시되지 않습니다. + +```md title="src/content/docs/partially-indexed.md" ins="data-pagefind-ignore" +--- +title: 부분적으로 색인이 생성된 페이지 +--- + +이 텍스트는 검색을 통해 찾을 수 있습니다. + +<div data-pagefind-ignore> + +이 텍스트는 검색에서 숨겨집니다. + +</div> +``` + +## 대체 검색 공급자 + +### Algolia DocSearch + +[Algolia의 DocSearch 프로그램](https://docsearch.algolia.com/)에 대한 액세스 권한이 있고, 이를 Pagefind 대신 사용하려는 경우, 공식 Starlight DocSearch 플러그인을 사용할 수 있습니다. + +<Steps> + +1. `@astrojs/starlight-docsearch`를 설치합니다. + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-docsearch + ``` + + </TabItem> + + </Tabs> + +2. `astro.config.mjs` 파일의 Starlight [`plugins`](/ko/reference/configuration/#plugins) 구성에 DocSearch를 추가하고 Algolia `appId`, `apiKey`, `indexName`를 전달합니다. + + ```js ins={4,10-16} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'DocSearch를 사용하는 사이트', + plugins: [ + starlightDocSearch({ + appId: 'YOUR_APP_ID', + apiKey: 'YOUR_SEARCH_API_KEY', + indexName: 'YOUR_INDEX_NAME', + }), + ], + }), + ], + }); + ``` + +</Steps> + +이 업데이트된 구성을 사용하면 사이트의 검색 창에서 기본 검색 모달 대신 Algolia 모달이 열립니다. + +#### DocSearch 구성 + +Starlight DocSearch 플러그인은 다음과 같은 인라인 옵션을 통해 DocSearch 컴포넌트를 사용자 지정할 수 있습니다: + +- `maxResultsPerGroup`: 각 검색 그룹에 표시되는 결과 수를 제한합니다. 기본값은 `5`입니다. +- `disableUserPersonalization`: DocSearch가 사용자의 최근 검색 및 즐겨찾기를 로컬 스토리지에 저장하지 못하도록 합니다. 기본값은 `false`입니다. +- `insights`: Algolia Insights 플러그인을 활성화하고 검색 이벤트를 DocSearch 인덱스로 보냅니다. 기본값은 `false`입니다. +- `searchParameters`: [Algolia Search Parameters](https://www.algolia.com/doc/api-reference/search-api-parameters/)를 사용자 정의하는 객체입니다. + +##### 추가 DocSearch 옵션 + +`transformItems()` 또는 `resultsFooterComponent()`와 같은 함수 옵션을 DocSearch 컴포넌트에 전달하려면 별도의 구성 파일이 필요합니다. + +<Steps> + +1. DocSearch 구성을 내보내는 TypeScript 파일을 만듭니다. + + ```ts + // src/config/docsearch.ts + import type { DocSearchClientOptions } from '@astrojs/starlight-docsearch'; + + export default { + appId: 'YOUR_APP_ID', + apiKey: 'YOUR_SEARCH_API_KEY', + indexName: 'YOUR_INDEX_NAME', + getMissingResultsUrl({ query }) { + return `https://github.com/algolia/docsearch/issues/new?title=${query}`; + }, + // ... + } satisfies DocSearchClientOptions; + ``` + +2. `astro.config.mjs`의 Starlight DocSearch 플러그인에 구성 파일 경로를 전달합니다. + + ```js {11-13} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Site with DocSearch', + plugins: [ + starlightDocSearch({ + clientOptionsModule: './src/config/docsearch.ts', + }), + ], + }), + ], + }); + ``` + +</Steps> + +지원되는 모든 옵션은 [DocSearch JavaScript 클라이언트 API 참조](https://docsearch.algolia.com/docs/api/)를 확인하세요. + +#### DocSearch UI 번역 + +DocSearch는 기본적으로 영어 UI 문자열만 제공합니다. +Starlight에 내장된 [국제화 시스템](/ko/guides/i18n/#starlight-ui-번역)을 사용하여 모달 UI 번역을 추가하세요. + +<Steps> + +1. `src/content.config.ts` 파일의 DocSearch 스키마를 사용하여 Starlight의 `i18n` 콘텐츠 컬렉션 정의를 확장합니다. + + ```js ins={5} ins=/{ extend: .+ }/ + // src/content.config.ts + import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; + import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + import { docSearchI18nSchema } from '@astrojs/starlight-docsearch/schema'; + + export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ extend: docSearchI18nSchema() }), + }), + }; + ``` + +2. `src/content/i18n/` 디렉터리에 있는 JSON 파일에 번역을 추가하세요. + + DocSearch에서 사용되는 영어 기본값은 다음과 같습니다. + + ```json title="src/content/i18n/en.json" + { + "docsearch.searchBox.resetButtonTitle": "Clear the query", + "docsearch.searchBox.resetButtonAriaLabel": "Clear the query", + "docsearch.searchBox.cancelButtonText": "Cancel", + "docsearch.searchBox.cancelButtonAriaLabel": "Cancel", + "docsearch.searchBox.searchInputLabel": "Search", + + "docsearch.startScreen.recentSearchesTitle": "Recent", + "docsearch.startScreen.noRecentSearchesText": "No recent searches", + "docsearch.startScreen.saveRecentSearchButtonTitle": "Save this search", + "docsearch.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", + "docsearch.startScreen.favoriteSearchesTitle": "Favorite", + "docsearch.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + + "docsearch.errorScreen.titleText": "Unable to fetch results", + "docsearch.errorScreen.helpText": "You might want to check your network connection.", + + "docsearch.footer.selectText": "to select", + "docsearch.footer.selectKeyAriaLabel": "Enter key", + "docsearch.footer.navigateText": "to navigate", + "docsearch.footer.navigateUpKeyAriaLabel": "Arrow up", + "docsearch.footer.navigateDownKeyAriaLabel": "Arrow down", + "docsearch.footer.closeText": "to close", + "docsearch.footer.closeKeyAriaLabel": "Escape key", + "docsearch.footer.searchByText": "Search by", + + "docsearch.noResultsScreen.noResultsText": "No results for", + "docsearch.noResultsScreen.suggestedQueryText": "Try searching for", + "docsearch.noResultsScreen.reportMissingResultsText": "Believe this query should return results?", + "docsearch.noResultsScreen.reportMissingResultsLinkText": "Let us know." + } + ``` + +</Steps> + +### 커뮤니티 검색 공급자 + +[커뮤니티 플러그인](/ko/resources/plugins/#커뮤니티-플러그인)은 Starlight의 기본 Pagefind 검색 공급자에 대한 대안을 제공할 수도 있습니다. + +#### Typesense DocSearch + +[Starlight DocSearch Typesense](https://starlight-docsearch.typesense.org/) 커뮤니티 플러그인은 [DocSearch](https://github.com/typesense/typesense-docsearch.js) 인터페이스와 [Typesense](https://typesense.org/) 백엔드를 통합하는 자체 호스팅 가능한 오픈 소스 대안을 제공합니다. + +프로젝트에서 사용하는 방법을 알아보려면 Starlight DocSearch Typesense 문서의 [“시작하기”](https://starlight-docsearch.typesense.org/getting-started/) 가이드를 참조하세요. diff --git a/docs/src/content/docs/ko/index.mdx b/docs/src/content/docs/ko/index.mdx index 105059824df..baa0bdf1e1d 100644 --- a/docs/src/content/docs/ko/index.mdx +++ b/docs/src/content/docs/ko/index.mdx @@ -1,56 +1,155 @@ --- -title: Starlight 🌟를 이용해 Astro로 문서 웹 사이트를 만드세요! -description: Starlight는 Astro를 이용해 고성능의 아름다운 문서 웹 사이트를 구축할 수 있도록 도와줍니다. +title: Starlight 🌟 Astro 문서 웹 사이트를 만드세요 +head: + - tag: title + content: Starlight 🌟 Astro 문서 웹 사이트를 만드세요 +description: Starlight로 아름답고 성능이 좋은 Astro 문서 웹 사이트를 만들 수 있습니다. template: splash -banner: - content: | - <span class="ph-banner"> - <span class="ph-houston"><img src="/ph-houston.svg" alt="" width="72" height="72"/></span> - <span class="ph-text"> - <strong>Product Hunters 분들을 모두 환영합니다! 👋</strong> - <a href="https://www.producthunt.com/posts/starlight-by-astro">현재 라이브 중입니다!</a> - </span> - </span> +editUrl: false +lastUpdated: false hero: - title: Starlight로 더 빛나는 문서를 만들어보세요 + title: Starlight로 멋진 문서를 만드세요 tagline: 아름다운 문서 웹 사이트를 만드는데 필요한 모든 것. 빠르고, 접근성이 좋으며 사용하기 쉽습니다. image: - file: ../../../assets/hero-star.webp + file: ~/assets/hero-star.webp actions: - text: 시작하기 icon: right-arrow - variant: primary link: /ko/getting-started/ - text: GitHub에서 보기 icon: external + variant: minimal link: https://github.com/withastro/starlight --- import { CardGrid, Card } from '@astrojs/starlight/components'; -import AboutAstro from '../../../components/about-astro.astro'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; <CardGrid stagger> <Card title="아름다운 문서" icon="open-book"> - 사이트 네비게이션, 검색창, 국제화, SEO, 읽기 쉬운 타이포그래피, 코드 - 하이라이팅, 다크 모드 등이 포함되어 있습니다. + 사이트 탐색, 검색, 국제화, SEO, 읽기 쉬운 타이포그래피, 구문 강조, 어두운 + 테마 등이 포함되어 있습니다. </Card> <Card title="Astro 기반" icon="rocket"> - Astro의 모든 기능과 성능을 활용하세요. 선호하는 Astro 통합 및 라이브러리로 + Astro의 힘과 성능을 활용하세요. 선호하는 Astro 통합 및 라이브러리로 Starlight를 확장하세요. </Card> <Card title="Markdown, Markdoc, MDX" icon="document"> 선호하는 마크업 언어를 사용하세요. Starlight는 TypeScript 타입 안정성을 갖춘 - 내장 frontmatter 유효성 검사를 제공합니다. + 내장 프론트매터 유효성 검사를 제공합니다. </Card> <Card title="선호하는 UI 컴포넌트 사용" icon="puzzle"> - Starlight는 프레임워크에 구애받지 않는 완벽한 문서 솔루션으로 제공됩니다. React, Vue, Svelte, Solid 등으로 확장하세요. + Starlight는 프레임워크에 구애받지 않는 완벽한 문서 솔루션으로 제공됩니다. + React, Vue, Svelte, Solid 등으로 확장하세요. </Card> - </CardGrid> -<AboutAstro title="제공"> +<TestimonialGrid title="사용 후기를 들어보세요"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + Astro 팀은 문서 작성 방법을 발전시켰으며 Starlight 프로젝트를 통해 모든 것을 즉시 사용할 수 있습니다. + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + Astro의 공식 시작 키트인 Starlight는 문서 웹 사이트 구축을 위한 정말 놀라운 도구입니다. + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + Starlight는 훌륭한 DX의 대표적인 예시입니다. 속도, 편리함, 세부 사항에 대한 관심이 인상적입니다. 기술과 디자인을 모두 관리하므로 콘텐츠에 집중할 수 있습니다 👏 + + StackBlitz 팀은 이 프로젝트를 정말 좋아합니다! + + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + Starlight는 제가 콘텐츠 제작에 집중할 수 있게 해준 게임 체인저였습니다. + + 직관적인 디자인은 작업 흐름을 간소화할 뿐만 아니라 오픈 소스 개발자의 온보딩 시간도 줄여줍니다. + + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + Course Builder 문서를 구축하기 위해 Starlight를 오래 사용하였으며 지금까지는 훌륭합니다. 많은 부분이 잘 만들어져 있기 때문에 사이트를 만지작거리지 않고 Markdown을 작성하는 데 집중할 수 있습니다. + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + Starlight를 사용하기 시작했습니다. 기본적으로 제공되는 성능에 깊은 인상을 받았습니다. + + 💯💯💯💯 -Astro는 빠른 속도를 위해 설계된 올인원 웹 프레임워크입니다. 선호하는 UI 컴포넌트와 라이브러리를 이용해 어디서든 컨텐츠를 가져와 배포하세요. + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + Starlight는 문서화를 시작하는 가장 좋은 방법입니다. Astro의 성능과 속도 및 Starlight 도구는 환상의 조합입니다. + + 한동안 계속 사용하였고, 계속해서 좋아하고 있어요! + + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + 나는 지난 직장에서 Starlight를 사용했고 정말 좋아했습니다. 훌륭한 컴포넌트, 직관적인 디자인, 반응이 빠른 커뮤니티 (누군가 필요한 것이 있을 때마다 즉시 배송하거나 해결 방법을 알려줍니다). 매우 즐거운 경험이었어요. + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + 내 모노레포 사이트의 문서는 Starlight 덕분에 그 어느 때보다 좋아 보입니다. Astro의 모든 기능을 잃지 않고 사용하기가 매우 쉽습니다. 작업해 주셔서 감사합니다! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + Starlight는 문서화를 위해 제가 즐겨 사용하는 도구입니다. 다른 도구와 함께 사용하기 위해 하위 도메인이 필요한 것에 비해 기존 Astro 제품 웹사이트에 문서를 추가하는 것이 매우 쉬워졌습니다. + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + 저는 WPEngine Atlas 플랫폼 문서를 다시 작성했습니다. Starlight에 A+ 문서 플랫폼을 만드는 데 필요한 모든 것이 있다고 말할 때 저를 믿으십시오. 🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + Starlight를 사용해 보세요! + + 나는 내 사이트 중 일부에 이 프로젝트를 사용하고 있으며 훌륭합니다. + + </Testimonial> +</TestimonialGrid> + +<AboutAstro title="제공"> +Astro는 빠른 속도를 위해 설계된 올인원 웹 프레임워크입니다. 선호하는 UI 컴포넌트와 라이브러리를 사용하여 어디서든 콘텐츠를 가져와 배포하세요. [Astro에 대해 알아보기](https://astro.build/) diff --git a/docs/src/content/docs/ko/manual-setup.mdx b/docs/src/content/docs/ko/manual-setup.mdx index 4a1556c55a2..bebae1ba1f9 100644 --- a/docs/src/content/docs/ko/manual-setup.mdx +++ b/docs/src/content/docs/ko/manual-setup.mdx @@ -5,7 +5,7 @@ description: Starlight를 기존 Astro 프로젝트에 추가하기 위해 수 import { Tabs, TabItem } from '@astrojs/starlight/components'; -새로운 Starlight 사이트를 시작하는 가장 빠른 방법은 [시작하기](/ko/getting-started/#새-프로젝트-시작하기)에 나와있는 것처럼 `create astro`를 사용하는 것입니다. 이 가이드에서는 기존 Astro 프로젝트에 Starlight를 추가하는 방법을 설명합니다. +새로운 Starlight 사이트를 시작하는 가장 빠른 방법은 [시작하기](/ko/getting-started/#새-프로젝트-생성)에 나와있는 것처럼 `create astro`를 사용하는 것입니다. 이 가이드에서는 기존 Astro 프로젝트에 Starlight를 추가하는 방법을 설명합니다. ## Starlight 설정 @@ -13,9 +13,9 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; ### Starlight 통합 추가 -Starlight는 [Astro 통합](https://docs.astro.build/ko/guides/integrations-guide/)입니다. 사이트에 이를 추가하기 위해 프로젝트의 루트 디렉토리에서 `astro add` 명령을 실행하세요. +Starlight는 [Astro 통합](https://docs.astro.build/ko/guides/integrations-guide/)입니다. 사이트에 이를 추가하기 위해 프로젝트의 루트 디렉터리에서 `astro add` 명령을 실행하세요. -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh npx astro add starlight @@ -43,7 +43,7 @@ Starlight 통합은 `astro.config.mjs` 파일에서 구성됩니다. 시작하려면 `title`을 추가하세요. -```js {7-9} +```js ins={8} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -61,25 +61,29 @@ export default defineConfig({ ### 콘텐츠 컬렉션 구성 -Starlight는 `src/content/config.ts` 파일에 구성된 Astro의 [콘텐츠 컬렉션](https://docs.astro.build/ko/guides/content-collections/) 위에 구축되었습니다. +Starlight는 `src/content.config.ts` 파일에 구성된 Astro의 [콘텐츠 컬렉션](https://docs.astro.build/ko/guides/content-collections/) 위에 구축되었습니다. -Starlight의 `docsSchema`를 사용하는 `docs` 컬렉션을 추가하여 콘텐츠 구성 파일을 생성하거나 업데이트하세요. +Starlight의 [`docsLoader`](/ko/reference/configuration/#docsloader) 및 [`docsSchema`](/ko/reference/configuration/#docsschema)를 사용하는 `docs` 컬렉션을 추가하여 콘텐츠 구성 파일을 생성하거나 업데이트하세요. -```js ins={3,6} -// src/content/config.ts +```js ins={3-4,7} +// src/content.config.ts import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; import { docsSchema } from '@astrojs/starlight/schema'; export const collections = { - docs: defineCollection({ schema: docsSchema() }), + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), }; ``` +Starlight는 레거시 콘텐츠 컬렉션 구현을 사용하여 컬렉션을 처리하는 [`legacy.collections` 플래그](https://docs.astro.build/ko/reference/legacy-flags/)도 지원합니다. +이 플래그는 기존 Astro 프로젝트가 있고 현재 로더를 사용하기 위해 컬렉션을 변경할 수 없는 경우에 유용합니다. + ### 콘텐츠 추가 이제 Starlight가 구성되었으며 콘텐츠를 추가할 시간입니다! -`src/content/docs/` 디렉토리를 생성한 후 `index.md` 파일을 추가하여 시작하세요. +`src/content/docs/` 디렉터리를 생성한 후 `index.md` 파일을 추가하여 시작하세요. 이것은 웹 사이트의 홈페이지가 됩니다. ```md @@ -100,11 +104,11 @@ Starlight는 파일 기반 라우팅을 사용합니다. 즉, `src/content/docs/ ### 하위 경로에서 Starlight 사용 -모든 Starlight 페이지를 하위 경로에 추가하려면 모든 문서 콘텐츠를 `src/content/docs/`의 하위 디렉토리에 배치하세요. +모든 Starlight 페이지를 하위 경로에 추가하려면 모든 문서 콘텐츠를 `src/content/docs/`의 하위 디렉터리에 배치하세요. -예를 들어, Starlight의 모든 페이지가 `/guides/`에서 시작해야 하는 경우 `src/content/docs/guides/` 디렉토리에 콘텐츠를 추가하세요. +예를 들어, Starlight의 모든 페이지가 `/guides/`에서 시작해야 하는 경우 `src/content/docs/guides/` 디렉터리에 콘텐츠를 추가하세요. -import FileTree from '../../../components/file-tree.astro'; +import { FileTree } from '@astrojs/starlight/components'; <FileTree> @@ -119,8 +123,10 @@ import FileTree from '../../../components/file-tree.astro'; </FileTree> -앞으로 우리는 `src/content/docs/`에 추가로 중첩된 디렉토리가 필요하지 않도록 이 사용 사례에 대한 지원을 더 늘릴 예정입니다. +앞으로 우리는 `src/content/docs/`에 추가로 중첩된 디렉터리가 필요하지 않도록 이 사용 사례에 대한 지원을 더 늘릴 예정입니다. ### SSR과 함께 Starlight 사용 -현재 Starlight는 Astro의 서버 어댑터를 사용한 [SSR 배포](https://docs.astro.build/ko/guides/server-side-rendering/)를 지원하지 않습니다. 우리는 곧 이것을 지원할 것입니다. +SSR을 사용하려면 Astro 문서에 있는 ["요청 시 렌더링 어댑터"](https://docs.astro.build/ko/guides/on-demand-rendering/) 가이드에 따라 Starlight 프로젝트에 서버 어댑터를 추가하세요. + +Starlight에서 생성된 문서 페이지는 프로젝트의 출력 모드에 관계없이 기본적으로 미리 렌더링됩니다. Starlight 페이지의 사전 렌더링을 선택 해제하려면 [`prerender` 구성 옵션](/ko/reference/configuration/#prerender)을 `false`로 설정하세요. diff --git a/docs/src/content/docs/ko/reference/configuration.md b/docs/src/content/docs/ko/reference/configuration.md deleted file mode 100644 index 20c09053a60..00000000000 --- a/docs/src/content/docs/ko/reference/configuration.md +++ /dev/null @@ -1,425 +0,0 @@ ---- -title: 구성 참조 -description: Starlight가 지원하는 모든 구성 옵션에 대한 개요입니다. ---- - -## `starlight` 통합 구성 - -Starlight는 [Astro](https://astro.build) 웹 프레임워크 위에 구축된 통합입니다. `astro.config.mjs` 구성 파일에서 프로젝트를 구성할 수 있습니다. - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: '즐거운 문서 사이트', - }), - ], -}); -``` - -`starlight` 통합에 다음 옵션을 전달할 수 있습니다. - -### `title` (필수) - -**타입:** `string` - -웹사이트의 제목을 설정합니다. 메타데이터 및 브라우저 탭 제목에 사용됩니다. - -### `description` - -**타입:** `string` - -웹사이트에 대한 설명을 설정합니다. 페이지의 frontmatter에 `description`이 설정되지 않은 경우, `<meta name="description">` 태그에서 검색 엔진과 공유되는 메타데이터로 사용됩니다. - -### `logo` - -**타입:** [`LogoConfig`](#logoconfig) - -사이트 제목을 대체하거나 사이트 제목과 함께 네비게이션 바에 표시되는 로고 이미지를 설정합니다. 단일 `src` 속성을 설정하거나 `light` 및 `dark` 속성에 다른 이미지 소스를 전달할 수 있습니다. - -```js -starlight({ - logo: { - src: './src/assets/my-logo.svg', - }, -}); -``` - -#### `LogoConfig` - -```ts -type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( - | { src: string } - | { light: string; dark: string } -); -``` - -### `tableOfContents` - -**타입:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` -**기본값:** `{ minHeadingLevel: 2; maxHeadingLevel: 3; }` - -각 페이지 오른쪽에 표시되는 목차를 구성합니다. 기본적으로 `<h2>` 및 `<h3>` 제목이 이 목차에 포함됩니다. - -### `editLink` - -**타입:** `{ baseUrl: string }` - -기본 URL을 설정하여 "페이지 편집" 링크를 활성화합니다. 최종 링크는 `editLink.baseUrl` + 현재 페이지 경로가 됩니다. 예를 들어, 다음 코드를 통해 GitHub의 `withastro/starlight` 저장소의 페이지 편집 기능을 활성화할 수 있습니다. - -```js -starlight({ - editLink: { - baseUrl: 'https://github.com/withastro/starlight/edit/main/', - }, -}); -``` - -이 구성을 통해 `/introduction` 페이지에 있는 편집 링크는 `https://github.com/withastro/starlight/edit/main/src/docs/introduction.md`를 가리킵니다. - -### `sidebar` - -**타입:** [`SidebarItem[]`](#sidebaritem) - -사이트의 사이드바 탐색 항목을 구성합니다. - -사이드바는 링크의 배열과 링크 그룹입니다. 각 항목은 `label`과 함께 다음 속성 중 하나를 반드시 포함해야합니다. - -- `link` — 특정 URL에 대한 단일 링크(예: `'/home'` 또는 `'https://example.com'`). - -- `items` — 더 많은 사이드바 링크와 하위 그룹을 포함하는 배열 - -- `autogenerate` — 링크 그룹을 자동으로 생성하기 위해 문서의 디렉토리를 지정하는 객체 - -```js -starlight({ - sidebar: [ - // '홈'이라는 라벨이 붙은 단일 링크 항목 - { label: '홈', link: '/' }, - // 두 개의 링크가 포함된 '여기서부터' 라는 라벨이 붙은 그룹 - { - label: '여기서부터', - items: [ - { label: '소개', link: '/intro' }, - { label: '다음 단계', link: '/next-steps' }, - ], - }, - // 'reference' 디렉토리의 모든 페이지에 연결되는 그룹 - { - label: '참조', - autogenerate: { directory: 'reference' }, - }, - ], -}); -``` - -#### 정렬 - -자동 생성된 사이드바 그룹은 파일 이름을 기준으로 알파벳순으로 정렬됩니다. 예를 들어 `astro.md`에서 생성된 페이지는 `starlight.md` 페이지 위에 표시됩니다. - -#### 그룹 최소화 - -링크 그룹은 기본적으로 펼쳐져 있습니다. 그룹의 `collapsed` 속성을 `true`로 설정하여 이 동작을 변경할 수 있습니다. - -자동 생성된 하위 그룹은 기본적으로 상위 그룹의 `collapsed` 속성을 따릅니다. 이를 변경하려면 `autogenerate.collapsed` 속성을 설정하세요. - -```js -sidebar: [ - // 최소화된 링크 그룹 - { - label: '최소화된 링크 모음', - collapsed: true, - items: [ - { label: '소개', link: '/intro' }, - { label: '다음 단계', link: '/next-steps' }, - ], - }, - // 최소화된 자동 생성 하위 그룹을 포함하는 펼쳐진 그룹 - { - label: '참조', - autogenerate: { - directory: 'reference', - collapsed: true, - }, - }, -], -``` - -#### 라벨 번역 - -다국어 사이트의 경우, 각 항목의 `label`은 기본 언어로 설정됩니다. `translations` 속성을 설정하여 지원하는 다른 언어로 된 라벨을 제공할 수 있습니다. - -```js -sidebar: [ - // 한국어로 번역된 라벨을 사용하는 사이드바 예시 - { - label: 'Start Here', - translations: { ko: '여기서부터' }, - items: [ - { - label: 'Getting Started', - translations: { ko: '시작하기' }, - link: '/getting-started', - }, - { - label: 'Project Structure', - translations: { ko: '프로젝트 구조' }, - link: '/structure', - }, - ], - }, -], -``` - -#### `SidebarItem` - -```ts -type SidebarItem = { - label: string; - translations?: Record<string, string>; -} & ( - | { link: string; badge?: string | BadgeConfig } - | { items: SidebarItem[]; collapsed?: boolean } - | { - autogenerate: { directory: string; collapsed?: boolean }; - collapsed?: boolean; - } -); -``` - -#### `BadgeConfig` - -```ts -interface BadgeConfig { - text: string; - variant: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; -} -``` - -### `locales` - -**타입:** <code>{ \[dir: string\]: [LocaleConfig](#localeconfig) }</code> - -지원되는 `locales`를 설정하여 사이트의 [국제화(i18n)를 구성](/ko/guides/i18n/)하세요. - -각 항목은 언어 파일이 저장된 디렉토리를 키로 사용해야 합니다. - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: '나의 사이트', - // 이 사이트의 기본 언어를 한국어로 설정합니다. - defaultLocale: 'ko', - locales: { - // 한국어 문서는 `src/content/docs/ko/`에 있습니다. - ko: { - label: '한국어', - }, - // 영어 문서는 `src/content/docs/en/`에 있습니다. - en: { - label: 'English', - lang: 'en', - }, - // 중국어 간체 문서는 `src/content/docs/zh/`에 있습니다. - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - // 아랍어 문서는 `src/content/docs/ar/`에 있습니다. - ar: { - label: 'العربية', - dir: 'rtl', - }, - }, - }), - ], -}); -``` - -#### `LocaleConfig` - -```ts -interface LocaleConfig { - label: string; - lang?: string; - dir?: 'ltr' | 'rtl'; -} -``` - -각 언어에 대해 다음 옵션을 설정할 수 있습니다. - -##### `label` (필수) - -**타입:** `string` - -언어의 라벨은 언어 변경 기능에서 사용자에게 보여지는 문자입니다. 대부분의 경우, `"English"`, `"العربية"`, 또는 `"简体中文"`와 같이 해당 언어를 사용하는 사용자가 읽을 것으로 예상되는 언어의 이름을 작성하는 것이 좋습니다. - -##### `lang` - -**타입:** `string` - -`"en"`, `"ar"` 또는 `"zh-CN"`와 같은 언어의 BCP-47 태그입니다. 설정하지 않으면 기본적으로 해당 언어의 디렉토리 이름이 사용됩니다. 지역 하위 태그가 있는 언어 태그(예: `"pt-BR"` 또는 `"en-US"`)는 지역별 번역이 없는 경우에 내장된 기본 언어 UI 번역을 사용합니다. - -##### `dir` - -**타입:** `'ltr' | 'rtl'` - -언어의 쓰기 방향입니다. `"ltr"`은 왼쪽에서 오른쪽으로 진행함을 나타내며 기본값입니다. `"rtl"`은 오른쪽에서 왼쪽으로 진행함을 나타냅니다. - -#### 루트 로케일 - -`root` 로케일을 설정하면 `/lang/` 디렉토리 없이 기본 언어를 제공할 수 있습니다. - -```js -starlight({ - locales: { - root: { - label: '한국어', - lang: 'ko', - }, - fr: { - label: 'Français', - }, - }, -}); -``` - -예를 들어, `/getting-started/`를 한국어 경로로 제공하고, `/fr/getting-started/`를 동일한 페이지의 프랑스어 버전으로 제공할 수 있습니다. - -### `defaultLocale` - -**타입:** `string` - -사이트의 기본 언어를 설정합니다. -값은 [`locales`](#locales) 객체의 키 중 하나와 일치해야 합니다. -(기본 언어가 [루트 로케일](#루트-로케일)인 경우 이 단계를 건너뛸 수 있습니다.) - -이 값은 번역이 누락된 대체 콘텐츠를 제공하는 데 사용됩니다. - -### `social` - -**타입:** `Partial<Record<'bitbucket' | 'codeberg' | 'codePen' | 'discord' | 'github' | 'gitlab' | 'gitter' | 'instagram' | 'linkedin' | 'mastodon' | 'microsoftTeams' | 'stackOverflow' | 'threads' | 'twitch' | 'twitter' | 'youtube', string>>` - -이 사이트의 소셜 미디어 계정에 대한 선택적 세부 정보입니다. 이 중 하나를 추가하면 사이트 헤더에 아이콘 링크로 표시됩니다. - -```js -starlight({ - social: { - codeberg: 'https://codeberg.org/knut/examples', - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - gitlab: 'https://gitlab.com/delucis', - linkedin: 'https://www.linkedin.com/company/astroinc', - mastodon: 'https://m.webtoo.ls/@astro', - threads: 'https://www.threads.net/@nmoodev', - twitch: 'https://www.twitch.tv/bholmesdev', - twitter: 'https://twitter.com/astrodotbuild', - youtube: 'https://youtube.com/@astrodotbuild', - }, -}); -``` - -### `customCss` - -**타입:** `string[]` - -Starlight 사이트의 모양과 느낌을 변경하려면 CSS 파일을 제공하세요. - -`'./src/custom.css'`와 같은 프로젝트 루트에서 상대 경로로 지정한 로컬 CSS 파일 및 `'@fontsource/roboto'`와 같은 npm 모듈로 설치한 CSS를 지원합니다. - -```js -starlight({ - customCss: ['./src/custom-styles.css', '@fontsource/roboto'], -}); -``` - -### `head` - -**타입:** [`HeadConfig[]`](#headconfig) - -Starlight 사이트의 `<head>`에 사용자 정의 태그를 추가합니다. 분석 및 기타 서드파티 스크립트와 리소스를 추가하는 데 유용할 수 있습니다. - -```js -starlight({ - head: [ - // Fathom 분석 스크립트 태그를 추가하는 예시 - { - tag: 'script', - attrs: { - src: 'https://cdn.usefathom.com/script.js', - 'data-site': 'MY-FATHOM-ID', - defer: true, - }, - }, - ], -}); -``` - -#### `HeadConfig` - -```ts -interface HeadConfig { - tag: string; - attrs?: Record<string, string | boolean | undefined>; - content?: string; -} -``` - -### `lastUpdated` - -**타입:** `boolean` -**기본값:** `false` - -페이지 하단에 최종 업데이트 날짜를 표시할지 여부를 제어합니다. - -기본적으로 이 기능은 저장소의 Git 기록에 의존하며 [얕은 복제](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt)를 수행하는 일부 배포 플랫폼에서는 정확하지 않을 수 있습니다. 페이지는 [`lastUpdated` frontmatter 필드](/ko/reference/frontmatter/#lastupdated)를 사용하여 이 설정이나 Git 기반 날짜를 변경할 수 있습니다. - -### `pagination` - -**타입:** `boolean` -**기본값:** `true` - -페이지 하단에 이전 페이지 링크와 다음 페이지 링크가 포함되어야 하는지 정의합니다. - -페이지는 [`prev`](/ko/reference/frontmatter/#prev)와 [`next`](/ko/reference/frontmatter/#next) frontmatter 필드를 통해 이 설정이나 링크 텍스트, URL을 변경할 수 있습니다. - -### `favicon` - -**타입:** `string` -**기본값:** `'/favicon.svg'` - -`public/` 디렉토리에 포함되어 있으며 유효한 아이콘 파일인 (`.ico`, `.gif`, `.jpg`, `.png`, 또는 `.svg`) 웹 사이트의 기본 파비콘 경로를 설정합니다. - -```js -starlight({ - favicon: '/images/favicon.svg', -}), -``` - -추가 변형이나 대체 파비콘을 설정해야 하는 경우 [`head` 옵션](#head)을 사용하여 태그를 추가할 수 있습니다. - -```js -starlight({ - favicon: '/images/favicon.svg'. - head: [ - // Safari용 대체 ICO 파비콘을 추가합니다. - { - tag: 'link', - attrs: { - rel: 'icon', - href:'/images/favicon.ico', - sizes: '32x32', - }, - }, - ], -}); -``` diff --git a/docs/src/content/docs/ko/reference/configuration.mdx b/docs/src/content/docs/ko/reference/configuration.mdx new file mode 100644 index 00000000000..7af20a7113b --- /dev/null +++ b/docs/src/content/docs/ko/reference/configuration.mdx @@ -0,0 +1,818 @@ +--- +title: 구성 참조 +description: Starlight가 지원하는 모든 구성 옵션에 대한 개요입니다. +--- + +## `starlight` 통합 구성 + +Starlight는 [Astro](https://astro.build) 웹 프레임워크 위에 구축된 통합입니다. `astro.config.mjs` 구성 파일에서 프로젝트를 구성할 수 있습니다. + +```js +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: '즐거운 문서 사이트', + }), + ], +}); +``` + +`starlight` 통합에 다음 옵션을 전달할 수 있습니다. + +### `title` (필수) + +**타입:** `string | Record<string, string>` + +웹사이트의 제목을 설정합니다. 메타데이터 및 브라우저 탭 제목에 사용됩니다. + +값은 문자열일 수도 있고, 다국어 사이트의 경우 각기 다른 로케일에 대한 값이 포함된 객체일 수도 있습니다. +객체 형식을 사용할 때 키는 BCP-47 태그(예: `en`, `ar` 또는 `zh-CN`)여야 합니다. + +```ts +starlight({ + title: { + en: 'My delightful docs site', + de: 'Meine bezaubernde Dokumentationsseite', + }, +}); +``` + +### `description` + +**타입:** `string` + +웹사이트에 대한 설명을 설정합니다. 페이지의 프론트매터에 `description`이 설정되지 않은 경우, `<meta name="description">` 태그에서 검색 엔진과 공유되는 메타데이터로 사용됩니다. + +### `logo` + +**타입:** [`LogoConfig`](#logoconfig) + +사이트 제목을 대체하거나 사이트 제목과 함께 네비게이션 바에 표시되는 로고 이미지를 설정합니다. 단일 `src` 속성을 설정하거나 `light` 및 `dark` 속성에 다른 이미지 소스를 전달할 수 있습니다. + +```js +starlight({ + logo: { + src: './src/assets/my-logo.svg', + }, +}); +``` + +#### `LogoConfig` + +```ts +type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( + | { src: string } + | { light: string; dark: string } +); +``` + +### `tableOfContents` + +**타입:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number }` +**기본값:** `{ minHeadingLevel: 2, maxHeadingLevel: 3 }` + +각 페이지 오른쪽에 표시되는 목차를 구성합니다. 기본적으로 `<h2>` 및 `<h3>` 제목이 이 목차에 포함됩니다. + +### `editLink` + +**타입:** `{ baseUrl: string }` + +기본 URL을 설정하여 "페이지 편집" 링크를 활성화합니다. 최종 링크는 `editLink.baseUrl` + 현재 페이지 경로가 됩니다. 예를 들어, 다음 코드를 통해 GitHub의 `withastro/starlight` 저장소의 페이지 편집 기능을 활성화할 수 있습니다. + +```js +starlight({ + editLink: { + baseUrl: 'https://github.com/withastro/starlight/edit/main/', + }, +}); +``` + +이 구성을 통해 `/introduction` 페이지에 있는 편집 링크는 `https://github.com/withastro/starlight/edit/main/src/content/docs/introduction.md`를 가리킵니다. + +### `sidebar` + +**타입:** [`SidebarItem[]`](#sidebaritem) + +사이트의 사이드바 탐색 항목을 구성합니다. + +사이드바는 링크의 배열과 링크 그룹입니다. +`slug`를 사용하는 항목을 제외하고, 각 항목은 `label`과 함께 다음 속성 중 하나를 반드시 포함해야합니다. + +- `link` — 특정 URL에 대한 단일 링크(예: `'/home'` 또는 `'https://example.com'`). + +- `slug` — 내부 페이지에 대한 참조 (예: `'guides/getting-started'`). + +- `items` — 더 많은 사이드바 링크와 하위 그룹을 포함하는 배열 + +- `autogenerate` — 링크 그룹을 자동으로 생성하기 위해 문서의 디렉터리를 지정하는 객체 + +내부 링크는 `slug` 속성이 있는 객체 대신 문자열로 지정할 수도 있습니다. + +```js +starlight({ + sidebar: [ + // '홈'이라는 라벨이 붙은 단일 링크 항목 + { label: '홈', link: '/' }, + // 네 개의 링크가 포함된 '여기서부터' 라는 라벨이 붙은 그룹 + { + label: '여기서부터', + items: [ + // 내부 링크에 `slug`를 사용합니다. + { slug: 'intro' }, + { slug: 'installation' }, + // 또는 내부 링크에 대한 약칭을 사용합니다. + 'tutorial', + 'next-steps', + ], + }, + // 'reference' 디렉터리의 모든 페이지에 연결되는 그룹 + { + label: '참조', + autogenerate: { directory: 'reference' }, + }, + ], +}); +``` + +#### 정렬 + +자동 생성된 사이드바 그룹은 파일 이름을 기준으로 알파벳순으로 정렬됩니다. 예를 들어 `astro.md`에서 생성된 페이지는 `starlight.md` 페이지 위에 표시됩니다. + +#### 그룹 최소화 + +링크 그룹은 기본적으로 펼쳐져 있습니다. 그룹의 `collapsed` 속성을 `true`로 설정하여 이 동작을 변경할 수 있습니다. + +자동 생성된 하위 그룹은 기본적으로 상위 그룹의 `collapsed` 속성을 따릅니다. 이를 변경하려면 `autogenerate.collapsed` 속성을 설정하세요. + +```js {5,13} +sidebar: [ + // 최소화된 링크 그룹 + { + label: '최소화된 링크 모음', + collapsed: true, + items: ['intro', 'next-steps'], + }, + // 최소화된 자동 생성 하위 그룹을 포함하는 펼쳐진 그룹 + { + label: '참조', + autogenerate: { + directory: 'reference', + collapsed: true, + }, + }, +], +``` + +#### 라벨 번역 + +다국어 사이트의 경우, 각 항목의 `label`은 기본 언어로 설정됩니다. `translations` 속성을 설정하여 지원하는 다른 언어로 된 라벨을 제공할 수 있습니다. + +```js {5,9,14} +sidebar: [ + // 브라질 포르투갈어로 번역된 라벨이 있는 예시 사이드바입니다. + { + label: '여기서부터', + translations: { 'pt-BR': 'Comece Aqui' }, + items: [ + { + label: '시작하기', + translations: { 'pt-BR': 'Introdução' }, + link: '/getting-started', + }, + { + label: '프로젝트 구조', + translations: { 'pt-BR': 'Estrutura de Projetos' }, + link: '/structure', + }, + ], + }, +], +``` + +#### `SidebarItem` + +```ts +type SidebarItem = + | string + | ({ + translations?: Record<string, string>; + badge?: string | BadgeConfig; + } & ( + | { + // 링크 + link: string; + label: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // 내부 링크 + slug: string; + label?: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // 링크 그룹 + label: string; + items: SidebarItem[]; + collapsed?: boolean; + } + | { + // 자동으로 생성된 링크 그룹 + label: string; + autogenerate: { + directory: string; + collapsed?: boolean; + attrs?: Record<string, string | number | boolean | undefined>; + }; + collapsed?: boolean; + } + )); +``` + +#### `BadgeConfig` + +```ts +interface BadgeConfig { + text: string; + variant?: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; + class?: string; +} +``` + +### `locales` + +**타입:** <code>\{ \[dir: string\]: [LocaleConfig](#localeconfig) }</code> + +지원되는 `locales`를 설정하여 사이트의 [국제화(i18n)를 구성](/ko/guides/i18n/)하세요. + +각 항목은 언어 파일이 저장된 디렉터리를 키로 사용해야 합니다. + +```js +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: '나의 사이트', + // 이 사이트의 기본 언어를 한국어로 설정합니다. + defaultLocale: 'ko', + locales: { + // 한국어 문서는 `src/content/docs/ko/`에 있습니다. + ko: { + label: '한국어', + }, + // 영어 문서는 `src/content/docs/en/`에 있습니다. + en: { + label: 'English', + lang: 'en', + }, + // 중국어 간체 문서는 `src/content/docs/zh-cn/`에 있습니다. + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + // 아랍어 문서는 `src/content/docs/ar/`에 있습니다. + ar: { + label: 'العربية', + dir: 'rtl', + }, + }, + }), + ], +}); +``` + +#### `LocaleConfig` + +```ts +interface LocaleConfig { + label: string; + lang?: string; + dir?: 'ltr' | 'rtl'; +} +``` + +각 언어에 대해 다음 옵션을 설정할 수 있습니다. + +##### `label` (필수) + +**타입:** `string` + +언어의 라벨은 언어 변경 기능에서 사용자에게 보여지는 문자입니다. 대부분의 경우, `"English"`, `"العربية"`, 또는 `"简体中文"`와 같이 해당 언어를 사용하는 사용자가 읽을 것으로 예상되는 언어의 이름을 작성하는 것이 좋습니다. + +##### `lang` + +**타입:** `string` + +`"en"`, `"ar"` 또는 `"zh-CN"`와 같은 언어의 BCP-47 태그입니다. 설정하지 않으면 기본적으로 해당 언어의 디렉터리 이름이 사용됩니다. 지역 하위 태그가 있는 언어 태그(예: `"pt-BR"` 또는 `"en-US"`)는 지역별 번역이 없는 경우에 내장된 기본 언어 UI 번역을 사용합니다. + +##### `dir` + +**타입:** `'ltr' | 'rtl'` + +언어의 쓰기 방향입니다. `"ltr"`은 왼쪽에서 오른쪽으로 진행함을 나타내며 기본값입니다. `"rtl"`은 오른쪽에서 왼쪽으로 진행함을 나타냅니다. + +#### 루트 로케일 + +`root` 로케일을 설정하면 `/lang/` 디렉터리 없이 기본 언어를 제공할 수 있습니다. + +```js {3-6} +starlight({ + locales: { + root: { + label: '한국어', + lang: 'ko', + }, + fr: { + label: 'Français', + }, + }, +}); +``` + +예를 들어, `/getting-started/`를 한국어 경로로 제공하고, `/fr/getting-started/`를 동일한 페이지의 프랑스어 버전으로 제공할 수 있습니다. + +### `defaultLocale` + +**타입:** `string` + +사이트의 기본 언어를 설정합니다. +값은 [`locales`](#locales) 객체의 키 중 하나와 일치해야 합니다. +(기본 언어가 [루트 로케일](#루트-로케일)인 경우 이 단계를 건너뛸 수 있습니다.) + +이 값은 번역이 누락된 대체 콘텐츠를 제공하는 데 사용됩니다. + +### `social` + +**타입:** <code>{`Array<{ label: string; icon: `}[StarlightIcon](/ko/reference/icons/){`; href: string }>`}</code> + +이 사이트의 소셜 미디어 계정에 대한 선택적 세부 정보입니다. +각 항목은 사이트 헤더에 아이콘 링크로 표시됩니다. + +```js +starlight({ + social: [ + { icon: 'codeberg', label: 'Codeberg', href: 'https://codeberg.org/knut' }, + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro' }, + { icon: 'gitlab', label: 'GitLab', href: 'https://gitlab.com/delucis' }, + { icon: 'mastodon', label: 'Mastodon', href: 'https://m.webtoo.ls/@astro' }, + ], +}), +``` + +### `customCss` + +**타입:** `string[]` + +Starlight 사이트의 모양과 느낌을 변경하려면 CSS 파일을 제공하세요. + +`'./src/custom.css'`와 같은 프로젝트 루트에서 상대 경로로 지정한 로컬 CSS 파일 및 `'@fontsource/roboto'`와 같은 npm 모듈로 설치한 CSS를 지원합니다. + +```js +starlight({ + customCss: ['./src/custom-styles.css', '@fontsource/roboto'], +}); +``` + +### `markdown` + +**타입:** `{ headingLinks?: boolean; processedDirs?: string[] }` +**기본값:** `{ headingLinks: true, processedDirs: [] }` + +Starlight의 Markdown 처리를 구성합니다. + +#### `headingLinks` + +**타입:** `boolean` +**기본값:** `true` + +제목이 클릭 가능한 앵커 링크와 함께 렌더링될지 여부를 제어합니다. + +```js +starlight({ + markdown: { + // Starlight의 클릭 가능한 제목 앵커 링크를 비활성화합니다. + headingLinks: false, + }, +}), +``` + +#### `processedDirs` + +**타입:** `string[]` +**기본값:** `[]` + +Starlight의 Markdown 파이프라인에 의해 처리되어야 하는 파일들을 포함하는 디렉터리를 추가로 정의합니다. +기본적으로 Starlight는 [`docsLoader()`](/ko/reference/configuration/#docsloader)를 사용하여 로드된 Markdown 및 MDX 콘텐츠만 처리합니다. +프로젝트 루트를 기준으로 한 로컬 디렉터리(예: `'./src/data/comments/'`)를 지원합니다. + +Starlight의 처리는 [클릭 가능한 제목 앵커 링크](#headinglinks), [Markdown의 asides 지시어 구문](/ko/guides/authoring-content/#보조-내용), 코드 블록에 대한 RTL 지원을 포함합니다. +이 옵션은 `<StarlightPage>` 컴포넌트를 사용하여 [사용자 정의 페이지](/ko/guides/pages/#사용자-정의-페이지)에서 사용자 정의 콘텐츠 컬렉션의 콘텐츠를 렌더링하고, Starlight의 Markdown 처리가 해당 콘텐츠에도 적용되기를 기대하는 경우에 유용할 수 있습니다. + +```js +starlight({ + markdown: { + // `src/data/reviews/` 디렉터리에 있는 `reviews` 콘텐츠 컬렉션의 Markdown 파일을 처리합니다. + processedDirs: ['./src/data/reviews/'], + }, +}), +``` + +### `expressiveCode` + +**타입:** `StarlightExpressiveCodeOptions | boolean` +**기본값:** `true` + +Starlight는 [Expressive Code](https://expressive-code.com)를 사용하여 코드 블록을 렌더링하고 코드 예시의 부분 강조 표시, 코드 블록에 파일 이름 추가 등 다양한 기능을 지원합니다. +Markdown 및 MDX 콘텐츠에서 Expressive Code 구문을 사용하는 방법을 알아보려면 [“코드 블록” 가이드](/ko/guides/authoring-content/#코드-블록)를 참조하세요. + +Starlight의 `expressiveCode` 옵션을 설정하여 표준 [Expressive Code 구성 옵션](https://expressive-code.com/reference/configuration/)과 일부 Starlight 관련 속성을 사용할 수 있습니다. +예를 들어, Expressive Code의 `styleOverrides` 옵션을 설정하여 기본 CSS를 재정의할 수 있습니다. 이를 통해 코드 블록에 둥근 모서리를 제공하는 등의 사용자 정의가 가능해집니다. + +```js ins={2-4} +starlight({ + expressiveCode: { + styleOverrides: { borderRadius: '0.5rem' }, + }, +}); +``` + +Expressive Code를 비활성화하려면 Starlight 구성에서 `expressiveCode: false`를 설정하세요. + +```js ins={2} +starlight({ + expressiveCode: false, +}); +``` + +표준 Expressive Code 옵션 외에도 `expressiveCode` 구성에서 다음과 같은 Starlight 관련 속성을 설정하여 코드 블록에 대한 테마를 추가로 변경할 수도 있습니다. + +#### `themes` + +**타입:** `Array<string | ThemeObject | ExpressiveCodeTheme>` +**기본값:** `['starlight-dark', 'starlight-light']` + +코드 블록 스타일을 지정하는 데 사용되는 테마를 설정합니다. +지원되는 테마 형식에 대한 자세한 내용은 [Expressive Code `themes` 문서](https://expressive-code.com/guides/themes/)를 참조하세요. + +Starlight는 기본적으로 Sarah Drasner가 제작한 [Night Owl theme](https://github.com/sdras/night-owl-vscode-theme)의 어둡고 밝은 변형을 사용합니다. + +어두운 테마와 밝은 테마를 최소 하나씩 제공하는 경우 Starlight는 자동으로 활성 코드 블록 테마를 현재 사이트 테마와 동기화된 상태로 유지합니다. +[`useStarlightDarkModeSwitch`](#usestarlightdarkmodeswitch) 옵션을 사용하여 이 동작을 구성하세요. + +#### `useStarlightDarkModeSwitch` + +**타입:** `boolean` +**기본값:** `true` + +값이 `true`인 경우, 사이트 테마가 변경되면 코드 블록이 밝은 테마와 어두운 테마를 자동으로 전환합니다. +값이 `false`인 경우, 여러 테마 간 전환을 처리하기 위해 CSS를 수동으로 추가해야 합니다. + +:::note +`themes`를 설정할 때, 최소 하나의 어두운 테마와 밝은 테마를 제공해야 Starlight 어두운 모드 스위치가 작동합니다. +::: + +#### `useStarlightUiThemeColors` + +**타입:** `boolean` +**기본값:** `themes`가 설정되어 있지 않으면 `true`이고, 그렇지 않으면 `false`입니다. + +값이 `true`인 경우, Starlight의 CSS 변수는 코드 블록의 UI 요소(배경, 버튼, 그림자 등)에 사용되며, [사이트 색상 테마](/ko/guides/css-and-tailwind/#테마)와 일치합니다. +값이 `false`인 경우, 활성 구문 강조 테마에서 제공하는 색상이 이러한 요소에 사용됩니다. + +:::note +사용자 정의 테마를 사용하고 이를 `true`로 설정하는 경우, 적절한 색상 대비를 보장하기 위해 최소한 하나의 어두운 테마와 하나의 밝은 테마를 제공해야 합니다. +::: + +### `pagefind` + +**타입:** <code>boolean | <a href="#pagefindoptions">PagefindOptions</a></code> +**기본값:** `true` + +Starlight의 기본 사이트 검색 공급자인 [Pagefind](https://pagefind.app/)를 구성합니다. + +Pagefind로 사이트 색인을 생성하지 않으려면 `false`로 설정하세요. +또한, 이는 기본 검색 UI도 숨깁니다. + +[`prerender`](#prerender) 옵션이 `false`로 설정된 경우 Pagefind를 활성화할 수 없습니다. + +`pagefind`를 객체로 설정하여 Pagefind 검색 클라이언트를 구성합니다: + +- `pagefind.ranking` 옵션을 사용하여 검색 결과 순위 계산 방법을 제어하는 방법에 대한 자세한 내용은 Pagefind 문서의 ["Customize Pagefind's result ranking"](https://pagefind.app/docs/ranking/)을 참조하세요. +- 여러 사이트에서 검색하는 방법을 제어하기 위해 `pagefind.mergeIndex` 옵션을 사용하는 방법에 대한 자세한 내용은 Pagefind 문서의 ["Searching multiple sites"](https://pagefind.app/docs/multisite/)를 참조하세요. + +#### `PagefindOptions` + +```ts +interface PagefindOptions { + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + indexWeight?: number; + mergeIndex?: Array<{ + bundlePath: string; + indexWeight?: number; + basePath?: string; + baseUrl?: string; + mergeFilter?: Record<string, string | string[]>; + language?: string; + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + }>; +} +``` + +### `prerender` + +**타입:** `boolean` +**기본값:** `true` + +Starlight 페이지를 정적 HTML로 사전 렌더링할지, 아니면 [SSR 어댑터](https://docs.astro.build/ko/guides/on-demand-rendering/)를 통해 주문형으로 렌더링할지 정의합니다. + +Starlight 페이지는 기본적으로 사전 렌더링됩니다. +SSR 어댑터를 사용 중이고 Starlight 페이지를 주문형으로 렌더링하기를 원한다면 `prerender: false`를 설정하세요. + +### `head` + +**타입:** [`HeadConfig[]`](#headconfig) + +Starlight 사이트의 `<head>`에 사용자 정의 태그를 추가합니다. 분석 및 기타 서드파티 스크립트와 리소스를 추가하는 데 유용할 수 있습니다. + +```js +starlight({ + head: [ + // Fathom 분석 스크립트 태그를 추가하는 예시 + { + tag: 'script', + attrs: { + src: 'https://cdn.usefathom.com/script.js', + 'data-site': 'MY-FATHOM-ID', + defer: true, + }, + }, + ], +}); +``` + +`head`의 항목은 HTML 요소로 직접 변환되며 Astro의 [스크립트](https://docs.astro.build/ko/guides/client-side-scripts/#스크립트-처리)나 [스타일](https://docs.astro.build/ko/guides/styling/#astro에서-스타일링하기) 처리를 거치지 않습니다. +스크립트, 스타일 또는 이미지와 같은 로컬 자산을 가져와야 하는 경우 [Head 컴포넌트를 재정의하세요](/ko/guides/overriding-components/#내장-컴포넌트-재사용). + +#### `HeadConfig` + +```ts +interface HeadConfig { + tag: string; + attrs?: Record<string, string | boolean | undefined>; + content?: string; +} +``` + +### `lastUpdated` + +**타입:** `boolean` +**기본값:** `false` + +페이지 하단에 최종 업데이트 날짜를 표시할지 여부를 제어합니다. + +기본적으로 이 기능은 저장소의 Git 기록에 의존하며 [얕은 복제](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt)를 수행하는 일부 배포 플랫폼에서는 정확하지 않을 수 있습니다. 페이지는 [`lastUpdated` 프론트매터 필드](/ko/reference/frontmatter/#lastupdated)를 사용하여 이 설정이나 Git 기반 날짜를 변경할 수 있습니다. + +### `pagination` + +**타입:** `boolean` +**기본값:** `true` + +페이지 하단에 이전 페이지 링크와 다음 페이지 링크가 포함되어야 하는지 정의합니다. + +페이지는 [`prev`](/ko/reference/frontmatter/#prev)와 [`next`](/ko/reference/frontmatter/#next) 프론트매터 필드를 통해 이 설정이나 링크 텍스트, URL을 변경할 수 있습니다. + +### `favicon` + +**타입:** `string` +**기본값:** `'/favicon.svg'` + +`public/` 디렉터리에 포함되어 있으며 유효한 아이콘 파일인 (`.ico`, `.gif`, `.jpg`, `.png`, 또는 `.svg`) 웹 사이트의 기본 파비콘 경로를 설정합니다. + +```js +starlight({ + favicon: '/images/favicon.svg', +}), +``` + +추가 변형이나 대체 파비콘을 설정해야 하는 경우 [`head` 옵션](#head)을 사용하여 태그를 추가할 수 있습니다. + +```js +starlight({ + favicon: '/images/favicon.svg', + head: [ + // Safari용 대체 ICO 파비콘을 추가합니다. + { + tag: 'link', + attrs: { + rel: 'icon', + href: '/images/favicon.ico', + sizes: '32x32', + }, + }, + ], +}); +``` + +### `titleDelimiter` + +**타입:** `string` +**기본값:** `'|'` + +브라우저 탭에 표시되는 페이지의 `<title>` 태그에서 페이지 제목과 사이트 제목 사이의 구분 기호를 설정합니다. + +기본적으로 모든 페이지에 설정된 `<title>` 태그의 내용은 `페이지 제목 | 사이트 제목`입니다. +예를 들어, 이 페이지의 제목이 "구성 참조"이고, 이 사이트의 제목이 "Starlight"라면, 이 페이지의 `<title>`의 내용은 `구성 참조 | Starlight`가 됩니다. + +### `disable404Route` + +**타입:** `boolean` +**기본값:** `false` + +Starlight의 기본 [404 페이지](https://docs.astro.build/ko/basics/astro-pages/#사용자-정의-404-오류-페이지) 삽입을 비활성화합니다. 프로젝트에서 사용자 정의 `src/pages/404.astro` 경로를 사용하려면 이 옵션을 `true`로 설정하세요. + +### `routeMiddleware` + +**타입:** `string | string[]` + +Starlight가 데이터를 처리하는 방식을 수정할 수 있는 라우트 미들웨어 경로를 제공합니다. +이 파일 경로는 [Astro의 미들웨어](https://docs.astro.build/ko/guides/middleware/)와 충돌해서는 안 됩니다. + +라우트 미들웨어를 만드는 방법에 대한 자세한 내용은 [라우트 데이터 가이드](/ko/guides/route-data/#경로-데이터-사용자-정의)를 참조하세요. + +### `components` + +**타입:** `Record<string, string>` + +Starlight의 기본 구현을 재정의하기 위해 컴포넌트에 대한 경로를 제공합니다. + +```js +starlight({ + components: { + SocialLinks: './src/components/MySocialLinks.astro', + }, +}); +``` + +재정의할 수 있는 모든 컴포넌트에 대한 자세한 내용은 [재정의 참조](/ko/reference/overrides/)를 확인하세요. + +### `plugins` + +**타입:** [`StarlightPlugin[]`](/ko/reference/plugins/#빠른-api-참조) + +맞춤형 플러그인으로 Starlight를 확장하세요. +플러그인은 프로젝트에 변경 사항을 적용하여 Starlight의 기능을 수정하거나 추가합니다. + +사용 가능한 플러그인 목록을 보려면 [플러그인 쇼케이스](/ko/resources/plugins/)를 방문하세요. + +```js +starlight({ + plugins: [starlightPlugin()], +}); +``` + +나만의 플러그인을 만드는 방법에 대한 자세한 내용은 [플러그인 참조](/ko/reference/plugins/)를 확인하세요. + +### `credits` + +**타입:** `boolean` +**기본값:** `false` + +사이트 바닥글에 “Starlight로 제작됨” 링크 표시를 활성화합니다. + +```js +starlight({ + credits: true, +}); +``` + +## 콘텐츠 컬렉션 구성 + +Starlight는 Astro의 [콘텐츠 컬렉션](https://docs.astro.build/ko/guides/content-collections/)을 사용하여 콘텐츠를 로드합니다. +Starlight의 콘텐츠 로더 및 스키마는 필요에 따라 컬렉션을 구성하는 데 도움이 됩니다. + +```js +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + // 선택 사항: i18n 컬렉션은 다국어 사이트의 UI 번역에 사용됩니다. + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), +}; +``` + +### 로더 + +Starlight는 콘텐츠 컬렉션 구성을 간소화하기 위해 `@astrojs/starlight/loaders` 모듈에서 다음과 같은 [Astro 로더](https://docs.astro.build/ko/reference/content-loader-reference/)를 내보냅니다. + +#### `docsLoader()` + +`docsLoader()`는 `src/content/docs/` 디렉터리에서 로컬 Markdown, MDX 및 Markdoc 파일을 로드합니다. +밑줄 (`_`)로 시작하는 파일 이름은 무시됩니다. + +##### 가져오기 + +```js +import { docsLoader } from '@astrojs/starlight/loaders'; +``` + +##### 옵션 + +###### `generateId()` + +**타입:** `({ entry: string; base: URL; data: Record<string, unknown> }) => string` + +기본적으로 `docsLoader()`를 사용하여 생성된 페이지는 특수 문자를 제거하고 파일 이름을 소문자로 처리하는 sluggifier를 사용하여 파일 이름을 처리합니다. 이 기본 동작을 재정의하려면 사용자 정의 `generateId()` 함수를 제공하세요. + +예를 들어, 이는 제거될 특수 문자를 보존하는 데 유용할 수 있습니다. +기본적으로 `Example.File.md`는 `/examplefile`에서 제공됩니다. +이를 `/Example.File`에서 제공하려면 사용자 정의 `generateId()` 함수를 정의하면 됩니다. + +```js +docsLoader({ + // `.md` 또는 `.mdx` 확장자를 제거하되, 파일 이름은 그대로 유지합니다. + generateId: ({ entry }) => entry.split('.').slice(0, -1).join('.'), +}), +``` + +자세한 내용은 [Astro 문서에서 `generateId()`](https://docs.astro.build/ko/reference/content-loader-reference/#generateid)를 참조하세요. + +#### `i18nLoader()` + +`i18nLoader()`는 `src/content/i18n/` 디렉터리에서 로컬 JSON 및 YAML 파일을 로드합니다. +밑줄 (`_`)로 시작하는 파일 이름은 무시됩니다. + +##### 가져오기 + +```js +import { i18nLoader } from '@astrojs/starlight/loaders'; +``` + +##### 옵션 + +현재 `i18nLoader()`를 구성하는 옵션은 없습니다. + +### 스키마 + +Starlight는 `@astrojs/starlight/schema` 모듈에서 다음과 같은 [콘텐츠 컬렉션 스키마](https://docs.astro.build/ko/guides/content-collections/#컬렉션-스키마-정의)를 제공합니다. +이러한 스키마는 Starlight가 의존하는 `docs` 및 `i18n` 컬렉션에 사용해야 합니다. + +#### `docsSchema()` + +`docsSchema()`는 `docs` 컬렉션의 모든 콘텐츠에 대한 프런트매터를 구문 분석합니다. + +##### 가져오기 + +```js +import { docsSchema } from '@astrojs/starlight/schema'; +``` + +##### 옵션 + +###### `extend` + +**타입:** Zod 스키마 또는 Zod 스키마를 반환하는 함수 +**기본값:** `z.object({})` + +추가 필드를 사용하여 Starlight의 프런트매터 스키마를 확장합니다. +`extend` 옵션 사용에 대한 자세한 내용은 ["프런트매터 스키마 사용자 정의"](/ko/reference/frontmatter/#프런트매터-스키마-사용자-정의)를 참조하세요. + +#### `i18nSchema()` + +`i18nSchema()`는 `i18n` 컬렉션의 모든 데이터 파일을 구문 분석합니다. + +##### 가져오기 + +```js +import { i18nSchema } from '@astrojs/starlight/schema'; +``` + +##### 옵션 + +###### `extend` + +**타입:** Zod 객체 +**기본값:** `z.object({})` + +추가 필드를 사용하여 Starlight의 i18n 스키마를 확장합니다. +`extend` 옵션 사용에 대한 자세한 내용은 ["번역 스키마 확장하기"](/ko/guides/i18n/#번역-스키마-확장)를 참조하세요. diff --git a/docs/src/content/docs/ko/reference/frontmatter.md b/docs/src/content/docs/ko/reference/frontmatter.md index eff787270a2..598d866ba6c 100644 --- a/docs/src/content/docs/ko/reference/frontmatter.md +++ b/docs/src/content/docs/ko/reference/frontmatter.md @@ -1,12 +1,13 @@ --- -title: Frontmatter 참조 -description: Starlight가 지원하는 기본 frontmatter 필드에 대한 개요입니다. +title: 프런트매터 참조 +description: Starlight가 지원하는 기본 프런트매터 필드에 대한 개요입니다. --- -Frontmatter의 값을 설정하여 Starlight에서 개별 Markdown 및 MDX 페이지를 변경할 수 있습니다. 예를 들어 일반 페이지에서는 `title` 및 `description` 필드를 설정할 수 있습니다. +프런트매터의 값을 설정하여 Starlight에서 개별 Markdown 및 MDX 페이지를 변경할 수 있습니다. 예를 들어 일반 페이지에서는 `title` 및 `description` 필드를 설정할 수 있습니다. -```md +```md {3-4} --- +# src/content/docs/example.md title: 이 프로젝트에 대하여 description: 내가 진행 중인 프로젝트에 대해 자세히 알아보세요. --- @@ -14,7 +15,7 @@ description: 내가 진행 중인 프로젝트에 대해 자세히 알아보세 나를 소개하는 페이지에 오신 것을 환영합니다! ``` -## Frontmatter 필드 +## 프런트매터 필드 ### `title` (필수) @@ -28,6 +29,12 @@ description: 내가 진행 중인 프로젝트에 대해 자세히 알아보세 페이지 설명은 페이지 메타데이터에 사용되며 검색 엔진과 소셜 미디어 미리 보기에서 선택됩니다. +### `slug` + +**타입**: `string` + +페이지의 슬러그를 재정의합니다. 자세한 내용은 Astro 공식문서의 [“사용자 지정 ID 정의”](https://docs.astro.build/ko/guides/content-collections/#사용자-지정-id-정의)를 참조하세요. + ### `editUrl` **타입:** `string | boolean` @@ -38,10 +45,11 @@ description: 내가 진행 중인 프로젝트에 대해 자세히 알아보세 **타입:** [`HeadConfig[]`](/ko/reference/configuration/#headconfig) -`head` frontmatter 필드를 사용하여 페이지의 `<head>`에 태그를 추가할 수 있습니다. 이는 사용자 정의 스타일, 메타데이터 또는 기타 태그를 단일 페이지에 추가할 수 있음을 의미합니다. [전역 `head` 옵션](/ko/reference/configuration/#head)과 유사합니다. +`head` 프런트매터 필드를 사용하여 페이지의 `<head>`에 태그를 추가할 수 있습니다. 이는 사용자 정의 스타일, 메타데이터 또는 기타 태그를 단일 페이지에 추가할 수 있음을 의미합니다. [전역 `head` 옵션](/ko/reference/configuration/#head)과 유사합니다. ```md --- +# src/content/docs/example.md title: 회사 소개 head: # 사용자 정의 <title> 태그 사용 @@ -59,6 +67,7 @@ head: ```md --- +# src/content/docs/example.md title: 목차에 H2만 있는 페이지 tableOfContents: minHeadingLevel: 2 @@ -68,6 +77,7 @@ tableOfContents: ```md --- +# src/content/docs/example.md title: 목차가 없는 페이지 tableOfContents: false --- @@ -90,6 +100,7 @@ tableOfContents: false ```md --- +# src/content/docs/example.md title: 나의 홈페이지 template: splash hero: @@ -102,10 +113,25 @@ hero: - text: 더보기 link: /getting-started/ icon: right-arrow - variant: primary - text: Github에서 보기 link: https://github.com/astronaut/my-project icon: external + variant: minimal + attrs: + rel: me +--- +``` + +밝은 모드와 어두운 모드에서 다양한 버전의 hero 이미지를 표시할 수 있습니다. + +```md +--- +# src/content/docs/example.md +hero: + image: + alt: 반짝이는 밝은 색상의 로고 + dark: ../../assets/logo-dark.png + light: ../../assets/logo-light.png --- ``` @@ -115,23 +141,56 @@ hero: interface HeroConfig { title?: string; tagline?: string; - image?: { - alt?: string; - // 저장소에 있는 이미지의 상대 경로입니다. - file?: string; - // 이미지 슬롯에 사용할 Raw HTML입니다. - // 사용자 정의 `<img>` 태그 또는 인라인 `<svg>`일 수 있습니다. - html?: string; - }; + image?: + | { + // 저장소에 있는 이미지의 상대 경로입니다. + file: string; + // 보조 기술이 이미지에 접근할 수 있도록 하는 대체 텍스트입니다. + alt?: string; + } + | { + // 어두운 모드에 사용할 저장소의 이미지에 대한 상대 경로입니다. + dark: string; + // 밝은 모드에 사용할 저장소의 이미지에 대한 상대 경로입니다. + light: string; + // 보조 기술이 이미지에 접근할 수 있도록 하는 대체 텍스트입니다. + alt?: string; + } + | { + // 이미지 슬롯에 사용할 원시 HTML입니다. + // 사용자 정의 `<img>` 태그 또는 인라인 `<svg>` 태그일 수 있습니다. + html: string; + }; actions?: Array<{ text: string; link: string; - variant: 'primary' | 'secondary' | 'minimal'; - icon: string; + variant?: 'primary' | 'secondary' | 'minimal'; + icon?: string; + attrs?: Record<string, string | number | boolean>; }>; } ``` +### `banner` + +**타입:** `{ content: string }` + +이 페이지 상단에 공지 배너를 표시합니다. + +`content` 값에는 링크나 다른 콘텐츠에 대한 HTML이 포함될 수 있습니다. +예를 들어, 이 페이지에서는 `example.com`으로 이동하는 링크가 포함된 배너가 표시됩니다. + +```md +--- +# src/content/docs/example.md +title: 배너가 포함된 페이지 +banner: + content: | + 방금 멋진 것을 출시했습니다! + <a href="https://example.com">확인하러 가기</a> +--- +``` + ### `lastUpdated` **타입:** `Date | boolean` @@ -140,6 +199,7 @@ interface HeroConfig { ```md --- +# src/content/docs/example.md title: 수정된 최종 업데이트 날짜가 포함된 페이지 lastUpdated: 2022-08-09 --- @@ -153,6 +213,7 @@ lastUpdated: 2022-08-09 ```md --- +# src/content/docs/example.md # 이전 페이지 링크 숨기기 prev: false --- @@ -160,6 +221,7 @@ prev: false ```md --- +# src/content/docs/example.md # 이전 페이지 링크의 텍스트 변경 prev: 튜토리얼 계속하기 --- @@ -167,6 +229,7 @@ prev: 튜토리얼 계속하기 ```md --- +# src/content/docs/example.md # 이전 페이지 링크와 텍스트 모두 변경 prev: link: /unrelated-page/ @@ -182,6 +245,7 @@ prev: ```md --- +# src/content/docs/example.md # 다음 페이지 링크 숨기기 next: false --- @@ -196,17 +260,48 @@ next: false ```md --- +# src/content/docs/example.md # 검색 색인에서 이 페이지 숨기기 pagefind: false --- ``` +### `draft` + +**타입:** `boolean` +**기본값:** `false` + +이 페이지를 초안으로 간주하여 [프로덕션 빌드](https://docs.astro.build/ko/reference/cli-reference/#astro-build)에서 제외할지 설정합니다. 페이지를 초안으로 표시하여 개발 중에만 표시하려면 `true`로 설정하세요. + +```md +--- +# src/content/docs/example.md +# 프로덕션 빌드에서 이 페이지 제외 +draft: true +--- +``` + +초안 페이지는 빌드 출력에 포함되지 않으므로 [슬러그](/ko/guides/sidebar/#내부-링크)를 사용하여 사이트 사이드바 구성에 직접 초안 페이지를 추가할 수 없습니다. +[자동 생성된 사이드바 그룹](/ko/guides/sidebar/#자동-생성-그룹)에 사용되는 디렉터리의 초안 페이지는 프로덕션 빌드에서 자동으로 제외됩니다. + ### `sidebar` -**타입:** `{ label?: string; order?: number; hidden?: boolean; badge?: string | BadgeConfig }` +**타입:** [`SidebarConfig`](#sidebarconfig) 자동 생성된 링크 그룹을 사용할 때 이 페이지가 [사이드바](/ko/reference/configuration/#sidebar)에 표시되는 방식을 제어합니다. +#### `SidebarConfig` + +```ts +interface SidebarConfig { + label?: string; + order?: number; + hidden?: boolean; + badge?: string | BadgeConfig; + attrs?: Record<string, string | number | boolean | undefined>; +} +``` + #### `label` **타입:** `string` @@ -216,6 +311,7 @@ pagefind: false ```md --- +# src/content/docs/example.md title: 이 프로젝트에 대하여 sidebar: label: 소개 @@ -230,6 +326,7 @@ sidebar: ```md --- +# src/content/docs/example.md title: 첫 번째로 표시될 페이지 sidebar: order: 1 @@ -245,6 +342,7 @@ sidebar: ```md --- +# src/content/docs/example.md title: 자동 생성된 사이드바에서 숨길 페이지 sidebar: hidden: true @@ -253,12 +351,13 @@ sidebar: #### `badge` -**type:** <code>string | <a href="/ko/reference/configuration/#badgeconfig">BadgeConfig</a></code> +**타입:** <code>string | <a href="/ko/reference/configuration/#badgeconfig">BadgeConfig</a></code> -자동 생성된 링크 그룹에 표시될 때 사이드바의 페이지에 배지를 추가합니다. 문자열을 사용하면 배지가 기본 강조 색상으로 표시됩니다. 선택적으로, `text` 및 `variant`필드가 포함된 [BadgeConfig 객체](/ko/reference/configuration/#badgeconfig)를 전달하여 배지를 사용자가 원하는대로 변경할 수 있습니다. +자동 생성된 링크 그룹에 표시될 때 사이드바의 페이지에 배지를 추가합니다. 문자열을 사용하면 배지가 기본 강조 색상으로 표시됩니다. 선택적으로, `text`, `variant`, `class` 필드가 포함된 [BadgeConfig 객체](/ko/reference/configuration/#badgeconfig)를 전달하여 배지를 사용자가 원하는대로 변경할 수 있습니다. ```md --- +# src/content/docs/example.md title: 배지를 사용하는 페이지 sidebar: # 사이트의 강조 색상과 일치하는 기본 변형을 사용합니다. @@ -268,6 +367,7 @@ sidebar: ```md --- +# src/content/docs/example.md title: 배지를 사용하는 페이지 sidebar: badge: @@ -275,3 +375,94 @@ sidebar: variant: caution --- ``` + +#### `attrs` + +**타입:** `Record<string, string | number | boolean | undefined>` + +사이드바에서 자동 생성된 링크 그룹을 사용할 때, 이 페이지의 링크에 추가할 HTML 속성을 설정합니다. +이 페이지가 속한 자동 생성 그룹에 [`autogenerate.attrs`](/ko/guides/sidebar/#자동-생성-링크의-사용자-정의-html-속성)가 설정되어 있으면 프런트매터 속성이 그룹 속성과 병합됩니다. + +```md +--- +# src/content/docs/example.md +title: 새 탭에서 열리는 페이지 +sidebar: + # 새 탭에서 페이지를 엽니다. + attrs: + target: _blank +--- +``` + +## 프런트매터 스키마 사용자 정의 + +Starlight의 `docs` 콘텐츠 컬렉션에 대한 프런트매터 스키마는 `docsSchema()` 도우미를 사용하여 `src/content.config.ts`에 구성됩니다. + +```ts {4,7} +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; +``` + +Astro 공식문서의 ["컬렉션 스키마 정의"](https://docs.astro.build/ko/guides/content-collections/#컬렉션-스키마-정의)에서 콘텐츠 컬렉션 스키마에 대해 자세히 알아보세요. + +`docsSchema()`는 다음 옵션을 사용합니다: + +### `extend` + +**타입:** Zod 스키마 또는 Zod 스키마를 반환하는 함수 +**기본값:** `z.object({})` + +`docsSchema()` 옵션에서 `extend`를 설정하여 추가 필드로 Starlight의 스키마를 확장하세요. +값은 [Zod 스키마](https://docs.astro.build/ko/guides/content-collections/#zod를-사용한-데이터-타입-정의)여야 합니다. + +다음 예시에서는 `description` 필드에 더 엄격한 타입을 제공하여 필수 항목으로 만들고, 새로운 선택적 필드인 `category`를 추가합니다. + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: z.object({ + // 기본 제공 필드를 선택 사항이 아닌 필수 항목으로 변경합니다. + description: z.string(), + // 스키마에 새 필드를 추가합니다. + category: z.enum(['tutorial', 'guide', 'reference']).optional(), + }), + }), + }), +}; +``` + +[Astro `image()` 도우미](https://docs.astro.build/ko/guides/images/#콘텐츠-컬렉션의-이미지)를 활용하려면 스키마 확장을 반환하는 함수를 사용하세요. + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: ({ image }) => { + return z.object({ + // 로컬 이미지로 확인되어야 하는 필드를 추가합니다. + cover: image(), + }); + }, + }), + }), +}; +``` diff --git a/docs/src/content/docs/ko/reference/icons.mdx b/docs/src/content/docs/ko/reference/icons.mdx new file mode 100644 index 00000000000..0694f1b235d --- /dev/null +++ b/docs/src/content/docs/ko/reference/icons.mdx @@ -0,0 +1,32 @@ +--- +title: 아이콘 참조 +description: Starlight에서 사용할 수 있는 모든 아이콘에 대한 개요입니다. +--- + +Starlight는 `<Icon>` 컴포넌트를 사용하여 콘텐츠에 표시할 수 있는 내장 아이콘 세트를 제공합니다. + +## 아이콘 사용 + +아이콘은 [`<Icon>`](/ko/components/icons/) 컴포넌트를 사용하여 표시할 수 있습니다. +또한 [카드](/ko/components/cards/)와 같은 다른 컴포넌트나 [히어로 액션](/ko/reference/frontmatter/#hero)과 같은 설정에서도 자주 사용됩니다. + +## `StarlightIcon` 타입 + +`StarlightIcon` TypeScript 타입을 사용하여 [Starlight의 기본 제공 아이콘](#모든-아이콘)의 이름을 참조할 수 있습니다. + +```ts {2} /icon: (StarlightIcon)/ +// src/icon.ts +import type { StarlightIcon } from '@astrojs/starlight/types'; + +function getIconLabel(icon: StarlightIcon) { + // … +} +``` + +## 모든 아이콘 + +사용 가능한 모든 아이콘의 목록과 관련 이름이 아래에 나와 있습니다. 아이콘을 클릭하면 해당 이름을 클립보드에 복사할 수 있습니다. + +import IconsList from '~/components/icons-list.astro'; + +<IconsList labels={{ copied: '복사되었습니다!' }} /> diff --git a/docs/src/content/docs/ko/reference/overrides.md b/docs/src/content/docs/ko/reference/overrides.md new file mode 100644 index 00000000000..9741389e7cd --- /dev/null +++ b/docs/src/content/docs/ko/reference/overrides.md @@ -0,0 +1,260 @@ +--- +title: 재정의 참조 +description: Starlight 재정의에서 지원하는 컴포넌트 및 속성에 대한 개요입니다. +tableOfContents: + maxHeadingLevel: 4 +--- + +Starlight의 [`components`](/ko/reference/configuration/#components) 구성 옵션에 대체 컴포넌트에 대한 경로를 제공하여 Starlight의 내장 컴포넌트를 재정의할 수 있습니다. +이 페이지에는 재정의할 수 있는 모든 컴포넌트와 기본 구현에 대한 Github 링크가 나열되어 있습니다. + +[컴포넌트 재정의 가이드](/ko/guides/overriding-components/)에서 자세히 알아보세요. + +## 컴포넌트 + +### 헤드 + +이 컴포넌트들은 각 페이지의 `<head>` 요소 내에 렌더링됩니다. +또한, 반드시 [`<head>` 내에서 사용하는 것이 허용되는 요소](https://developer.mozilla.org/ko/docs/Web/HTML/Element/head#%EA%B0%99%EC%9D%B4_%EB%B3%B4%EA%B8%B0)만 포함해야 합니다. + +#### `Head` + +**기본 컴포넌트:** [`Head.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Head.astro) + +각 페이지의 `<head>` 내에서 렌더링되는 컴포넌트입니다. + +최후의 수단으로 이 컴포넌트를 재정의합니다. +기본 컴포넌트에서 렌더링되는 라우트 데이터를 사용자 정의하려면 [`head` 구성 옵션](/ko/reference/configuration/#head), [`head` 프런트매터 필드](/ko/reference/frontmatter/#head), 또는 [라우트 데이터 미들웨어](/ko/guides/route-data/#경로-데이터-사용자-정의)를 사용하는 것이 좋습니다. + +#### `ThemeProvider` + +**기본 컴포넌트:** [`ThemeProvider.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeProvider.astro) + +다크/라이트 테마를 설정하기 위해 `<head>` 내에서 렌더링되는 컴포넌트입니다. +기본 구현에는 [`<ThemeSelect />`](#themeselect)에서 사용되는 인라인 스크립트와 `<template>`이 포함되어 있습니다. + +--- + +### 접근성 + +#### `SkipLink` + +**기본 컴포넌트:** [`SkipLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SkipLink.astro) + +`<body>` 내부에서 첫 번째 요소로 렌더링되며 메인 페이지의 콘텐츠로 이동하는 접근성을 위한 컴포넌트입니다. +기본적으로 키보드의 탭을 통해 선택하기 전까지는 숨겨져 있습니다. + +--- + +### 레이아웃 + +이 컴포넌트들은 Starlight 컴포넌트들을 배치하고 다양한 중단점에서 보이는 모습을 관리합니다. +이 컴포넌트들을 재정의하면 상당한 복잡성이 발생하므로, 가능하면 하위 수준의 컴포넌트를 재정의하는 것이 좋습니다. + +#### `PageFrame` + +**기본 컴포넌트:** [`PageFrame.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageFrame.astro) +**명명된 슬롯:** `header`, `sidebar` + +대부분의 페이지 콘텐츠를 감싸는 레이아웃 컴포넌트입니다. +기본적으로 header-sidebar-main 레이아웃을 설정하고 슬롯으로 명명된 `header`와 `sidebar` 및 메인 콘텐츠에 대한 기본 슬롯을 포함합니다. +또한, 작은 (모바일) 뷰포트에서 사이드바 탐색 토글을 지원하기 위해 [`<MobileMenuToggle />`](#mobilemenutoggle)를 렌더링합니다. + +#### `MobileMenuToggle` + +**기본 컴포넌트:** [`MobileMenuToggle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuToggle.astro) + +작은 (모바일) 뷰포트에서 사이드바 탐색 토글을 수행하는 [`<PageFrame>`](#pageframe) 내부에서 렌더링되는 컴포넌트입니다. + +#### `TwoColumnContent` + +**기본 컴포넌트:** [`TwoColumnContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TwoColumnContent.astro) +**명명된 슬롯:** `right-sidebar` + +메인 콘텐츠 열과 오른쪽 사이드바 (목차)를 감싸는 레이아웃 컴포넌트입니다. +기본적으로 작은 뷰포트에서 하나의 열로 이루어진 레이아웃과 큰 뷰포트에서 두 개의 열로 이루어진 레이아웃 간 전환을 처리합니다. + +--- + +### 헤더 + +Starlight의 상단 탐색 바를 렌더링하는 컴포넌트입니다. + +#### `Header` + +**기본 컴포넌트:** [`Header.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Header.astro) + +Header 컴포넌트는 모든 페이지 상단에 표시됩니다. +기본적으로 [`<SiteTitle />`](#sitetitle), [`<Search />`](#search), [`<SocialIcons />`](#socialicons), [`<ThemeSelect />`](#themeselect), 와 [`<LanguageSelect />`](#languageselect)를 표시합니다. + +#### `SiteTitle` + +**기본 컴포넌트:** [`SiteTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SiteTitle.astro) + +사이트 제목을 렌더링하기 위해 사이트 헤더 시작 부분에 렌더링되는 컴포넌트입니다. +기본적으로 Starlight 구성에 정의된 로고를 렌더링하는 논리가 포함합니다. + +#### `Search` + +**기본 컴포넌트:** [`Search.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Search.astro) + +Starlight의 검색 UI를 렌더링하기 위해 사용되는 컴포넌트입니다. 기본적으로 헤더의 버튼과 클릭하면 [Pagefind의 UI](https://pagefind.app/)를 불러오는 검색 모달을 나타내는 코드가 포함되어 있습니다. + +[`pagefind`](/ko/reference/configuration/#pagefind)가 비활성화되면 기본 검색 컴포넌트가 렌더링되지 않습니다. +그러나, `Search`를 재정의하면 `pagefind` 구성 옵션이 `false`인 경우에도 사용자 정의 컴포넌트가 항상 렌더링됩니다. +이를 통해, Pagefind가 활성화되지 않았을 때 대체 검색 공급자에 대한 UI를 추가할 수 있습니다. + +#### `SocialIcons` + +**기본 컴포넌트:** [`SocialIcons.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SocialIcons.astro) + +사이트 헤더에 렌더링되며 소셜 아이콘 링크를 포함하는 컴포넌트입니다. +기본적으로 아이콘과 링크를 렌더링하기 위해 Starlight 구성에서 [`social`](/ko/reference/configuration/#social) 옵션을 사용합니다. + +#### `ThemeSelect` + +**기본 컴포넌트:** [`ThemeSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeSelect.astro) + +사용자가 선호하는 색 구성표를 선택할 수 있도록 사이트 헤더에 렌더링되는 컴포넌트입니다. + +#### `LanguageSelect` + +**기본 컴포넌트:** [`LanguageSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LanguageSelect.astro) + +사용자가 다른 언어로 전환할 수 있도록 사이트 헤더에 렌더링되는 컴포넌트입니다. + +--- + +### 전역 사이드바 + +Starlight의 전역 사이드바에는 메인 사이트 탐색이 포함되어 있습니다. +좁은 뷰포트에서는 드롭다운 메뉴 뒤에 숨겨져 있습니다. + +#### `Sidebar` + +**기본 컴포넌트:** [`Sidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Sidebar.astro) + +전역 탐색이 포함된 페이지 콘텐츠 앞에 렌더링되는 컴포넌트입니다. +기본적으로 충분히 넓은 뷰포트에서는 사이드바로 나타나고, 작은 (모바일) 뷰포트에서는 드롭다운 메뉴로 나타납니다. +또한, 모바일 메뉴 내부에 추가 항목을 표시하기 위해 [`<MobileMenuFooter />`](#mobilemenufooter)를 렌더링합니다. + +#### `MobileMenuFooter` + +**기본 컴포넌트:** [`MobileMenuFooter.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuFooter.astro) + +모바일 드롭다운 메뉴 하단에 렌더링되는 컴포넌트입니다. +기본적으로 [`<ThemeSelect />`](#themeselect)와 [`<LanguageSelect />`](#languageselect)를 렌더링합니다. + +--- + +### 페이지 사이드바 + +Starlight의 페이지 사이드바는 현재 페이지의 하위 제목을 간략하게 설명하는 목차를 표시합니다. +좁은 뷰포트에서는 고정된 드롭다운 메뉴로 축소됩니다. + +#### `PageSidebar` + +**기본 컴포넌트:** [`PageSidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageSidebar.astro) + +목차를 나타내기 위해 메인 페이지의 콘텐츠 앞에 렌더링되는 컴포넌트입니다. +기본적으로 [`<TableOfContents />`](#tableofcontents)와 [`<MobileTableOfContents />`](#mobiletableofcontents)를 렌더링합니다. + +#### `TableOfContents` + +**기본 컴포넌트:** [`TableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TableOfContents.astro) + +더 넓은 뷰포트에서 현재 페이지의 목차를 렌더링하는 컴포넌트입니다. + +#### `MobileTableOfContents` + +**기본 컴포넌트:** [`MobileTableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileTableOfContents.astro) + +작은 (모바일) 뷰포트에서 현재 페이지의 목차를 렌더링하는 컴포넌트입니다. + +--- + +### 콘텐츠 + +이 컴포넌트들은 페이지 콘텐츠의 메인 열에 렌더링됩니다. + +#### `Banner` + +**기본 컴포넌트:** [`Banner.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Banner.astro) + +각 페이지 상단에 렌더링되는 배너 컴포넌트입니다. +기본적으로 페이지의 [`banner`](/ko/reference/frontmatter/#banner) 프론트매터 속성을 사용하여 렌더링 여부를 결정합니다. + +#### `ContentPanel` + +**기본 컴포넌트:** [`ContentPanel.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ContentPanel.astro) + +메인 콘텐츠 열의 섹션을 감싸는 레이아웃 컴포넌트입니다. + +#### `PageTitle` + +**기본 컴포넌트:** [`PageTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageTitle.astro) + +현재 페이지의 `<h1>` 요소를 포함하는 컴포넌트입니다. +기본 구현과 같이 `<h1>` 요소에 `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) + +현재 언어에 대한 번역이 제공되지 않는 페이지에서 사용자에게 표시되는 알림입니다. +다국어 사이트에서만 사용됩니다. + +#### `Hero` + +**기본 컴포넌트:** [`Hero.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Hero.astro) + +프론트매터에서 [`hero`](/ko/reference/frontmatter/#hero)를 설정했을 때, 페이지 상단에 렌더링되는 컴포넌트입니다. +기본적으로 큰 제목, 태그라인, 클릭 유도 문구 링크와 선택적 이미지를 표시합니다. + +#### `MarkdownContent` + +**기본 컴포넌트:** [`MarkdownContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MarkdownContent.astro) + +각 페이지의 메인 콘텐츠 주위에 렌더링되는 컴포넌트입니다. +기본적으로 마크다운 콘텐츠에 적용할 기본 스타일을 설정합니다. + +Markdown 콘텐츠 스타일은 `@astrojs/starlight/style/markdown.css`에도 노출되며 `.sl-markdown-content` CSS 클래스로 범위가 지정됩니다. + +--- + +### 바닥글 + +이 컴포넌트들은 페이지 콘텐츠의 메인 열 하단에 렌더링됩니다. + +#### `Footer` + +**기본 컴포넌트:** [`Footer.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Footer.astro) + +각 페이지 하단에 표시되는 바닥글 컴포넌트입니다. +기본적으로 [`<LastUpdated />`](#lastupdated), [`<Pagination />`](#pagination), 그리고 [`<EditLink />`](#editlink)를 표시합니다. + +#### `LastUpdated` + +**기본 컴포넌트:** [`LastUpdated.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LastUpdated.astro) + +마지막 업데이트 날짜를 표시하기 위해 페이지 바닥글에 렌더링되는 컴포넌트입니다. + +#### `EditLink` + +**기본 컴포넌트:** [`EditLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/EditLink.astro) + +페이지를 편집할 수 있는 링크를 표시하기 위해 페이지 바닥글에 렌더링되는 컴포넌트입니다. + +#### `Pagination` + +**기본 컴포넌트:** [`Pagination.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Pagination.astro) + +Component rendered in the page footer to display navigation arrows between previous/next pages. + +이전/다음 페이지 사이에 탐색 화살표를 표시하기 위해 페이지 바닥글에 렌더링되는 컴포넌트입니다. diff --git a/docs/src/content/docs/ko/reference/plugins.md b/docs/src/content/docs/ko/reference/plugins.md new file mode 100644 index 00000000000..85f3ca165a6 --- /dev/null +++ b/docs/src/content/docs/ko/reference/plugins.md @@ -0,0 +1,375 @@ +--- +title: 플러그인 참조 +description: Starlight 플러그인 API의 개요입니다. +tableOfContents: + maxHeadingLevel: 4 +--- + +Starlight 플러그인은 Starlight 구성, UI, 동작을 사용자 정의할 수 있을 뿐만 아니라 공유 및 재사용하기도 쉽습니다. +이 참조 페이지에는 플러그인이 액세스할 수 있는 API가 문서화되어 있습니다. + +[구성 참조](/ko/reference/configuration/#plugins)에서 Starlight 플러그인 사용에 대해 자세히 알아보거나 [플러그인 쇼케이스](/ko/resources/plugins/)를 방문하여 사용 가능한 플러그인 목록을 확인하세요. + +## 빠른 API 참조 + +Starlight 플러그인은 다음과 같은 형태를 가지고 있습니다. +다양한 속성과 훅 매개변수에 대한 자세한 내용은 아래를 참조하세요. + +<!-- prettier-ignore-start --> +```ts +interface StarlightPlugin { + name: string; + hooks: { + 'i18n:setup'?: (options: { + injectTranslations: ( + translations: Record<string, Record<string, string>> + ) => void; + }) => void | Promise<void>; + 'config:setup': (options: { + config: StarlightUserConfig; + updateConfig: (newConfig: StarlightUserConfig) => void; + addIntegration: (integration: AstroIntegration) => void; + addRouteMiddleware: (config: { entrypoint: string; order?: 'pre' | 'post' | 'default' }) => void; + astroConfig: AstroConfig; + command: 'dev' | 'build' | 'preview'; + isRestart: boolean; + logger: AstroIntegrationLogger; + useTranslations: (lang: string) => I18nT; + absolutePathToLang: (path: string) => string; + }) => void | Promise<void>; + }; +} +``` +<!-- prettier-ignore-end --> + +## `name` + +**타입:** `string` + +플러그인은 자신을 설명하는 고유한 이름을 제공해야 합니다. 이름은 이 플러그인과 관련된 [메시지를 로깅](#logger)할 때 사용되며 다른 플러그인에서 이 플러그인의 존재를 감지하는 데 사용될 수도 있습니다. + +## `hooks` + +훅은 Starlight가 특정 시간에 플러그인 코드를 실행하기 위해 호출하는 함수입니다. + +훅의 인자 타입을 얻으려면 `HookParameters` 유틸리티 타입을 사용하고 훅 이름을 전달하세요. +다음 예제에서 `options` 매개변수는 `config:setup` 훅에 전달된 인자와 일치하도록 타입이 지정됩니다. + +```ts +import type { HookParameters } from '@astrojs/starlight/types'; + +function configSetup(options: HookParameters['config:setup']) { + options.useTranslations('ko'); +} +``` + +### `i18n:setup` + +Starlight가 초기화될 때 호출되는 플러그인 국제화 설정 함수입니다. +`i18n:setup` 훅을 사용하여 번역 문자열을 삽입할 수 있으므로 플러그인이 다른 로케일을 지원할 수 있습니다. +이러한 번역은 `config:setup` 훅에서 [`useTranslations()`](#usetranslations)를 통해, UI 컴포넌트에서 [`Astro.locals.t()`](/ko/guides/i18n/#ui-번역-사용)를 통해 사용할 수 있습니다. + +`i18n:setup` 훅은 다음 옵션과 함께 호출됩니다: + +#### `injectTranslations` + +**타입:** `(translations: Record<string, Record<string, string>>) => void` + +Starlight의 [지역화 API](/ko/guides/i18n/#ui-번역-사용)에서 사용되는 번역 문자열을 추가하거나 업데이트하는 콜백 함수입니다. + +다음 예제에서 플러그인은 `en` 및 `fr` 로케일에 대해 `myPlugin.doThing`이라는 사용자 지정 UI 문자열에 대한 번역을 삽입합니다. + +```ts {6-13} /(injectTranslations)[^(]/ +// plugin.ts +export default { + name: 'plugin-with-translations', + hooks: { + 'i18n:setup'({ injectTranslations }) { + injectTranslations({ + en: { + 'myPlugin.doThing': 'Do the thing', + }, + fr: { + 'myPlugin.doThing': 'Faire le truc', + }, + }); + }, + }, +}; +``` + +플러그인 UI에서 삽입된 번역을 사용하려면 ["UI 번역 사용" 가이드](/ko/guides/i18n/#ui-번역-사용)를 따르세요. +플러그인의 [`config:setup`](#configsetup) 훅의 컨텍스트에서 UI 문자열을 사용해야 하는 경우, [`useTranslations()`](#usetranslations) 콜백을 사용할 수 있습니다. + +플러그인에 삽입된 번역 문자열의 타입은 사용자 프로젝트에서 자동으로 생성되지만, 플러그인 코드베이스에서 작업할 때는 아직 사용할 수 없습니다. +플러그인의 컨텍스트에서 `locals.t` 객체의 타입을 지정하려면 TypeScript 선언 파일에서 다음 전역 네임스페이스를 선언하세요: + +```ts +// env.d.ts +declare namespace App { + type StarlightLocals = import('@astrojs/starlight').StarlightLocals; + // 플러그인 컨텍스트에서 `locals.t` 객체를 정의합니다. + interface Locals extends StarlightLocals {} +} + +declare namespace StarlightApp { + // `I18n` 인터페이스에서 추가 플러그인 번역을 정의합니다. + interface I18n { + 'myPlugin.doThing': string; + } +} +``` + +번역이 포함된 객체가 있는 경우 소스 파일에서 `StarlightApp.I18n` 인터페이스의 타입을 추론할 수도 있습니다. + +예를 들어, 다음 소스 파일이 주어졌을 때: + +```ts title="ui-strings.ts" +export const UIStrings = { + en: { 'myPlugin.doThing': 'Do the thing' }, + fr: { 'myPlugin.doThing': 'Faire le truc' }, +}; +``` + +다음 선언은 소스 파일의 영어 키에서 타입을 추론합니다: + +```ts title="env.d.ts" +declare namespace StarlightApp { + type UIStrings = typeof import('./ui-strings').UIStrings.en; + interface I18n extends UIStrings {} +} +``` + +### `config:setup` + +Starlight가 초기화될 때 호출되는 플러그인 구성 설정 함수입니다 ([`astro:config:setup`](https://docs.astro.build/ko/reference/integrations-reference/#astroconfigsetup) 통합 훅 실행 중 호출). +`config:setup` 훅을 사용하여 Starlight 구성을 업데이트하거나 Astro 통합을 추가할 수 있습니다. + +이 훅은 다음 옵션들과 함께 호출됩니다. + +#### `config` + +**타입:** `StarlightUserConfig` + +사용자 제공 [Starlight 구성](/ko/reference/configuration/)의 읽기 전용 복사본입니다. +이 구성은 현재 플러그인 이전에 구성된 다른 플러그인에 의해 업데이트되었을 수 있습니다. + +#### `updateConfig` + +**타입:** `(newConfig: StarlightUserConfig) => void` + +사용자가 제공한 [Starlight 구성](/ko/reference/configuration/)을 업데이트하는 콜백 함수입니다. +재정의하려는 루트 수준 구성 키를 제공합니다. +중첩된 구성 값을 업데이트하려면 전체 중첩 객체를 제공해야 합니다. + +기존 구성 옵션을 재정의하지 않고 확장하려면 기존 값을 새 값에 전개하여 확장하세요. +다음 예시에서는 `config.social`에 전개 연산자를 사용하여 새로운 `social` 배열을 확장합니다. 이를 통해, 새로운 [`social`](/ko/reference/configuration/#social) 미디어 계정을 기존 구성에 추가합니다. + +```ts {6-15} +// plugin.ts +export default { + name: 'add-twitter-plugin', + hooks: { + 'config:setup'({ config, updateConfig }) { + updateConfig({ + social: [ + ...config.social, + { + icon: 'twitter', + label: 'Twitter', + href: 'https://twitter.com/astrodotbuild', + }, + ], + }); + }, + }, +}; +``` + +#### `addIntegration` + +**타입:** `(integration: AstroIntegration) => void` + +플러그인에 필요한 [Astro 통합](https://docs.astro.build/ko/reference/integrations-reference/)을 추가하기 위한 콜백 함수입니다. + +다음 예시에서 플러그인은 먼저 [Astro의 React 통합](https://docs.astro.build/ko/guides/integrations-guide/react/)이 구성되어 있는지 확인하고, 구성되어 있지 않으면 `addIntegration()`을 사용하여 이를 추가합니다. + +```ts {14} "addIntegration," +// plugin.ts +import react from '@astrojs/react'; + +export default { + name: 'plugin-using-react', + hooks: { + 'config:setup'({ addIntegration, astroConfig }) { + const isReactLoaded = astroConfig.integrations.find( + ({ name }) => name === '@astrojs/react' + ); + + // 아직 불러오지 않은 경우에만 React 통합을 추가합니다. + if (!isReactLoaded) { + addIntegration(react()); + } + }, + }, +}; +``` + +#### `addRouteMiddleware` + +**타입:** `(config: { entrypoint: string; order?: 'pre' | 'post' | 'default' }) => void` + +사이트에 [경로 미들웨어 핸들러](/ko/guides/route-data/)를 추가하는 콜백 함수입니다. + +`entrypoint` 속성은 `onRequest` 핸들러를 내보내는 플러그인 미들웨어 파일의 모듈 지정자여야 합니다. + +다음 예제에서 `@example/starlight-plugin`으로 게시된 플러그인은 npm 모듈 지정자를 사용하여 경로 미들웨어를 추가합니다. + +```js {6-9} +// plugin.ts +export default { + name: '@example/starlight-plugin', + hooks: { + 'config:setup'({ addRouteMiddleware }) { + addRouteMiddleware({ + entrypoint: '@example/starlight-plugin/route-middleware', + }); + }, + }, +}; +``` + +##### 실행 순서 제어 + +기본적으로 플러그인 미들웨어는 플러그인이 추가된 순서대로 실행됩니다. + +미들웨어가 언제 실행되는지 더 세밀하게 제어해야 하는 경우 선택적 `order` 속성을 사용하세요. +사용자 미들웨어보다 먼저 실행하려면 `order: "pre"`를 설정하세요. +다른 모든 미들웨어 후에 실행하려면 `order: "post"`를 설정하세요. + +두 플러그인이 동일한 `order` 값으로 미들웨어를 추가하는 경우 먼저 추가된 플러그인이 먼저 실행됩니다. + +#### `astroConfig` + +**타입:** `AstroConfig` + +사용자 제공 [Astro 구성](https://docs.astro.build/ko/reference/configuration-reference/)의 읽기 전용 복사본입니다. + +#### `command` + +**타입:** `'dev' | 'build' | 'preview'` + +Starlight를 실행하는 데 사용되는 명령: + +- `dev` - 프로젝트는 `astro dev`로 실행 +- `build` - 프로젝트는 `astro build`로 실행 +- `preview` - 프로젝트는 `astro preview`로 실행 + +#### `isRestart` + +**타입:** `boolean` + +개발 서버가 시작되면 `false`, 서버가 다시 시작되면 `true`입니다. +개발 서버 재시작의 일반적인 이유에는 개발 서버가 실행되는 동안 사용자가 `astro.config.mjs`를 편집하는 경우가 포함됩니다. + +#### `logger` + +**타입:** `AstroIntegrationLogger` + +로그를 작성하는 데 사용할 수 있는 [Astro 통합 로거](https://docs.astro.build/ko/reference/integrations-reference/#astrointegrationlogger)의 인스턴스입니다. +기록된 모든 메시지에는 플러그인 이름이 앞에 추가됩니다. + +```ts {6} +// plugin.ts +export default { + name: 'long-process-plugin', + hooks: { + 'config:setup'({ logger }) { + logger.info('시간이 오래 걸리는 작업 진행 중…'); + // 오래 걸리는 작업… + }, + }, +}; +``` + +위 예시에서는 제공된 정보를 포함하는 메시지를 기록합니다. + +```shell +[long-process-plugin] 시간이 오래 걸리는 작업 진행 중… +``` + +#### `useTranslations` + +**타입:** `(lang: string) => I18nT` + +BCP-47 언어 태그와 함께 `useTranslations()`를 호출하여 해당 언어의 UI 문자열에 접근할 수 있는 유틸리티 함수를 생성합니다. +`useTranslations()`는 Astro 컴포넌트에서 사용 가능한 `Astro.locals.t()` API와 동일한 기능을 반환합니다. +사용 가능한 API에 대한 자세한 내용은 ["UI 번역 사용"](/ko/guides/i18n/#ui-번역-사용) 가이드를 참조하세요. + +```ts {6} +// plugin.ts +export default { + name: 'plugin-use-translations', + hooks: { + 'config:setup'({ useTranslations, logger }) { + const t = useTranslations('zh-CN'); + logger.info(t('builtWithStarlight.label')); + }, + }, +}; +``` + +위의 예제는 중국어 간체에 대한 내장 UI 문자열을 포함하는 메시지를 기록합니다. + +```shell +[plugin-use-translations] 基于 Starlight 构建 +``` + +#### `absolutePathToLang` + +**타입:** `(path: string) => string` + +절대 파일 경로와 함께 `absolutePathToLang()`을 호출하여 해당 파일의 언어를 가져옵니다. + +이는 Markdown 또는 MDX 파일을 처리하기 위해 [remark 또는 rehype 플러그인](https://docs.astro.build/ko/guides/markdown-content/#markdown-플러그인)을 추가할 때 특히 유용할 수 있습니다. +이러한 플러그인에서 사용하는 [가상 파일 형식](https://github.com/vfile/vfile)에는 처리 중인 파일의 [절대 경로](https://github.com/vfile/vfile#filepath)가 포함되어 있으며, 이는 `absolutePathToLang()`과 함께 사용하여 파일의 언어를 확인할 수 있습니다. +반환된 언어는 해당 언어에 대한 UI 문자열을 가져오기 위해 [`useTranslations()`](#usetranslations) 도우미와 함께 사용할 수 있습니다. + +예를 들어, 다음 Starlight 구성이 주어졌을 때: + +```js +starlight({ + title: 'My Docs', + defaultLocale: 'en', + locales: { + // `src/content/docs/en/`에서 영어 문서 + en: { label: 'English' }, + // `src/content/docs/fr/`에서 프랑스어 문서 + fr: { label: 'Français', lang: 'fr' }, + }, +}); +``` + +플러그인은 절대 경로를 사용하여 파일의 언어를 확인할 수 있습니다. + +```ts {6-8} /fr/ +// plugin.ts +export default { + name: 'plugin-use-translations', + hooks: { + 'config:setup'({ absolutePathToLang, useTranslations, logger }) { + const lang = absolutePathToLang( + '/absolute/path/to/project/src/content/docs/fr/index.mdx' + ); + const t = useTranslations(lang); + logger.info(t('aside.tip')); + }, + }, +}; +``` + +위의 예제는 프랑스어에 대한 내장 UI 문자열을 포함하는 메시지를 기록합니다. + +```shell +[plugin-use-translations] Astuce +``` diff --git a/docs/src/content/docs/ko/reference/route-data.mdx b/docs/src/content/docs/ko/reference/route-data.mdx new file mode 100644 index 00000000000..2a18016f78d --- /dev/null +++ b/docs/src/content/docs/ko/reference/route-data.mdx @@ -0,0 +1,203 @@ +--- +title: 경로 데이터 참조 +description: Starlight의 경로 데이터 객체에 대한 전체 참조 문서입니다. +--- + +Starlight의 경로 데이터 객체는 현재 페이지에 대한 정보를 담고 있습니다. +Starlight의 데이터 모델 작동 방식에 대한 자세한 내용은 ["경로 데이터" 가이드](/ko/guides/route-data/)에서 확인하세요. + +Astro 컴포넌트에서는 `Astro.locals.starlightRoute`를 통해 경로 데이터에 접근할 수 있습니다. + +```astro {4} +--- +// src/components/Custom.astro + +const { hasSidebar } = Astro.locals.starlightRoute; +--- +``` + +[경로 미들웨어](/ko/guides/route-data/#경로-데이터-사용자-정의)에서는 미들웨어 함수에 전달된 컨텍스트 객체에서 경로 데이터에 접근합니다. + +```ts {5} +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + const { hasSidebar } = context.locals.starlightRoute; +}); +``` + +## `starlightRoute` + +`starlightRoute` 객체는 다음 속성을 가집니다. + +### `dir` + +**타입:** `'ltr' | 'rtl'` + +페이지 작성 방향입니다. + +### `lang` + +**타입:** `string` + +이 페이지의 로케일에 대한 BCP-47 언어 태그입니다. 예: `en`, `zh-CN` 또는 `pt-BR` + +### `locale` + +**타입:** `string | undefined` + +언어가 제공되는 기본 경로입니다. 루트 로케일 슬러그의 경우 `undefined`입니다. + +### `siteTitle` + +**타입:** `string` + +이 페이지의 로케일에 대한 사이트 제목입니다. + +### `siteTitleHref` + +**타입:** `string` + +`/`처럼 홈페이지와 연결되는 사이트 제목 `href` 속성의 값입니다. +다국어 사이트의 경우 `/en/` 또는 `/zh-cn/`과 같은 현재 로케일이 포함됩니다. + +### `slug` + +**타입:** `string` + +콘텐츠 파일 이름에서 생성된 이 페이지의 슬러그입니다. + +이 속성은 더 이상 사용되지 않으며 향후 버전의 Starlight에서 제거될 예정입니다. +[Starlight의 `docsLoader`](/ko/manual-setup/#콘텐츠-컬렉션-구성)를 사용하여 새 콘텐츠 레이어 API로 마이그레이션하고 대신 [`id`](#id) 속성을 사용하세요. + +### `id` + +**타입:** `string` + +이 페이지의 슬러그 또는 [`legacy.collections`](https://docs.astro.build/ko/reference/legacy-flags/#collections) 플래그를 사용하는 경우 콘텐츠 파일명을 기준으로 한 이 페이지의 고유 ID입니다. + +### `isFallback` + +**타입:** `boolean | undefined` + +이 페이지가 현재 언어로 번역되지 않고 기본 로케일의 대체 콘텐츠를 사용하는 경우 `true`입니다. +다국어 사이트에서만 사용됩니다. + +### `entryMeta` + +**타입:** `{ dir: 'ltr' | 'rtl'; lang: string }` + +페이지 콘텐츠의 로케일 메타데이터입니다. 페이지가 대체 콘텐츠를 사용하는 경우 최상위 로케일 값과 다를 수 있습니다. + +### `entry` + +현재 페이지에 대한 Astro 콘텐츠 컬렉션 항목입니다. +`entry.data`는 현재 페이지에 대한 프론트매터 값을 포함합니다. + +```ts +entry: { + data: { + title: string; + description: string | undefined; + // 기타 + } +} +``` + +[Astro 컬렉션 엔트리 타입](https://docs.astro.build/ko/reference/modules/astro-content/#collectionentry) 참조에서 이 객체의 형태에 대해 자세히 알아보세요. + +### `sidebar` + +**타입:** `SidebarEntry[]` + +페이지에 대한 사이트 탐색 사이드바 엔트리입니다. + +### `hasSidebar` + +**타입:** `boolean` + +이 페이지에 사이드바를 표시할지 여부입니다. + +### `pagination` + +**타입:** `{ prev?: Link; next?: Link }` + +활성화된 경우 사이드바의 이전 및 다음 페이지로 이동하는 링크를 표시합니다. + +### `toc` + +**타입:** `{ minHeadingLevel: number; maxHeadingLevel: number; items: TocItem[] } | undefined` + +활성화된 경우 이 페이지의 목차를 표시합니다. + +### `headings` + +**타입:** `{ depth: number; slug: string; text: string }[]` + +현재 페이지에서 추출된 모든 Markdown 제목의 배열입니다. +Starlight의 구성 옵션을 준수하는 콘텐츠 목차 컴포넌트를 생성하기 위해서는 [`toc`](#toc)를 사용하세요. + +### `lastUpdated` + +**타입:** `Date | undefined` + +활성화된 경우 이 페이지가 마지막으로 업데이트된 날짜를 나타내기 위해 JavaScript `Date`객체가 사용됩니다. + +### `editUrl` + +**타입:** `URL | undefined` + +활성화된 경우 이 페이지를 편집할 수 있는 주소를 나타내기 위해 `URL` 객체가 사용됩니다. + +### `head` + +**타입:** [`HeadConfig[]`](/ko/reference/configuration/#headconfig) + +현재 페이지의 `<head>`에 포함할 모든 태그의 배열입니다. +`<title>` 및 `<meta charset="utf-8">`과 같은 중요한 태그를 포함합니다. + +## 유틸리티 + +### `defineRouteMiddleware()` + +`defineRouteMiddleware()` 유틸리티를 사용하여 경로 미들웨어 모듈의 타입을 지정하세요: + +```ts "defineRouteMiddleware" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + // ... +}); +``` + +### `StarlightRouteData` 타입 + +Starlight의 경로 데이터를 사용해야 하는 코드를 작성하는 경우, `StarlightRouteData` 타입을 가져와 `Astro.locals.starlightRoute`의 형태와 일치시킬 수 있습니다. + +다음 예제에서 `usePageTitleInTOC()` 함수는 경로 데이터를 업데이트하여 현재 페이지의 제목을 목차의 첫 번째 항목 레이블로 사용하고 기본 "개요" 레이블을 대체합니다. `StarlightRouteData` 타입을 사용하면 경로 데이터 변경 사항이 유효한지 확인할 수 있습니다. + +```ts "StarlightRouteData" +// src/route-utils.ts +import type { StarlightRouteData } from '@astrojs/starlight/route-data'; + +export function usePageTitleInTOC(starlightRoute: StarlightRouteData) { + const overviewLink = starlightRoute.toc?.items[0]; + if (overviewLink) { + overviewLink.text = starlightRoute.entry.data.title; + } +} +``` + +이 함수는 경로 미들웨어에서 호출할 수 있습니다. + +```ts {3,6} +// src/route-middleware.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; +import { usePageTitleInTOC } from './route-utils'; + +export const onRequest = defineRouteMiddleware((context) => { + usePageTitleInTOC(context.locals.starlightRoute); +}); +``` diff --git a/docs/src/content/docs/ko/resources/community-content.mdx b/docs/src/content/docs/ko/resources/community-content.mdx new file mode 100644 index 00000000000..d62925bd97c --- /dev/null +++ b/docs/src/content/docs/ko/resources/community-content.mdx @@ -0,0 +1,249 @@ +--- +title: 커뮤니티 콘텐츠 +description: Starlight를 배우고 구축하는 데 도움이 되는 커뮤니티 제작 가이드, 기사 및 비디오를 찾아보세요! +--- + +:::tip[직접 추가하세요!] +Starlight에 대한 콘텐츠를 제작한 적이 있나요? +이 페이지에 링크를 추가하여 PR을 열어보세요! +::: + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +## 기사 및 리뷰 + +다음은 Starlight와 다른 사람들의 경험에 대해 자세히 알아볼 수 있는 게시물과 기사 모음입니다. + +<CardGrid> + <LinkCard + href="https://devm.io/open-source/starlight-astro" + title="Starlight를 사용한 정적 사이트 생성" + description="“컴포넌트를 설계할 때 아이디어가 너무 크거나 너무 작으면 안 됩니다.” — Starlight 리드 개발자인 Chris Swithinbank와의 인터뷰" + /> + <LinkCard + href="https://frontendatscale.com/blog/hybrid-frontend-architecture/" + title="Astro와 Starlight를 사용한 하이브리드 프런트엔드 아키텍처" + description="Maxi Ferreira와 Ben Holmes는 Starlight, TinaCMS 및 인증 기능이 있는 대화형 API 플레이그라운드를 사용하여 문서 사이트를 구축합니다." + /> + <LinkCard + href="https://www.olets.dev/posts/comparing-docs-site-builders-vuepress-vs-starlight/" + title="문서 사이트 빌더 비교: VuePress vs Starlight" + description="이 두 프레임워크는 어떻게 비교되나요?" + /> + <LinkCard + href="https://astro.build/case-studies/wp-engine/" + title="사례 연구: 개발 비용 절감" + description="WP Engine이 Astro의 Starlight로 개발 비용을 50% 이상 절감한 방법" + /> + <LinkCard + href="https://maciekpalmowski.dev/blog/building-a-documentation-site-using-astro-starlight/" + title="Astro의 Starlight를 사용한 문서 사이트 구축" + description="Patchstack 문서를 Starlight로 마이그레이션하는 과정 - Maciek Palmowski" + /> + <LinkCard + href="https://blog.cloudflare.com/open-source-all-the-way-down-upgrading-our-developer-documentation/" + title="오픈소스의 힘으로" + description="Cloudflare가 Starlight로 개발자 문서를 개선한 방법" + /> + <LinkCard + href="https://starlight-changelog.netlify.app/" + title="Starlight 변경 로그" + description="@astrojs/starlight 패키지의 모든 릴리스를 한눈에 볼 수 있는 멋진 페이지" + /> + <LinkCard + href="https://hideoo.dev/notes/contributing-to-starlight" + title="Starlight에 기여하기" + description="Starlight와 같은 오픈 소스 프로젝트에 기여하는 것에 대한 개인적인 경험과 제안" + /> +</CardGrid> + +## 레시피 및 가이드 + +레시피는 일반적으로 특정 작업의 실제 예시를 완료하는 과정을 독자에게 안내하는 짧고 집중적인 가이드입니다. 레시피는 단계별 지침에 따라 Starlight 프로젝트에 새로운 기능이나 동작을 추가할 수 있는 좋은 방법입니다! 다른 가이드에서는 이미지 사용이나 MDX 작업 등 콘텐츠 영역과 관련된 개념을 설명할 수도 있습니다. + +Starlight 사용자들이 관리하는 커뮤니티 제작 콘텐츠를 살펴보세요. + +<CardGrid> + <LinkCard + href="https://www.webpro.nl/scraps/versioned-docs-with-starlight-and-vercel" + title="Starlight & Vercel을 사용한 버전별 문서" + description="프로젝트의 각 주요 버전에 대해 별도의 문서 버전을 구현하는 방법에 대한 가이드" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-heading-links" + title="Starlight 제목에 링크 추가" + description="문서의 특정 섹션에 대한 링크를 공유하기 위한 rehype 플러그인 사용 가이드" + /> + <LinkCard + href="https://blog.otterlord.dev/posts/starlight-sponsors/" + title="Starlight 사이트에 스폰서 추가" + description="문서 사이드바에 맞춤 스폰서 컴포넌트를 구현하기 위한 가이드" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images" + title="Starlight에 Open Graph 이미지 추가" + description="페이지에 대한 소셜 이미지 및 해당 메타 태그 생성에 대한 가이드" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-third-party-icon-sets" + title="Starlight에서 타사 아이콘 세트 사용" + description="unplugin-icons를 사용하여 Starlight에 사용 가능한 아이콘 선택 범위를 확장하는 방법에 대한 가이드" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-html-head" + title="Starlight 페이지의 HTML 헤드 편집" + description="웹 분석, 글꼴, 스크립트 등 일반적인 헤드 콘텐츠를 추가하는 방법을 알아보세요." + /> + <LinkCard + href="https://dev.to/mrrobot/publishing-documentation-with-astro-starlight-691" + title="Astro Starlight로 문서 게시" + description="Starlight 문서 시작하기" + /> + <LinkCard + href="https://events-3bg.pages.dev/jotter/starlight/" + title="뷰 전환 활성화" + description="Starlight 문서 사이트에 뷰 전환, 클라이언트 측 라우팅 및 SPA와 유사한 탐색 지원을 추가합니다." + /> + <LinkCard + href="https://jamcomments.com/posts/structured-data-with-starlight" + title="Starlight 페이지에 구조화된 데이터 추가" + description="문서 페이지에 대한 동적 JSON-LD 구조화된 데이터를 구축하는 방법을 알아보세요." + /> + <LinkCard + href="https://starlight-examples.netlify.app/" + title="Starlight 예시" + description="Starlight 문서 사이트에서 작업을 수행하는 실용적인 방법을 보여주는 StackBlitz 임베드 모음입니다." + /> + <LinkCard + href="https://hideoo.dev/notebooks/starlight-plugins-by-example" + title="Starlight Plugins 예시" + description="Starlight 플러그인과 이를 빌드하는 데 사용되는 일반적인 패턴에 대한 정보와 예시 모음입니다." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-progress-indicator/" + title="읽기 진행률 표시기 추가" + description="Starlight 사이트에 가로 읽기 진행률 표시줄을 추가하는 방법을 알아보세요." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-sidebar-whitespace/" + title="Starlight 사이드바에 사용자 정의 스타일 적용" + description="Starlight 사이드바의 글꼴, 색상 등을 조정하기 위한 약간의 CSS를 사용합니다." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-dropdown-and-list-together/" + title="모바일에서는 Starlight 주제 드롭다운, 데스크톱에서는 목록" + description="데스크톱 및 모바일 장치 모두에서 최고의 경험을 제공하기 위해 두 가지 플러그인을 결합합니다." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-autogenerate-whole-sidebar/" + title="미들웨어를 사용하여 Starlight 사이드바 처리" + description="라우트 미들웨어를 사용하여 사이드바 순서와 그룹 레이블을 제어합니다. 이는 Nuxt Content의 규칙에서 영감을 얻었습니다." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-social-links" + title="사용자 정의 아이콘을 사용하여 Starlight에 소셜 링크 추가" + description="Starlight 웹사이트 헤더에 소셜 링크용 사용자 정의 아이콘을 사용하는 방법을 알아보세요." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-paste-images-with-visual-studio-code" + title="Visual Studio Code를 사용하여 Starlight 페이지에 이미지 붙여넣기" + description="Visual Studio Code를 사용하여 Starlight 문서 페이지에 이미지를 붙여넣어 Starlight 문서 워크플로를 개선하세요." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-add-diagrams-using-d2" + title="D2를 사용하여 Starlight 문서에 다이어그램 추가" + description="D2를 사용하여 Starlight 문서에 다이어그램을 추가하는 방법을 알아보세요." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images-cloudinary-astro-sdk" + title="Cloudinary Astro SDK를 사용하여 Starlight용 오픈 그래프 이미지 생성" + description="Cloudinary Astro SDK를 사용하여 Starlight 문서 웹사이트용 오픈 그래프 이미지를 생성하는 방법을 알아보세요." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-list-recent-github-releases" + title="Astro의 Content Layer API를 사용하여 Starlight에 최근 GitHub 릴리스 나열" + description="Astro의 Content Layer API를 사용하여 Starlight 프로젝트에 최근 GitHub 릴리스를 나열하는 방법을 알아보세요." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-sitewide-banner" + title="Starlight에 사이트 전체 배너 추가" + description="Starlight의 페이지별 배너 기능을 사용하여 사이트 전체 배너를 만드는 방법을 알아보세요." + /> + <LinkCard + href="https://lirantal.com/blog/customizing-astro-starlight-sidebar-gated-content-auth" + title="인증을 통해 게이트된 콘텐츠용 Astro Starlight 사이드바 사용자 정의" + description="Clerk 및 SSR을 사용하여 사용자 로그인 여부에 따라 Starlight 사이드바 챕터를 동적으로 숨기거나 표시하여 강의 자료를 보호하세요." + /> +</CardGrid> + +## 영상 콘텐츠 + +라이브 스트림, 교육 콘텐츠 등 Starlight 콘텐츠가 포함된 비디오와 채널을 찾아보세요. + +import YouTubeGrid from '~/components/youtube-grid.astro'; + +### 공식 동영상 + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=5u0Ds7wzUeI', + title: 'Astro의 Starlight', + description: '공식 Starlight 출시 영상을 시청합니다.', + }, + { + href: 'https://www.youtube.com/watch?v=j8K-ESJF814', + title: 'Starlight 1주년!', + description: + 'Sarah가 Astro의 커뮤니티 제작 문서 테마에 대해 이야기합니다.', + }, + ]} +/> + +### 커뮤니티 동영상 및 스트림 + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/shorts/zjOWezSzd18', + title: '🌟 1분 안에 시작하기', + description: + 'Ben이 1분 안에 새로운 Starlight 사이트를 시작하는 것을 확인하세요!', + }, + { + href: 'https://www.youtube.com/watch?v=sF6UcV3moZg', + title: 'Starlight 및 Astro를 사용하여 문서 작성', + description: + 'CodingCat.dev를 통해 Chris와 Alex가 Code에서 Starlight에 대해 알아보는 모습을 시청하세요.', + }, + { + href: 'https://www.youtube.com/watch?v=sWkkHbwDeQc', + title: 'Astro Starlight', + description: '1분 안에 Starlight 소개', + }, + { + href: 'https://www.youtube.com/watch?v=-Ki-1E5gNCk', + title: 'Astro Starlight 문서 템플릿 (맞춤형 앱 문서 구축!)', + description: '약 5분 안에 새로운 Starlight 사이트를 시작하고 실행하세요.', + }, + { + href: 'https://www.youtube.com/watch?v=12o7WxjAxjM', + title: '프록시를 사용하여 Next.js 프로젝트에 Starlight 문서 포함', + description: + 'Next.js 웹사이트 내 하위 디렉터리 프로젝트로 Starlight 설정', + }, + { + href: 'https://www.youtube.com/watch?v=5pq80drDrNs', + title: + '이 놀라운 도구를 사용하여 Shadcn의 문서를 30분 만에 다시 만들었습니다.', + description: + '이 비디오에서는 Starlight가 왜 그렇게 멋진지, 그리고 왜 다음 프로젝트에서 Starlight를 사용해 보고 싶은지 설명합니다.', + }, + { + href: 'https://www.youtube.com/watch?v=Q1E4Gkt63ko', + title: 'Astro Starlight와 emoji-blast - Chris Swithinbank', + description: + '프레임워크 온 프레임워크인 Astro Starlight의 창시자 Chris가 새로운 emoji-blast 웹사이트를 설정하는 과정을 안내합니다. 🌟 🎇', + }, + ]} +/> diff --git a/docs/src/content/docs/ko/resources/plugins.mdx b/docs/src/content/docs/ko/resources/plugins.mdx new file mode 100644 index 00000000000..4147731086b --- /dev/null +++ b/docs/src/content/docs/ko/resources/plugins.mdx @@ -0,0 +1,305 @@ +--- +title: 플러그인 및 통합 +description: Starlight를 확장하는 플러그인 및 통합과 같은 커뮤니티 도구를 찾아보세요! +sidebar: + order: 1 +--- + +:::tip[직접 추가하세요!] +Starlight용 플러그인이나 도구를 구축하셨나요? +이 페이지에 링크를 추가하여 PR을 열어보세요! +::: + +## 플러그인 + +[플러그인](/ko/reference/plugins/)은 Starlight 구성, UI 및 동작을 사용자 정의하는 동시에 쉽게 공유하고 재사용할 수 있습니다. +Starlight 팀이 지원하는 공식 플러그인과 Starlight 사용자가 관리하는 커뮤니티 플러그인으로 사이트를 확장하세요. + +### 공식 플러그인 + +<CardGrid> + <LinkCard + href="/ko/guides/site-search/#algolia-docsearch" + title="Algolia DocSearch" + description="기본 검색 공급자인 Pagefind를 Algolia DocSearch로 바꾸세요." + /> +</CardGrid> + +### 커뮤니티 플러그인 + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-links-validator" + title="starlight-links-validator" + description="Starlight 페이지에 끊어진 링크가 있는지 확인하세요." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-typedoc" + title="starlight-typedoc" + description="TypeDoc을 사용하여 TypeScript로 Starlight 페이지를 생성하세요." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-blog" + title="starlight-blog" + description="문서 사이트에 블로그를 추가하세요." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-openapi" + title="starlight-openapi" + description="OpenAPI/Swagger 사양에서 문서 페이지를 만드세요." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-obsidian" + title="starlight-obsidian" + description="Starlight 사이트에 Obsidian Vault를 게시하세요." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-image-zoom" + title="starlight-image-zoom" + description="문서 이미지에 확대/축소 기능을 추가하세요." + /> + <LinkCard + href="https://github.com/lorenzolewis/starlight-utils" + title="starlight-utils" + description="일반적인 유틸리티 모음으로 Starlight를 확장하세요." + /> + <LinkCard + href="https://github.com/trueberryless/starlight-view-modes" + title="starlight-view-modes" + description="문서 웹사이트에 다양한 보기 모드 기능을 추가하세요." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-versions" + title="starlight-versions" + description="Starlight 문서 페이지 버전을 지정하세요." + /> + <LinkCard + href="https://inox-tools.fryuni.dev/star-warp" + title="star-warp" + description="문서에서 검색 결과를 워프 드라이브합니다." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-heading-badges" + title="starlight-heading-badges" + description="Markdown 및 MDX 제목에 배지를 추가합니다." + /> + <LinkCard + href="https://github.com/Fevol/starlight-site-graph" + title="starlight-site-graph" + description="페이지 사이드바에 대화형 사이트 그래프를 추가합니다." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-sidebar-topics" + title="starlight-sidebar-topics" + description="문서를 각각 고유한 사이드바가 있는 여러 섹션으로 분할하세요." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-cooler-credit" + title="starlight-cooler-credit" + description="Starlight 또는 Astro 목차 하단에 멋진 크레딧을 추가하세요." + /> + <LinkCard + href="https://github.com/dragomano/starlight-giscus" + title="starlight-giscus" + description="문서 사이트에 Giscus 댓글을 추가하세요." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-videos" + title="starlight-videos" + description="비디오 가이드와 강좌로 문서를 개선하세요." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-kbd" + title="starlight-kbd" + description="키보드 단축키를 쉽게 문서화하세요." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-auto-sidebar" + title="starlight-auto-sidebar" + description="자동 생성된 사이드바 그룹을 자유롭게 수정하세요." + /> + <LinkCard + href="https://github.com/delucis/starlight-llms-txt" + title="starlight-llms-txt" + description="llmstxt.org를 기반으로 llms.txt를 문서 사이트에 추가하세요." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-toc-overview-customizer" + title="starlight-toc-overview-customizer" + description="사용자 정의 가능한 개요 제목으로 Starlight의 목차를 자유롭게 수정하세요." + /> + <LinkCard + href="https://delucis.github.io/starlight-markdown-blocks/" + title="starlight-markdown-blocks" + description="사용자 지정 블록 타입으로 Starlight의 Markdown 보조 내용 (Asides) 구문을 확장하세요." + /> + <LinkCard + href="https://github.com/WindMillCode/starlight-fullview-mode" + title="starlight-fullview-mode" + description="전체 화면 경험을 위해 사이드바를 접고 콘텐츠를 확장합니다." + /> + <LinkCard + href="https://github.com/frostybee/starlight-scroll-to-top" + title="starlight-scroll-to-top" + description="문서 사이트에 맨 위로 이동하는 버튼을 추가하세요." + /> + <LinkCard + href="https://github.com/frostybee/starlight-codeblock-fullscreen" + title="starlight-codeblock-fullscreen" + description="문서에 있는 Expressive Code 블록에 전체 화면 토글 기능을 추가하세요." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-auto-drafts" + title="starlight-auto-drafts" + description="초안 페이지의 기본 동작을 조정하여 프로덕션 모드에서 초안 페이지에 대한 사이드바 링크를 자동으로 제거합니다." + /> + <LinkCard + href="https://github.com/corsfix/starlight-contextual-menu" + title="starlight-contextual-menu" + description="Starlight 문서에 컨텍스트 메뉴를 추가하세요." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-changelogs" + title="starlight-changelogs" + description="프로젝트 문서와 함께 변경 로그를 표시하세요." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-github-alerts" + title="starlight-github-alerts" + description="Starlight에서 GitHub 알림을 렌더링합니다." + /> + <LinkCard + href="https://github.com/dlcastillop/starlight-page-actions" + title="starlight-page-actions" + description="문서에 페이지 작업 버튼을 추가합니다." + /> + <LinkCard + href="https://github.com/typesense/starlight-docsearch-typesense" + title="starlight-docsearch-typesense" + description="공식 Algolia DocSearch 플러그인에 대한 Typesense 기반 대안입니다." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-swipe/" + title="starlight-sidebar-swipe" + description="모바일 Discord 앱처럼, 모바일 장치에서 왼쪽 사이드바를 스와이프할 수 있게 만듭니다." + /> + <LinkCard + href="https://github.com/Rettend/starlight-plugin-icons" + title="starlight-plugin-icons" + description="Astro Starlight의 사이드바, 코드 블록, 파일 트리에 아이콘을 추가합니다." + /> + <LinkCard + href="https://github.com/dlcastillop/starlight-ui-tweaks" + title="starlight-ui-tweaks" + description="사용자 정의 탐색 링크, 광고, 마케팅 푸터, 더 깔끔한 테마 토글로 핵심 UI 컴포넌트를 확장합니다." + /> + <LinkCard + href="https://frostybee.github.io/starlight-tags/" + title="starlight-tags" + description="Starlight 문서 페이지에 콘텐츠 조직 및 탐색을 위한 태그를 추가하세요." + /> + <LinkCard + href="https://github.com/dionysuzx/starlight-copy-button" + title="starlight-copy-button" + description="페이지 제목에 세련된 버튼을 추가해, 문서 전체 페이지를 Markdown 형식으로 한 번에 복사할 수 있습니다." + /> + <LinkCard + href="https://frostybee.github.io/starlight-telescope/" + title="starlight-telescope" + description="퍼지 검색과 키보드 중심 탐색을 통해 Starlight 문서의 모든 페이지로 빠르게 이동할 수 있습니다." + /> + <LinkCard + href="https://frostybee.github.io/starlight-announcement/" + title="starlight-announcement" + description="닫기 기능, 다양한 스타일, 예약 설정, 특정 페이지 지정 기능을 지원하는 향상된 공지 배너를 Starlight 문서에 추가할 수 있습니다." + /> +</CardGrid> + +## 커뮤니티 도구 및 통합 + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +이러한 커뮤니티 도구 및 통합을 사용하여 Starlight 사이트에 기능을 추가할 수 있습니다. + +<CardGrid> + <LinkCard + href="https://www.feelback.dev/blog/new-astro-starlight-integration/" + title="FeelBack" + description="문서 페이지에 사용자 피드백 시스템을 추가하세요." + /> + <LinkCard + href="https://github.com/val-town/notion-to-astro" + title="notion-to-astro" + description="Notion 내보내기를 Astro Starlight 문서로 변환하세요" + /> + <LinkCard + href="https://github.com/mattjennings/astro-live-code" + title="astro-live-code" + description="MDX 코드 블록을 대화형 컴포넌트로 렌더링하세요" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-i18n" + title="starlight-i18n" + description="Starlight 페이지를 번역하는 데 도움이 되는 Visual Studio Code 확장입니다." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-package-managers" + title="starlight-package-managers" + description="여러 패키지 관리자에 대한 npm 관련 명령을 빠르게 표시합니다." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-showcases" + title="starlight-showcases" + description="쇼케이스 페이지를 작성하기 위한 Starlight 컴포넌트의 집합입니다." + /> + <LinkCard + href="https://github.com/HiDeoo/generator-starlight-plugin" + title="@hideoo/starlight-plugin" + description="Starlight 플러그인을 빠르게 스캐폴딩할 수 있는 생성기입니다." + /> + <LinkCard + href="https://github.com/Linkerin/starlight-to-pdf" + title="starlight-to-pdf" + description="Starlight 웹사이트들을 PDF 파일들로 변환하기 위한 CLI 도구입니다." + /> + <LinkCard + href="https://github.com/joesaby/astro-plantuml" + title="astro-plantuml" + description="Markdown 코드 블록에서 PlantUML 콘텐츠를 렌더링합니다." + /> + <LinkCard + href="https://github.com/joesaby/astro-mermaid" + title="astro-mermaid" + description="Markdown 코드 블록의 Mermaid 콘텐츠를 클라이언트 측에서 렌더링합니다." + /> + <LinkCard + href="https://github.com/HiDeoo/astro-d2" + title="astro-d2" + description="D2 Markdown 코드 블록을 다이어그램으로 변환합니다." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-links" + title="starlight-links" + description="Starlight의 Markdown 및 MDX 콘텐츠 링크에 대한 IntelliSense를 제공하는 Visual Studio Code 확장 프로그램입니다." + /> + <LinkCard + href="https://docs.contentisland.net/templates/starlight/" + title="contentisland-cli" + description="Starlight 프로젝트를 Content Island Headless CMS에 연결하고 동기화하여 문서를 편집하고 관리하세요." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown" + title="starlight-sidebar-topics-dropdown" + description="문서 페이지를 여러 하위 페이지로 분할하고 이를 사이드바의 드롭다운 메뉴로 전환합니다." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-save-file-component" + title="starlight-save-file-component" + description="Starlight 사이트에서 다운로드 가능한 자산의 링크를 빠르게 표시합니다." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-contributor-list" + title="starlight-contributor-list" + description="프로젝트의 모든 기여자 목록을 표시합니다." + /> +</CardGrid> diff --git a/docs/src/content/docs/ko/resources/showcase.mdx b/docs/src/content/docs/ko/resources/showcase.mdx new file mode 100644 index 00000000000..f6009bab883 --- /dev/null +++ b/docs/src/content/docs/ko/resources/showcase.mdx @@ -0,0 +1,21 @@ +--- +title: Starlight 쇼케이스 +description: Starlight로 구축된 사이트를 찾아보세요! +sidebar: + label: 사이트 쇼케이스 +--- + +:::tip[직접 추가하세요!] +Starlight 사이트를 구축하셨나요? +이 페이지에 링크를 추가하는 [PR을 오픈하세요](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#showcase)! +::: + +## 사이트 + +import ShowcaseSites from '~/components/showcase-sites.astro'; + +Starlight는 이미 프로덕션에 사용되고 있습니다. 다음은 웹사이트 중 일부입니다. + +<ShowcaseSites /> + +[GitHub에서 Starlight를 사용하는 공개 프로젝트 저장소](https://github.com/withastro/starlight/network/dependents)를 모두 확인하세요. diff --git a/docs/src/content/docs/ko/resources/themes.mdx b/docs/src/content/docs/ko/resources/themes.mdx new file mode 100644 index 00000000000..a8cc68e388a --- /dev/null +++ b/docs/src/content/docs/ko/resources/themes.mdx @@ -0,0 +1,123 @@ +--- +title: 테마 +description: Starlight의 커뮤니티 테마로 문서를 스타일링하세요. +tableOfContents: false +sidebar: + order: 2 +head: + - tag: style + content: | + body { --sl-content-width: 66.75rem; } +--- + +import ThemeGrid from '~/components/theme-grid.astro'; + +테마는 [사용자 정의 CSS](/ko/guides/css-and-tailwind/), [컴포넌트 재정의](/ko/guides/overriding-components/) 또는 기타 새로운 기능을 사용하여 사이트의 시각적 모양을 변경하는 Starlight 플러그인입니다. + +## 커뮤니티 테마 + +커뮤니티에서 빌드한 테마를 설치하여 사이트의 모양과 느낌을 빠르게 사용자 정의하세요. + +아래에서 모든 테마 목록을 확인하거나 [Starlight 테마 데모 사이트](https://starlight-themes.netlify.app/)에서 직접 사용해 보세요. + +<ThemeGrid + labels={{ + /** 테마 전환을 위한 접근성 레이블입니다. */ + legend: '미리보기', + /** 어두운 색상 체계 변형에 대한 접근성 레이블입니다. */ + dark: '다크', + /** 밝은 색상 체계 변형에 대한 접근성 레이블입니다. */ + light: '라이트', + }} + themes={[ + { + title: 'Starlight Rapide', + description: + 'Visual Studio Code Vitesse 테마에서 영감을 받은 Starlight 테마', + href: 'https://starlight-theme-rapide.vercel.app/', + previews: { light: 'rapide-light.png', dark: 'rapide-dark.png' }, + }, + { + title: 'Starlight Obsidian', + description: + 'Obsidian Publish 사이트 스타일에서 영감을 받은 Starlight 테마', + href: 'https://fevol.github.io/starlight-theme-obsidian/', + previews: { light: 'obsidian-light.png', dark: 'obsidian-dark.png' }, + }, + { + title: 'Catppuccin for Starlight', + description: 'Starlight를 위한 편안한 파스텔 테마', + href: 'https://starlight.catppuccin.com/', + previews: { light: 'catppuccin-light.png', dark: 'catppuccin-dark.png' }, + }, + { + title: 'Ion', + description: 'Starlight를 위한 세련되고 현대적인 테마', + href: 'https://louisescher.github.io/starlight-ion-theme/', + previews: { light: 'ion-light.png', dark: 'ion-dark.png' }, + }, + { + title: 'Starlight Black', + description: 'shadcn 문서에서 영감을 받은 Starlight 테마', + href: 'https://starlight-theme-black.vercel.app/', + previews: { light: 'black-light.png', dark: 'black-dark.png' }, + }, + { + title: 'Starlight Flexoki', + description: 'Flexoki 색상 팔레트를 기반으로 한 따뜻하고 친근한 테마', + href: 'https://delucis.github.io/starlight-theme-flexoki/', + previews: { light: 'flexoki-light.png', dark: 'flexoki-dark.png' }, + }, + { + title: 'Starlight Nova', + description: 'Starlight를 위한 현대적이고 아름다운 테마', + href: 'https://starlight-theme-nova.pages.dev/', + previews: { light: 'nova-light.png', dark: 'nova-dark.png' }, + }, + { + title: 'Starlight Next.js', + description: 'Next.js 문서에서 영감을 받은 Starlight 테마', + href: 'https://starlight-theme-next.trueberryless.org/', + previews: { light: 'nextjs-light.png', dark: 'nextjs-dark.png' }, + }, + { + title: 'Starlight Galaxy', + description: + '문서 및 교육 콘텐츠 게시를 위한 맞춤형 Astro Starlight 테마', + href: 'https://frostybee.github.io/starlight-theme-galaxy/', + previews: { light: 'galaxy-light.png', dark: 'galaxy-dark.png' }, + }, + { + title: 'Starlight Page', + description: + '직관적이고 현대적이며, 부드러운 플로팅 애니메이션을 갖춘 Starlight 테마', + href: 'https://pelagornis-page.netlify.app/', + previews: { light: 'page-light.png', dark: 'page-dark.png' }, + }, + { + title: 'Starlight Gruvbox', + description: 'Starlight를 위한 레트로 그루브 테마', + href: 'https://starlight-theme-gruvbox.otterlord.dev/', + previews: { light: 'gruvbox-light.png', dark: 'gruvbox-dark.png' }, + }, + { + title: 'Starlight Six', + description: + 'Six Technology가 만든 깔끔하고 현대적인 Astro.js Starlight 테마', + href: 'https://six-tech.github.io/Six.StarlightTheme/', + previews: { light: 'six-light.png', dark: 'six-dark.png' }, + }, + { + title: 'Starlight Vintage', + description: + '기존 Astro 문서의 시대를 초월한 디자인에서 큰 영감을 받은 Starlight 테마', + href: 'https://starlight-theme-vintage.netlify.app/', + previews: { light: 'vintage-light.png', dark: 'vintage-dark.png' }, + }, + ]} +/> + +:::tip[여러분의 테마를 추가하세요!] +Starlight 테마를 만드셨나요? +이 페이지에 테마를 추가하는 [PR을 여세요](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#themes)! +::: diff --git a/docs/src/content/docs/ko/showcase.mdx b/docs/src/content/docs/ko/showcase.mdx deleted file mode 100644 index 527bcd730de..00000000000 --- a/docs/src/content/docs/ko/showcase.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Starlight 쇼케이스 -description: Starlight로 만들어진 사이트 및 Starlight를 확장하는 커뮤니티 도구를 찾아보세요! ---- - -:::tip[당신의 사이트를 추가하세요!] - -Starlight 사이트나 Starlight용 도구를 만드셨나요? -이 페이지에 링크를 추가하는 PR을 열어주세요! - -::: - -## 사이트 - -import ShowcaseSites from '../../../components/showcase-sites.astro'; - -Starlight는 이미 프로덕션에 사용되고 있습니다. 다음은 웹사이트 중 일부입니다. - -<ShowcaseSites /> - -GitHub에서 Starlight를 사용하는 [모든 공개 프로젝트 저장소](https://github.com/withastro/starlight/network/dependents)를 확인하세요. - -## 커뮤니티 플러그인 - -import { CardGrid, LinkCard } from '@astrojs/starlight/components'; - -이러한 커뮤니티 도구, 플러그인 및 통합은 Starlight와 함께 작동하여 기능을 확장합니다. - -<CardGrid> - <LinkCard - href="https://www.feelback.dev/blog/new-astro-starlight-integration/" - title="FeelBack" - description="문서 페이지에 사용자 피드백 시스템을 추가하세요." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-blog" - title="starlight-blog" - description="문서 사이트에 블로그를 추가하세요." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-links-validator" - title="starlight-links-validator" - description="Starlight 페이지에 끊어진 링크가 있는지 확인하세요." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-typedoc" - title="starlight-typedoc" - description="TypeDoc을 사용하여 TypeScript에서 Starlight 페이지를 생성합니다." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-openapi" - title="starlight-openapi" - description="OpenAPI/Swagger 사양에서 문서 페이지를 만드세요." - /> -</CardGrid> diff --git a/docs/src/content/docs/manual-setup.mdx b/docs/src/content/docs/manual-setup.mdx index ab32c737bf8..7b8fbe5dbfb 100644 --- a/docs/src/content/docs/manual-setup.mdx +++ b/docs/src/content/docs/manual-setup.mdx @@ -5,7 +5,7 @@ description: Learn how to configure Starlight manually to add it to an existing import { Tabs, TabItem } from '@astrojs/starlight/components'; -The quickest way to create a new Starlight site is using `create astro` as shown in the [Getting Started guide](/getting-started/#creating-a-new-project). +The quickest way to create a new Starlight site is using `create astro` as shown in the [Getting Started guide](/getting-started/#create-a-new-project). If you want to add Starlight to an existing Astro project, this guide will explain how. ## Set up Starlight @@ -16,7 +16,7 @@ To follow this guide, you’ll need an existing Astro project. Starlight is an [Astro integration](https://docs.astro.build/en/guides/integrations-guide/). Add it to your site by running the `astro add` command in your project’s root directory: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh npx astro add starlight @@ -44,7 +44,7 @@ The Starlight integration is configured in your `astro.config.mjs` file. Add a `title` to get started: -```js {7-9} +```js ins={8} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -62,20 +62,24 @@ Find all available options in the [Starlight configuration reference](/reference ### Configure content collections -Starlight is built on top of Astro’s [content collections](https://docs.astro.build/en/guides/content-collections/), which are configured in the `src/content/config.ts` file. +Starlight is built on top of Astro’s [content collections](https://docs.astro.build/en/guides/content-collections/), which are configured in the `src/content.config.ts` file. -Create or update the content config file, adding a `docs` collection that uses Starlight’s `docsSchema`: +Create or update the content config file, adding a `docs` collection that uses Starlight’s [`docsLoader`](/reference/configuration/#docsloader) and [`docsSchema`](/reference/configuration/#docsschema): -```js ins={3,6} -// src/content/config.ts +```js ins={3-4,7} +// src/content.config.ts import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; import { docsSchema } from '@astrojs/starlight/schema'; export const collections = { - docs: defineCollection({ schema: docsSchema() }), + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), }; ``` +Starlight also supports the [`legacy.collections` flag](https://docs.astro.build/en/reference/legacy-flags/) where collections are handled using the legacy content collections implementation. +This is useful if you have an existing Astro project and are unable to make any changes to collections at this time to use a loader. + ### Add content Starlight is now configured and it’s time to add some content! @@ -106,7 +110,7 @@ To add all Starlight pages at a subpath, place all your docs content inside a su For example, if Starlight pages should all start with `/guides/`, add your content in the `src/content/docs/guides/` directory: -import FileTree from '../../components/file-tree.astro'; +import { FileTree } from '@astrojs/starlight/components'; <FileTree> @@ -125,4 +129,6 @@ In the future, we plan to support this use case better to avoid the need for the ### Use Starlight with SSR -Currently, Starlight does not support [SSR deployment](https://docs.astro.build/en/guides/server-side-rendering/) using Astro’s server adapters. We hope to be able to support this soon. +To enable SSR, follow the [“On-demand Rendering Adapters”](https://docs.astro.build/en/guides/on-demand-rendering/) guide in Astro’s docs to add a server adapter to your Starlight project. + +Documentation pages generated by Starlight are pre-rendered by default regardless of your project's output mode. To opt out of pre-rendering your Starlight pages, set the [`prerender` config option](/reference/configuration/#prerender) to `false`. diff --git a/docs/src/content/docs/pt-br/404.md b/docs/src/content/docs/pt-br/404.md index df1fec2842e..df5ad07a7cc 100644 --- a/docs/src/content/docs/pt-br/404.md +++ b/docs/src/content/docs/pt-br/404.md @@ -2,6 +2,7 @@ title: Não encontrado template: splash editUrl: false +lastUpdated: false hero: title: '404' tagline: <strong>Houston, temos um problema.</strong> Não conseguimos encontrar essa página.<br>Verifique a URL ou tente utilizar a barra de pesquisa. diff --git a/docs/src/content/docs/pt-br/getting-started.mdx b/docs/src/content/docs/pt-br/getting-started.mdx index 7d29fda3b2d..f7de601480a 100644 --- a/docs/src/content/docs/pt-br/getting-started.mdx +++ b/docs/src/content/docs/pt-br/getting-started.mdx @@ -5,17 +5,20 @@ description: Aprenda como começar a construir seu próximo site de documentaç import { Tabs, TabItem } from '@astrojs/starlight/components'; -## Criando um novo projeto - Starlight é um tema de documentação cheio de funcionalidades construído em cima do framework [Astro](https://astro.build). +Esse guia o ajudará a iniciar um novo projeto. +Consulte as [instruções de instalação manual](/pt-br/manual-setup/) para adicionar Starlight a um projeto Astro existente. + +## Início Rápido + +### Crie um novo projeto -Você pode criar um novo projeto Astro + Starlight usando o seguinte comando: +Crie um novo projeto Astro + Starlight executando o seguinte comando em seu terminal: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# cria um novo projeto com npm npm create astro@latest -- --template starlight ``` @@ -23,7 +26,6 @@ npm create astro@latest -- --template starlight <TabItem label="pnpm"> ```sh -# cria um novo projeto com pnpm pnpm create astro --template starlight ``` @@ -31,7 +33,6 @@ pnpm create astro --template starlight <TabItem label="Yarn"> ```sh -# cria um novo projeto com yarn yarn create astro --template starlight ``` @@ -45,85 +46,95 @@ Experimente Starlight no seu navegador: [abrir o template no StackBlitz](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). ::: -## Criando conteúdo com Starlight +### Inicie o servidor de desenvolvimento -Starlight está pronto para você adicionar novo conteúdo, ou trazer seus arquivos existentes! +Quando estiver trabalhando localmente, o [servidor de desenvolvimento do Astro](https://docs.astro.build/pt-br/reference/cli-reference/#astro-dev) permite visualizar seu trabalho e atualizar automaticamente seu navegador ao fazer alterações. -### Formatos de arquivo +Dentro do diretório do seu projeto, execute o seguinte comando para iniciar o servidor de desenvolvimento: -Starlight suporta escrever conteúdo em Markdown e MDX. (Você pode adicionar suporte para Markdoc instalando a [integração experimental Astro Markdoc](https://docs.astro.build/en/guides/integrations-guide/markdoc/).) +<Tabs syncKey="pkg"> +<TabItem label="npm"> -### Adicione páginas +```sh +npm run dev +``` -Adicione novas páginas ao seu site automaticamente ao criar arquivos `.md` ou `.mdx` em `src/content/docs/`. Adicione subdiretórios para organizar seus arquivos, e para criar múltiplos segmentos de caminho: +</TabItem> +<TabItem label="pnpm"> +```sh +pnpm dev ``` -src/content/docs/ola-mundo.md => seu-site.com/ola-mundo -src/content/docs/guias/faq.md => seu-site.com/guias/faq + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev ``` -### Frontmatter com segurança de tipos +</TabItem> +</Tabs> -Todas as páginas do Starlight compartilham um [conjunto comum de propriedades frontmatter](/pt-br/reference/frontmatter/) para controlar como a página aparece: +Será exibida uma mensagem em seu terminal com a URL para visualização local. +Abra esta URL para começar a navegar no seu site. -```md ---- -title: Olá, Mundo! -description: Essa é uma página no meu site com Starlight ---- -``` +### Crie conteúdo -Se você esquecer de algo importante, Starlight vai te informar. +Starlight está pronto para você adicionar novo conteúdo, ou trazer seus arquivos existentes! -## Fazendo deploy do seu website Starlight +Adicione novas páginas ao seu site criando arquivos Markdown na pasta `src/content/docs/`. -Assim que você tiver criado e customizado seu website Starlight, você pode fazer deploy dele para um servidor web ou plataforma de hospedagem de sua escolha, incluindo Netlify, Vercel, GitHub Pages e vários outros. +Leia mais sobre roteamento baseado em arquivos e suporte para arquivos MDX e Markdoc no guia de [“Páginas”](/pt-br/guides/pages/). -[Aprenda sobre como fazer deploy de um site Astro na documentação do Astro.](https://docs.astro.build/pt-br/guides/deploy/) +### Próximos passos + +- **Configurar:** Descubra opções comuns em ["Customizando Starlight"](/pt-br/guides/customization/). +- **Navegar:** Configure a barra lateral com o guia [“Barra lateral de navegação”](/pt-br/guides/sidebar/). +- **Componentes:** Conheça os cartões, abas e outros componentes integrados no guia [“Componentes”](/pt-br/components/using-components/). +- **Deploy:** Publique seu projeto com o guia [“Deploy do seu site Astro”](https://docs.astro.build/pt-br/guides/deploy/) na documentação do Astro. ## Atualizando Starlight :::tip -Como o Starlight é um software em beta, haverá frequentes atualizações e melhorias. Certifique-se de atualizar Starlight constantemente! +Como o Starlight é um software em beta, haverá frequentes atualizações e melhorias. +Certifique-se de atualizar Starlight constantemente! ::: -Starlight é uma integração Astro, e é atualizado como qualquer outra integração `@astrojs/*`: +Starlight é uma integração Astro. Você pode atualiza-lo e outros pacotes Astro com o seguinte comando em seu terminal: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh -# atualiza Starlight com npm -npm install @astrojs/starlight@latest +npx @astrojs/upgrade ``` </TabItem> <TabItem label="pnpm"> ```sh -# atualiza Starlight com pnpm -pnpm upgrade @astrojs/starlight --latest +pnpm dlx @astrojs/upgrade ``` </TabItem> <TabItem label="Yarn"> ```sh -# atualiza Starlight com yarn -yarn upgrade @astrojs/starlight --latest +yarn dlx @astrojs/upgrade ``` </TabItem> </Tabs> -Você pode ver uma lista completa das mudanças feitas para cada versão no [histórico de mudanças do Starlight](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md). +Consulte o [histórico de mudanças do Starlight](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md) para ver a lista completa das alterações feitas em cada versão. ## Solucionando Problemas no Starlight -Informação sobre tanto a [configuração de projeto](/pt-br/reference/configuration/) e [configuração de frotmatter individual de página](/pt-br/reference/frontmatter/) do Starlight estão disponíveis na seção Referência deste site. Use essas páginas para garantir que seu site Starlight está configurado e funcionando de acordo. - -Veja a lista crescente de guias na navegação lateral para conseguir ajuda em adicionar conteúdo e customizar seu site Starlight. +Use as páginas de referência [configuração do projeto](/pt-br/reference/configuration/) e [configuração do frontmatter para cada página](/pt-br/reference/frontmatter/) para garantir que seu site Starlight esteja configurado e funcionando corretamente. +Confira os guias na barra lateral para ajudá-lo a adicionar conteúdo e personalizar seu site Starlight. -Se a sua resposta não pôde ser encontrada nessa documentação, por favor visite a [documentação do Astro](https://docs.astro.build) para uma documentação mais completa sobre o Astro. Sua pergunta pode ser respondida ao entender como o Astro funciona no geral, por debaixo do tema Starlight. +Se a sua resposta não pôde ser encontrada nessa documentação, por favor visite a [documentação do Astro](https://docs.astro.build/pt-br/) para uma documentação mais completa sobre o Astro. +Sua pergunta pode ser respondida ao entender como o Astro funciona no geral, por debaixo do tema Starlight. Você também pode checar por quaisquer [problemas conhecidos do Starlight no GitHub](https://github.com/withastro/starlight/issues), e conseguir ajuda no [Discord do Astro](https://astro.build/chat/) da nossa ativa e amigável comunidade! Envie perguntas em nosso fórum `#support` com a tag "starlight", ou visite nosso canal dedicado `#starlight` para discutir o desenvolvimento atual e mais! diff --git a/docs/src/content/docs/pt-br/guides/authoring-content.md b/docs/src/content/docs/pt-br/guides/authoring-content.md deleted file mode 100644 index 831b2e48971..00000000000 --- a/docs/src/content/docs/pt-br/guides/authoring-content.md +++ /dev/null @@ -1,209 +0,0 @@ ---- -title: Escrevendo Conteúdo em Markdown -description: Uma visão geral da sintaxe Markdown suportada pelo Starlight. ---- - -Starlight suporta completamente a sintaxe [Markdown](https://daringfireball.net/projects/markdown/) em arquivos `.md` assim como frontmatter [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) para definir metadados como o título e a descrição. - -Por favor verifique a [documentação do MDX](https://mdxjs.com/docs/what-is-mdx/#markdown) ou a [documentação do Markdoc](https://markdoc.dev/docs/syntax) se estiver utilizando esses formatos de arquivo, já que o suporte e uso do Markdown podem variar. - -## Estilos Inline - -Texto pode estar em **negrito**, _itálico_, ou ~~tachado~~. - -```md -Texto pode estar em **negrito**, _itálico_, ou ~~tachado~~. -``` - -Você pode [fazer links para outras páginas](/pt-br/getting-started/). - -```md -Você pode [fazer links para outras páginas](/pt-br/getting-started/). -``` - -Você pode destacar `código inline` com crases. - -```md -Você pode destacar `código inline` com crases. -``` - -## Imagens - -Imagens no Starlight usam o [suporte integrado a assets otimizados do Astro](https://docs.astro.build/pt-br/guides/assets/). - -Markdown e MDX suportam a sintaxe do Markdown para mostrar imagens que incluem texto alternativo para leitores de tela e tecnologias assistivas. - -![Uma ilustração de planetas e estrelas apresentando a palavra “astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) - -```md -![Uma ilustração de planetas e estrelas apresentando a palavra “astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) -``` - -Caminhos de imagem relativos também são suportados para imagens armazenadas localmente no seu projeto. - -```md -// src/content/docs/pagina-1.md - -![Um foguete no espaço](../../assets/imagens/foguete.svg) -``` - -## Cabeçalhos - -Você pode estruturar o conteúdo utilizando um cabeçalho. Cabeçalhos no Markdown são indicados pelo número de `#` no início de uma linha. - -### Como estruturar o conteúdo da página no Starlight - -Starlight é configurado para automaticamente utilizar o título da sua página como um cabeçalho superior e irá incluir um cabeçalho "Visão geral" no topo do índice de cada página. Nós recomendamos começar cada página com um parágrafo normal e utilizar cabeçalhos na página a partir de `<h2>` para baixo: - -```md ---- -title: Guia de Markdown -description: Como utilizar Markdown no Starlight ---- - -Esta página descreve como utilizar Markdown no Starlight. - -## Estilos Inline - -## Cabeçalhos -``` - -### Links de âncora automáticos de cabeçalho - -Utilizar cabeçalhos no Markdown irá automaticamente dá-lo links de âncora para que você direcione diretamente a certas seções da sua página: - -```md ---- -title: Minha página de conteúdo -description: Como utilizar os links de âncora integrados do Starlight ---- - -## Introdução - -Eu posso fazer um link para [minha conclusão](#conclusão) abaixo na mesma página. - -## Conclusão - -`https://meu-site.com/pagina1/#introdução` navega diretamente para minha Introdução. -``` - -Cabeçalhos de Nível 2 (`<h2>`) e Nível 3 (`<h3>`) vão aparecer automaticamente no índice da página. - -## Asides - -Asides (também conhecidos como “advertências” ou “frases de destaque”) são úteis para mostrar informações secundárias ao lado do conteúdo principal de uma página. - -Starlight providencia uma sintaxe Markdown customizada para renderizar asides. Blocos Aside são indicados utilizando um par de dois pontos triplo `:::` para envolver o seu conteúdo, e podem ser do tipo `note`, `tip`, `caution` ou `danger`. - -Você pode aninhar qualquer outras formas de conteúdo Markdown dentro de um aside, mas asides são mais adequados para blocos curtos e concisos de conteúdo. - -### Aside de Nota - -:::note -Starlight é um conjunto de ferramentas para websites de documentação feito com [Astro](https://astro.build/). Você pode começar com o comando: - -```sh -npm create astro@latest -- --template starlight -``` - -::: - -````md -:::note -Starlight é um conjunto de ferramentas para websites de documentação feito com [Astro](https://astro.build/). Você pode começar com o comando: - -```sh -npm create astro@latest -- --template starlight -``` - -::: -```` - -### Títulos de aside customizados - -Você pode especificar um título customizado para o aside em colchetes seguindo o tipo do aside, e.x. `:::tip[Você sabia?]`. - -:::tip[Você sabia?] -Astro te ajuda a construir websites mais rápidos com a [“Arquitetura em Ilhas”](https://docs.astro.build/pt-br/concepts/islands/). -::: - -```md -:::tip[Você sabia?] -Astro te ajuda a construir websites mais rápidos com a [“Arquitetura em Ilhas”](https://docs.astro.build/pt-br/concepts/islands/). -::: -``` - -### Mais tipos de aside - -Asides de cuidado e perigo são úteis para chamar a atenção de um usuário a detalhes que podem o atrapalhar. -Se você anda os utilizando muito, pode ser um sinal de que o que você está documentando se beneficiaria com uma mudança. - -:::caution -Se você não tem certeza de que você quer um site de documentação incrível, pense novamente antes de utilizar [Starlight](../../). -::: - -:::danger -Seus usuários podem ser mais produtivos e considerar seu produto mais fácil de usar graças a funcionalidades úteis do Starlight. - -- Navegação compreensível -- Tema de cores configurável pelo usuário -- [Suporte a internacionalização](/pt-br/guides/i18n) - -::: - -```md -:::caution -Se você não tem certeza de que você quer um site de documentação incrível, pense novamente antes de utilizar [Starlight](../../). -::: - -:::danger -Seus usuários podem ser mais produtivos e considerar seu produto mais fácil de usar graças a funcionalidades úteis do Starlight. - -- Navegação compreensível -- Tema de cores configurável pelo usuário -- [Suporte a internacionalização](/pt-br/guides/i18n) - -::: -``` - -## Citações - -> Esta é uma citação, que é comumente utilizada ao citar outra pessoa ou documento. -> -> Citações são indicadas com um `>` no começo de cada linha. - -```md -> Esta é uma citação, que é comumente utilizada ao citar outra pessoa ou documento. -> -> Citações são indicadas com um `>` no começo de cada linha. -``` - -## Blocos de código - -Um bloco de código é indicado por um bloco com três crases <code>```</code> no começo e fim. Você pode indicar a linguagem de programação sendo utilizada após as crases iniciais. - -```js -// Código JavaScript com syntax highlighting. -var divertido = function lingua(l) { - formatodata.i18n = require('./lingua/' + l); - return true; -}; -``` - -````md -```js -// Código JavaScript com syntax highlighting. -var divertido = function lingua(l) { - formatodata.i18n = require('./lingua/' + l); - return true; -}; -``` -```` - -```md -Longos blocos de código de linha única não devem quebrar linha. Eles devem rolar horizontalmente se forem muito longos. Esta linha deve ser longa o suficiente para demonstrar isso. -``` - -## Outras funcionalidades comuns do Markdown - -Starlight suporta todo o resto da sintaxe de escrita do Markdown, como listas e tabelas. Veja a [Cheat Sheet de Markdown do The Markdown Guide](https://www.markdownguide.org/cheat-sheet/) para uma visão geral rápida de todos os elementos da sintaxe do Markdown. diff --git a/docs/src/content/docs/pt-br/guides/components.mdx b/docs/src/content/docs/pt-br/guides/components.mdx deleted file mode 100644 index 8d7175750ae..00000000000 --- a/docs/src/content/docs/pt-br/guides/components.mdx +++ /dev/null @@ -1,196 +0,0 @@ ---- -title: Componentes -description: Utilizando componentes no MDX com Starlight. ---- - -Componentes te permitem facilmente reutilizar pedaços da UI ou estilizar consistentemente. -Alguns exemplos são um cartão de link ou um embed do YouTube. -Starlight suporta o uso de componentes em arquivos [MDX](https://mdxjs.com/) e providencia alguns components comuns para você utilizar. - -[Aprenda mais sobre como construir componentes na documentação do Astro](https://docs.astro.build/pt-br/core-concepts/astro-components/). - -## Utilizando um componente - -Você pode utilizar um componente ao importá-lo em seu arquivo MDX e então renderizá-lo como uma tag JSX. - -Elas se parecem com tags HTML porém começam com uma letra maiúscula correspondente ao nome na sua declaração `import`: - -```mdx ---- -# src/content/docs/index.mdx -title: Bem-vindo a minha documentação ---- - -import AlgumComponente from '../../components/AlgumComponente.astro'; -import OutroComponente from '../../components/OutroComponente.astro'; - -<AlgumComponente prop="algo" /> - -<OutroComponente> - Componentes também podem conter **conteúdo aninhado**. -</OutroComponente> -``` - -Já que Starlight é feito com Astro, você pode adicionar suporte para componentes feitos com qualquer [framework de UI suportado (React, Preact, Svelte, Vue, Solid, Lit e Alpine)](https://docs.astro.build/pt-br/core-concepts/framework-components/) em seus arquivos MDX. -Aprenda mais sobre como [utilizar componentes no MDX](https://docs.astro.build/pt-br/guides/markdown-content/#usando-componentes-no-mdx) na documentação do Astro. - -### Compatibilidade com os estilos do Starlight - -Starlight aplica estilos padrões para seu conteúdo Markdown, como por exemplo, adicionando margem entre elementos. -Se esses estilos conflitam com a aparência do seu componente, defina a classe `not-content` no seu componente para desabilitá-los. - -```astro ---- -// src/components/Exemplo.astro ---- - -<div class="not-content"> - <p>Não é impactado pelos estilos padrões de conteúdo do Starlight.</p> -</div> -``` - -## Componentes integrados - -Starlight providencia alguns componentes integrados para casos de uso comuns em documentações. -Esses componentes estão disponíveis através do pacote `@astrojs/starlight/components`. - -### Abas - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -Você pode mostrar uma interface com abas utilizando os componentes `<Tabs>` e `<TabItem>`. -Cada `<TabItem>` tem que ter uma `label` para mostrar aos usuários. - -```mdx -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -<Tabs> - <TabItem label="Estrelas">Sirius, Vega, Betelgeuse</TabItem> - <TabItem label="Luas">Io, Europa, Ganymede</TabItem> -</Tabs> -``` - -O código acima gera as seguintes abas na página: - -<Tabs> - <TabItem label="Estrelas">Sirius, Vega, Betelgeuse</TabItem> - <TabItem label="Luas">Io, Europa, Ganymede</TabItem> -</Tabs> - -### Cartões - -import { Card, CardGrid } from '@astrojs/starlight/components'; - -Você pode mostrar conteúdo em uma caixa seguindo os estilos do Starlight utilizando o componente `<Card>`. -Coloque múltiplos cartões no componente `<CardGrid>` para mostrar cartões lado a lado quando houver espaço suficiente. - -Um `<Card>` precisa de um `title` e pode opcionalmente incluir o atributo `icon` para definir o nome de um dos [ícones integrados do Starlight](#all-icons). - -```mdx -import { Card, CardGrid } from '@astrojs/starlight/components'; - -<Card title="Veja isso">Conteúdo interessante que você quer destacar.</Card> - -<CardGrid> - <Card title="Estrelas" icon="star"> - Sirius, Vega, Betelgeuse - </Card> - <Card title="Luas" icon="moon"> - Io, Europa, Ganymede - </Card> -</CardGrid> -``` - -O código acima gera o seguinte na página: - -<Card title="Veja isso">Conteúdo interessante que você quer destacar.</Card> - -<CardGrid> - <Card title="Estrelas" icon="star"> - Sirius, Vega, Betelgeuse - </Card> - <Card title="Luas" icon="moon"> - Io, Europa, Ganymede - </Card> -</CardGrid> - -:::tip -Utilize um grid de cartões na sua página inicial para mostrar as principais funcionalidades do seu projeto. -Adicione o atributo `stagger` para mover a segunda coluna de cartões verticalmente para adicionar interesse visual: - -```astro -<CardGrid stagger> - <!-- cartões --> -</CardGrid> -``` - -::: - -### Cartões de Link - -Utilize o componente `<LinkCard>` para fazer um link proeminente para outras páginas. - -Um `<LinkCard>` precisa de um `title` e um atributo [`href`](https://developer.mozilla.org/pt-BR/docs/Web/HTML/Element/a#attr-href). Você pode opcionalmente incluir uma pequena `description` ou outros atributos de link como `target`. - -Agrupe múltiplos componentes `<LinkCard>` em `<CardGrid>` para mostrar cartões lado a lado quando houver espaço suficiente. - -```mdx -import { LinkCard, CardGrid } from '@astrojs/starlight/components'; - -<LinkCard - title="Customizando Starlight" - description="Aprenda como fazer seu site Starlight único com estilos customizados, fontes e mais." - href="/pt-br/guides/customization/" -/> - -<CardGrid> - <LinkCard - title="Escrevendo Markdown" - href="/pt-br/guides/authoring-content/" - /> - <LinkCard title="Componentes" href="/pt-br/guides/components/" /> -</CardGrid> -``` - -O código acima gera o seguinte na página: - -import { LinkCard } from '@astrojs/starlight/components'; - -<LinkCard - title="Customizando Starlight" - description="Aprenda como fazer seu site Starlight único com estilos customizados, fontes e mais." - href="/pt-br/guides/customization/" -/> - -<CardGrid> - <LinkCard - title="Escrevendo Markdown" - href="/pt-br/guides/authoring-content/" - /> - <LinkCard title="Componentes" href="/pt-br/guides/components/" /> -</CardGrid> - -### Ícone - -import { Icon } from '@astrojs/starlight/components'; -import IconsList from '../../../../components/icons-list.astro'; - -Starlight providencia um conjunto comum de ícones que você pode mostrar em seu conteúdo utilizando o componente `<Icon>`. - -Cada `<Icon>` requer um [`name`](#todos-os-ícones) e pode opcionalmente incluir um atributo `label`, `size` e `color`. - -```mdx -import { Icon } from '@astrojs/starlight/components'; - -<Icon name="star" color="goldenrod" size="2rem" /> -``` - -O código acima gera o seguinte na página: - -<Icon name="star" color="goldenrod" size="2rem" /> - -#### Todos os ícones - -Uma lista de todos os ícones disponíveis é mostrada abaixo com seus nomes associados. Clique em um ícone para copiar o código do componente dele. - -<IconsList /> diff --git a/docs/src/content/docs/pt-br/guides/css-and-tailwind.mdx b/docs/src/content/docs/pt-br/guides/css-and-tailwind.mdx deleted file mode 100644 index bb71b2e5cba..00000000000 --- a/docs/src/content/docs/pt-br/guides/css-and-tailwind.mdx +++ /dev/null @@ -1,288 +0,0 @@ ---- -title: CSS e Estilização -description: Aprenda como estilizar seu site Starlight com CSS customizado ou integrá-lo com Tailwind CSS. ---- - -Você pode estilizar seu site Starlight com arquivos CSS customizados ou utilizar o plugin Starlight Tailwind. - -## Estilos CSS customizados - -Customize os estilos aplicados ao seu site Starlight ao fornecer arquivos CSS adicionais para modificar ou estender os estilos padrões do Starlight. - -1. Adicione um arquivo CSS ao seu diretório `src/`. - Por exemplo, você poderia definir uma largura padrão de coluna mais larga e um tamanho de texto maior para títulos da página: - - ```css - /* src/styles/customizado.css */ - :root { - --sl-content-width: 50rem; - --sl-text-5xl: 3.5rem; - } - ``` - -2. Adicione o caminho para seu arquivo CSS ao array `customCss` do Starlight em `astro.config.mjs`: - - ```js - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - - export default defineConfig({ - integrations: [ - starlight({ - title: 'Documentação com CSS Customizado', - customCss: [ - // Caminho relativo ao seu arquivo CSS customizado - './src/styles/customizado.css', - ], - }), - ], - }); - ``` - -Você pode ver todas as propriedades CSS customizadas utilizadas pelo Starlight que você pode definir para customizar o seu site no [arquivo `props.css` no GitHub](https://github.com/withastro/starlight/blob/main/packages/starlight/style/props.css). - -## Tailwind CSS - -Suporte para Tailwind CSS em projetos Astro é providenciado pela [integração Astro Tailwind](https://docs.astro.build/pt-br/guides/integrations-guide/tailwind/). -Starlight providencia um plugin Tailwind complementar para ajudar a configurar o Tailwind de forma compatível com os estilos do Starlight. - -O plugin Starlight Tailwind plugin aplica a seguinte configuração: - -- Configura as variantes `dark:` do Tailwind para funcionarem com o modo escuro do Starlight. -- Utiliza [cores de tema e fontes](#estilizando-starlight-com-tailwind) do Tailwind na UI do Starlight. -- Desabilita os estilos de reset [Preflight](https://tailwindcss.com/docs/preflight) do Tailwind enquanto seletivamente restora partes essenciais do Preflight necessárias para o as classes utilitárias de borda do Tailwind. - -### Crie um novo projeto com Tailwind - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -Comece um novo projeto Starlight com Tailwind CSS pré-configurado utilizando `create astro`: - -<Tabs> -<TabItem label="npm"> - -```sh -npm create astro@latest -- --template starlight/tailwind -``` - -</TabItem> -<TabItem label="pnpm"> - -```sh -pnpm create astro --template starlight/tailwind -``` - -</TabItem> -<TabItem label="Yarn"> - -```sh -yarn create astro --template starlight/tailwind -``` - -</TabItem> -</Tabs> - -### Adicione Tailwind a um projeto existente - -Se você já tem um site Starlight e quer adicionar Tailwind CSS, siga estes passos. - -1. Adicione a integração Astro Tailwind: - - <Tabs> - - <TabItem label="npm"> - - ```sh - npx astro add tailwind - ``` - - </TabItem> - - <TabItem label="pnpm"> - - ```sh - pnpm astro add tailwind - ``` - - </TabItem> - - <TabItem label="Yarn"> - - ```sh - yarn astro add tailwind - ``` - - </TabItem> - - </Tabs> - -2. Instale o plugin Starlight Tailwind: - - <Tabs> - - <TabItem label="npm"> - - ```sh - npm install @astrojs/starlight-tailwind - ``` - - </TabItem> - - <TabItem label="pnpm"> - - ```sh - pnpm install @astrojs/starlight-tailwind - ``` - - </TabItem> - - <TabItem label="Yarn"> - - ```sh - yarn add @astrojs/starlight-tailwind - ``` - - </TabItem> - - </Tabs> - -3. Crie um arquivo CSS para os estilos base do Tailwind, por exemplo, em `src/tailwind.css`: - - ```css - /* src/tailwind.css */ - @tailwind base; - @tailwind components; - @tailwind utilities; - ``` - -4. Atualize seu arquivo de configuração do Astro para utilizar seus estilos base do Tailwind e desabilitar os estilos base padrões: - - ```js {11-12,16-17} - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - import tailwind from '@astrojs/tailwind'; - - export default defineConfig({ - integrations: [ - starlight({ - title: 'Documentação com Tailwind', - customCss: [ - // Caminho para seus estilos base do Tailwind: - './src/tailwind.css', - ], - }), - tailwind({ - // Desabilita os estilos base padrões: - applyBaseStyles: false, - }), - ], - }); - ``` - -5. Adicione o plugin Starlight Tailwind em `tailwind.config.cjs`: - - ```js ins={2,7} - // tailwind.config.cjs - const starlightPlugin = require('@astrojs/starlight-tailwind'); - - /** @type {import('tailwindcss').Config} */ - module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - plugins: [starlightPlugin()], - }; - ``` - -### Estilizando Starlight com Tailwind - -Starlight irá utilizar os valores da sua [configuração de tema do Tailwind](https://tailwindcss.com/docs/theme) em sua UI. - -Se definidas, as seguintes opções irão sobrescrever os estilos padrões do Starlight: - -- `colors.accent` — usado para os links e o item atualmente destacado -- `colors.gray` — usado para as cores de fundo e bordas -- `fontFamily.sans` — usado para o texto da UI e conteúdo -- `fontFamily.mono` — usado para códigos de exemplo - -```js {12,14,18,20} -// tailwind.config.cjs -const starlightPlugin = require('@astrojs/starlight-tailwind'); -const colors = require('tailwindcss/colors'); - -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: { - colors: { - // Sua cor de destaque preferida. Indigo é o mais próximo do padrão do Starlight. - accent: colors.indigo, - // Sua escala de cinzas preferida. Zinc é o mais próximo do padrão do Starlight. - gray: colors.zinc, - }, - fontFamily: { - // Sua fonte de texto preferida. Starlight utiliza um conjunto de fontes do sistema por padrão. - sans: ['"Atkinson Hyperlegible"'], - // Sua fonte de código preferida. Starlight utiliza fontes monospace do sistema por padrão. - mono: ['"IBM Plex Mono"'], - }, - }, - }, - plugins: [starlightPlugin()], -}; -``` - -## Tema - -O tema de cores do Starlight pode ser controlado ao sobreescrever suas propriedades customizada padrões. -Essas variáveis são usadas na UI com uma variedade de tons de cinza usados como cores de texto e fundo e uma cor de destaque usada para links e para destacar itens atuais da navegação. - -### Editor de tema de cores - -Use os controles deslizantes abaixo para modificar as paletas de cor de destaque e cinza do Starlight. -As áreas de pré-visualização escura e clara irão mostrar as cores resultantes, e a página inteira também será atualizada para visualizar suas mudanças. - -Quando você estiver feliz com as mudanças, copie o código CSS ou Tailwind abaixo e use-o no seu projeto. - -import ThemeDesigner from '../../../../components/theme-designer.astro'; - -<ThemeDesigner - labels={{ - presets: { - label: 'Predefinições', - ocean: 'Oceano', - forest: 'Floresta', - oxide: 'Ferrugem', - nebula: 'Nebulosa', - default: 'Padrão', - random: 'Aleatório', - }, - editor: { - accentColor: 'Destaque', - grayColor: 'Cinza', - hue: 'Tonalidade', - chroma: 'Croma', - pickColor: 'Escolha uma cor', - }, - preview: { - darkMode: 'Modo escuro', - lightMode: 'Modo claro', - bodyText: - 'Texto de corpo é mostrado em um tom de cinza com alto contraste com o fundo.', - linkText: 'Links são coloridos.', - dimText: 'Algum texto, como o índice, tem um menor contraste.', - inlineCode: 'Código inline tem um fundo distinto.', - }, - }} -> - <Fragment slot="css-docs"> - Adicione o seguinte CSS ao seu projeto em um [arquivo CSS - customizado](#estilos-css-customizados) para aplicar este tema ao seu site. - </Fragment> - <Fragment slot="tailwind-docs"> - O [arquivo de configuração do Tailwind](#estilizando-starlight-com-tailwind) - de exemplo abaixo inclui paletas de cor `accent` e `gray` para utilizar no - objeto da configuração `theme.extend.colors`. - </Fragment> -</ThemeDesigner> diff --git a/docs/src/content/docs/pt-br/guides/customization.mdx b/docs/src/content/docs/pt-br/guides/customization.mdx deleted file mode 100644 index 55b30e78912..00000000000 --- a/docs/src/content/docs/pt-br/guides/customization.mdx +++ /dev/null @@ -1,429 +0,0 @@ ---- -title: Customizando Starlight -description: Aprenda como fazer seu site Starlight único com sua própria logo, fontes customizadas, design de página inicial e mais. ---- - -import { Tabs, TabItem } from '@astrojs/starlight/components'; -import FileTree from '../../../../components/file-tree.astro'; - -Starlight providencia uma estilização e funcionalidades sensíveis padrões, para que você inicie rapidamente sem nenhuma configuração necessária. - -Quando você quiser começar a customizar a aparência e sensação do seu site Starlight, este guia tem tudo o que você precisa. - -## Adicione sua logo - -Adicionar uma logo customizada ao cabeçalho do site é uma forma rápida de adicionar sua marca individual a um site Starlight. - -1. Adicione o arquivo de imagem da sua logo para o diretório `src/assets/`: - - <FileTree> - - - src/ - - assets/ - - **minha-logo.svg** - - content/ - - astro.config.mjs - - </FileTree> - -2. Adicione o caminho para sua logo como a opção [`logo.src`](/pt-br/reference/configuration/#logo) do Starlight em `astro.config.mjs`: - - ```js - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - - export default defineConfig({ - integrations: [ - starlight({ - title: 'Documentação com Minha Logo', - logo: { - src: './src/assets/minha-logo.svg', - }, - }), - ], - }); - ``` - -Por padrão, a logo será mostrada ao lado do `title` do seu site. -Se sua imagem da logo já inclui o título do site, você pode esconder o texto do título visualmente ao definir a opção `replacesTitle`. -O texto do `title` ainda será incluido para leitores de tela para que o cabeçalho continue acessível. - -```js -starlight({ - title: 'Documentação com Minha Logo', - logo: { - src: './src/assets/minha-logo.svg', - replacesTitle: true, - }, -}), -``` - -### Variantes clara e escura da logo - -Você pode mostrar diferentes versões da sua logo no modo claro e escuro. - -1. Adicione um arquivo de imagem para cada variante em `src/assets/`: - - <FileTree> - - - src/ - - assets/ - - **logo-clara.svg** - - **logo-escura.svg** - - content/ - - astro.config.mjs - - </FileTree> - -2. Adicione o caminho para suas variantes da logo como as opções `light` e `dark` ao invés de `src` em `astro.config.mjs`: - - ```js - starlight({ - title: 'Documentação com Minha Logo', - logo: { - light: './src/assets/logo-clara.svg', - dark: './src/assets/logo-escura.svg', - }, - }), - ``` - -## Habilitar o sitemap - -O Starlight possui suporte integrado para a geração de um sitemap. Habilite a geração do sitemap definindo sua URL como `site` em `astro.config.mjs`: - -```js -// astro.config.mjs - -export default defineConfig({ - site: 'https://stargazers.club', - integrations: [starlight({ title: 'Site com sitemap' })], -}); -``` - -## Layout da página - -Por padrão, páginas do Starlight usam um layout com uma barra de navegação lateral global e um índice que mostra os cabeçalhos da página atual. - -Você pode aplicar um layout de página maior sem barras laterais definindo [`template: splash`](/pt-br/reference/frontmatter/#template) no frontmatter de uma página. -Isso funciona particularmente bem para páginas iniciais e você pode vê-lo em ação na [página inicial deste site](/pt-br/). - -```md ---- -# src/content/docs/index.md - -title: Minha Página Inicial -template: splash ---- -``` - -## Índice - -Starlight mostra um índice para cada página para tornar mais fácil para leitores pularem ao cabeçalho no qual estão procurando. -Você pode customizar - ou até desabilitar - o índice globalmente na integração Starlight ou página a página no frontmatter. - -Por padrão, cabeçalhos `<h2>` e `<h3>` são inclusos no índice. Modifique quais níveis de cabeçalho incluir ao redor do site utilizando as opções `minHeadingLevel` e `maxHeadingLevel` na [global `tableOfContents`](/pt-br/reference/configuration/#tableofcontents). Sobrescreva esses padrões em uma página individual adicionando as propriedades correspondentes do [frontmatter `tableOfContents`](/pt-br/reference/frontmatter/#tableofcontents): - -<Tabs> - <TabItem label="Frontmatter"> - -```md ---- -# src/content/docs/exemplo.md -title: Página com apenas H2s no índice -tableOfContents: - minHeadingLevel: 2 - maxHeadingLevel: 2 ---- -``` - - </TabItem> - <TabItem label="Configuração global"> - -```js -// astro.config.mjs - -defineConfig({ - integrations: [ - starlight({ - title: '', - tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 2 }, - }), - ], -}); -``` - - </TabItem> -</Tabs> - -Desabilite o índice completamente definindo a opção `tableOfContents` como `false`: - -<Tabs> - <TabItem label="Frontmatter"> - -```md ---- -# src/content/docs/exemplo.md -title: Página sem um índice -tableOfContents: false ---- -``` - - </TabItem> - <TabItem label="Configuração global"> - -```js -// astro.config.mjs - -defineConfig({ - integrations: [ - starlight({ - title: 'Documentação com um índice desabilitado globalmente', - tableOfContents: false, - }), - ], -}); -``` - - </TabItem> -</Tabs> - -## Links de redes sociais - -Starlight tem suporte integrado para adicionar links de suas contas de redes sociais ao cabeçalho do site através da opção [`social`](/pt-br/reference/configuration/#social) na integração Starlight. - -Atualmente, links para Bitbucket, Codeberg, CodePen, Discord, GitHub, GitLab, Gitter, LinkedIn, Mastodon, Microsoft Teams, Stack Overflow, Threads, Twitch, Twitter e Youtube são suportados. -Nos avise no GitHub ou Discord se você precisa de suporte para outro serviço! - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'Documentação com Links de Redes Sociais', - social: { - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - }, - }), - ], -}); -``` - -## Links de Edição - -Starlight pode mostrar um link de "Editar página" no rodapé de cada página. -Isso faz fácil para um leitor encontrar o arquivo para editar para melhorar sua documentação. -Particularmente para projetos open-source, isso pode ajudar a encorajar contribuições da sua comunidade. - -Para habilitar links de edição, defina [`editLink.baseUrl`](/pt-br/reference/configuration/#editlink) para a URL usada para editar seu repositório na configuração da integração Starlight. -O valor de `editLink.baseUrl` será anexado ao caminho para a página atual para formar o link de edição completo. - -Padrões comuns incluem: - -- GitHub: `https://github.com/USUARIO/REPOSITORIO/edit/BRANCH/` -- GitLab: `https://gitlab.com/USUARIO/REPOSITORIO/-/edit/BRANCH/` - -Se o seu projeto Starlight não está na raiz do seu repositório, inclua o caminho ao projeto no fim da URL base. - -Este exemplo mostra o link de edição configurado para a documentação do Starlight, que vive no subdiretório `docs/` da branch `main` do repositório `withastro/starlight` no GitHub: - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'Documentação com Links de Edição', - editLink: { - baseUrl: 'https://github.com/withastro/starlight/edit/main/docs/', - }, - }), - ], -}); -``` - -## Página 404 Customizada - -Sites Starlight mostram uma página 404 simples por padrão. -Você pode customizá-la adicionando um arquivo `404.md` (ou `404.mdx`) ao seu diretório `src/content/docs/`: - -<FileTree> - -- src/ - - content/ - - docs/ - - **404.md** - - index.md -- astro.config.mjs - -</FileTree> - -Você pode utilizar todas as técnicas de customização e layout de página do Starlight em sua página 404. Por exemplo, a página 404 padrão utiliza o [template `splash`](#layout-da-página) e o componente [`hero`](/pt-br/reference/frontmatter/#hero) no frontmatter: - -```md ---- -title: '404' -template: splash -editUrl: false -hero: - title: '404' - tagline: Página não encontrada. Verifique a URL ou tenta utilizar a barra de pesquisa. ---- -``` - -## Fontes customizadas - -Por padrão, Starlight utiliza fontes sans-serif disponíveis no dispositivo local do usuário para todo o texto. -Isso garante que a documentação carrega rapidamente em uma fonte que é familiar para cada usuário, sem precisar de largura de banda para baixar grandes arquivos de fonte. - -Se você deve adicionar uma fonte customizada ao seu site Starlight, você pode definir fontes para usar em arquivos CSS customizados ou com qualquer outra [técnica de estilização do Astro](https://docs.astro.build/pt-br/guides/styling/). - -### Configure fontes - -Se você já tem arquivos de fonte, siga o [guia de configuração local](#configure-arquivos-de-fonte-locais). -Para utilizar Google Fonts, siga o [guia de configuração do Fontsource](#configure-uma-fonte-do-fontsource). - -#### Configure arquivos de fonte locais - -1. Adicione seus arquivos de fonte para o diretório `src/fonts/` e crie um arquivo vazio `font-face.css`: - - <FileTree> - - - src/ - - content/ - - fonts/ - - **FonteCustomizada.woff2** - - **font-face.css** - - astro.config.mjs - - </FileTree> - -2. Adicione uma [declaração `@font-face`](https://developer.mozilla.org/pt-BR/docs/Web/CSS/@font-face) para cada uma de suas fontes em `src/fonts/font-face.css`. - Utilize um caminho relativo para o arquivo de fonte na função `url()`. - - ```css - /* src/fonts/font-face.css */ - - @font-face { - font-family: 'Fonte Customizada'; - /* Use um caminho relativo para o arquivo de fonte local em `url()`. */ - src: url('./FonteCustomizada.woff2') format('woff2'); - font-weight: normal; - font-style: normal; - font-display: swap; - } - ``` - -3. Adicione o caminho para seu arquivo `font-face.css` ao array `customCss` do Starlight em `astro.config.mjs`: - - ```js - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - - export default defineConfig({ - integrations: [ - starlight({ - title: 'Documentação Com Meu Tipo de Letra Customizado', - customCss: [ - // Caminho relativo para seu arquivo CSS @font-face. - './src/fonts/font-face.css', - ], - }), - ], - }); - ``` - -#### Configure uma fonte do Fontsource - -O projeto [Fontsource](https://fontsource.org/) simplifica a utilização de Google Fonts e outras fontes open-source. -Ele providencia módulos do npm que você pode isntalar para as fontes que você quer usar e inclui arquivos CSS prontos para adicionar ao seu projeto. - -1. Encontre a fonte que você quer utilizar no [catálogo do Fontsource](https://fontsource.org/). - Este exemplo irá utilizar [IBM Plex Serif](https://fontsource.org/fonts/ibm-plex-serif). - -2. Instale o pacote da sua fonte escolhida. - Você pode encontrar o nome do pacote clicando em “Install” na página de fontes do Fontsource. - - <Tabs> - - <TabItem label="npm"> - - ```sh - npm install @fontsource/ibm-plex-serif - ``` - - </TabItem> - - <TabItem label="pnpm"> - - ```sh - pnpm install @fontsource/ibm-plex-serif - ``` - - </TabItem> - - <TabItem label="Yarn"> - - ```sh - yarn add @fontsource/ibm-plex-serif - ``` - - </TabItem> - - </Tabs> - -3. Adicione os arquivos CSS do Fontsource ao array `customCss` do Starlight em `astro.config.mjs`: - - ```js - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - - export default defineConfig({ - integrations: [ - starlight({ - title: 'Documentação Com Meu Tipo de Letra Customizado', - customCss: [ - // Arquivos do Fontsource para as espessuras de fonte regular e semi-negrito. - '@fontsource/ibm-plex-serif/400.css', - '@fontsource/ibm-plex-serif/600.css', - ], - }), - ], - }); - ``` - - Fontsource envia múltiplos arquivos CSS para cada fonte. Veja a [documentação do Fontsource](https://fontsource.org/docs/getting-started/install#4-weights-and-styles) em como incluir diferentes espessuras e estilos para entender quais utilizar. - -### Utilize fontes - -Para aplicar a fonte que você definiu para o seu site, utilize o nome da sua fonte escolhida em um [arquivo CSS customizado](/pt-br/guides/css-and-tailwind/#estilos-css-customizados). -Por exemplo, para sobrescrever a fonte padrão do Starlight em todo lugar, defina a propriedade customizada `--sl-font`: - -```css -/* src/styles/customizada.css */ - -:root { - --sl-font: 'IBM Plex Serif', serif; -} -``` - -Você também pode escrever CSS mais específico se você quiser aplicar sua fonte mais seletivamente. -Por exemplo, para definir uma fonte no conteúdo principal apenas, mas não nas barras laterais: - -```css -/* src/styles/customizada.css */ - -main { - font-family: 'IBM Plex Serif', serif; -} -``` - -Siga as [instruções de CSS customizado](/pt-br/guides/css-and-tailwind/#estilos-css-customizados) para adicionar seus estilos ao seu site. diff --git a/docs/src/content/docs/pt-br/guides/i18n.mdx b/docs/src/content/docs/pt-br/guides/i18n.mdx deleted file mode 100644 index 2f004eb5cc7..00000000000 --- a/docs/src/content/docs/pt-br/guides/i18n.mdx +++ /dev/null @@ -1,220 +0,0 @@ ---- -title: Internacionalização (i18n) -description: Aprenda como configurar seu site Starlight para suportar várias línguas. ---- - -import FileTree from '../../../../components/file-tree.astro'; - -Starlight providencia suporte integrado para sites multilíngue, incluindo roteamento, conteúdo de fallback e suporte completo para línguas right-to-left (RTL). - -## Configure i18n - -1. Diga ao Starlight as línguas que você suporta passando [`locales`](/pt-br/reference/configuration/#locales) e [`defaultLocale`](/pt-br/reference/configuration/#defaultlocale) para a integração Starlight: - - ```js - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - - export default defineConfig({ - integrations: [ - starlight({ - title: 'Minha Documentação', - // Define Português como a língua padrão deste site. - defaultLocale: 'pt', - locales: { - // Documentação em Português em `src/content/docs/pt/` - pt: { - label: 'Português', - }, - // Documentação em Chinês Simplificado em `src/content/docs/zh/` - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - // Documentação em Árabe docs in `src/content/docs/ar/` - ar: { - label: 'العربية', - dir: 'rtl', - }, - }, - }), - ], - }); - ``` - - Seu `defaultLocale` será utilizado para o conteúdo de fallback e rótulos da UI, então escolha a língua que é a mais provável para você começar a escrever conteúdo em, ou já tem conteúdo para ela. - -2. Crie um diretório para cada língua em `src/content/docs/`. - Por exemplo, para a configuração mostrada acima, crie as seguintes pastas: - - <FileTree> - - - src/ - - content/ - - docs/ - - ar/ - - pt/ - - zh/ - - </FileTree> - -3. Você agora pode adicionar arquivos de conteúdo em seus diretórios da língua. Use o mesmo nome de arquivo para associar páginas entre línguas e se aproveite do conjunto completo de funcionalidades de i18n do Starlight, incluindo conteúdo de fallback, avisos de tradução e mais. - - Por exemplo, crie `ar/index.md` e `pt/index.md` para representar a página inicial em Árabe e Português respectivamente. - -### Use um local raiz - -Você pode usar um local “raiz” para servir uma língua sem nenhum prefixo de i18n no seu caminho. Por exemplo, se Português é seu local raiz, um caminho de página em Português se pareceria com `/sobre` ao invés de `/pt/sobre`. - -Para definir um local raiz, use a chave `root` na sua configuração de `locales`. Se o local raiz também for o local padrão do seu conteúdo, remova `defaultLocale` ou defina-o como `'root'`. - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'Minha Documentação', - defaultLocale: 'root', // opcional - locales: { - root: { - label: 'Português', - lang: 'pt', // lang é obrigatório para locais raiz - }, - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - }, - }), - ], -}); -``` - -Ao utilizar um local `root`, mantenha as páginas para aquela língua diretamente em `src/content/docs/` ao invés de em uma pasta dedicada para a língua. Por exemplo, aqui está os arquivos para a página inicial em Português e Chinês ao utilizar a configuração acima: - -<FileTree> - -- src/ - - content/ - - docs/ - - **index.md** - - zh/ - - **index.md** - -</FileTree> - -#### Sites monolíngue - -Por padrão, Starlight é um site (Inglês) monolíngue. Para criar um site de língua única em outra língua, a defina como o `root` na sua configuração de `locales`: - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'Minha Documentação', - locales: { - root: { - label: '简体中文', - lang: 'zh-CN', - }, - }, - }), - ], -}); -``` - -Isso te permite sobrescrever a língua padrão do Starlight sem habilitar outras funcionalidades de internacionalização para sites multilíngue, como o seletor de língua. - -## Conteúdo de Fallback - -Starlight espera que você crie páginas equivalentes em todas as suas línguas. Por exemplo, se você tem um arquivo `en/about.md` crie, um `about.md` para cada outra língua que você suporta. Isso permite que Starlight providencie conteúdo de fallback automático para páginas que você ainda não tenha traduzidas. - -Se uma tradução ainda não está disponível para uma língua, Starlight irá mostrar aos leitores o conteúdo dessa página na língua padrão (definida através de `defaultLocale`). Por exemplo, se você ainda não criou uma versão em Francês da sua página "Sobre" e sua língua padrão é Inglês, visitantes de `/fr/about` irão ver o conteúdo em Inglês de `/en/about` com um aviso de que esta página ainda não foi traduzida. Isso te ajuda a adicionar conteúdo na sua língua padrão e então progressivamente traduzí-la quando seus tradutores tiverem tempo. - -## Traduza a UI do Starlight - -Em adição a hospedar arquivos de conteúdo traduzido, Starlight te permite traduzir as strings padrões da UI (e.x. o cabeçalho "Nesta página" no índice) para que seus leitores possam experienciar seu site inteiramente na língua selecionada. - -Strings da UI são providenciadas para Inglês, Tcheco, Francês, Alemão, Italiano, Japonês, Português, Holandês, Dinarmaquês, Espanhol, Turco, Árabe, Norueguês, Persa, Chinês Simplificado, Coreano e Sueco por padrão, e nós aceitamos [contribuições para adicionar mais línguas padrões](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md). - -Você pode fornecer traduções para línguas adicionais que você suporta — ou sobrescrever nossos rótulos padrões — através da coleção de dados `i18n`. - -1. Configure a coleção de dados `i18n` em `src/content/config.ts` se já não estiver configurado: - - ```js - // src/content/config.ts - import { defineCollection } from 'astro:content'; - import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; - - export const collections = { - docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), - }; - ``` - -2. Crie um arquivo JSON em `src/content/i18n/` para cada local adicional que você quer providenciar tradução de strings da UI. - Por exemplo, isso adicionaria arquivos de tradução para Árabe e Chinês Simplificado: - - <FileTree> - - - src/ - - content/ - - i18n/ - - ar.json - - zh-CN.json - - </FileTree> - -3. Adicione traduções para as chaves que você quer traduzir para os arquivos JSON. Traduza apenas os valores, deixando as chaves em Inglês (e.x. `"search.label": "Buscar"`). - - Essas são as strings padrões existentes em Inglês que vem com o Starlight: - - ```json - { - "skipLink.label": "Skip to content", - "search.label": "Search", - "search.shortcutLabel": "(Press / to Search)", - "search.cancelLabel": "Cancel", - "search.devWarning": "Search is only available in production builds. \nTry building and previewing the site to test it out locally.", - "themeSelect.accessibleLabel": "Select theme", - "themeSelect.dark": "Dark", - "themeSelect.light": "Light", - "themeSelect.auto": "Auto", - "languageSelect.accessibleLabel": "Select language", - "menuButton.accessibleLabel": "Menu", - "sidebarNav.accessibleLabel": "Main", - "tableOfContents.onThisPage": "On this page", - "tableOfContents.overview": "Overview", - "i18n.untranslatedContent": "This content is not available in your language yet.", - "page.editLink": "Edit page", - "page.lastUpdated": "Last updated:", - "page.previousLink": "Next", - "page.nextLink": "Previous" - } - ``` - - O modal de pesquisa do Starlight é fornecido pela biblioteca [Pagefind](https://pagefind.app/). - Você pode definir traduções para a UI do Pagefind no mesmo arquivo JSON utilizando chaves com `pagefind`: - - ```json - { - "pagefind.clear_search": "Clear", - "pagefind.load_more": "Load more results", - "pagefind.search_label": "Search this site", - "pagefind.filters_label": "Filters", - "pagefind.zero_results": "No results for [SEARCH_TERM]", - "pagefind.many_results": "[COUNT] results for [SEARCH_TERM]", - "pagefind.one_result": "[COUNT] result for [SEARCH_TERM]", - "pagefind.alt_search": "No results for [SEARCH_TERM]. Showing results for [DIFFERENT_TERM] instead", - "pagefind.search_suggestion": "No results for [SEARCH_TERM]. Try one of the following searches:", - "pagefind.searching": "Searching for [SEARCH_TERM]..." - } - ``` diff --git a/docs/src/content/docs/pt-br/guides/project-structure.mdx b/docs/src/content/docs/pt-br/guides/project-structure.mdx deleted file mode 100644 index bae682af1ad..00000000000 --- a/docs/src/content/docs/pt-br/guides/project-structure.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Estrutura de Projetos -description: Aprenda como organizar arquivos no seu projeto Starlight. ---- - -Este guia irá te mostrar como um projeto Starlight é organizado e o que diferentes arquivos em seu projeto fazem. - -Projetos Starlight geralmente seguem a mesma estrutura de arquivos e diretórios que outros projetos Astro. Veja a [documentação de estrutura de projetos do Astro](https://docs.astro.build/pt-br/core-concepts/project-structure/) para mais detalhes. - -## Arquivos e diretórios - -- `astro.config.mjs` — O arquivo de configuração do Astro; inclui a integração Starlight e configurações. -- `src/content/config.ts` — Arquivo de configuração de coleções de conteúdo; adiciona os esquemas de frontmatter do Starlight ao seu projeto. -- `src/content/docs/` — Arquivos de conteúdo. Starlight torna cada arquivo `.md`, `.mdx` ou `.mdoc` nesse diretório em uma página no seu site. -- `src/content/i18n/` (opcional) — Dados de tradução para dar suporte a [internacionalização](/pt-br/guides/i18n/). -- `src/` — Outros arquivos e código-fonte (componentes, estilos, imagens, etc.) para seu projeto. -- `public/` — Assets estáticos (fontes, favicon, PDFs, etc.) que não serão processados pelo Astro. - -## Conteúdos de um projeto de exemplo - -O diretório de um projeto Starlight pode se parecer com isso: - -import FileTree from '../../../../components/file-tree.astro'; - -<FileTree> - -- public/ - - favicon.svg -- src/ - - assets/ - - logo.svg - - capturadetela.jpg - - components/ - - BotaoCustomizado.astro - - WidgetInterativo.jsx - - content/ - - docs/ - - guias/ - - 01-introducao.md - - 02-avancado.md - - index.mdx - - config.ts - - env.d.ts -- astro.config.mjs -- package.json -- tsconfig.json - -</FileTree> diff --git a/docs/src/content/docs/pt-br/index.mdx b/docs/src/content/docs/pt-br/index.mdx index 0fbeb24b30c..275382f7544 100644 --- a/docs/src/content/docs/pt-br/index.mdx +++ b/docs/src/content/docs/pt-br/index.mdx @@ -1,40 +1,36 @@ --- title: Starlight 🌟 Construa sites de documentação com Astro +head: + - tag: title + content: Starlight 🌟 Construa sites de documentação com Astro description: Starlight te ajuda a construir belos e performáticos websites de documentação com Astro. template: splash -banner: - content: | - <span class="ph-banner"> - <span class="ph-houston"><img src="/ph-houston.svg" alt="" width="72" height="72"/></span> - <span class="ph-text"> - <strong>Bem-vindos Product Hunters 👋</strong> - <a href="https://www.producthunt.com/posts/starlight-by-astro">Estamos ao vivo agora!</a> - </span> - </span> +editUrl: false +lastUpdated: false hero: title: Faça sua documentação brilhar com Starlight tagline: Tudo o que você precisa para construir um site de documentação brilhante. Rápido, acessível e fácil de usar. image: - file: ../../../assets/hero-star.webp + file: ~/assets/hero-star.webp actions: - - text: Introdução + - text: Começar icon: right-arrow - variant: primary link: /pt-br/getting-started/ - text: Veja no GitHub icon: external + variant: minimal link: https://github.com/withastro/starlight --- import { CardGrid, Card } from '@astrojs/starlight/components'; -import AboutAstro from '../../../components/about-astro.astro'; +import AboutAstro from '~/components/about-astro.astro'; <CardGrid stagger> <Card title="Documentação de iluminar os olhos" icon="open-book"> Inclui: Navegação do site, pesquisa, internacionalização, SEO, tipografia fácil de ler, highlighting de código, modo escuro e mais. </Card> - <Card title="Possibilidado por Astro" icon="rocket"> + <Card title="Possibilitado por Astro" icon="rocket"> Aproveite todo o poder e performance do Astro. Estenda Starlight com suas integrações e bibliotecas favoritas do Astro. </Card> @@ -48,7 +44,7 @@ import AboutAstro from '../../../components/about-astro.astro'; </Card> </CardGrid> -<AboutAstro title="Trazido até você por"> +<AboutAstro title="Trazido a você por"> Astro é o framework web tudo-em-um projetado para velocidade. Traga seu conteúdo de qualquer lugar e faça deploy em todo lugar, tudo fornecido pelos seus componentes de UI e bibliotecas favoritas. diff --git a/docs/src/content/docs/pt-br/manual-setup.mdx b/docs/src/content/docs/pt-br/manual-setup.mdx deleted file mode 100644 index 9ff2deedb05..00000000000 --- a/docs/src/content/docs/pt-br/manual-setup.mdx +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: Instalação Manual -description: Aprenda como instalar Starlight manualmente e o adicionar a um projeto Astro existente. ---- - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -A forma mais rápida de criar um novo site Starlight é utilizando `create astro` como é mostrado no [guia Introdução](/pt-br/getting-started/#criando-um-novo-projeto). -Se você deseja adicionar Starlight a um projeto Astro existente, este guia irá te explicar como. - -## Instale Starlight - -Para seguir este guia, você vai precisar de um projeto Astro existente. - -### Adicione a integração Starlight - -Starlight é uma [integração Astro](https://docs.astro.build/pt-br/guides/integrations-guide/). Adicione-o ao seu site executando o comando `astro add` no diretório raiz do seu projeto: - -<Tabs> - <TabItem label="npm"> - ```sh - npx astro add starlight - ``` - - </TabItem> - <TabItem label="pnpm"> - ```sh - pnpm astro add starlight - ``` - </TabItem> - <TabItem label="Yarn"> - ```sh - yarn astro add starlight - ``` - </TabItem> - -</Tabs> - -Ele vai instalar as dependências necessárias e adicionar o Starlight no array `integrations` do seu arquivo de configuração do Astro. - -### Configure a integração - -A integração Starlight é configurada no seu arquivo `astro.config.mjs`. - -Adicione um `title` para começar: - -```js {7-9} -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'Meu brilhante site de documentação', - }), - ], -}); -``` - -Encontre todas as opções disponíveis na [referência de configuração do Starlight](/pt-br/reference/configuration/). - -### Configure coleções de conteúdo - -Starlight é construído com base nas [coleções de conteúdo](https://docs.astro.build/pt-br/guides/content-collections/) do Astro, que são configuradas no arquivo `src/content/config.ts`. - -Crie ou atualize o arquivo de configuração de conteúdo, adicionando uma coleção `docs` que usa o esquema `docsSchema` do Starlight: - -```js ins={3,6} -// src/content/config.ts -import { defineCollection } from 'astro:content'; -import { docsSchema } from '@astrojs/starlight/schema'; - -export const collections = { - docs: defineCollection({ schema: docsSchema() }), -}; -``` - -### Adicione conteúdo - -Starlight agora está configurado e chegou a hora de adicionar algum conteúdo! - -Crie um diretório `src/content/docs/` e comece por adicionar um arquivo `index.md`. -Essa será a página inicial do seu site: - -```md ---- -# src/content/docs/index.md -title: Minha documentação -description: Aprenda mais sobre meu projeto nesse site de documentação construído com Starlight. ---- - -Bem-vindo ao meu projeto! -``` - -Starlight usa roteamento baseado em arquivos, o que significa que todo arquivo Markdown, MDX ou Markdoc em `src/content/docs/` se tornará uma página no seu site. Metadados do frontmatter (os campos `title` e `description` no exemplo acima) podem mudar como cada página é mostrada. -Veja todas as opções disponíveis na [referência de frontmatter](/pt-br/reference/frontmatter/). - -## Dicas para sites existentes - -Se você tem um projeto Astro existente, você pode utilizar Starlight para rapidamente adicionar uma seção de documentação ao seu site. - -### Use Starlight como um subcaminho - -Para adicionar todas as páginas do Starlight em um subcaminho, coloque todo o conteúdo da sua documentação dentro de um subdiretório de `src/content/docs/`. - -Por exemplo, se todas as páginas do Starlight devem começar com `/guias/`, adicione seu conteúdo no diretório `src/content/docs/guias/`: - -import FileTree from '../../../components/file-tree.astro'; - -<FileTree> - -- src/ - - content/ - - docs/ - - **guias/** - - guia.md - - index.md - - pages/ -- astro.config.mjs - -</FileTree> - -No futuro, planejamos suportar esse caso de uso melhor para evitar a necessidade de um diretório aninhado adicional em `src/content/docs/`. - -### Use Starlight com SSR - -Atualmente, Starlight não suporta [deployments com SSR](https://docs.astro.build/pt-br/guides/server-side-rendering/) usando os adaptadores de servidor do Astro. Nós esperamos ser capazes de suportar isso em breve. diff --git a/docs/src/content/docs/pt-br/reference/configuration.md b/docs/src/content/docs/pt-br/reference/configuration.md deleted file mode 100644 index 3402b754fcf..00000000000 --- a/docs/src/content/docs/pt-br/reference/configuration.md +++ /dev/null @@ -1,426 +0,0 @@ ---- -title: Referência da Configuração -description: Uma visão geral de todas as opções de configuração que o Starlight suporta. ---- - -## Configure a integração `starlight` - -Starlight é uma integração construída acima do framework web [Astro](https://astro.build). Você pode configurar o seu projeto dentro do arquivo de configuração `astro.config.mjs`: - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'Minha documentação de iluminar os olhos', - }), - ], -}); -``` - -Você pode passar as seguintes opções para a integração `starlight`. - -### `title` (obrigatório) - -**tipo:** `string` - -Define o título do seu site. Será usado em metadados e no título da aba do navegador. - -### `description` - -**tipo:** `string` - -Define a descrição do seu website. Usado em metadados compartilhados com motores de busca na tag `<meta name="description">` se `description` não for definido no frontmatter de uma página. - -### `logo` - -**tipo:** [`LogoConfig`](#logoconfig) - -Define a imagem da logo a ser mostrada na barra de navegação ao lado ou no lugar do título da página. Você pode definir uma única propriedade `src` ou definir fontes de imagem separadas para os modos `light` e `dark`. - -```js -starlight({ - logo: { - src: './src/assets/minha-logo.svg', - }, -}); -``` - -#### `LogoConfig` - -```ts -type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( - | { src: string } - | { light: string; dark: string } -); -``` - -### `tableOfContents` - -**tipo:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` -**padrão:** `{ minHeadingLevel: 2; maxHeadingLevel: 3; }` - -Configura o índice mostrado a direita de cada página. Por padrão, cabeçalhos `<h2>` e `<h3>` serão incluídos no índice. - -### `editLink` - -**tipo:** `{ baseUrl: string }` - -Habilita links “Editar página” definindo a URL base que deve ser utilizada. O link final será `editLink.baseUrl` + o caminho da página atual. Por exemplo, para habilitar editar páginas no repositório `withastro/starlight` no GitHub: - -```js -starlight({ - editLink: { - baseUrl: 'https://github.com/withastro/starlight/edit/main/', - }, -}); -``` - -Com essa configuração, uma página `/introducao` teria um link de edição apontando para `https://github.com/withastro/starlight/edit/main/src/docs/introducao.md`. - -### `sidebar` - -**tipo:** [`SidebarItem[]`](#sidebaritem) - -Configura os itens de navegação da barra lateral do seu site. - -Uma barra lateral é um array de links e grupos de links. -Cada item deve ter um `label` e uma das seguintes propriedades: - -- `link` — um único link para uma URL específica, e.x. `'/inicio'` ou `'https://exemplo.com'`. - -- `items` — um array contendo mais links da barra lateral e subgrupos. - -- `autogenerate` — um objeto especificando um diretório da sua documentação para gerar automaticamente um grupo de links. - -```js -starlight({ - sidebar: [ - // Um único link rotulado como "Início”. - { label: 'Início', link: '/' }, - // Um grupo rotulado "Comece Aqui" contendo dois links. - { - label: 'Comece Aqui', - items: [ - { label: 'Introdução', link: '/intro' }, - { label: 'Próximos Passos', link: '/proximos-passos' }, - ], - }, - // Um grupo com links para todas as páginas no diretório referencia. - { - label: 'Referência', - autogenerate: { directory: 'referencia' }, - }, - ], -}); -``` - -#### Ordenação - -Grupos da barra lateral gerados automaticamente são ordenados pelo nome de arquivo alfabeticamente. -Por exemplo, uma página gerada de `astro.md` apareceria acima da página de `starlight.md`. - -#### Escondendo grupos - -Grupos de links são expandidos por padrão. Você pode modificar esse comportamento definindo a propriedade `collapsed` de um grupo para `true`. - -Subgrupos gerados automaticamente respeitam a propriedade `collapsed` de seu grupo pai por padrão. Defina a propriedade `autogenerate.collapsed` para sobrescrever isso. - -```js -sidebar: [ - // Um grupo escondido de links. - { - label: 'Links Escondidos', - collapsed: true, - items: [ - { label: 'Introdução', link: '/intro' }, - { label: 'Próximos Passos', link: '/proximos-passos' }, - ], - }, - // Um grupo expandido contendo subgrupos gerados automaticamente escondidos. - { - label: 'Referência', - autogenerate: { - directory: 'referencia', - collapsed: true, - }, - }, -], -``` - -#### Traduzindo rótulos - -Se o seu site é multilíngue, a `label` de cada item é considerada como estando no seu local padrão. Você pode definir uma propriedade `translations` para providenciar rótulos para suas outras línguas suportadas: - -```js -sidebar: [ - // um exemplo de barra lateral com rótulos traduzidos para o Francês. - { - label: 'Comece Aqui', - translations: { fr: 'Commencez ici' }, - items: [ - { - label: 'Introdução', - translations: { fr: 'Bien démarrer' }, - link: '/introducao', - }, - { - label: 'Estrutura de Projetos', - translations: { fr: 'Structure du projet' }, - link: '/estrutura', - }, - ], - }, -], -``` - -#### `SidebarItem` - -```ts -type SidebarItem = { - label: string; - translations?: Record<string, string>; -} & ( - | { - link: string; - badge?: string | BadgeConfig; - } - | { items: SidebarItem[]; collapsed?: boolean } - | { - autogenerate: { directory: string; collapsed?: boolean }; - collapsed?: boolean; - } -); -``` - -#### `BadgeConfig` - -```ts -interface BadgeConfig { - text: string; - variant: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; -} -``` - -### `locales` - -**tipo:** <code>{ \[dir: string\]: [LocaleConfig](#localeconfig) }</code> - -[Configure internacionalização (i18n)](/pt-br/guides/i18n/) para o seu site definindo quais `locales` são suportados. - -Cada entrada deve usar o diretório onde os arquivos daquela língua estão salvos como a chave. - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'Meu Site', - // Define Inglês como a língua padrão para esse site. - defaultLocale: 'en', - locales: { - // Documentação em Inglês em `src/content/docs/en/` - en: { - label: 'English', - }, - // Documentação em Chinês Simplificado em `src/content/docs/zh/` - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - // Documentação em Árabe em `src/content/docs/ar/` - ar: { - label: 'العربية', - dir: 'rtl', - }, - }, - }), - ], -}); -``` - -#### `LocaleConfig` - -```ts -interface LocaleConfig { - label: string; - lang?: string; - dir?: 'ltr' | 'rtl'; -} -``` - -Você pode definir as seguintes opções para cada local: - -##### `label` (obrigatório) - -**tipo:** `string` - -O rótulo para essa língua para mostrar aos usuários, por exemplo no seletor de língua. Geralmente você vai querer que isso seja o nome da língua da forma com que um usuário da língua esperaria lê-lo, e.x. `"English"`, `"العربية"` ou `"简体中文"`. - -##### `lang` - -**tipo:** `string` - -A tag BCP-47 para essa língua, e.x. `"en"`, `"ar"` ou `"zh-CN"`. Se não definido, o diretório da língua será usado por padrão. Tags de línguas com subtags regionais (e.x. `"pt-BR"` ou `"en-US"`) irão utilizar as traduções de UI integradas de sua língua base se nenhuma tradução específica da região for encontrada. - -##### `dir` - -**tipo:** `'ltr' | 'rtl'` - -A direção de escrita dessa língua; `"ltr"` para esquerda-para-direita (o padrão) ou `"rtl"` para direita-para-esquerda. - -#### Local raiz - -Você pode definir a língua padrão sem um diretório `/lingua/` definindo um local `root`: - -```js -starlight({ - locales: { - root: { - label: 'English', - lang: 'en', - }, - fr: { - label: 'Français', - }, - }, -}); -``` - -Por exemplo, isso te permite servir `/getting-started/` como uma rota em Inglês e utiliazr `/fr/getting-started/` como a página equivalente em Francês. - -### `defaultLocale` - -**tipo:** `string` - -Define a língua que é padrão para esse site. -O valor deve corresponder uma das chaves do seu objeto [`locales`](#locales). -(Se sua língua padrão é seu [local raiz](#local-raiz), você pode pular isso.) - -O local padrãoserá utilizado para providenciar conteúdo de fallback onde está se faltando traduções. - -### `social` - -**tipo:** `Partial<Record<'bitbucket' | 'codeberg' | 'codePen' | 'discord' | 'github' | 'gitlab' | 'gitter' | 'instagram' | 'linkedin' | 'mastodon' | 'microsoftTeams' | 'stackOverflow' | 'threads' | 'twitch' | 'twitter' | 'youtube', string>>` - -Detalhes opcionais sobre as contas de redes sociais para esse site. Adicionar qualquer um desses irá os mostrar como links de ícone no cabeçalho do site. - -```js -starlight({ - social: { - codeberg: 'https://codeberg.org/knut/examples', - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - gitlab: 'https://gitlab.com/delucis', - linkedin: 'https://www.linkedin.com/company/astroinc', - mastodon: 'https://m.webtoo.ls/@astro', - threads: 'https://www.threads.net/@nmoodev', - twitch: 'https://www.twitch.tv/bholmesdev', - twitter: 'https://twitter.com/astrodotbuild', - youtube: 'https://youtube.com/@astrodotbuild', - }, -}); -``` - -### `customCss` - -**tipo:** `string[]` - -Fornece arquivos CSS para customizar a aparência e sensação do seu site Starlight. - -Suporta arquivos CSS locais relativos a raiz do seu projeto, e.x. `'./src/customizado.css'` e CSS que você instalou como um módulo do npm, e.x. `'@fontsource/roboto'`. - -```js -starlight({ - customCss: ['./src/estilos-customizados.css', '@fontsource/roboto'], -}); -``` - -### `head` - -**tipo:** [`HeadConfig[]`](#headconfig) - -Adiciona tags customizadas ao `<head>` do seu site Starlight. -Pode ser útil para adicionar rastreamento de analytics e outros scripts e recursos de terceiros. - -```js -starlight({ - head: [ - // Exemplo: adiciona a tag de script de analytics do Fathom. - { - tag: 'script', - attrs: { - src: 'https://cdn.usefathom.com/script.js', - 'data-site': 'MEU-ID-FATHOM', - defer: true, - }, - }, - ], -}); -``` - -#### `HeadConfig` - -```ts -interface HeadConfig { - tag: string; - attrs?: Record<string, string | boolean | undefined>; - content?: string; -} -``` - -### `lastUpdated` - -**tipo:** `boolean` -**padrão:** `false` - -Controla se o rodapé mostra quando a página foi atualizada pela última vez. - -Por padrão, essa funcionalidade depende no histórico do Git do seu repositório e pode não ser preciso em algumas plataformas de deployment utilizando [shallow clones](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt). Uma página pode sobrescrever essa opção ou a data baseada no Git utilizando o [campo frontmatter `lastUpdated`](/pt-br/reference/frontmatter/#lastupdated). - -### `pagination` - -**tipo:** `boolean` -**padrão:** `true` - -Define se o rodapé deve incluir links para a próxima página e a anterior. - -Uma página pode sobrescrever essa opção ou o texto do link e/ou a URL usando os campos do frontmatter [`prev`](/pt-br/reference/frontmatter/#prev) e [`next`](/pt-br/reference/frontmatter/#next). - -### `favicon` - -**tipo:** `string` -**padrão:** `'/favicon.svg'` - -Define o caminho do favicon padrão para seu website que deve estar localizado no diretório `public/` e ser um arquivo de ícone válido (`.ico`, `.gif`, `.jpg`, `.png` ou `.svg`). - -```js -starlight({ - favicon: '/imagens/favicon.svg', -}), -``` - -Se você precisa definir variantes adicionais ou favicons de fallback, você pode adicionar tags utilizando a [opção `head`](#head): - -```js -starlight({ - favicon: '/imagens/favicon.svg'. - head: [ - // Adiciona um favicon ICO de fallback para o Safari. - { - tag: 'link', - attrs: { - rel: 'icon', - href:'/imagens/favicon.ico', - sizes: '32x32', - }, - }, - ], -}); -``` diff --git a/docs/src/content/docs/pt-br/reference/frontmatter.md b/docs/src/content/docs/pt-br/reference/frontmatter.md deleted file mode 100644 index c03c527bf88..00000000000 --- a/docs/src/content/docs/pt-br/reference/frontmatter.md +++ /dev/null @@ -1,287 +0,0 @@ ---- -title: Referência do Frontmatter -description: Uma visão geral dos campos padrões do frontmatter que o Starlight suporta. ---- - -Você pode customizar páginas Markdown e MDX no Starlight definindo valores em seu frontmatter. Por exemplo, uma página comum pode definir os campos `title` e `description`: - -```md ---- -title: Sobre este projeto -description: Aprenda mais sobre o projeto no qual estou trabalhando. ---- - -Bem-vindo a página "sobre"! -``` - -## Campos do Frontmatter - -### `title` (obrigatório) - -**tipo:** `string` - -Você deve providenciar um título para cada página. Ele será mostrado no topo da página, em abas do navegador e nos metadados da página. - -### `description` - -**tipo:** `string` - -A descrição da página é utilizada para metadados da página e será utilizada por motores de busca e em pré-visualizações em redes sociais. - -### `editUrl` - -**tipo:** `string | boolean` - -Sobreescreve a [configuração global `editLink`](/pt-br/reference/configuration/#editlink). Defina como `false` para desabilitar o link “Editar página" para uma página específica ou providencie uma URL alternativa onde o conteúdo dessa página é editável. - -### `head` - -**tipo:** [`HeadConfig[]`](/pt-br/reference/configuration/#headconfig) - -Você pode adicionar tags adicionais para ao `<head>` da sua página utilizando o campo frontmatter `head`. Isso significa que você pode adicionar estilos customizados, metadados ou outras tags a uma única página. Similar a [opção global `head`](/pt-br/reference/configuration/#head). - -```md ---- -title: Sobre nós -head: - # Utilize uma tag <title> customizada - - tag: title - content: Título sobre customizado ---- -``` - -### `tableOfContents` - -**tipo:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` - -Sobrescreve a [configuração global `tableOfContents`](/pt-br/reference/configuration/#tableofcontents). -Customize os níveis de cabeçalho a serem incluídos ou defina como `false` para esconder o índice nessa página. - -```md ---- -title: Página com apenas H2s no índice -tableOfContents: - minHeadingLevel: 2 - maxHeadingLevel: 2 ---- -``` - -```md ---- -title: Página sem índice -tableOfContents: false ---- -``` - -### `template` - -**tipo:** `'doc' | 'splash'` -**padrão:** `'doc'` - -Define o layout de template para essa página. -Páginas usam o layout `'doc'` por padrão. -Defina para `'splash'` para usar o layout mais largo sem nenhuma barra lateral, projetado para páginas iniciais. - -### `hero` - -**tipo:** [`HeroConfig`](#heroconfig) - -Adiciona um componente hero ao topo dessa página. Funciona bem com `template: splash`. - -Por exemplo, essa configuração mostra algumas opções comuns, incluindo carregamento de uma imagem do seu repositório. - -```md ---- -title: Minha Página Inicial -template: splash -hero: - title: 'Meu Projeto: Coisas Estelares Cedo' - tagline: Leve suas coisas ao espaço e de volta em um piscar de olhos. - image: - alt: Uma logo reluzente e brilhantemente colorida - file: ../../assets/logo.png - actions: - - text: Me diga mais - link: /getting-started/ - icon: right-arrow - variant: primary - - text: Veja no GitHub - link: https://github.com/astronaut/meu-projeto - icon: external ---- -``` - -#### `HeroConfig` - -```ts -interface HeroConfig { - title?: string; - tagline?: string; - image?: { - alt?: string; - // Caminho relativo a uma imagem no seu repositório. - file?: string; - // HTML bruto para utilizar no slot de imagem. - // Pode ser uma tag `<img>` customizada ou um `<svg>` inline. - html?: string; - }; - actions?: Array<{ - text: string; - link: string; - variant: 'primary' | 'secondary' | 'minimal'; - icon: string; - }>; -} -``` - -### `banner` - -**tipo:** `{ content: string }` - -Exibe um banner de anúncio no topo desta página. - -O valor de `conteúdo` pode incluir HTML para links ou outro conteúdo. -Por exemplo, esta página exibe um banner que inclui um link para `example.com`. - -```md ---- -title: Página com um banner -banner: - content: | - Acabamos de lançar algo legal! - <a href="https://example.com">Confira</a> ---- -``` - -### `lastUpdated` - -**tipo:** `Date | boolean` - -Sobrescreve a [opção global `lastUpdated`](/pt-br/reference/configuration/#lastupdated). Se uma data é especificada, ela deve ser um [timestamp YAML](https://yaml.org/type/timestamp.html) válido e irá sobrescrever a data armazenada no histórico do Git para essa página. - -```md ---- -title: Página com uma data de última atualização customizada -lastUpdated: 2022-08-09 ---- -``` - -### `prev` - -**tipo:** `boolean | string | { link?: string; label?: string }` - -Sobrescreve a [opção global `pagination`](/pt-br/reference/configuration/#pagination). Se uma string é especificada, o texto do link gerado será substituído e se um objeto for especificado, ambos o link e o texto serão sobrescritos. - -```md ---- -# Esconda o link da página anterior -prev: false ---- -``` - -```md ---- -# Sobrescreva o texto do link da página anterior -prev: Continue o tutorial ---- -``` - -```md ---- -# Sobrescreva ambos o link e o texto da página anterior -prev: - link: /pagina-diferente/ - label: Veja essa outra página ---- -``` - -### `next` - -**tipo:** `boolean | string | { link?: string; label?: string }` - -Mesmo que [`prev`](#prev) mas para o link da próxima página. - -```md ---- -# Esconda o link da próxima página -next: false ---- -``` - -### `sidebar` - -**tipo:** `{ label?: string; order?: number; hidden?: boolean; badge?: string | BadgeConfig }` - -Controla como essa página é mostrada na [barra lateral](/pt-br/reference/configuration/#sidebar), quando se utiliza um grupo de links gerados automaticamente. - -#### `label` - -**tipo:** `string` -**padrão:** [`title`](#title-obrigatório) da página - -Define o rótulo para essa página na barra lateral quando mostrado em um grupo de links gerados automaticamente. - -```md ---- -title: Sobre este projeto -sidebar: - label: Sobre ---- -``` - -#### `order` - -**tipo:** `number` - -Controla a ordem dessa página ao ordenar um grupo de links gerados automaticamente. -Números menores são mostrados acima no grupo de links. - -```md ---- -title: Página para mostrar primeiro -sidebar: - order: 1 ---- -``` - -#### `hidden` - -**tipo:** `boolean` -**padrão:** `false` - -Previne essa página de ser incluída no no grupo gerado automaticamente da barra lateral. - -```md ---- -title: Página para esconder da barra lateral gerada automaticamente -sidebar: - hidden: true ---- -``` - -#### `badge` - -**type:** <code>string | <a href="/pt-br/reference/configuration/#badgeconfig">BadgeConfig</a></code> - -Adicione um emblema a página na barra lateral ao ser mostrada em um grupo gerado automaticamente de links. -Ao utilizar uma string, o emblema será mostrado com uma cor de destaque padrão. -Opcionalmente, passe um [objeto `BadgeConfig`](/pt-br/reference/configuration/#badgeconfig) com os campos `text` e `variant` para customizar o emblema. - -```md ---- -title: Página com um emblema -sidebar: - # Utiliza a variante padrão correspondente a cor de destaque do seu site - badge: New ---- -``` - -```md ---- -title: Página com um emblema -sidebar: - badge: - text: Experimental - variant: caution ---- -``` diff --git a/docs/src/content/docs/pt-br/resources/community-content.mdx b/docs/src/content/docs/pt-br/resources/community-content.mdx new file mode 100644 index 00000000000..780354917b3 --- /dev/null +++ b/docs/src/content/docs/pt-br/resources/community-content.mdx @@ -0,0 +1,131 @@ +--- +title: Conteúdo da Comunidade +description: Descubra guias produzidos pela comunidade, artigos e vídeos para ajudar a aprender e construir com Starlight! +--- + +:::tip[Adicione o seu!] +Você já produziu conteúdo sobre Starlight? +Abra um PR adicionando um link para esta página! +::: + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +## Artigos e Avaliações + +Aqui há uma coletânea de posts e artigos para aprender mais sobre Starlight e sobre a experiência de outras pessoas: + +<CardGrid> + <LinkCard + href="https://devm.io/open-source/starlight-astro" + title="Geração de Site Estático com Starlight" + description="Nenhuma ideia é tão grande ou pequena ao projetar componentes” — uma entrevista com Chris Swithinbank, Líder Starlight" + /> + <LinkCard + href="https://frontendatscale.com/blog/hybrid-frontend-architecture/" + title="Arquitetura Frontend Híbrida com Astro e Starlight" + description="Maxi Ferreira e Ben Holmes constroem um site de documentação com Starlight, TinaCMS, e um Playground de API interativo com autenticação." + /> + <LinkCard + href="https://www.olets.dev/posts/comparing-docs-site-builders-vuepress-vs-starlight/" + title="Comparando construtores de site de documentação: VuePress vs Starlight" + description="Como esses dois frameworks se correspondem?" + /> +</CardGrid> + +## Receitas e Guias + +Receitas são tipicamente guias passo a passo, curtos e focados, que levam o leitor a completar um exemplo funcional de uma tarefa específica. Receitas são uma ótima maneira de adicionar novas funcionalidades ou comportamentos para seu projeto Starlight ao seguir receitas passo a passo! Outros guias podem explicar conceitos relacionados a determinada área de conteúdo, como usar imagens ou trabalhar com MDX. + +Explore conteúdo produzido pela comunidade mantido por usuários Starlight: + +<CardGrid> + <LinkCard + href="https://www.webpro.nl/scraps/versioned-docs-with-starlight-and-vercel" + title="Documentação versionada com Starlight e Vercel" + description="Um guia para implementar versões separadas da documentação para cada versão principal de um projeto" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-heading-links" + title="Adicione links em cabeçalhos Starlight" + description="Um guia sobre como usar um plugin rehype para criar links para seções específicas de sua documentação" + /> + <LinkCard + href="https://blog.otterlord.dev/posts/starlight-sponsors/" + title="Adicione patrocinadores para seu site Starlight" + description="Um guia sobre implementar um componente de patrocinadores personalizado na barra lateral de sua documentação" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images" + title="Adicione imagens Open Graph a Starlight" + description="Um guia para gerar imagens sociais e as metatags correspondentes para as suas páginas" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-third-party-icon-sets" + title="Use ícones de terceiros em Starlight" + description="Um guia sobre como usar unplugin-icons para expandir a seleção de ícones disponíveis para Starlight" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-html-head" + title="Edite o elemento HTML head de páginas Starlight" + description="Aprenda sobre como adicionar conteúdo como fontes, scripts e web analytics" + /> + <LinkCard + href="https://dev.to/mrrobot/publishing-documentation-with-astro-starlight-691" + title="Publicando documentação com Astro Starlight" + description="Começando com a documentação Starlight" + /> + <LinkCard + href="https://events-3bg.pages.dev/jotter/starlight/guide/" + title="Habilite Transições de Visualização" + description="Tenha aquela aparência e experiência de uma SPA com o suporte a transições de visualização da Mochila de Truques" + /> +</CardGrid> + +## Conteúdo em Vídeo + +Descubra vídeos e canais com conteúdo Starlight, incluindo _lives_ e conteúdo educacional. + +import YouTubeGrid from '~/components/youtube-grid.astro'; + +### Astro Videos + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=5u0Ds7wzUeI', + title: 'Starlight por Astro', + description: 'Assista ao vídeo oficial do lançamento Starlight', + }, + { + href: 'https://www.youtube.com/shorts/zjOWezSzd18', + title: '🌟 SUB 1 MINUTE RUN', + description: + 'Assista Ben lançar um novo site Starlight em menos de um minuto!', + }, + ]} +/> + +### Vídeos da Comunidade e Streams + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=sF6UcV3moZg', + title: 'Construindo documentação com Starlight e Astro', + description: + 'Assista Chris e Alex mergulhando no código do Starlight com CodingCat.dev', + }, + { + href: 'https://www.youtube.com/watch?v=sWkkHbwDeQc', + title: 'Astro Starlight', + description: 'Introdução ao Starlight em menos de um minuto.', + }, + { + href: 'https://www.youtube.com/watch?v=-Ki-1E5gNCk', + title: + 'Modelo de Documentação Astro Starlight (construa documentações personalizadas!)', + description: + 'Tenha um novo site Starlight em funcionamento em cerca de 5 minutos', + }, + ]} +/> diff --git a/docs/src/content/docs/pt-br/resources/plugins.mdx b/docs/src/content/docs/pt-br/resources/plugins.mdx new file mode 100644 index 00000000000..16d027c2c42 --- /dev/null +++ b/docs/src/content/docs/pt-br/resources/plugins.mdx @@ -0,0 +1,125 @@ +--- +title: Plugins e Integrações +description: Descubra ferramentas da comunidade e integrações que estendem Starlight! +sidebar: + order: 1 +--- + +:::tip[Adicione o seu!] +Você construiu um plugin ou uma ferramenta para Starlight? +Abra um PR adicionando um link para esta página! +::: + +## Plugins + +[Plugins](/pt-br/reference/plugins/) podem personalizar a configuração Starlight, a interface do usuário e o comportamento, enquanto também são fáceis de compartilhar e de reutilizar. +Estenda o seu site com os plugins oficiais suportados pelo time Starlight e plugins da comunidade mantidos por usuários Starlight. + +### Plugins oficiais + +<CardGrid> + <LinkCard + href="/pt-br/guides/site-search/#algolia-docsearch" + title="Algolia DocSearch" + description="Substitua Pagefind, o provedor de busca padrão, com Algolia DocSearch." + /> +</CardGrid> + +### Plugins da comunidade + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-links-validator" + title="starlight-links-validator" + description="Verifique links quebrados em suas páginas Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-typedoc" + title="starlight-typedoc" + description="Gere páginas Starlight a partir de TypeScript utilizando TypeDoc." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-blog" + title="starlight-blog" + description="Adicione um blog ao seu site de documentação." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-openapi" + title="starlight-openapi" + description="Crie páginas de documentação a partir de especificações OpenAPI/Swagger." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-obsidian" + title="starlight-obsidian" + description="Publique vaults Obsidian em seu site Starlight." + /> + <LinkCard + href="https://astro-ghostcms.xyz/intro/starlight/install/" + title="starlight-ghostcms" + description="Adicione suas postagens do blog GhostCMS ao lado de suas páginas Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-image-zoom" + title="starlight-image-zoom" + description="Adicione recursos de zoom as imagens da sua documentação." + /> + <LinkCard + href="https://github.com/lorenzolewis/starlight-utils" + title="starlight-utils" + description="Estenda Starlight com uma coleção de utilitários comuns." + /> + <LinkCard + href="https://github.com/trueberryless/starlight-view-modes" + title="starlight-view-modes" + description="Adicione diferentes recursos de modo de exibição ao seu site de documentação." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-versions" + title="starlight-versions" + description="Versione suas páginas de documentação Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-theme-rapide" + title="starlight-theme-rapide" + description="Tema Starlight inspirado pelo tema Visual Studio Code Vitesse." + /> +</CardGrid> + +## Ferramentas da comunidade e integrações + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +Essas ferramentas da comunidade e integrações podem ser usadas para adicionar funcionalidades para o seu site Starlight. + +<CardGrid> + <LinkCard + href="https://www.feelback.dev/blog/new-astro-starlight-integration/" + title="FeelBack" + description="Adicione um sistema de feedback de usuário para as páginas da sua documentação." + /> + <LinkCard + href="https://github.com/val-town/notion-to-astro" + title="notion-to-astro" + description="Converta exportações do Notion para documentação Asto Starlight" + /> + <LinkCard + href="https://github.com/mattjennings/astro-live-code" + title="astro-live-code" + description="Apresente seus blocos de código MDX como componentes interativos" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-i18n" + title="starlight-i18n" + description="Extensão para Visual Studio Code para ajudar a traduzir páginas Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-package-managers" + title="starlight-package-managers" + description="Exiba rapidamente comandos relacionados ao npm para vários gerenciadores de pacotes." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-showcases" + title="starlight-showcases" + description="Conjunto de componentes Starlight para criar páginas de exibição." + /> +</CardGrid> diff --git a/docs/src/content/docs/pt-br/resources/showcase.mdx b/docs/src/content/docs/pt-br/resources/showcase.mdx new file mode 100644 index 00000000000..5a6c3b103db --- /dev/null +++ b/docs/src/content/docs/pt-br/resources/showcase.mdx @@ -0,0 +1,21 @@ +--- +title: Vitrine Starlight +description: Descubra sites construídos com Starlight! +sidebar: + label: Vitrine de Sites +--- + +:::tip[Adicione o seu!] +Você construiu um site com Starlight? +[Abra um PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#showcase) adicionando um link para esta página! +::: + +## Sites + +import ShowcaseSites from '~/components/showcase-sites.astro'; + +Starlight já está sendo usado em produção. Esses são alguns sites que estão pela web: + +<ShowcaseSites /> + +Veja todos os [repositórios de projetos públicos usando Starlight no GitHub](https://github.com/withastro/starlight/network/dependents). diff --git a/docs/src/content/docs/pt-br/showcase.mdx b/docs/src/content/docs/pt-br/showcase.mdx deleted file mode 100644 index abb8b6c1c82..00000000000 --- a/docs/src/content/docs/pt-br/showcase.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Showcase do Starlight -description: Descubra sites construídos com Starlight e ferramentas da comunidade que estendem o Starlight! ---- - -:::tip[Adicione o seu próprio!] -Você construiu um site Starlight ou uma ferramenta para o Starlight? -Abra um PR adicionando um link a esta página! -::: - -## Sites - -import ShowcaseSites from '../../../components/showcase-sites.astro'; - -Starlight já está sendo utilizado em produção. Esses são alguns dos sites através da web: - -<ShowcaseSites /> - -Veja todos os [repositórios de projetos públicos utilizando Starlight no GitHub](https://github.com/withastro/starlight/network/dependents). - -## Plugins da comunidade - -import { CardGrid, LinkCard } from '@astrojs/starlight/components'; - -Essas ferramentas, plugins e integrações da comunidade funcionam ao lado do Starlight para estender sua funcionalidade. - -<CardGrid> - <LinkCard - href="https://www.feelback.dev/blog/new-astro-starlight-integration/" - title="FeelBack" - description="Adicione um sistema de feedback do usuário ao seu site." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-blog" - title="starlight-blog" - description="Adicione um blog ao seu site de documentação." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-links-validator" - title="starlight-links-validator" - description="Verifique se há links quebrados em suas páginas Starlight." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-typedoc" - title="starlight-typedoc" - description="Gere páginas do Starlight a partir do TypeScript utilizando TypeDoc." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-openapi" - title="starlight-openapi" - description="Crie páginas de documentação a partir de especificações OpenAPI/Swagger." - /> -</CardGrid> diff --git a/docs/src/content/docs/pt-pt/404.md b/docs/src/content/docs/pt-pt/404.md new file mode 100644 index 00000000000..0dc144583ce --- /dev/null +++ b/docs/src/content/docs/pt-pt/404.md @@ -0,0 +1,14 @@ +--- +title: Não encontrado +template: splash +editUrl: false +lastUpdated: false +hero: + title: '404' + tagline: <strong>Houston, temos um problema.</strong> Não conseguimos encontrar esta página.<br>Verifique se o URL está correto ou tente utilizar a barra de pesquisa. + actions: + - text: Ir para o início + icon: right-arrow + link: /pt-pt/ + variant: primary +--- diff --git a/docs/src/content/docs/pt-pt/environmental-impact.md b/docs/src/content/docs/pt-pt/environmental-impact.md new file mode 100644 index 00000000000..576e9057d28 --- /dev/null +++ b/docs/src/content/docs/pt-pt/environmental-impact.md @@ -0,0 +1,142 @@ +--- +title: Documentação ecológica +description: Aprenda como o Starlight te pode ajudar a construir sites de documentação mais ecológicos e reduzir a pegada de carbono. +--- + +As estimativas para o impacto climático da indústria web variam entre [2%][sf] e [4% das emissões globais de carbono][bbc], aproximadamente o equivalente às emissões da indústria aeronáutica. +Há vários fatores complexos no cálculo do impacto ecológico de um website, mas este guia inclui algumas dicas para reduzir a pegada ambiental do seu site de documentação. + +A boa noticía é que, escolher o Starlight já é um bom começo! +De acordo com o "Website Carbon Calculator", este site é [mais limpo do que 99% das páginas web testadas][sl-carbon], produzindo 0.01g de CO₂ por cada visita à página. + +## Peso da página + +Quanto mais dados uma página web transfere mais recursos energéticos são necessários. +De acordo com [dados do HTTP Archive][http], em Abril de 2023, uma página web mediana necessitava que o utilizador baixasse mais de 2,000 KB. + +O Starlight constrói páginas que são o mais leve possível. +Por exemplo, na primeira visita, um utilizador vai descarregar menos do que 50 KB de dados comprimidos, ou seja, apenas 2.5% da mediana indicada pelo HTTP Archive. +Com uma boa estratégia de _cache_, as navegações subsequentes podem descarregar tão pouco quanto 10 KB. + +### Imagens + +Enquanto o Starlight providencia uma boa base, as imagens que você adicionar à sua documentação podem aumentar o peso da sua página rapidamente. +O Starlight usa o [suporte a assets otimizados][assets] do Astro para otimizar imagens locais nos seus arquivos Markdown e MDX. + +### Componentes de UI + +Os componentes construídos com frameworks de UI como React ou Vue podem facilmente adicionar grandes quantidades de JavaScript a uma página. +Porque o Starlight é construído com o Astro, e graças às [Ilhas Astro][islands], esses componentes carregam, **por padrão, zero código JavaScript no lado do cliente**. + +### _Cache_ + +A _Cache_ é usada para controlar por quanto tempo um navegador armazena e reutiliza os dados já descarregados. +Uma boa estratégia de _caching_ garante que um utilizador receba o conteúdo novo o mais cedo possível assim que ele muda, mas também evita descarregar inutil e repetidamente o mesmo conteúdo sem que ele mude. + +A forma mais comum de configurar a _cache_ é com o [header HTTP `Cache-Control`][cache]. +Ao utilizar o Starlight, você pode definir um grande tempo de cache para todo o conteúdo do diretório `/_astro/`. +Este diretório contém CSS, JavaScript e outros artefactos em _bundle_ que podem ser seguramente _cached_ para sempre, reduzindo assim downloads desnecessários: + +``` +Cache-Control: public, max-age=604800, immutable +``` + +A forma de configurar a _cache_ depende do seu alojamento web. Por exemplo, o Vercel aplica por você esta estratégia de _cache_ sem necessidade de configuração adicional, já a definição de [cabeçalhos customizados para Netlify][ntl-headers] necessita que adicione um arquivo `public/_headers` ao seu projeto: + +``` +/_astro/* + Cache-Control: public + Cache-Control: max-age=604800 + Cache-Control: immutable +``` + +[cache]: https://csswizardry.com/2019/03/cache-control-for-civilians/ +[ntl-headers]: https://docs.netlify.com/routing/headers/ + +## Consumo de energia + +A forma com que uma página web é construída pode ter impacto na energia necessária para executá-la no dispositivo de um utilizador. +Por utilizar JavaScript ao mínimo, o Starlight reduz a quantidade de energia de processamento que o celular, tablet ou computador de um utilizador precisa para carregar e renderizar páginas. + +Tenha atenção ao adicionar funcionalidades como scripts de rastreamento de _Analytics_ ou conteúdo cheio de JavaScript como embeds de vídeo já que estes podem aumentar o consumo de energia da página. +Se você precisa de _Analytics_, considere escolher uma opção leve como [Cabin][cabin], [Fathom][fathom] ou [Plausible][plausible]. +Embeds como vídeos do YouTube e Vimeo podem ser melhorados se [carregar o vídeo mediante a interação do usuário][lazy-video]. +Pacotes como o [`astro-embed`][embed] podem ajudá-lo com alguns dos serviços comuns. + +:::tip[Sabia que?] +Fazer parse e compilação de JavaScript é uma das tarefas mais caras que os navegadores tem que fazer. +Comparado com a renderização de uma imagem JPEG de mesmo tamanho, [o JavaScript pode levar mais do que 30 vezes o tempo para processar][cost-of-js]. +::: + +[cabin]: https://withcabin.com/ +[fathom]: https://usefathom.com/ +[plausible]: https://plausible.io/ +[lazy-video]: https://web.dev/iframe-lazy-loading/ +[embed]: https://www.npmjs.com/package/astro-embed +[cost-of-js]: https://medium.com/dev-channel/the-cost-of-javascript-84009f51e99e + +## Alojamento + +O lugar onde uma página web é alojada pode ter um grande impacto no quão amigável ao ambiente o seu site de documentação é. +Os centros de dados e de servidores podem ter um grande impacto ecológico, incluindo alto consumo de eletricidade e uso intensivo de água. + +Escolher um alojamento que utiliza energia renovável significará menos emissões de carbono para o seu site. A [Green Web Directory][gwb] é uma ferramenta que poderá ajudá-lo a encontrar empresas de alojamento. + +[gwb]: https://www.thegreenwebfoundation.org/directory/ + +## Comparações + +Está curioso para comparar com os outros frameworks de documentação? +Estes testes realizados com o [Website Carbon Calculator][wcc] comparam páginas semelhantes construídas com diferentes ferramentas. + +| Framework | CO₂ per page visit | Rating | +| --------------------------- | ------------------ | :----: | +| [Starlight][sl-carbon] | 0.01g | A+ | +| [Read the Docs][rtd-carbon] | 0.05g | A+ | +| [Sphinx][sx-carbon] | 0.06g | A+ | +| [VitePress][vp-carbon] | 0.07g | A+ | +| [Docus][dc-carbon] | 0.09g | A+ | +| [docsify][dy-carbon] | 0.10g | A | +| [Nextra][nx-carbon] | 0.11g | A | +| [MkDocs][mk-carbon] | 0.19g | B | +| [Docusaurus][ds-carbon] | 0.21g | B | +| [GitBook][gb-carbon] | 0.43g | C | +| [Mintlify][mt-carbon] | 1.22g | F | + +<small>Dados recolhidos a 22 de Julho de 2024. Clique num dos links para ver os valores atualizados.</small> + +[sl-carbon]: https://www.websitecarbon.com/website/starlight-astro-build-getting-started/ +[vp-carbon]: https://www.websitecarbon.com/website/vitepress-dev-guide-what-is-vitepress/ +[dc-carbon]: https://www.websitecarbon.com/website/docus-dev-introduction-getting-started/ +[sx-carbon]: https://www.websitecarbon.com/website/sphinx-doc-org-en-master-usage-quickstart-html/ +[mk-carbon]: https://www.websitecarbon.com/website/mkdocs-org-getting-started/ +[nx-carbon]: https://www.websitecarbon.com/website/nextra-site-docs-docs-theme-start/ +[dy-carbon]: https://www.websitecarbon.com/website/docsify-js-org/ +[ds-carbon]: https://www.websitecarbon.com/website/docusaurus-io-docs/ +[rtd-carbon]: https://www.websitecarbon.com/website/docs-readthedocs-io-en-stable-index-html/ +[gb-carbon]: https://www.websitecarbon.com/website/docs-gitbook-com/ +[mt-carbon]: https://www.websitecarbon.com/website/mintlify-com-docs-quickstart/ + +## Mais recursos + +### Ferramentas + +- [Website Carbon Calculator][wcc] +- [GreenFrame](https://greenframe.io/) +- [Ecograder](https://ecograder.com/) +- [WebPageTest Carbon Control](https://www.webpagetest.org/carbon-control/) +- [Ecoping](https://ecoping.earth/) + +### Artigos e palestras + +- [“Building a greener web”](https://youtu.be/EfPoOt7T5lg), palestra por Michelle Barker +- [“Sustainable Web Development Strategies Within An Organization”](https://www.smashingmagazine.com/2022/10/sustainable-web-development-strategies-organization/), artigo por Michelle Barker +- [“A sustainable web for everyone”](https://2021.stateofthebrowser.com/speakers/tom-greenwood/), palestra por Tom Greenwood +- [“How Web Content Can Affect Power Usage”](https://webkit.org/blog/8970/how-web-content-can-affect-power-usage/), artigo por Benjamin Poulain e Simon Fraser + +[sf]: https://www.sciencefocus.com/science/what-is-the-carbon-footprint-of-the-internet/ +[bbc]: https://www.bbc.com/future/article/20200305-why-your-internet-habits-are-not-as-clean-as-you-think +[http]: https://httparchive.org/reports/state-of-the-web +[assets]: https://docs.astro.build/en/guides/images/ +[islands]: https://docs.astro.build/pt-pt/concepts/islands/ +[wcc]: https://www.websitecarbon.com/ diff --git a/docs/src/content/docs/pt-pt/getting-started.mdx b/docs/src/content/docs/pt-pt/getting-started.mdx new file mode 100644 index 00000000000..557cda2ee73 --- /dev/null +++ b/docs/src/content/docs/pt-pt/getting-started.mdx @@ -0,0 +1,140 @@ +--- +title: Introdução +description: Aprenda como começar a construir o seu próximo site de documentação com Starlight pelo Astro. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +O Starlight é um tema de documentação cheio de funcionalidades construído em cima do framework [Astro](https://astro.build). +Este guia irá ajudá-lo a começar um novo projeto. +Consulte as [instruções de instalação manual](/pt-pt/manual-setup/) para adicionar o Starlight a um projeto Astro já existente. + +## Início Rápido + +### Crie um novo projeto + +Crie um novo projeto Astro + Starlight executando o seguinte comando no seu terminal: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight +``` + +</TabItem> +</Tabs> + +Isto irá criar um novo [diretório de projeto](/pt-pt/guides/project-structure/) com todos os arquivos e configurações necessárias para o seu novo site. + +:::tip[Veja-o em ação] +Experimente o Starlight directamente no seu navegador: +[abrir o template no StackBlitz](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). +::: + +### Inicie o servidor de desenvolvimento + +Quando estiver a trabalhar localmente, o [servidor de desenvolvimento do Astro](https://docs.astro.build/pt/reference/cli-reference/#astro-dev) permitirá visualizar seu trabalho e atualizar automaticamente o seu navegador após fazer alterações. + +Dentro do diretório do seu projeto, execute o seguinte comando para iniciar o servidor de desenvolvimento: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm run dev +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm dev +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev +``` + +</TabItem> +</Tabs> + +Será exibida uma mensagem no seu terminal com o URL para a visualização local. +Abra esse URL para começar a navegar no seu site. + +### Crie conteúdo + +O Starlight está pronto para você adicionar novos conteúdos, ou trazer os seus arquivos existentes! + +Adicione páginas ao seu site criando ficheiros _Markdown_ no directório `src/content/docs/`. + +Saiba mais acerca de _routing_ baseado em ficheiros e suporte para ficheiros MDX e Markdoc no guia [“Páginas”](/pt-pt/guides/pages/). + +### Próximos passos + +- **Configurar:** Descubra opções comuns em ["Customização do Starlight"](/pt-pt/guides/customization/). +- **Navegar:** Configure a barra lateral com o guia [“Barra lateral de navegação”](/pt-pt/guides/sidebar/). +- **Componentes:** Conheça os cartões, separadores e outros componentes integrados no guia [“Componentes”](/pt-pt/components/using-components/). +- **Deploy:** Publique o seu projeto com a ajuda do guia [“Deploy do seu site Astro”](https://docs.astro.build/pt-br/guides/deploy/) na documentação do Astro. + +## Atualizar o Starlight + +:::tip +Como o Starlight é um software em beta é normal que ocorram atualizações e melhorias frequentes. +Certifique-se que atualiza o Starlight constantemente! +::: + +O Starlight é uma integração do Astro. Pode atualizá-lo, como outros pacotes Astro, executando no seu terminal o seguinte comando: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npx @astrojs/upgrade +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm dlx @astrojs/upgrade +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dlx @astrojs/upgrade +``` + +</TabItem> +</Tabs> + +Consulte o [histórico de mudanças do Starlight](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md) para ver a lista completa das alterações feitas em cada versão. + +## Solucionar Problemas no Starlight + +Utilize as páginas de referência [configuração do projeto](/pt-pt/reference/configuration/) e [configuração do frontmatter para cada página](/pt-pt/reference/frontmatter/) para garantir que seu site Starlight está configurado e a funcionar corretamente. +Confira os guias na barra lateral para ajudá-lo a adicionar conteúdo e a personalizar o seu site Starlight. + +Se não encontrar a sua resposta nesta documentação, visite por favor a [documentação do Astro](https://docs.astro.build/pt-br/) para consultar uma documentação mais completa sobre o Astro. +A sua dúvida pode ser respondida se entender como é que o Astro funciona no geral e por debaixo do tema Starlight. + +Pode ainda procurar por [problemas conhecidos do Starlight no GitHub](https://github.com/withastro/starlight/issues), e obter ajuda no [Discord do Astro](https://astro.build/chat/) com a nossa ativa e amigável comunidade! Envie perguntas no nosso fórum `#support` com a tag "starlight", ou visite o canal dedicado `#starlight` para discutir o desenvolvimento atual e mais! diff --git a/docs/src/content/docs/pt-pt/index.mdx b/docs/src/content/docs/pt-pt/index.mdx new file mode 100644 index 00000000000..95ea0dfff31 --- /dev/null +++ b/docs/src/content/docs/pt-pt/index.mdx @@ -0,0 +1,173 @@ +--- +title: Starlight 🌟 Construa sites de documentação com Astro +head: + - tag: title + content: Starlight 🌟 Construa sites de documentação com Astro +description: Starlight ajuda-te a construir websites de documentação belos e rápidos com Astro. +template: splash +editUrl: false +lastUpdated: false +banner: + content: | + Atualização para o Astro 5? + <a href="https://github.com/withastro/starlight/releases/tag/%40astrojs/starlight%400.30.0"> + Aprenda como fazer + </a> +hero: + title: Faça a sua documentação brilhar com Starlight + tagline: Tudo o que precisa para construir um site de documentação brilhante. Rápido, acessível e fácil de usar. + image: + file: ~/assets/hero-star.webp + actions: + - text: Começar + icon: right-arrow + link: /pt-pt/getting-started/ + - text: Veja no GitHub + icon: external + variant: minimal + link: https://github.com/withastro/starlight +--- + +import { CardGrid, Card } from '@astrojs/starlight/components'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; + +<CardGrid stagger> + <Card title="Documentação de iluminar os olhos" icon="open-book"> + Inclui: Navegação do site, pesquisa, internacionalização, SEO, tipografia + fácil de ler, _highlighting_ de código, modo escuro e mais. + </Card> + <Card title="Possibilitado pelo Astro" icon="rocket"> + Aproveite todo o poder e performance do Astro. Estenda o Starlight com suas + integrações e bibliotecas favoritas do Astro. + </Card> + <Card title="Markdown, Markdoc e MDX" icon="document"> + Utilize a sua linguagem de marcação favorita. O Starlight inclui validação + com _frontmatter_ e segurança integrada de tipos com TypeScript. + </Card> + <Card title="Traga seus componentes de UI" icon="puzzle"> + O Starlight é uma solução completa de documentação agnóstica a frameworks. + Estenda-o com React, Vue, Svelte, Solid e outros. + </Card> +</CardGrid> + +<TestimonialGrid title="O que dizem acerca de nós"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + A equipa do Astro EVOLUIU a forma como a documentação pode ser feita e podemos ter tudo pronto a instalar com o seu o projecto Starlight. + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + O _kit_ oficial de iniciação Starlight é de facto uma ferramenta incrível para construir um website de documentação + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + O Starlight é o nosso modelo exemplar de uma grande experiência de DX: a rapidez, conveniência, + e atenção ao detalhe são inspiradoras. Ele trata da tecnologia e do aspecto, para que se possa + focar no seu conteúdo 👏 + + A equipa StackBlitz simplesmente adora-o! + + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + O Startlight tem sido uma completa mudança para mim, permitindo-me focar na criação de conteúdos. + + O seu design intituitivo não só agiliza o meu fluxo de trabalho mas também reduz o tempo de envolvimento para developers open-source. + + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + Dediquei mais algum tempo com o Starlight para a documentação do meu "Course Builder" e tem sido fantástico até agora. + Muitos pormenores interessantes e permite-me focar em escrever com _Markdown_ em vez de perder tempo no site. + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + Comecei a mexer com o Starlight. Tenho de dizer que estou bastante impressionado com a performance + pronta-a-instalar! + + 💯💯💯💯 + + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + O Starlight é a melhor forma de começar com a documentação, entre o poder + e a rapidez do Astro, e as ferramentas do Starlight, é uma combinação feita no céu. + + Tem sido a minha escolha de eleição há algum tempo, e continuo a adorá-lo! + + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + Utilizei o Starlight no meu último trabalho e adorei-o! Componentes fantásticos, + design intuitivo, e uma comunidade super responsiva (sempre que alguém precisava de algo, + eles lançavam-no mais cedo ou mostravam uma alternativa). Uma experiência muito agradável. + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + A documentação do meu site mono-repositório parece melhor do que nunca graças ao Starlight. É extremamente fácil de utilizar sem perder nenhum do poder do Astro. + Obrigado por trabalharem nele! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + O Starlight é a minha ferramenta de seleção para documentação. Ele tornou a inclusão de documentação no meu site Astro super fácil sem necessidade + de um sub-domínio ou de utilizar outra ferramenta. + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + Tenho estado a reconstruir a documentação da plataforma WPEngine Atlas Platform. Confiem em mim quando digo que o Starlight tem tudo o que precisam + para criar uma plataforma de documentação A+ 🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + Experimente o Starlight! + + Eu utilizo-o em alguns dos meus sites e é fantástico. + + </Testimonial> +</TestimonialGrid> + +<AboutAstro title="Trazido por"> +Astro é o framework web tudo-em-um projetado para velocidade. +Traga o seu conteúdo de qualquer lugar e faça deploy em qualquer lugar, tudo fornecido pelos seus componentes de UI e bibliotecas favoritas. + +[Aprenda acerca do Astro](https://astro.build/) + +</AboutAstro> diff --git a/docs/src/content/docs/pt-pt/resources/community-content.mdx b/docs/src/content/docs/pt-pt/resources/community-content.mdx new file mode 100644 index 00000000000..af035338a99 --- /dev/null +++ b/docs/src/content/docs/pt-pt/resources/community-content.mdx @@ -0,0 +1,163 @@ +--- +title: Conteúdo da Comunidade +description: Descubra guias produzidos pela comunidade, artigos e vídeos para ajudar a aprender e construir com o Starlight! +--- + +:::tip[Inclua o seu!] +Já produziu conteúdo sobre Starlight? +Então abra um PR e adicione o seu link nesta página! +::: + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +## Artigos e Avaliações + +Aqui está uma coleção de posts e artigos para aprender mais sobre Starlight e sobre as experiências de outras pessoas: + +<CardGrid> + <LinkCard + href="https://devm.io/open-source/starlight-astro" + title="Geração de Site Estático com Starlight" + description="'Nenhuma ideia é tão grande ou pequena ao projetar componentes' — uma entrevista com Chris Swithinbank, Líder Starlight" + /> + <LinkCard + href="https://frontendatscale.com/blog/hybrid-frontend-architecture/" + title="Arquitetura Frontend Híbrida com Astro e Starlight" + description="Maxi Ferreira e Ben Holmes constroem um site de documentação com Starlight, TinaCMS, e um Playground de API interativo com autenticação." + /> + <LinkCard + href="https://www.olets.dev/posts/comparing-docs-site-builders-vuepress-vs-starlight/" + title="Comparando construtores de site de documentação: VuePress vs Starlight" + description="Como estes dois frameworks se comparam?" + /> +</CardGrid> + +## Receitas e Guias + +Receitas são tipicamente guias passo a passo, curtos e focados, que levam o leitor a completar um exemplo funcional de uma tarefa específica. +As receitas são também uma ótima maneira de adicionar novas funcionalidades ou comportamentos para seu projeto Starlight bastando seguir simples instruções passo a passo! +Outros guias podem explicar conceitos relacionados a determinada área de conteúdo, como por exemplo usar imagens ou trabalhar com MDX. + +Explore o conteúdo produzido pela comunidade e mantido pelos utilizadores Starlight: + +<CardGrid> + <LinkCard + href="https://www.webpro.nl/scraps/versioned-docs-with-starlight-and-vercel" + title="Documentação versionada com Starlight e Vercel" + description="Um guia para implementar versões separadas da documentação para cada versão principal de um projeto" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-heading-links" + title="Adicione links em cabeçalhos Starlight" + description="Um guia sobre como usar um plugin rehype para criar links para seções específicas da sua documentação" + /> + <LinkCard + href="https://blog.otterlord.dev/posts/starlight-sponsors/" + title="Adicione patrocinadores para seu site Starlight" + description="Um guia sobre implementar um componente de patrocinadores personalizado na barra lateral da sua documentação" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images" + title="Adicione imagens Open Graph a Starlight" + description="Um guia para gerar imagens sociais e as metatags correspondentes para as suas páginas" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-third-party-icon-sets" + title="Use ícones de terceiros em Starlight" + description="Um guia sobre como usar unplugin-icons para expandir a seleção de ícones disponíveis para Starlight" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-html-head" + title="Edite o elemento HTML head de páginas Starlight" + description="Aprenda sobre como adicionar conteúdo como fontes, scripts e web analytics" + /> + <LinkCard + href="https://dev.to/mrrobot/publishing-documentation-with-astro-starlight-691" + title="Publicando documentação com Astro Starlight" + description="Começando com a documentação Starlight" + /> + <LinkCard + href="https://events-3bg.pages.dev/jotter/starlight/guide/" + title="Ativar Transições de Vistas" + description="Obtenha o aspecto de SPA com o suporte às transições de vistas do Bag of Tricks’" + /> + <LinkCard + href="https://jamcomments.com/posts/structured-data-with-starlight" + title="Acrescentar Dados Estructurados a páginas do Starlight" + description="Aprenda a construir dados dinâmicos estructurados JSON-LD para as suas páginas de documentação." + /> + <LinkCard + href="https://starlight-examples.netlify.app/" + title="Exemplos do Starlight" + description="Uma coleção de exemplos deStackBlitz embebidos que demonstram formas práticas de fazer coisas em sites de documentação do Starlight." + /> +</CardGrid> + +## Conteúdo de Vídeo + +Descubra os vídeos e canais com conteúdo Starlight, incluíndo transmissões ao vivo e conteúdo educacional. + +import YouTubeGrid from '~/components/youtube-grid.astro'; + +### Videos oficiais do Astro + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=5u0Ds7wzUeI', + title: 'Starlight por Astro', + description: 'Veja o vídeo oficial do lançamento Starlight', + }, + { + href: 'https://www.youtube.com/shorts/zjOWezSzd18', + title: '🌟 SUB 1 MINUTE RUN', + description: + 'Veja o Ben lançar um novo site Starlight em menos de um minuto!', + }, + ]} +/> + +### Vídeos e Transmissões da Comunidade + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=sF6UcV3moZg', + title: 'Construir documentação com o Starlight e Astro', + description: + "Veja o Chris e Alex mergulhar no Starlight em 'Code with CodingCat.dev'", + }, + { + href: 'https://www.youtube.com/watch?v=sWkkHbwDeQc', + title: 'Astro Starlight', + description: 'Introdução ao Starlight em menos de um minuto.', + }, + { + href: 'https://www.youtube.com/watch?v=-Ki-1E5gNCk', + title: + 'Modelo de Documentação Astro Starlight (construa documentações personalizadas!)', + description: + 'Tenha um novo site Starlight a funcionar em cerca de 5 minutos', + }, + { + href: 'https://www.youtube.com/watch?v=12o7WxjAxjM', + title: + 'Inclua a documentação Starlight num projecto Next.js através de proxies', + description: + 'Configurar o Starlight como uma sub-directoria dentro de um site Next.js', + }, + { + href: 'https://www.youtube.com/watch?v=5pq80drDrNs', + title: + "Eu recreei a documentação do Shadcn's em 30 minutoes com esta ferramenta fantástica", + description: + 'Neste video eu abordo o que torna o Starlight tão porreiro e porque razão deve experimentá-lo no seu próximo projecto.', + }, + { + href: 'https://www.youtube.com/watch?v=Q1E4Gkt63ko', + title: 'Astro Starlight and emoji-blast with Chris Swithinbank', + description: + "Wherein Chris, the creator of Astro's Starlight framework-on-a-framework, walks me through setting it up for a new emoji-blast website. 🌟 🎇", + }, + ]} +/> diff --git a/docs/src/content/docs/pt-pt/resources/plugins.mdx b/docs/src/content/docs/pt-pt/resources/plugins.mdx new file mode 100644 index 00000000000..dbb189781ff --- /dev/null +++ b/docs/src/content/docs/pt-pt/resources/plugins.mdx @@ -0,0 +1,183 @@ +--- +title: Plugins e Integrações +description: Descubra ferramentas da comunidade e integrações que estendem o Starlight! +sidebar: + order: 1 +--- + +:::tip[Inclua o seu!] +Já construiu um plugin ou uma ferramenta para o Starlight? +Então abra um PR e adicione o seu link nesta página! +::: + +## Plugins + +Os [plugins](/pt-pt/reference/plugins/) podem personalizar ou estender a configuração do Starlight, a interface do utilizador e o comportamento, sendo também fáceis de compartilhar e de reutilizar. +Estenda o seu site com os plugins oficiais suportados pela equipa Starlight e com plugins da comunidade mantidos por outros utilizadores Starlight. + +### Plugins oficiais + +<CardGrid> + <LinkCard + href="/pt-pt/guides/site-search/#algolia-docsearch" + title="Algolia DocSearch" + description="Substitua o fornecedor de pesquisa Pagefind pelo Algolia DocSearch." + /> +</CardGrid> + +### Plugins da comunidade + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-links-validator" + title="starlight-links-validator" + description="Verifique links incorretos nas suas páginas do Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-typedoc" + title="starlight-typedoc" + description="Crie páginas Starlight a partir de TypeScript utilizando o TypeDoc." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-blog" + title="starlight-blog" + description="Adicione um blog ao seu site de documentação." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-openapi" + title="starlight-openapi" + description="Crie páginas de documentação a partir de especificações OpenAPI/Swagger." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-obsidian" + title="starlight-obsidian" + description="Publique cofres de Obsidian no seu site Starlight." + /> + <LinkCard + href="https://astro-ghostcms.xyz/intro/starlight/install/" + title="starlight-ghostcms" + description="Adicione os artigos do seu blog GhostCMS ao lado das páginas Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-image-zoom" + title="starlight-image-zoom" + description="Adicione funções de zoom à sua documentação do Starlight." + /> + <LinkCard + href="https://github.com/lorenzolewis/starlight-utils" + title="starlight-utils" + description="Estenda o Starlight com uma coleção de utilitários comuns." + /> + <LinkCard + href="https://github.com/trueberryless/starlight-view-modes" + title="starlight-view-modes" + description="Adicione a capacidade de mostrar diferentes formas de visualização no seu website de documentação." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-versions" + title="starlight-versions" + description="Acrescente a versão às páginas da sua documentação Starlight." + /> + <LinkCard + href="https://inox-tools.fryuni.dev/star-warp" + title="star-warp" + description="Acelere a pesquisa de resultados na sua documentação." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-heading-badges" + title="starlight-heading-badges" + description="Adicione distintivos aos cabeçalhos de Markdown e MDX." + /> + <LinkCard + href="https://github.com/Fevol/starlight-site-graph" + title="starlight-site-graph" + description="Adicione um mapa interativo do site à barra lateral das suas páginas." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-sidebar-topics" + title="starlight-sidebar-topics" + description="Divida a sua documentação em secções diferentes cada uma com a sua barra lateral." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown" + title="starlight-sidebar-topics-dropdown" + description="Divida as suas páginas de documentação em várias sub-páginas e alterne entre elas através de um menu na barra lateral." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-cooler-credit" + title="starlight-cooler-credit" + description="Adicione os créditos do Starlight ou Astro no fundo da tabela de conteúdos." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-contributor-list" + title="starlight-contributor-list" + description="Apresente uma lista de todos os contribuidores do seu projeto." + /> +</CardGrid> + +### Temas da comunidade + +Um Tema é um plugin do Starlight que muda visualmente a aparência do site através da sobreposição de componentes, CSS personalizados, ou outras +novas funcionalidades. + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-theme-rapide" + title="starlight-theme-rapide" + description="Tema do Starlight inspirado no tema Vitesse do Visual Studio Code." + /> + <LinkCard + href="https://github.com/Fevol/starlight-theme-obsidian" + title="starlight-theme-obsidian" + description="Tema do Starlight inspirado em sites com o tema Obsidian Publish." + /> + <LinkCard + href="https://github.com/TheOtterlord/catppuccin-starlight" + title="catppuccin-starlight" + description="Tema em tons de pastel suave para o Starlight" + /> +</CardGrid> + +## Ferramentas e integrações da comunidade + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +Estas ferramentas e integrações da comunidade podem ser usadas para adicionar funcionalidades ao seu site Starlight. + +<CardGrid> + <LinkCard + href="https://www.feelback.dev/blog/new-astro-starlight-integration/" + title="FeelBack" + description="Adicione um sistema de feedback de utilizador às páginas da documentação." + /> + <LinkCard + href="https://github.com/val-town/notion-to-astro" + title="notion-to-astro" + description="Converta exportações do Notion para documentos do Starlight" + /> + <LinkCard + href="https://github.com/mattjennings/astro-live-code" + title="astro-live-code" + description="Apresente blocos de código MDX como componentes interativos" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-i18n" + title="starlight-i18n" + description="Extensão para o Visual Studio Code que ajuda a traduzir páginas do Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-package-managers" + title="starlight-package-managers" + description="Mostra de forma rápida comandos npm relacionados para vários gestores de packages." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-showcases" + title="starlight-showcases" + description="Conjunto de componentes do Starlight para construir páginas de demonstração." + /> + <LinkCard + href="https://github.com/HiDeoo/generator-starlight-plugin" + title="@hideoo/starlight-plugin" + description="A generator to quickly scaffold Starlight plugins." + /> +</CardGrid> diff --git a/docs/src/content/docs/pt-pt/resources/showcase.mdx b/docs/src/content/docs/pt-pt/resources/showcase.mdx new file mode 100644 index 00000000000..ba58e224bbb --- /dev/null +++ b/docs/src/content/docs/pt-pt/resources/showcase.mdx @@ -0,0 +1,21 @@ +--- +title: Montra Starlight +description: Descubra sites construídos com Starlight! +sidebar: + label: Montra de Sites +--- + +:::tip[Inclua o seu!] +Já construiu um site com o Starlight? +Então abra um PR e adicione o seu link nesta página! +::: + +## Sites + +import ShowcaseSites from '~/components/showcase-sites.astro'; + +O Starlight já está a ser usado em muitos sites em produção. Estes são alguns desses sites já espalhados pela web: + +<ShowcaseSites /> + +Pesquise todos os [repositórios de projetos públicos que usam o Starlight no GitHub](https://github.com/withastro/starlight/network/dependents). diff --git a/docs/src/content/docs/reference/configuration.md b/docs/src/content/docs/reference/configuration.md deleted file mode 100644 index 19c877db075..00000000000 --- a/docs/src/content/docs/reference/configuration.md +++ /dev/null @@ -1,426 +0,0 @@ ---- -title: Configuration Reference -description: An overview of all the configuration options Starlight supports. ---- - -## Configure the `starlight` integration - -Starlight is an integration built on top the [Astro](https://astro.build) web framework. You can configure your project inside the `astro.config.mjs` configuration file: - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'My delightful docs site', - }), - ], -}); -``` - -You can pass the following options to the `starlight` integration. - -### `title` (required) - -**type:** `string` - -Set the title for your website. Will be used in metadata and in the browser tab title. - -### `description` - -**type:** `string` - -Set the description for your website. Used in metadata shared with search engines in the `<meta name="description">` tag if `description` is not set in a page’s frontmatter. - -### `logo` - -**type:** [`LogoConfig`](#logoconfig) - -Set a logo image to show in the navigation bar alongside or instead of the site title. You can either set a single `src` property or set separate image sources for `light` and `dark`. - -```js -starlight({ - logo: { - src: './src/assets/my-logo.svg', - }, -}); -``` - -#### `LogoConfig` - -```ts -type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( - | { src: string } - | { light: string; dark: string } -); -``` - -### `tableOfContents` - -**type:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` -**default:** `{ minHeadingLevel: 2; maxHeadingLevel: 3; }` - -Configure the table of contents shown on the right of each page. By default, `<h2>` and `<h3>` headings will be included in this table of contents. - -### `editLink` - -**type:** `{ baseUrl: string }` - -Enable “Edit this page” links by setting the base URL these should use. The final link will be `editLink.baseUrl` + the current page path. For example, to enable editing pages in the `withastro/starlight` repo on GitHub: - -```js -starlight({ - editLink: { - baseUrl: 'https://github.com/withastro/starlight/edit/main/', - }, -}); -``` - -With this config, a `/introduction` page would have an edit link pointing to `https://github.com/withastro/starlight/edit/main/src/docs/introduction.md`. - -### `sidebar` - -**type:** [`SidebarItem[]`](#sidebaritem) - -Configure your site’s sidebar navigation items. - -A sidebar is an array of links and groups of links. -Each item must have a `label` and one of the following properties: - -- `link` — a single link to a specific URL, e.g. `'/home'` or `'https://example.com'`. - -- `items` — an array containing more sidebar links and subgroups. - -- `autogenerate` — an object specifying a directory of your docs to automatically generate a group of links from. - -```js -starlight({ - sidebar: [ - // A single link item labelled “Home”. - { label: 'Home', link: '/' }, - // A group labelled “Start Here” containing two links. - { - label: 'Start Here', - items: [ - { label: 'Introduction', link: '/intro' }, - { label: 'Next Steps', link: '/next-steps' }, - ], - }, - // A group linking to all pages in the reference directory. - { - label: 'Reference', - autogenerate: { directory: 'reference' }, - }, - ], -}); -``` - -#### Sorting - -Autogenerated sidebar groups are sorted by filename alphabetically. -For example, a page generated from `astro.md` would appear above the page for `starlight.md`. - -#### Collapsing groups - -Groups of links are expanded by default. You can change this behavior by setting a group’s `collapsed` property to `true`. - -Autogenerated subgroups respect the `collapsed` property of their parent group by default. Set the `autogenerate.collapsed` property to override this. - -```js -sidebar: [ - // A collapsed group of links. - { - label: 'Collapsed Links', - collapsed: true, - items: [ - { label: 'Introduction', link: '/intro' }, - { label: 'Next Steps', link: '/next-steps' }, - ], - }, - // An expanded group containing collapsed autogenerated subgroups. - { - label: 'Reference', - autogenerate: { - directory: 'reference', - collapsed: true, - }, - }, -], -``` - -#### Translating labels - -If your site is multilingual, each item’s `label` is considered to be in the default locale. You can set a `translations` property to provide labels for your other supported languages: - -```js -sidebar: [ - // An example sidebar with labels translated to French. - { - label: 'Start Here', - translations: { fr: 'Commencez ici' }, - items: [ - { - label: 'Getting Started', - translations: { fr: 'Bien démarrer' }, - link: '/getting-started', - }, - { - label: 'Project Structure', - translations: { fr: 'Structure du projet' }, - link: '/structure', - }, - ], - }, -], -``` - -#### `SidebarItem` - -```ts -type SidebarItem = { - label: string; - translations?: Record<string, string>; -} & ( - | { - link: string; - badge?: string | BadgeConfig; - } - | { items: SidebarItem[]; collapsed?: boolean } - | { - autogenerate: { directory: string; collapsed?: boolean }; - collapsed?: boolean; - } -); -``` - -#### `BadgeConfig` - -```ts -interface BadgeConfig { - text: string; - variant: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; -} -``` - -### `locales` - -**type:** <code>{ \[dir: string\]: [LocaleConfig](#localeconfig) }</code> - -[Configure internationalization (i18n)](/guides/i18n/) for your site by setting which `locales` are supported. - -Each entry should use the directory where that language’s files are saved as the key. - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'My Site', - // Set English as the default language for this site. - defaultLocale: 'en', - locales: { - // English docs in `src/content/docs/en/` - en: { - label: 'English', - }, - // Simplified Chinese docs in `src/content/docs/zh/` - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - // Arabic docs in `src/content/docs/ar/` - ar: { - label: 'العربية', - dir: 'rtl', - }, - }, - }), - ], -}); -``` - -#### `LocaleConfig` - -```ts -interface LocaleConfig { - label: string; - lang?: string; - dir?: 'ltr' | 'rtl'; -} -``` - -You can set the following options for each locale: - -##### `label` (required) - -**type:** `string` - -The label for this language to show to users, for example in the language switcher. Most often you will want this to be the language’s name as a user of that language would expect to read it, e.g. `"English"`, `"العربية"`, or `"简体中文"`. - -##### `lang` - -**type:** `string` - -The BCP-47 tag for this language, e.g. `"en"`, `"ar"`, or `"zh-CN"`. If not set, the language’s directory name will be used by default. Language tags with regional subtags (e.g. `"pt-BR"` or `"en-US"`) will use built-in UI translations for their base language if no region-specific translations are found. - -##### `dir` - -**type:** `'ltr' | 'rtl'` - -The writing direction of this language; `"ltr"` for left-to-right (the default) or `"rtl"` for right-to-left. - -#### Root locale - -You can serve the default language without a `/lang/` directory by setting a `root` locale: - -```js -starlight({ - locales: { - root: { - label: 'English', - lang: 'en', - }, - fr: { - label: 'Français', - }, - }, -}); -``` - -For example, this allows you to serve `/getting-started/` as an English route and use `/fr/getting-started/` as the equivalent French page. - -### `defaultLocale` - -**type:** `string` - -Set the language which is the default for this site. -The value should match one of the keys of your [`locales`](#locales) object. -(If your default language is your [root locale](#root-locale), you can skip this.) - -The default locale will be used to provide fallback content where translations are missing. - -### `social` - -**type:** `Partial<Record<'bitbucket' | 'codeberg' | 'codePen' | 'discord' | 'github' | 'gitlab' | 'gitter' | 'instagram' | 'linkedin' | 'mastodon' | 'microsoftTeams' | 'stackOverflow' | 'threads' | 'twitch' | 'twitter' | 'youtube', string>>` - -Optional details about the social media accounts for this site. Adding any of these will display them as icon links in the site header. - -```js -starlight({ - social: { - codeberg: 'https://codeberg.org/knut/examples', - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - gitlab: 'https://gitlab.com/delucis', - linkedin: 'https://www.linkedin.com/company/astroinc', - mastodon: 'https://m.webtoo.ls/@astro', - threads: 'https://www.threads.net/@nmoodev', - twitch: 'https://www.twitch.tv/bholmesdev', - twitter: 'https://twitter.com/astrodotbuild', - youtube: 'https://youtube.com/@astrodotbuild', - }, -}); -``` - -### `customCss` - -**type:** `string[]` - -Provide CSS files to customize the look and feel of your Starlight site. - -Supports local CSS files relative to the root of your project, e.g. `'./src/custom.css'`, and CSS you installed as an npm module, e.g. `'@fontsource/roboto'`. - -```js -starlight({ - customCss: ['./src/custom-styles.css', '@fontsource/roboto'], -}); -``` - -### `head` - -**type:** [`HeadConfig[]`](#headconfig) - -Add custom tags to the `<head>` of your Starlight site. -Can be useful for adding analytics and other third-party scripts and resources. - -```js -starlight({ - head: [ - // Example: add Fathom analytics script tag. - { - tag: 'script', - attrs: { - src: 'https://cdn.usefathom.com/script.js', - 'data-site': 'MY-FATHOM-ID', - defer: true, - }, - }, - ], -}); -``` - -#### `HeadConfig` - -```ts -interface HeadConfig { - tag: string; - attrs?: Record<string, string | boolean | undefined>; - content?: string; -} -``` - -### `lastUpdated` - -**type:** `boolean` -**default:** `false` - -Control whether the footer shows when the page was last updated. - -By default, this feature relies on your repository’s Git history and may not be accurate on some deployment platforms performing [shallow clones](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt). A page can override this setting or the Git-based date using the [`lastUpdated` frontmatter field](/reference/frontmatter/#lastupdated). - -### `pagination` - -**type:** `boolean` -**default:** `true` - -Define if the footer should include previous and next page links. - -A page can override this setting or the link text and/or URL using the [`prev`](/reference/frontmatter/#prev) and [`next`](/reference/frontmatter/#next) frontmatter fields. - -### `favicon` - -**type:** `string` -**default:** `'/favicon.svg'` - -Set the path of the default favicon for your website which should be located in the `public/` directory and be a valid (`.ico`, `.gif`, `.jpg`, `.png`, or `.svg`) icon file. - -```js -starlight({ - favicon: '/images/favicon.svg', -}), -``` - -If you need to set additional variants or fallback favicons, you can add tags using the [`head` option](#head): - -```js -starlight({ - favicon: '/images/favicon.svg'. - head: [ - // Add ICO favicon fallback for Safari. - { - tag: 'link', - attrs: { - rel: 'icon', - href:'/images/favicon.ico', - sizes: '32x32', - }, - }, - ], -}); -``` diff --git a/docs/src/content/docs/reference/configuration.mdx b/docs/src/content/docs/reference/configuration.mdx new file mode 100644 index 00000000000..05f980d8878 --- /dev/null +++ b/docs/src/content/docs/reference/configuration.mdx @@ -0,0 +1,816 @@ +--- +title: Configuration Reference +description: An overview of all the configuration options Starlight supports. +--- + +## Configure the `starlight` integration + +Starlight is an integration built on top the [Astro](https://astro.build) web framework. You can configure your project inside the `astro.config.mjs` configuration file: + +```js +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'My delightful docs site', + }), + ], +}); +``` + +You can pass the following options to the `starlight` integration. + +### `title` (required) + +**type:** `string | Record<string, string>` + +Set the title for your website. Will be used in metadata and in the browser tab title. + +The value can be a string, or for multilingual sites, an object with values for each different locale. +When using the object form, the keys must be BCP-47 tags (e.g. `en`, `ar`, or `zh-CN`): + +```ts +starlight({ + title: { + en: 'My delightful docs site', + de: 'Meine bezaubernde Dokumentationsseite', + }, +}); +``` + +### `description` + +**type:** `string` + +Set the description for your website. Used in metadata shared with search engines in the `<meta name="description">` tag if `description` is not set in a page’s frontmatter. + +### `logo` + +**type:** [`LogoConfig`](#logoconfig) + +Set a logo image to show in the navigation bar alongside or instead of the site title. You can either set a single `src` property or set separate image sources for `light` and `dark`. + +```js +starlight({ + logo: { + src: './src/assets/my-logo.svg', + }, +}); +``` + +#### `LogoConfig` + +```ts +type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( + | { src: string } + | { light: string; dark: string } +); +``` + +### `tableOfContents` + +**type:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number }` +**default:** `{ minHeadingLevel: 2, maxHeadingLevel: 3 }` + +Configure the table of contents shown on the right of each page. By default, `<h2>` and `<h3>` headings will be included in this table of contents. + +### `editLink` + +**type:** `{ baseUrl: string }` + +Enable “Edit this page” links by setting the base URL these should use. The final link will be `editLink.baseUrl` + the current page path. For example, to enable editing pages in the `withastro/starlight` repo on GitHub: + +```js +starlight({ + editLink: { + baseUrl: 'https://github.com/withastro/starlight/edit/main/', + }, +}); +``` + +With this config, a `/introduction` page would have an edit link pointing to `https://github.com/withastro/starlight/edit/main/src/content/docs/introduction.md`. + +### `sidebar` + +**type:** [`SidebarItem[]`](#sidebaritem) + +Configure your site’s sidebar navigation items. + +A sidebar is an array of links and groups of links. +With the exception of items using `slug`, each item must have a `label` and one of the following properties: + +- `link` — a single link to a specific URL, e.g. `'/home'` or `'https://example.com'`. + +- `slug` — a reference to an internal page, e.g. `'guides/getting-started'`. + +- `items` — an array containing more sidebar links and subgroups. + +- `autogenerate` — an object specifying a directory of your docs to automatically generate a group of links from. + +Internal links can also be specified as a string instead of an object with a `slug` property. + +```js +starlight({ + sidebar: [ + // A single link item labelled “Home”. + { label: 'Home', link: '/' }, + // A group labelled “Start Here” containing four links. + { + label: 'Start Here', + items: [ + // Using `slug` for internal links. + { slug: 'intro' }, + { slug: 'installation' }, + // Or using the shorthand for internal links. + 'tutorial', + 'next-steps', + ], + }, + // A group linking to all pages in the reference directory. + { + label: 'Reference', + autogenerate: { directory: 'reference' }, + }, + ], +}); +``` + +#### Sorting + +Autogenerated sidebar groups are sorted by filename alphabetically. +For example, a page generated from `astro.md` would appear above the page for `starlight.md`. + +#### Collapsing groups + +Groups of links are expanded by default. You can change this behavior by setting a group’s `collapsed` property to `true`. + +Autogenerated subgroups respect the `collapsed` property of their parent group by default. Set the `autogenerate.collapsed` property to override this. + +```js {5,13} +sidebar: [ + // A collapsed group of links. + { + label: 'Collapsed Links', + collapsed: true, + items: ['intro', 'next-steps'], + }, + // An expanded group containing collapsed autogenerated subgroups. + { + label: 'Reference', + autogenerate: { + directory: 'reference', + collapsed: true, + }, + }, +], +``` + +#### Translating labels + +If your site is multilingual, each item’s `label` is considered to be in the default locale. You can set a `translations` property to provide labels for your other supported languages: + +```js {5,9,14} +sidebar: [ + // An example sidebar with labels translated to Brazilian Portuguese. + { + label: 'Start Here', + translations: { 'pt-BR': 'Comece Aqui' }, + items: [ + { + label: 'Getting Started', + translations: { 'pt-BR': 'Introdução' }, + link: '/getting-started', + }, + { + label: 'Project Structure', + translations: { 'pt-BR': 'Estrutura de Projetos' }, + link: '/structure', + }, + ], + }, +], +``` + +#### `SidebarItem` + +```ts +type SidebarItem = + | string + | ({ + translations?: Record<string, string>; + badge?: string | BadgeConfig; + } & ( + | { + // Link + link: string; + label: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // Internal link + slug: string; + label?: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // Group of links + label: string; + items: SidebarItem[]; + collapsed?: boolean; + } + | { + // Autogenerated link group + label: string; + autogenerate: { + directory: string; + collapsed?: boolean; + attrs?: Record<string, string | number | boolean | undefined>; + }; + collapsed?: boolean; + } + )); +``` + +#### `BadgeConfig` + +```ts +interface BadgeConfig { + text: string; + variant?: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; + class?: string; +} +``` + +### `locales` + +**type:** <code>\{ \[dir: string\]: [LocaleConfig](#localeconfig) \}</code> + +[Configure internationalization (i18n)](/guides/i18n/) for your site by setting which `locales` are supported. + +Each entry should use the directory where that language’s files are saved as the key. + +```js +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'My Site', + // Set English as the default language for this site. + defaultLocale: 'en', + locales: { + // English docs in `src/content/docs/en/` + en: { + label: 'English', + }, + // Simplified Chinese docs in `src/content/docs/zh-cn/` + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + // Arabic docs in `src/content/docs/ar/` + ar: { + label: 'العربية', + dir: 'rtl', + }, + }, + }), + ], +}); +``` + +#### `LocaleConfig` + +```ts +interface LocaleConfig { + label: string; + lang?: string; + dir?: 'ltr' | 'rtl'; +} +``` + +You can set the following options for each locale: + +##### `label` (required) + +**type:** `string` + +The label for this language to show to users, for example in the language switcher. Most often you will want this to be the language’s name as a user of that language would expect to read it, e.g. `"English"`, `"العربية"`, or `"简体中文"`. + +##### `lang` + +**type:** `string` + +The BCP-47 tag for this language, e.g. `"en"`, `"ar"`, or `"zh-CN"`. If not set, the language’s directory name will be used by default. Language tags with regional subtags (e.g. `"pt-BR"` or `"en-US"`) will use built-in UI translations for their base language if no region-specific translations are found. + +##### `dir` + +**type:** `'ltr' | 'rtl'` + +The writing direction of this language; `"ltr"` for left-to-right (the default) or `"rtl"` for right-to-left. + +#### Root locale + +You can serve the default language without a `/lang/` directory by setting a `root` locale: + +```js {3-6} +starlight({ + locales: { + root: { + label: 'English', + lang: 'en', + }, + fr: { + label: 'Français', + }, + }, +}); +``` + +For example, this allows you to serve `/getting-started/` as an English route and use `/fr/getting-started/` as the equivalent French page. + +### `defaultLocale` + +**type:** `string` + +Set the language which is the default for this site. +The value should match one of the keys of your [`locales`](#locales) object. +(If your default language is your [root locale](#root-locale), you can skip this.) + +The default locale will be used to provide fallback content where translations are missing. + +### `social` + +**type:** <code>{`Array<{ label: string; icon: `}[StarlightIcon](/reference/icons/){`; href: string }>`}</code> + +Optional details about the social media accounts for this site. +Each entry will be displayed as an icon link in the site header. + +```js +starlight({ + social: [ + { icon: 'codeberg', label: 'Codeberg', href: 'https://codeberg.org/knut' }, + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro' }, + { icon: 'gitlab', label: 'GitLab', href: 'https://gitlab.com/delucis' }, + { icon: 'mastodon', label: 'Mastodon', href: 'https://m.webtoo.ls/@astro' }, + ], +}), +``` + +### `customCss` + +**type:** `string[]` + +Provide CSS files to customize the look and feel of your Starlight site. + +Supports local CSS files relative to the root of your project, e.g. `'./src/custom.css'`, and CSS you installed as an npm module, e.g. `'@fontsource/roboto'`. + +```js +starlight({ + customCss: ['./src/custom-styles.css', '@fontsource/roboto'], +}); +``` + +### `markdown` + +**type:** `{ headingLinks?: boolean; processedDirs?: string[] }` +**default:** `{ headingLinks: true, processedDirs: [] }` + +Configure Starlight’s Markdown processing. + +#### `headingLinks` + +**type:** `boolean` +**default:** `true` + +Controls whether or not headings are rendered with a clickable anchor link. + +```js +starlight({ + markdown: { + // Disable Starlight’s clickable heading anchor links. + headingLinks: false, + }, +}), +``` + +#### `processedDirs` + +**type:** `string[]` +**default:** `[]` + +Define additional directories where files should be processed by Starlight’s Markdown pipeline. +By default, only Markdown and MDX content loaded using Starlight's [`docsLoader()`](/reference/configuration/#docsloader) is processed. +Supports local directories relative to the root of your project, e.g. `'./src/data/comments/'`. + +Starlight’s processing includes support for [clickable heading anchor links](#headinglinks), [asides Markdown directive syntax](/guides/authoring-content/#asides), and RTL support for code blocks. +This option can be useful if you are rendering content from a custom content collection in a [custom page](/guides/pages/#custom-pages) using the `<StarlightPage>` component and expect Starlight's Markdown processing to be applied to that content as well. + +```js +starlight({ + markdown: { + // Process Markdown files from the `reviews` content collection located in the + // `src/data/reviews/` directory. + processedDirs: ['./src/data/reviews/'], + }, +}), +``` + +### `expressiveCode` + +**type:** `StarlightExpressiveCodeOptions | boolean` +**default:** `true` + +Starlight uses [Expressive Code](https://expressive-code.com) to render code blocks and add support for highlighting parts of code examples, adding filenames to code blocks, and more. +See the [“Code blocks” guide](/guides/authoring-content/#code-blocks) to learn how to use Expressive Code syntax in your Markdown and MDX content. + +You can use any of the standard [Expressive Code configuration options](https://expressive-code.com/reference/configuration/) as well as some Starlight-specific properties, by setting them in Starlight’s `expressiveCode` option. +For example, set Expressive Code’s `styleOverrides` option to override the default CSS. This enables customizations like giving your code blocks rounded corners: + +```js ins={2-4} +starlight({ + expressiveCode: { + styleOverrides: { borderRadius: '0.5rem' }, + }, +}); +``` + +If you want to disable Expressive Code, set `expressiveCode: false` in your Starlight config: + +```js ins={2} +starlight({ + expressiveCode: false, +}); +``` + +In addition to the standard Expressive Code options, you can also set the following Starlight-specific properties in your `expressiveCode` config to further customize theme behavior for your code blocks : + +#### `themes` + +**type:** `Array<string | ThemeObject | ExpressiveCodeTheme>` +**default:** `['starlight-dark', 'starlight-light']` + +Set the themes used to style code blocks. +See the [Expressive Code `themes` documentation](https://expressive-code.com/guides/themes/) for details of the supported theme formats. + +Starlight uses the dark and light variants of Sarah Drasner’s [Night Owl theme](https://github.com/sdras/night-owl-vscode-theme) by default. + +If you provide at least one dark and one light theme, Starlight will automatically keep the active code block theme in sync with the current site theme. +Configure this behavior with the [`useStarlightDarkModeSwitch`](#usestarlightdarkmodeswitch) option. + +#### `useStarlightDarkModeSwitch` + +**type:** `boolean` +**default:** `true` + +When `true`, code blocks automatically switch between light and dark themes when the site theme changes. +When `false`, you must manually add CSS to handle switching between multiple themes. + +:::note +When setting `themes`, you must provide at least one dark and one light theme for the Starlight dark mode switch to work. +::: + +#### `useStarlightUiThemeColors` + +**type:** `boolean` +**default:** `true` if `themes` is not set, otherwise `false` + +When `true`, Starlight's CSS variables are used for the colors of code block UI elements (backgrounds, buttons, shadows etc.), matching the [site color theme](/guides/css-and-tailwind/#theming). +When `false`, the colors provided by the active syntax highlighting theme are used for these elements. + +:::note +When using custom themes and setting this to `true`, you must provide at least one dark and one light theme to ensure proper color contrast. +::: + +### `pagefind` + +**type:** <code>boolean | <a href="#pagefindoptions">PagefindOptions</a></code> +**default:** `true` + +Configure Starlight’s default site search provider [Pagefind](https://pagefind.app/). + +Set to `false` to disable indexing your site with Pagefind. +This will also hide the default search UI if in use. + +Pagefind cannot be enabled when the [`prerender`](#prerender) option is set to `false`. + +Set `pagefind` to an object to configure the Pagefind search client: + +- See [“Customize Pagefind's result ranking”](https://pagefind.app/docs/ranking/) in the Pagefind documentation for more details about using the `pagefind.ranking` option to control how search result ranking is calculated +- See [“Searching multiple sites”](https://pagefind.app/docs/multisite/) in the Pagefind documentation for more details about using the `pagefind.mergeIndex` option to control how to search across multiple sites + +#### `PagefindOptions` + +```ts +interface PagefindOptions { + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + indexWeight?: number; + mergeIndex?: Array<{ + bundlePath: string; + indexWeight?: number; + basePath?: string; + baseUrl?: string; + mergeFilter?: Record<string, string | string[]>; + language?: string; + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + }>; +} +``` + +### `prerender` + +**type:** `boolean` +**default:** `true` + +Define whether Starlight pages should be pre-rendered to static HTML or on-demand rendered by an [SSR adapter](https://docs.astro.build/en/guides/on-demand-rendering/). + +Starlight pages are pre-rendered by default. +If you are using an SSR adapter and want to render Starlight pages on demand, set `prerender: false`. + +### `head` + +**type:** [`HeadConfig[]`](#headconfig) + +Add custom tags to the `<head>` of your Starlight site. +Can be useful for adding analytics and other third-party scripts and resources. + +```js +starlight({ + head: [ + // Example: add Fathom analytics script tag. + { + tag: 'script', + attrs: { + src: 'https://cdn.usefathom.com/script.js', + 'data-site': 'MY-FATHOM-ID', + defer: true, + }, + }, + ], +}); +``` + +Entries in `head` are converted directly to HTML elements and do not pass through Astro’s [script](https://docs.astro.build/en/guides/client-side-scripts/#script-processing) or [style](https://docs.astro.build/en/guides/styling/#styling-in-astro) processing. +If you need to import local assets like scripts, styles, or images, [override the Head component](/guides/overriding-components/#reuse-a-built-in-component). + +#### `HeadConfig` + +```ts +interface HeadConfig { + tag: string; + attrs?: Record<string, string | boolean | undefined>; + content?: string; +} +``` + +### `lastUpdated` + +**type:** `boolean` +**default:** `false` + +Control whether the footer shows when the page was last updated. + +By default, this feature relies on your repository’s Git history and may not be accurate on some deployment platforms performing [shallow clones](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt). A page can override this setting or the Git-based date using the [`lastUpdated` frontmatter field](/reference/frontmatter/#lastupdated). + +### `pagination` + +**type:** `boolean` +**default:** `true` + +Define if the footer should include previous and next page links. + +A page can override this setting or the link text and/or URL using the [`prev`](/reference/frontmatter/#prev) and [`next`](/reference/frontmatter/#next) frontmatter fields. + +### `favicon` + +**type:** `string` +**default:** `'/favicon.svg'` + +Set the path of the default favicon for your website which should be located in the `public/` directory and be a valid (`.ico`, `.gif`, `.jpg`, `.png`, or `.svg`) icon file. + +```js +starlight({ + favicon: '/images/favicon.svg', +}), +``` + +If you need to set additional variants or fallback favicons, you can add tags using the [`head` option](#head): + +```js +starlight({ + favicon: '/images/favicon.svg', + head: [ + // Add ICO favicon fallback for Safari. + { + tag: 'link', + attrs: { + rel: 'icon', + href: '/images/favicon.ico', + sizes: '32x32', + }, + }, + ], +}); +``` + +### `titleDelimiter` + +**type:** `string` +**default:** `'|'` + +Sets the delimiter between page title and site title in the page’s `<title>` tag, which is displayed on browser tabs. + +By default, every page has a `<title>` of `Page Title | Site Title`. +For example, this page is titled “Configuration Reference” and this site is titled “Starlight”, so the `<title>` for this page is “Configuration Reference | Starlight”. + +### `disable404Route` + +**type:** `boolean` +**default:** `false` + +Disables injecting Starlight's default [404 page](https://docs.astro.build/en/basics/astro-pages/#custom-404-error-page). To use a custom `src/pages/404.astro` route in your project, set this option to `true`. + +### `routeMiddleware` + +**type:** `string | string[]` + +Provide paths to route middleware that can modify how Starlight processes your data. +These file paths must not conflict with [Astro’s middleware](https://docs.astro.build/en/guides/middleware/). + +See the [Route Data guide](/guides/route-data/#customizing-route-data) for details about how to create route middleware. + +### `components` + +**type:** `Record<string, string>` + +Provide the paths to components to override Starlight’s default implementations. + +```js +starlight({ + components: { + SocialLinks: './src/components/MySocialLinks.astro', + }, +}); +``` + +See the [Overrides Reference](/reference/overrides/) for details of all the components that you can override. + +### `plugins` + +**type:** [`StarlightPlugin[]`](/reference/plugins/#quick-api-reference) + +Extend Starlight with custom plugins. +Plugins apply changes to your project to modify or add to Starlight's features. + +Visit the [plugins showcase](/resources/plugins/#plugins) to see a list of available plugins. + +```js +starlight({ + plugins: [starlightPlugin()], +}); +``` + +See the [Plugins Reference](/reference/plugins/) for details about creating your own plugins. + +### `credits` + +**type:** `boolean` +**default:** `false` + +Enable displaying a “Built with Starlight” link in your site’s footer. + +```js +starlight({ + credits: true, +}); +``` + +## Configure content collections + +Starlight uses Astro [content collections](https://docs.astro.build/en/guides/content-collections/) to load your content. +Starlight’s content loaders and schemas help configure collections as required. + +```js +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + // Optional: the i18n collection is used to translate UI in multilingual sites + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), +}; +``` + +### Loaders + +Starlight exports the following [Astro loaders](https://docs.astro.build/en/reference/content-loader-reference/) from the `@astrojs/starlight/loaders` module to simplify configuring content collections. + +#### `docsLoader()` + +The `docsLoader()` loads local Markdown, MDX, and Markdoc files from the `src/content/docs/` directory. +File names starting with an underscore (`_`) are ignored. + +##### Import + +```js +import { docsLoader } from '@astrojs/starlight/loaders'; +``` + +##### Options + +###### `generateId()` + +**type:** `({ entry: string; base: URL; data: Record<string, unknown> }) => string` + +By default, pages generated using `docsLoader()` process your file names using a sluggifier, which removes special characters and lowercases the file name. +If you want to override this default, provide your own custom `generateId()` function. + +For example, this can be useful to preserve special characters that would be removed. +By default, `Example.File.md` would be served at `/examplefile`. +If you wanted to serve it at `/Example.File`, you could do so by defining a custom `generateId()` function: + +```js +docsLoader({ + // Remove the `.md` or `.mdx` extension, but otherwise don’t process filenames. + generateId: ({ entry }) => entry.split('.').slice(0, -1).join('.'), +}), +``` + +See [`generateId()` in the Astro docs](https://docs.astro.build/en/reference/content-loader-reference/#generateid) for more details. + +#### `i18nLoader()` + +The `i18nLoader()` loads local JSON and YAML files from the `src/content/i18n/` directory. +File names starting with an underscore (`_`) are ignored. + +##### Import + +```js +import { i18nLoader } from '@astrojs/starlight/loaders'; +``` + +##### Options + +There are currently no options to configure `i18nLoader()`. + +### Schemas + +Starlight provides the following [content collection schemas](https://docs.astro.build/en/guides/content-collections/#defining-the-collection-schema) from the `@astrojs/starlight/schema` module. +These schemas must be used for the `docs` and `i18n` collections Starlight depends on. + +#### `docsSchema()` + +The `docsSchema()` parses frontmatter for all your content in the `docs` collection. + +##### Import + +```js +import { docsSchema } from '@astrojs/starlight/schema'; +``` + +##### Options + +###### `extend` + +**type:** Zod schema or function that returns a Zod schema +**default:** `z.object({})` + +Extend Starlight’s frontmatter schema with additional fields. +See [“Customize frontmatter schema”](/reference/frontmatter/#customize-frontmatter-schema) for more details about using the `extend` option. + +#### `i18nSchema()` + +The `i18nSchema()` parses all data files in the `i18n` collection. + +##### Import + +```js +import { i18nSchema } from '@astrojs/starlight/schema'; +``` + +##### Options + +###### `extend` + +**type:** Zod object +**default:** `z.object({})` + +Extend Starlight’s i18n schema with additional fields. +See [“Extend translation schema”](/guides/i18n/#extend-translation-schema) for more details about using the `extend` option. diff --git a/docs/src/content/docs/reference/frontmatter.md b/docs/src/content/docs/reference/frontmatter.md index 7b30541165f..b8028a7d298 100644 --- a/docs/src/content/docs/reference/frontmatter.md +++ b/docs/src/content/docs/reference/frontmatter.md @@ -5,8 +5,9 @@ description: An overview of the default frontmatter fields Starlight supports. You can customize individual Markdown and MDX pages in Starlight by setting values in their frontmatter. For example, a regular page might set `title` and `description` fields: -```md +```md {3-4} --- +# src/content/docs/example.md title: About this project description: Learn more about the project I’m working on. --- @@ -28,6 +29,12 @@ You must provide a title for every page. This will be displayed at the top of th The page description is used for page metadata and will be picked up by search engines and in social media previews. +### `slug` + +**type**: `string` + +Override the slug of the page. See [“Defining custom IDs”](https://docs.astro.build/en/guides/content-collections/#defining-custom-ids) in the Astro docs for more details. + ### `editUrl` **type:** `string | boolean` @@ -42,6 +49,7 @@ You can add additional tags to your page’s `<head>` using the `head` frontmatt ```md --- +# src/content/docs/example.md title: About us head: # Use a custom <title> tag @@ -59,6 +67,7 @@ Customize the heading levels to be included or set to `false` to hide the table ```md --- +# src/content/docs/example.md title: Page with only H2s in the table of contents tableOfContents: minHeadingLevel: 2 @@ -68,6 +77,7 @@ tableOfContents: ```md --- +# src/content/docs/example.md title: Page with no table of contents tableOfContents: false --- @@ -92,6 +102,7 @@ For example, this config shows some common options, including loading an image f ```md --- +# src/content/docs/example.md title: My Home Page template: splash hero: @@ -99,15 +110,30 @@ hero: tagline: Take your stuff to the moon and back in the blink of an eye. image: alt: A glittering, brightly colored logo - file: ../../assets/logo.png + file: ~/assets/logo.png actions: - text: Tell me more link: /getting-started/ icon: right-arrow - variant: primary - text: View on GitHub link: https://github.com/astronaut/my-project icon: external + variant: minimal + attrs: + rel: me +--- +``` + +You can display different versions of the hero image in light and dark modes. + +```md +--- +# src/content/docs/example.md +hero: + image: + alt: A glittering, brightly colored logo + dark: ~/assets/logo-dark.png + light: ~/assets/logo-light.png --- ``` @@ -117,19 +143,32 @@ hero: interface HeroConfig { title?: string; tagline?: string; - image?: { - alt?: string; - // Relative path to an image in your repository. - file?: string; - // Raw HTML to use in the image slot. - // Could be a custom `<img>` tag or inline `<svg>`. - html?: string; - }; + image?: + | { + // Relative path to an image in your repository. + file: string; + // Alt text to make the image accessible to assistive technology + alt?: string; + } + | { + // Relative path to an image in your repository to be used for dark mode. + dark: string; + // Relative path to an image in your repository to be used for light mode. + light: string; + // Alt text to make the image accessible to assistive technology + alt?: string; + } + | { + // Raw HTML to use in the image slot. + // Could be a custom `<img>` tag or inline `<svg>`. + html: string; + }; actions?: Array<{ text: string; link: string; - variant: 'primary' | 'secondary' | 'minimal'; - icon: string; + variant?: 'primary' | 'secondary' | 'minimal'; + icon?: string; + attrs?: Record<string, string | number | boolean>; }>; } ``` @@ -145,6 +184,7 @@ For example, this page displays a banner including a link to `example.com`. ```md --- +# src/content/docs/example.md title: Page with a banner banner: content: | @@ -161,6 +201,7 @@ Overrides the [global `lastUpdated` option](/reference/configuration/#lastupdate ```md --- +# src/content/docs/example.md title: Page with a custom last update date lastUpdated: 2022-08-09 --- @@ -174,6 +215,7 @@ Overrides the [global `pagination` option](/reference/configuration/#pagination) ```md --- +# src/content/docs/example.md # Hide the previous page link prev: false --- @@ -181,6 +223,7 @@ prev: false ```md --- +# src/content/docs/example.md # Override the previous page link text prev: Continue the tutorial --- @@ -188,6 +231,7 @@ prev: Continue the tutorial ```md --- +# src/content/docs/example.md # Override both the previous page link and text prev: link: /unrelated-page/ @@ -203,6 +247,7 @@ Same as [`prev`](#prev) but for the next page link. ```md --- +# src/content/docs/example.md # Hide the next page link next: false --- @@ -217,17 +262,48 @@ Set whether this page should be included in the [Pagefind](https://pagefind.app/ ```md --- +# src/content/docs/example.md # Hide this page from the search index pagefind: false --- ``` +### `draft` + +**type:** `boolean` +**default:** `false` + +Set whether this page should be considered a draft and not be included in [production builds](https://docs.astro.build/en/reference/cli-reference/#astro-build). Set to `true` to mark a page as a draft and make it only visible during development. + +```md +--- +# src/content/docs/example.md +# Exclude this page from production builds +draft: true +--- +``` + +Because draft pages are not included in build output, you cannot add draft pages directly to your site sidebar config using [slugs](/guides/sidebar/#internal-links). +Draft pages in directories used for [autogenerated sidebar groups](/guides/sidebar/#autogenerated-groups) are automatically excluded in production builds. + ### `sidebar` -**type:** `{ label?: string; order?: number; hidden?: boolean; badge?: string | BadgeConfig }` +**type:** [`SidebarConfig`](#sidebarconfig) Control how this page is displayed in the [sidebar](/reference/configuration/#sidebar), when using an autogenerated link group. +#### `SidebarConfig` + +```ts +interface SidebarConfig { + label?: string; + order?: number; + hidden?: boolean; + badge?: string | BadgeConfig; + attrs?: Record<string, string | number | boolean | undefined>; +} +``` + #### `label` **type:** `string` @@ -237,6 +313,7 @@ Set the label for this page in the sidebar when displayed in an autogenerated gr ```md --- +# src/content/docs/example.md title: About this project sidebar: label: About @@ -252,6 +329,7 @@ Lower numbers are displayed higher up in the link group. ```md --- +# src/content/docs/example.md title: Page to display first sidebar: order: 1 @@ -267,6 +345,7 @@ Prevents this page from being included in an autogenerated sidebar group. ```md --- +# src/content/docs/example.md title: Page to hide from autogenerated sidebar sidebar: hidden: true @@ -279,10 +358,11 @@ sidebar: Add a badge to the page in the sidebar when displayed in an autogenerated group of links. When using a string, the badge will be displayed with a default accent color. -Optionally, pass a [`BadgeConfig` object](/reference/configuration/#badgeconfig) with `text` and `variant` fields to customize the badge. +Optionally, pass a [`BadgeConfig` object](/reference/configuration/#badgeconfig) with `text`, `variant`, and `class` fields to customize the badge. ```md --- +# src/content/docs/example.md title: Page with a badge sidebar: # Uses the default variant matching your site’s accent color @@ -292,6 +372,7 @@ sidebar: ```md --- +# src/content/docs/example.md title: Page with a badge sidebar: badge: @@ -299,3 +380,94 @@ sidebar: variant: caution --- ``` + +#### `attrs` + +**type:** `Record<string, string | number | boolean | undefined>` + +HTML attributes to add to the page link in the sidebar when displayed in an autogenerated group of links. +If [`autogenerate.attrs`](/guides/sidebar/#custom-html-attributes-for-autogenerated-links) is set on the autogenerated group this page belongs to, frontmatter attributes will be merged with the group attributes. + +```md +--- +# src/content/docs/example.md +title: Page opening in a new tab +sidebar: + # Opens the page in a new tab + attrs: + target: _blank +--- +``` + +## Customize frontmatter schema + +The frontmatter schema for Starlight’s `docs` content collection is configured in `src/content.config.ts` using the `docsSchema()` helper: + +```ts {4,7} +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; +``` + +Learn more about content collection schemas in [“Defining a collection schema”](https://docs.astro.build/en/guides/content-collections/#defining-the-collection-schema) in the Astro docs. + +`docsSchema()` takes the following options: + +### `extend` + +**type:** Zod schema or function that returns a Zod schema +**default:** `z.object({})` + +Extend Starlight’s schema with additional fields by setting `extend` in the `docsSchema()` options. +The value should be a [Zod schema](https://docs.astro.build/en/guides/content-collections/#defining-datatypes-with-zod). + +In the following example, we provide a stricter type for `description` to make it required and add a new optional `category` field: + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: z.object({ + // Make a built-in field required instead of optional. + description: z.string(), + // Add a new field to the schema. + category: z.enum(['tutorial', 'guide', 'reference']).optional(), + }), + }), + }), +}; +``` + +To take advantage of the [Astro `image()` helper](https://docs.astro.build/en/guides/images/#images-in-content-collections), use a function that returns your schema extension: + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: ({ image }) => { + return z.object({ + // Add a field that must resolve to a local image. + cover: image(), + }); + }, + }), + }), +}; +``` diff --git a/docs/src/content/docs/reference/icons.mdx b/docs/src/content/docs/reference/icons.mdx new file mode 100644 index 00000000000..3f024642e5b --- /dev/null +++ b/docs/src/content/docs/reference/icons.mdx @@ -0,0 +1,32 @@ +--- +title: Icons Reference +description: An overview of all the icons available in Starlight. +--- + +Starlight provides a set of built-in icons that you can display in your content using the `<Icon>` component. + +## Use icons + +Icons can be displayed using the [`<Icon>`](/components/icons/) component. +They are also often used in other components, such as [cards](/components/cards/) or settings like [hero actions](/reference/frontmatter/#hero). + +## `StarlightIcon` type + +Use the `StarlightIcon` TypeScript type to reference the names of [Starlight’s built-in icons](#all-icons). + +```ts {2} /icon: (StarlightIcon)/ +// src/icon.ts +import type { StarlightIcon } from '@astrojs/starlight/types'; + +function getIconLabel(icon: StarlightIcon) { + // … +} +``` + +## All icons + +A list of all available icons is shown below with their associated names. Click an icon to copy its name to your clipboard. + +import IconsList from '~/components/icons-list.astro'; + +<IconsList labels={{ copied: 'Copied!' }} /> diff --git a/docs/src/content/docs/reference/overrides.md b/docs/src/content/docs/reference/overrides.md new file mode 100644 index 00000000000..decd9a9440d --- /dev/null +++ b/docs/src/content/docs/reference/overrides.md @@ -0,0 +1,261 @@ +--- +title: Overrides Reference +description: An overview of the components and component props supported by Starlight overrides. +tableOfContents: + maxHeadingLevel: 4 +--- + +You can override Starlight’s built-in components by providing paths to replacement components in Starlight’s [`components`](/reference/configuration/#components) configuration option. +This page lists all components available to override and links to their default implementations on GitHub. + +Learn more in the [Guide to Overriding Components](/guides/overriding-components/). + +## Components + +### Head + +These components are rendered inside each page’s `<head>` element. +They should only include [elements permitted inside `<head>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head#see_also). + +#### `Head` + +**Default component:** [`Head.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Head.astro) + +Component rendered inside each page’s `<head>`. + +Override this component as a last resort. +Prefer the [`head` config option](/reference/configuration/#head), the [`head` frontmatter field](/reference/frontmatter/#head), or a [route data middleware](/guides/route-data/#customizing-route-data) to customize the route data rendered by the default component if possible. + +#### `ThemeProvider` + +**Default component:** [`ThemeProvider.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeProvider.astro) + +Component rendered inside `<head>` that sets up dark/light theme support. +The default implementation includes an inline script and a `<template>` used by the script in [`<ThemeSelect />`](#themeselect). + +--- + +### Accessibility + +#### `SkipLink` + +**Default component:** [`SkipLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SkipLink.astro) + +Component rendered as the first element inside `<body>` which links to the main page content for accessibility. +The default implementation is hidden until a user focuses it by tabbing with their keyboard. + +--- + +### Layout + +These components are responsible for laying out Starlight’s components and managing views across different breakpoints. +Overriding these comes with significant complexity. +When possible, prefer overriding a lower-level component. + +#### `PageFrame` + +**Default component:** [`PageFrame.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageFrame.astro) +**Named slots:** `header`, `sidebar` + +Layout component wrapped around most of the page content. +The default implementation sets up the header–sidebar–main layout and includes `header` and `sidebar` named slots along with a default slot for the main content. +It also renders [`<MobileMenuToggle />`](#mobilemenutoggle) to support toggling the sidebar navigation on small (mobile) viewports. + +#### `MobileMenuToggle` + +**Default component:** [`MobileMenuToggle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuToggle.astro) + +Component rendered inside [`<PageFrame>`](#pageframe) that is responsible for toggling the sidebar navigation on small (mobile) viewports. + +#### `TwoColumnContent` + +**Default component:** [`TwoColumnContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TwoColumnContent.astro) +**Named slot:** `right-sidebar` + +Layout component wrapped around the main content column and right sidebar (table of contents). +The default implementation handles the switch between a single-column, small-viewport layout and a two-column, larger-viewport layout. + +--- + +### Header + +These components render Starlight’s top navigation bar. + +#### `Header` + +**Default component:** [`Header.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Header.astro) + +Header component displayed at the top of every page. +The default implementation displays [`<SiteTitle />`](#sitetitle), [`<Search />`](#search), [`<SocialIcons />`](#socialicons), [`<ThemeSelect />`](#themeselect), and [`<LanguageSelect />`](#languageselect). + +#### `SiteTitle` + +**Default component:** [`SiteTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SiteTitle.astro) + +Component rendered at the start of the site header to render the site title. +The default implementation includes logic for rendering logos defined in Starlight config. + +#### `Search` + +**Default component:** [`Search.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Search.astro) + +Component used to render Starlight’s search UI. +The default implementation includes the button in the header and the code for displaying a search modal when it is clicked and loading [Pagefind’s UI](https://pagefind.app/). + +When [`pagefind`](/reference/configuration/#pagefind) is disabled, the default search component will not be rendered. +However, if you override `Search`, your custom component will always be rendered even if the `pagefind` configuration option is `false`. +This allows you to add UI for alternative search providers when disabling Pagefind. + +#### `SocialIcons` + +**Default component:** [`SocialIcons.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SocialIcons.astro) + +Component rendered in the site header including social icon links. +The default implementation uses the [`social`](/reference/configuration/#social) option in Starlight config to render icons and links. + +#### `ThemeSelect` + +**Default component:** [`ThemeSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeSelect.astro) + +Component rendered in the site header that allows users to select their preferred color scheme. + +#### `LanguageSelect` + +**Default component:** [`LanguageSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LanguageSelect.astro) + +Component rendered in the site header that allows users to switch to a different language. + +--- + +### Global Sidebar + +Starlight’s global sidebar includes the main site navigation. +On narrow viewports this is hidden behind a drop-down menu. + +#### `Sidebar` + +**Default component:** [`Sidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Sidebar.astro) + +Component rendered before page content that contains global navigation. +The default implementation displays as a sidebar on wide enough viewports and inside a drop-down menu on small (mobile) viewports. +It also renders [`<MobileMenuFooter />`](#mobilemenufooter) to show additional items inside the mobile menu. + +#### `MobileMenuFooter` + +**Default component:** [`MobileMenuFooter.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuFooter.astro) + +Component rendered at the bottom of the mobile drop-down menu. +The default implementation renders [`<ThemeSelect />`](#themeselect) and [`<LanguageSelect />`](#languageselect). + +--- + +### Page Sidebar + +Starlight’s page sidebar is responsible for displaying a table of contents outlining the current page’s subheadings. +On narrow viewports this collapse into a sticky, drop-down menu. + +#### `PageSidebar` + +**Default component:** [`PageSidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageSidebar.astro) + +Component rendered before the main page’s content to display a table of contents. +The default implementation renders [`<TableOfContents />`](#tableofcontents) and [`<MobileTableOfContents />`](#mobiletableofcontents). + +#### `TableOfContents` + +**Default component:** [`TableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TableOfContents.astro) + +Component that renders the current page’s table of contents on wider viewports. + +#### `MobileTableOfContents` + +**Default component:** [`MobileTableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileTableOfContents.astro) + +Component that renders the current page’s table of contents on small (mobile) viewports. + +--- + +### Content + +These components are rendered in the main column of page content. + +#### `Banner` + +**Default component:** [`Banner.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Banner.astro) + +Banner component rendered at the top of each page. +The default implementation uses the page’s [`banner`](/reference/frontmatter/#banner) frontmatter value to decide whether or not to render. + +#### `ContentPanel` + +**Default component:** [`ContentPanel.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ContentPanel.astro) + +Layout component used to wrap sections of the main content column. + +#### `PageTitle` + +**Default component:** [`PageTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageTitle.astro) + +Component containing the `<h1>` element for the current page. + +Implementations should ensure they set `id="_top"` on the `<h1>` element as in the default implementation. + +#### `DraftContentNotice` + +**Default component:** [`DraftContentNotice.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/DraftContentNotice.astro) + +Notice displayed to users during development when the current page is marked as a draft. + +#### `FallbackContentNotice` + +**Default component:** [`FallbackContentNotice.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/FallbackContentNotice.astro) + +Notice displayed to users on pages where a translation for the current language is not available. +Only used on multilingual sites. + +#### `Hero` + +**Default component:** [`Hero.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Hero.astro) + +Component rendered at the top of the page when [`hero`](/reference/frontmatter/#hero) is set in frontmatter. +The default implementation shows a large title, tagline, and call-to-action links alongside an optional image. + +#### `MarkdownContent` + +**Default component:** [`MarkdownContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MarkdownContent.astro) + +Component rendered around each page’s main content. +The default implementation sets up basic styles to apply to Markdown content. + +The Markdown content styles are also exposed in `@astrojs/starlight/style/markdown.css` and scoped to the `.sl-markdown-content` CSS class. + +--- + +### Footer + +These components are rendered at the bottom of the main column of page content. + +#### `Footer` + +**Default component:** [`Footer.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Footer.astro) + +Footer component displayed at the bottom of each page. +The default implementation displays [`<LastUpdated />`](#lastupdated), [`<Pagination />`](#pagination), and [`<EditLink />`](#editlink). + +#### `LastUpdated` + +**Default component:** [`LastUpdated.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LastUpdated.astro) + +Component rendered in the page footer to display the last-updated date. + +#### `EditLink` + +**Default component:** [`EditLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/EditLink.astro) + +Component rendered in the page footer to display a link to where the page can be edited. + +#### `Pagination` + +**Default component:** [`Pagination.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Pagination.astro) + +Component rendered in the page footer to display navigation arrows between previous/next pages. diff --git a/docs/src/content/docs/reference/plugins.md b/docs/src/content/docs/reference/plugins.md new file mode 100644 index 00000000000..1c46004aad5 --- /dev/null +++ b/docs/src/content/docs/reference/plugins.md @@ -0,0 +1,375 @@ +--- +title: Plugins Reference +description: An overview of the Starlight plugin API. +tableOfContents: + maxHeadingLevel: 4 +--- + +Starlight plugins can customize Starlight configuration, UI, and behavior, while also being easy to share and reuse. +This reference page documents the API that plugins have access to. + +Learn more about using a Starlight plugin in the [Configuration Reference](/reference/configuration/#plugins) or visit the [plugins showcase](/resources/plugins/#plugins) to see a list of available plugins. + +## Quick API Reference + +A Starlight plugin has the following shape. +See below for details of the different properties and hook parameters. + +<!-- prettier-ignore-start --> +```ts +interface StarlightPlugin { + name: string; + hooks: { + 'i18n:setup'?: (options: { + injectTranslations: ( + translations: Record<string, Record<string, string>> + ) => void; + }) => void | Promise<void>; + 'config:setup': (options: { + config: StarlightUserConfig; + updateConfig: (newConfig: StarlightUserConfig) => void; + addIntegration: (integration: AstroIntegration) => void; + addRouteMiddleware: (config: { entrypoint: string; order?: 'pre' | 'post' | 'default' }) => void; + astroConfig: AstroConfig; + command: 'dev' | 'build' | 'preview'; + isRestart: boolean; + logger: AstroIntegrationLogger; + useTranslations: (lang: string) => I18nT; + absolutePathToLang: (path: string) => string; + }) => void | Promise<void>; + }; +} +``` +<!-- prettier-ignore-end --> + +## `name` + +**type:** `string` + +A plugin must provide a unique name that describes it. The name is used when [logging messages](#logger) related to this plugin and may be used by other plugins to detect the presence of this plugin. + +## `hooks` + +Hooks are functions which Starlight calls to run plugin code at specific times. + +To get the type of a hook's arguments, use the `HookParameters` utility type and pass in the hook name. +In the following example, the `options` parameter is typed to match the arguments passed to the `config:setup` hook: + +```ts +import type { HookParameters } from '@astrojs/starlight/types'; + +function configSetup(options: HookParameters['config:setup']) { + options.useTranslations('en'); +} +``` + +### `i18n:setup` + +Plugin internationalization setup function called when Starlight is initialized. +The `i18n:setup` hook can be used to inject translation strings so a plugin can support different locales. +These translations will be available via [`useTranslations()`](#usetranslations) in the `config:setup` hook and in UI components via [`Astro.locals.t()`](/guides/i18n/#using-ui-translations). + +The `i18n:setup` hook is called with the following options: + +#### `injectTranslations` + +**type:** `(translations: Record<string, Record<string, string>>) => void` + +A callback function to add or update translation strings used in Starlight’s [localization APIs](/guides/i18n/#using-ui-translations). + +In the following example, a plugin injects translations for a custom UI string named `myPlugin.doThing` for the `en` and `fr` locales: + +```ts {6-13} /(injectTranslations)[^(]/ +// plugin.ts +export default { + name: 'plugin-with-translations', + hooks: { + 'i18n:setup'({ injectTranslations }) { + injectTranslations({ + en: { + 'myPlugin.doThing': 'Do the thing', + }, + fr: { + 'myPlugin.doThing': 'Faire le truc', + }, + }); + }, + }, +}; +``` + +To use the injected translations in your plugin UI, follow the [“Using UI translations” guide](/guides/i18n/#using-ui-translations). +If you need to use UI strings in the context of the [`config:setup`](#configsetup) hook of your plugin, you can use the [`useTranslations()`](#usetranslations) callback. + +Types for a plugin’s injected translation strings are generated automatically in a user’s project, but are not yet available when working in your plugin’s codebase. +To type the `locals.t` object in the context of your plugin, declare the following global namespaces in a TypeScript declaration file: + +```ts +// env.d.ts +declare namespace App { + type StarlightLocals = import('@astrojs/starlight').StarlightLocals; + // Define the `locals.t` object in the context of a plugin. + interface Locals extends StarlightLocals {} +} + +declare namespace StarlightApp { + // Define the additional plugin translations in the `I18n` interface. + interface I18n { + 'myPlugin.doThing': string; + } +} +``` + +You can also infer the types for the `StarlightApp.I18n` interface from a source file if you have an object containing your translations. + +For example, given the following source file: + +```ts title="ui-strings.ts" +export const UIStrings = { + en: { 'myPlugin.doThing': 'Do the thing' }, + fr: { 'myPlugin.doThing': 'Faire le truc' }, +}; +``` + +The following declaration would infer types from the English keys in the source file: + +```ts title="env.d.ts" +declare namespace StarlightApp { + type UIStrings = typeof import('./ui-strings').UIStrings.en; + interface I18n extends UIStrings {} +} +``` + +### `config:setup` + +Plugin configuration setup function called when Starlight is initialized (during the [`astro:config:setup`](https://docs.astro.build/en/reference/integrations-reference/#astroconfigsetup) integration hook). +The `config:setup` hook can be used to update the Starlight configuration or add Astro integrations. + +This hook is called with the following options: + +#### `config` + +**type:** `StarlightUserConfig` + +A read-only copy of the user-supplied [Starlight configuration](/reference/configuration/). +This configuration may have been updated by other plugins configured before the current one. + +#### `updateConfig` + +**type:** `(newConfig: StarlightUserConfig) => void` + +A callback function to update the user-supplied [Starlight configuration](/reference/configuration/). +Provide the root-level configuration keys you want to override. +To update nested configuration values, you must provide the entire nested object. + +To extend an existing config option without overriding it, spread the existing value into your new value. +In the following example, a new [`social`](/reference/configuration/#social) media account is added to the existing configuration by spreading `config.social` into the new `social` array: + +```ts {6-15} +// plugin.ts +export default { + name: 'add-twitter-plugin', + hooks: { + 'config:setup'({ config, updateConfig }) { + updateConfig({ + social: [ + ...config.social, + { + icon: 'twitter', + label: 'Twitter', + href: 'https://twitter.com/astrodotbuild', + }, + ], + }); + }, + }, +}; +``` + +#### `addIntegration` + +**type:** `(integration: AstroIntegration) => void` + +A callback function to add an [Astro integration](https://docs.astro.build/en/reference/integrations-reference/) required by the plugin. + +In the following example, the plugin first checks if [Astro’s React integration](https://docs.astro.build/en/guides/integrations-guide/react/) is configured and, if it isn’t, uses `addIntegration()` to add it: + +```ts {14} "addIntegration," +// plugin.ts +import react from '@astrojs/react'; + +export default { + name: 'plugin-using-react', + hooks: { + 'config:setup'({ addIntegration, astroConfig }) { + const isReactLoaded = astroConfig.integrations.find( + ({ name }) => name === '@astrojs/react' + ); + + // Only add the React integration if it's not already loaded. + if (!isReactLoaded) { + addIntegration(react()); + } + }, + }, +}; +``` + +#### `addRouteMiddleware` + +**type:** `(config: { entrypoint: string; order?: 'pre' | 'post' | 'default' }) => void` + +A callback function to add a [route middleware handler](/guides/route-data/) to the site. + +The `entrypoint` property must be a module specifier for your plugin’s middleware file that exports an `onRequest` handler. + +In the following example, a plugin published as `@example/starlight-plugin` adds a route middleware using an npm module specifier: + +```js {6-9} +// plugin.ts +export default { + name: '@example/starlight-plugin', + hooks: { + 'config:setup'({ addRouteMiddleware }) { + addRouteMiddleware({ + entrypoint: '@example/starlight-plugin/route-middleware', + }); + }, + }, +}; +``` + +##### Controlling execution order + +By default, plugin middleware runs in the order the plugins are added. + +Use the optional `order` property if you need more control over when your middleware runs. +Set `order: "pre"` to run before a user’s middleware. +Set `order: "post"` to run after all other middleware. + +If two plugins add middleware with the same `order` value, the plugin added first will run first. + +#### `astroConfig` + +**type:** `AstroConfig` + +A read-only copy of the user-supplied [Astro configuration](https://docs.astro.build/en/reference/configuration-reference/). + +#### `command` + +**type:** `'dev' | 'build' | 'preview'` + +The command used to run Starlight: + +- `dev` - Project is executed with `astro dev` +- `build` - Project is executed with `astro build` +- `preview` - Project is executed with `astro preview` + +#### `isRestart` + +**type:** `boolean` + +`false` when the dev server starts, `true` when a reload is triggered. +Common reasons for a restart include a user editing their `astro.config.mjs` while the dev server is running. + +#### `logger` + +**type:** `AstroIntegrationLogger` + +An instance of the [Astro integration logger](https://docs.astro.build/en/reference/integrations-reference/#astrointegrationlogger) that you can use to write logs. +All logged messages will be prefixed with the plugin name. + +```ts {6} +// plugin.ts +export default { + name: 'long-process-plugin', + hooks: { + 'config:setup'({ logger }) { + logger.info('Starting long process…'); + // Some long process… + }, + }, +}; +``` + +The example above will log a message that includes the provided info message: + +```shell +[long-process-plugin] Starting long process… +``` + +#### `useTranslations` + +**type:** `(lang: string) => I18nT` + +Call `useTranslations()` with a BCP-47 language tag to generate a utility function that provides access to UI strings for that language. +`useTranslations()` returns an equivalent of the `Astro.locals.t()` API that is available in Astro components. +To learn more about the available APIs, see the [“Using UI translations”](/guides/i18n/#using-ui-translations) guide. + +```ts {6} +// plugin.ts +export default { + name: 'plugin-use-translations', + hooks: { + 'config:setup'({ useTranslations, logger }) { + const t = useTranslations('zh-CN'); + logger.info(t('builtWithStarlight.label')); + }, + }, +}; +``` + +The example above will log a message that includes a built-in UI string for the Simplified Chinese language: + +```shell +[plugin-use-translations] 基于 Starlight 构建 +``` + +#### `absolutePathToLang` + +**type:** `(path: string) => string` + +Call `absolutePathToLang()` with an absolute file path to get the language for that file. + +This can be particularly useful when adding [remark or rehype plugins](https://docs.astro.build/en/guides/markdown-content/#markdown-plugins) to process Markdown or MDX files. +The [virtual file format](https://github.com/vfile/vfile) used by these plugins includes the [absolute path](https://github.com/vfile/vfile#filepath) of the file being processed, which can be used with `absolutePathToLang()` to determine the language of the file. +The returned language can be used with the [`useTranslations()`](#usetranslations) helper to get UI strings for that language. + +For example, given the following Starlight configuration: + +```js +starlight({ + title: 'My Docs', + defaultLocale: 'en', + locales: { + // English docs in `src/content/docs/en/` + en: { label: 'English' }, + // French docs in `src/content/docs/fr/` + fr: { label: 'Français', lang: 'fr' }, + }, +}); +``` + +A plugin can determine the language of a file using its absolute path: + +```ts {6-8} /fr/ +// plugin.ts +export default { + name: 'plugin-use-translations', + hooks: { + 'config:setup'({ absolutePathToLang, useTranslations, logger }) { + const lang = absolutePathToLang( + '/absolute/path/to/project/src/content/docs/fr/index.mdx' + ); + const t = useTranslations(lang); + logger.info(t('aside.tip')); + }, + }, +}; +``` + +The example above will log a message that includes a built-in UI string for the French language: + +```shell +[plugin-use-translations] Astuce +``` diff --git a/docs/src/content/docs/reference/route-data.mdx b/docs/src/content/docs/reference/route-data.mdx new file mode 100644 index 00000000000..5b53eafb8e9 --- /dev/null +++ b/docs/src/content/docs/reference/route-data.mdx @@ -0,0 +1,204 @@ +--- +title: Route Data Reference +description: The full reference documentation for Starlight’s route data object. +--- + +Starlight’s route data object contains information about the current page. +Learn more about how Starlight’s data model works in the [“Route Data” guide](/guides/route-data/). + +In Astro components, access route data from `Astro.locals.starlightRoute`: + +```astro {4} +--- +// src/components/Custom.astro + +const { hasSidebar } = Astro.locals.starlightRoute; +--- +``` + +In [route middleware](/guides/route-data/#customizing-route-data), access route data from the context object passed to your middleware function: + +```ts {5} +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + const { hasSidebar } = context.locals.starlightRoute; +}); +``` + +## `starlightRoute` + +The `starlightRoute` object has the following properties: + +### `dir` + +**Type:** `'ltr' | 'rtl'` + +Page writing direction. + +### `lang` + +**Type:** `string` + +BCP-47 language tag for this page’s locale, e.g. `en`, `zh-CN`, or `pt-BR`. + +### `locale` + +**Type:** `string | undefined` + +The base path at which a language is served. `undefined` for root locale slugs. + +### `siteTitle` + +**Type:** `string` + +The site title for this page’s locale. + +### `siteTitleHref` + +**Type:** `string` + +The value for the site title’s `href` attribute, linking back to the homepage, e.g. `/`. +For multilingual sites this will include the current locale, e.g. `/en/` or `/zh-cn/`. + +### `slug` + +**Type:** `string` + +The slug for this page generated from the content filename. + +This property is deprecated and will be removed in a future version of Starlight. +Migrate to the new Content Layer API by using [Starlight’s `docsLoader`](/manual-setup/#configure-content-collections) and use the [`id`](#id) property instead. + +### `id` + +**Type:** `string` + +The slug for this page or the unique ID for this page based on the content filename if using the [`legacy.collections`](https://docs.astro.build/en/reference/legacy-flags/#collections) flag. + +### `isFallback` + +**Type:** `boolean | undefined` + +`true` if this page is untranslated in the current language and using fallback content from the default locale. +Only used in multilingual sites. + +### `entryMeta` + +**Type:** `{ dir: 'ltr' | 'rtl'; lang: string }` + +Locale metadata for the page content. Can be different from top-level locale values when a page is using fallback content. + +### `entry` + +The Astro content collection entry for the current page. +Includes frontmatter values for the current page at `entry.data`. + +```ts +entry: { + data: { + title: string; + description: string | undefined; + // etc. + } +} +``` + +Learn more about the shape of this object in [Astro’s Collection Entry Type](https://docs.astro.build/en/reference/modules/astro-content/#collectionentry) reference. + +### `sidebar` + +**Type:** `SidebarEntry[]` + +Site navigation sidebar entries for this page. + +### `hasSidebar` + +**Type:** `boolean` + +Whether or not the sidebar should be displayed on this page. + +### `pagination` + +**Type:** `{ prev?: Link; next?: Link }` + +Links to the previous and next page in the sidebar if enabled. + +### `toc` + +**Type:** `{ minHeadingLevel: number; maxHeadingLevel: number; items: TocItem[] } | undefined` + +Table of contents for this page if enabled. + +### `headings` + +**Type:** `{ depth: number; slug: string; text: string }[]` + +Array of all Markdown headings extracted from the current page. +Use [`toc`](#toc) instead if you want to build a table of contents component that respects Starlight’s configuration options. + +### `lastUpdated` + +**Type:** `Date | undefined` + +JavaScript `Date` object representing when this page was last updated if enabled. + +### `editUrl` + +**Type:** `URL | undefined` + +`URL` object for the address where this page can be edited if enabled. + +### `head` + +**type:** [`HeadConfig[]`](/reference/configuration/#headconfig) + +Array of all tags to include in the `<head>` of the current page. +Includes important tags such as `<title>` and `<meta charset="utf-8">`. + +## Utilities + +### `defineRouteMiddleware()` + +Use the `defineRouteMiddleware()` utility to help type your route middleware module: + +```ts "defineRouteMiddleware" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + // ... +}); +``` + +### `StarlightRouteData` type + +If you are writing code that needs to work with Starlight’s route data, you can import the `StarlightRouteData` type to match the shape of `Astro.locals.starlightRoute`. + +In the following example, a `usePageTitleInTOC()` function updates route data to use the current page’s title as the label for the first item in the table of contents, replacing the default “Overview” label. +The `StarlightRouteData` type allows you to check whether the route data changes are valid. + +```ts "StarlightRouteData" +// src/route-utils.ts +import type { StarlightRouteData } from '@astrojs/starlight/route-data'; + +export function usePageTitleInTOC(starlightRoute: StarlightRouteData) { + const overviewLink = starlightRoute.toc?.items[0]; + if (overviewLink) { + overviewLink.text = starlightRoute.entry.data.title; + } +} +``` + +This function can then be called from a route middleware: + +```ts {3,6} +// src/route-middleware.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; +import { usePageTitleInTOC } from './route-utils'; + +export const onRequest = defineRouteMiddleware((context) => { + usePageTitleInTOC(context.locals.starlightRoute); +}); +``` diff --git a/docs/src/content/docs/resources/community-content.mdx b/docs/src/content/docs/resources/community-content.mdx new file mode 100644 index 00000000000..48b419a8684 --- /dev/null +++ b/docs/src/content/docs/resources/community-content.mdx @@ -0,0 +1,247 @@ +--- +title: Community Content +description: Discover community-produced guides, articles and videos to help you learn and build with Starlight! +--- + +:::tip[Add your own!] +Have you produced content about Starlight? +Open a PR adding a link to this page! +::: + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +## Articles and Reviews + +Here is a collection of posts and articles to learn more about Starlight and other people's experiences: + +<CardGrid> + <LinkCard + href="https://devm.io/open-source/starlight-astro" + title="Static Site Generation with Starlight" + description="“No idea is too big or too small when designing components” — an interview with Chris Swithinbank, Starlight Lead" + /> + <LinkCard + href="https://frontendatscale.com/blog/hybrid-frontend-architecture/" + title="Hybrid Frontend Architecture with Astro and Starlight" + description="Maxi Ferreira and Ben Holmes build a docs site with Starlight, TinaCMS, and an interactive API Playground with authentication." + /> + <LinkCard + href="https://www.olets.dev/posts/comparing-docs-site-builders-vuepress-vs-starlight/" + title="Comparing docs site builders: VuePress vs Starlight" + description="How do these two frameworks measure up?" + /> + <LinkCard + href="https://astro.build/case-studies/wp-engine/" + title="Case Study: Slashing Development Costs" + description="How WP Engine Lowered Development Costs by Over 50% with Astro’s Starlight." + /> + <LinkCard + href="https://maciekpalmowski.dev/blog/building-a-documentation-site-using-astro-starlight/" + title="Building a documentation site using Astro Starlight" + description="Maciek Palmowski describes how Patchstack migrated their documentation to Starlight" + /> + <LinkCard + href="https://blog.cloudflare.com/open-source-all-the-way-down-upgrading-our-developer-documentation/" + title="Open source all the way down" + description="How Cloudflare used Starlight to upgrade their developer documentation." + /> + <LinkCard + href="https://starlight-changelog.netlify.app/" + title="Starlight Changelog" + description="View all releases of the @astrojs/starlight package on a single beautiful page." + /> + <LinkCard + href="https://hideoo.dev/notes/contributing-to-starlight" + title="Contributing to Starlight" + description="My personal experience and suggestions for contributing to open-source projects like Starlight." + /> +</CardGrid> + +## Recipes and Guides + +Recipes are typically short, focused how-to guides that walk a reader through completing a working example of a specific task. Recipes are a great way to add new features or behavior to your Starlight project by following step-by-step instructions! Other guides might explain concepts related to an area of content, such as using images or working with MDX. + +Explore community-produced content maintained by Starlight users: + +<CardGrid> + <LinkCard + href="https://www.webpro.nl/scraps/versioned-docs-with-starlight-and-vercel" + title="Versioned documentation with Starlight & Vercel" + description="A guide to implementing separate versions of documentation for each major version of a project." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-heading-links" + title="Add links to Starlight headings" + description="A guide to using a rehype plugin to share links to specific sections of your documentation." + /> + <LinkCard + href="https://blog.otterlord.dev/posts/starlight-sponsors/" + title="Add sponsors to your Starlight site" + description="A guide to implement a custom sponsors component in your documentation sidebar." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images" + title="Add Open Graph images to Starlight" + description="A guide to generating social images and the corresponding meta tags for your pages." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-third-party-icon-sets" + title="Use third-party icon sets in Starlight" + description="A guide to using unplugin-icons to expand the selection of available icons for Starlight." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-html-head" + title="Edit the HTML head of Starlight pages" + description="Learn how to add common head content such as web analytics, fonts, and scripts." + /> + <LinkCard + href="https://dev.to/mrrobot/publishing-documentation-with-astro-starlight-691" + title="Publishing Documentation with Astro Starlight" + description="Getting started with Starlight documentation." + /> + <LinkCard + href="https://events-3bg.pages.dev/jotter/starlight/" + title="Enable View Transitions" + description="Add support for view transitions, client-side routing, and SPA-like navigation to your Starlight documentation site." + /> + <LinkCard + href="https://jamcomments.com/posts/structured-data-with-starlight" + title="Adding Structured Data to Starlight Pages" + description="Learn how to build dynamic JSON-LD structured data for your documentation pages." + /> + <LinkCard + href="https://starlight-examples.netlify.app/" + title="Starlight Examples" + description="A collection of StackBlitz embeds demonstrating practical ways of doing stuff in Starlight documentation sites." + /> + <LinkCard + href="https://hideoo.dev/notebooks/starlight-plugins-by-example" + title="Starlight Plugins by Example" + description="A collection of notes and examples about Starlight plugins and common patterns used to build them." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-progress-indicator/" + title="Add a reading progress indicator" + description="Find out how to add a horizontal reading progress bar to your Starlight site." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-sidebar-whitespace/" + title="Apply custom styles to your Starlight sidebar" + description="Using a little bit of CSS to adjust fonts, colours and more of the Starlight sidebar." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-dropdown-and-list-together/" + title="Starlight Topics Dropdown on mobile, List on desktop" + description="Combine two plugins to have the best of both on desktop and mobile devices." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-autogenerate-whole-sidebar/" + title="Processing Starlight sidebars with middleware" + description="Use route middleware to control sidebar ordering and group labels, inspired by Nuxt Content’s conventions." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-social-links" + title="Add social links with custom icons to Starlight" + description="Learn how to use custom icons for social links in Starlight website header." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-paste-images-with-visual-studio-code" + title="Paste images to Starlight pages with Visual Studio Code" + description="Improve your Starlight documentation workflow by pasting images to your documentation pages using Visual Studio Code." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-add-diagrams-using-d2" + title="Add diagrams to your Starlight documentation using D2" + description="Learn how to use D2 to add diagrams to your Starlight documentation." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images-cloudinary-astro-sdk" + title="Generate Open Graph images for Starlight using the Cloudinary Astro SDK" + description="Learn how to use the Cloudinary Astro SDK to generate Open Graph images for your Starlight documentation website." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-list-recent-github-releases" + title="List recent GitHub releases in Starlight using the Astro Content Layer API" + description="Learn how to use the Astro Content Layer API to list the recent GitHub releases in a Starlight project." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-sitewide-banner" + title="Add a sitewide banner to Starlight" + description="Learn how to create a sitewide banner using Starlight's built-in per-page banner feature." + /> + <LinkCard + href="https://lirantal.com/blog/customizing-astro-starlight-sidebar-gated-content-auth" + title="Customizing Astro Starlight Sidebar for Gated Content with Authentication" + description="Secure your course material by using Clerk and SSR to dynamically hide or reveal Starlight sidebar chapters based on user login." + /> +</CardGrid> + +## Video Content + +Discover videos and channels with Starlight content, including live streams and educational content. + +import YouTubeGrid from '~/components/youtube-grid.astro'; + +### Official Videos + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=5u0Ds7wzUeI', + title: 'Starlight by Astro', + description: 'Watch the official Starlight launch video', + }, + { + href: 'https://www.youtube.com/watch?v=j8K-ESJF814', + title: 'One year of Starlight!', + description: + "Sarah talks about Astro's community-built documentation theme", + }, + ]} +/> + +### Community Videos and Streams + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/shorts/zjOWezSzd18', + title: '🌟 SUB 1 MINUTE RUN', + description: 'Watch Ben launch a new Starlight site in under a minute!', + }, + { + href: 'https://www.youtube.com/watch?v=sF6UcV3moZg', + title: 'Building docs with Starlight and Astro', + description: + 'Watch Chris and Alex dive into Starlight on Code with CodingCat.dev', + }, + { + href: 'https://www.youtube.com/watch?v=sWkkHbwDeQc', + title: 'Astro Starlight', + description: 'Introduction to Starlight in under a minute.', + }, + { + href: 'https://www.youtube.com/watch?v=-Ki-1E5gNCk', + title: 'Astro Starlight Documentation Template (build custom app docs!)', + description: 'Get a new Starlight site up and running in about 5 minutes', + }, + { + href: 'https://www.youtube.com/watch?v=12o7WxjAxjM', + title: 'Include Starlight docs in a Next.js project with proxies', + description: + 'Set up Starlight as a sub-directory project inside a Next.js website', + }, + { + href: 'https://www.youtube.com/watch?v=5pq80drDrNs', + title: "I Recreated Shadcn's Docs In 30 Minutes With This Amazing Tool", + description: + 'In this video I go over what makes Starlight so cool and why you may want to give it a try on your next project.', + }, + { + href: 'https://www.youtube.com/watch?v=Q1E4Gkt63ko', + title: 'Astro Starlight and emoji-blast with Chris Swithinbank', + description: + "Wherein Chris, the creator of Astro's Starlight framework-on-a-framework, walks me through setting it up for a new emoji-blast website. 🌟 🎇", + }, + ]} +/> diff --git a/docs/src/content/docs/resources/plugins.mdx b/docs/src/content/docs/resources/plugins.mdx new file mode 100644 index 00000000000..704606937d7 --- /dev/null +++ b/docs/src/content/docs/resources/plugins.mdx @@ -0,0 +1,305 @@ +--- +title: Plugins and Integrations +description: Discover community tools like plugins and integrations that extend Starlight! +sidebar: + order: 1 +--- + +:::tip[Add your own!] +Have you built a plugin or a tool for Starlight? +Open a PR adding a link to this page! +::: + +## Plugins + +[Plugins](/reference/plugins/) can customize Starlight configuration, UI, and behavior, while also being easy to share and reuse. +Extend your site with official plugins supported by the Starlight team and community plugins maintained by Starlight users. + +### Official plugins + +<CardGrid> + <LinkCard + href="/guides/site-search/#algolia-docsearch" + title="Algolia DocSearch" + description="Replace Pagefind, the default search provider, with Algolia DocSearch." + /> +</CardGrid> + +### Community plugins + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-links-validator" + title="starlight-links-validator" + description="Check for broken links in your Starlight pages." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-typedoc" + title="starlight-typedoc" + description="Generate Starlight pages from TypeScript using TypeDoc." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-blog" + title="starlight-blog" + description="Add a blog to your documentation site." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-openapi" + title="starlight-openapi" + description="Create documentation pages from OpenAPI/Swagger specifications." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-obsidian" + title="starlight-obsidian" + description="Publish Obsidian vaults in your Starlight site." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-image-zoom" + title="starlight-image-zoom" + description="Add zoom capabilities to your documentation images." + /> + <LinkCard + href="https://github.com/lorenzolewis/starlight-utils" + title="starlight-utils" + description="Extend Starlight with a collection of common utilities." + /> + <LinkCard + href="https://github.com/trueberryless/starlight-view-modes" + title="starlight-view-modes" + description="Add different view mode capabilities to your documentation website." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-versions" + title="starlight-versions" + description="Version your Starlight documentation pages." + /> + <LinkCard + href="https://inox-tools.fryuni.dev/star-warp" + title="star-warp" + description="Warp-drive through search results in your documentation." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-heading-badges" + title="starlight-heading-badges" + description="Add badges to your Markdown and MDX headings." + /> + <LinkCard + href="https://github.com/Fevol/starlight-site-graph" + title="starlight-site-graph" + description="Add an interactive site graph inside your page’s sidebar." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-sidebar-topics" + title="starlight-sidebar-topics" + description="Split your documentation into different sections, each with its own sidebar." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-cooler-credit" + title="starlight-cooler-credit" + description="Add a nice credit to Starlight or Astro at the bottom of the table of contents." + /> + <LinkCard + href="https://github.com/dragomano/starlight-giscus" + title="starlight-giscus" + description="Add Giscus comments to your docs site." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-videos" + title="starlight-videos" + description="Enhance your documentation with video guides and courses." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-kbd" + title="starlight-kbd" + description="Document keyboard shortcuts with ease." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-auto-sidebar" + title="starlight-auto-sidebar" + description="Tweak your autogenerated sidebar groups." + /> + <LinkCard + href="https://github.com/delucis/starlight-llms-txt" + title="starlight-llms-txt" + description="Add llms.txt to your documentation site based on llmstxt.org." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-toc-overview-customizer" + title="starlight-toc-overview-customizer" + description="Tweak Starlight’s table of contents with customizable overview title." + /> + <LinkCard + href="https://delucis.github.io/starlight-markdown-blocks/" + title="starlight-markdown-blocks" + description="Extend Starlight’s Markdown asides syntax with custom block types." + /> + <LinkCard + href="https://github.com/WindMillCode/starlight-fullview-mode" + title="starlight-fullview-mode" + description="Collapse sidebars and expand content for a fullscreen experience." + /> + <LinkCard + href="https://github.com/frostybee/starlight-scroll-to-top" + title="starlight-scroll-to-top" + description="Add a scroll-to-top button to your documentation site." + /> + <LinkCard + href="https://github.com/frostybee/starlight-codeblock-fullscreen" + title="starlight-codeblock-fullscreen" + description="Add fullscreen toggle functionality to Expressive Code blocks in your documentation." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-auto-drafts" + title="starlight-auto-drafts" + description="Tweak draft pages default behavior and automatically remove sidebar links to draft pages in production mode." + /> + <LinkCard + href="https://github.com/corsfix/starlight-contextual-menu" + title="starlight-contextual-menu" + description="Add a contextual menu to your Starlight documentation." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-changelogs" + title="starlight-changelogs" + description="Display changelogs alongside your project documentation." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-github-alerts" + title="starlight-github-alerts" + description="Render GitHub alerts as Starlight asides." + /> + <LinkCard + href="https://github.com/dlcastillop/starlight-page-actions" + title="starlight-page-actions" + description="Adds page action buttons to your documentation." + /> + <LinkCard + href="https://github.com/typesense/starlight-docsearch-typesense" + title="starlight-docsearch-typesense" + description="A Typesense-powered alternative to the official Algolia DocSearch plugin." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-swipe/" + title="starlight-sidebar-swipe" + description="Make the left sidebar swipeable on mobile devices like Discord Mobile." + /> + <LinkCard + href="https://github.com/Rettend/starlight-plugin-icons" + title="starlight-plugin-icons" + description="Add icons to Astro Starlight: sidebar, codeblocks, filetree." + /> + <LinkCard + href="https://github.com/dlcastillop/starlight-ui-tweaks" + title="starlight-ui-tweaks" + description="Extends core UI components with custom navigation links, ads, marketing footers, and a cleaner theme toggle." + /> + <LinkCard + href="https://frostybee.github.io/starlight-tags/" + title="starlight-tags" + description="Add tags to your Starlight documentation pages for content organization and discovery." + /> + <LinkCard + href="https://github.com/dionysuzx/starlight-copy-button" + title="starlight-copy-button" + description="Copy full docs page Markdown with a polished button in the page title." + /> + <LinkCard + href="https://frostybee.github.io/starlight-telescope/" + title="starlight-telescope" + description="Quickly navigate to any page in your Starlight docs with fuzzy search and keyboard-first navigation." + /> + <LinkCard + href="https://frostybee.github.io/starlight-announcement/" + title="starlight-announcement" + description="Add enhanced announcement banners with dismissibility, variants, scheduling, and page targeting for your Starlight docs." + /> +</CardGrid> + +## Community tools and integrations + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +These community tools and integrations can be used to add features to your Starlight site. + +<CardGrid> + <LinkCard + href="https://www.feelback.dev/blog/new-astro-starlight-integration/" + title="FeelBack" + description="Add a user feedback system to your docs pages." + /> + <LinkCard + href="https://github.com/val-town/notion-to-astro" + title="notion-to-astro" + description="Convert Notion exports to Astro Starlight docs" + /> + <LinkCard + href="https://github.com/mattjennings/astro-live-code" + title="astro-live-code" + description="Render your MDX code blocks as interactive components" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-i18n" + title="starlight-i18n" + description="Visual Studio Code extension to help translate Starlight pages." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-package-managers" + title="starlight-package-managers" + description="Quickly display npm related commands for multiple package managers." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-showcases" + title="starlight-showcases" + description="Set of Starlight components to author showcase pages." + /> + <LinkCard + href="https://github.com/HiDeoo/generator-starlight-plugin" + title="@hideoo/starlight-plugin" + description="A generator to quickly scaffold Starlight plugins." + /> + <LinkCard + href="https://github.com/Linkerin/starlight-to-pdf" + title="starlight-to-pdf" + description="A CLI tool to convert Starlight websites into PDF files." + /> + <LinkCard + href="https://github.com/joesaby/astro-plantuml" + title="astro-plantuml" + description="Render PlantUML content in Markdown code blocks." + /> + <LinkCard + href="https://github.com/joesaby/astro-mermaid" + title="astro-mermaid" + description="Client-side render Mermaid content in Markdown code blocks." + /> + <LinkCard + href="https://github.com/HiDeoo/astro-d2" + title="astro-d2" + description="Transform D2 Markdown code blocks into diagrams." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-links" + title="starlight-links" + description="Visual Studio Code extension providing IntelliSense for Starlight Markdown and MDX content links." + /> + <LinkCard + href="https://docs.contentisland.net/templates/starlight/" + title="contentisland-cli" + description="Connect and sync your Starlight project to Content Island Headless CMS to edit and manage your documentation." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown" + title="starlight-sidebar-topics-dropdown" + description="Split your docs page into multiple subpages and switch between them with a dropdown menu in the sidebar." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-save-file-component" + title="starlight-save-file-component" + description="Quickly display a link to some download asset on your Starlight site." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-contributor-list" + title="starlight-contributor-list" + description="Display a list of all contributors to your project." + /> +</CardGrid> diff --git a/docs/src/content/docs/resources/showcase.mdx b/docs/src/content/docs/resources/showcase.mdx new file mode 100644 index 00000000000..c155b3632a7 --- /dev/null +++ b/docs/src/content/docs/resources/showcase.mdx @@ -0,0 +1,21 @@ +--- +title: Starlight Showcase +description: Discover sites built with Starlight! +sidebar: + label: Site Showcase +--- + +:::tip[Add your own!] +Have you built a Starlight site? +[Open a PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#showcase) adding a link to this page! +::: + +## Sites + +import ShowcaseSites from '~/components/showcase-sites.astro'; + +Starlight is already being used in production. These are some of the sites around the web: + +<ShowcaseSites /> + +See all the [public project repos using Starlight on GitHub](https://github.com/withastro/starlight/network/dependents). diff --git a/docs/src/content/docs/resources/themes.mdx b/docs/src/content/docs/resources/themes.mdx new file mode 100644 index 00000000000..464b564c056 --- /dev/null +++ b/docs/src/content/docs/resources/themes.mdx @@ -0,0 +1,130 @@ +--- +title: Themes +description: Style your docs with a community theme for Starlight +tableOfContents: false +sidebar: + order: 2 +head: + - tag: style + content: | + body { --sl-content-width: 66.75rem; } +--- + +import ThemeGrid from '~/components/theme-grid.astro'; + +A theme is a Starlight plugin that changes the visual appearance of a site with [custom CSS](/guides/css-and-tailwind/), [component overrides](/guides/overriding-components/), or other new features. + +## Community Themes + +Install a theme built by the community to quickly customize the look and feel of your site. + +Preview a list of all themes below or try them out interactively on the [Starlight Themes demo site](https://starlight-themes.netlify.app/). + +<ThemeGrid + labels={{ + /** Accessible label for the theme toggle. */ + legend: 'Preview', + /** Accessible label for the dark color scheme variant. */ + dark: 'Dark', + /** Accessible label for the light color scheme variant. */ + light: 'Light', + }} + themes={[ + { + title: 'Starlight Rapide', + description: + 'Starlight theme inspired by the Visual Studio Code Vitesse theme.', + href: 'https://starlight-theme-rapide.vercel.app/', + previews: { light: 'rapide-light.png', dark: 'rapide-dark.png' }, + }, + { + title: 'Starlight Obsidian', + description: + 'Starlight theme inspired by the style of Obsidian Publish sites.', + href: 'https://fevol.github.io/starlight-theme-obsidian/', + previews: { light: 'obsidian-light.png', dark: 'obsidian-dark.png' }, + }, + { + title: 'Catppuccin for Starlight', + description: 'Soothing pastel theme for Starlight.', + href: 'https://starlight.catppuccin.com/', + previews: { light: 'catppuccin-light.png', dark: 'catppuccin-dark.png' }, + }, + { + title: 'Ion', + description: 'A sleek, modern theme for Starlight.', + href: 'https://louisescher.github.io/starlight-ion-theme/', + previews: { light: 'ion-light.png', dark: 'ion-dark.png' }, + }, + { + title: 'Starlight Black', + description: 'Starlight theme inspired by shadcn docs.', + href: 'https://starlight-theme-black.vercel.app/', + previews: { light: 'black-light.png', dark: 'black-dark.png' }, + }, + { + title: 'Starlight Flexoki', + description: + 'A warm and friendly theme based on the Flexoki color palette.', + href: 'https://delucis.github.io/starlight-theme-flexoki/', + previews: { light: 'flexoki-light.png', dark: 'flexoki-dark.png' }, + }, + { + title: 'Starlight Nova', + description: 'A modern and beautiful theme for Starlight.', + href: 'https://starlight-theme-nova.pages.dev/', + previews: { light: 'nova-light.png', dark: 'nova-dark.png' }, + }, + { + title: 'Starlight Next.js', + description: 'Starlight theme inspired by the Next.js docs.', + href: 'https://starlight-theme-next.trueberryless.org/', + previews: { light: 'nextjs-light.png', dark: 'nextjs-dark.png' }, + }, + { + title: 'Starlight Galaxy', + description: + 'An Astro Starlight theme tailored for publishing documentation and educational content.', + href: 'https://frostybee.github.io/starlight-theme-galaxy/', + previews: { light: 'galaxy-light.png', dark: 'galaxy-dark.png' }, + }, + { + title: 'Starlight Page', + description: + 'An intuitive, modern Starlight theme with smooth, float-in animations.', + href: 'https://pelagornis-page.netlify.app/', + previews: { light: 'page-light.png', dark: 'page-dark.png' }, + }, + { + title: 'Starlight Gruvbox', + description: 'Retro groove theme for Starlight', + href: 'https://starlight-theme-gruvbox.otterlord.dev/', + previews: { light: 'gruvbox-light.png', dark: 'gruvbox-dark.png' }, + }, + { + title: 'Starlight Six', + description: + 'Clean and modern Astro.js Starlight theme by Six Technology ', + href: 'https://six-tech.github.io/Six.StarlightTheme/', + previews: { light: 'six-light.png', dark: 'six-dark.png' }, + }, + { + title: 'Starlight Vintage', + description: + 'Starlight theme heavily inspired by the timeless design of the legacy Astro documentation.', + href: 'https://starlight-theme-vintage.netlify.app/', + previews: { light: 'vintage-light.png', dark: 'vintage-dark.png' }, + }, + { + title: 'Starlight Rosé Pine', + description: 'Soho vibes for Starlight.', + href: 'https://starlight-theme-rose-pine.trueberryless.org/', + previews: { light: 'rose-pine-light.png', dark: 'rose-pine-dark.png' }, + }, + ]} +/> + +:::tip[Add your own!] +Have you built a Starlight theme? +[Open a PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#themes) adding your theme to this page! +::: diff --git a/docs/src/content/docs/ru/404.md b/docs/src/content/docs/ru/404.md new file mode 100644 index 00000000000..c179fa9c166 --- /dev/null +++ b/docs/src/content/docs/ru/404.md @@ -0,0 +1,14 @@ +--- +title: Не найдено +template: splash +editUrl: false +lastUpdated: false +hero: + title: '404' + tagline: <strong>Хьюстон, у нас проблемы.</strong> Мы не смогли найти эту страницу.<br>Проверьте URL или попробуйте использовать поиск. + actions: + - text: На главную + icon: right-arrow + link: /ru/ + variant: primary +--- diff --git a/docs/src/content/docs/ru/components/asides.mdx b/docs/src/content/docs/ru/components/asides.mdx new file mode 100644 index 00000000000..6792fde6d77 --- /dev/null +++ b/docs/src/content/docs/ru/components/asides.mdx @@ -0,0 +1,194 @@ +--- +title: Вставки +description: Узнайте, как использовать вставки в Starlight для отображения второстепенной информации рядом с основным содержимым страницы. +--- + +import { Aside } from '@astrojs/starlight/components'; + +Для отображения второстепенной информации рядом с основным содержимым страницы используйте компонент `<Aside>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Aside slot="preview"> + Включите несущественную, дополнительную информацию в `<Aside>`. +</Aside> + +</Preview> + +## Импорт + +```tsx +import { Aside } from '@astrojs/starlight/components'; +``` + +## Использование + +Отображайте вставки (также известные как «наставления» или «призывы») с помощью компонента `<Aside>`. + +`<Aside>` может иметь дополнительный атрибут [`type`](#type), который управляет цветом, значком и заголовком по умолчанию. + +<Preview> + +````mdx +import { Aside } from '@astrojs/starlight/components'; + +<Aside>Некоторый контент.</Aside> + +<Aside type="caution">Некоторое предостережение.</Aside> + +<Aside type="tip"> + +Другой контент также поддерживается. + +```js +// Например, фрагмент кода. +``` + +</Aside> + +<Aside type="danger">Никому не сообщайте свой пароль.</Aside> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% aside %} +Некоторый контент. +{% /aside %} + +{% aside type="caution" %} +Некоторое предостережение. +{% /aside %} + +{% aside type="tip" %} +Другой контент также поддерживается. + +```js +// Например, фрагмент кода. +``` +{% /aside %} + +{% aside type="danger" %} +Никому не сообщайте свой пароль. +{% /aside %} +```` + +</Fragment> + +<Fragment slot="preview"> + + <Aside>Некоторый контент.</Aside> + + <Aside type="caution">Некоторое предостережение.</Aside> + + <Aside type="tip"> + + Другой контент также поддерживается. + + ```js + // Например, фрагмент кода. + ``` + + </Aside> + + <Aside type="danger">Никому не сообщайте свой пароль.</Aside> + +</Fragment> + +</Preview> + +Starlight также предоставляет собственный синтаксис для рендеринга в Markdown и MDX в качестве альтернативы компоненту `<Aside>`. +Подробную информацию о пользовательском синтаксисе см. в руководстве [Создание контента в Markdown](/ru/guides/authoring-content/#вставки). + +### Использование пользовательских заголовков + +Переопределяйте стандартные заголовки вставок, используя атрибут [`title`](#title). + +<Preview> + +```mdx 'title="Осторожно!"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="caution" title="Осторожно!"> + Предупреждение *с* пользовательским заголовком. +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'title="Осторожно!"' +{% aside type="caution" title="Осторожно!" %} +Предупреждение *с* пользовательским заголовком. +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="caution" title="Осторожно!"> + Предупреждение *с* пользовательским заголовком. +</Aside> + +</Preview> + +### Использование пользовательских иконок + +Переопределяйте стандартные иконки боковой панели, используя атрибут [`icon`](#icon) с именем одной из [встроенных иконок Starlight](/ru/reference/icons/#все-иконки). + +<Preview> + +```mdx 'icon="starlight"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="tip" icon="starlight"> + Подсказка *с* пользовательской иконкой. +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="starlight"' +{% aside type="tip" icon="starlight" %} +Подсказка *с* пользовательской иконкой. +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="tip" icon="starlight"> + Подсказка *с* пользовательской иконкой. +</Aside> + +</Preview> + +## Параметры `<Aside>` + +**Реализация:** [`Aside.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Aside.astro) + +Компонент `<Aside>` принимает следующие параметры: + +### `type` + +**тип:** `'note' | 'tip' | 'caution' | 'danger'` +**по умолчанию:** `'note'` + +Тип вставки для отображения: + +- `note` (по умолчанию), вставка синего цвета, с информационной иконкой. +- `tip`, вставка фиолетового цвета, с иконкой ракеты. +- `caution`, вставка жёлтого цвета, с треугольной предупреждающей иконкой. +- `danger`, вставка красного цвета, с восьмиугольнаой предупреждающей иконкой. + +### `title` + +**тип:** `string` + +Заголовок вставки для отображения. +Если `title` не установлен, будет использоваться заголовок по умолчанию для текущего `type` вставки. + +### `icon` + +**тип:** [`StarlightIcon`](/ru/reference/icons/#тип-starlighticon) + +Вставка может включать атрибут `icon`, содержащий имя одной из [встроенных иконок Starlight](/ru/reference/icons/#все-иконки). diff --git a/docs/src/content/docs/ru/components/badges.mdx b/docs/src/content/docs/ru/components/badges.mdx new file mode 100644 index 00000000000..cfaacf2db76 --- /dev/null +++ b/docs/src/content/docs/ru/components/badges.mdx @@ -0,0 +1,150 @@ +--- +title: Значки +description: Узнайте, как использовать значки в Starlight для отображения дополнительной информации. +--- + +import { Badge } from '@astrojs/starlight/components'; + +Для отображения небольших фрагментов информации, таких как статус или категория, используйте компонент `<Badge>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Badge slot="preview" text="Новинка" /> + +</Preview> + +## Импорт + +```tsx +import { Badge } from '@astrojs/starlight/components'; +``` + +## Использование + +Отображайте значки с помощью компонента `<Badge>`, с передачей желаемого содержимого через атрибут [`text`](#text). + +По умолчанию значок будет использовать акцентный цвет темы вашего сайта. +Чтобы использовать встроенный цвет значка, установите для атрибута [`variant`](#variant) одно из поддерживаемых значений. + +<Preview> + +```mdx +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="Примечание" variant="note" /> +- <Badge text="Успешно" variant="success" /> +- <Badge text="Совет" variant="tip" /> +- <Badge text="Внимание" variant="caution" /> +- <Badge text="Опасность" variant="danger" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +- {% badge text="Примечание" variant="note" /%} +- {% badge text="Успешно" variant="success" /%} +- {% badge text="Совет" variant="tip" /%} +- {% badge text="Внимание" variant="caution" /%} +- {% badge text="Опасность" variant="danger" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="Примечание" variant="note" /> + - <Badge text="Успешно" variant="success" /> + - <Badge text="Совет" variant="tip" /> + - <Badge text="Внимание" variant="caution" /> + - <Badge text="Опасность" variant="danger" /> +</Fragment> + +</Preview> + +### Использование разных размеров + +Используйте атрибут [`size`](#size) для управления размером текста значка. + +<Preview> + +```mdx /size="\w+"/ +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="Новинки" size="small" /> +- <Badge text="Новинки и улучшения" size="medium" /> +- <Badge text="Новинки, улучшения и другое" size="large" /> +``` + +<Fragment slot="markdoc"> + +```markdoc /size="\w+"/ +- {% badge text="Новинки" size="small" /%} +- {% badge text="Новинки и улучшения" size="medium" /%} +- {% badge text="Новинки, улучшения и другое" size="large" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="Новинки" size="small" /> + - <Badge text="Новинки и улучшения" size="medium" /> + - <Badge text="Новинки, улучшения и другое" size="large" /> +</Fragment> + +</Preview> + +### Настройка значков + +Настраивайте значки, используя другие атрибуты `<span>`, такие как `class` или `style`, с помощью пользовательского CSS. + +<Preview> + +```mdx "style={{ fontStyle: 'italic' }}" +import { Badge } from '@astrojs/starlight/components'; + +<Badge text="Свой текст" variant="success" style={{ fontStyle: 'italic' }} /> +``` + +<Fragment slot="markdoc"> + +```markdoc 'style="font-style: italic;"' +{% badge text="Свой текст" variant="success" style="font-style: italic;" /%} +``` + +</Fragment> + +<Badge + slot="preview" + text="Свой текст" + variant="success" + style={{ fontStyle: 'italic' }} +/> + +</Preview> + +## Параметры `<Badge>` + +**Реализация:** [`Badge.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Badge.astro) + +Компонент `<Badge>` принимает следующие параметры, а также любые [другие атрибуты `<span>`](https://developer.mozilla.org/ru/docs/Web/HTML/Global_attributes): + +### `text` + +**обязательный** +**тип:** `string` + +Текстовое содержимое для отображения в значке. + +### `variant` + +**тип:** `'note' | 'danger' | 'success' | 'caution' | 'tip' | 'default'` +**по умолчанию:** `'default'` + +Вариант цвета значка для использования: `note` (синий), `tip` (фиолетовый), `danger` (красный), `caution` (оранжевый), `success` (зелёный) или `default` (акцентный цвет темы). + +### `size` + +**тип:** `'small' | 'medium' | 'large'` + +Определяет размер отображаемого значка. diff --git a/docs/src/content/docs/ru/components/card-grids.mdx b/docs/src/content/docs/ru/components/card-grids.mdx new file mode 100644 index 00000000000..be59f596f55 --- /dev/null +++ b/docs/src/content/docs/ru/components/card-grids.mdx @@ -0,0 +1,179 @@ +--- +title: Карточные сетки +description: Узнайте, как обернуть несколько карточек в сетку в Starlight. +sidebar: + order: 4 +--- + +import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; + +Чтобы обернуть несколько компонентов [`<Card>`](/ru/components/cards/) или [`<LinkCard>`](/ru/components/link-cards/) в сетку, используйте компонент `<CardGrid>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<CardGrid slot="preview"> + <Card title="Звёзды" icon="star"> + Сириус, Вега, Бетельгейзе + </Card> + <Card title="Луны" icon="moon"> + Ио, Европа, Ганимед + </Card> +</CardGrid> + +</Preview> + +## Импорт + +```tsx +import { CardGrid } from '@astrojs/starlight/components'; +``` + +## Использование + +### Группировка карточек + +Отображайте несколько компонентов [`<Card>`](/ru/components/cards/) рядом друг с другом при наличии свободного места, группируя их с помощью компонента `<CardGrid>`. + +<Preview> + +```mdx {3,10} +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <Card title="Зацените это" icon="open-book"> + Интересный контент, который вы хотите выделить. + </Card> + <Card title="Другая фича" icon="information"> + Дополнительная информация, которой вы хотите поделиться. + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,9} +{% cardgrid %} +{% card title="Зацените это" icon="open-book" %} +Интересный контент, который вы хотите выделить. +{% /card %} + +{% card title="Другая фича" icon="information" %} +Дополнительная информация, которой вы хотите поделиться. +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <Card title="Зацените это" icon="open-book"> + Интересный контент, который вы хотите выделить. + </Card> + <Card title="Другая фича" icon="information"> + Дополнительная информация, которой вы хотите поделиться. + </Card> +</CardGrid> + +</Preview> + +### Группировка карточек-ссылок + +Отображайте несколько компонентов [`<LinkCard>`](/ru/components/link-cards/) рядом друг с другом при наличии свободного места, группируя их с помощью компонента `<CardGrid>`. + +<Preview> + +```mdx {3,6} +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <LinkCard + title="Создание контента в Markdown" + href="/ru/guides/authoring-content/" + /> + <LinkCard title="Компоненты" href="/ru/components/using-components/" /> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,5} +{% cardgrid %} +{% linkcard title="Создание контента в Markdown" href="/ru/guides/authoring-content/" /%} + +{% linkcard title="Компоненты" href="/ru/components/using-components/" /%} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <LinkCard + title="Создание контента в Markdown" + href="/ru/guides/authoring-content/" + /> + <LinkCard title="Компоненты" href="/ru/components/using-components/" /> +</CardGrid> + +</Preview> + +### Смещение карточек + +Сместите второй столбец сетки по вертикали, чтобы добавить визуальный интерес, добавив атрибут [`stagger`](#stagger) к компоненту `<CardGrid>`. + +Этот атрибут полезен на главной странице для отображения ключевых особенностей вашего проекта. + +<Preview> + +```mdx "stagger" +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid stagger> + <Card title="Зацените это" icon="open-book"> + Интересный контент, который вы хотите выделить. + </Card> + <Card title="Другая фича" icon="information"> + Дополнительная информация, которой вы хотите поделиться. + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc "stagger=true" +{% cardgrid stagger=true %} +{% card title="Зацените это" icon="open-book" %} +Интересный контент, который вы хотите выделить. +{% /card %} + +{% card title="Другая фича" icon="information" %} +Дополнительная информация, которой вы хотите поделиться. +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview" stagger> + <Card title="Зацените это" icon="open-book"> + Интересный контент, который вы хотите выделить. + </Card> + <Card title="Другая фича" icon="information"> + Дополнительная информация, которой вы хотите поделиться. + </Card> +</CardGrid> + +</Preview> + +## Параметры `<CardGrid>` + +**Реализация:** [`CardGrid.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/CardGrid.astro) + +Компонент `<CardGrid>` принимает следующие параметры: + +### `stagger` + +**тип:** `boolean` + +Определяет, нужно ли перемешивать карты в сетке или нет. diff --git a/docs/src/content/docs/ru/components/cards.mdx b/docs/src/content/docs/ru/components/cards.mdx new file mode 100644 index 00000000000..e77e1d328ec --- /dev/null +++ b/docs/src/content/docs/ru/components/cards.mdx @@ -0,0 +1,108 @@ +--- +title: Карточки +description: Узнайте, как использовать карточки в Starlight для отображения содержимого в прямоугольных блоках. +sidebar: + order: 2 +--- + +import { Card } from '@astrojs/starlight/components'; + +Для отображения контента в блоке со стилями Starlight используя компонент `<Card>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Card slot="preview" title="Луны" icon="moon"> + Ио, Европа, Ганимед +</Card> + +</Preview> + +## Импорт + +```tsx +import { Card } from '@astrojs/starlight/components'; +``` + +## Использование + +Отображайте карточки с помощью компонента `<Card>`, используя атрибут [`title`](#title) для добавления заголовка. + +<Preview> + +```mdx +import { Card } from '@astrojs/starlight/components'; + +<Card title="Зацените это">Интересный контент, который хочется выделить.</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% card title="Зацените это" %} +Интересный контент, который хочется выделить. +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="Зацените это"> + Интересный контент, который хочется выделить. +</Card> + +</Preview> + +### Добавление иконок + +Включите иконку в карточку, используя атрибут [`icon`](#icon), содержащий имя [одной из встроенных иконок Starlight](/ru/reference/icons/#все-иконки). + +<Preview> + +```mdx 'icon="star"' +import { Card } from '@astrojs/starlight/components'; + +<Card title="Звёзды" icon="star"> + Сириус, Вега, Бетельгейзе +</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="star"' +{% card title="Звёзды" icon="star" %} +Сириус, Вега, Бетельгейзе +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="Звёзды" icon="star"> + Сириус, Вега, Бетельгейзе +</Card> + +</Preview> + +### Группировка карточек + +Отображайте несколько карточек рядом друг с другом при наличии свободного места, группируя их с помощью компонента [`<CardGrid>`](/ru/components/card-grids/). +Пример смотрите в статье [Группировка карточек](/ru/components/card-grids/#группировка-карточек). + +## Параметры `<Card>` + +**Реализация:** [`Card.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Card.astro) + +Компонент `<Card>` принимает следующие параметры: + +### `title` + +**обязательный** +**тип:** `string` + +Заголовок карточки для отображения. + +### `icon` + +**тип:** `string` + +Карточка может содержать атрибут `icon`, содержащий имя [одной из встроенных иконок Starlight](/ru/reference/icons/#все-иконки). diff --git a/docs/src/content/docs/ru/components/code.mdx b/docs/src/content/docs/ru/components/code.mdx new file mode 100644 index 00000000000..6ddf4a050d5 --- /dev/null +++ b/docs/src/content/docs/ru/components/code.mdx @@ -0,0 +1,103 @@ +--- +title: Код +description: Узнайте, как отображать код с подсветкой синтаксиса в Starlight без блоков кода Markdown. +--- + +import { Code } from '@astrojs/starlight/components'; + +Компонент `<Code>` отображает код с подсветкой синтаксиса. +Это полезно, когда использование [блоков кода Markdown](/ru/guides/authoring-content/#блоки-кода) невозможно, например, для отображения данных, поступающих из внешних источников, таких как файлы, базы данных или API. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Code + slot="preview" + code={`## Добро пожаловать + +Привет из **космоса**!`} +lang="md" +title="example.md" +ins={3} +/> + +</Preview> + +## Импорт + +```tsx +import { Code } from '@astrojs/starlight/components'; +``` + +## Использование + +Используйте компонент `<Code>` для отображения кода с подсветкой синтаксиса, например, при отображении кода, полученного из внешних источников. + +См. главу [Компонент кода](https://expressive-code.com/key-features/code-component/) в документации Expressive Code для получения полной информации о параметрах, которые поддерживает `<Code>`. + +<Preview> + +```mdx +import { Code } from '@astrojs/starlight/components'; + +export const exampleCode = `console.log('Это может быть файл или CMS!');`; +export const fileName = 'example.js'; +export const highlights = ['файл', 'CMS']; + +<Code code={exampleCode} lang="js" title={fileName} mark={highlights} /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% code + code="console.log('Это может быть файл или CMS!');" + lang="js" + title="example.js" + meta="'файл' 'CMS'" /%} +``` + +</Fragment> + +export const exampleCode = `console.log('Это может быть файл или CMS!');`; +export const fileName = 'example.js'; +export const highlights = ['файл', 'CMS']; + +<Code + slot="preview" + code={exampleCode} + lang="js" + title={fileName} + mark={highlights} +/> + +</Preview> + +### Отображение импортированного кода + +Используйте [суффикс `?raw`](https://vite.dev/guide/assets#importing-asset-as-string) в MDX-файлах и компонентах Astro, чтобы импортировать любой файл кода в виде строки. +Затем можно передать эту импортированную строку компоненту `<Code>`, чтобы включить её на свою страницу. + +<Preview> + +```mdx "?raw" +# src/content/docs/example.mdx + +import { Code } from '@astrojs/starlight/components'; +import importedCode from '/tsconfig.json?raw'; + +<Code code={importedCode} lang="json" title="tsconfig.json" /> +``` + +import importedCode from '../../../../../../examples/basics/tsconfig.json?raw'; + +<Code slot="preview" code={importedCode} lang="json" title="tsconfig.json" /> + +</Preview> + +## Параметры `<Code>` + +**Реализация:** [`Code.astro`](https://github.com/expressive-code/expressive-code/blob/main/packages/astro-expressive-code/components/Code.astro) + +Компонент `<Code>` принимает все параметры, описанные в документации [Компонент кода](https://expressive-code.com/key-features/code-component/#available-props) Expressive Code. diff --git a/docs/src/content/docs/ru/components/file-tree.mdx b/docs/src/content/docs/ru/components/file-tree.mdx new file mode 100644 index 00000000000..bd7c82b896e --- /dev/null +++ b/docs/src/content/docs/ru/components/file-tree.mdx @@ -0,0 +1,265 @@ +--- +title: Дерево файлов +description: Узнайте, как отобразить структуру каталога с помощью значков файлов и сворачиваемых подкаталогов в Starlight. +--- + +import { FileTree } from '@astrojs/starlight/components'; + +Для отображения структуры каталога с иконками файлов и сворачиваемыми подкаталогами используйте компонент `<FileTree>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<FileTree slot="preview"> + +- astro.config.mjs — **важный** файл +- package.json +- README.md +- src + - components + - **Header.astro** + - … +- pages/ + +</FileTree> + +</Preview> + +## Импорт + +```tsx +import { FileTree } from '@astrojs/starlight/components'; +``` + +## Использование + +Отображайте дерево файлов с иконками файлов и сворачиваемыми подкаталогами с помощью компонента `<FileTree>`. + +Укажите структуру ваших файлов и каталогов с помощью [неупорядоченного списка Markdown](https://www.markdownguide.org/basic-syntax/#unordered-lists) внутри `<FileTree>`. +Создайте подкаталог с помощью вложенного списка или добавьте `/` в конец элемента списка, чтобы отобразить его как каталог без определённого содержимого. + +<Preview> + +```mdx +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% filetree %} +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> + +</Preview> + +### Выделение элементов + +Выделите файл или каталог, сделав его имя жирным, например: `**README.md**`. + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - **Header.astro** + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> + +</Preview> + +### Добавление комментариев + +Добавьте комментарий к файлу или каталогу с помощью дополнительного текста после имени. +В комментариях поддерживается встроенное форматирование Markdown, такое как полужирное и курсивное начертание. + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro — **важный** файл + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - Header.astro — **важный** файл + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro — **важный** файл + - Title.astro + +</FileTree> + +</Preview> + +### Добавление заглушек + +Добавьте заглушки файлов и каталогов, используя в качестве имени либо `...`, либо `_`. +Это может быть полезно для указания читателю, что папка должна содержать больше элементов, не указывая их все в явном виде. + +<Preview> + +```mdx {8} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro + - … + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {5} +{% filetree %} +- src + - components + - Header.astro + - … +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro + - … + +</FileTree> + +</Preview> + +### Экранирование специальных символов + +Экранируйте специальные символы, такие как нижнее подчёркивание или пробелы в именах файлов, заключая имя файла в обратные кавычки. + +<Preview> + +```mdx +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- `__init__.py` +- `Hello world.txt` +- **`READ ME FIRST.md`** + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% filetree %} +- `__init__.py` +- `Hello world.txt` +- **`READ ME FIRST.md`** +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- `__init__.py` +- `Hello world.txt` +- **`READ ME FIRST.md`** + +</FileTree> + +</Preview> + +## Параметры `<FileTree>` + +**Реализация:** [`FileTree.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/FileTree.astro) + +Компонент `<FileTree>` не принимает никаких параметров. diff --git a/docs/src/content/docs/ru/components/icons.mdx b/docs/src/content/docs/ru/components/icons.mdx new file mode 100644 index 00000000000..770dabc20b4 --- /dev/null +++ b/docs/src/content/docs/ru/components/icons.mdx @@ -0,0 +1,128 @@ +--- +title: Иконки +description: Узнайте, как отображать иконки в Starlight. +--- + +import { Icon } from '@astrojs/starlight/components'; + +Для отображения иконок из [встроенного набора Starlight](/ru/reference/icons/#все-иконки) используйте компонент `<Icon>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Icon + slot="preview" + name="open-book" + color="var(--sl-color-text-accent)" + size="4rem" +/> + +</Preview> + +## Импорт + +```tsx +import { Icon } from '@astrojs/starlight/components'; +``` + +## Использование + +Отображайте иконки с помощью компонента `<Icon>`. +Иконка требует указания атрибута [`name`](#name) с именем [одной из встроенных иконок Starlight](/ru/reference/icons/#все-иконки) и по желанию может включать атрибут [`label`](#label), чтобы обеспечить контекст для программ чтения с экрана. + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" /> +<Icon name="starlight" label="Логотип Starlight" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" /%} +{% icon name="starlight" label="Логотип Starlight" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" /> + <Icon name="starlight" label="Логотип Starlight" /> +</Fragment> + +</Preview> + +### Настройка иконок + +Атрибуты [`size`](#size) и [`color`](#color) можно использовать для настройки внешнего вида иконки с помощью единиц CSS и значений цвета. +Атрибут [`class`](#class) можно использовать для добавления пользовательских классов CSS к иконке. + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" color="goldenrod" size="2rem" /> +<Icon name="rocket" color="var(--sl-color-text-accent)" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" color="goldenrod" size="2rem" /%} +{% icon name="rocket" color="var(--sl-color-text-accent)" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" color="goldenrod" size="2rem" /> + <Icon name="rocket" color="var(--sl-color-text-accent)" /> +</Fragment> + +</Preview> + +## Параметры `<Icon>` + +**Реализация:** [`Icon.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Icon.astro) + +Компонент `<Icon>` принимает следующие параметры: + +### `name` + +**обязательный** +**тип:** [`StarlightIcon`](/ru/reference/icons/#тип-starlighticon) + +Имя отображаемой иконки, из набора [встроенных иконок Starlight](/ru/reference/icons/#все-иконки). + +### `label` + +**тип:** `string` + +Необязательная метка, обеспечивающая контекст для вспомогательных технологий, таких как программы чтения с экрана. + +Если `label` не задана, иконка будет полностью скрыта от вспомогательных технологий. +В этом случае убедитесь, что контекст понятен и без иконки. +Например, ссылка, содержащая только иконку, **обязательно** должна содержать атрибут `label`, чтобы быть доступной, но если ссылка содержит текст, а иконка является чисто декоративной, опустить `label` может быть вполне разумно. + +### `size` + +**тип:** `string` + +Размер иконки, заданный с помощью единиц CSS. Например, `2rem`. + +### `color` + +**тип:** `string` + +Цвет иконки с использованием значения цвета CSS. Например, `red`. + +### `class` + +**тип:** `string` + +Пользовательские классы CSS для добавления к иконке. diff --git a/docs/src/content/docs/ru/components/link-buttons.mdx b/docs/src/content/docs/ru/components/link-buttons.mdx new file mode 100644 index 00000000000..9c9b7ef79c0 --- /dev/null +++ b/docs/src/content/docs/ru/components/link-buttons.mdx @@ -0,0 +1,145 @@ +--- +title: Кнопки-ссылки +description: Узнайте, как создавать кнопки-ссылки в Starlight для визуального выделения ссылок, призывающих к действию. +--- + +import { LinkButton } from '@astrojs/starlight/components'; + +Для отображения визуально различимых ссылок, призывающих к действию, используйте компонент `<LinkButton>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkButton slot="preview" href="/ru/getting-started/"> + Прочитайте документацию +</LinkButton> + +</Preview> + +## Импорт + +```tsx +import { LinkButton } from '@astrojs/starlight/components'; +``` + +## Использование + +Используйте компонент `<LinkButton>` для визуального выделения ссылок, призывающих к действию. +Кнопка-ссылка полезна для направления пользователей к наиболее релевантному или действующему контенту и часто используется на целевых страницах. + +`<LinkButton>` требует обязательного заполнения атрибута [`href`](#href). +Кроме того, можно настроить внешний вид кнопки ссылки с помощью атрибута [`variant`](#variant), который может иметь одно из следующих значений: `primary` (по умолчанию), `secondary` или `minimal`. + +<Preview> + +```mdx +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton href="/ru/getting-started/">Первые шаги</LinkButton> +<LinkButton href="/ru/reference/configuration/" variant="secondary"> + Справочник по конфигурации +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkbutton href="/ru/getting-started/" %}Первые шаги{% /linkbutton %} + +{% linkbutton href="/ru/reference/configuration/" variant="secondary" %} +Справочник по конфигурации +{% /linkbutton %} +``` + +</Fragment> + +<Fragment slot="preview"> + <LinkButton href="/ru/getting-started/">Первые шаги</LinkButton> + <LinkButton href="/ru/reference/configuration/" variant="secondary"> + Справочник по конфигурации + </LinkButton> +</Fragment> + +</Preview> + +### Добавление иконок + +Включите иконку в кнопку-ссылку, используя атрибут [`icon`](#icon), содержащий имя [одной из встроенных иконок Starlight](/ru/reference/icons/#все-иконки). + +Атрибут [`iconPlacement`](#iconplacement) можно использовать для размещения иконки перед текстом, задав ему значение `start` (по умолчанию `end`). + +<Preview> + +```mdx {6-7} +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" +> + Похожие: Astro +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc {4-5} +{% linkbutton + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" %} +Похожие: Astro +{% /linkbutton %} +``` + +</Fragment> + +<LinkButton + slot="preview" + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" +> + Похожие: Astro +</LinkButton> + +</Preview> + +## Параметры `<LinkButton>` + +**Реализация:** [`LinkButton.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkButton.astro) + +Компонент `<LinkButton>` принимает следующие параметры, а также любые [другие атрибуты `<a>`](https://developer.mozilla.org/ru/docs/Web/HTML/Element/a): + +### `href` + +**обязательный** +**тип:** `string` + +URL-адрес, на который указывает кнопка-ссылка. + +### `variant` + +**тип:** `'primary' | 'secondary' | 'minimal'` +**по умолчанию:** `'primary'` + +Внешний вид кнопки-ссылки. +Установите значение `primary` для заметной ссылки с призывом к действию, использующей акцентный цвет темы, `secondary` — для менее заметной ссылки, или `minimal` — для ссылки с минимальным оформлением. + +### `icon` + +**тип:** `string` + +Кнопка-ссылка может содержать атрибут `icon` с именем [одной из встроенных иконок Starlight](/ru/reference/icons/#все-иконки). + +### `iconPlacement` + +**тип:** `'start' | 'end'` +**по умолчанию:** `'end'` + +Определяет расположение значка по отношению к тексту кнопки-ссылки. diff --git a/docs/src/content/docs/ru/components/link-cards.mdx b/docs/src/content/docs/ru/components/link-cards.mdx new file mode 100644 index 00000000000..bc72abce28b --- /dev/null +++ b/docs/src/content/docs/ru/components/link-cards.mdx @@ -0,0 +1,128 @@ +--- +title: Карточки-ссылки +description: Узнайте, как отображать ссылки в виде карточек в Starlight. +sidebar: + order: 3 +--- + +import { LinkCard } from '@astrojs/starlight/components'; + +Для создания карточек-ссылок на разные страницы используйте компонент `<LinkCard>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkCard + slot="preview" + title="Кастомизация Starlight" + description="Узнайте, как сделать ваш сайт на Starlight уникальным с помощью пользовательских стилей, шрифтов и многого другого." + href="/ru/guides/customization/" +/> + +</Preview> + +## Импорт + +```tsx +import { LinkCard } from '@astrojs/starlight/components'; +``` + +## Использование + +Отображайте карточку-ссылку с помощью компонента `<LinkCard>`. +Каждый компонент `<LinkCard>` требует использования атрибутов [`title`](#title) и [`href`](#href). + +<Preview> + +```mdx +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard + title="Создание контента в Markdown" + href="/ru/guides/authoring-content/" +/> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkcard title="Создание контента в Markdown" href="/ru/guides/authoring-content/" /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="Создание контента в Markdown" + href="/ru/guides/authoring-content/" +/> + +</Preview> + +### Добавление описания ссылки + +Добавьте краткое описание к карточке-ссылке с помощью атрибута [`description`](#description). + +<Preview> + +```mdx {6} +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard + title="Интернационализация" + href="/ru/guides/i18n/" + description="Настройте Starlight для поддержки нескольких языков." +/> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% linkcard + title="Интернационализация" + href="/ru/guides/i18n/" + description="Настройте Starlight для поддержки нескольких языков." /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="Интернационализация" + href="/ru/guides/i18n/" + description="Настройте Starlight для поддержки нескольких языков." +/> + +</Preview> + +### Группировка карточек-ссылок + +Отображайте несколько карточек-ссылок рядом друг с другом при наличии свободного места, группируя их с помощью компонента [`<CardGrid>`](/ru/components/card-grids/). +См. пример в статье [Группировка карточек](/ru/components/card-grids/#группировка-карточек). + +## Параметры `<LinkCard>` + +**Реализация:** [`LinkCard.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkCard.astro) + +Компонент `<LinkCard>` принимает следующие параметры, а также все остальные атрибуты элементов [`<a>`](https://developer.mozilla.org/ru/docs/Web/HTML/Element/a): + +### `title` + +**обязательный** +**тип:** `string` + +Заголовок карточки-ссылки. + +### `href` + +**обязательный** +**тип:** `string` + +URL-адрес, на который нужно ссылаться при взаимодействии с карточкой. + +### `description` + +**тип:** `string` + +Необязательное описание для отображения под заголовком. diff --git a/docs/src/content/docs/ru/components/steps.mdx b/docs/src/content/docs/ru/components/steps.mdx new file mode 100644 index 00000000000..a7a084379f6 --- /dev/null +++ b/docs/src/content/docs/ru/components/steps.mdx @@ -0,0 +1,120 @@ +--- +title: Шаги +description: Узнайте, как стилизовать нумерованные списки задач для создания пошаговых руководств в Starlight. +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +Для стилизации нумерованного списка задач, при создании пошаговых руководств, используйте компонент `<Steps>`. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Steps slot="preview"> + +1. Создайте новый проект Starlight: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm create astro@latest -- --template starlight + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm create astro --template starlight + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn create astro --template starlight + ``` + + </TabItem> + + </Tabs> + +2. Напишите первую страницу документации. + +</Steps> + +</Preview> + +## Импорт + +```tsx +import { Steps } from '@astrojs/starlight/components'; +``` + +## Использование + +Используйте компонент `<Steps>` для стилизации нумерованных списков задач. +Это удобно для сложных пошаговых руководств, где каждый шаг должен быть чётко выделен. + +Оберните `<Steps>` вокруг стандартного упорядоченного списка Markdown. +Внутри `<Steps>` применим весь обычный синтаксис Markdown. + +<Preview> + +````mdx +import { Steps } from '@astrojs/starlight/components'; + +<Steps> + +1. Импортируйте компонент в свой MDX-файл: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Оберните `<Steps>` вокруг элементов упорядоченного списка. + +</Steps> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% steps %} + +1. Импортируйте компонент в свой MDX-файл: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Оберните `<Steps>` вокруг элементов упорядоченного списка. + +{% /steps %} +```` + +</Fragment> + +<Steps slot="preview"> + +1. Импортируйте компонент в свой MDX-файл: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. Оберните `<Steps>` вокруг элементов упорядоченного списка. + +</Steps> + +</Preview> + +## Параметры `<Steps>` + +**Реализация:** [`Steps.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Steps.astro) + +Компонент `<Steps>` не принимает никаких параметров. diff --git a/docs/src/content/docs/ru/components/tabs.mdx b/docs/src/content/docs/ru/components/tabs.mdx new file mode 100644 index 00000000000..5637a598980 --- /dev/null +++ b/docs/src/content/docs/ru/components/tabs.mdx @@ -0,0 +1,221 @@ +--- +title: Вкладки +description: Узнайте, как создавать интерфейсы с вкладками в Starlight для группировки равнозначной информации. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +Для создания интерфейса с вкладками используйте компоненты `<Tabs>` и `<TabItem>`. +Вкладки полезны для группировки эквивалентной информации, когда пользователю нужно увидеть только один из нескольких вариантов. + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Tabs slot="preview"> + <TabItem label="Звёзды">Сириус, Вега, Бетельгейзе</TabItem> + <TabItem label="Луны">Ио, Европа, Ганимед</TabItem> +</Tabs> + +</Preview> + +## Импорт + +```tsx +import { Tabs, TabItem } from '@astrojs/starlight/components'; +``` + +## Использование + +Создавайте интерфейс с вкладками с помощью компонентов `<Tabs>` и `<TabItem>`. +Каждый компонент `<TabItem>` должен иметь атрибут [`label`](#label) для отображения пользователям. + +<Preview> + +```mdx +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="Звёзды">Сириус, Вега, Бетельгейзе</TabItem> + <TabItem label="Луны">Ио, Европа, Ганимед</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% tabs %} +{% tabitem label="Звёзды" %} +Сириус, Вега, Бетельгейзе +{% /tabitem %} + +{% tabitem label="Луны" %} +Ио, Европа, Ганимед +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="Звёзды">Сириус, Вега, Бетельгейзе</TabItem> + <TabItem label="Луны">Ио, Европа, Ганимед</TabItem> +</Tabs> + +</Preview> + +### Синхронизация вкладок + +Обеспечьте синхронизацию нескольких групп вкладок, добавив атрибут [`syncKey`](#synckey). + +Все `<Tabs>` с одинаковым значением `syncKey` будут отображать одну и ту же активную метку. +Это позволит вашему читателю выбрать один раз (например, операционную систему или менеджер пакетов), и видеть, что их выбор сохраняется при переходе по страницам. + +Чтобы синхронизировать связанные вкладки, добавьте идентичное свойство `syncKey` к каждому компоненту `<Tabs>` и убедитесь, что все они используют одни и те же метки `<TabItem>`: + +<Preview> + +```mdx 'syncKey="constellations"' +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +_Некоторые звёзды:_ + +<Tabs syncKey="constellations"> + <TabItem label="Орион">Беллатрикс, Ригель, Бетельгейзе</TabItem> + <TabItem label="Близнецы">Поллукс, Кастор А, Кастор Б</TabItem> +</Tabs> + +_Некоторые экзопланеты:_ + +<Tabs syncKey="constellations"> + <TabItem label="Орион">HD 34445 b, Gliese 179 b, Wasp-82 b</TabItem> + <TabItem label="Близнецы">Поллукс b, HAT-P-24b, HD 50554 b</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc 'syncKey="constellations"' +_Некоторые звёзды:_ + +{% tabs syncKey="constellations" %} +{% tabitem label="Orion" %} +Беллатрикс, Ригель, Бетельгейзе +{% /tabitem %} + +{% tabitem label="Gemini" %} +Pollux, Castor A, Castor B +{% /tabitem %} +{% /tabs %} + +_Некоторые экзопланеты:_ + +{% tabs syncKey="constellations" %} +{% tabitem label="Orion" %} +HD 34445 b, Gliese 179 b, Wasp-82 b +{% /tabitem %} + +{% tabitem label="Gemini" %} +Pollux b, HAT-P-24b, HD 50554 b +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Fragment slot="preview"> + +_Некоторые звёзды:_ + +<Tabs syncKey="constellations"> + <TabItem label="Орион">Беллатрикс, Ригель, Бетельгейзе</TabItem> + <TabItem label="Близнецы">Поллукс, Кастор А, Кастор Б</TabItem> +</Tabs> + +_Некоторые экзопланеты:_ + +<Tabs syncKey="constellations"> + <TabItem label="Орион">HD 34445 b, Gliese 179 b, Wasp-82 b</TabItem> + <TabItem label="Близнецы">Поллукс b, HAT-P-24b, HD 50554 b</TabItem> +</Tabs> + +</Fragment> + +</Preview> + +### Добавление иконок + +Включите иконку в элемент вкладки, используя атрибут [`icon`](#icon), содержащий имя [одной из встроенных иконок Starlight](/ru/reference/icons/#все-иконки), чтобы отобразить иконку рядом с меткой. + +<Preview> + +```mdx /icon="\w+"/ +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="Звёзды" icon="star"> + Сириус, Вега, Бетельгейзе + </TabItem> + <TabItem label="Луны" icon="moon"> + Ио, Европа, Ганимед + </TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc /icon="\w+"/ +{% tabs %} +{% tabitem label="Звёзды" icon="star" %} +Сириус, Вега, Бетельгейзе +{% /tabitem %} + +{% tabitem label="Луны" icon="moon" %} +Ио, Европа, Ганимед +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="Звёзды" icon="star"> + Сириус, Вега, Бетельгейзе + </TabItem> + <TabItem label="Луны" icon="moon"> + Ио, Европа, Ганимед + </TabItem> +</Tabs> + +</Preview> + +## Параметры `<Tabs>` + +**Реализация:** [`Tabs.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Tabs.astro) + +Компонент `<Tabs>` объединяет несколько компонентов `<TabItem>` и принимает следующие параметры: + +### `syncKey` + +**тип:** `string` + +Ключ, используемый для синхронизации нескольких групп вкладок на нескольких страницах. + +## Параметры `<TabItem>` + +**Реализация:** [`TabItem.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/TabItem.astro) + +Набор вкладок состоит из элементов вкладок, каждый из которых имеет следующие параметры: + +### `label` + +**обязательный** +**тип:** `string` + +Элемент вкладки должен содержать атрибут `label`, содержащий текст, который будет отображаться на вкладке. + +### `icon` + +**тип:** `string` + +Каждый элемент вкладки может включать атрибут `icon` с именем [одной из встроенных иконок Starlight](/ru/reference/icons/#все-иконки), для отображения иконки рядом с меткой. diff --git a/docs/src/content/docs/ru/components/using-components.mdx b/docs/src/content/docs/ru/components/using-components.mdx new file mode 100644 index 00000000000..dcdd658e3d2 --- /dev/null +++ b/docs/src/content/docs/ru/components/using-components.mdx @@ -0,0 +1,94 @@ +--- +title: Использование компонентов +description: Использование компонентов в MDX и Markdoc с помощью Starlight. +sidebar: + order: 1 +--- + +Компоненты позволяют легко и последовательно переиспользовать часть пользовательского интерфейса или стиля. +Примерами могут служить карточки-ссылки или встраиваемые ролики YouTube. +Starlight поддерживает использование компонентов в файлах [MDX](https://mdxjs.com/) и [Markdoc](https://markdoc.dev/), а также предоставляет некоторые общие компоненты для применения. + +[Узнайте больше о создании компонентов в документации Astro](https://docs.astro.build/ru/basics/astro-components/). + +## Использование компонента в MDX + +Вы можете использовать компонент, импортировав его в ваш файл MDX, а затем отобразив его как тег JSX. +Они выглядят как HTML-теги, но начинаются с заглавной буквы, соответствующей имени в вашем операторе `import`: + +```mdx +--- +# src/content/docs/example.mdx +title: Добро пожаловать в мою документацию +--- + +import { Icon } from '@astrojs/starlight/components'; +import CustomCard from '../../components/CustomCard.astro'; + +<Icon name="open-book" /> + +<CustomCard>Компоненты могут содержать **вложенное содержимое**.</CustomCard> +``` + +Поскольку Starlight работает на базе Astro, вы можете использовать в своих файлах MDX любые компоненты, созданные на [поддерживаемом UI-фреймворке (React, Preact, Svelte, Vue, Solid и Alpine)](https://docs.astro.build/ru/guides/framework-components/). +Узнайте больше об [использовании компонентов в MDX](https://docs.astro.build/ru/guides/integrations-guide/mdx/#using-components-in-mdx) в документации Astro. + +## Использование компонента в Markdoc + +Добавьте поддержку создания контента в Markdoc, следуя нашему [руководству по настройке Markdoc](/ru/guides/authoring-content/#markdoc). + +С помощью пресета Starlight Markdoc вы можете использовать встроенные компоненты Starlight с синтаксисом тегов `{% %}` в Markdoc. +В отличие от MDX, компоненты в Markdoc не нужно импортировать. +Следующий пример отображает [компонент карточки](/ru/components/cards/) Starlight в файле Markdoc: + +```markdoc +--- +# src/content/docs/example.mdoc +title: Добро пожаловать в мою документацию +--- + +{% card title="Звёзды" icon="star" %} +Сириус, Вега, Бетельгейзе +{% /card %} +``` + +Дополнительные сведения об использовании компонентов в файлах Markdoc см. в [документация по интеграции Astro Markdoc](https://docs.astro.build/ru/guides/integrations-guide/markdoc/#render-components). + +## Встроенные компоненты + +Starlight предоставляет встроенные компоненты для частых случаев, нужных в документации. +Эти компоненты доступны из пакета `@astrojs/starlight/components` в файлах MDX и из [пресета Starlight Markdoc](/ru/guides/authoring-content/#markdoc) в файлах Markdoc. + +Список доступных компонентов и способы их использования см. на боковой панели. + +## Совместимость со стилями Starlight + +Starlight применяет стандартную стилистику к содержимому Markdown, например, добавляет поля между элементами. +Если эти стили конфликтуют с внешним видом вашего компонента, установите класс `not-content` для своего компонента, чтобы отключить их. + +```astro 'class="not-content"' +--- +// src/components/Example.astro +--- + +<div class="not-content"> + <p>Стилизация содержимого по умолчанию не влияет на Starlight.</p> +</div> +``` + +## Параметры компонента + +Используйте тип [`ComponentProps`](https://docs.astro.build/ru/guides/typescript/#%D1%82%D0%B8%D0%BF-componentprops) из `astro/types` для ссылки на `Props`, принимаемые компонентом, даже если они не экспортируются самим компонентом. +Это может быть полезно при обёртке или расширении существующего компонента. + +В следующем примере используется `ComponentProps` для получения типа параметров, принимаемых встроенным компонентом Starlight `Badge`: + +```astro +--- +// src/components/Example.astro +import type { ComponentProps } from 'astro/types'; +import { Badge } from '@astrojs/starlight/components'; + +type BadgeProps = ComponentProps<typeof Badge>; +--- +``` diff --git a/docs/src/content/docs/ru/environmental-impact.md b/docs/src/content/docs/ru/environmental-impact.md new file mode 100644 index 00000000000..2ea388e4541 --- /dev/null +++ b/docs/src/content/docs/ru/environmental-impact.md @@ -0,0 +1,146 @@ +--- +title: Экологичная документация +description: Узнайте, как Starlight может помочь вам создавать более экологичные сайты документации и сократить ваш углеродный след. +--- + +Оценки влияния интернет-индустрии на климат варьируются от [2%][sf] до [4% глобальных выбросов углерода][bbc], что близко к выбросам авиационной индустрии. +Расчет экологического воздействия веб-сайта включает в себя множество сложных факторов, но в данном руководстве перечислены несколько советов по снижению экологического следа вашего сайта с документацией. + +Хорошая новость в том, что выбор Starlight — отличное начало. +Согласно Website Carbon Calculator, этот сайт [чище, чем 98% протестированных веб-страниц][sl-carbon], производя 0,01 г CO₂ за каждое посещение страницы. + +## Вес страницы + +Чем больше данных передает веб-страница, тем больше энергетических ресурсов она требует. +В апреле 2023 года, медианная веб-страница требовала от пользователя скачать более 2 000 КБ данных, согласно [данным из HTTP Archive][http]. + +Starlight создает страницы лёгкими, настолько, насколько это возможно. +Например, при первом посещении пользователь загрузит менее 50 КБ сжатых данных, что составляет всего 2,5% от медианного значения HTTP архива. +При хорошей стратегии кэширования последующие навигации могут загружать всего 10 КБ. + +### Изображения + +Хоть Starlight и предлагает лёгкие страницы по умолчанию, изображения, которые вы добавляете на страницы документации, могут быстро увеличивать вес вашей страницы. +Starlight использует [оптимизировацию ресурсов][assets] Astro для оптимизации локальных изображений в ваших файлах Markdown и MDX. + +### UI-компоненты + +Компоненты, на UI-фреймворках, как React или Vue, могут легко добавлять большие объемы JavaScript на страницу. +Поскольку Starlight основан на Astro, эти компоненты по умолчанию **не загружают клиентский JavaScript** благодаря [островкам Astro][islands]. + +### Кэширование + +Кэширование управляет тем, как долго браузер хранит и повторно использует данные, которые он уже загрузил. +Хорошая стратегия кэширования гарантирует, что пользователь получает новое содержание как можно быстрее, когда оно меняется, но также избегает бесполезной повторной загрузки одного и того же содержания снова и снова, когда оно не изменилось. + +Самым распространённым способом настройки кэширования является использование [HTTP-заголовка `Cache-Control`][cache]. +При использовании Starlight вы можете установить длительное время кэширования для всего, что находится в каталоге `/_astro/`. +Этот каталог содержит CSS, JavaScript и другие ресурсы, которые можно безопасно кэшировать навсегда, что позволяет снизить избыточные загрузки: + +``` +Cache-Control: public, max-age=604800, immutable +``` + +Как настроить кэширование зависит от вашего веб-хоста. Например, Vercel автоматически применяет эту стратегию кэширования без необходимости настройки, в то же время вы можете установить [заголовки для Netlify][ntl-headers], добавив файл `public/_headers` в ваш проект: + +``` +/_astro/* + Cache-Control: public + Cache-Control: max-age=604800 + Cache-Control: immutable +``` + +[cache]: https://csswizardry.com/2019/03/cache-control-for-civilians/ +[ntl-headers]: https://docs.netlify.com/routing/headers/ + +## Потребление энергии + +То, как реализована веб-страница может влиять на потребление энергии при её запуске на устройстве пользователя. +За счет минимального использования JavaScript, Starlight снижает объем вычислительных ресурсов, необходимых телефону, планшету или компьютеру пользователя для загрузки и отображения страниц. + +Будьте внимательны при добавлении функций, таких как скрипты отслеживания аналитики или контент, зависящий от JavaScript, например, встроенные видео, так как они могут увеличить энергопотребление страницы. +Если вам необходима аналитика, рассмотрите выбор легковесного варианта, такого как [Cabin][cabin], [Fathom][fathom] или [Plausible][plausible]. +Встроенные видео, такие как YouTube и Vimeo, можно улучшить, ожидая [взаимодействие пользователя для загрузки видео][lazy-video]. +Пакеты, такие как [`astro-embed`][embed], могут помочь с часто используемыми сервисами. + +:::tip +Разбор и компиляция JavaScript являются одной из самых ресурсоемких задач, которые браузерам приходится выполнять. +По сравнению с отображением изображения JPEG того же размера, [обработка JavaScript может занять более чем в 30 раз больше времени][cost-of-js]. +::: + +[cabin]: https://withcabin.com/ +[fathom]: https://usefathom.com/ +[plausible]: https://plausible.io/ +[lazy-video]: https://web.dev/iframe-lazy-loading/ +[embed]: https://www.npmjs.com/package/astro-embed +[cost-of-js]: https://medium.com/dev-channel/the-cost-of-javascript-84009f51e99e + +## Хостинг + +Место, где размещена веб-страница, может иметь большое влияние на то, насколько экологичен ваш сайт с документацией. +Дата-центры и серверные фермы могут оказывать значительное экологическое воздействие, включая высокий энергопотребление и интенсивное использование воды. + +Выбор хостинга, использующего возобновляемую энергию, снизит выбросы углерода для вашего сайта. [Справочник Green Web][gwb] — один из инструментов, который может помочь вам найти хостинговые компании, работающие с экологически чистой энергией. + +[gwb]: https://www.thegreenwebfoundation.org/directory/ + +## Сравнения + +Хотите сравнивить другие фреймворки для документации? +Эти тесты с использованием [Website Carbon Calculator][wcc] сравнивают аналогичные страницы, созданные с помощью разных инструментов. + +| Фреймворк | CO₂ на каждое посещение стр. | Рейтинг | +| --------------------------- | ---------------------------- | :-----: | +| [Starlight][sl-carbon] | 0.01g | A+ | +| [Sphinx][sx-carbon] | 0.01g | A+ | +| [Read the Docs][rtd-carbon] | 0.03g | A+ | +| [VitePress][vp-carbon] | 0.04g | A | +| [docsify][dy-carbon] | 0.05g | A | +| [mdBook][md-carbon] | 0.05g | A | +| [Nextra][nx-carbon] | 0.05g | A | +| [MkDocs][mk-carbon] | 0.07g | A | +| [Fumadocs][fs-carbon] | 0.07g | A | +| [Docusaurus][ds-carbon] | 0.10g | B | +| [Docus][dc-carbon] | 0.11g | B | +| [GitBook][gb-carbon] | 0.42g | F | +| [Mintlify][mt-carbon] | 0.48g | F | + +<small>Данные собраны 7 августа 2025 года. Нажмите на ссылку для просмотра актуальной информации.</small> + +[sl-carbon]: https://www.websitecarbon.com/website/starlight-astro-build-getting-started/ +[vp-carbon]: https://www.websitecarbon.com/website/vitepress-dev-guide-what-is-vitepress/ +[dc-carbon]: https://www.websitecarbon.com/website/docus-dev-en-getting-started-project-structure/ +[sx-carbon]: https://www.websitecarbon.com/website/sphinx-doc-org-en-master-usage-quickstart-html/ +[mk-carbon]: https://www.websitecarbon.com/website/mkdocs-org-getting-started/ +[md-carbon]: https://www.websitecarbon.com/website/rust-lang-github-io-mdbook/ +[nx-carbon]: https://www.websitecarbon.com/website/nextra-site-docs-docs-theme-start/ +[fs-carbon]: https://www.websitecarbon.com/website/fumadocs-dev-docs-ui/ +[dy-carbon]: https://www.websitecarbon.com/website/docsify-js-org/ +[ds-carbon]: https://www.websitecarbon.com/website/docusaurus-io-docs/ +[rtd-carbon]: https://www.websitecarbon.com/website/docs-readthedocs-io-en-stable-index-html/ +[gb-carbon]: https://www.websitecarbon.com/website/gitbook-com-docs/ +[mt-carbon]: https://www.websitecarbon.com/website/mintlify-com-docs-quickstart/ + +## Дополнительные ресурсы + +### Инструменты + +- [Website Carbon Calculator][wcc] +- [GreenFrame](https://greenframe.io/) +- [Ecograder](https://ecograder.com/) +- [WebPageTest Carbon Control](https://www.webpagetest.org/carbon-control/) +- [Ecoping](https://ecoping.earth/) + +### Статьи и выступления + +- [Построение более экологичного веба](https://youtu.be/EfPoOt7T5lg), выступление Мишель Баркер +- [Стратегии устойчивого веб-развития в организации](https://www.smashingmagazine.com/2022/10/sustainable-web-development-strategies-organization/), статья Мишель Баркер +- [Экологически устойчивый веб для каждого](https://2021.stateofthebrowser.com/speakers/tom-greenwood/), выступление Тома Гринвуда +- [Как веб-контент может влиять на энергопотребление](https://webkit.org/blog/8970/how-web-content-can-affect-power-usage/), статья Бенджамина Пулена и Саймона Фрейзера. + +[sf]: https://www.sciencefocus.com/science/what-is-the-carbon-footprint-of-the-internet/ +[bbc]: https://www.bbc.com/future/article/20200305-why-your-internet-habits-are-not-as-clean-as-you-think +[http]: https://httparchive.org/reports/state-of-the-web +[assets]: https://docs.astro.build/ru/guides/images/ +[islands]: https://docs.astro.build/ru/concepts/islands/ +[wcc]: https://www.websitecarbon.com/ diff --git a/docs/src/content/docs/ru/getting-started.mdx b/docs/src/content/docs/ru/getting-started.mdx new file mode 100644 index 00000000000..7f3dcd6a644 --- /dev/null +++ b/docs/src/content/docs/ru/getting-started.mdx @@ -0,0 +1,144 @@ +--- +title: Введение +description: Узнайте, как начать создание вашего следующего сайта с документацией с помощью Starlight от Astro. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +Starlight — это полнофункциональная тема для документации, созданная на основе фреймворка [Astro](https://astro.build). +Это руководство поможет вам начать работу над новым проектом. +См. [инструкции по ручной настройке](/ru/manual-setup/), чтобы добавить Starlight в существующий проект Astro. + +## Быстрый старт + +### Создание нового проекта + +Вы можете создать новый проект на базе Astro + Starlight, используя следующую команду: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight +``` + +</TabItem> +</Tabs> + +Это создаст новую [директорию проекта](/ru/guides/project-structure/) со всеми необходимыми файлами и настройками для вашего сайта. + +:::tip[Посмотрите это в действии] +Попробуйте Starlight в вашем браузере: +[откройте шаблон на StackBlitz](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). +::: + +### Запуск сервера разработки + +При локальной работе [сервер разработки Astro](https://docs.astro.build/ru/reference/cli-reference/#astro-dev) позволяет предварительно просмотреть вашу работу и автоматически обновляет ваш браузер при внесении изменений. + +Внутри каталога вашего проекта выполните следующую команду, чтобы запустить сервер разработки: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm run dev +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm dev +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev +``` + +</TabItem> +</Tabs> + +На ваш терминал будет отправлено сообщение с URL-адресом вашего локального предварительного просмотра. +Откройте этот URL-адрес, чтобы начать просмотр вашего сайта. + +### Добавление контента + +Starlight готов к созданию нового контента или к интеграции уже существующих файлов! + +Добавляйте новые страницы на свой сайт, создавая файлы Markdown в каталоге `src/content/docs/`. + +Подробнее о файловой маршрутизации и поддержке файлов MDX и Markdoc читайте в руководстве [Страницы](/ru/guides/pages/). + +### Следующие шаги + +- **Настройка:** Узнайте об общих опциях в главе [Настройка Starlight](/ru/guides/customization/). +- **Навигация:** Настройте боковую панель с помощью руководства [Навигация по боковой панели](/ru/guides/sidebar/). +- **Компоненты:** Узнайте о встроенных карточках, вкладках и многом другом в руководстве [Компоненты](/ru/components/using-components/). +- **Расширение:** Изучите дополнения сообщества в наших каталогах [Плагины](/ru/resources/plugins/) и [Темы](/ru/resources/themes/). +- **Развёртывание:** Опубликуйте свою работу с помощью руководства [Развёртывание вашего сайта](https://docs.astro.build/ru/guides/deploy/) в документации Astro. + +## Обновление Starlight + +:::tip +Поскольку Starlight ещё в статусе beta, будут частые обновления и улучшения. +Не забывайте регулярно обновлять Starlight! +::: + +Starlight является интеграцией Astro и обновляется так же, как любая интеграция @astrojs/\*: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npx @astrojs/upgrade +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm dlx @astrojs/upgrade +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dlx @astrojs/upgrade +``` + +</TabItem> +</Tabs> + +Вы можете увидеть полный список изменений, сделанных в каждом релизе, в [списке изменений Starlight](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md). + +## Устранение проблем со Starlight + +Используйте справочные страницы [конфигурация проекта](/ru/reference/configuration/) и [конфигурация метаданных отдельной страницы](/ru/reference/frontmatter/), чтобы убедиться, что ваш сайт Starlight настроен и работает правильно. +См. руководства на боковой панели, чтобы получить помощь в добавлении контента и настройке вашего сайта Starlight. + +Если вы не можете найти ответ в этой документации, пожалуйста, посетите [полную документацию Astro](https://docs.astro.build/ru/). +На ваш вопрос можно ответить, если вы поймете, как работает Astro в целом в рамках темы Starlight. + +Вы также можете узнать про любые известные [проблемы Starlight на GitHub](https://github.com/withastro/starlight/issues) и получить помощь в +[Discord Astro](https://astro.build/chat/) от нашего активного, дружелюбного сообщества! +Задавайте вопросы на нашем форуме `#support` с тегом "starlight", или посетите наш специальный канал `#starlight`, +чтобы обсудить текущую разработку и многое другое! diff --git a/docs/src/content/docs/ru/guides/authoring-content.mdx b/docs/src/content/docs/ru/guides/authoring-content.mdx new file mode 100644 index 00000000000..b82c403a99f --- /dev/null +++ b/docs/src/content/docs/ru/guides/authoring-content.mdx @@ -0,0 +1,698 @@ +--- +title: Создание контента в Markdown +description: Обзор синтаксиса Markdown, который поддерживается в Starlight. +--- + +Starlight поддерживает весь синтаксис [Markdown](https://daringfireball.net/projects/markdown/) в файлах с расширением `.md`, а также синтаксис [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) для определения метаданных, таких как заголовок и описание. + +Пожалуйста, обратитесь к [документации MDX](https://mdxjs.com/docs/what-is-mdx/#markdown) или [документации Markdoc](https://markdoc.dev/docs/syntax), если вы используете эти форматы файлов, поскольку поддержка и использование Markdown могут отличаться. + +## Метаданные + +Вы можете настроить отдельные страницы в Starlight, установив значения в их заглавной части. +Метаданные устанавливаются в верхней части ваших файлов между разделителями `---`: + +```md title="src/content/docs/example.md" +--- +title: Заголовок страницы +--- + +Содержимое страницы следует за вторым `---`. +``` + +Каждая страница должна включать хотя бы заголовок. +См. [справочник по метаданным](/ru/reference/frontmatter/) для получения информации обо всех доступных полях и о том, как добавлять настраиваемые поля. + +## Встроенные стили + +Текст может быть **жирным**, _курсивом_ или ~~зачёркнутым~~. + +```md +Текст может быть **жирным**, _курсивом_ или ~~зачёркнутым~~. +``` + +Вы можете [ссылаться на другую страницу](/ru/getting-started/). + +```md +Вы можете [ссылаться на другую страницу](/ru/getting-started/). +``` + +Вы можете выделить `код` обратными кавычками. + +```md +Вы можете выделить `код` обратными кавычками. +``` + +## Изображения + +Изображения в Starlight используют [встроенную оптимизацию ресурсов Astro](https://docs.astro.build/ru/guides/images/). + +Markdown и MDX поддерживают синтаксис Markdown для отображения изображений, который включает альтернативный текст для экранных читателей и вспомогательных технологий. + +![Иллюстрация планет и звёзд с надписью "astro"](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) + +```md +![Иллюстрация планет и звёзд с надписью "astro"](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) +``` + +Относительные пути к изображениям также поддерживаются для изображений, хранящихся локально в вашем проекте. + +```md +// src/content/docs/page-1.md + +![Ракета в космосе](../../assets/images/rocket.svg) +``` + +## Заголовки + +Вы можете структурировать контент, используя заголовки. Заголовки в Markdown обозначаются количеством символов `#` в начале строки. + +### Как структурировать контент страницы + +Starlight настроен так, чтобы автоматически использовать заголовок вашей страницы в качестве заголовка верхнего уровня и включать заголовок «Обзор» в начале оглавления каждой страницы. Мы рекомендуем начинать каждую страницу с обычного текстового содержания абзаца и использовать заголовки на странице от `<h2>` и ниже: + +```md +--- +title: Руководство по Markdown +description: Как использовать Markdown в Starlight +--- + +Эта страница описывает, как использовать Markdown в Starlight. + +## Форматирование текста + +## Заголовки +``` + +### Автоматические якорные ссылки для заголовков + +Использование заголовков в Markdown автоматически создает якорные ссылки, позволяя вам ссылаться на определённые разделы вашей страницы: + +```md +--- +title: Моя страница с контентом +description: Как использовать встроенные в Starlight якорные ссылки. +--- + +## Введение + +Я могу создать ссылку на [заключение](#заключение) ниже на этой же странице. + +## Заключение + +`https://my-site.com/page1/#введение` переходит непосредственно к моему Введению. +``` + +Заголовки уровня 2 (`<h2>`) и уровня 3 (`<h3>`) автоматически появятся в оглавлении страницы. + +Узнайте больше о том, как Astro обрабатывает идентификаторы заголовков, в [документации Astro](https://docs.astro.build/ru/guides/markdown-content/#%D0%B8%D0%B4%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D1%80%D1%8B-%D0%B7%D0%B0%D0%B3%D0%BE%D0%BB%D0%BE%D0%B2%D0%BA%D0%BE%D0%B2) + +## Вставки + +Вставки полезны для отображения дополнительной информации рядом с основным контентом страницы. + +Starlight предоставляет специальный синтаксис Markdown для отображения вставок. Вставки должны быть обернуты парой тройных двоеточий `:::` и могут иметь тип `note`, `tip`, `caution` или `danger`. + +Вы можете указывать любые типы контента Markdown внутри вставок, но вставки лучше всего подходят для коротких и лаконичных блоков информации. + +### Вставка «Заметка» + +:::note +Starlight — это инструмент для создания сайтов с документацией, построенный с использованием [Astro](https://astro.build/ru/). Вы можете начать с этой команды: + +```sh +npm create astro@latest -- --template starlight +``` + +::: + +````md +:::note +Starlight — это инструмент для создания сайтов с документацией, построенный с использованием [Astro](https://astro.build/ru/). Вы можете начать с этой команды: + +```sh +npm create astro@latest -- --template starlight +``` + +::: +```` + +### Настраиваемые заголовки вставок + +Вы можете указать свой заголовок вставки в квадратных скобках после типа вставки, например, `:::tip[Небольшой совет]`. + +:::tip[Небольшой совет] +Astro позволяет создавать быстрые сайты с помощью [архитектуры островков](https://docs.astro.build/ru/concepts/islands/) +::: + +```md +:::tip[Небольшой совет] +Astro позволяет создавать быстрые сайты с помощью [архитектуры островков](https://docs.astro.build/ru/concepts/islands/) +::: +``` + +### Пользовательские иконки вставок + +Вы можете указать пользовательскую иконку для вставки в фигурных скобках после типа панели или [пользовательского заголовка](#настраиваемые-заголовки-вставок), например, `:::tip{icon="heart"}` или `:::tip[Знаете ли вы?]{icon="heart"}` соответственно. +В качестве имени должна использоваться одна из [встроенных иконок Starlight](/ru/reference/icons/#все-иконки). + +:::tip{icon="heart"} +Astro помогает создавать более быстрые веб-сайты с помощью [архитектуры островков](https://docs.astro.build/ru/concepts/islands/). +::: + +```md +:::tip{icon="heart"} +Astro помогает создавать более быстрые веб-сайты с помощью [архитектуры островков](https://docs.astro.build/ru/concepts/islands/). +::: +``` + +### Другие типы вставок + +Вставки с типами «caution» и «danger» полезны для привлечения внимания пользователя к деталям, которые могут сбивать с толку. +Если вы часто используете их, это может быть признаком того, что может быть нужно пересмотреть то, что вы документируете. + +:::caution +Если вы не уверены, что хотите отличный сайт с документацией, подумайте дважды, прежде чем использовать [Starlight](/ru/). +::: + +:::danger +Ваши пользователи могут быть более продуктивными и находить ваш продукт более простым в использовании благодаря полезным функциям Starlight. + +- Чёткая навигация +- Цветовая тема, настраиваемая пользователем +- [Поддержка i18n](/ru/guides/i18n/) + +::: + +```md +:::caution +Если вы не уверены, что хотите отличный сайт с документацией, подумайте дважды, прежде чем использовать [Starlight](/ru/). +::: + +:::danger +Ваши пользователи могут быть более продуктивными и находить ваш продукт более простым в использовании благодаря полезным функциям Starlight. + +- Чёткая навигация +- Цветовая тема, настраиваемая пользователем +- [Поддержка i18n](/ru/guides/i18n/) + +::: +``` + +## Цитаты + +> Это цитата, которую обычно используют при цитировании другого человека или документа. +> +> Цитаты обозначаются символом `>` в начале каждой строки. + +```md +> Это цитата, которую обычно используют при цитировании другого человека или документа. +> +> Цитаты обозначаются символом `>` в начале каждой строки. +``` + +## Блоки кода + +Блок кода обозначается блоком с тремя обратными апострофами <code>```</code> в начале и в конце. Вы можете указать язык программирования после открывающих апострофов. + +```js +// Javascript код с подсветкой синтаксиса. +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` + +````md +```js +// Javascript код с подсветкой синтаксиса. +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` +```` + +### Возможности Expressive Code + +Starlight использует [Expressive Code](https://expressive-code.com/) для расширения возможностей форматирования блоков кода. +Текстовые маркеры и плагины оконных рамок Expressive Code включены по умолчанию. +Рендеринг блоков кода можно настроить с помощью [параметра конфигурации `expressiveCode`](/ru/reference/configuration/#expressivecode) Starlight. + +#### Текстовые маркеры + +Вы можете выделить определённые строки или части блоков кода с помощью [текстовых маркеров Expressive Code](https://expressive-code.com/key-features/text-markers/) в первой строке вашего блока кода. +Используйте фигурные скобки (`{ }`), чтобы выделить целые строки, и кавычки, чтобы выделить строки текста. + +Существует три стиля выделения: нейтральный для привлечения внимания к коду, зелёный для обозначения вставленного кода и красный для обозначения удалённого кода. +И текст, и целые строки можно пометить с помощью маркера по умолчанию или в сочетании с `ins=` и `del=` для получения желаемого выделения. + +Expressive Code предоставляет несколько вариантов настройки внешнего вида примеров кода. +Многие из них можно комбинировать для получения наглядных примеров кода. +Ознакомьтесь с [документацией Expressive Code](https://expressive-code.com/key-features/text-markers/#configuration), чтобы узнать о расширенных возможностях. доступный. +Некоторые из наиболее распространённых примеров показаны ниже: + +- [Пометка целых строк и диапазонов строк с помощью маркера `{ }`](https://expressive-code.com/key-features/text-markers/#marking-full-lines--line-ranges): + + ```js {2-3} + function demo() { + // Эта строка (#2) и следующая выделены + return 'Это строка №3 этого фрагмента'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js {2-3} + function demo() { + // Эта строка (#2) и следующая выделены + return 'Это строка №3 этого фрагмента'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="{2-3}" %} + function demo() { + // Эта строка (#2) и следующая выделены + return 'Это строка №3 этого фрагмента'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [Пометка выделенного текста с помощью маркера `" "` или регулярных выражений](https://expressive-code.com/key-features/text-markers/#marking-individual-text-inside-lines): + + ```js "Отдельные термины" /даже.*выражения/ + // Отдельные термины также могут быть выделены + function demo() { + return 'Поддерживаются даже регулярные выражения'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "Отдельные термины" /даже.*выражения/ + // Отдельные термины также могут быть выделены + function demo() { + return 'Поддерживаются даже регулярные выражения'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'Отдельные термины' /даже.*выражения/" %} + // Отдельные термины также могут быть выделены + function demo() { + return 'Поддерживаются даже регулярные выражения'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [Пометка текста или строк как вставленных или удалённых с помощью `ins` или `del`](https://expressive-code.com/key-features/text-markers/#selecting-inline-marker-types-mark-ins-del): + + ```js "return true;" ins="вставленные" del="удалённые" + function demo() { + console.log('Это вставленные и удалённые типы маркеров'); + // Оператор return использует тип маркера по умолчанию + return true; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "return true;" ins="вставленные" del="удалённые" + function demo() { + console.log('Это вставленные и удалённые типы маркеров'); + // Оператор return использует тип маркера по умолчанию + return true; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'return true;' ins='вставленные' del='удалённые'" %} + function demo() { + console.log('Это вставленные и удалённые типы маркеров'); + // Оператор return использует тип маркера по умолчанию + return true; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [Объединение подсветки синтаксиса с синтаксисом типа `diff`](https://expressive-code.com/key-features/text-markers/#combining-syntax-highlighting-with-diff-like-syntax): + + ```diff lang="js" + function thisIsJavaScript() { + // Весь этот блок выделяется как JavaScript, + // и мы можем добавить к нему маркеры различий! + - console.log('Старый код, который нужно удалить') + + console.log('Новый и блестящий код!') + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```diff lang="js" + function thisIsJavaScript() { + // Весь этот блок выделяется как JavaScript, + // и мы можем добавить к нему маркеры различий! + - console.log('Устаревший код, который нужно удалить') + + console.log('Обновлённый и крутой код!') + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```diff {% meta="lang='js'" %} + function thisIsJavaScript() { + // Весь этот блок выделяется как JavaScript, + // и мы можем добавить к нему маркеры различий! + - console.log('Устаревший код, который нужно удалить') + + console.log('Обновлённый и крутой код!') + } + ``` + ```` + + </TabItem> + + </Tabs> + +#### Рамки и заголовки + +Блоки кода могут отображаться внутри оконного фрейма. +Рамка, похожая на окно терминала, будет использоваться для языков сценариев оболочки (например, `bash` или `sh`). +Другие языки отображаются внутри рамки в стиле редактора кода, если они включают заголовок. + +Необязательный заголовок блока кода может быть установлен либо с помощью атрибута `title="..."` после открывающих обратных кавычек блока кода и идентификатора языка, либо с помощью комментария к имени файла в первых строках кода. + +- [Добавление вкладки имени файла с помощью комментария](https://expressive-code.com/key-features/frames/#code-editor-frames) + + ```js + // my-test-file.js + console.log('Привет, мир!'); + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js + // my-test-file.js + console.log('Привет, мир!'); + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````md + ```js + // my-test-file.js + console.log('Привет, мир!'); + ``` + ```` + + </TabItem> + + </Tabs> + +- [Добавление заголовка в окне терминала](https://expressive-code.com/key-features/frames/#terminal-frames) + + ```bash title="Установка зависимостей…" + npm install + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash title="Установка зависимостей…" + npm install + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% title="Установка зависимостей…" %} + npm install + ``` + ```` + + </TabItem> + + </Tabs> + +- [Отключение оконных рамок с помощью `frame="none"`](https://expressive-code.com/key-features/frames/#overriding-frame-types) + + ```bash frame="none" + echo "Это не отображается как терминал, несмотря на использование языка bash" + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash frame="none" + echo "Это не отображается как терминал, несмотря на использование языка bash" + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% frame="none" %} + echo "Это не отображается как терминал, несмотря на использование языка bash" + ``` + ```` + + </TabItem> + + </Tabs> + +## Спойлеры + +Спойлеры (также известные как «раскрытия» или «аккордеоны») полезны для того, чтобы скрыть содержимое, которое не имеет непосредственного отношения к делу. +Пользователи могут нажать на краткое содержание, чтобы развернуть его и просмотреть полный текст. + +Используйте стандартные элементы HTML [`<details>`](https://developer.mozilla.org/ru/docs/Web/HTML/Element/details) и [`<summary>`](https://developer.mozilla.org/ru/docs/Web/HTML/Element/summary) в вашем Markdown-контенте, чтобы создать виджет раскрытия информации. + +Внутри элемента `<details>` можно использовать любой другой синтаксис Markdown. + +<details> +<summary>Где и когда созвездие Андромеды видно лучше всего?</summary> + +[Созвездие Андромеды](<https://ru.wikipedia.org/wiki/%D0%90%D0%BD%D0%B4%D1%80%D0%BE%D0%BC%D0%B5%D0%B4%D0%B0_(%D1%81%D0%BE%D0%B7%D0%B2%D0%B5%D0%B7%D0%B4%D0%B8%D0%B5)>) наиболее заметно на ночном небе в ноябре на широтах от `+90°` до `-40°`. + +</details> + +```md +<details> +<summary>Где и когда созвездие Андромеды видно лучше всего?</summary> + +[Созвездие Андромеды](<https://ru.wikipedia.org/wiki/%D0%90%D0%BD%D0%B4%D1%80%D0%BE%D0%BC%D0%B5%D0%B4%D0%B0_(%D1%81%D0%BE%D0%B7%D0%B2%D0%B5%D0%B7%D0%B4%D0%B8%D0%B5)>) наиболее заметно на ночном небе в ноябре на широтах от `+90°` до `-40°`. + +</details> +``` + +## Сноски + +[Сноски](https://www.markdownguide.org/extended-syntax/#footnotes) полезны для добавления кратких ссылок или пояснений, не прерывая поток вашего контента. Они отображаются как нумерованные надстрочные ссылки, которые ведут к тексту сносок, собранному внизу страницы. + +Определите сноску с помощью квадратных скобок с символом вставки (^) и нумерованной ссылкой: + +```md +Здесь есть сноска[^1] с некоторым дополнительным текстом после неё. + +[^1]: Моя ссылка. +``` + +## Другие возможности Markdown + +Starlight поддерживает все синтаксические возможности Markdown, такие как списки и таблицы. Посмотрите [шпаргалку по Markdown от The Markdown Guide](https://www.markdownguide.org/cheat-sheet/) для изучения всех возможностей синтаксиса Markdown. + +## Расширенная конфигурация Markdown и MDX + +Starlight использует Markdown и рендерер MDX от Astro, основанный на `remark` и `rehype`. Вы можете добавить поддержку пользовательского синтаксиса и поведения, добавив `remarkPlugins` или `rehypePlugins` в свой файл конфигурации Astro. Дополнительную информацию см. в статье [Плагины Markdown](https://docs.astro.build/ru/guides/markdown-content/#%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D1%8B-markdown) в документации Astro. + +## Markdoc + +Starlight поддерживает создание контента в Markdoc с помощью экспериментальной [интеграции с Astro](https://docs.astro.build/ru/guides/integrations-guide/markdoc/) и пресета Starlight Markdoc. + +### Создание нового проекта с Markdoc + +Начните новый проект Starlight с предварительно настроенным Markdoc с помощью команды `create astro`: + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight/markdoc +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight/markdoc +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight/markdoc +``` + +</TabItem> +</Tabs> + +### Добавление Markdoc в существующий проект + +Если у вас уже есть сайт Starlight и вы хотите добавить Markdoc, выполните следующие действия. + +<Steps> + +1. Добавьте интеграцию Markdoc: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npx astro add markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm astro add markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn astro add markdoc + ``` + + </TabItem> + + </Tabs> + +2. Установите пресет Markdoc для Starlight: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-markdoc + ``` + + </TabItem> + + </Tabs> + +3. Создайте файл конфигурации Markdoc по адресу `markdoc.config.mjs` и используйте пресет Markdoc: + + ```js + import { defineMarkdocConfig } from '@astrojs/markdoc/config'; + import starlightMarkdoc from '@astrojs/starlight-markdoc'; + + export default defineMarkdocConfig({ + extends: [starlightMarkdoc()], + }); + ``` + +</Steps> + +Чтобы узнать больше о синтаксисе и возможностях Markdoc, смотрите [документацию](https://markdoc.dev/docs/syntax) или [Руководство по интеграции Markdoc в Astro](https://docs.astro.build/ru/guides/integrations-guide/markdoc/). + +### Настройка пресета Markdoc + +Пресет `starlightMarkdoc()` принимает следующие параметры конфигурации: + +#### `headingLinks` + +**тип:** `boolean` +**по умолчанию:** `true` + +Определяет, будут ли заголовки отображаться с кликабельной ссылкой-якорем. +Эквивалентно опции [`markdown.headingLinks`](/ru/reference/configuration/#markdown), которая применяется к файлам Markdown и MDX. + +```js "headingLinks: false" +export default defineMarkdocConfig({ + // Отключение поддержки ссылок-якорей для заголовков по умолчанию + extends: [starlightMarkdoc({ headingLinks: false })], +}); +``` diff --git a/docs/src/content/docs/ru/guides/css-and-tailwind.mdx b/docs/src/content/docs/ru/guides/css-and-tailwind.mdx new file mode 100644 index 00000000000..aab95e45352 --- /dev/null +++ b/docs/src/content/docs/ru/guides/css-and-tailwind.mdx @@ -0,0 +1,348 @@ +--- +title: CSS и стилизация +description: Узнайте, как стилизовать ваш сайт Starlight с помощью CSS-файлов или интегрировать с Tailwind CSS. +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +Вы можете стилизовать ваш сайт Starlight с помощью CSS-файлов или использовать плагин Starlight Tailwind. + +Для быстрого изменения стандартного стиля вашего сайта ознакомьтесь с [темами от сообщества](/ru/resources/themes/). + +## Ваши CSS стили + +Настройте стили, применяемые к вашему сайту Starlight, предоставив дополнительные CSS-файлы для изменения или расширения стандартных стилей Starlight. + +<Steps> + +1. Добавьте CSS-файл в ваш каталог `src/`. + Например, вы можете установить большую ширину колонки по умолчанию и бóльший размер текста для заголовков страниц: + + ```css + /* src/styles/custom.css */ + :root { + --sl-content-width: 50rem; + --sl-text-5xl: 3.5rem; + } + ``` + +2. Добавьте путь к вашему CSS-файлу в массив `customCss` Starlight в `astro.config.mjs`: + + ```js + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Документация с изменёнными CSS-стилями', + customCss: [ + // Относительный путь к вашему CSS файлу + './src/styles/custom.css', + ], + }), + ], + }); + ``` + +</Steps> + +Вы можете увидеть все кастомные свойства CSS, используемые Starlight, которые вы можете установить для настройки вашего сайта, в [файле `props.css` на GitHub](https://github.com/withastro/starlight/blob/main/packages/starlight/style/props.css). + +### Каскадные слои + +Starlight использует [каскадные слои](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers) внутри для управления порядком своих стилей. +Это обеспечивает предсказуемый порядок CSS и упрощает переопределение стилей. +Любые пользовательские CSS-стили без слоёв переопределят стандартные стили Starlight. + +Если вы используете каскадные слои, вы можете применить [`@layer`](https://developer.mozilla.org/ru/docs/Web/CSS/@layer) в вашем пользовательском CSS для определения порядка приоритета различных слоёв относительно стилей из слоя `starlight`: + +```css "starlight" +/* src/styles/custom.css */ +@layer my-reset, starlight, my-overrides; +``` + +Пример выше определяет пользовательский слой `my-reset`, применяемый перед всеми слоями Starlight, и другой слой `my-overrides`, применяемый после всех слоёв Starlight. +Любые стили в слое `my-overrides` будут иметь приоритет над стилями Starlight, но Starlight всё ещё сможет изменять стили, установленные в слое `my-reset`. + +## Tailwind CSS + +Поддержка Tailwind CSS v4 в проектах Astro обеспечивается [плагином Tailwind Vite](https://tailwindcss.com/docs/installation/using-vite). +Starlight предоставляет дополнительный CSS для настройки Tailwind, обеспечивающий совместимость со стилями Starlight. + +CSS Tailwind от Starlight применяет следующую конфигурацию: + +- Настраивает `dark:` варианты Tailwind для работы с тёмным режимом Starlight. +- Использует [цвета и шрифты темы Tailwind](#стилизация-starlight-с-использованием-tailwind) в пользовательском интерфейсе Starlight. +- Восстанавливает основные части стилей сброса Preflight от Tailwind. + +### Создание нового проекта с Tailwind + +Создайте новый проект Starlight с предварительно настроенным Tailwind CSS, используя `create astro`: + + <Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight/tailwind +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight/tailwind +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight/tailwind +``` + +</TabItem> +</Tabs> + +### Добавление Tailwind в существующий проект + +Если у вас уже есть сайт на Starlight и вы хотите добавить Tailwind CSS, следуйте этим шагам. + +<Steps> + +1. Настройте Tailwind в вашем проекте, выполнив следующую команду и следуя инструкциям в терминале: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npx astro add tailwind + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm astro add tailwind + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn astro add tailwind + ``` + + </TabItem> + + </Tabs> + +2. Установите пакет совместимости Tailwind для Starlight: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-tailwind + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-tailwind + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-tailwind + ``` + + </TabItem> + + </Tabs> + +3. Замените содержимое файла `src/styles/global.css`, созданного Astro, для обеспечения совместимости со Starlight: + + ```css + /* src/styles/global.css */ + @layer base, starlight, theme, components, utilities; + + @import '@astrojs/starlight-tailwind'; + @import 'tailwindcss/theme.css' layer(theme); + @import 'tailwindcss/utilities.css' layer(utilities); + ``` + + Эта конфигурация темы Tailwind определяет порядок [каскадных слоев](#каскадные-слои) Starlight, импортирует дополнительные стили Tailwind от Starlight, а также стили темы и утилиты Tailwind. + Если вашему проекту требуется дополнительная конфигурация Tailwind, ознакомьтесь с разделом [Использование нескольких конфигураций Tailwind](#использование-нескольких-конфигураций-tailwind). + +4. Обновите конфигурацию Starlight, добавив файл Tailwind CSS как первый элемент массива `customCss`: + + ```js ins={11-12} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import tailwindcss from '@tailwindcss/vite'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Docs with Tailwind', + customCss: [ + // Путь к базовым стилям Tailwind: + './src/styles/global.css', + ], + }), + ], + vite: { plugins: [tailwindcss()] }, + }); + ``` + +</Steps> + +### Стилизация Starlight с использованием Tailwind + +При [создании нового проекта Starlight с Tailwind](#создание-нового-проекта-с-tailwind) или при [добавлении Tailwind в существующий проект Starlight](#добавление-tailwind-в-существующий-проект), Starlight будет использовать значения из вашей [конфигурации темы Tailwind](https://tailwindcss.com/docs/theme), расположенной в файле `src/styles/global.css`, для стилизации своего пользовательского интерфейса. + +Если установлены, следующие пользовательские свойства CSS переопределят стили Starlight по умолчанию: + +- `--color-accent-*` — используется для ссылок и выделения текущего элемента; +- `--color-gray-*` — используется для цветов фона и границ; +- `--font-sans` — используется для текста в интерфейсе и контента; +- `--font-mono` — используется для примеров кода. + +```css {9,11,13,25} +/* src/styles/global.css */ +@layer base, starlight, theme, components, utilities; + +@import '@astrojs/starlight-tailwind'; +@import 'tailwindcss/theme.css' layer(theme); +@import 'tailwindcss/utilities.css' layer(utilities); + +@theme { + /* Предпочитаемый шрифт для текста. По умолчанию Starlight использует системный стек шрифтов. */ + --font-sans: 'Atkinson Hyperlegible'; + /* Предпочитаемый шрифт для кода. По умолчанию Starlight использует системные моноширинные шрифты. */ + --font-mono: 'IBM Plex Mono'; + /* Предпочитаемый акцентный цвет. Indigo наиболее близок к цветам по умолчанию в Starlight. */ + --color-accent-50: var(--color-indigo-50); + --color-accent-100: var(--color-indigo-100); + --color-accent-200: var(--color-indigo-200); + --color-accent-300: var(--color-indigo-300); + --color-accent-400: var(--color-indigo-400); + --color-accent-500: var(--color-indigo-500); + --color-accent-600: var(--color-indigo-600); + --color-accent-700: var(--color-indigo-700); + --color-accent-800: var(--color-indigo-800); + --color-accent-900: var(--color-indigo-900); + --color-accent-950: var(--color-indigo-950); + /* Предпочитаемая серая палитра. Zinc наиболее близок к значениям по умолчанию в Starlight. */ + --color-gray-50: var(--color-zinc-50); + --color-gray-100: var(--color-zinc-100); + --color-gray-200: var(--color-zinc-200); + --color-gray-300: var(--color-zinc-300); + --color-gray-400: var(--color-zinc-400); + --color-gray-500: var(--color-zinc-500); + --color-gray-600: var(--color-zinc-600); + --color-gray-700: var(--color-zinc-700); + --color-gray-800: var(--color-zinc-800); + --color-gray-900: var(--color-zinc-900); + --color-gray-950: var(--color-zinc-950); +} +``` + +### Использование нескольких конфигураций Tailwind + +Несколько конфигураций Tailwind могут быть использованы для применения различных стилей к разным частям вашего сайта, например, при [использовании Starlight с подкаталогами](/ru/manual-setup/#использование-starlight-с-подкаталогами) или при добавлении [пользовательских страниц](/ru/guides/pages/#пользовательские-страницы) на ваш сайт. +Например, вы можете захотеть использовать стили сброса Preflight от Tailwind на пользовательских страницах, сохраняя при этом слой совместимости Starlight для страниц Starlight. + +Следующая конфигурация Tailwind CSS настраивает Tailwind без каких-либо плагинов или дополнительной конфигурации и может использоваться как отправная точка для страниц, не относящихся к Starlight: + +```css title="src/styles/custom-pages-tailwind.css" +/* Загрузка Tailwind без дополнительных стилей от Starlight. */ +@import 'tailwindcss'; +``` + +<Steps> + +1. Для страниц Starlight примените предпочитаемую конфигурацию Tailwind CSS, следуя инструкциям из раздела [Добавление Tailwind в существующий проект](#добавление-tailwind-в-существующий-проект). + +2. Для других страниц примените предпочитаемую конфигурацию Tailwind CSS, импортируя её на этих страницах. Это часто делается в компоненте макета, чтобы стили Tailwind могли использоваться на всех страницах, использующих этот макет. + ```astro + --- + // src/layouts/CustomPageLayout.astro + import '../styles/custom-pages-tailwind.css'; + --- + ``` + +</Steps> + +Чтобы узнать больше о конфигурациях тем Tailwind, ознакомьтесь с [документацией Tailwind CSS](https://tailwindcss.com/docs/theme). + +## Темизация + +Цветовая тема Starlight может быть настроена путем переопределения её стандартных кастомных свойств. +Эти переменные используются по всему интерфейсу, причём различные оттенки серого используются для текста и цветов фона, а акцентный цвет используется для ссылок и выделения текущих элементов в навигации. + +### Редактор цветовой темы + +Используйте ползунки ниже, чтобы изменить палитры акцентного и серого цветов Starlight. +Тёмные и светлые области предпросмотра будут показывать результирующие цвета, и вся страница также обновится, чтобы показать ваши изменения. + +Используйте параметр «Уровень контрастности», чтобы указать, какому из [стандартов цветовой контрастности](https://developer.mozilla.org/ru/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast) должен соответствовать веб-контент. + +Когда вы будете довольны внесёнными изменениями, скопируйте приведённый ниже код CSS или Tailwind и используйте его в своем проекте. + +import ThemeDesigner from '~/components/theme-designer.astro'; + +<ThemeDesigner + labels={{ + presets: { + label: 'Заготовки', + ocean: 'Океан', + forest: 'Лес', + oxide: 'Оксид', + nebula: 'Туман', + default: 'По умолчанию', + random: 'Случайно', + }, + contrast: { + label: 'Уровень контрастности', + }, + editor: { + accentColor: 'Акцентный цвет', + grayColor: 'Серый', + hue: 'Оттенок', + chroma: 'Интенсивность ', + pickColor: 'Выбор цвета', + }, + preview: { + darkMode: 'Тёмный режим', + lightMode: 'Светлый режим', + bodyText: + 'Основной текст отображается в оттенке серого с высоким контрастом по отношению к фону.', + linkText: 'Ссылки выделены цветом.', + dimText: 'Некоторый текст, например, оглавление, имеет меньший контраст.', + inlineCode: 'Встроенный код имеет выделенный фон.', + }, + }} +> + <Fragment slot="css-docs"> + Добавьте следующий CSS в ваш проект в [пользовательском + CSS-файле](#ваши-css-стили), чтобы применить эту тему к вашему сайту. + </Fragment> + <Fragment slot="tailwind-docs"> + Добавьте следующие CSS-переменные в блок `@theme` вашего [файла Tailwind + CSS](#стилизация-starlight-с-использованием-tailwind), чтобы применить эту + тему к вашему сайту. + </Fragment> +</ThemeDesigner> diff --git a/docs/src/content/docs/ru/guides/customization.mdx b/docs/src/content/docs/ru/guides/customization.mdx new file mode 100644 index 00000000000..401f92d0377 --- /dev/null +++ b/docs/src/content/docs/ru/guides/customization.mdx @@ -0,0 +1,474 @@ +--- +title: Кастомизация Starlight +description: Узнайте, как сделать ваш сайт на Starlight уникальным с вашим логотипом, шрифтами, дизайном главной страницы и многим другим. +--- + +import { Tabs, TabItem, FileTree, Steps } from '@astrojs/starlight/components'; + +Starlight предоставляет осмысленные стили и функции по умолчанию, так что вы можете быстро начать работу без необходимости конфигурации. +Когда вы захотите начать настройку внешнего вида вашего сайта на Starlight, это руководство поможет вам в этом. + +## Добавление своего логотипа + +Добавление логотипа в заголовок сайта - это быстрый способ добавить индивидуальность на ваш сайт Starlight. + +<Steps> + +1. Добавьте изображение вашего логотипа в директорию `src/assets/`: + + <FileTree> + + - src/ + - assets/ + - **my-logo.svg** + - content/ + - astro.config.mjs + + </FileTree> + +2. Укажите путь к вашему логотипу у параметра [`logo.src`](/ru/reference/configuration/#logo) в `astro.config.mjs`: + + ```diff lang="js" + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Документация с моим логотипом', + logo: { + + src: './src/assets/my-logo.svg', + }, + }), + ], + }); + ``` + +</Steps> + +По умолчанию логотип будет отображаться рядом с `title` вашего сайта. +Если ваше изображение логотипа уже включает в себя название сайта, вы можете визуально скрыть текст заголовка, через параметр `replacesTitle`. +Текст `title` всё равно будет доступен для экранных читалок, чтобы заголовок оставался доступным. + +```js {5} +starlight({ + title: 'Документация с моим логотипом', + logo: { + src: './src/assets/my-logo.svg', + replacesTitle: true, + }, +}), +``` + +### Варианты логотипа для светлой и тёмной темы + +Вы можете отображать разные версии вашего логотипа в светлом и тёмном режимах. + +<Steps> + +1. Добавьте изображения для каждого варианта в директорию `src/assets/`: + + <FileTree> + + - src/ + - assets/ + - **light-logo.svg** + - **dark-logo.svg** + - content/ + - astro.config.mjs + + </FileTree> + +2. Укажите путь к вариантам вашего логотипа в параметрах `light` и `dark` вместо `src` в `astro.config.mjs`: + + ```diff lang="js" + starlight({ + title: 'Документация с моим логотипом', + logo: { + + light: './src/assets/light-logo.svg', + + dark: './src/assets/dark-logo.svg', + }, + }), + ``` + +</Steps> + +## Включение карты сайта + +У Starlight есть встроенная поддержка создания карты сайта. Чтобы включить генерацию карты сайта, укажите ваш URL в качестве `site` в `astro.config.mjs`: + +```js {4} +// astro.config.mjs + +export default defineConfig({ + site: 'https://stargazers.club', + integrations: [starlight({ title: 'Документация с картой сайта' })], +}); +``` + +Узнайте, как [добавить ссылку на карту сайта в `robots.txt`](https://docs.astro.build/ru/guides/integrations-guide/sitemap/#sitemap-link-in-robotstxt) в документации Astro. + +## Макеты страниц + +По умолчанию страницы Starlight используют макет с боковой панелью и оглавлением, которое показывает заголовки текущей страницы. + +Вы можете применить более широкий макет страницы без боковых панелей, установив [`template: splash`](/ru/reference/frontmatter/#template) в метаданных страницы. +Это хорошо подходит для лендингов, вы можете увидеть живой пример на [главной странице этого сайта](/ru/). + +```md {5} +--- +# src/content/docs/index.md + +title: Моя главная страница +template: splash +--- +``` + +## Оглавление + +Starlight отображает оглавление на каждой странице, чтобы читателям было проще перейти к интересующему их заголовку. +Вы можете настроить или даже отключить оглавление полностью в интеграции Starlight или отдельно для каждой страницы в метаданных. + +По умолчанию заголовки `<h2>` и `<h3>` включены в оглавление. Укажите уровни заголовков, которые нужно включить на всем сайте, с помощью параметров `minHeadingLevel` и `maxHeadingLevel`, в [`tableOfContents`](/ru/reference/configuration/#tableofcontents). Переопределите эти значения для отдельных страниц, добавив свойства в [метаданные `tableOfContents`](/ru/reference/frontmatter/#tableofcontents): + +<Tabs syncKey="config-type"> + <TabItem label="Метаданные"> + +```md {4-6} +--- +# src/content/docs/example.md +title: Страница только с заголовками H2 в оглавлении +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 2 +--- +``` + + </TabItem> + <TabItem label="Глобальный конфиг"> + +```js {7} +// astro.config.mjs + +defineConfig({ + integrations: [ + starlight({ + title: 'Документация с изменённой конфигурацией оглавления', + tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 2 }, + }), + ], +}); +``` + + </TabItem> +</Tabs> + +Чтобы полностью отключить оглавление, установите параметр `tableOfContents` в значение `false`: + +<Tabs syncKey="config-type"> + <TabItem label="Метаданные"> + +```md {4} +--- +# src/content/docs/example.md +title: Страница без оглавления +tableOfContents: false +--- +``` + + </TabItem> + <TabItem label="Глобальный конфиг"> + +```js {7} +// astro.config.mjs + +defineConfig({ + integrations: [ + starlight({ + title: 'Документация с глобально отключенным оглавлением', + tableOfContents: false, + }), + ], +}); +``` + + </TabItem> +</Tabs> + +## Ссылки на социальные сети + +Starlight имеет встроенную поддержку для добавления ссылок на ваши аккаунты в социальных сетях в заголовок сайта через параметр [`social`](/ru/reference/configuration/#social) в интеграции Starlight. + +Каждый элемент массива `social` должен быть объектом с тремя свойствами: + +- `icon`: одна из [встроенных иконок](/ru/reference/icons/) Starlight, например `"github"`. +- `label`: доступная подпись для ссылки, например `"GitHub"`. +- `href`: URL-адрес ссылки, например `"https://github.com/withastro/starlight"`. + +Следующий пример добавляет ссылки на чат Astro в Discord и репозиторий Starlight на GitHub: + +```js {9-16} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Документация с социальными ссылками', + social: [ + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { + icon: 'github', + label: 'GitHub', + href: 'https://github.com/withastro/starlight', + }, + ], + }), + ], +}); +``` + +## Ссылки редактирования + +Starlight может отображать ссылку «Редактировать страницу» в нижней части каждой страницы. +Это упрощает для читателя поиск файла, который можно редактировать, чтобы улучшить документацию. +Особенно это может помочь open-source проектам, упрощая процесс внесения вклада от сообщества. + +Чтобы включить ссылки редактирования, установите URL в параметре [`editLink.baseUrl`](/ru/reference/configuration/#editlink), для редактирования репозитория. +Значение `editLink.baseUrl` будет добавлено в начало пути текущей страницы, чтобы сформировать полную ссылку для редактирования. + +Примеры: + +- GitHub: `https://github.com/USER_NAME/REPO_NAME/edit/BRANCH_NAME/` +- GitLab: `https://gitlab.com/USER_NAME/REPO_NAME/-/edit/BRANCH_NAME/` + +Если ваш проект Starlight не находится в корне вашего репозитория, включите путь к проекту в конце базового URL. + +В этом примере показана настройка ссылки для редактирования документации Starlight, которая находится в подкаталоге `docs/` в ветке `main` репозитория `withastro/starlight` на GitHub: + +```js {9-11} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Документация со ссылками для редактирования', + editLink: { + baseUrl: 'https://github.com/withastro/starlight/edit/main/docs/', + }, + }), + ], +}); +``` + +## Настройка страницы 404 + +Сайты на Starlight по умолчанию отображают простую страницу 404. +Вы можете настроить это, добавив файл `404.md` (или `404.mdx`) в директорию `src/content/docs/`: + +<FileTree> + +- src/ + - content/ + - docs/ + - **404.md** + - index.md +- astro.config.mjs + +</FileTree> + +Вы можете использовать другие макеты и настройки страниц Starlight в вашей странице 404. +Например, страница 404 по умолчанию использует макет [`splash`](#макеты-страниц) и компонент [`hero`](/ru/reference/frontmatter/#hero) в метаданных. + +```md {4,6-8} +--- +title: '404' +template: splash +editUrl: false +hero: + title: '404' + tagline: Страница не найдена. Проверьте URL или попробуйте использовать поиск. +--- +``` + +### Отключение стандартной страницы 404 + +Если вашему проекту требуется полностью настроенный макет 404, вы можете создать маршрут `src/pages/404.astro` и установить параметр конфигурации [`disable404Route`](/ru/reference/configuration/#disable404route), чтобы отключить маршрут Starlight по умолчанию: + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Документация с пользовательской страницей 404', + disable404Route: true, + }), + ], +}); +``` + +## Пользовательские шрифты + +По умолчанию Starlight использует шрифты семейства Sans-Serif, доступные на устройстве пользователя, для всего текста. +Это обеспечивает быструю загрузку документации с использованием шрифта, знакомого каждому пользователю, и не требует скачивания больших файлов шрифтов. + +Если вам необходимо добавить пользовательский шрифт на ваш сайт Starlight, вы можете настроить шрифты в CSS-файлах или с помощью любой другой [техники оформления Astro](https://docs.astro.build/ru/guides/styling/). + +### Настройка шрифтов + +Если у вас уже есть файлы шрифтов, следуйте [руководству по локальной настройке](#настройка-локальных-шрифтов). +Чтобы использовать Google Fonts, следуйте [руководству по настройке Fontsource](#настройка-шрифта-из-fontsource). + +#### Настройка локальных шрифтов + +<Steps> + +1. Добавьте ваши шрифты в директорию `src/fonts/` и создайте пустой файл `font-face.css`: + + <FileTree> + + - src/ + - content/ + - fonts/ + - **CustomFont.woff2** + - **font-face.css** + - astro.config.mjs + + </FileTree> + +2. Добавьте объявление [`@font-face`](https://developer.mozilla.org/ru/docs/Web/CSS/@font-face) для каждого из ваших шрифтов в файл `src/fonts/font-face.css`. + Используйте относительный путь к шрифту в функции `url()`. + + ```css + /* src/fonts/font-face.css */ + + @font-face { + font-family: 'Custom Font'; + /* Используйте относительный путь к шрифту в функции `url()`. */ + src: url('./CustomFont.woff2') format('woff2'); + font-weight: normal; + font-style: normal; + font-display: swap; + } + ``` + +3. Добавьте путь к вашему файлу `font-face.css` в массив `customCss` в `astro.config.mjs`: + + ```diff lang="js" + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Документация с пользовательским шрифтом', + customCss: [ + + // Относительный путь к вашему CSS-файлу с @font-face. + + './src/fonts/font-face.css', + ], + }), + ], + }); + ``` + +</Steps> + +#### Настройка шрифта из Fontsource + +Проект [Fontsource](https://fontsource.org/) упрощает использование шрифтов Google Fonts и других open-source шрифтов. +Проект предоставляет npm-пакеты, для использования шрифтов, которые вас интересуют, и включает готовые CSS-файлы, которые можно добавить в ваш проект. + +<Steps> + +1. Найдите шрифт, который вы хотите использовать, в [каталоге Fontsource](https://fontsource.org/). + В данном примере будет использоваться шрифт [IBM Plex Serif](https://fontsource.org/fonts/ibm-plex-serif). + +2. Установите пакет для выбранного вами шрифта. + Вы можете найти имя пакета, нажав «Install» на странице шрифта Fontsource. + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @fontsource/ibm-plex-serif + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @fontsource/ibm-plex-serif + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @fontsource/ibm-plex-serif + ``` + + </TabItem> + + </Tabs> + +3. Добавьте CSS-файлы Fontsource в массив `customCss` в `astro.config.mjs`: + + ```diff lang="js" + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Документация с пользовательским шрифтом', + customCss: [ + + // Файлы Fontsource для regular и semi-bold шрифтов. + + '@fontsource/ibm-plex-serif/400.css', + + '@fontsource/ibm-plex-serif/600.css', + ], + }), + ], + }); + ``` + + Fontsource предоставляет несколько CSS-файлов для каждого шрифта. См. [документацию Fontsource](https://fontsource.org/docs/getting-started/install#4-weights-and-styles) по включению различных начертаний и стилей, чтобы понять, какие использовать. + +</Steps> + +### Использование шрифтов + +Чтобы применить шрифт, который вы настроили для вашего сайта, используйте имя вашего выбранного шрифта в [CSS-файле](/ru/guides/css-and-tailwind/#ваши-css-стили). +Например, чтобы заменить шрифт по умолчанию везде, установите пользовательское свойство `--sl-font`: + +```css +/* src/styles/custom.css */ + +:root { + --sl-font: 'IBM Plex Serif', serif; +} +``` + +Вы также можете написать более точные стили CSS, если хотите применить ваш шрифт более выборочно. +Например, чтобы установить шрифт только для основного контента, но не для боковых панелей: + +```css +/* src/styles/custom.css */ + +main { + font-family: 'IBM Plex Serif', serif; +} +``` + +Следуйте [инструкциям по настройке пользовательских стилей CSS](/ru/guides/css-and-tailwind/#ваши-css-стили), чтобы добавить свои стили на ваш сайт. diff --git a/docs/src/content/docs/ru/guides/i18n.mdx b/docs/src/content/docs/ru/guides/i18n.mdx new file mode 100644 index 00000000000..075948bb41e --- /dev/null +++ b/docs/src/content/docs/ru/guides/i18n.mdx @@ -0,0 +1,410 @@ +--- +title: Интернационализация (i18n) +description: Узнайте, как настроить ваш сайт на Starlight для поддержки нескольких языков. +--- + +import { FileTree, Steps } from '@astrojs/starlight/components'; + +Starlight обеспечивает встроенную поддержку многоязычных сайтов, включая маршрутизацию, резервный контент и полную поддержку языков с письмом справа налево (RTL). + +## Настройка i18n + +<Steps> + +1. Сообщите Starlight о поддерживаемых вами языках, передав свойства [`locales`](/ru/reference/configuration/#locales) и [`defaultLocale`](/ru/reference/configuration/#defaultlocale) в интеграцию Starlight: + + ```js {9-26} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Моя документация', + // Устанавливаем «Русский» как язык по умолчанию для этого сайта + defaultLocale: 'ru', + locales: { + // Документация на английском в `src/content/docs/en/` + en: { + label: 'English', + }, + // Документация на китайском в `src/content/docs/zh-cn/` + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + // Документация на русском в `src/content/docs/ru/` + ru: { + label: 'Русский', + lang: 'ru', + }, + }, + }), + ], + }); + ``` + + `defaultLocale` будет использоваться для резервного контента и текста UI, поэтому выберите язык, на котором вы скорее всего начнете писать контент или для которого у вас уже есть материалы. + +2. Создайте каталог для каждого языка в `src/content/docs/`. + Например, для показанной выше конфигурации создайте следующие папки: + + <FileTree> + + - src/ + - content/ + - docs/ + - en/ + - ru/ + - zh-cn/ + + </FileTree> + +3. Теперь вы можете добавлять контент в свои языковые каталоги. Используйте одно и то же имя файла для связывания страниц на разных языках и воспользуйтесь полным набором функций i18n Starlight, включая резервный контент, уведомления о переводе и многое другое. + + Например, создайте `ru/index.md` и `en/index.md` для отображения главной страницы на русском и английском языках. + +</Steps> + +Для более продвинутых сценариев использования i18n Starlight также поддерживает настройку интернационализации с помощью [опции `i18n` Astro](https://docs.astro.build/ru/guides/internationalization/#%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-i18n-%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8). + +### Использование корневой локали + +Вы можете использовать «корневую» локаль для отображения языка без префикса i18n в его пути. Например, если русский является вашей корневой локалью, путь к странице на русском языке будет выглядеть как `/about` вместо `/ru/about`. + +Чтобы установить корневую локаль, используйте ключ `root` в вашей конфигурации `locales`. Если корневая локаль также является локалью по умолчанию для вашего контента, удалите `defaultLocale` или установите его значение как `'root'`. + +```js {9,11-14} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Моя документация', + defaultLocale: 'root', // опционально + locales: { + root: { + label: 'Русский', + lang: 'ru', // параметр lang обязателен для корневых локалей + }, + en: { + label: 'English', + lang: 'en', + }, + }, + }), + ], +}); +``` + +При использовании локали `root` храните страницы для этого языка непосредственно в `src/content/docs/`, а не в отдельной языковой папке. Например, вот файлы домашней страницы для английского и русского языков при использовании приведённой выше конфигурации: + +<FileTree> + +- src/ + - content/ + - docs/ + - **index.md** + - en/ + - **index.md** + +</FileTree> + +#### Одноязычные сайты + +По умолчанию, Starlight является одноязычным сайтом, с английским языком. Чтобы создать сайт на другом языке, укажите его как `root` в вашей конфигурации `locales`: + +```diff lang="js" {10-13} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Моя документация', + locales: { + root: { + label: 'Русский', + lang: 'ru', + }, + }, + }), + ], +}); +``` + +Это позволяет вам переопределить язык по умолчанию для Starlight без включения других функций интернационализации для многоязычных сайтов, таких как выбор языка. + +## Резервный контент + +Starlight предполагает, что вы создадите эквивалентные страницы на всех поддерживаемых языках. Например, если у вас есть файл `en/about.md`, создайте файл `about.md` для каждого другого языка, который вы поддерживаете. Это позволяет Starlight предоставлять автоматически резервный контент для страниц, которые ещё не были переведены. + +Если перевод для языка ещё не доступен, Starlight покажет читателям контент этой страницы на языке по умолчанию (установленном через `defaultLocale`). Например, если вы ещё не создали французскую версию вашей страницы «О нас» и вашим языком по умолчанию является английский, посетители `/fr/about` увидят английский контент из `/en/about` с уведомлением о том, что эта страница ещё не была переведена. Это помогает вам добавлять контент на вашем языке по умолчанию и постепенно переводить его, когда у ваших переводчиков есть время. + +## Перевод заголовка сайта + +По умолчанию Starlight использует одно и то же название сайта для всех языков. +Если вам нужно настроить заголовок для каждой локали, вы можете передать объект [`title`](/ru/reference/configuration/#title-обязателен) в опциях Starlight: + +```diff lang="js" +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ +- title: 'Моя документация', ++ title: { ++ ru: "Моя документация", ++ 'zh-CN': '我的文档', ++ }, + defaultLocale: 'ru', + locales: { + ru: { label: 'Русский' }, + 'zh-cn': { label: '简体中文', lang: 'zh-CN' }, + }, + }), + ], +}); +``` + +## Перевод интерфейса Starlight + +import LanguagesList from '~/components/languages-list.astro'; +import UIStringsList from '~/components/ui-strings-list.astro'; + +Кроме размещения переведённых файлов с контентом, Starlight позволяет вам переводить текст интерфейсе (например, заголовок «На этой странице» в оглавлении), чтобы ваши читатели могли полностью погрузиться в ваш сайт на выбранном языке. + +<LanguagesList startsSentence /> — все переведённые строки пользовательского +интерфейса на указанных языках предоставляются «из коробки», и мы приветствуем +[вклад в добавление новых +языков](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md). + +Вы можете добавить переводы для дополнительных языков, которые вы поддерживаете — или переопределить наши стандартные тексты — через коллекцию данных `i18n`. + +<Steps> + +1. Сконфигурируйте коллекцию данных `i18n` в `src/content.config.ts`, если она ещё не настроена: + + ```diff lang="js" ins=/, (i18nLoader|i18nSchema)/ + // src/content.config.ts + import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; + import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + + export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), + }; + ``` + +2. Создайте файл JSON в `src/content/i18n/` для каждой дополнительной локали, для которой вы хотите добавить строки перевода интерфейса. + Например, так можно добавить файлы перевода для арабского и русского: + + <FileTree> + + - src/ + - content/ + - i18n/ + - ar.json + - ru.json + + </FileTree> + +3. Добавьте переводы для ключей, которые вы хотите перевести, в файлы JSON. Переводите только значения, оставляя ключи на английском языке (например, `"search.label": "Поиск"`). + + Это английские значения по умолчанию для существующих строк, с которыми поставляется Starlight: + + <UIStringsList /> + + Блоки кода Starlight основаны на библиотеке [Expressive Code](https://expressive-code.com/). + Вы можете установить переводы для строк пользовательского интерфейса в том же файле JSON, используя ключи `expressiveCode`: + + ```json + { + "expressiveCode.copyButtonCopied": "Copied!", + "expressiveCode.copyButtonTooltip": "Copy to clipboard", + "expressiveCode.terminalWindowFallbackTitle": "Terminal window" + } + ``` + + Модальное окно поиска в Starlight работает с помощью библиотеки [Pagefind](https://pagefind.app/). + Вы можете установить переводы для пользовательского интерфейса Pagefind в том же JSON-файле, используя ключи `pagefind`: + + ```json + { + "pagefind.clear_search": "Clear", + "pagefind.load_more": "Load more results", + "pagefind.search_label": "Search this site", + "pagefind.filters_label": "Filters", + "pagefind.zero_results": "No results for [SEARCH_TERM]", + "pagefind.many_results": "[COUNT] results for [SEARCH_TERM]", + "pagefind.one_result": "[COUNT] result for [SEARCH_TERM]", + "pagefind.alt_search": "No results for [SEARCH_TERM]. Showing results for [DIFFERENT_TERM] instead", + "pagefind.search_suggestion": "No results for [SEARCH_TERM]. Try one of the following searches:", + "pagefind.searching": "Searching for [SEARCH_TERM]..." + } + ``` + +</Steps> + +### Расширение схемы переводов + +Добавьте пользовательские ключи в словари переводов вашего сайта, установив `extend` в опциях `i18nSchema()`. +В следующем примере к ключам по умолчанию добавляется новый необязательный ключ `custom.label`: + +```diff lang="js" +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ ++ extend: z.object({ ++ 'custom.label': z.string().optional(), ++ }), + }), + }), +}; +``` + +Дополнительную информацию о схемах коллекции контента см. в разделе [Определение схемы коллекции](https://docs.astro.build/ru/guides/content-collections/#%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D1%85%D0%B5%D0%BC%D1%8B-%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8) в документации Astro. + +## Использование UI-переводов + +Вы можете получить доступ к [встроенным строкам пользовательского интерфейса](/ru/guides/i18n/#перевод-интерфейса-starlight) Starlight, а также к [пользовательским](/ru/guides/i18n/#расширение-схемы-переводов) и [предоставляемым плагинами](/ru/reference/plugins/#injecttranslations) строкам пользовательского интерфейса через единый API на базе [i18next](https://www.i18next.com/). +Это включает поддержку таких функций, как [интерполяция](https://www.i18next.com/translation-function/interpolation) и [плюрализация](https://www.i18next.com/translation-function/plurals). + +В компонентах Astro этот API доступен как часть [глобального объекта `Astro`](https://docs.astro.build/en/reference/api-reference/#locals) в виде `Astro.locals.t`: + +```astro title="example.astro" +<p dir={Astro.locals.t.dir()}> + {Astro.locals.t('404.text')} +</p> +``` + +Вы также можете использовать API в [эндпойнтах](https://docs.astro.build/ru/guides/endpoints/), где объект `locals` доступен как часть контекста [эндпойнта](https://docs.astro.build/en/reference/api-reference/#locals): + +```ts title="src/pages/404.ts" +export const GET = (context) => { + return new Response(context.locals.t('404.text')); +}; +``` + +В контексте плагина Starlight вы можете использовать хелпер [`useTranslations()`](/ru/reference/plugins/#usetranslations) для доступа к этому API для конкретного языка. +Дополнительную информацию смотрите в [справочнике по плагинам](/ru/reference/plugins/). + +### Рендеринг строки пользовательского интерфейса + +Отрисовка строк пользовательского интерфейса с помощью функции `locals.t()`. +Это экземпляр функции i18next `t()`, которая принимает в качестве первого аргумента строку-ключ UI и возвращает соответствующий перевод для текущего языка. + +Например, задан файл пользовательского перевода со следующим содержанием: + +```json title="src/content/i18n/ru.json" +{ + "link.astro": "Документация Astro", + "link.astro.custom": "Документация Astro о {{feature}}" +} +``` + +Первую строку пользовательского интерфейса можно отобразить, передав `'link.astro'` в функцию `t()`: + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/"> + {Astro.locals.t('link.astro')} +</a> +<!-- Отрисовывает: <a href="...">Документация Astro</a> --> +``` + +Вторая строка пользовательского интерфейса использует [синтаксис интерполяции](https://www.i18next.com/translation-function/interpolation) i18next для размещения `{{feature}}`. +Значение для `feature` должно быть задано в объекте options, передаваемом в качестве второго аргумента в `t()`: + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/ru/guides/astro-db/"> + {Astro.locals.t('link.astro.custom', { feature: 'Astro DB' })} +</a> +<!-- Отрисовывает: <a href="...">Документация Astro о Astro DB</a> --> +``` + +Подробнее о том, как использовать функцию `t()` для интерполяции, форматирования и т. д., см. в [документации i18next](https://www.i18next.com/overview/api#t). + +### Расширенные API + +#### `t.all()` + +Функция `locals.t.all()` возвращает объект, содержащий все строки пользовательского интерфейса, доступные для текущей локали. + +```astro +--- +// src/components/Example.astro +const allStrings = Astro.locals.t.all(); +// ^ +// { +// "skipLink.label": "Перейти к содержанию", +// "search.label": "Поиск", +// … +// } +--- +``` + +#### `t.exists()` + +Чтобы проверить, существует ли ключ перевода, используйте функцию `locals.t.exists()` с ключом перевода в качестве первого аргумента. +Передайте необязательный второй аргумент, если нужно проверить наличие перевода для определённой локали. + +```astro +--- +// src/components/Example.astro +const keyExists = Astro.locals.t.exists('a.key'); +// ^ true +const keyExistsInFrench = Astro.locals.t.exists('other.key', { lngs: ['fr'] }); +// ^ false +--- +``` + +Дополнительную информацию см. в статье [`exists()` в документации i18next](https://www.i18next.com/overview/api#exists). + +#### `t.dir()` + +Функция `locals.t.dir()` возвращает направление текста текущей или определённой локали. + +```astro +--- +// src/components/Example.astro +const currentDirection = Astro.locals.t.dir(); +// ^ +// 'ltr' +const arabicDirection = Astro.locals.t.dir('ar'); +// ^ +// 'rtl' +--- +``` + +Дополнительную информацию см. в статье [`dir()` в документации i18next](https://www.i18next.com/overview/api#dir). + +## Доступ к текущей локали + +Вы можете использовать [`Astro.currentLocale`](https://docs.astro.build/en/reference/api-reference/#currentlocale) для получения текущей локали в компонентах `.astro`. + +Следующий пример считывает текущую локаль и использует её с помощью хелпера [`getRelativeLocaleUrl()`](https://docs.astro.build/ru/reference/modules/astro-i18n/#getrelativelocaleurl) для генерации ссылки на страницу «О сайте» на текущем языке: + +```astro +--- +// src/components/AboutLink.astro +import { getRelativeLocaleUrl } from 'astro:i18n'; +--- + +<a href={getRelativeLocaleUrl(Astro.currentLocale ?? 'en', 'about')}>О сайте</a> +``` diff --git a/docs/src/content/docs/ru/guides/overriding-components.mdx b/docs/src/content/docs/ru/guides/overriding-components.mdx new file mode 100644 index 00000000000..baa88f5245e --- /dev/null +++ b/docs/src/content/docs/ru/guides/overriding-components.mdx @@ -0,0 +1,152 @@ +--- +title: Переопределение компонентов +description: Узнайте, как переопределить встроенные компоненты Starlight, чтобы добавить пользовательские элементы в интерфейс вашего сайта документации. +--- + +import { Steps } from '@astrojs/starlight/components'; + +Пользовательский интерфейс и параметры конфигурации Starlight по умолчанию разработаны таким образом, чтобы быть гибкими и работать с разнообразным контентом. Большую часть внешнего вида Starlight по умолчанию можно настроить с помощью [CSS](/ru/guides/css-and-tailwind/) и [параметров конфигурации](/ru/guides/customization/). + +Если вам нужно больше, чем возможно из коробки, Starlight поддерживает создание собственных пользовательских компонентов для расширения или переопределения (полной замены) компонентов по умолчанию. + +## Когда переопределять + +Переопределение стандартных компонентов Starlight может быть полезно, когда: + +- Вы хотите изменить внешний вид интерфейса Starlight, если это невозможно сделать с использованием [пользовательских CSS](/ru/guides/css-and-tailwind/). +- Вы хотите изменить поведение интерфейса Starlight. +- Вы хотите добавить какой-то дополнительный интерфейс наряду с существующим интерфейсом Starlight. + +## Как выполнить переопределение + +<Steps> + +1. Выберите компонент Starlight, который вы хотите переопределить. + Вы можете найти полный список компонентов в [Справочнике по переопределениям](/ru/reference/overrides/). + + :::tip + Не уверены, какой компонент нужно переопределить? Используйте [интерактивную карту переопределений Starlight](https://starlight-overrides-map.netlify.app/), чтобы узнать названия UI-компонентов Starlight. + ::: + + В этом примере будет переопределён компонент [`SocialIcons`](/ru/reference/overrides/#socialicons) в навигационной панели страницы. + +2. Создайте компонент Astro для замены компонента Starlight. + В этом примере отображается ссылка для связи. + + ```astro + --- + // src/components/EmailLink.astro + + const email = 'houston@example.com'; + --- + + <a href=`mailto:${email}`>Напишите мне</a> + ``` + +3. Сообщите Starlight, что нужно использовать ваш компонент, указав его в параметре конфигурации [`components`](/ru/reference/configuration/#components) в `astro.config.mjs`: + + ```js {9-12} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Моя документация, с переопределением компонентов', + components: { + // Переопределение компонента `SocialIcons`. + SocialIcons: './src/components/EmailLink.astro', + }, + }), + ], + }); + ``` + +</Steps> + +## Переиспользование встроенного компонента + +Вы можете работать со стандартными UI-компонентами Starlight так же, как и со своими собственными: импортировать их и использовать в своих компонентах. Это позволяет вам сохранить весь интерфейс Starlight в рамках вашего дизайна, добавляя свой интерфейс рядом с ними. + +Пример ниже показывает компонент, который отображает ссылку на электронную почту наряду со стандартным компонентом `SocialIcons`: + +```astro {3,7} +--- +// src/components/EmailLink.astro +import Default from '@astrojs/starlight/components/SocialIcons.astro'; +--- + +<a href="mailto:houston@example.com"> Связаться с нами по электронной почте </a> +<Default><slot /></Default> +``` + +При рендеринге встроенного компонента внутри пользовательского компонента добавьте [`<slot />`](https://docs.astro.build/ru/basics/astro-components/#%D1%81%D0%BB%D0%BE%D1%82%D1%8B) внутрь компонента по умолчанию. Это гарантирует, что если компоненту переданы дочерние элементы, Astro будет знать, где их отобразить. + +Если вы повторно используете компоненты [`PageFrame`](/ru/reference/overrides/#pageframe) или [`TwoColumnContent`](/ru/reference/overrides/#twocolumncontent), содержащие [именованные слоты](https://docs.astro.build/ru/basics/astro-components/#именованые-слоты), вам также необходимо [перенести](https://docs.astro.build/ru/basics/astro-components/#перенос-слотов) эти слоты. + +Ниже показан пользовательский компонент, который повторно использует компонент `TwoColumnContent`, содержащий дополнительный именованный слот `right-sidebar`, нуждающийся в переносе: + +```astro {8} +--- +// src/components/CustomContent.astro +import Default from '@astrojs/starlight/components/TwoColumnContent.astro'; +--- + +<Default> + <slot /> + <slot name="right-sidebar" slot="right-sidebar" /> +</Default> +``` + +## Использование данных страницы + +При переопределении компонента Starlight вы можете получить доступ к глобальному объекту [`starlightRoute`](/ru/guides/route-data/), который содержит все данные для текущей страницы. +Это позволяет вам использовать эти значения для управления тем, как ваш компонент будет отображаться. + +В следующем примере заменяющий компонент [`PageTitle`](/ru/reference/overrides/#pagetitle) отображает заголовок текущей страницы, установленный в метаданных контента: + +```astro {4} "{title}" +--- +// src/components/Title.astro + +const { title } = Astro.locals.starlightRoute.entry.data; +--- + +<h1 id="_top">{title}</h1> + +<style> + h1 { + font-family: 'Comic Sans'; + } +</style> +``` + +Узнайте больше обо всех доступных свойствах в [Справочнике по данным маршрута](/ru/reference/route-data/). + +### Переопределение только на определённых страницах + +Переопределение компонентов применяется ко всем страницам. Тем не менее, вы можете осуществлять условную отрисовку, используя значения из `starlightRoute`, чтобы определить, когда показывать ваш интерфейс, когда показывать интерфейс Starlight, или даже когда показывать что-то совершенно другое. + +В следующем примере компонент, переопределяющий [`Footer`](/ru/reference/overrides/#footer) от Starlight, отображает надпись «Создано с помощью Starlight 🌟» только на главной странице, а на всех остальных страницах показывает футер по умолчанию: + +```astro +--- +// src/components/ConditionalFooter.astro +import Default from '@astrojs/starlight/components/Footer.astro'; + +const isHomepage = Astro.locals.starlightRoute.id === ''; +--- + +{ + isHomepage ? ( + <footer>Создано с помощью Starlight 🌟</footer> + ) : ( + <Default> + <slot /> + </Default> + ) +} +``` + +Узнайте больше об отрисовке по условию в руководстве [Синтаксис Astro](https://docs.astro.build/ru/basics/astro-syntax/#динамический-html). diff --git a/docs/src/content/docs/ru/guides/pages.mdx b/docs/src/content/docs/ru/guides/pages.mdx new file mode 100644 index 00000000000..9dcfe3db911 --- /dev/null +++ b/docs/src/content/docs/ru/guides/pages.mdx @@ -0,0 +1,230 @@ +--- +title: Страницы +description: Узнайте, как создавать страницы вашего сайта документации и управлять ими с помощью Starlight. +sidebar: + order: 1 +tableOfContents: + maxHeadingLevel: 4 +--- + +Starlight генерирует HTML-страницы вашего сайта на основе вашего контента с гибкими опциями, предоставляемыми через интерфейс Markdown. +Кроме того, проекты Starlight имеют полный доступ к [мощным инструментам создания страниц Astro](https://docs.astro.build/ru/basics/astro-pages/). +В этом руководстве объясняется, как работает генерация страниц в Starlight. + +## Содержимое страниц + +### Форматы файлов + +Starlight поддерживает создание контента в Markdown и MDX без необходимости настройки. +Вы можете добавить поддержку Markdoc, следуя [руководству](/ru/guides/authoring-content/#markdoc). + +### Добавление страниц + +Добавляйте новые страницы на свой сайт, создавая файлы `.md` или `.mdx` в `src/content/docs/`. +Используйте подпапки для организации файлов и создания нескольких сегментов пути. + +Например, следующая файловая структура будет генерировать страницы `example.com/hello-world` и `example.com/reference/faq`: + +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - reference/ + - faq.md + +</FileTree> + +### Типобезопасные метаданные + +Все страницы Starlight используют настраиваемый [общий набор свойств метаданных](/ru/reference/frontmatter/) для контроля отображения страницы: + +```md +--- +title: Привет, мир! +description: Это страница на моем сайте, работающем на Starlight +--- +``` + +Если вы что-то забудете, Starlight сообщит вам об этом. + +## Пользовательские страницы + +Для расширенных вариантов использования вы можете добавлять собственные страницы, создав каталог `src/pages/`. +Каталог `src/pages/` использует [маршрутизацию на основе файлов Astro](https://docs.astro.build/ru/basics/astro-pages/#%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F-%D0%BD%D0%B0-%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B5-%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2) и включает поддержку файлов с расширением `.astro` помимо других форматов страниц. +Это полезно, если вам нужно создать страницу с полностью настраиваемым макетом или создать страницу из альтернативного источника данных. + +Например, в этом проекте содержимое Markdown смешивается в `src/content/docs/` с маршрутами Astro и HTML в `src/pages/`: + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - pages/ + - custom.astro + - archived.html + +</FileTree> + +Подробнее читайте в [руководстве «Страницы» в документации Astro](https://docs.astro.build/ru/basics/astro-pages/). + +### Использование дизайна Starlight на пользовательских страницах + +Чтобы использовать макет Starlight на пользовательских страницах, оберните содержимое страницы [компонентом `<StarlightPage>`](#компонент-starlightpage). +Это может быть полезно, если вы динамически генерируете контент, но всё же хотите использовать дизайн Starlight. + +Чтобы добавить ссылки-якоря к заголовкам, соответствующие стилю ссылок-якорей Markdown в Starlight, вы можете использовать компонент [`<AnchorHeading>`](#компонент-anchorheading) на своих пользовательских страницах. + +```astro +--- +// src/pages/custom-page/example.astro +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +import CustomComponent from './CustomComponent.astro'; +--- + +<StarlightPage frontmatter={{ title: 'Моя персонализированная страница' }}> + <p>Это пользовательская страница с пользовательским компонентом:</p> + <CustomComponent /> + + <AnchorHeading level="2" id="learn-more">Узнать больше</AnchorHeading> + <p> + <a href="https://starlight.astro.build/" + >Узнайте больше в документации Starlight</a + > + </p> +</StarlightPage> +``` + +#### Компонент `<StarlightPage>` + +Компонент `<StarlightPage />` отображает полную страницу контента с использованием макета и стилей Starlight. + +```astro +--- +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +--- + +<StarlightPage frontmatter={{ title: 'Моя пользовательская страница' }}> + <!-- Содержимое пользовательской страницы --> +</StarlightPage> +``` + +Компонент `<StarlightPage />` принимает следующие параметры. + +##### `frontmatter` + +**обязательный** +**тип:** `StarlightPageFrontmatter` + +Установка [метаданных](/ru/reference/frontmatter/) для этой страницы, аналогично метаданным на страницах Markdown. +Свойство [`title`](/ru/reference/frontmatter/#title-обязательно) является обязательным, а все остальные свойства — нет. + +Следующие свойства отличаются от метаданных Markdown: + +- Свойство [`slug`](/ru/reference/frontmatter/#slug) не поддерживается и устанавливается автоматически на основе URL-адреса пользовательской страницы. +- Свойство [`editUrl`](/ru/reference/frontmatter/#editurl) требует указания URL-адреса для отображения ссылки на редактирование. +- Свойство [`sidebar`](/ru/reference/frontmatter/#sidebar) для настройки отображения страницы в [автогенерируемых группах ссылок](/ru/reference/configuration/#sidebar) недоступно. Страницы, использующие компонент `<StarlightPage />`, не являются частью коллекции и не могут быть добавлены в автоматически созданную группу боковой панели. +- Свойство [`draft`](/ru/reference/frontmatter/#draft) лишь отображает [уведомление](/ru/reference/overrides/#draftcontentnotice) о том, что страница является черновиком, но не исключает её автоматически из продакшен-сборок. + +##### `sidebar` + +**тип:** [`SidebarItem[]`](/ru/reference/configuration/#sidebaritem) +**по умолчанию:** боковая панель, созданная на основе [глобальной конфигурации `sidebar`](/ru/reference/configuration/#sidebar) + +Предоставление настраиваемой боковой панели навигации для этой страницы. +Если этот параметр не установлен, на странице будет использоваться глобальная боковая панель по умолчанию. + +Например, следующая страница переопределяет стандартную боковую панель со ссылкой на главную страницу и группой ссылок на другие пользовательские страницы. + +```astro {3-13} +<StarlightPage + frontmatter={{ title: 'Орион' }} + sidebar={[ + { label: 'Главная', link: '/' }, + { + label: 'Созвездия', + items: [ + { label: 'Андромеда', link: '/andromeda/' }, + { label: 'Орион', link: '/orion/' }, + { label: 'Малая Медведица', link: '/ursa-minor/', badge: 'Заглушка' }, + ], + }, + ]} +> + Пример контента. +</StarlightPage> +``` + +Подробнее о доступных вариантах настройки боковой панели см. в руководстве [Боковая панель](/ru/guides/sidebar/). + +##### `hasSidebar` + +**тип:** `boolean` +**по умолчанию:** `false` если [`frontmatter.template`](/ru/reference/frontmatter/#template) имеет значение `'splash'`, в противном случае `true` + +Отображение боковой панели на этой странице. + +##### `headings` + +**тип:** `{ depth: number; slug: string; text: string }[]` +**по умолчанию:** `[]` + +Предоставление массива всех заголовков на этой странице. +Starlight сгенерирует оглавление страницы из этих заголовков, если они предусмотрены. + +##### `dir` + +**тип:** `'ltr' | 'rtl'` +**по умолчанию:** направление письма для текущей локали + +Установка направления письма для содержимого этой страницы. + +##### `lang` + +**тип:** `string` +**по умолчанию:** язык текущей локали + +Установка языкового тега BCP-47 для содержимого этой страницы, например: `en`, `zh-CN` или `pt-BR`. + +##### `isFallback` + +**тип:** `boolean` +**по умолчанию:** `false` + +Отображение [резервного контента](/ru/guides/i18n/#резервный-контент), если перевод на текущий язык отсутствует. + +#### Компонент `<AnchorHeading>` + +Компонент `<AnchorHeading />` отображает HTML-элемент заголовка с кликабельной ссылкой-якорем, соответствующей стилям Markdown в Starlight. + +```astro +--- +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +--- + +<AnchorHeading level="2" id="sub-heading">Подзаголовок</AnchorHeading> +``` + +Он принимает следующие свойства, а также любые другие допустимые [глобальные HTML-атрибуты](https://developer.mozilla.org/ru/docs/Web/HTML/Reference/Global_attributes). + +##### `level` + +**обязательный** +**тип:** `1 | 2 | 3 | 4 | 5 | 6` + +Уровень заголовка для отображения. +Например, `level="1"` отобразит элемент `<h1>`. + +##### `id` + +**обязательный** +**тип:** `string` + +Уникальный идентификатор для этого заголовка. +Он будет использован в качестве атрибута `id` отображаемого заголовка, и значок якоря будет ссылаться на него. diff --git a/docs/src/content/docs/ru/guides/project-structure.mdx b/docs/src/content/docs/ru/guides/project-structure.mdx new file mode 100644 index 00000000000..9f8bc37cb4d --- /dev/null +++ b/docs/src/content/docs/ru/guides/project-structure.mdx @@ -0,0 +1,47 @@ +--- +title: Структура проекта +description: Узнайте, как организовать файлы в вашем проекте Starlight. +--- + +Это руководство покажет вам, как организован проект Starlight и какую роль выполняют различные файлы в вашем проекте. + +Проекты Starlight, как правило, следуют той же структуре файлов и каталогов, что и другие проекты Astro. Подробнее смотрите в [документации по структуре проекта Astro](https://docs.astro.build/ru/basics/project-structure/). + +## Файлы и папки + +- `astro.config.mjs` — Файл конфигурации Astro; включает интеграцию и конфигурацию Starlight. +- `src/content.config.ts` — Файл конфигурации коллекций контента; добавляет метаданные (frontmatter) от Starlight в ваш проект. +- `src/content/docs/` — Файлы контента. Starlight преобразует каждый файл `.md`, `.mdx` или `.mdoc` в этом каталоге в страницу на вашем сайте. +- `src/content/i18n/` (по необходимости) — Данные перевода для поддержки [интернационализации](/ru/guides/i18n/). +- `src/` — Другой исходный код и файлы (компоненты, стили, изображения и т. д.) для вашего проекта. +- `public/` — Статические активы (шрифты, значки, PDF и т. д.), которые не будут обработаны Astro. + +## Пример проекта + +Директория проекта Starlight может выглядеть так: + +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- public/ + - favicon.svg +- src/ + - assets/ + - logo.svg + - screenshot.jpg + - components/ + - CustomButton.astro + - InteractiveWidget.jsx + - content/ + - docs/ + - guides/ + - 01-getting-started.md + - 02-advanced.md + - index.mdx + - content.config.ts +- astro.config.mjs +- package.json +- tsconfig.json + +</FileTree> diff --git a/docs/src/content/docs/ru/guides/route-data.mdx b/docs/src/content/docs/ru/guides/route-data.mdx new file mode 100644 index 00000000000..719b02d33c0 --- /dev/null +++ b/docs/src/content/docs/ru/guides/route-data.mdx @@ -0,0 +1,139 @@ +--- +title: Данные маршрута +description: Узнайте, как модель данных страниц Starlight используется для рендеринга ваших страниц и как вы можете её настроить. +--- + +import { Steps } from '@astrojs/starlight/components'; + +Когда Starlight рендерит страницу в вашей документации, он сначала создаёт объект данных маршрута, чтобы представить содержимое этой страницы. +В этом руководстве объясняется, как генерируются данные маршрута, как их использовать и как настроить, чтобы изменить поведение Starlight по умолчанию. + +Полный список доступных свойств см. в [«Справочнике по данным маршрута»](/ru/reference/route-data/). + +## Что такое данные маршрута? + +Данные маршрута в Starlight — это объект, содержащий всю информацию, необходимую для рендеринга отдельной страницы. +Он включает сведения о текущей странице, а также данные, сгенерированные на основе вашей конфигурации Starlight. + +## Использование данных маршрута + +Все компоненты Starlight используют данные маршрута, чтобы определить, что рендерить на каждой странице. +Например, строка [`siteTitle`](/ru/reference/route-data/#sitetitle) используется для отображения заголовка сайта, а массив [`sidebar`](/ru/reference/route-data/#sidebar) — для рендеринга глобальной боковой навигации. + +Вы можете получить доступ к этим данным через глобальный объект `Astro.locals.starlightRoute` в компонентах Astro: + +```astro title="example.astro" {2} +--- +const { siteTitle } = Astro.locals.starlightRoute; +--- + +<p>Заголовок этого сайта — «{siteTitle}»</p> +``` + +Это может быть полезно, например, при создании [переопределений компонентов](/ru/guides/overriding-components/), чтобы настроить отображаемый контент. + +## Настройка данных маршрута + +Данные маршрута в Starlight работают «из коробки» и не требуют дополнительной настройки. +Однако в сложных сценариях может понадобиться настроить данные маршрута для отдельных страниц или всех страниц, чтобы изменить отображение вашего сайта. + +Этот процесс похож на [переопределение компонентов](/ru/guides/overriding-components/), но вместо изменения того, как Starlight рендерит ваши данные, вы изменяете сами данные, которые рендерит Starlight. + +### Когда настраивать данные маршрута + +Настройка данных маршрута полезна, когда вам нужно изменить способ обработки данных Starlight так, как это невозможно сделать с помощью существующих параметров конфигурации. + +Например, вы можете захотеть отфильтровать элементы боковой панели или настроить заголовки для отдельных страниц. +Такие изменения не требуют модификации стандартных компонентов Starlight, а только данных, передаваемых этим компонентам. + +### Как настроить данные маршрута + +Вы можете настроить данные маршрута с помощью специальной формы «мидлвара». +Это функция, которая вызывается каждый раз при рендеринге страницы в Starlight и может изменять значения в объекте данных маршрута. + +<Steps> + +1. Создайте новый файл, экспортирующий функцию `onRequest`, используя утилиту `defineRouteMiddleware()` из Starlight: + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware(() => {}); + ``` + +2. Укажите Starlight местоположение файла мидлвара для данных маршрута в `astro.config.mjs`: + + ```js ins={9} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Мой замечательный сайт документации', + routeMiddleware: './src/routeData.ts', + }), + ], + }); + ``` + +3. Обновите вашу функцию `onRequest`, чтобы изменить данные маршрута. + + Первый аргумент, который получит ваш мидлвар, — это [объект `context` Astro](https://docs.astro.build/en/reference/api-reference/). + Он содержит полную информацию о рендеринге текущей страницы, включая текущий URL и `locals`. + + В этом примере мы сделаем нашу документацию более выразительной, добавляя восклицательный знак в конец заголовка каждой страницы. + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware((context) => { + // Получаем запись из коллекции контента для этой страницы. + const { entry } = context.locals.starlightRoute; + // Обновляем заголовок, добавляя восклицательный знак. + entry.data.title = entry.data.title + '!'; + }); + ``` + +</Steps> + +#### Несколько мидлваров для маршрута + +Starlight также поддерживает использование нескольких мидлваров. +Установите `routeMiddleware` как массив путей, чтобы добавить более одного обработчика мидлвара: + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Мой сайт с несколькими мидлварами', + routeMiddleware: ['./src/middleware-one.ts', './src/middleware-two.ts'], + }), + ], +}); +``` + +#### Ожидание выполнения последующих мидлваров для маршрута + +Чтобы дождаться выполнения мидлваров, расположенных позже в стеке, перед выполнением вашего кода, вы можете использовать `await` для вызова колбэка `next()`, передаваемого как второй аргумент в вашу функцию-мидлвар. +Это может быть полезно, если нужно дождаться выполнения мидлвара плагина перед внесением изменений. Например: + +```ts "next" "await next();" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware(async (context, next) => { + // Ожидаем выполнения последующих мидлваров. + await next(); + // Изменяем данные маршрута. + const { entry } = context.locals.starlightRoute; + entry.data.title = entry.data.title + '!'; +}); +``` diff --git a/docs/src/content/docs/ru/guides/sidebar.mdx b/docs/src/content/docs/ru/guides/sidebar.mdx new file mode 100644 index 00000000000..57365d8b913 --- /dev/null +++ b/docs/src/content/docs/ru/guides/sidebar.mdx @@ -0,0 +1,739 @@ +--- +title: Боковая панель +description: Узнайте, как установить и настроить навигационные ссылки в боковой панели сайта Starlight. +--- + +import { FileTree } from '@astrojs/starlight/components'; +import SidebarPreview from '~/components/sidebar-preview.astro'; + +Хорошо организованная боковая панель — ключ к хорошей документации, поскольку это один из основных способов навигации пользователей по вашему сайту. Starlight предоставляет полный набор опций для настройки макета и содержимого боковой панели. + +## Стандартная боковая панель + +По умолчанию Starlight автоматически генерирует боковую панель на основе структуры файловой системы вашей документации, используя свойство `title` каждого файла в качестве элемента боковой панели. + +Например, при следующей структуре файлов: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - andromeda.md + - orion.md + - stars/ + - betelgeuse.md + +</FileTree> + +Будет автоматически сгенерирована следующая боковая панель: + +<SidebarPreview + config={[ + { + label: 'constellations', + items: [ + { label: 'Андромеда', link: '' }, + { label: 'Орион', link: '' }, + ], + }, + { + label: 'stars', + items: [{ label: 'Бетельгейзе', link: '' }], + }, + ]} +/> + +Узнайте больше об автоматически генерируемых боковых панелях в разделе [Автогенерируемые группы](#автогенерируемые-группы). + +## Добавление ссылок и групп ссылок + +Чтобы настроить ссылки и группы ссылок на боковой панели (внутри сворачиваемого заголовка), используйте свойство [`starlight.sidebar`](/ru/reference/configuration/#sidebar) в `astro.config.mjs`. + +Комбинируя ссылки и группы, вы можете создавать разнообразные макеты боковой панели. + +### Внутренние ссылки + +Добавьте ссылку на страницу в `src/content/docs/`, используя объект со свойством `slug`. +Заголовок связанной страницы будет использоваться в качестве метки по умолчанию. + +Например, со следующей конфигурацией: + +```js "slug:" +starlight({ + sidebar: [ + { slug: 'constellations/andromeda' }, + { slug: 'constellations/orion' }, + ], +}); +``` + +И следующей файловой структурой: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - andromeda.md + - orion.md + +</FileTree> + +Будет создана следующая боковая панель: + +<SidebarPreview + config={[ + { label: 'Андромеда', link: '' }, + { label: 'Орион', link: '' }, + ]} +/> + +Чтобы переопределить значения, полученные из метаданных связанной страницы, вы можете добавить свойства `label`, [`translations`](#интернационализация) и [`attrs`](#пользовательские-html-атрибуты). + +См. [Настройка сгенерированных ссылок](#настройка-сгенерированных-ссылок-через-метаданные) для получения более подробной информации об управлении внешним видом боковой панели из метаданных страницы. + +#### Сокращенное обозначение внутренних ссылок + +Внутренние ссылки также можно определить, указав только строку для обозначения страницы в качестве сокращения. + +Например, следующая конфигурация эквивалентна конфигурации выше, в которой используется `slug`: + +```js "slug:" +starlight({ + sidebar: ['constellations/andromeda', 'constellations/orion'], +}); +``` + +### Другие ссылки + +Добавьте ссылку на внешнюю страницу или страницу, не являющуюся документацией, используя объект со свойствами `label` и `link`. + +```js "label:" "link:" +starlight({ + sidebar: [ + // Ссылка на страницу, не связанную с документацией, на этом сайте. + { label: 'Meteor Store', link: '/shop/' }, + // Внешняя ссылка на веб-сайт NASA. + { label: 'NASA', link: 'https://www.nasa.gov/' }, + ], +}); +``` + +Конфигурация выше создаёт следующую боковую панель: + +<SidebarPreview + config={[ + { label: 'Meteor Store', link: '' }, + { label: 'NASA', link: 'https://www.nasa.gov/' }, + ]} +/> + +### Группы + +Вы можете структурировать вашу боковую панель, группируя связанные ссылки вместе под раскрывающимся заголовком. +Группы могут содержать как ссылки, так и другие подгруппы. + +Добавьте группу, используя объект со свойствами `label` и `items`. +`label` будет использован как заголовок для группы. +Добавляйте ссылки или подгруппы в массив `items`. + +```js /^\s*(label:|items:)/ +starlight({ + sidebar: [ + // Группа ссылок с названием «Созвездия». + { + label: 'Созвездия', + items: [ + 'constellations/carina', + 'constellations/centaurus', + // Вложенная группа ссылок для сезонных созвездий. + { + label: 'Сезонные', + items: [ + 'constellations/andromeda', + 'constellations/orion', + 'constellations/ursa-minor', + ], + }, + ], + }, + ], +}); +``` + +Вышеуказанная конфигурация генерирует следующую боковую панель: + +<SidebarPreview + config={[ + { + label: 'Созвездия', + items: [ + { label: 'Карина', link: '' }, + { label: 'Центавр', link: '' }, + { + label: 'Сезонные', + items: [ + { label: 'Андромеда', link: '' }, + { label: 'Орион', link: '' }, + { label: 'Малая Медведица', link: '' }, + ], + }, + ], + }, + ]} +/> + +### Автогенерируемые группы + +Starlight может автоматически генерировать группу в вашей боковой панели, основываясь на директориях в вашей документации. +Это полезно, когда вы не хотите вручную вводить каждый элемент боковой панели в группе. + +По умолчанию страницы сортируются в алфавитном порядке в соответствии со свойством [`slug`](/ru/reference/route-data/#slug) или именем файла. + +Добавьте автогенерируемую группу, используя объект со свойствами `label` и `autogenerate`. Ваша конфигурация `autogenerate` должна указывать `directory`, которая будет использоваться для записей боковой панели. Например, со следующей конфигурацией: + +```js "label:" "autogenerate:" +starlight({ + sidebar: [ + { + label: 'Созвездия', + // Автогенерация группы ссылок для директории 'constellations'. + autogenerate: { directory: 'constellations' }, + }, + ], +}); +``` + +И следующей структурой файлов: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - carina.md + - centaurus.md + - seasonal/ + - andromeda.md + +</FileTree> + +Будет сгенерирована следующая боковая панель: + +<SidebarPreview + config={[ + { + label: 'Созвездия', + items: [ + { label: 'Карина', link: '' }, + { label: 'Центавр', link: '' }, + { + label: 'seasonal', + items: [{ label: 'Андромеда', link: '' }], + }, + ], + }, + ]} +/> + +## Настройка сгенерированных ссылок через метаданные + +Используйте [поле `sidebar`](/ru/reference/frontmatter/#sidebar) в метаданных страниц для настройки автоматически генерируемых ссылок. + +Параметры в метаданных для боковой панели позволяют установить [пользовательскую метку](/ru/reference/frontmatter/#label), использовать [пользовательские атрибуты](/ru/reference/frontmatter/#attrs), добавить [значок](/ru/reference/frontmatter/#badge) к ссылке, [скрыть](/ru/reference/frontmatter/#hidden) ссылку из боковой панели или определить [порядок её сортировки](/ru/reference/frontmatter/#order). + +```md "sidebar:" +--- +# src/content/docs/example.md +title: Моя страница +sidebar: + # Установить текст для ссылки + label: Текст в боковой панели + # Установить порядок для ссылки (чем ниже число, тем выше будет отображаться ссылка) + order: 2 + # Добавить значок к ссылке + badge: + text: Новое + variant: tip +--- +``` + +Автоматически созданная группа, включающая страницу с вышеуказанными метаданными, сгенерирует следующую боковую панель: + +<SidebarPreview + config={[ + { + label: 'Руководства', + items: [ + { label: 'Моя страница', link: '' }, + { + label: 'Текст в боковой панели', + link: '', + badge: { text: 'Новое', variant: 'tip' }, + }, + { label: 'Другая страница', link: '' }, + ], + }, + ]} +/> + +:::note +Параметр `sidebar` в метаданных используется только для ссылок в автогенерируемых группах и ссылок на документы, заданных с помощью свойства `slug`. Он не применяется к ссылкам, заданным с помощью свойства `link`. +::: + +## Значки + +Ссылки также могут включать свойство `badge` для отображения значка рядом с текстом ссылки. + +```js {9,16} +starlight({ + sidebar: [ + { + label: 'Звёзды', + items: [ + // Ссылка со значком «Сверхгигант». + { + slug: 'stars/persei', + badge: 'Сверхгигант', + }, + ], + }, + // Автогенерируемая группа со значком "Устарело". + { + label: 'Луны', + badge: 'Устарело', + autogenerate: { directory: 'moons' }, + }, + ], +}); +``` + +Конфигурация выше создаст следующую боковую панель: + +<SidebarPreview + config={[ + { + label: 'Звёзды', + items: [ + { + label: 'Персей', + link: '', + badge: { text: 'Сверхгигант', variant: 'default' }, + }, + ], + }, + { + label: 'Луны', + badge: { text: 'Устарело', variant: 'default' }, + items: [ + { + label: 'Ио', + link: '', + }, + { + label: 'Европа', + link: '', + }, + { + label: 'Ганимед', + link: '', + }, + ], + }, + ]} +/> + +### Варианты значков и индивидуальная стилизация + +Настройте стиль значка, используя объект со свойствами `text`, `variant` и `class`. + +`text` представляет содержимое для отображения (например, «Новое»). +По умолчанию значок будет использовать акцентный цвет вашего сайта. Чтобы использовать встроенный стиль значка, установите для свойства `variant` одно из следующих значений: `note`, `tip`, `danger`, `caution` или `success`. + +Кроме того, можно создать собственный стиль значка, задав свойству `class` имя класса CSS. + +```js {9} +starlight({ + sidebar: [ + { + label: 'Звёзды', + items: [ + // Ссылка с жёлтым значком «Заглушка» + { + slug: 'stars/sirius', + badge: { text: 'Заглушка', variant: 'caution' }, + }, + ], + }, + ], +}); +``` + +Конфигурация выше создаст следующую боковую панель: + +<SidebarPreview + config={[ + { + label: 'Звёзды', + items: [ + { + label: 'Сириус', + link: '', + badge: { text: 'Заглушка', variant: 'caution' }, + }, + ], + }, + ]} +/> + +Узнайте больше об [использовании и настройке значков](/ru/components/badges/#использование). + +## Пользовательские HTML-атрибуты + +Ссылки также могут включать свойство `attrs` для добавления пользовательских HTML-атрибутов к элементу ссылки. + +В следующем примере `attrs` используется для добавления атрибута `target="_blank"`, чтобы ссылка открывалась в новой вкладке, а также для применения атрибута `style`, чтобы курсивом выделить метку ссылки: + +```js {10} +starlight({ + sidebar: [ + { + label: 'Ресурсы', + items: [ + // Внешняя ссылка на сайт NASA, открывающаяся в новой вкладке. + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { target: '_blank', style: 'font-style: italic' }, + }, + ], + }, + ], +}); +``` + +Конфигурация выше создаст следующую боковую панель: + +<SidebarPreview + config={[ + { + label: 'Ресурсы', + items: [ + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { + target: '_blank', + style: 'font-style: italic', + }, + }, + ], + }, + ]} +/> + +### Пользовательские HTML-атрибуты для автоматически сгенерированных ссылок + +Настройте HTML-атрибуты всех ссылок в [автоматически сгенерированных группах](#автогенерируемые-группы), указав свойство `attrs` в конфигурации `autogenerate`. +Отдельные страницы могут задавать пользовательские атрибуты с помощью поля [`sidebar.attrs`](/ru/reference/frontmatter/#attrs) в метаданных, которое будет объединено с конфигурацией `autogenerate.attrs`. + +Например, со следующей конфигурацией: + +```js {9} +starlight({ + sidebar: [ + { + label: 'Созвездия', + autogenerate: { + // Автоматически генерируем группу ссылок для директории 'constellations' + directory: 'constellations', + // Выделяем курсивом все ярлыки ссылок в этой группе + attrs: { style: 'font-style: italic' }, + }, + }, + ], +}); +``` + +и следующей файловой структурой: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - carina.md + - centaurus.md + - seasonal/ + - andromeda.md + +</FileTree> + +Будет сгенерирована боковая панель с выделением всех автоматически созданных ссылок курсивом: + +<SidebarPreview + config={[ + { + label: 'Созвездия', + items: [ + { label: 'Карина', link: '', attrs: { style: 'font-style: italic' } }, + { + label: 'Центавр', + link: '', + attrs: { style: 'font-style: italic' }, + }, + { + label: 'seasonal', + items: [ + { + label: 'Андромеда', + link: '', + attrs: { style: 'font-style: italic' }, + }, + ], + }, + ], + }, + ]} +/> + +## Интернационализация + +Используйте свойство `translations` для записей ссылок и групп, чтобы перевести метку ссылки или группы для каждого поддерживаемого языка, указав тег языка [BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags), например, `"en"`, `"ru"` или `"zh-CN"` в качестве ключа, и перевод метки — в качестве значения. +Свойство `label` будет использоваться для локали по умолчанию и для языков без перевода. + +```js {5-7,11-13,18-20} +starlight({ + sidebar: [ + { + label: 'Созвездия', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { + label: 'Андромеда', + translations: { + 'pt-BR': 'Andrômeda', + }, + slug: 'constellations/andromeda', + }, + { + label: 'Скорпион', + translations: { + 'pt-BR': 'Escorpião', + }, + slug: 'constellations/scorpius', + }, + ], + }, + ], +}); +``` + +При просмотре документации на бразильском португальском языке будет сгенерирована следующая боковая панель: + +<SidebarPreview + config={[ + { + label: 'Constelação', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +### Интернационализация с внутренними ссылками + +[Внутренние ссылки](#внутренние-ссылки) по умолчанию будут автоматически использовать переведённые заголовки страниц из метаданных контента: + +```js {9-10} +starlight({ + sidebar: [ + { + label: 'Созвездия', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { slug: 'constellations/andromeda' }, + { slug: 'constellations/scorpius' }, + ], + }, + ], +}); +``` + +При просмотре документации на бразильском португальском языке появится следующая боковая панель: + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +На многоязычных сайтах значение `slug` не включает языковую часть URL. +Например, если у вас есть страницы `en/intro` и `pt-br/intro`, при настройке боковой панели в качестве slug будет `intro`. + +### Интернационализация с помощью значков + +Для [значков](#значки) свойство `text` может быть строкой, а для многоязычных сайтов — объектом со значениями для каждой локали. +При использовании объектной формы ключи должны быть тегами [BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags) (например: `en`, `ar` или `zh-CN`): + +```js {11-16} +starlight({ + sidebar: [ + { + label: 'Созвездия', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { + slug: 'constellations/andromeda', + badge: { + text: { + ru: 'Новинка', + 'pt-BR': 'Novo', + }, + }, + }, + ], + }, + ], +}); +``` + +При просмотре документации на бразильском португальском языке появится следующая боковая панель: + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { + label: 'Andrômeda', + link: '', + badge: { text: 'Novo', variant: 'default' }, + }, + ], + }, + ]} +/> + +## Сворачиваемые группы + +Группы ссылок могут быть свёрнуты по умолчанию, если установить свойство `collapsed` в `true`. + +```js {5-6} +starlight({ + sidebar: [ + { + label: 'Созвездия', + // Сворачивание группы по умолчанию + collapsed: true, + items: [ + items: ['constellations/andromeda', 'constellations/orion'], + ], + }, + ], +}); +``` + +Конфигурация выше создает следующую боковую панель: + +<SidebarPreview + config={[ + { + label: 'Созвездия', + collapsed: true, + items: [ + { label: 'Андромеда', link: '' }, + { label: 'Орион', link: '' }, + ], + }, + ]} +/> + +[Автогенерируемые группы](#автогенерируемые-группы) учитывают значение `collapsed` родительской группы: + +```js {5-6} +starlight({ + sidebar: [ + { + label: 'Созвездия', + // Сворачивание группы и её автогенерируемых подгрупп по умолчанию. + collapsed: true, + autogenerate: { directory: 'constellations' }, + }, + ], +}); +``` + +Конфигурация выше создает следующую боковую панель: + +<SidebarPreview + config={[ + { + label: 'Созвездия', + collapsed: true, + items: [ + { label: 'Карина', link: '' }, + { label: 'Центавр', link: '' }, + { + label: 'seasonal', + collapsed: true, + items: [{ label: 'Андромеда', link: '' }], + }, + ], + }, + ]} +/> + +Это поведение может быть переопределено путём установки свойства `autogenerate.collapsed`. + +```js {5-7} "collapsed: true" +starlight({ + sidebar: [ + { + label: 'Созвездия', + // Не сворачивать группу «Созвездия», но сворачивать её + // автоматически сгенерированные подгруппы. + collapsed: false, + autogenerate: { directory: 'constellations', collapsed: true }, + }, + ], +}); +``` + +Конфигурация выше создает следующую боковую панель: + +<SidebarPreview + config={[ + { + label: 'Созвездия', + items: [ + { label: 'Карина', link: '' }, + { label: 'Центавр', link: '' }, + { + label: 'seasonal', + collapsed: true, + items: [{ label: 'Андромеда', link: '' }], + }, + ], + }, + ]} +/> diff --git a/docs/src/content/docs/ru/guides/site-search.mdx b/docs/src/content/docs/ru/guides/site-search.mdx new file mode 100644 index 00000000000..b3669453546 --- /dev/null +++ b/docs/src/content/docs/ru/guides/site-search.mdx @@ -0,0 +1,244 @@ +--- +title: Поиск по сайту +description: Узнайте о встроенных в Starlight функциях поиска по сайту и о том, как их настроить. +tableOfContents: + maxHeadingLevel: 4 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +По умолчанию сайты Starlight включают полнотекстовый поиск на основе [Pagefind](https://pagefind.app/), который является быстрым и не требующим большой пропускной способности инструментом поиска для статических сайтов. + +Для включения поиска не требуется никакой настройки. Создайте и разверните свой сайт, а затем используйте строку поиска в шапке сайта для поиска контента. + +## Скрытие содержимого из результатов поиска + +### Исключение страницы + +Чтобы исключить страницу из поискового индекса, добавьте [`pagefind: false`](/ru/reference/frontmatter/#pagefind) в метаданных страницы: + +```md title="src/content/docs/not-indexed.md" ins={3} +--- +title: Содержимое, которое нужно скрыть от поиска +pagefind: false +--- +``` + +### Исключение части страницы + +Pagefind будет игнорировать содержимое внутри элемента с атрибутом [`data-pagefind-ignore`](https://pagefind.app/docs/indexing/#removing-individual-elements-from-the-index). + +В следующем примере первый абзац будет отображаться в результатах поиска, а содержимое `<div>` — нет: + +```md title="src/content/docs/partially-indexed.md" ins="data-pagefind-ignore" +--- +title: Частично проиндексированная страница +--- + +Этот текст можно будет найти с помощью поиска. + +<div data-pagefind-ignore> + +Этот текст будет скрыт от поиска. + +</div> +``` + +## Альтернативные поставщики услуг поиска + +### Algolia DocSearch + +Если у вас есть доступ к [программе DocSearch от Algolia](https://docsearch.algolia.com/) и вы хотите использовать её вместо Pagefind, вы можете воспользоваться официальным плагином Starlight DocSearch. + +<Steps> + +1. Установите `@astrojs/starlight-docsearch`: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-docsearch + ``` + + </TabItem> + + </Tabs> + +2. Добавьте DocSearch в конфигурацию Starlight [`plugins`](/ru/reference/configuration/#plugins) в `astro.config.mjs` и передайте ему ваши Algolia `appId`, `apiKey` и `indexName`: + + ```js ins={4,10-16} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Сайт с DocSearch', + plugins: [ + starlightDocSearch({ + appId: 'YOUR_APP_ID', + apiKey: 'YOUR_SEARCH_API_KEY', + indexName: 'YOUR_INDEX_NAME', + }), + ], + }), + ], + }); + ``` + +</Steps> + +С этой обновлённой конфигурацией строка поиска на вашем сайте теперь будет открывать модальное окно Algolia вместо стандартного модального окна поиска. + +#### Конфигурация DocSearch + +Плагин Starlight DocSearch поддерживает настройку компонента DocSearch с помощью следующих встроенных опций: + +- `maxResultsPerGroup`: Ограничивает количество результатов, отображаемых для каждой группы поиска. По умолчанию `5`. +- `disableUserPersonalization`: Предотвращает сохранение недавних поисков и избранных элементов пользователя в локальном хранилище. По умолчанию `false`. +- `insights`: Включает плагин Algolia Insights и отправляет события поиска в ваш индекс DocSearch. По умолчанию `false`. +- `searchParameters`: Объект, настраивающий [параметры поиска Algolia](https://www.algolia.com/doc/api-reference/search-api-parameters/). + +##### Дополнительные опции DocSearch + +Для передачи в компонент DocSearch параметров-функций, таких как `transformItems()` или `resultsFooterComponent()`, необходим отдельный файл конфигурации. + +<Steps> + +1. Создайте файл TypeScript, экспортирующий вашу конфигурацию DocSearch. + + ```ts + // src/config/docsearch.ts + import type { DocSearchClientOptions } from '@astrojs/starlight-docsearch'; + + export default { + appId: 'YOUR_APP_ID', + apiKey: 'YOUR_SEARCH_API_KEY', + indexName: 'YOUR_INDEX_NAME', + getMissingResultsUrl({ query }) { + return `https://github.com/algolia/docsearch/issues/new?title=${query}`; + }, + // ... + } satisfies DocSearchClientOptions; + ``` + +2. Передайте путь к вашему файлу конфигурации плагину Starlight DocSearch в `astro.config.mjs`. + + ```js {11-13} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Сайт с DocSearch', + plugins: [ + starlightDocSearch({ + clientOptionsModule: './src/config/docsearch.ts', + }), + ], + }), + ], + }); + ``` + +</Steps> + +Смотрите [Документацию по API JavaScript-клиента DocSearch](https://docsearch.algolia.com/docs/api/), чтобы узнать все поддерживаемые параметры. + +#### Перевод пользовательского интерфейса DocSearch + +По умолчанию DocSearch предоставляет только английские строки пользовательского интерфейса. +Добавьте перевод модального пользовательского интерфейса для вашего языка, используя встроенную [систему интернационализации](/ru/guides/i18n/#перевод-интерфейса-starlight) Starlight. + +<Steps> + +1. Расширьте определение коллекции контента Starlight `i18n` схемой DocSearch в файле `src/content.config.ts`: + + ```js ins={5} ins=/{ extend: .+ }/ + // src/content.config.ts + import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; + import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + import { docSearchI18nSchema } from '@astrojs/starlight-docsearch/schema'; + + export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ extend: docSearchI18nSchema() }), + }), + }; + ``` + +2. Добавьте переводы в JSON-файлы в `src/content/i18n/`. + + Это английские значения по умолчанию, используемые DocSearch: + + ```json title="src/content/i18n/en.json" + { + "docsearch.searchBox.resetButtonTitle": "Clear the query", + "docsearch.searchBox.resetButtonAriaLabel": "Clear the query", + "docsearch.searchBox.cancelButtonText": "Cancel", + "docsearch.searchBox.cancelButtonAriaLabel": "Cancel", + "docsearch.searchBox.searchInputLabel": "Search", + + "docsearch.startScreen.recentSearchesTitle": "Recent", + "docsearch.startScreen.noRecentSearchesText": "No recent searches", + "docsearch.startScreen.saveRecentSearchButtonTitle": "Save this search", + "docsearch.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", + "docsearch.startScreen.favoriteSearchesTitle": "Favorite", + "docsearch.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + + "docsearch.errorScreen.titleText": "Unable to fetch results", + "docsearch.errorScreen.helpText": "You might want to check your network connection.", + + "docsearch.footer.selectText": "to select", + "docsearch.footer.selectKeyAriaLabel": "Enter key", + "docsearch.footer.navigateText": "to navigate", + "docsearch.footer.navigateUpKeyAriaLabel": "Arrow up", + "docsearch.footer.navigateDownKeyAriaLabel": "Arrow down", + "docsearch.footer.closeText": "to close", + "docsearch.footer.closeKeyAriaLabel": "Escape key", + "docsearch.footer.searchByText": "Search by", + + "docsearch.noResultsScreen.noResultsText": "No results for", + "docsearch.noResultsScreen.suggestedQueryText": "Try searching for", + "docsearch.noResultsScreen.reportMissingResultsText": "Believe this query should return results?", + "docsearch.noResultsScreen.reportMissingResultsLinkText": "Let us know." + } + ``` + +</Steps> + +### Поисковые провайдеры от сообщества + +[Плагины от сообщества](/ru/resources/plugins/#плагины-от-сообщества) также могут предоставлять альтернативы встроенному поисковому провайдеру Pagefind от Starlight. + +#### Typesense DocSearch + +Плагин от сообщества [Starlight DocSearch Typesense](https://starlight-docsearch.typesense.org/) предоставляет полностью открытую альтернативу, которую можно развернуть на собственном сервере. Он интегрирует интерфейс [DocSearch](https://github.com/typesense/typesense-docsearch.js) с бэкендом [Typesense](https://typesense.org/). + +См. руководство [«Getting Started»](https://starlight-docsearch.typesense.org/getting-started/) в документации Starlight DocSearch Typesense, чтобы узнать, как использовать его в вашем проекте. diff --git a/docs/src/content/docs/ru/index.mdx b/docs/src/content/docs/ru/index.mdx new file mode 100644 index 00000000000..157ba8c4641 --- /dev/null +++ b/docs/src/content/docs/ru/index.mdx @@ -0,0 +1,164 @@ +--- +title: Starlight 🌟 Создавайте сайты с документацией с помощью Astro +head: + - tag: title + content: Starlight 🌟 Создавайте сайты с документацией с помощью Astro +description: Starlight помогает вам создавать красивые, высокопроизводительные веб-сайты с документацией с Astro. +template: splash +editUrl: false +lastUpdated: false +hero: + title: Сделайте свою документацию яркой с помощью Starlight + tagline: Всё, что вам нужно, чтобы создать впечатляющий сайт с документацией. Быстро, доступно и просто в использовании. + image: + file: ~/assets/hero-star.webp + actions: + - text: Начать + icon: right-arrow + link: /ru/getting-started/ + - text: Открыть в GitHub + icon: external + variant: minimal + link: https://github.com/withastro/starlight +--- + +import { CardGrid, Card } from '@astrojs/starlight/components'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; + +<CardGrid stagger> + <Card title="Документация, которая восхищает" icon="open-book"> + Включает в себя: навигацию по сайту, поиск, интернационализацию, оптимизацию + для поисковых систем (SEO), удобную типографику, подсветку кода, тёмный + режим и многое другое. + </Card> + <Card title="Работает на Astro" icon="rocket"> + Воспользуйтесь всей мощью и производительностью Astro. Расширьте Starlight с + вашими любимыми интеграциями и библиотеками Astro. + </Card> + <Card title="Markdown, Markdoc и MDX" icon="document"> + Используйте свой любимый язык разметки. Starlight предоставляет встроенную + проверку метаданных с поддержкой TypeScript для обеспечения + типобезопасности. + </Card> + <Card title="Используйте свои UI компоненты" icon="puzzle"> + Starlight не зависим от других фреймворков. Используйте с ним React, Vue, + Svelte, Solid и другие фреймворки. + </Card> +</CardGrid> + +<TestimonialGrid title="Что говорят люди"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + Команда Astro РАЗВИВАЛА способы создания документации, и вы можете получить всё это прямо из коробки с их проектом Starlight. + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + Официальный стартовый комплект Astro Starlight — поистине невероятный инструмент для создания веб-сайта документации. + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + Starlight — наш лучший пример отличного DX: скорость, удобство и + внимание к деталям вдохновляет. Он заботится о технологиях и внешнем виде, + чтобы вы могли сосредоточиться на своем контенте 👏 + + Команде StackBlitz это очень нравится! + + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + Starlight изменил правила игры для меня, позволив мне сосредоточиться на создании контента. + + Его интуитивно понятный дизайн не только оптимизирует мой рабочий процесс, но и сокращает время адаптации для разработчиков ПО с открытым исходным кодом. + + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + Потратил ещё немного времени на Starlight для документации Course Builder, и до сих пор всё было отлично. Множество приятных мелочей и возможность сосредоточиться на написании в Markdown, а не на возне с сайтом. + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + Начал играть со Starlight. Должен сказать, что я очень впечатлен производительностью «из коробки». + + 💯💯💯💯 + + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + Starlight — лучший способ начать работу с документацией: + мощь и скорость Astro и инструменты Starlight — это идеальное сочетание. + + Я уже давно это делаю и продолжаю любить! + + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + Я использовала Starlight на своей последней работе, и мне он понравился. Отличные компоненты, интуитивно понятный + дизайн и сверхотзывчивое сообщество (всякий раз, когда кому-то что-то нужно, + они очень быстро направят его в нужном направлении или подскажут обходной путь). Очень приятный опыт. + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + Документы на моем сайте монорепозитория выглядят лучше, чем когда-либо, благодаря Starlight. Его чрезвычайно легко использовать, не теряя при этом всей мощи Astro. Спасибо за работу над этим! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + Starlight — мой любимый инструмент для документирования. Благодаря этому стало очень легко добавлять документы на мой существующий веб-сайт продукта Astro, вместо того, чтобы использовать поддомен с другим инструментом. + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + Я перестраивал документацию платформы WPEngine Atlas. Поверьте мне, когда я говорю, что у Starlight есть всё необходимое для создания платформы документации A+ 🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + Попробуйте Starlight! + + Я использую его для нескольких своих сайтов, и это здорово. + + </Testimonial> +</TestimonialGrid> + +<AboutAstro title="Предоставлено вам"> +Astro — универсальный веб-фреймворк, разработанный для максимальной производительности. +Используйте контент из любых источников и развёртывайте его везде, используя ваши любимые UI-компоненты и библиотеки. + +[Узнать больше об Astro](https://astro.build/) + +</AboutAstro> diff --git a/docs/src/content/docs/ru/manual-setup.mdx b/docs/src/content/docs/ru/manual-setup.mdx new file mode 100644 index 00000000000..3372da9ac75 --- /dev/null +++ b/docs/src/content/docs/ru/manual-setup.mdx @@ -0,0 +1,135 @@ +--- +title: Установка вручную +description: Узнайте, как настроить Starlight вручную, чтобы добавить его к существующему проекту Astro. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +Самый быстрый способ создать новый сайт на Starlight - использовать `create astro`, как показано во [введении](/ru/getting-started/#создание-нового-проекта). +Если вы хотите добавить Starlight к существующему проекту Astro, это руководство расскажет, как это сделать. + +## Настройка Starlight + +Для работы по этому руководству вам понадобится существующий проект на Astro. + +### Интеграция Starlight + +Starlight является [интеграцией Astro](https://docs.astro.build/ru/guides/integrations-guide/). Добавьте её на ваш сайт, запустив команду `astro add` в корневой директории вашего проекта: + +<Tabs syncKey="pkg"> + <TabItem label="npm"> + ```sh + npx astro add starlight + ``` + + </TabItem> + <TabItem label="pnpm"> + ```sh + pnpm astro add starlight + ``` + </TabItem> + <TabItem label="Yarn"> + ```sh + yarn astro add starlight + ``` + </TabItem> + +</Tabs> + +Это установит необходимые зависимости и добавит Starlight в массив `integrations` в конфигурационном файле Astro. + +### Настройка интеграции + +Интеграция Starlight настраивается в вашем файле `astro.config.mjs`. + +Добавьте `title`, чтобы начать: + +```js ins={8} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Мой замечательный сайт с документацией', + }), + ], +}); +``` + +Найдите все доступные параметры в [справочнике конфигурации Starlight](/ru/reference/configuration/). + +### Настройка коллекций контента + +Starlight создан на основе [коллекций контента](https://docs.astro.build/ru/guides/content-collections/) Astro, которые настраиваются в файле `src/content.config.ts`. + +Создайте или обновите файл конфигурации контента, добавив коллекцию `docs`, которая использует схемы [`docsLoader`](/ru/reference/configuration/#docsloader) и [`docsSchema`](/ru/reference/configuration/#docsschema): от Starlight: + +```js ins={3-4,7} +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; +``` + +Starlight также поддерживает флаг [`legacy.collections`](https://docs.astro.build/ru/reference/legacy-flags/), при котором коллекции обрабатываются с использованием устаревшей реализации коллекций контента. +Это полезно, если у вас есть существующий проект Astro, и вы не можете в данный момент внести изменения в коллекции для использования загрузчика. + +### Добавление контента + +Starlight настроен, и пришло время добавить контент! + +Создайте директорию `src/content/docs/` и начните с добавления файла `index.md`. +Это будет главной страницей вашего нового сайта: + +```md +--- +# src/content/docs/index.md +title: Моя документация +description: Узнайте больше о моем проекте на этом сайте с документацией, созданном с помощью Starlight. +--- + +Добро пожаловать в мой проект! +``` + +Starlight использует маршрутизацию на основе файлов, что означает, что каждый файл Markdown, MDX или Markdoc в `src/content/docs/` становится страницей на вашем сайте. Метаданные в начале файла (например, поля `title` и `description` в приведённом выше примере) могут изменить отображение страниц. + +Посмотрите все доступные параметры в [справочнике по метаданным](/ru/reference/frontmatter/). + +## Советы для существующих сайтов + +Если у вас уже есть существующий проект Astro, вы можете использовать Starlight, чтобы быстро добавить раздел с документацией на ваш сайт. + +### Использование Starlight с подкаталогами + +Чтобы добавить все страницы Starlight по подкаталогу, поместите всё содержимое ваших документов в подкаталог `src/content/docs/`. + +Например, если все страницы Starlight должны начинаться с `/guides/`, добавьте свой контент в каталог `src/content/docs/guides/`: + +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src/ + - content/ + - docs/ + - **guides/** + - guide.md + - index.md + - pages/ +- astro.config.mjs + +</FileTree> + +В будущем мы планируем улучшить такой вариант использования путей, чтобы избежать необходимости в лишнем вложенном каталоге в `src/content/docs/`. + +### Использование Starlight с SSR + +Чтобы включить SSR, следуйте руководству [Адаптеры рендеринга по требованию](https://docs.astro.build/ru/guides/on-demand-rendering/) в документации Astro, для добавления серверного адаптера в ваш проект Starlight. + +Страницы документации, создаваемые Starlight, по умолчанию предварительно отрисовываются независимо от режима вывода вашего проекта. Для отключения предварительного рендеринга страниц установите для [параметра `prerender`](/ru/reference/configuration/#prerender) значение `false`. diff --git a/docs/src/content/docs/ru/reference/configuration.mdx b/docs/src/content/docs/ru/reference/configuration.mdx new file mode 100644 index 00000000000..d7a33b3371d --- /dev/null +++ b/docs/src/content/docs/ru/reference/configuration.mdx @@ -0,0 +1,820 @@ +--- +title: Конфигурация +description: Обзор всех опций конфигурации, поддерживаемых Starlight. +--- + +## Настройка интеграции `starlight` + +Starlight — это интеграция, построенная на основе веб-фреймворка [Astro](https://astro.build). Вы можете настроить свой проект в файле конфигурации `astro.config.mjs`: + +```js +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Мой восхитительный сайт документации', + }), + ], +}); +``` + +Вы можете передать следующие параметры интеграции `starlight`. + +### `title` (обязателен) + +**тип:** `string | Record<string, string>` + +Задайте название для вашего сайта. Будет использоваться в метаданных и в заголовке вкладки браузера. + +Значение может быть строкой, а для многоязычных сайтов — объектом со значениями для каждой локали. +При использовании объектной формы ключи должны быть тегами BCP-47 (например, `en`, `ru` или `zh-CN`): + +```ts +starlight({ + title: { + en: 'My delightful docs site', + ru: 'Моя восхитительная документация', + }, +}); +``` + +### `description` + +**тип:** `string` + +Задайте описание для вашего сайта. Используется в метаданных, передаваемых поисковым системам, в теге `<meta name="description">`, если `description` не задан в метаданных страницы. + +### `logo` + +**тип:** [`LogoConfig`](#logoconfig) + +Установите изображение логотипа, которое будет отображаться в навигационной панели вместе с заголовком сайта или вместо него. Вы можете задать одно свойство `src` или установить отдельные источники изображения для стилей `light` и `dark`. + +```js +starlight({ + logo: { + src: './src/assets/my-logo.svg', + }, +}); +``` + +#### `LogoConfig` + +```ts +type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( + | { src: string } + | { light: string; dark: string } +); +``` + +### `tableOfContents` + +**тип:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number }` +**по умолчанию:** `{ minHeadingLevel: 2, maxHeadingLevel: 3 }` + +Настройте оглавление, отображаемое справа на каждой странице. По умолчанию в оглавление будут включены заголовки `<h2>` и `<h3>`. + +### `editLink` + +**тип:** `{ baseUrl: string }` + +Включите ссылки "Редактировать эту страницу", задав базовый URL, который они должны использовать. Конечной ссылкой будет `editLink.baseUrl` + путь к текущей странице. Например, чтобы разрешить редактирование страниц в репозитории `withastro/starlight` на GitHub: + +```js +starlight({ + editLink: { + baseUrl: 'https://github.com/withastro/starlight/edit/main/', + }, +}); +``` + +При такой конфигурации страница `/introduction` будет иметь ссылку редактирования, указывающую на `https://github.com/withastro/starlight/edit/main/src/content/docs/introduction.md`. + +### `sidebar` + +**тип:** [`SidebarItem[]`](#sidebaritem) + +Настройте элементы навигации боковой панели вашего сайта. + +Боковая панель — это массив ссылок и групп ссылок. +За исключением элементов, использующих `slug`, каждый элемент должен иметь `label` и одно из следующих свойств: + +- `link` — одиночная ссылка на определённый URL, например, `'/home'` или `'https://example.com'`. + +- `slug` — ссылка на внутреннюю страницу, например, `'guides/getting-started'`. + +- `items` — массив, содержащий дополнительные ссылки и подгруппы боковой панели. + +- `autogenerate` — объект, указывающий каталог ваших документов для автоматической генерации группы ссылок. + +Внутренние ссылки также могут быть указаны в виде строки, а не объекта со свойством `slug`. + +```js +starlight({ + sidebar: [ + // Одиночный элемент ссылки, помеченный как «Главная». + { label: 'Главная', link: '/' }, + // Группа с надписью «Первые шаги» содержит четыре ссылки. + { + label: 'Первые шаги', + items: [ + // Использование `slug` для внутренних ссылок. + { slug: 'intro' }, + { slug: 'installation' }, + // Или использование сокращения для обозначения внутренних ссылок. + 'tutorial', + 'next-steps', + ], + }, + // Группа, связывающая все страницы директории reference. + { + label: 'Справочник', + autogenerate: { directory: 'reference' }, + }, + ], +}); +``` + +#### Сортировка + +Автогенерируемые группы боковых панелей сортируются по имени файла в алфавитном порядке. +Например, страница, созданная на основе `astro.md`, будет отображаться выше страницы для `starlight.md`. + +#### Сворачиваемые группы + +Группы ссылок раскрываются по умолчанию. Вы можете изменить это поведение, установив для свойства `collapsed` группы значение `true`. + +Автогенерируемые подгруппы по умолчанию уважают свойство `collapsed` своей родительской группы. Установите свойство `autogenerate.collapsed`, чтобы переопределить его. + +```js {5,13} +sidebar: [ + // Группа свёрнутых ссылок. + { + label: 'Свёрнутые ссылки', + collapsed: true, + items: ['intro', 'next-steps'], + }, + // Развёрнутая группа, содержащая свёрнутые автогенерируемые подгруппы. + { + label: 'Справочник', + autogenerate: { + directory: 'reference', + collapsed: true, + }, + }, +], +``` + +#### Перевод меток + +Если ваш сайт многоязычный, считается, что `label` каждого элемента соответствует локали по умолчанию. Вы можете установить свойство `translations`, чтобы предоставить метки для других поддерживаемых вами языков: + +```js {5,9,14} +sidebar: [ + // Пример боковой панели с метками, переведёнными на бразильский португальский язык. + { + label: 'Первые шаги', + translations: { 'pt-BR': 'Comece Aqui' }, + items: [ + { + label: 'Введение', + translations: { 'pt-BR': 'Introdução' }, + link: '/getting-started', + }, + { + label: 'Структура проекта', + translations: { 'pt-BR': 'Estrutura de Projetos' }, + link: '/structure', + }, + ], + }, +], +``` + +#### `SidebarItem` + +```ts +type SidebarItem = + | string + | ({ + translations?: Record<string, string>; + badge?: string | BadgeConfig; + } & ( + | { + // Обычная ссылка + link: string; + label: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // Внутренняя ссылка + slug: string; + label?: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // Группа ссылок + label: string; + items: SidebarItem[]; + collapsed?: boolean; + } + | { + // Автоматически созданная группа ссылок + label: string; + autogenerate: { + directory: string; + collapsed?: boolean; + attrs?: Record<string, string | number | boolean | undefined>; + }; + collapsed?: boolean; + } + )); +``` + +#### `BadgeConfig` + +```ts +interface BadgeConfig { + text: string; + variant?: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; + class?: string; +} +``` + +### `locales` + +**тип:** <code>\{ \[dir: string\]: [LocaleConfig](#localeconfig) \}</code> + +[Настройте интернационализацию (i18n)](/ru/guides/i18n/) для вашего сайта, установив, какие `locales` поддерживаются. + +В каждой записи в качестве ключа должен использоваться каталог, в котором хранятся файлы этого языка. + +```js +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Мой сайт', + // Устанавливаем русский язык в качестве языка по умолчанию для этого сайта. + defaultLocale: 'ru', + locales: { + // Английская документация в `src/content/docs/en/` + en: { + label: 'English', + }, + // Китайская документация в `src/content/docs/zh-cn/` + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + // Арабская документация в `src/content/docs/ar/` + ar: { + label: 'العربية', + dir: 'rtl', + }, + // Русская документация в `src/content/docs/ru/` + ru: { + label: 'Русский', + }, + }, + }), + ], +}); +``` + +#### `LocaleConfig` + +```ts +interface LocaleConfig { + label: string; + lang?: string; + dir?: 'ltr' | 'rtl'; +} +``` + +Для каждой локали можно задать следующие параметры: + +##### `label` (required) + +**тип:** `string` + +Метка для этого языка, которую нужно показывать пользователям, например, в переключателе языков. Чаще всего вы хотите, чтобы это было название языка в том виде, в котором пользователь этого языка ожидал бы его прочитать, например `"English"`, `"Русский` или `"简体中文"`. + +##### `lang` + +**тип:** `string` + +Метка BCP-47 для этого языка, например, `"en"`, `"ru"`, или `"zh-CN"`. Если не задано, то по умолчанию будет использоваться имя каталога языка. Языковые теги с региональными подтегами (например, `"pt-BR"` или `"en-US"`) будут использовать встроенные переводы пользовательского интерфейса для своего базового языка, если не будут найдены переводы для конкретного региона. + +##### `dir` + +**тип:** `'ltr' | 'rtl'` + +Направление письма на этом языке; `"ltr"` — слева направо (по умолчанию) или `"rtl"` — справа налево. + +#### Корневая локаль + +Вы можете использовать язык по умолчанию без каталога `/lang/`, установив локаль `root`: + +```js {3-6} +starlight({ + locales: { + root: { + label: 'English', + lang: 'en', + }, + ru: { + label: 'Русский', + }, + }, +}); +``` + +Например, это позволит вам обслуживать `/getting-started/` как маршрут по умолчанию и использовать `/ru/getting-started/` как эквивалентную русскую страницу. + +### `defaultLocale` + +**тип:** `string` + +Установите язык, который используется по умолчанию для этого сайта. +Значение должно соответствовать одному из ключей вашего объекта [`locales`](#locales). +(Если языком по умолчанию является ваша [корневая локаль](#корневая-локаль), это можно пропустить). + +Локаль по умолчанию будет использоваться для предоставления резервного содержимого, если перевод отсутствует. + +### `social` + +**тип:** <code>{`Array<{ label: string; icon: `}[StarlightIcon](/ru/reference/icons/){`; href: string }>`}</code> + +Необязательные данные об аккаунтах в социальных сетях для этого сайта. +Каждая запись будет отображаться в виде иконки-ссылки в шапке сайта. + +```js +starlight({ + social: [ + { icon: 'codeberg', label: 'Codeberg', href: 'https://codeberg.org/knut' }, + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro' }, + { icon: 'gitlab', label: 'GitLab', href: 'https://gitlab.com/delucis' }, + { icon: 'mastodon', label: 'Mastodon', href: 'https://m.webtoo.ls/@astro' }, + ], +}), +``` + +### `customCss` + +**тип:** `string[]` + +Предоставьте CSS-файлы для настройки внешнего вида вашего сайта Starlight. + +Поддерживаются локальные CSS-файлы относительно корня вашего проекта, например: `'./src/custom.css'`, и CSS, которые вы установили как модуль npm, например: `'@fontsource/roboto'`. + +```js +starlight({ + customCss: ['./src/custom-styles.css', '@fontsource/roboto'], +}); +``` + +### `markdown` + +**тип:** `{ headingLinks?: boolean; processedDirs?: string[] }` +**по умолчанию:** `{ headingLinks: true, processedDirs: [] }` + +Настройте обработку Markdown в Starlight. + +#### `headingLinks` + +**тип:** `boolean` +**по умолчанию:** `true` + +Определяет, будут ли заголовки отображаться с кликабельной якорной ссылкой. + +```js +starlight({ + markdown: { + // Отключаем кликабельные якорные ссылки заголовков в Starlight. + headingLinks: false, + }, +}), +``` + +#### `processedDirs` + +**тип:** `string[]` +**по умолчанию:** `[]` + +Определяет дополнительные директории, в которых файлы должны обрабатываться конвейером Markdown от Starlight. +По умолчанию Starlight обрабатывает только Markdown и MDX-файлы, загруженные через [`docsLoader()`](/ru/reference/configuration/#docsloader). +Поддерживаются локальные директории относительно корня проекта, например `'./src/data/comments/'`. + +Обработка Starlight включает [кликабельные якорные ссылки в заголовках](#headinglinks), [синтаксис директивы `<aside>`](/ru/guides/authoring-content/#вставки), и поддержку RTL для блоков кода. +Эта опция полезна, если вы выводите контент из собственной коллекции в [кастомной странице](/ru/guides/pages/#пользовательские-страницы) с помощью компонента `<StarlightPage>` и хотите, чтобы к этому контенту применялась стандартная обработка Markdown от Starlight. + +```js +starlight({ + markdown: { + // Обработка Markdown-файлов из коллекции `reviews`, расположенной в + // директории src/data/reviews/ + processedDirs: ['./src/data/reviews/'], + }, +}), +``` + +### `expressiveCode` + +**тип:** `StarlightExpressiveCodeOptions | boolean` +**по умолчанию:** `true` + +Starlight использует [Expressive Code](https://expressive-code.com) для визуализации блоков кода и добавляет поддержку выделения частей примеров кода, добавления имён файлов к блокам кода и многое другое. +Смотрите руководство [Блоки кода](/ru/guides/authoring-content/#блоки-кода), чтобы узнать, как использовать синтаксис выразительного кода в Markdown и MDX-содержимом. + +Вы также можете использовать любые стандартные [параметры конфигурации Expressive Code](https://expressive-code.com/reference/configuration/), как некоторые свойства, специфичные для Starlight, установив их в опции `expressiveCode` Starlight. +Например, установите опцию `styleOverrides` в Expressive Code, чтобы переопределить CSS по умолчанию. Это позволяет настраивать код, например, сделать блокам кода закругленные углы: + +```js ins={2-4} +starlight({ + expressiveCode: { + styleOverrides: { borderRadius: '0.5rem' }, + }, +}); +``` + +Если вы хотите отключить Expressive Code, установите `expressiveCode: false` в конфигурации Starlight: + +```js ins={2} +starlight({ + expressiveCode: false, +}); +``` + +В дополнение к стандартным параметрам Expressive Code вы также можете установить следующие свойства, специфичные для Starlight, в вашей конфигурации `expressiveCode` для дальнейшей настройки поведения темы для ваших блоков кода: + +#### `themes` + +**тип:** `Array<string | ThemeObject | ExpressiveCodeTheme>` +**по умолчанию:** `['starlight-dark', 'starlight-light']` + +Установите темы, используемые для оформления блоков кода. +См. [документацию по темам Expressive Code](https://expressive-code.com/guides/themes/) для получения подробной информации о поддерживаемых форматах тем. + +По умолчанию Starlight использует тёмный и светлый варианты [темы Night Owl](https://github.com/sdras/night-owl-vscode-theme) Сары Драснер. + +Если вы предоставите хотя бы одну тёмную и одну светлую тему, Starlight автоматически синхронизирует активную тему блока кода с текущей темой сайта. +Настройте это поведение с помощью параметра [`useStarlightDarkModeSwitch`](#usestarlightdarkmodeswitch). + +#### `useStarlightDarkModeSwitch` + +**тип:** `boolean` +**по умолчанию:** `true` + +Если установлено значение true, блоки кода автоматически переключаются между светлой и тёмной темами при изменении темы сайта. +Если установлено значение false, вам придется вручную добавить CSS для переключения между несколькими темами. + +:::note +При настройке `themes` вы должны указать хотя бы одну тёмную и одну светлую тему, чтобы переключатель темного режима Starlight работал. +::: + +#### `useStarlightUiThemeColors` + +**тип:** `boolean` +**по умолчанию:** `true` если `themes` не задано, иначе — `false` + +Если `true`, то для цветов элементов пользовательского интерфейса кодового блока (фонов, кнопок, теней и т. д.) используются CSS-переменные Starlight, соответствующие [цветовой теме сайта](/ru/guides/css-and-tailwind/#темизация). +Если `false`, то для этих элементов используются цвета, предоставляемые активной темой подсветки синтаксиса. + +:::note +При использовании пользовательских тем и установке для этого параметра значения `true` необходимо указать хотя бы одну тёмную и одну светлую тему, чтобы обеспечить правильный цветовой контраст. +::: + +### `pagefind` + +**тип:** <code>boolean | <a href="#pagefindoptions">PagefindOptions</a></code> +**по умолчанию:** `true` + +Настройте стандартный поставщик поиска по сайту Starlight — [Pagefind](https://pagefind.app/). + +Установите значение `false`, чтобы отключить индексацию вашего сайта с помощью Pagefind. +Это также скроет стандартный пользовательский интерфейс поиска, если он используется. + +Pagefind не может быть включен, если для параметра [`prerender`](#prerender) установлено значение `false`. + +Установите объект в качестве значения `pagefind` для настройки клиента поиска Pagefind: + +- Смотрите [Настройка ранжирования результатов Pagefind (English)](https://pagefind.app/docs/ranking/) в документации Pagefind для получения дополнительных сведений об использовании опции `pagefind.ranking` для управления порядком сортировки результатов поиска. +- Смотрите [Поиск по нескольким сайтам (English)](https://pagefind.app/docs/multisite/) в документации Pagefind для получения дополнительных сведений об использовании опции `pagefind.mergeIndex` для управления поиском по нескольким сайтам. + +#### `PagefindOptions` + +```ts +interface PagefindOptions { + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + indexWeight?: number; + mergeIndex?: Array<{ + bundlePath: string; + indexWeight?: number; + basePath?: string; + baseUrl?: string; + mergeFilter?: Record<string, string | string[]>; + language?: string; + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + }>; +} +``` + +### `prerender` + +**тип:** `boolean` +**по умолчанию:** `true` + +Определите, должны ли страницы Starlight предварительно отрисовываться в статический HTML или отрисовываться по требованию с помощью [SSR-адаптера](https://docs.astro.build/ru/guides/on-demand-rendering/). + +Страницы Starlight предварительно отрисовываются по умолчанию. +Если вы используете адаптер SSR и хотите рендерить страницы Starlight по требованию, установите `prerender: false`. + +### `head` + +**тип:** [`HeadConfig[]`](#headconfig) + +Добавьте пользовательские теги в `<head>` вашего сайта Starlight. +Может пригодиться для добавления аналитики и других сторонних скриптов и ресурсов. + +```js +starlight({ + head: [ + // Пример: добавляем тег скрипта аналитики Fathom. + { + tag: 'script', + attrs: { + src: 'https://cdn.usefathom.com/script.js', + 'data-site': 'MY-FATHOM-ID', + defer: true, + }, + }, + ], +}); +``` + +Записи в `head` преобразуются непосредственно в HTML-элементы и не проходят через обработку [скриптов](https://docs.astro.build/ru/guides/client-side-scripts/#обработка-скриптов) или [стилей](https://docs.astro.build/ru/guides/styling/#styling-in-astro) Astro. +Если вам нужно импортировать локальные ресурсы, такие как скрипты, стили или изображения, [переопределите компонент Head](/ru/guides/overriding-components/#переиспользование-встроенного-компонента). + +#### `HeadConfig` + +```ts +interface HeadConfig { + tag: string; + attrs?: Record<string, string | boolean | undefined>; + content?: string; +} +``` + +### `lastUpdated` + +**тип:** `boolean` +**по умолчанию:** `false` + +Укажите, показывать ли в нижнем колонтитуле дату последнего обновления страницы. + +По умолчанию эта функция полагается на историю Git вашего репозитория и может быть неточной на некоторых платформах развёртывания, создающих [копии репозитория, включающие только самый последний коммит](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt). Страница может переопределить эту настройку или дату, основанную на Git, с помощью поля [`lastUpdated` frontmatter](/ru/reference/frontmatter/#lastupdated). + +### `pagination` + +**тип:** `boolean` +**по умолчанию:** `true` + +Определите, должен ли нижний колонтитул включать ссылки на предыдущую и следующую страницы. + +Страница может переопределить эту настройку или текст ссылки и/или URL с помощью полей [`prev`](/ru/reference/frontmatter/#prev) и [`next`](/ru/reference/frontmatter/#next) в метаданных страницы. + +### `favicon` + +**тип:** `string` +**по умолчанию:** `'/favicon.svg'` + +Задайте путь к фавиконке по умолчанию для вашего сайта, который должен находиться в директории `public/` и быть валидным (`.ico`, `.gif`, `.jpg`, `.png` или `.svg`) файлом иконок. + +```js +starlight({ + favicon: '/images/favicon.svg', +}), +``` + +Если вам нужно задать дополнительные варианты или резервные фавиконки, вы можете добавить теги с помощью опции [`head`](#head): + +```js +starlight({ + favicon: '/images/favicon.svg', + head: [ + // Добавляем резервную фавиконку для Safari + { + tag: 'link', + attrs: { + rel: 'icon', + href: '/images/favicon.ico', + sizes: '32x32', + }, + }, + ], +}); +``` + +### `titleDelimiter` + +**тип:** `string` +**по умолчанию:** `'|'` + +Устанавливает разделитель между заголовком страницы и заголовком сайта в теге `<title>`, который отображается на вкладках браузера. + +По умолчанию каждая страница имеет `<title>` вида `Заголовок страницы | Заголовок сайта`. +Например, эта страница называется «Конфигурация», а этот сайт — «Starlight», поэтому `<title>` для этой страницы будет «Конфигурация | Starlight». + +### `disable404Route` + +**тип:** `boolean` +**по умолчанию:** `false` + +Отключает внедрение стандартной [страницы 404](https://docs.astro.build/ru/basics/astro-pages/#custom-404-error-page) Starlight. Чтобы использовать в своем проекте собственный маршрут `src/pages/404.astro`, установите для этого параметра значение `true`. + +### `routeMiddleware` + +**тип:** `string | string[]` + +Укажите пути к мидлвару маршрута, который может изменять обработку данных в Starlight. +Эти пути к файлам не должны конфликтовать с [мидлварами Astro](https://docs.astro.build/ru/guides/middleware/). + +Подробнее о создании мидлваров маршрута см. в [руководстве по данным маршрута](/ru/guides/route-data/#настройка-данных-маршрута). + +### `components` + +**тип:** `Record<string, string>` + +Укажите пути к компонентам для переопределения реализаций Starlight по умолчанию. + +```js +starlight({ + components: { + SocialLinks: './src/components/MySocialLinks.astro', + }, +}); +``` + +См. [Справочник по переопределениям](/ru/reference/overrides/) для получения подробной информации обо всех компонентах, которые можно переопределить. + +### `plugins` + +**тип:** [`StarlightPlugin[]`](/ru/reference/plugins/#краткая-справка-по-api) + +Расширьте Starlight с помощью пользовательских плагинов. +Плагины вносят изменения в ваш проект, чтобы изменить или добавить функции Starlight. + +Посетите [витрину плагинов](/ru/resources/plugins/#плагины), чтобы увидеть список доступных плагинов. + +```js +starlight({ + plugins: [starlightPlugin()], +}); +``` + +См. [Справочник по плагинам](/ru/reference/plugins/) для получения подробной информации о создании собственных плагинов. + +### `credits` + +**тип:** `boolean` +**по умолчанию:** `false` + +Включите отображение ссылки «Сделано с помощью Starlight» в подвале вашего сайта. + +```js +starlight({ + credits: true, +}); +``` + +## Настройка коллекций контента + +Starlight использует [коллекции контента](https://docs.astro.build/ru/guides/content-collections/) Astro для загрузки вашего контента. +Загрузчики контента и схемы Starlight помогают настроить коллекции в соответствии с вашими потребностями. + +```js +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + // Необязательно: коллекция i18n используется для перевода + // пользовательского интерфейса на многоязычных сайтах + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), +}; +``` + +### Загрузчики + +Starlight экспортирует следующие [загрузчики Astro](https://docs.astro.build/ru/reference/content-loader-reference/) из модуля `@astrojs/starlight/loaders`, чтобы упростить настройку коллекций контента. + +#### `docsLoader()` + +Загрузчик `docsLoader()` загружает локальные файлы Markdown, MDX и Markdoc из директории `src/content/docs/`. Файлы, названия которых начинаются с подчёркивания (`_`), игнорируются. + +##### Импорт + +```js +import { docsLoader } from '@astrojs/starlight/loaders'; +``` + +##### Параметры + +###### `generateId()` + +**тип:** `({ entry: string; base: URL; data: Record<string, unknown> }) => string` + +По умолчанию страницы, созданные с помощью `docsLoader()`, обрабатывают имена файлов с помощью «слагификатора» (sluggifier), который удаляет специальные символы и приводит имя к нижнему регистру. +Если вы хотите переопределить это поведение, можно предоставить собственную функцию `generateId()`. + +Например, это может быть полезно для сохранения специальных символов, которые в противном случае были бы удалены. +По умолчанию файл `Example.File.md` будет доступен по пути `/examplefile`. +Если нужно, чтобы он был доступен по пути `/Example.File`, можно определить кастомную функцию `generateId()`: + +```js +docsLoader({ + // Удаляет расширение `.md` или `.mdx`, но в остальном не изменяет названия файлов. + generateId: ({ entry }) => entry.split('.').slice(0, -1).join('.'), +}), +``` + +Подробнее см. [`generateId()` в документации Astro](https://docs.astro.build/ru/reference/content-loader-reference/#generateid). + +#### `i18nLoader()` + +Загрузчик `i18nLoader()` загружает локальные файлы JSON и YAML из директории `src/content/i18n/`. +Файлы, названия которых начинаются с подчёркивания (`_`), игнорируются. + +##### Импорт + +```js +import { i18nLoader } from '@astrojs/starlight/loaders'; +``` + +##### Параметры + +На данный момент у `i18nLoader()` нет доступных параметров. + +### Схемы + +Starlight предоставляет следующие [схемы для коллекций контента](https://docs.astro.build/ru/guides/content-collections/#%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D1%85%D0%B5%D0%BC%D1%8B-%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8) из модуля `@astrojs/starlight/schema`. +Эти схемы обязательны для использования в коллекциях `docs` и `i18n`, от которых зависит Starlight. + +#### `docsSchema()` + +`schema()` обрабатывает метаданные для всего контента в коллекции `docs`. + +##### Импорт + +```js +import { docsSchema } from '@astrojs/starlight/schema'; +``` + +##### Параметры + +###### `extend` + +**тип:** схема Zod или функция, возвращающая схему Zod +**по умолчанию:** `z.object({})` + +Расширяет схему метаданных Starlight дополнительными полями. +Подробнее об использовании опции `extend` см. в разделе [Настройка схемы метаданных](/ru/reference/frontmatter/#настройка-схемы-метаданных). + +#### `i18nSchema()` + +Схема `i18nSchema()` обрабатывает все файлы данных в коллекции `i18n`. + +##### Импорт + +```js +import { i18nSchema } from '@astrojs/starlight/schema'; +``` + +##### Параметры + +###### `extend` + +**тип:** объект Zod +**по умолчанию:** `z.object({})` + +Расширяет схему интернационализации (i18n) Starlight дополнительными полями. +Подробнее об использовании опции `extend` см. в разделе [Расширение схемы переводов](/ru/guides/i18n/#расширение-схемы-переводов). diff --git a/docs/src/content/docs/ru/reference/frontmatter.md b/docs/src/content/docs/ru/reference/frontmatter.md new file mode 100644 index 00000000000..289af10f2b5 --- /dev/null +++ b/docs/src/content/docs/ru/reference/frontmatter.md @@ -0,0 +1,473 @@ +--- +title: Метаданные +description: Обзор полей метаданных, поддерживаемых Starlight по умолчанию. +--- + +Вы можете настроить отдельные страницы Markdown и MDX в Starlight, задав значения в их метаданных. Например, на обычной странице можно задать поля `title` и `description`: + +```md {3-4} +--- +# src/content/docs/example.md +title: Об этом проекте +description: Узнайте больше о проекте, над которым я работаю. +--- + +Добро пожаловать на страницу «О сайте»! +``` + +## Поля метаданных + +### `title` (обязательно) + +**тип:** `string` + +Вы должны указать заголовок для каждой страницы. Это будет отображаться в верхней части страницы, на вкладках браузера и в метаданных страницы. + +### `description` + +**тип:** `string` + +Описание страницы используется в качестве метаданных страницы и будет воспринято поисковыми системами и в превью социальных сетей. + +### `slug` + +**type**: `string` + +Переопределите slug страницы. Более подробную информацию вы найдете в разделе [Определение пользовательских идентификаторов](https://docs.astro.build/en/guides/content-collections/#defining-custom-ids) в документации Astro. + +### `editUrl` + +**тип:** `string | boolean` + +Переопределяет [глобальную конфигурацию `editLink`](/ru/reference/configuration/#editlink). Установите значение `false`, чтобы отключить ссылку «Редактировать страницу» для конкретной страницы или предоставить альтернативный URL, по которому можно редактировать содержимое этой страницы. + +### `head` + +**тип:** [`HeadConfig[]`](/ru/reference/configuration/#headconfig) + +Вы можете добавить дополнительные теги в `<head>` вашей страницы, используя поле `head` метаданных. Это означает, что вы можете добавлять пользовательские стили, метаданные и другие теги на одну страницу. Аналогично [глобальной опции `head`](/ru/reference/configuration/#head). + +```md +--- +# src/content/docs/example.md +title: О нас +head: + # Используем свой тег <title> + - tag: title + content: Пользовательский заголовок +--- +``` + +### `tableOfContents` + +**тип:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` + +Переопределяет [глобальную конфигурацию `tableOfContents`](/ru/reference/configuration/#tableofcontents). +Настройте уровни заголовков, которые будут включены, или установите значение `false`, чтобы скрыть оглавление на этой странице. + +```md +--- +# src/content/docs/example.md +title: Страница, содержащая только H2 в оглавлении +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 2 +--- +``` + +```md +--- +# src/content/docs/example.md +title: Страница без оглавления +tableOfContents: false +--- +``` + +### `template` + +**тип:** `'doc' | 'splash'` +**по умолчанию:** `'doc'` + +Установите шаблон макета для этой страницы. +Страницы используют макет `'doc'` по умолчанию. +Установите значение `'splash'`, чтобы использовать более широкий макет без боковых панелей, предназначенный для целевых страниц. + +### `hero` + +**тип:** [`HeroConfig`](#heroconfig) + +Добавьте компонент hero в верхнюю часть этой страницы. Хорошо сочетается с `template: splash`. + +Например, в этом конфиге показаны некоторые общие опции, включая загрузку изображения из вашего репозитория. + +```md +--- +# src/content/docs/example.md +title: Моя домашняя страница +template: splash +hero: + title: 'Мой проект: Быстрая доставка в космосе' + tagline: Доставьте свои вещи на Луну и обратно в мгновение ока. + image: + alt: Сверкающий, ярко раскрашенный логотип + file: ~/assets/logo.png + actions: + - text: Расскажите мне больше + link: /getting-started/ + icon: right-arrow + - text: Просмотр на GitHub + link: https://github.com/astronaut/my-project + icon: external + variant: minimal + attrs: + rel: me +--- +``` + +Вы можете отображать разные версии главного изображения в светлом и тёмном режимах. + +```md +--- +# src/content/docs/example.md +hero: + image: + alt: Сверкающий, ярко раскрашенный логотип + dark: ~/assets/logo-dark.png + light: ~/assets/logo-light.png +--- +``` + +#### `HeroConfig` + +```ts +interface HeroConfig { + title?: string; + tagline?: string; + image?: + | { + // Относительный путь к изображению в вашем репозитории. + file: string; + // Alt-текст, чтобы сделать изображение доступным для вспомогательных технологий + alt?: string; + } + | { + // Относительный путь к изображению в вашем репозитории, которое будет использоваться для тёмного режима. + dark: string; + // Относительный путь к изображению в вашем репозитории, которое будет использоваться для светлого режима. + light: string; + // Alt-текст, чтобы сделать изображение доступным для вспомогательных технологий + alt?: string; + } + | { + // Необработанный HTML для использования в слоте изображения. + // Это может быть пользовательский тег `<img>` или встроенный `<svg>`. + html: string; + }; + actions?: Array<{ + text: string; + link: string; + variant?: 'primary' | 'secondary' | 'minimal'; + icon?: string; + attrs?: Record<string, string | number | boolean>; + }>; +} +``` + +### `banner` + +**тип:** `{ content: string }` + +Отображает баннер объявления в верхней части этой страницы. + +Значение `content` может включать HTML для ссылок или другого содержимого. +Например, на этой странице отображается баннер со ссылкой на `example.com`. + +```md +--- +# src/content/docs/example.md +title: Страница с баннером +banner: + content: | + Мы только что запустили нечто крутое! + <a href="https://example.com">Проверьте</a> +--- +``` + +### `lastUpdated` + +**тип:** `Date | boolean` + +Переопределяет [глобальную опцию `lastUpdated`](/ru/reference/configuration/#lastupdated). Если указана дата, она должна быть действительной [временной меткой YAML](https://yaml.org/type/timestamp.html) и будет переопределять дату, хранящуюся в истории Git для этой страницы. + +```md +--- +# src/content/docs/example.md +title: Страница с пользовательской датой последнего обновления +lastUpdated: 2022-08-09 +--- +``` + +### `prev` + +**тип:** `boolean | string | { link?: string; label?: string }` + +Переопределяет [глобальную опцию `pagination`](/ru/reference/configuration/#pagination). Если указана строка, будет заменен сгенерированный текст ссылки, а если указан объект, будут переопределены и ссылка, и текст. + +```md +--- +# src/content/docs/example.md +# Скрываем ссылку на предыдущую страницу +prev: false +--- +``` + +```md +--- +# src/content/docs/example.md +# Переопределяем текст ссылки на предыдущую страницу +prev: Продолжить обучение +--- +``` + +```md +--- +# src/content/docs/example.md +# Переопределяем ссылку и текст предыдущей страницы +prev: + link: /unrelated-page/ + label: Загляните на другую страницу +--- +``` + +### `next` + +**тип:** `boolean | string | { link?: string; label?: string }` + +То же самое, что и [`prev`](#prev), но для ссылки на следующую страницу. + +```md +--- +# src/content/docs/example.md +# Скрываем ссылку на следующую страницу +next: false +--- +``` + +### `pagefind` + +**тип:** `boolean` +**по умолчанию:** `true` + +Установите, должна ли эта страница быть включена в поисковый индекс [Pagefind](https://pagefind.app/). Установите значение `false`, чтобы исключить страницу из результатов поиска: + +```md +--- +# src/content/docs/example.md +# Скрываем эту страницу из поискового индекса +pagefind: false +--- +``` + +### `draft` + +**тип:** `boolean` +**по умолчанию:** `false` + +Установите, следует ли считать эту страницу черновиком и не включать её в [продакшен-сборки](https://docs.astro.build/ru/reference/cli-reference/#astro-build). Установите значение `true`, чтобы пометить страницу как черновик и сделать её видимой только во время разработки. + +```md +--- +# src/content/docs/example.md +# Исключить эту страницу из продакшен-сборок +draft: true +--- +``` + +Поскольку черновики страниц не включаются в выходные данные сборки, вы не можете добавить черновики страниц напрямую в конфигурацию боковой панели вашего сайта, используя [слаги](/ru/guides/sidebar/#внутренние-ссылки). +Черновики страниц в каталогах, используемых для [автоматически сгенерированных групп боковой панели](/ru/guides/sidebar/#автогенерируемые-группы), автоматически исключаются в продакшен-сборках. + +### `sidebar` + +**тип:** [`SidebarConfig`](#sidebarconfig) + +Управление отображением этой страницы в [боковой панели](/ru/reference/configuration/#sidebar) при использовании автогенерируемой группы ссылок. + +#### `SidebarConfig` + +```ts +interface SidebarConfig { + label?: string; + order?: number; + hidden?: boolean; + badge?: string | BadgeConfig; + attrs?: Record<string, string | number | boolean | undefined>; +} +``` + +#### `label` + +**тип:** `string` +**по умолчанию:** [`title`](#title-обязательно) страницы + +Устанавливает метку для этой страницы в боковой панели при отображении в автогенерируемой группе ссылок. + +```md +--- +# src/content/docs/example.md +title: Об этом проекте +sidebar: + label: О сайте +--- +``` + +#### `order` + +**тип:** `number` + +Управляйте порядком этой страницы при сортировке автоматически созданной группы ссылок. +Страницы с меньшим значением параметра `order` отображаются выше в группе ссылок. + +```md +--- +# src/content/docs/example.md +title: Страница, которая будет отображаться первой +sidebar: + order: 1 +--- +``` + +#### `hidden` + +**тип:** `boolean` +**по умолчанию:** `false` + +Запрещает включать эту страницу в автоматически создаваемую группу боковой панели. + +```md +--- +# src/content/docs/example.md +title: Страница, которую нужно скрыть из автоматически созданной боковой панели +sidebar: + hidden: true +--- +``` + +#### `badge` + +**тип:** <code>string | <a href="/ru/reference/configuration/#badgeconfig">BadgeConfig</a></code> + +Добавьте значок на страницу в боковой панели, если она отображается в автогенерируемой группе ссылок. +При использовании строки значок будет отображаться с акцентным цветом по умолчанию. +В качестве опции передайте объект [`BadgeConfig`](/ru/reference/configuration/#badgeconfig) с полями `text`, `variant` и `class` для настройки значка. + +```md +--- +# src/content/docs/example.md +title: Страница со значком +sidebar: + # Используется вариант по умолчанию, соответствующий акцентному цвету вашего сайта + badge: Новое +--- +``` + +```md +--- +# src/content/docs/example.md +title: Страница со значком +sidebar: + badge: + text: Экспериментально + variant: caution +--- +``` + +#### `attrs` + +**тип:** `Record<string, string | number | boolean | undefined>` + +Атрибуты HTML для добавления к ссылке на страницу в боковой панели при отображении в автогенерируемой группе ссылок. +Если поле [`autogenerate.attrs`](/ru/guides/sidebar/#пользовательские-html-атрибуты-для-автоматически-сгенерированных-ссылок) установлено для автоматически сгенерированной группы, к которой относится эта страница, атрибуты в метаданных будут объединены с атрибутами группы. + +```md +--- +# src/content/docs/example.md +title: Открытие страницы в новой вкладке +sidebar: + # Открывает страницу в новой вкладке + attrs: + target: _blank +--- +``` + +## Настройка схемы метаданных + +Схема метаданных для коллекции контента Starlight `docs` настраивается в файле `src/content.config.ts` с помощью хелпера `docsSchema()`: + +```ts {4,7} +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; +``` + +Подробнее о схемах коллекций содержимого читайте в разделе [Определение схемы коллекции](https://docs.astro.build/ru/guides/content-collections/#%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D1%85%D0%B5%D0%BC%D1%8B-%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8) в документации Astro. + +`docsSchema()` принимает следующие параметры: + +### `extend` + +**тип:** Схема Zod или функция, возвращающая схему Zod +**по умолчанию:** `z.object({})` + +Расширьте схему Starlight дополнительными полями, задав `extend` в опциях `docsSchema()`. +Значение должно быть [схемой Zod](https://docs.astro.build/ru/guides/content-collections/#defining-datatypes-with-zod). + +В следующем примере мы задаем более строгий тип для `description`, чтобы сделать его обязательным, и добавляем новое необязательное поле `category`: + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: z.object({ + // Делаем встроенное поле обязательным + description: z.string(), + // Добавляем новое поле в схему + category: z.enum(['tutorial', 'guide', 'reference']).optional(), + }), + }), + }), +}; +``` + +Чтобы воспользоваться преимуществами [хелпера `image()`](https://docs.astro.build/ru/guides/images/#images-in-content-collections), используйте функцию, которая возвращает расширение вашей схемы: + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: ({ image }) => { + return z.object({ + // Добавляем поле, которое должно разрешаться в локальное изображение + cover: image(), + }); + }, + }), + }), +}; +``` diff --git a/docs/src/content/docs/ru/reference/icons.mdx b/docs/src/content/docs/ru/reference/icons.mdx new file mode 100644 index 00000000000..78554bb3297 --- /dev/null +++ b/docs/src/content/docs/ru/reference/icons.mdx @@ -0,0 +1,32 @@ +--- +title: Иконки +description: Обзор всех иконок, доступных в Starlight. +--- + +Starlight предоставляет набор общих иконок, которые вы можете отображать в своем контенте, используя компонент `<Icon>`. + +## Использование иконок + +Иконки можно отображать с помощью компонента [`<Icon>`](/ru/components/icons/). +Они также часто используются в других компонентах, таких как [карточки](/ru/components/cards/) или в настройках, таких как [hero](/ru/reference/frontmatter/#hero). + +## Тип `StarlightIcon` + +Используйте тип TypeScript `StarlightIcon`, чтобы ссылаться на названия [встроенных иконок Starlight](#все-иконки). + +```ts {2} /icon: (StarlightIcon)/ +// src/icon.ts +import type { StarlightIcon } from '@astrojs/starlight/types'; + +function getIconLabel(icon: StarlightIcon) { + // … +} +``` + +## Все иконки + +Список всех доступных иконок показан ниже с их соответствующими именами. Кликните по значку, чтобы скопировать код компонента для него. + +import IconsList from '~/components/icons-list.astro'; + +<IconsList labels={{ copied: 'Скопировано!' }} /> diff --git a/docs/src/content/docs/ru/reference/overrides.md b/docs/src/content/docs/ru/reference/overrides.md new file mode 100644 index 00000000000..0ef1c21bceb --- /dev/null +++ b/docs/src/content/docs/ru/reference/overrides.md @@ -0,0 +1,261 @@ +--- +title: Переопределения +description: Обзор компонентов и параметров компонентов, поддерживаемых переопределениями Starlight. +tableOfContents: + maxHeadingLevel: 4 +--- + +Вы можете переопределить встроенные компоненты Starlight, указав пути к заменяющим компонентам в опции конфигурации Starlight [`components`](/ru/reference/configuration/#components). +На этой странице перечислены все компоненты, доступные для переопределения, и даны ссылки на их реализации по умолчанию на GitHub. + +Подробнее см. в [Руководстве по переопределению компонентов](/ru/guides/overriding-components/). + +## Компоненты + +### Элемент `head` + +Эти компоненты отображаются внутри элемента `<head>` каждой страницы. +Они должны включать только [элементы, разрешённые внутри `<head>`](https://developer.mozilla.org/ru/docs/Web/HTML/Element/head#%D1%81%D0%BC%D0%BE%D1%82%D1%80%D0%B8%D1%82%D0%B5_%D1%82%D0%B0%D0%BA%D0%B6%D0%B5). + +#### `Head` + +**Стандартный компонент:** [`Head.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Head.astro) + +Компонент, отображаемый внутри `<head>` каждой страницы. + +Переопределяйте этот компонент только в крайнем случае. +По возможности используйте [параметр `head` в конфигурации](/ru/reference/configuration/#head), [поле `head` в метаданных](/ru/reference/frontmatter/#head) или [мидлвар для данных маршрута](/ru/guides/route-data/#настройка-данных-маршрута), чтобы настроить данные маршрута, отображаемые компонентом по умолчанию. + +#### `ThemeProvider` + +**Стандартный компонент:** [`ThemeProvider.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeProvider.astro) + +Компонент, отображаемый внутри `<head>`, который устанавливает поддержку тёмной/светлой темы. +Реализация по умолчанию включает в себя встроенный скрипт и `<template>`, используемый скриптом в [`<ThemeSelect />`](#themeselect). + +--- + +### Доступность + +#### `SkipLink` + +**Стандартный компонент:** [`SkipLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SkipLink.astro) + +Компонент, отображаемый как первый элемент внутри `<body>`, который ссылается на основное содержимое страницы для обеспечения доступности. +Реализация по умолчанию скрыта до тех пор, пока пользователь не наведет на нее курсор с помощью табуляции на клавиатуре. + +--- + +### Макет + +Эти компоненты отвечают за компоновку компонентов Starlight и управление представлениями в различных точках останова. +Их переопределение сопряжено со значительными сложностями. +По возможности предпочитайте переопределять компоненты более низкого уровня. + +#### `PageFrame` + +**Стандартный компонент:** [`PageFrame.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageFrame.astro) +**Именованные слоты:** `header`, `sidebar` + +Компонент макета оборачивается вокруг большей части содержимого страницы. +Реализация по умолчанию устанавливает макет header-sidebar-main и включает в себя именованные слоты `header` и `sidebar`, а также слот по умолчанию для основного содержимого. +Он также отображает [`<MobileMenuToggle />`](#mobilemenutoggle) для поддержки переключения навигации в боковой панели на маленьких (мобильных) экранах просмотра. + +#### `MobileMenuToggle` + +**Стандартный компонент:** [`MobileMenuToggle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuToggle.astro) + +Компонент, отображаемый внутри [`<PageFrame>`](#pageframe), который отвечает за переключение навигации боковой панели на маленьких (мобильных) экранах просмотра. + +#### `TwoColumnContent` + +**Стандартный компонент:** [`TwoColumnContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TwoColumnContent.astro) +**Именованный слот:** `right-sidebar` + +Компонент макета оборачивается вокруг колонки с основным содержанием и правой боковой панели (оглавление). +Реализация по умолчанию управляет переключением между одноколоночным макетом с малой областью просмотра и двухколоночным макетом с большей областью просмотра. + +--- + +### Шапка + +Эти компоненты отображают верхнюю навигационную панель Starlight. + +#### `Header` + +**Стандартный компонент:** [`Header.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Header.astro) + +Компонент заголовка отображается в верхней части каждой страницы. +По умолчанию отображаются [`<SiteTitle />`](#sitetitle), [`<Search />`](#search), [`<SocialIcons />`](#socialicons), [`<ThemeSelect />`](#themeselect), и [`<LanguageSelect />`](#languageselect). + +#### `SiteTitle` + +**Стандартный компонент:** [`SiteTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SiteTitle.astro) + +Компонент, отображаемый в начале заголовка сайта для отображения заголовка сайта. +Реализация по умолчанию включает логику для отрисовки логотипов, определённую в конфигурации Starlight. + +#### `Search` + +**Стандартный компонент:** [`Search.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Search.astro) + +Компонент, используемый для отображения пользовательского интерфейса поиска Starlight. +Реализация по умолчанию включает кнопку в заголовке и код для отображения модального окна поиска при нажатии на нее и загрузки [интерфейса Pagefind](https://pagefind.app/). + +Когда [`pagefind`](/ru/reference/configuration/#pagefind) отключен, компонент поиска по умолчанию не будет отображаться. +Однако если вы переопределите `Search`, ваш пользовательский компонент будет отображаться всегда, даже если параметр конфигурации `pagefind` будет равен `false`. +Это позволяет добавить пользовательский интерфейс для альтернативных поставщиков поиска при отключении Pagefind. + +#### `SocialIcons` + +**Стандартный компонент:** [`SocialIcons.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SocialIcons.astro) + +Компонент, отображаемый в шапке сайта, включая ссылки на социальные иконки. +Реализация по умолчанию использует опцию [`social`](/ru/reference/configuration/#social) в конфигурации Starlight для отображения иконок и ссылок. + +#### `ThemeSelect` + +**Стандартный компонент:** [`ThemeSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeSelect.astro) + +Компонент, отображаемый в шапке сайта, который позволяет пользователям выбрать желаемую цветовую схему. + +#### `LanguageSelect` + +**Стандартный компонент:** [`LanguageSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LanguageSelect.astro) + +Компонент, отображаемый в заголовке сайта, который позволяет пользователям переключиться на другой язык. + +--- + +### Глобальная боковая панель + +В глобальной боковой панели Starlight находится основная навигация сайта. +На узких экранах она скрывается за выпадающим меню. + +#### `Sidebar` + +**Стандартный компонент:** [`Sidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Sidebar.astro) + +Компонент, отображаемый перед содержимым страницы, содержащим глобальную навигацию. +Реализация по умолчанию отображается в виде боковой панели на достаточно широких экранах и в виде выпадающего меню на маленьких (мобильных) экранах. +Он также отображает [`<MobileMenuFooter />`](#mobilemenufooter), чтобы показать дополнительные пункты внутри мобильного меню. + +#### `MobileMenuFooter` + +**Стандартный компонент:** [`MobileMenuFooter.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuFooter.astro) + +Компонент, отображаемый в нижней части мобильного выпадающего меню. +Реализация по умолчанию отображает [`<ThemeSelect />`](#themeselect) и [`<LanguageSelect />`](#languageselect). + +--- + +### Боковая панель страницы + +Боковая панель страницы Starlight отвечает за отображение оглавления, в котором указаны подзаголовки текущей страницы. +На узких экранах это сворачивается в липкое выпадающее меню. + +#### `PageSidebar` + +**Стандартный компонент:** [`PageSidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageSidebar.astro) + +Компонент, отображаемый перед содержимым главной страницы для вывода оглавления. +Реализация по умолчанию отображает [`<TableOfContents />`](#tableofcontents) и [`<MobileTableOfContents />`](#mobiletableofcontents). + +#### `TableOfContents` + +**Стандартный компонент:** [`TableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TableOfContents.astro) + +Компонент, который отображает оглавление текущей страницы на широких экранах просмотра. + +#### `MobileTableOfContents` + +**Стандартный компонент:** [`MobileTableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileTableOfContents.astro) + +Компонент, который отображает оглавление текущей страницы на маленьких (мобильных) экранах просмотра. + +--- + +### Контент + +Эти компоненты отображаются в основной колонке содержимого страницы. + +#### `Banner` + +**Стандартный компонент:** [`Banner.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Banner.astro) + +Баннерный компонент, отображаемый в верхней части каждой страницы. +Реализация по умолчанию использует значение [`banner`](/ru/reference/frontmatter/#banner) метаданных страницы для принятия решения о необходимости отрисовки. + +#### `ContentPanel` + +**Стандартный компонент:** [`ContentPanel.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ContentPanel.astro) + +Компонент макета, используемый для обёртывания секций колонки основного содержимого. + +#### `PageTitle` + +**Стандартный компонент:** [`PageTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageTitle.astro) + +Компонент, содержащий элемент `<h1>` для текущей страницы. + +Реализации должны обеспечить установку `id="_top"` для элемента `<h1>`, как в реализации по умолчанию. + +#### `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) + +Уведомление, отображаемое пользователям на страницах, где перевод на текущий язык недоступен. +Используется только на многоязычных сайтах. + +#### `Hero` + +**Стандартный компонент:** [`Hero.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Hero.astro) + +Компонент, отображаемый в верхней части страницы, когда в метаданных задан параметр [`hero`](/ru/reference/frontmatter/#hero). +В стандартном варианте на экране отображается крупный заголовок, теглайн и ссылки, призывающие к действию, а также дополнительное изображение. + +#### `MarkdownContent` + +**Стандартный компонент:** [`MarkdownContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MarkdownContent.astro) + +Компонент отображается вокруг основного содержимого каждой страницы. +Реализация по умолчанию устанавливает базовые стили для применения к содержимому Markdown. + +Стили контента Markdown также представлены в `@astrojs/starlight/style/markdown.css` и ограничены классом CSS `.sl-markdown-content`. + +--- + +### Подвал + +Эти компоненты отображаются внизу основного столбца содержимого страницы. + +#### `Footer` + +**Стандартный компонент:** [`Footer.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Footer.astro) + +Компонент нижнего колонтитула отображается внизу каждой страницы. +Реализация по умолчанию отображает [`<LastUpdated />`](#lastupdated), [`<Pagination />`](#pagination) и [`<EditLink />`](#editlink). + +#### `LastUpdated` + +**Стандартный компонент:** [`LastUpdated.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LastUpdated.astro) + +Компонент отображается в нижнем колонтитуле страницы для отображения даты последнего обновления. + +#### `EditLink` + +**Стандартный компонент:** [`EditLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/EditLink.astro) + +Компонент, отображаемый в нижнем колонтитуле страницы для отображения ссылки на страницу, где её можно редактировать. + +#### `Pagination` + +**Стандартный компонент:** [`Pagination.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Pagination.astro) + +Компонент отображается в нижнем колонтитуле страницы для отображения стрелок навигации между предыдущими и следующими страницами. diff --git a/docs/src/content/docs/ru/reference/plugins.md b/docs/src/content/docs/ru/reference/plugins.md new file mode 100644 index 00000000000..2b98280ef6c --- /dev/null +++ b/docs/src/content/docs/ru/reference/plugins.md @@ -0,0 +1,380 @@ +--- +title: Плагины +description: Обзор API плагинов Starlight. +tableOfContents: + maxHeadingLevel: 4 +--- + +Плагины Starlight могут настраивать конфигурацию, пользовательский интерфейс и поведение Starlight, а также легко распространяться и использоваться повторно. +На этой справочной странице описаны API, к которым имеют доступ плагины. + +Подробнее об использовании плагинов Starlight можно узнать в разделе [Конфигурация](/ru/reference/configuration/#plugins) или на [Витрине плагинов](/ru/resources/plugins/#плагины), чтобы посмотреть список доступных плагинов. + +## Краткая справка по API + +Плагин Starlight имеет следующую форму. +Подробнее о различных свойствах и параметрах хуков см. ниже. + +<!-- prettier-ignore-start --> + +```ts +interface StarlightPlugin { + name: string; + hooks: { + 'i18n:setup'?: (options: { + injectTranslations: ( + translations: Record<string, Record<string, string>> + ) => void; + }) => void | Promise<void>; + 'config:setup': (options: { + config: StarlightUserConfig; + updateConfig: (newConfig: StarlightUserConfig) => void; + addIntegration: (integration: AstroIntegration) => void; + addRouteMiddleware: (config: { + entrypoint: string; + order?: 'pre' | 'post' | 'default'; + }) => void; + astroConfig: AstroConfig; + command: 'dev' | 'build' | 'preview'; + isRestart: boolean; + logger: AstroIntegrationLogger; + useTranslations: (lang: string) => I18nT; + absolutePathToLang: (path: string) => string; + }) => void | Promise<void>; + }; +} +``` + +<!-- prettier-ignore-start --> + +## `name` + +**тип:** `string` + +Плагин должен иметь уникальное имя, описывающее его. Имя используется при [регистрации сообщений](#logger), связанных с этим плагином, и может использоваться другими плагинами для определения присутствия этого плагина. + +## `hooks` + +Хуки — это функции, которые Starlight вызывает для запуска кода плагина в определённое время. + +Чтобы получить тип аргументов хука, используйте утилиту `HookParameters` и передайте в неё имя хука. +В следующем примере параметр `options` типизирован таким образом, чтобы соответствовать аргументам, передаваемым в хук `config:setup`: + +```ts +import type { HookParameters } from '@astrojs/starlight/types'; + +function configSetup(options: HookParameters['config:setup']) { + options.useTranslations('ru'); +} +``` + +### `i18n:setup` + +Функция настройки интернационализации плагина, вызываемая при инициализации Starlight. +Хук `i18n:setup` можно использовать для добавления строк перевода, чтобы плагин поддерживал разные локали. +Эти переводы будут доступны через [`useTranslations()`](#usetranslations) в хуке `config:setup` и в UI-компонентах через [`Astro.locals.t()`](/ru/guides/i18n/#использование-ui-переводов). + +Хук `i18n:setup` вызывается со следующими параметрами: + +#### `injectTranslations` + +**тип:** `(translations: Record<string, Record<string, string>>) => void` + +Функция обратного вызова для добавления или обновления строк перевода, используемых в [API локализации](/ru/guides/i18n/#использование-ui-переводов) Starlight. + +В следующем примере плагин добавляет переводы для пользовательской строки интерфейса `myPlugin.doThing` для локалей `en` и `ru`: + +```ts {6-13} /(injectTranslations)[^(]/ +// plugin.ts +export default { + name: 'plugin-with-translations', + hooks: { + 'i18n:setup'({ injectTranslations }) { + injectTranslations({ + en: { + 'myPlugin.doThing': 'Do the thing', + }, + ru: { + 'myPlugin.doThing': 'Делаем что-то', + }, + }); + }, + }, +}; +``` + +Чтобы использовать добавленные переводы в интерфейсе вашего плагина, следуйте [руководству по использованию UI-переводов](/ru/guides/i18n/#использование-ui-переводов). +Если вам нужно использовать строки интерфейса в контексте хука [`config:setup`](#configsetup) вашего плагина, примените функцию [`useTranslations()`](#usetranslations). + +Типы для строк перевода, добавленных плагином, автоматически генерируются в проекте пользователя, но пока недоступны при работе с кодовой базой самого плагина. +Чтобы задать тип объекта `locals.t` в контексте вашего плагина, объявите следующие глобальные пространства имён в файле деклараций TypeScript: + +```ts +// env.d.ts +declare namespace App { + type StarlightLocals = import('@astrojs/starlight').StarlightLocals; + // Определяем объект `locals.t` в контексте плагина. + interface Locals extends StarlightLocals {} +} + +declare namespace StarlightApp { + // Определяем дополнительные переводы плагина в интерфейсе `I18n`. + interface I18n { + 'myPlugin.doThing': string; + } +} +``` + +Вы также можете вывести типы для интерфейса `StarlightApp.I18n` из исходного файла, если у вас есть объект, содержащий ваши переводы. + +Например, для следующего исходного файла: + +```ts title="ui-strings.ts" +export const UIStrings = { + en: { 'myPlugin.doThing': 'Do the thing' }, + ru: { 'myPlugin.doThing': 'Делаем что-то' }, +}; +``` + +Следующее объявление будет выводить типы на основе английских ключей в исходном файле: + +```ts title="env.d.ts" +declare namespace StarlightApp { + type UIStrings = typeof import('./ui-strings').UIStrings.en; + interface I18n extends UIStrings {} +} +``` + +### `config:setup` + +Функция настройки конфигурации плагина, вызываемая при инициализации Starlight (во время выполнения хука интеграции [`astro:config:setup`](https://docs.astro.build/ru/reference/integrations-reference/#astroconfigsetup)). +Хук `config:setup` можно использовать для обновления конфигурации Starlight или добавления интеграций Astro. + +Этот хук вызывается со следующими параметрами: + +#### `config` + +**тип:** `StarlightUserConfig` + +Доступная только для чтения копия предоставленной пользователем [конфигурации Starlight](/ru/reference/configuration/). +Эта конфигурация могла быть обновлена другими плагинами, настроенными до текущего. + +#### `updateConfig` + +**тип:** `(newConfig: StarlightUserConfig) => void` + +Функция обратного вызова для обновления предоставленной пользователем [конфигурации Starlight](/ru/reference/configuration/). +Укажите ключи конфигурации корневого уровня, которые вы хотите отменить. +Чтобы обновить значения вложенной конфигурации, необходимо предоставить весь вложенный объект. + +Чтобы расширить существующий параметр конфигурации, не переопределяя его, добавьте существующее значение в новое. +В следующем примере новый аккаунт в [`social`](/ru/reference/configuration/#social) добавляется в существующую конфигурацию путем расширения `config.social` в новом массиве `social`: + +```ts {6-15} +// plugin.ts +export default { + name: 'add-twitter-plugin', + hooks: { + 'config:setup'({ config, updateConfig }) { + updateConfig({ + social: [ + ...config.social, + { + icon: 'twitter', + label: 'Twitter', + href: 'https://twitter.com/astrodotbuild', + }, + ], + }); + }, + }, +}; +``` + +#### `addIntegration` + +**тип:** `(integration: AstroIntegration) => void` + +Функция обратного вызова для добавления [интеграции Astro](https://docs.astro.build/ru/reference/integrations-reference/), необходимой плагину. + +В следующем примере плагин сначала проверяет, настроена ли [интеграция Astro с React](https://docs.astro.build/ru/guides/integrations-guide/react/), и, если нет, использует `addIntegration()` для её добавления: + +```ts {14} "addIntegration," +// plugin.ts +import react from '@astrojs/react'; + +export default { + name: 'plugin-using-react', + hooks: { + 'config:setup'({ addIntegration, astroConfig }) { + const isReactLoaded = astroConfig.integrations.find( + ({ name }) => name === '@astrojs/react' + ); + + // Добавляем интеграцию React только в том случае, если она ещё не загружена. + if (!isReactLoaded) { + addIntegration(react()); + } + }, + }, +}; +``` + +#### `addRouteMiddleware` + +**тип:** `(config: { entrypoint: string; order?: 'pre' | 'post' | 'default' }) => void` + +Функция обратного вызова для добавления [мидлвара-обработчика маршрутов](/ru/guides/route-data/) на сайт. + +Свойство `entrypoint` должно быть указателем модуля для файла мидлвара вашего плагина, который экспортирует обработчик `onRequest`. + +В следующем примере плагин, опубликованный как `@example/starlight-plugin`, добавляет мидлвар маршрутов, используя указатель модуля npm: + +```js {6-9} +// plugin.ts +export default { + name: '@example/starlight-plugin', + hooks: { + 'config:setup'({ addRouteMiddleware }) { + addRouteMiddleware({ + entrypoint: '@example/starlight-plugin/route-middleware', + }); + }, + }, +}; +``` + +##### Контроль порядка выполнения + +По умолчанию мидлвары плагинов выполняются в порядке их добавления. + +Если вам нужно больше контроля над порядком выполнения, используйте необязательное свойство `order`. +Установите `order: "pre"`, чтобы мидлвар выполнялся перед пользовательскими мидлварами. +Установите `order: "post"`, чтобы мидлвар выполнялся после всех остальных мидлваров. + +Если два плагина добавляют мидлвары с одинаковым значением `order`, первым выполнится плагин, добавленный первым. + +#### `astroConfig` + +**тип:** `AstroConfig` + +Доступная только для чтения копия предоставленной пользователем [конфигурации Astro](https://docs.astro.build/ru/reference/configuration-reference/). + +#### `command` + +**тип:** `'dev' | 'build' | 'preview'` + +Команда, используемая для запуска Starlight: + +- `dev` — Проект выполняется с помощью `astro dev`. +- `build` — Проект выполняется с помощью `astro build`. +- `preview` — Проект выполняется с `astro preview`. + +#### `isRestart` + +**тип:** `boolean` + +`false` при запуске dev-сервера, `true` при перезагрузке. +Частыми причинами перезапуска являются редактирование пользователем файла `astro.config.mjs` во время работы dev-сервера. + +#### `logger` + +**тип:** `AstroIntegrationLogger` + +Экземпляр [логгера интеграции Astro](https://docs.astro.build/ru/reference/integrations-reference/#astrointegrationlogger), который можно использовать для записи журналов. +Все сообщения в журнале будут иметь префикс с названием плагина. + +```ts {6} +// plugin.ts +export default { + name: 'long-process-plugin', + hooks: { + 'config:setup'({ logger }) { + logger.info('Начало длительного процесса…'); + // Долгий процесс... + }, + }, +}; +``` + +В приведённом выше примере в журнал будет выведено сообщение, включающее в себя предоставленное информационное сообщение: + +```shell +[long-process-plugin] Начало длительного процесса... +``` + +#### `useTranslations` + +**тип:** `(lang: string) => I18nT` + +Вызовите `useTranslations()` с тегом языка BCP-47, чтобы сгенерировать утилиту для доступа к строкам интерфейса для этого языка. +`useTranslations()` возвращает аналог API `Astro.locals.t()`, который доступен в компонентах Astro. +Чтобы узнать больше о доступных API, ознакомьтесь с руководством [«Использование UI-переводов»](/ru/guides/i18n/#использование-ui-переводов). + +```ts {6} +// plugin.ts +export default { + name: 'plugin-use-translations', + hooks: { + 'config:setup'({ useTranslations, logger }) { + const t = useTranslations('zh-CN'); + logger.info(t('builtWithStarlight.label')); + }, + }, +}; +``` + +Пример выше выведет сообщение, которое включает встроенную строку интерфейса для упрощённого китайского языка: + +```shell +[plugin-use-translations] 基于 Starlight 构建 +``` + +#### `absolutePathToLang` + +**тип:** `(path: string) => string` + +Вызовите `absolutePathToLang()` с абсолютным путём к файлу, чтобы получить язык для этого файла. + +Это может быть особенно полезно при добавлении [плагинов remark или rehype](https://docs.astro.build/ru/guides/markdown-content/#%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D1%8B-markdown) для обработки файлов Markdown или MDX. +Виртуальный формат файлов, используемый этими плагинами, включает [абсолютный путь](https://github.com/vfile/vfile#filepath) обрабатываемого файла, который можно использовать с `absolutePathToLang()`, чтобы определить язык файла. +Возвращаемый язык можно использовать с хелпером [`useTranslations()`](#usetranslations) для получения строк интерфейса для этого языка. + +Например, с учётом следующей конфигурации Starlight: + +```js +starlight({ + title: 'Моя документация', + defaultLocale: 'en', + locales: { + // Англоязычная документация в `src/content/docs/en/` + en: { label: 'English' }, + // Русскоязычная документация в `src/content/docs/ru/` + ru: { label: 'Русский', lang: 'ru' }, + }, +}); +``` + +Плагин может определить язык файла, используя его абсолютный путь: + +```ts {6-8} /ru/ +// plugin.ts +export default { + name: 'plugin-use-translations', + hooks: { + 'config:setup'({ absolutePathToLang, useTranslations, logger }) { + const lang = absolutePathToLang( + '/absolute/path/to/project/src/content/docs/ru/index.mdx' + ); + const t = useTranslations(lang); + logger.info(t('aside.tip')); + }, + }, +}; +``` + +Пример выше выведет сообщение, которое включает встроенную строку интерфейса для русского языка: + +```shell +[plugin-use-translations] Совет +``` diff --git a/docs/src/content/docs/ru/reference/route-data.mdx b/docs/src/content/docs/ru/reference/route-data.mdx new file mode 100644 index 00000000000..c5bf881d3c8 --- /dev/null +++ b/docs/src/content/docs/ru/reference/route-data.mdx @@ -0,0 +1,204 @@ +--- +title: Данные маршрута +description: Полная справочная документация по объекту данных маршрута Starlight. +--- + +Объект данных маршрута Starlight содержит информацию о текущей странице. +Подробнее о том, как работает модель данных Starlight, читайте в [руководстве «Данные маршрута»](/ru/guides/route-data/). + +В компонентах Astro доступ к данным маршрута осуществляется через `Astro.locals.starlightRoute`: + +```astro {4} +--- +// src/components/Custom.astro + +const { hasSidebar } = Astro.locals.starlightRoute; +--- +``` + +В [мидлварах для маршрутов](/ru/guides/route-data/#настройка-данных-маршрута) доступ к данным маршрута осуществляется через объект `context`, передаваемый в вашу функцию-мидлвар: + +```ts {5} +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + const { hasSidebar } = context.locals.starlightRoute; +}); +``` + +## `starlightRoute` + +Объект `starlightRoute` имеет следующие свойства: + +### `dir` + +**Тип:** `'ltr' | 'rtl'` + +Направление текста страницы. + +### `lang` + +**Тип:** `string` + +Тег языка BCP-47 для локали этой страницы. Например: `en`, `zh-CN` или `pt-BR`. + +### `locale` + +**Тип:** `string | undefined` + +Базовый путь, по которому доступен язык. `undefined` для корневых локалей. + +### `siteTitle` + +**Тип:** `string` + +Заголовок сайта для локали этой страницы. + +### `siteTitleHref` + +**Тип:** `string` + +Значение для атрибута `href` заголовка сайта, ссылающегося на главную страницу, например, `/`. +Для многоязычных сайтов это будет включать текущую локаль. Например: `/en/` или `/zh-cn/`. + +### `slug` + +**Тип:** `string` + +Слаг для этой страницы, сгенерированный из имени файла контента. + +Это свойство устарело и будет удалено в будущей версии Starlight. +Перейдите на новый API Content Layer, используя [`docsLoader` Starlight](/ru/manual-setup/#настройка-коллекций-контента), и используйте свойство [`id`](#id) вместо этого. + +### `id` + +**Тип:** `string` + +Слаг для этой страницы или уникальный идентификатор для этой страницы, основанный на имени файла контента, если используется флаг [`legacy.collections`](https://docs.astro.build/en/reference/legacy-flags/#collections). + +### `isFallback` + +**Тип:** `boolean | undefined` + +`true`, если эта страница не переведена на текущий язык и отображает контент по умолчанию из основной локали. +Используется только на многоязычных сайтах. + +### `entryMeta` + +**Тип:** `{ dir: 'ltr' | 'rtl'; lang: string }` + +Метаданные локали для контента страницы. Могут отличаться от значений локали верхнего уровня, если страница использует контент по умолчанию. + +### `entry` + +Запись коллекции контента Astro для текущей страницы. +Включает значения метаданных для текущей страницы в `entry.data`. + +```ts +entry: { + data: { + title: string; + description: string | undefined; + // и т. д. + } +} +``` + +Узнайте больше о структуре этого объекта в справочнике: [`CollectionEntry`](https://docs.astro.build/en/reference/modules/astro-content/#collectionentry). + +### `sidebar` + +**Тип:** `SidebarEntry[]` + +Элементы боковой панели навигации сайта для этой страницы. + +### `hasSidebar` + +**Тип:** `boolean` + +Отображать ли боковую панель на этой странице. + +### `pagination` + +**Тип:** `{ prev?: Link; next?: Link }` + +Ссылки на предыдущую и следующую страницы в боковой панели, если она включена. + +### `toc` + +**Тип:** `{ minHeadingLevel: number; maxHeadingLevel: number; items: TocItem[] } | undefined` + +Содержание для этой страницы, если оно включено. + +### `headings` + +**Тип:** `{ depth: number; slug: string; text: string }[]` + +Массив всех заголовков Markdown, извлечённых с текущей страницы. +Используйте [`toc`](#toc), если хотите создать компонент содержания, который будет учитывать параметры конфигурации Starlight. + +### `lastUpdated` + +**Тип:** `Date | undefined` + +Объект JavaScript `Date`, представляющий дату последнего обновления этой страницы, если это включено. + +### `editUrl` + +**Тип:** `URL | undefined` + +Объект `URL` для адреса, по которому можно отредактировать эту страницу, если это включено. + +### `head` + +**Тип:** [`HeadConfig[]`](/ru/reference/configuration/#headconfig) + +Массив всех тегов, которые следует включить в `<head>` текущей страницы. +Включает важные теги, такие как `<title>` и `<meta charset="utf-8">`. + +## Утилиты + +### `defineRouteMiddleware()` + +Используйте утилиту `defineRouteMiddleware()`, чтобы типизировать мидлвар-модуль для маршрута: + +```ts "defineRouteMiddleware" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + // ... +}); +``` + +### Тип `StarlightRouteData` + +Если вы пишете код, который должен работать с данными маршрута Starlight, вы можете импортировать тип `StarlightRouteData`, чтобы соответствовать структуре `Astro.locals.starlightRoute`. + +В следующем примере функция `usePageTitleInTOC()` обновляет данные маршрута, чтобы использовать заголовок текущей страницы в качестве метки для первого элемента в содержании, заменяя стандартную метку «Обзор». +Тип `StarlightRouteData` позволяет проверить, являются ли изменения данных маршрута допустимыми. + +```ts "StarlightRouteData" +// src/route-utils.ts +import type { StarlightRouteData } from '@astrojs/starlight/route-data'; + +export function usePageTitleInTOC(starlightRoute: StarlightRouteData) { + const overviewLink = starlightRoute.toc?.items[0]; + if (overviewLink) { + overviewLink.text = starlightRoute.entry.data.title; + } +} +``` + +Эту функцию затем можно вызвать из мидлвара маршрута: + +```ts {3,6} +// src/route-middleware.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; +import { usePageTitleInTOC } from './route-utils'; + +export const onRequest = defineRouteMiddleware((context) => { + usePageTitleInTOC(context.locals.starlightRoute); +}); +``` diff --git a/docs/src/content/docs/ru/resources/community-content.mdx b/docs/src/content/docs/ru/resources/community-content.mdx new file mode 100644 index 00000000000..1ecdd8b8b1f --- /dev/null +++ b/docs/src/content/docs/ru/resources/community-content.mdx @@ -0,0 +1,251 @@ +--- +title: Контент сообщества +description: Откройте для себя подготовленные сообществом руководства, статьи и видео, которые помогут вам учиться и строить с помощью Starlight! +--- + +:::tip[Добавьте собственную работу!] +Вы создали какой-то материал о Starlight? +Откройте PR, добавляющий вашу ссылку на эту страницу! +::: + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +## Статьи и обзоры + +Вот подборка постов и статей, в которых вы узнаете больше о Starlight и опыте других людей: + +<CardGrid> + <LinkCard + href="https://devm.io/open-source/starlight-astro" + title="Генерация статических сайтов с помощью Starlight" + description="«При разработке компонентов ни одна идея не является слишком большой или слишком маленькой» — интервью с Крисом Свитинбанком, руководителем Starlight" + /> + <LinkCard + href="https://frontendatscale.com/blog/hybrid-frontend-architecture/" + title="Гибридная архитектура фронтенда с Astro и Starlight" + description="Макси Феррейра и Бен Холмс создают сайт документации с помощью Starlight, TinaCMS и интерактивной площадки API Playground с аутентификацией." + /> + <LinkCard + href="https://www.olets.dev/posts/comparing-docs-site-builders-vuepress-vs-starlight/" + title="Сравнение конструкторов сайтов документаций: VuePress против Starlight" + description="Как соотносятся эти две системы?" + /> + <LinkCard + href="https://astro.build/case-studies/wp-engine/" + title="Кейс: Снижение затрат на разработку" + description="Как WP Engine снизил затраты на разработку более чем на 50% с помощью Starlight от Astro." + /> + <LinkCard + href="https://maciekpalmowski.dev/blog/building-a-documentation-site-using-astro-starlight/" + title="Создание сайта документации с использованием Astro Starlight" + description="Мачек Пальмовски описывает, как Patchstack мигрировал свою документацию на Starlight." + /> + <LinkCard + href="https://blog.cloudflare.com/open-source-all-the-way-down-upgrading-our-developer-documentation/" + title="Открытый код на каждом уровне" + description="Как Cloudflare использовал Starlight для обновления своей документации для разработчиков." + /> + <LinkCard + href="https://starlight-changelog.netlify.app/" + title="Журнал изменений Starlight" + description="Просмотр всех релизов пакета @astrojs/starlight на одной удобной странице." + /> + <LinkCard + href="https://hideoo.dev/notes/contributing-to-starlight" + title="Вклад в Starlight" + description="Мой личный опыт и рекомендации по внесению вклада в open-source проекты, такие как Starlight." + /> +</CardGrid> + +## Рецепты и руководства + +Рецепты — это, как правило, короткие, целенаправленные руководства, которые помогают читателю выполнить конкретную задачу на рабочем примере. Это отличный способ добавить новые функции или поведение в проект Starlight, следуя пошаговым инструкциям! Другие руководства могут объяснять концепции, связанные с той или иной областью контента, например, использование изображений или работа с MDX. + +Изучите контент, созданный пользователями Starlight: + +<CardGrid> + <LinkCard + href="https://www.webpro.nl/scraps/versioned-docs-with-starlight-and-vercel" + title="Версионированная документация с помощью Starlight и Vercel" + description="Руководство по внедрению отдельных версий документации для каждой основной версии проекта." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-heading-links" + title="Добавление ссылок на рубрики Starlight" + description="Руководство по использованию плагина rehype для обмена ссылками на определенные разделы вашей документации." + /> + <LinkCard + href="https://blog.otterlord.dev/posts/starlight-sponsors/" + title="Добавление спонсоров на сайт Starlight" + description="Руководство по внедрению пользовательского компонента спонсора в боковую панель документации." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images" + title="Добавление изображений Open Graph к Starlight" + description="Руководство по созданию социальных изображений и соответствующих метатегов для ваших страниц." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-third-party-icon-sets" + title="Использование сторонних наборов иконок в Starlight" + description="Руководство по использованию unplugin-icons для расширения выбора доступных иконок для Starlight." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-html-head" + title="Редактирование HTML-заголовка страниц Starlight" + description="Узнайте, как добавлять дополнительные данные в head страницы: веб-аналитику, шрифты и скрипты." + /> + <LinkCard + href="https://dev.to/mrrobot/publishing-documentation-with-astro-starlight-691" + title="Публикация документации с помощью Astro Starlight" + description="Начало работы с документацией в Starlight." + /> + <LinkCard + href="https://events-3bg.pages.dev/jotter/starlight/" + title="Включение View Transitions" + description="Добавьте поддержку анимаций переходов между представлениями, клиентской маршрутизации и навигации в стиле SPA на ваш сайт документации Starlight." + /> + <LinkCard + href="https://jamcomments.com/posts/structured-data-with-starlight" + title="Добавление структурированных данных на страницы Starlight" + description="Узнайте, как создавать динамические структурированные данные JSON-LD для страниц документации." + /> + <LinkCard + href="https://starlight-examples.netlify.app/" + title="Примеры Starlight" + description="Коллекция вставок StackBlitz, демонстрирующих практические способы работы с сайтами документации Starlight." + /> + <LinkCard + href="https://hideoo.dev/notebooks/starlight-plugins-by-example" + title="Плагины Starlight на примерах" + description="Коллекция заметок и примеров по плагинам Starlight и распространённым шаблонам для их создания." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-progress-indicator/" + title="Добавление индикатора прогресса чтения" + description="Узнайте, как добавить горизонтальную полосу прогресса чтения на ваш сайт Starlight." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-sidebar-whitespace/" + title="Применяем свои стили к боковой панели Starlight" + description="Используем CSS, чтобы настроить шрифты, цвета и другие элементы боковой панели Starlight." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-dropdown-and-list-together/" + title="Выпадающее меню тем на мобильных, обычный список — на десктопе" + description="Объединяем два плагина, чтобы на мобильных устройствах было выпадающее меню, а на десктопе — обычный список." + /> + <LinkCard + href="https://blog.trueberryless.org/blog/starlight-autogenerate-whole-sidebar/" + title="Обработка боковой панели Starlight через мидлвар" + description="Используем мидлвар маршрутов для управления порядком и подписями групп в боковой панели по аналогии с Nuxt Content." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-social-links" + title="Добавляем социальные ссылки с собственными иконками в Starlight" + description="Узнайте, как добавить в шапку сайта Starlight социальные ссылки с собственными иконками." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-paste-images-with-visual-studio-code" + title="Вставляем изображения в страницы Starlight прямо из Visual Studio Code" + description="Ускоряем работу с документацией Starlight: вставляем изображения прямо из Visual Studio Code." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-add-diagrams-using-d2" + title="Добавляем диаграммы в документацию Starlight с помощью D2" + description="Узнайте, как добавлять диаграммы в документацию Starlight с помощью языка D2." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images-cloudinary-astro-sdk" + title="Генерируем Open Graph-изображения для Starlight через Cloudinary Astro SDK" + description="Узнайте, как использовать Cloudinary Astro SDK для генерации изображений Open Graph для сайта на Starlight." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-list-recent-github-releases" + title="Выводим последние GitHub-релизы в Starlight через Astro Content Layer API" + description="Узнайте, как использовать Astro Content Layer APIВ для получения списка последних GitHub-релизов в проекте на Starlight." + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-sitewide-banner" + title="Добавляем общий баннер на весь сайт Starlight" + description="Как сделать общий для всего сайта баннер, используя встроенную функцию Starlight для баннеров на отдельных страницах." + /> + <LinkCard + href="https://lirantal.com/blog/customizing-astro-starlight-sidebar-gated-content-auth" + title="Настройка боковой панели Astro Starlight для закрытого контента с аутентификацией" + description="Защитите свои учебные материалы, используя Clerk и SSR для динамического скрытия или отображения разделов сайдбара Starlight в зависимости от статуса авторизации пользователя." + /> +</CardGrid> + +## Видеоконтент + +Откройте для себя видео и каналы с контентом Starlight, включая прямые трансляции и образовательный контент. + +import YouTubeGrid from '~/components/youtube-grid.astro'; + +### Официальные видео + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=5u0Ds7wzUeI', + title: 'Starlight от Astro', + description: 'Смотрите официальное видео запуска Starlight', + }, + { + href: 'https://www.youtube.com/watch?v=j8K-ESJF814', + title: 'Starlight один год!', + description: + 'Sarah рассказывает о созданной сообществом Astro теме для документации', + }, + ]} +/> + +### Видео и стримы от сообщества + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/shorts/zjOWezSzd18', + title: '🌟 Запуск сайта на Starlight менее чем за минуту', + description: + 'Смотрите, как Ben запускает новый сайт на Starlight меньше чем за минуту!', + }, + { + href: 'https://www.youtube.com/watch?v=sF6UcV3moZg', + title: 'Создание документов с помощью Starlight и Astro', + description: + 'Посмотрите, как Крис и Алекс погружаются в Starlight с помощью CodingCat.dev', + }, + { + href: 'https://www.youtube.com/watch?v=sWkkHbwDeQc', + title: 'Astro Starlight', + description: 'Знакомство со Starlight за одну минуту', + }, + { + href: 'https://www.youtube.com/watch?v=-Ki-1E5gNCk', + title: + 'Шаблон документации Astro Starlight (создаём документацию для пользовательского приложения!)', + description: 'Запустите новый сайт Starlight примерно за 5 минут', + }, + { + href: 'https://www.youtube.com/watch?v=12o7WxjAxjM', + title: + 'Включите документацию Starlight в проект Next.js с помощью прокси', + description: + 'Установите Starlight в подкаталоге проекта сайта на Next.js', + }, + { + href: 'https://www.youtube.com/watch?v=5pq80drDrNs', + title: + 'Я воссоздал документы Shadcn за 30 минут с помощью этого удивительного инструмента', + description: + 'В этом видео я рассказываю о том, что делает Starlight таким крутым и почему вы можете попробовать его в своем следующем проекте.', + }, + { + href: 'https://www.youtube.com/watch?v=Q1E4Gkt63ko', + title: 'Astro Starlight и взрыв эмоций с Крисом Свитинбанком', + description: + 'В этой статье Крис, создатель Starlight, рассказывает о том, как настроить этот фреймворк для нового сайта, посвящённого эмодзи. 🌟 🎇', + }, + ]} +/> diff --git a/docs/src/content/docs/ru/resources/plugins.mdx b/docs/src/content/docs/ru/resources/plugins.mdx new file mode 100644 index 00000000000..92117ccbc06 --- /dev/null +++ b/docs/src/content/docs/ru/resources/plugins.mdx @@ -0,0 +1,305 @@ +--- +title: Плагины и интеграции +description: Откройте для себя инструменты сообщества, такие как плагины и интеграции, которые расширяют возможности Starlight! +sidebar: + order: 1 +--- + +:::tip[Добавьте собственную работу!] +Вы создали плагин или инструмент для Starlight? +Откройте PR, добавляющий ваш плагин на эту страницу! +::: + +## Плагины + +[Плагины](/ru/reference/plugins/) могут настраивать конфигурацию, пользовательский интерфейс и поведение Starlight, а также легко распространяться и использоваться повторно. +Расширяйте свой сайт с помощью официальных плагинов, поддерживаемых командой Starlight, и плагинов сообщества, поддерживаемых пользователями Starlight. + +### Официальные плагины + +<CardGrid> + <LinkCard + href="/ru/guides/site-search/#algolia-docsearch" + title="Algolia DocSearch" + description="Замена Pagefind, провайдера поиска по умолчанию, на Algolia DocSearch." + /> +</CardGrid> + +### Плагины от сообщества + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-links-validator" + title="starlight-links-validator" + description="Поиск нерабочих ссылок на страницах Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-typedoc" + title="starlight-typedoc" + description="Генерация страниц Starlight из TypeScript с помощью TypeDoc." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-blog" + title="starlight-blog" + description="Добавление блога на сайт документации." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-openapi" + title="starlight-openapi" + description="Создание страниц документации на основе спецификаций OpenAPI/Swagger." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-obsidian" + title="starlight-obsidian" + description="Публикация хранилищ Obsidian на сайте Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-image-zoom" + title="starlight-image-zoom" + description="Добавление возможности масштабирования к изображениям вашей документации." + /> + <LinkCard + href="https://github.com/lorenzolewis/starlight-utils" + title="starlight-utils" + description="Расширение Starlight с помощью набора распространённых утилит." + /> + <LinkCard + href="https://github.com/trueberryless/starlight-view-modes" + title="starlight-view-modes" + description="Добавление различных режимов просмотра на ваш сайт документации." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-versions" + title="starlight-versions" + description="Отображение версий для страниц документации Starlight." + /> + <LinkCard + href="https://inox-tools.fryuni.dev/star-warp" + title="star-warp" + description="Поиск на вашем веб-сайте напрямую из панели поиска браузера." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-heading-badges" + title="starlight-heading-badges" + description="Добавление значков в заголовки Markdown и MDX." + /> + <LinkCard + href="https://github.com/Fevol/starlight-site-graph" + title="starlight-site-graph" + description="Добавление интерактивного графика сайта в боковую панель." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-sidebar-topics" + title="starlight-sidebar-topics" + description="Разделение документации на разделы с собственными боковыми панелями." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-cooler-credit" + title="starlight-cooler-credit" + description="Добавление блока благодарностей Starlight или Astro в нижней части оглавления." + /> + <LinkCard + href="https://github.com/dragomano/starlight-giscus" + title="starlight-giscus" + description="Добавление комментариев Giscus для вашей документации." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-videos" + title="starlight-videos" + description="Создание более информативной документации с помощью видео-руководств и курсов." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-kbd" + title="starlight-kbd" + description="Удобное документирование горячих клавиш." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-auto-sidebar" + title="starlight-auto-sidebar" + description="Настройка автоматически создаваемых групп в боковой панели." + /> + <LinkCard + href="https://github.com/delucis/starlight-llms-txt" + title="starlight-llms-txt" + description="Добавление файла llms.txt на сайт документации (основано на llmstxt.org)." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-toc-overview-customizer" + title="starlight-toc-overview-customizer" + description="Настройка оглавления в Starlight с изменяемым заголовком раздела «Обзор»." + /> + <LinkCard + href="https://delucis.github.io/starlight-markdown-blocks/" + title="starlight-markdown-blocks" + description="Расширение синтаксиса Markdown-вставок в Starlight с помощью пользовательских типов блоков." + /> + <LinkCard + href="https://github.com/WindMillCode/starlight-fullview-mode" + title="starlight-fullview-mode" + description="Сворачивание боковых панелей и разворачивание контента на весь экран." + /> + <LinkCard + href="https://github.com/frostybee/starlight-scroll-to-top" + title="starlight-scroll-to-top" + description="Добавление кнопки прокрутки страницы вверх к вашему сайту документации." + /> + <LinkCard + href="https://github.com/frostybee/starlight-codeblock-fullscreen" + title="starlight-codeblock-fullscreen" + description="Добавление функционала полноэкранного режима для блоков кода Expressive Code в вашей документации." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-auto-drafts" + title="starlight-auto-drafts" + description="Изменение поведения черновиков по умолчанию и автоматическое скрытие ссылок на черновики в боковой панели в продакшене." + /> + <LinkCard + href="https://github.com/corsfix/starlight-contextual-menu" + title="starlight-contextual-menu" + description="Добавление контекстного меню для вашей документации Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-changelogs" + title="starlight-changelogs" + description="Отображение журналов изменений вместе с документацией вашего проекта." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-github-alerts" + title="starlight-github-alerts" + description="Отображение предупреждений GitHub в виде боковых заметок Starlight." + /> + <LinkCard + href="https://github.com/dlcastillop/starlight-page-actions" + title="starlight-page-actions" + description="Добавление кнопок действий для страниц в вашу документацию." + /> + <LinkCard + href="https://github.com/typesense/starlight-docsearch-typesense" + title="starlight-docsearch-typesense" + description="Альтернатива официальному плагину Algolia DocSearch, работающая на Typesense." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-swipe/" + title="starlight-sidebar-swipe" + description="Делаем левую боковую панель свайпаемой на мобильных устройствах, как в Discord Mobile." + /> + <LinkCard + href="https://github.com/Rettend/starlight-plugin-icons" + title="starlight-plugin-icons" + description="Добавление иконок в Astro Starlight: боковая панель, блоки кода, дерево файлов." + /> + <LinkCard + href="https://github.com/dlcastillop/starlight-ui-tweaks" + title="starlight-ui-tweaks" + description="Расширяет основные компоненты интерфейса: добавляет пользовательские ссылки навигации, рекламу, маркетинговые футеры и более чистый переключатель темы." + /> + <LinkCard + href="https://frostybee.github.io/starlight-tags/" + title="starlight-tags" + description="Добавьте теги на страницы Starlight для удобной организации и поиска контента." + /> + <LinkCard + href="https://github.com/dionysuzx/starlight-copy-button" + title="starlight-copy-button" + description="Копируйте Markdown всей страницы документации с помощью изящной кнопки в заголовке." + /> + <LinkCard + href="https://frostybee.github.io/starlight-telescope/" + title="starlight-telescope" + description="Быстро переходите к любой странице вашей документации Starlight благодаря нечёткому поиску и навигации, ориентированной на управление с клавиатуры." + /> + <LinkCard + href="https://frostybee.github.io/starlight-announcement/" + title="starlight-announcement" + description="Добавьте в свою документацию Starlight улучшенные баннеры объявлений с возможностью закрытия, различными вариантами оформления, планированием показов и таргетингом на конкретные страницы." + /> +</CardGrid> + +## Инструменты и интеграции от сообщества + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +Эти инструменты и интеграции сообщества можно использовать для добавления функций на ваш сайт Starlight. + +<CardGrid> + <LinkCard + href="https://www.feelback.dev/blog/new-astro-starlight-integration/" + title="FeelBack" + description="Добавление системы обратной связи с пользователями на страницы вашей документации." + /> + <LinkCard + href="https://github.com/val-town/notion-to-astro" + title="notion-to-astro" + description="Преобразование экспорта Notion в документы Astro Starlight." + /> + <LinkCard + href="https://github.com/mattjennings/astro-live-code" + title="astro-live-code" + description="Отображение блоков кода MDX в виде интерактивных компонентов." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-i18n" + title="starlight-i18n" + description="Расширение Visual Studio Code для перевода страниц Starlight." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-package-managers" + title="starlight-package-managers" + description="Быстрое отображение команд, связанных с npm, для нескольких менеджеров пакетов." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-showcases" + title="starlight-showcases" + description="Набор компонентов Starlight для создания страниц-витрин." + /> + <LinkCard + href="https://github.com/HiDeoo/generator-starlight-plugin" + title="@hideoo/starlight-plugin" + description="Генератор для быстрого создания плагинов Starlight." + /> + <LinkCard + href="https://github.com/Linkerin/starlight-to-pdf" + title="starlight-to-pdf" + description="Инструмент командной строки для конвертации сайтов Starlight в PDF-файлы." + /> + <LinkCard + href="https://github.com/joesaby/astro-plantuml" + title="astro-plantuml" + description="Рендеринг содержимого PlantUML в блоках кода Markdown." + /> + <LinkCard + href="https://github.com/joesaby/astro-mermaid" + title="astro-mermaid" + description="Рендеринг Mermaid-контента на стороне клиента в блоках кода Markdown." + /> + <LinkCard + href="https://github.com/HiDeoo/astro-d2" + title="astro-d2" + description="Преобразование блоков кода D2 Markdown в диаграммы." + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-links" + title="starlight-links" + description="Предоставление IntelliSense для ссылок в контенте Starlight Markdown и MDX с помощью расширения Visual Studio Code." + /> + <LinkCard + href="https://docs.contentisland.net/templates/starlight/" + title="contentisland-cli" + description="Подключение и синхронизация проекта Starlight с Headless CMS Content Island для редактирования и управления документацией." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown" + title="starlight-sidebar-topics-dropdown" + description="Разделение страницы с документами на несколько подстраниц и переключение между ними с помощью выпадающего меню в боковой панели." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-save-file-component" + title="starlight-save-file-component" + description="Быстрое добавление на сайт Starlight ссылки для скачивания файла или другого ресурса." + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-contributor-list" + title="starlight-contributor-list" + description="Отображение списка всех контрибьюторов вашего проекта." + /> +</CardGrid> diff --git a/docs/src/content/docs/ru/resources/showcase.mdx b/docs/src/content/docs/ru/resources/showcase.mdx new file mode 100644 index 00000000000..5d0327cde0c --- /dev/null +++ b/docs/src/content/docs/ru/resources/showcase.mdx @@ -0,0 +1,21 @@ +--- +title: Витрина Starlight +description: Откройте для себя сайты, созданные с помощью Starlight! +sidebar: + label: Витрина сайтов +--- + +:::tip[Добавьте свой собственный сайт!] +Вы создали сайт с помощью Starlight? +[Откройте PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#showcase), добавив ссылку на эту страницу! +::: + +## Сайты + +import ShowcaseSites from '~/components/showcase-sites.astro'; + +Starlight уже используется в производстве. Вот некоторые из сайтов в Интернете: + +<ShowcaseSites /> + +Посмотреть все [публичные репозитории проектов, использующих Starlight, на GitHub](https://github.com/withastro/starlight/network/dependents). diff --git a/docs/src/content/docs/ru/resources/themes.mdx b/docs/src/content/docs/ru/resources/themes.mdx new file mode 100644 index 00000000000..4f2d37623ca --- /dev/null +++ b/docs/src/content/docs/ru/resources/themes.mdx @@ -0,0 +1,124 @@ +--- +title: Темы +description: Оформите документацию с помощью темы от сообщества для Starlight +tableOfContents: false +sidebar: + order: 2 +head: + - tag: style + content: | + body { --sl-content-width: 66.75rem; } +--- + +import ThemeGrid from '~/components/theme-grid.astro'; + +Тема — это плагин Starlight, который изменяет внешний вид сайта с помощью [пользовательского CSS](/ru/guides/css-and-tailwind/), [переопределения компонентов](/ru/guides/overriding-components/), или других новых возможностей. + +## Темы от сообщества + +Установите тему, созданную сообществом, чтобы быстро настроить внешний вид и стиль вашего сайта. + +Ознакомьтесь со списком всех тем ниже или попробуйте их интерактивно на [демо-сайте Starlight Themes](https://starlight-themes.netlify.app/). + +<ThemeGrid + labels={{ + /** Accessible label for the theme toggle. */ + legend: 'Превью', + /** Accessible label for the dark color scheme variant. */ + dark: 'Тёмные', + /** Accessible label for the light color scheme variant. */ + light: 'Светлые', + }} + themes={[ + { + title: 'Starlight Rapide', + description: + 'Тема Starlight, вдохновлённая темой Visual Studio Code Vitesse.', + href: 'https://starlight-theme-rapide.vercel.app/', + previews: { light: 'rapide-light.png', dark: 'rapide-dark.png' }, + }, + { + title: 'Starlight Obsidian', + description: + 'Тема Starlight, вдохновлённая стилем сайтов Obsidian Publish.', + href: 'https://fevol.github.io/starlight-theme-obsidian/', + previews: { light: 'obsidian-light.png', dark: 'obsidian-dark.png' }, + }, + { + title: 'Catppuccin for Starlight', + description: 'Успокаивающая пастельная тема для Starlight.', + href: 'https://starlight.catppuccin.com/', + previews: { light: 'catppuccin-light.png', dark: 'catppuccin-dark.png' }, + }, + { + title: 'Ion', + description: 'Элегантная, современная тема для Starlight.', + href: 'https://louisescher.github.io/starlight-ion-theme/', + previews: { light: 'ion-light.png', dark: 'ion-dark.png' }, + }, + { + title: 'Starlight Black', + description: 'Тема Starlight, вдохновлённая документацией shadcn.', + href: 'https://starlight-theme-black.vercel.app/', + previews: { light: 'black-light.png', dark: 'black-dark.png' }, + }, + { + title: 'Starlight Flexoki', + description: + 'Тёплая и дружелюбная тема, основанная на цветовой палитре Flexoki.', + href: 'https://delucis.github.io/starlight-theme-flexoki/', + previews: { light: 'flexoki-light.png', dark: 'flexoki-dark.png' }, + }, + { + title: 'Starlight Nova', + description: 'Красивая и современная тема для Starlight.', + href: 'https://starlight-theme-nova.pages.dev/', + previews: { light: 'nova-light.png', dark: 'nova-dark.png' }, + }, + { + title: 'Starlight Next.js', + description: 'Тема Starlight, вдохновлённая документацией Next.js.', + href: 'https://starlight-theme-next.trueberryless.org/', + previews: { light: 'nextjs-light.png', dark: 'nextjs-dark.png' }, + }, + { + title: 'Starlight Galaxy', + description: + 'Тема Astro Starlight, разработанная для публикации документации и образовательного контента.', + href: 'https://frostybee.github.io/starlight-theme-galaxy/', + previews: { light: 'galaxy-light.png', dark: 'galaxy-dark.png' }, + }, + { + title: 'Starlight Page', + description: + 'Интуитивно понятная, современная тема Starlight с плавными анимациями появления.', + href: 'https://pelagornis-page.netlify.app/', + previews: { light: 'page-light.png', dark: 'page-dark.png' }, + }, + { + title: 'Starlight Gruvbox', + description: 'Ретро-тема в стиле Gruvbox для Starlight', + href: 'https://starlight-theme-gruvbox.otterlord.dev/', + previews: { light: 'gruvbox-light.png', dark: 'gruvbox-dark.png' }, + }, + { + title: 'Starlight Six', + description: + 'Чистая и современная тема для Astro.js Starlight от Six Technology', + href: 'https://six-tech.github.io/Six.StarlightTheme/', + previews: { light: 'six-light.png', dark: 'six-dark.png' }, + }, + { + title: 'Starlight Vintage', + description: + 'Данная тема во многом вдохновлена неустаревающим дизайном оригинальной документации Astro.', + href: 'https://starlight-theme-vintage.netlify.app/', + previews: { light: 'vintage-light.png', dark: 'vintage-dark.png' }, + }, + ]} +/> + +:::tip[Добавьте собственную работу!] +Вы создали тему для Starlight? +[Откройте PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#themes), добавляющий вашу тему на эту страницу! +::: diff --git a/docs/src/content/docs/showcase.mdx b/docs/src/content/docs/showcase.mdx deleted file mode 100644 index 194caafdfe8..00000000000 --- a/docs/src/content/docs/showcase.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Starlight Showcase -description: Discover sites built with Starlight and community tools that extend Starlight! ---- - -:::tip[Add your own!] -Have you built a Starlight site or a tool for Starlight? -Open a PR adding a link to this page! -::: - -## Sites - -import ShowcaseSites from '../../components/showcase-sites.astro'; - -Starlight is already being used in production. These are some of the sites around the web: - -<ShowcaseSites /> - -See all the [public project repos using Starlight on GitHub](https://github.com/withastro/starlight/network/dependents). - -## Community plugins - -import { CardGrid, LinkCard } from '@astrojs/starlight/components'; - -These community tools, plugins, and integrations work alongside Starlight to extend its functionality. - -<CardGrid> - <LinkCard - href="https://www.feelback.dev/blog/new-astro-starlight-integration/" - title="FeelBack" - description="Add a user feedback system to your docs pages." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-blog" - title="starlight-blog" - description="Add a blog to your documentation site." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-links-validator" - title="starlight-links-validator" - description="Check for broken links in your Starlight pages." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-typedoc" - title="starlight-typedoc" - description="Generate Starlight pages from TypeScript using TypeDoc." - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-openapi" - title="starlight-openapi" - description="Create documentation pages from OpenAPI/Swagger specifications." - /> -</CardGrid> diff --git a/docs/src/content/docs/tr/404.md b/docs/src/content/docs/tr/404.md new file mode 100644 index 00000000000..5edfbf04a61 --- /dev/null +++ b/docs/src/content/docs/tr/404.md @@ -0,0 +1,14 @@ +--- +title: Sayfa Bulunamadı +template: splash +editUrl: false +lastUpdated: false +hero: + title: '404' + tagline: <strong>Houston, bi' problem var.</strong> Bu sayfayı bulamadık.<br>URL'i kontrol et ya da arama çubuğunu kullanmayı dene. + actions: + - text: Ana Sayfaya Git + icon: right-arrow + link: /tr/ + variant: primary +--- diff --git a/docs/src/content/docs/tr/environmental-impact.md b/docs/src/content/docs/tr/environmental-impact.md new file mode 100644 index 00000000000..05bc3804178 --- /dev/null +++ b/docs/src/content/docs/tr/environmental-impact.md @@ -0,0 +1,140 @@ +--- +title: Doğa Dostu Dokümanlar +description: Starlight'ın daha çevreci dokümantasyon sitesi oluşturmanda nasıl yardımcı olacağını ve karbon ayakizini nasıl düşüreceğini öğren. +--- + +Web endüstrisinin iklime etkisinin [%2][sf] ila [%4 arasında küresel karbon emisyonu][bbc]'na sahip olduğu tahmin ediliyor; kabaca havayolları endüstrisindeki emisyon oranında. +Bir websitesinin ekolojik etkisini hesaplamada çok fazla karmaşık etken var, ancak bu rehber dokümantasyon sitenizin çevresel ayakizini düşürmek için birkaç ipucu içerir. + +İyi haber şu ki, Starlight'ı seçmek mükemmel bir başlangıç. +Bu site, Carbon Calculator web sitesine göre sayfa başına ziyarette 0.01 gr CO₂ üretimiyle [test edilmiş web sayfaları arasında %99 daha çevreci][sl-carbon]. + +## Sayfa Büyüklüğü + +Bir web sayfası ne kadar veri transfer ederse, ihtiyaç duyacağı enerji o kadar yüksek olur. +Nisan 2023'te [HTTP Archive'daki veri][http]'ye göre orta büyüklükte web sayfası, kullanıcıdan 2,000 KB'tan daha fazla veri indirmeye ihtiyaç duydu. + +Starlight, sayfaları mümkün olan en küçük boyutta oluşturur. +Örneğin, ilk ziyarette kullanıcı 50 KB'tan daha az sıkıştırılmış veriyi indirecektir - sadece HTTP Archive medyan değerinin %2.5'i kadar. +İyi bir ön belleğe alma stratejisi ile takip eden gezinmelerde 10 KB kadar küçük veri indirir. + +### Görseller + +Starlight iyi bir temel sunmasına rağmen, dokümantasyon sayfalarına eklediğiniz görseller sayfa büyüklüğünü hızlıca artırabilir. +Starlight, Astro'nun [optimize edilmiş varlık desteği][assets] yardımıyla Markdown ve MDX dosyalarındaki yerel görselleri optimize etmek için kullanır. + +### Arayüz Bileşenleri + +React ya da Vue gibi arayüz kütüphaneleri ile oluşturulmuş bileşenler, sayfaya büyük boyutta Javascript ekleyebilir. +[Astro Adaları][islands] ile oluşturulmuş bileşenlerin **varsayılan olarak sıfır tarayıcı-tarafı Javascript** yüklemesi nedeniyle Starlight, Astro üzerine kurulmuştur. + +### Ön Bellekleme + +Ön bellekleme, halihazırda yüklenmiş verilerin tekrar kullanımı ve tarayıcının ne kadar süre bu veriyi tutacağını kontrol etmek için kullanılır. +İyi bir ön bellekleme stratejisi; kullanıcının yeni içeriği değiştikten sonra mümkün olan en kısa sürede almasını sağlar, fakat buna ek olarak içerik değişmediğinde tekrar tekrar aynı içeriği yüklemesini önler. + +[`Cache-Control` HTTP header][cache], ön belleklemeyi yapılandırmanın sık kullanılan bir yoludur. +Starlight kullanarak, `/_astro/` dizini içindeki her şey için uzun ön bellekleme süresi ayarlayabilirsiniz. +Bu dizin CSS, Javascript ve diğer paketlenmiş dosyaları içerir ve güvenle sonsuza dek ön belleğe alınarak gereksiz indirmeleri azaltır: + +``` +Cache-Control: public, max-age=604800, immutable +``` + +Ön belleklemenin nasıl yapılandırılacağı web sunucunuza bağlıdır. Örneğin; Vercel önbellekleme stratejisini herhangi bir yapılandırmaya gerek kalmadan uygularken, Netlify'da `public/_headers` altına [Netlify için özel header'lar][ntl-headers] ile ayarlayabilirsiniz: + +``` +/_astro/* + Cache-Control: public + Cache-Control: max-age=604800 + Cache-Control: immutable +``` + +[cache]: https://csswizardry.com/2019/03/cache-control-for-civilians/ +[ntl-headers]: https://docs.netlify.com/routing/headers/ + +## Güç tüketimi + +Bir web sitesinin nasıl oluşturulduğu, web sitesinin kullanıcı cihazında ne kadar güç tüketeceğini etkiler. +En az Javascript kullanarak, Starlight kullanıcının telefon, tablet ve bilgisayarında yükleme ve sayfayı çizme sürecinde ihtiyaç duyulan enerjiyi düşürür. + +Analitik takip scriptleri ya da gömülü video gibi ağır Javascript içeriklerini eklerken, bu özelliklerin sayfanızın güç tüketimini artıracağını aklınızda tutun. +Analitik takip script'ine ihtiyacınız varsa, [Cabin][cabin], [Fathom][fathom], ya da [Plausible][plausible] gibi daha hafif seçenekleri göz önünde bulundurun. +Youtube ve Vimeo gibi gömülü videolar [kullanıcı etkileşimi ile videoyu yükleme][lazy-video]. yöntemiyle geliştirilebilir. +[`astro-embed`][embed] gibi paketler ortak hizmetler için yardımcı olabilir. + +:::tip[Bunu biliyor musun?] +Javascript'in ayrıştırılması ve derlenmesi tarayıcıların yapması gereken en maliyetli görevlerden biri. +Aynı boyutta JPEG görsel çizimi ile kıyaslandığında, [JavaScript 30 kez daha uzun işleme süresi alabilir][cost-of-js]. +::: + +[cabin]: https://withcabin.com/ +[fathom]: https://usefathom.com/ +[plausible]: https://plausible.io/ +[lazy-video]: https://web.dev/iframe-lazy-loading/ +[embed]: https://www.npmjs.com/package/astro-embed +[cost-of-js]: https://medium.com/dev-channel/the-cost-of-javascript-84009f51e99e + +## Barındırma + +Web sayfasının nerede barındırıldığı, dokümantasyon sitenizin ne kadar çevre dostu olduğu konusunda büyük etkisi vardır. +Veri merkezleri ve sunucu çiftlikleri büyük ekolojik etkiye sahip olabilir, yüksek elektrik tüketimi ve büyük oranda su kullanımı dahil. + +Yenilenebilir enerji kullanan barındırma opsiyonunu seçmek, sitenizin daha az karbon emisyonuna neden olacağı anlamına gelir. [Green Web Directory][gwb] size bu konuda barındırma şirketleri bulmanıza yardımcı olacak bir araçtır. + +[gwb]: https://www.thegreenwebfoundation.org/directory/ + +## Karşılaştırmalar + +Diğer dokümantasyon çerçeveleri ile nasıl kıyaslandığını merak ediyor musun? +[Website Carbon Calculator][wcc] ile yapılan testlerle, farklı araçlarla oluşturulmuş benzer sayfaları karşılaştırın. + +| Çerçeve | sayfa başına ziyarette CO₂ | +| --------------------------- | -------------------------- | +| [Starlight][sl-carbon] | 0.01gr | +| [VitePress][vp-carbon] | 0.05gr | +| [Docus][dc-carbon] | 0.05gr | +| [Sphinx][sx-carbon] | 0.07gr | +| [MkDocs][mk-carbon] | 0.10gr | +| [Nextra][nx-carbon] | 0.11gr | +| [docsify][dy-carbon] | 0.11gr | +| [Docusaurus][ds-carbon] | 0.24gr | +| [Read the Docs][rtd-carbon] | 0.24gr | +| [GitBook][gb-carbon] | 0.71gr | + +<small>14 Mayıs 2023 tarihli veriler. Güncel bilgileri görmek için linke tıkla.</small> + +[sl-carbon]: https://www.websitecarbon.com/website/starlight-astro-build-getting-started/ +[vp-carbon]: https://www.websitecarbon.com/website/vitepress-dev-guide-what-is-vitepress/ +[dc-carbon]: https://www.websitecarbon.com/website/docus-dev-introduction-getting-started/ +[sx-carbon]: https://www.websitecarbon.com/website/sphinx-doc-org-en-master-usage-quickstart-html/ +[mk-carbon]: https://www.websitecarbon.com/website/mkdocs-org-getting-started/ +[nx-carbon]: https://www.websitecarbon.com/website/nextra-site-docs-docs-theme-start/ +[dy-carbon]: https://www.websitecarbon.com/website/docsify-js-org/ +[ds-carbon]: https://www.websitecarbon.com/website/docusaurus-io-docs/ +[rtd-carbon]: https://www.websitecarbon.com/website/docs-readthedocs-io-en-stable-index-html/ +[gb-carbon]: https://www.websitecarbon.com/website/docs-gitbook-com/ + +## Diğer Kaynaklar + +### Araçlar + +- [Website Carbon Calculator][wcc] +- [GreenFrame](https://greenframe.io/) +- [Ecograder](https://ecograder.com/) +- [WebPageTest Carbon Control](https://www.webpagetest.org/carbon-control/) +- [Ecoping](https://ecoping.earth/) + +### Makaleler ve Konuşmalar + +- [“Building a greener web”](https://youtu.be/EfPoOt7T5lg), Michelle Barker'ın konuşması +- [“Sustainable Web Development Strategies Within An Organization”](https://www.smashingmagazine.com/2022/10/sustainable-web-development-strategies-organization/), Michelle Barker'ın makalesi +- [“A sustainable web for everyone”](https://2021.stateofthebrowser.com/speakers/tom-greenwood/), Tom Greenwood'un konuşması +- [“How Web Content Can Affect Power Usage”](https://webkit.org/blog/8970/how-web-content-can-affect-power-usage/), Benjamin Poulain and Simon Fraser'ın makalesi + +[sf]: https://www.sciencefocus.com/science/what-is-the-carbon-footprint-of-the-internet/ +[bbc]: https://www.bbc.com/future/article/20200305-why-your-internet-habits-are-not-as-clean-as-you-think +[http]: https://httparchive.org/reports/state-of-the-web +[assets]: https://docs.astro.build/en/guides/assets/ +[islands]: https://docs.astro.build/en/concepts/islands/ +[wcc]: https://www.websitecarbon.com/ diff --git a/docs/src/content/docs/tr/getting-started.mdx b/docs/src/content/docs/tr/getting-started.mdx new file mode 100644 index 00000000000..fe0f9884eab --- /dev/null +++ b/docs/src/content/docs/tr/getting-started.mdx @@ -0,0 +1,139 @@ +--- +title: Başlarken +description: Sıradaki dokümantasyon siteni Astro'nun Starlight'ı ile nasıl oluşturacağını öğren. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +Starlight, [Astro](https://astro.build) çerçevesi üstüne kurulmuş çok özellikli bir dokümantasyon temasıdır. +Bu rehber, yeni projeye başlamanda yardımcı olacak. +Mevcut Astro projesine Starlight eklemek için [elle kurulum talimatlarını](/tr/manual-setup/) incele. + +## Hızlı Başlangıç + +### Yeni Proje Oluşturma + +Aşağıdaki komutu terminalinde çalıştırarak yeni bir Astro + Starlight projesi oluştur: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight +``` + +</TabItem> +</Tabs> + +Bu, siten için yapılandırmalar ve tüm gerekli dosyalarla birlikte yeni bir [proje dizini](/tr/guides/project-structure/) oluşturacaktır. + +:::tip[Çalışan haline göz at] +Starlight'ı tarayıcında dene: +[StackBlitz'deki taslağı aç](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). +::: + +### Geliştirme sunucusunu başlat + +[Astro’nun geliştirme sunucusu](https://docs.astro.build/en/reference/cli-reference/#astro-dev) lokalinizde çalışırken, çalışmanızı önizlemeye ve otomatik olarak tarayıcınızın değişiklik yaptığınızda yenilenmesine olanak tanır. + +Geliştirme sunucusunu başlatmak için aşağıdaki komutu proje dizininizde çalıştırın: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm run dev +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm dev +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev +``` + +</TabItem> +</Tabs> + +Bu, terminalinizde lokal önizleme bağlantılı bir mesaj gösterecektir. +Sitenizi tarayıcıda görüntülemek için bu bağlantıyı açın. + +### İçerik Ekle + +Starlight, yeni bir içerik eklemen ya da var olan dosyalarını getirmen için hazır! + +`src/content/docs/` dizini içerisinde yeni Markdown dosyaları oluşturarak yeni sayfalar ekleyin. + +Dosya bazlı gezinim ve MDX ile Markdoc dosya desteği hakkında daha fazlası için [“Sayfalar”](/tr/guides/pages/) rehberini okuyun. + +### Sonraki Adımlar + +- **Yapılandır:** [“Starlight'ı özelleştirmek”](/tr/guides/customization/) rehberinde ortak ayarlar hakkında öğren. +- **Gezinme:** [“Kenar Çubuğu Gezinimi”](/tr/guides/sidebar/) rehberi ile kenar çubuğunu ayarla. +- **Bileşenler:** [“Bileşenler”](/tr/components/using-components/) rehberinde hazır yapılmış kartlar, tablar ve daha fazlasını keşfet. +- **Yayına al:** Astro dokümantayonu içerisindeki [“Siteni yayına al”](https://docs.astro.build/en/guides/deploy/) rehberi ile çalışmanı yayınla. + +## Starlight'ı Güncelleme + +:::tip +Starlight, beta sürümünde olduğundan dolayı sıklıkla güncelleme ve geliştirmeler yapılacak. +Starlight'ı güncel tuttuğuna emin ol! +::: + +Starlight bir Astro entegrasyonudur. Bunu ve diğer Astro paketlerini, terminalinde aşağıdaki komutu çalıştırarak güncelleyebilirsin: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npx @astrojs/upgrade +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm dlx @astrojs/upgrade +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dlx @astrojs/upgrade +``` + +</TabItem> +</Tabs> + +[Starlight Değişim Günlüğü](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md)'nde her yayın içindeki değişikliklerin tümünü listeleyebilirsin. + +## Starlight'ta Sorun Giderme + +Starlight [Proje Yapılandırması](/tr/reference/configuration/) ve [Benzersiz Sayfa Ön-bölüm Yapılandırması](/tr/reference/frontmatter/) bilgileri, bu sitenin referanslar bölümünde mevcuttur. Bu sayfalardan, Starlight siteni doğru yapılandırdığından ve sitenin düzgün çalıştığından emin olmak için kullanabilirsin. + +İçerik eklemede ve Starlight siteni özelleştirmene yardımcı olmak için kenar çubuğundaki rehber listesine göz at. +Aradığın cevap dokümantasyonda yoksa, tüm Astro dokümantasyonu için lütfen [Astro Dokümantasyonu](https://docs.astro.build)'nu ziyaret et. Starlight teması altında Astro'nun genel olarak nasıl çalıştığıyla sorun yanıtlanmış olabilir. + +Ayrıca, [GitHub üzerindeki Starlight sorunları](https://github.com/withastro/starlight/issues)'nı kontrol edebilir, aktif ve dost canlısı topluluğumuzdan [Astro Discord](https://astro.build/chat/) üzerinden yardım isteyebilirsin! Sorularını `#support` forumunda "starlight" etiketi ile sorabilir, ya da özel `#starlight` kanalımızı mevcut geliştirmeler ve daha fazlası için ziyaret edebilirsin! diff --git a/docs/src/content/docs/tr/index.mdx b/docs/src/content/docs/tr/index.mdx new file mode 100644 index 00000000000..0bf9e924775 --- /dev/null +++ b/docs/src/content/docs/tr/index.mdx @@ -0,0 +1,154 @@ +--- +title: Starlight 🌟 Astro ile dokümantasyon sitesi oluştur +head: + - tag: title + content: Starlight 🌟 Astro ile dokümantasyon sitesi oluştur +description: Starlight, Astro ile güzel ve yüksek performanslı dokümantasyon siteleri oluşturmanıza yardımcı olur. +template: splash +editUrl: false +lastUpdated: false +hero: + title: Starlight ile dokümanlarınız şıkır şıkır olsun + tagline: Yıldız gibi dokümantasyon sitesi oluşturmanız için gereken her şey. Hızlı, erişilebilir ve kullanımı kolay. + image: + file: ~/assets/hero-star.webp + actions: + - text: Başla + icon: right-arrow + link: getting-started + - text: Github'da Görüntüle + icon: external + variant: minimal + link: https://github.com/withastro/starlight +--- + +import { CardGrid, Card } from '@astrojs/starlight/components'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; + +<CardGrid stagger> + <Card title="Memnun eden dokümantasyon" icon="open-book"> + İçerir: site navigasyonu, arama, uluslararasılaştırma, arama motoru + optimizasyonu, okuması kolay tipografi, kod vurgulama, koyu mod and daha + fazlası. + </Card> + <Card title="Astro ile çalışır" icon="rocket"> + Astro'nun tüm gücünü ve performasını sonuna kadar kullanın. Starlight'ı + favori Astro entegrasyon ve kütüphanelerinizle genişletin. + </Card> + <Card title="Markdown, Markdoc, ve MDX" icon="document"> + Favori işaretleme dilinizi getirin. Starlight size Typescript'in tip + güvenliliğiyle birlikte kurulu ön-bölüm doğrumalasını sunar. + </Card> + <Card title="Kendi arayüz bileşenlerini getir" icon="puzzle"> + Starlight bütün bir dokümantasyon çözümüdür ve çerçeve-bağımsız olarak + gelir. React, Vue, Svelte ve daha fazlası ile genişletin. + </Card> +</CardGrid> + +<TestimonialGrid title="İnsanlar ne diyor"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + Astro ekibi dokümantasyonun nasıl yapılacağını GELİŞTİRDİ ve kullanıma hazır olarak Starlight projesiyle edinebilirsiniz. + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + Astro'nun resmi başlangıç kiti Starlight, dokümantasyon sitesi oluşturmak için gerçekten muhteşem bir araç. + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + Starlight bizim mükemmel geliştirici deneyimine başlangıç örneğimiz: hız, kolaylık ve detaylara karşı titizlik ilham verici. Teknik ve görünümü hallediyor, böylece siz içeriğinize odaklanabiliyorsunuz 👏 + + StackBlitz ekibi tümüyle seviyor! + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + Starlight benim için oyun-değiştirici oldu, içerik oluşturmaya odaklanmama müsade ediyor. + Sezgisel tasarımı sadece iş akışımı kolaylaştırmıyor, ayrıca açık kaynak geliştiricileri için oryantasyon süresini kısaltıyor. + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + Course Builder dokümantasyonu için Starlight ile biraz vakit geçirdim ve harika geçti. Çokça iyi dokunuşlar ve detaylara boğulmadan Markdown ile yazmaya odaklanabiliyorum. + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + Starlight ile uğraşmaya başladım. Söylemeliyim ki kullanıma hazır halde gelen performansından etkilendim. + + 💯💯💯💯 + + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + Starlight dokümantasyona başlamanın en iyi yolu. Astro'nun hızı ve gücünün arasında ve Starlight'tan gelen kalıp, mükemmel çift. + Bir süredir benim başlangıcım ve hala seviyorum! + + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + Starlight'ı son işimde kullandım ve bayıldım. Harika bileşenler, sezgisel tasarım, ve süper-hevesli topluluk (ne zaman biri bir şeye ihtiyaç duyarsa ya yakın zamanda ihtiyacı yerine getirirler ya da iş görecek yolu paylaşırlar). Çok keyifli bir deneyim. + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + Starlight sayesinde monorepo sitemdeki dokümantasyon her zamankinden daha iyi görünüyor. Astro'nun tüm gücünü kaybetmeden kullanmak aşırı kolay. Starlight üzerinde çalıştığınız için teşekkür ederim! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + Starlight dokümantasyon için benim başlangıç aracım. Varolan Astro ürün web siteme dokümantasyon eklemeyi çok kolaylaştırdı, başka bir araç olsaydı alt alan adına ihtiyaç duyardım. + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + WPEngine Atlas Platform dokümantasyonunu yeniden oluşturuyordum. İnanın bana Starlight A+ dokümantasyon platformu oluştumrak için ihtiyacınız olan her şeye sahip 🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + Starlight'a bir şans verin! + + Birkaç sitem için kullandım ve o muhteşem. + + </Testimonial> +</TestimonialGrid> + +<AboutAstro title="Size getirildi"> +Astro, hız için tasarlanmış hepsi bir arada web çerçevesidir. +Herhangi bir yerden içeriğinizi çekin ve her yere yükleyin, hepsi favori arayüz komponentleriniz ve kütüphanelerinizle güçlendirildi. + +[Astro hakkında daha fazlasını öğren](https://astro.build/) + +</AboutAstro> diff --git a/docs/src/content/docs/tr/resources/community-content.mdx b/docs/src/content/docs/tr/resources/community-content.mdx new file mode 100644 index 00000000000..6e293b2317d --- /dev/null +++ b/docs/src/content/docs/tr/resources/community-content.mdx @@ -0,0 +1,144 @@ +--- +title: Topluluk İçeriği +description: Size Starlight ile site yapma ve öğrenmenizde yardım etmesi için topluluk üretimi rehber, makale ve videoları keşfedin! +--- + +:::tip[Seninkini ekle!] +Starlight ile ilgili içerik oluşturdun mu? +Bu sayfaya bağlantı eklemek için PR açın! +::: + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +## Makaleler ve Görüşler + +Starlight hakkında daha fazlasını öğrenmek ve diğer insanları deneyimlerini içeren makale ve gönderiler ait koleksiyon burada: + +<CardGrid> + <LinkCard + href="https://devm.io/open-source/starlight-astro" + title="Starlight ile Statik Site Oluşturma" + description="“Bileşenleri tasarlarken hiçbir fikir çok büyük ya da çok küçük değildir” — Starlight Lideri Chris Swithinbank ile röportaj" + /> + <LinkCard + href="https://frontendatscale.com/blog/hybrid-frontend-architecture/" + title="Astro ve Starlight ile Hibrit Ön Uç Mimarisi" + description="Maxi Ferreira ile Ben Holmes; Starlight, TinaCMS ve yetkilendirmeli interaktif API oyunalanı ile dokümantasyon sitesi oluşturuyor." + /> + <LinkCard + href="https://www.olets.dev/posts/comparing-docs-site-builders-vuepress-vs-starlight/" + title="Dokümantasyon site oluşturucularını karşılaştırmak: VuePress ve Starlight" + description="Bu iki çerçeve nasıl ölçülür?" + /> +</CardGrid> + +## Tarifler ve Rehberler + +Tarifler tipik olarak kısa, okuyucuya belirli bir görevi tamamlayan çalışan örneğini sunan nasıl yapılır rehberi odaklıdır. Tarifler yeni özellik eklemek ya da Starlight projesine takip eden adım adım açıklamalar ile davranış eklemenin mükemmel bir yoludur! Diğer rehber içerik alanı ile ilişkili konseptleri açıklayabilir, görselleri kullanmak ya da MDX ile çalışmak gibi. + +Starlight kullanıcı tarafından sağlanan topluluk üretimi içerikleri keşfedin: + +<CardGrid> + <LinkCard + href="https://www.webpro.nl/scraps/versioned-docs-with-starlight-and-vercel" + title="Starlight ve Vercel ile Versiyonlanmış dokümantasyon" + description="Bir projenin her ana versiyonu için ayrı dokümantasyon versiyonlarının uygulanmasına yönelik bir rehber" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-heading-links" + title="Starlight başlıklarına bağlantılar ekleyin" + description="Belgelerinizin belirli bölümlerine giden bağlantıları paylaşmak için rehype eklentisi kullanma rehberi" + /> + <LinkCard + href="https://blog.otterlord.dev/posts/starlight-sponsors/" + title="Starlight sitenize sponsor ekleyin" + description="Belgelerinizin kenar çubuğuna özel sponsorlar bileşenini uygulamaya yönelik bir rehber" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images" + title="Starlight'a Open Graph görselleri ekleme" + description="Sayfalarınız için sosyal görseller ve ilgili meta etiketleri oluşturma rehberi" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-third-party-icon-sets" + title="Starlight'ta üçüncü taraf ikon setlerini kullanın" + description="Starlight için mevcut ikonların seçimini genişletmek amacıyla unplugin-icons kullanma rehberi" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-html-head" + title="Starlight sayfalarının HTML başlığını düzenleyin" + description="Web analizi, yazı tipleri ve komut dosyaları gibi ortak başlık içeriğini nasıl ekleyeceğinizi öğrenin" + /> + <LinkCard + href="https://dev.to/mrrobot/publishing-documentation-with-astro-starlight-691" + title="Astro Starlight ile Belgelerin Yayınlanması" + description="Starlight dokümantasyonunu kullanmaya başlama" + /> + <LinkCard + href="https://events-3bg.pages.dev/jotter/starlight/guide/" + title="Görünüm Geçişlerini Etkinleştir" + description="Bag of Tricks'in görünüm geçiş desteğiyle SPA benzeri görünüm ve hissi elde edin" + /> +</CardGrid> + +## Video İçerikleri + +Canlı yayınlar ve eğitim içerikleri de dahil olmak üzere Starlight içeriğine sahip videoları ve kanalları keşfedin. + +import YouTubeGrid from '~/components/youtube-grid.astro'; + +### Astro Videoları + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=5u0Ds7wzUeI', + title: "Astro'dan Starlight", + description: 'Resmi Starlight lansman videosunu izleyin', + }, + { + href: 'https://www.youtube.com/shorts/zjOWezSzd18', + title: '🌟 1 DAKİKA ALTINDA HAZIR', + description: + "Ben'in bir dakikadan kısa sürede yeni bir Starlight sitesi açmasını izleyin!", + }, + ]} +/> + +### Topluluk Videoları ve Yayınları + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=sF6UcV3moZg', + title: 'Starlight ve Astro ile dokümanlar oluşturma', + description: + "CodingCat.dev ile Chris ve Alex'in Code'da Starlight'a girişini izleyin", + }, + { + href: 'https://www.youtube.com/watch?v=sWkkHbwDeQc', + title: 'Astro Starlight', + description: "Bir dakikadan kısa sürede Starlight'a giriş.", + }, + { + href: 'https://www.youtube.com/watch?v=-Ki-1E5gNCk', + title: + 'Astro Starlight Belgelendirme Şablonu (özel uygulama belgeleri oluşturun!)', + description: + 'Yaklaşık 5 dakika içinde yeni bir Starlight sitesini çalışır duruma getirin', + }, + { + href: 'https://www.youtube.com/watch?v=12o7WxjAxjM', + title: "Starlight belgelerini proxy'lerle Next.js projesine dahil etme", + description: + "Starlight'ı Next.js web sitesinde bir alt dizin projesi olarak ayarlama", + }, + { + href: 'https://www.youtube.com/watch?v=5pq80drDrNs', + title: + "Bu Harika Araçla Shadcn'in Dokümanlarını 30 Dakikada Yeniden Oluşturdum", + description: + "Bu videoda Starlight'ı bu kadar harika yapan şeyin ne olduğunu ve bir sonraki projenizde neden onu denemek isteyebileceğinizi ele alacağım.", + }, + ]} +/> diff --git a/docs/src/content/docs/tr/resources/showcase.mdx b/docs/src/content/docs/tr/resources/showcase.mdx new file mode 100644 index 00000000000..4d30cf433cc --- /dev/null +++ b/docs/src/content/docs/tr/resources/showcase.mdx @@ -0,0 +1,21 @@ +--- +title: Starlight Vitrini +description: Starlight ile hazırlanmış siteleri keşfet! +sidebar: + label: Site Vitrini +--- + +:::tip[Seninkini ekle!] +Starlight ile site yaptın mı? +Bu sayfaya bağlantı eklemek için [PR açın](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#showcase)! +::: + +## Siteler + +import ShowcaseSites from '~/components/showcase-sites.astro'; + +Starlight halihazırda canlıda kullanılıyor. Web'deki bazı siteler şunlar: + +<ShowcaseSites /> + +[Github üzerinde Starlight kullanan herkese açık proje repolarının](https://github.com/withastro/starlight/network/dependents) tümüne bakın. diff --git a/docs/src/content/docs/uk/404.md b/docs/src/content/docs/uk/404.md new file mode 100644 index 00000000000..49ea221fba8 --- /dev/null +++ b/docs/src/content/docs/uk/404.md @@ -0,0 +1,14 @@ +--- +title: Не знайдено +template: splash +editUrl: false +lastUpdated: false +hero: + title: '404' + tagline: <strong>Г'юстоне, у нас проблема.</strong> Ми не змогли знайти цю сторінку.<br>Перевірте URL або спробуйте скористатися пошуком. + actions: + - text: Додому + icon: right-arrow + link: /uk/ + variant: primary +--- diff --git a/docs/src/content/docs/uk/getting-started.mdx b/docs/src/content/docs/uk/getting-started.mdx new file mode 100644 index 00000000000..bc4ff46238a --- /dev/null +++ b/docs/src/content/docs/uk/getting-started.mdx @@ -0,0 +1,174 @@ +--- +title: Вступ +description: Дізнайтеся, як стати до створення свого наступного документаційного сайту зі Starlight від Astro. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +Starlight ─ це повнофункціональна документаційна схема, побудована на основа фреймворку [Astro](https://astro.build). +Цей ґайд допоможе вам розпочати роботу над новим проєктом. +Щоби додати Starlight до наявного проєкту Astro, дивіться [інструкції з ручного встановлення](/uk/manual-setup/). + +## Прудкий старт + +### Створіть новий проєкт + +Створіть новий проєкт Astro + Starlight, виконавши наступну команду в вашому терміналі: + +<Tabs> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight +``` + +</TabItem> +</Tabs> + +Це створить нову [директорію проєкту](/uk/guides/project-structure/) з усіма необхідними файлами й конфіґурацією для вашого сайту. + +:::tip[Побачте це в дії] +Випробуйте Starlight у вашому браузері: +[відкрити шаблон на StackBlitz](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics). +::: + +### Запустіть розробницький сервер + +Коли працюєте локально, [розробницький сервер Astro](https://docs.astro.build/en/reference/cli-reference/#astro-dev) дозволяє попередньо переглянути вашу роботу та автоматично оновлює браузер, щойно ви вносите зміни. + +Щоби запустити розробницький сервер, виконайте таку команду в теці вашого проєкту: + +<Tabs> +<TabItem label="npm"> + +```sh +npm run dev +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm dev +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev +``` + +</TabItem> +</Tabs> + +У термінал видрукується URL локального сервера. +Відкрийте цю ланку, щоби переглянути сайт. + +### Додайте контент + +Starlight підготовлено, тепер ви можете додавати новий контент або долучати наявні файли! + +#### Формати файлів + +Starlight підтримує створення контенту у форматах Markdown і MDX без жодних додаткових налаштувань. +Ви можете додати підтримку Markdoc, встановивши експериментальну [інтеґрацію Astro Markdoc](https://docs.astro.build/guides/integrations-guide/markdoc/). + +#### Додайте сторінки + +Додавайте нові сторінки на ваш сайт, створюючи файли `.md` та `.mdx` у теці `src/content/docs/`. +Використовуйте підтеки, щоб орґанізовувати файли та створювати множинні сеґменти шляху. + +Наприклад, оттака структура файлів зґенерує сторінки за адресами `example.com/hello-world` і `example.com/guides/faq`: + +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src/ + - content/ + - docs/ + - guides/ + - faq.md + - hello-world.md + +</FileTree> + +#### Безпека типів у преамбулі (frontmatter) + +У Starlight усі сторінки поділяють спільний налаштовуваний [набір властивостей преамбули](/uk/reference/frontmatter/), якими визначається вигляд сторінки: + +```md +--- +title: Привіт, світ! +description: Це сторінка на моїм сайті, що він працює на Starlight! +--- +``` + +Якщо ви забудете щось важливе, Starlight сповістить вас про це. + +### Наступні кроки + +- **Конфіґурація:** Дізнайтеся про поширені параметри в ґайді [“Налаштовування Starlight”](/uk/guides/customization/). +- **Навіґація:** Спорудить бічну панель у розділі [“Навіґація бічною панеллю”](/uk/guides/sidebar/). +- **Компоненти:** Відкрийте вбудовані картки, вкладки та багато іншого в [“Компонентах”](/uk/components/using-components/). +- **Розгортування:** Опублікуйте власну працю за допомогою посібника [“Розгорніть свій сайт”](https://docs.astro.build/guides/deploy/) в документації Astro. + +## Оновлення Starlight + +:::tip +Оскільки Starlight поки на стадії beta, очікуйте частих оновлень. +Не забувайте регулярно оновлювати Starlight! +::: + +Starlight є інтеґрацією Astro, отже ви можете оновити його так само, як і решту пакетів Astro, ─ виконавши в терміналі команду: + +<Tabs> +<TabItem label="npm"> + +```sh +npx @astrojs/upgrade +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm dlx @astrojs/upgrade +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dlx @astrojs/upgrade +``` + +</TabItem> +</Tabs> + +Повний список змін до кожного релізу дивіться в [списку змін Starlight](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md). + +## Зневадження Starlight + +Використовуйте довідкові сторінки [конфіґурація проєкту](/uk/reference/configuration/) та [індивідуальні налаштуванні преамбули сторінки](/uk/reference/frontmatter/), щоб упевнитися, що ваш сайт налаштований і функціонує належним чином. +Перегляньте ґайди на бічній панелі, щоби дізнатися, як додавати контент і налаштовувати сайт Starlight. + +Якщо ви не можете знайти відповідь у цій документації, будь ласка, перегляньте [повну документацію Astro](https://docs.astro.build/). +Ваше питання можна вирішити, зрозумівши, як працює Астро загалом, під капотом Starlight. + +Ви також можете перевірити відомі [проблеми Starlight на GitHub](https://github.com/withastro/starlight/issues), а також звернутися по допомогу на [Discord-сервері Astro](https://astro.build/chat/) до нашої активної, дружньої спільноти! Ставте запитання в гілці `#support` із теґом "starlight" або відвідайте спеціальну гілку `#starlight`, щоб обговорити поточну розробку та багато іншого! diff --git a/docs/src/content/docs/uk/index.mdx b/docs/src/content/docs/uk/index.mdx new file mode 100644 index 00000000000..e35e7229791 --- /dev/null +++ b/docs/src/content/docs/uk/index.mdx @@ -0,0 +1,169 @@ +--- +title: Starlight 🌟 Створюйте документацію з Astro +head: + - tag: title + content: Starlight 🌟 Створюйте документацію з Astro +description: Starlight допомагає створювати якісну й високоефективну документацію за допомогою Astro. +template: splash +editUrl: false +lastUpdated: false +banner: + content: | + Оновлюєтесь до Astro 5? + <a href="https://github.com/withastro/starlight/releases/tag/%40astrojs/starlight%400.30.0"> + Дізнайтеся, як оновити + </a> +hero: + title: Осяйте вашу документацію зі Starlight + tagline: Усе, що треба для створення блискучого сайту з документацією. Швидко, доступно та без зайвих складнощів. + image: + file: ~/assets/hero-star.webp + actions: + - text: Розпочати + icon: right-arrow + link: /uk/getting-started/ + - text: Переглянути на GitHub + icon: external + variant: minimal + link: https://github.com/withastro/starlight +--- + +import { CardGrid, Card } from '@astrojs/starlight/components'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; + +<CardGrid stagger> + <Card title="Документація, яка вражає" icon="open-book"> + Включає в себе: навігацію сайтом, пошук, інтернаціоналізацію, SEO, чітку + типографіку, підсвітку коду, темний режим і багато іншого. + </Card> + <Card title="Працює на Astro" icon="rocket"> + Отримайте усю міць і швидкість Astro. Розширте можливості Starlight за + допомогою ваших улюблених інтеграцій та бібліотек для Astro. + </Card> + <Card title="Markdown, Markdoc і MDX" icon="document"> + Використовуйте свою улюблену мову розмітки. Starlight має вбудовану + валідацію фронтматера і типобезпечність TypeScript. + </Card> + <Card title="Використовуйте вже створені власні UI-компоненти" icon="puzzle"> + Starlight - це фреймворк-незалежне рішення повного циклу для створення + документації. Воно легко поєднується з React, Vue, Svelte, Solid тощо. + </Card> +</CardGrid> + +<TestimonialGrid title="Що кажуть люди"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + Команда Astro УДОСКОНАЛИЛА процес створення документації, і ви можете отримати все це завдяки їх проєкту Starlight. + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + Astro Starlight - це дійсно неймовірний інструмент для створення веб-сайту з документацією. + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + Starlight - найкращий приклад чудового DX: швидкість, зручність та + увага до деталей надихає. Вона бере на себе технології та зовнішній вигляд, + щоб ви могли зосередитися на вмісті 👏 + + Команда StackBlitz абсолютно в захваті від неї! + + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + Starlight змінила для мене правила гри, дозволивши зосередитися на створенні контенту. + + Її інтуїтивно зрозумілий дизайн не лише спрощує мій робочий процес, але й скорочує час впровадження для розробників відкритого коду. + + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + Провів ще трохи часу зі Starlight створюючи документацію для Course Builder, і це був чудовий досвід. Багато приємних дрібниць, і головне що можна зосередитися на написанні в Markdown, а не на налаштуванні сайту. + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + Вирішив погратися зі Starlight. Маю зазначити, що я дуже вражений продуктивністю зі старту. + + 💯💯💯💯 + + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + Starlight — найкращий спосіб почати створювати документацію: + потужність і швидкість Astro разом із інструментами Starlight — + це ідеальне поєднання. + + Це мій улюблений інструмент вже давно, і я продовжую захоплюватися ним! + + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + Я використовувала Starlight на попередній роботі й була у захваті. Чудові компоненти, інтуїтивний + дизайн і надзвичайно чуйна спільнота (коли комусь щось було потрібно, + вони швидко додавали це або пропонували альтернативне рішення). Дуже приємний досвід. + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + Документація мого сайту-монорепозиторію виглядає краще, ніж будь-коли, завдяки Starlight. Її надзвичайно легко використовувати, не втрачаючи всю потужність Astro. Дякую за вашу роботу над цим! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + Starlight — мій улюблений інструмент для документації. Завдяки йому я легко додав документацію до свого існуючого сайту на Astro, при цьому не довелося створювати окремий піддомен, як з іншими подібними інструментами. + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + Я перебудовую документацію платформи WPEngine Atlas. Повірте, Starlight має все необхідне, щоб створити платформу з документацією найвищого рівня 🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + Спробуйте Starlight! + + Я використовую його для кількох своїх сайтів, і вона чудова. + + </Testimonial> +</TestimonialGrid> + +<AboutAstro title="Подано"> +Astro ─ це універсальний веб-фреймворк налаштований на швидкість. +Беріть контент хоч звідки та розгортайте його будь-де, використовуючи ваші улюблені UI-компоненти і бібліотеки. + +[Дізнатися більше про Astro](https://astro.build/) + +</AboutAstro> diff --git a/docs/src/content/docs/uk/manual-setup.mdx b/docs/src/content/docs/uk/manual-setup.mdx new file mode 100644 index 00000000000..a55c4caac72 --- /dev/null +++ b/docs/src/content/docs/uk/manual-setup.mdx @@ -0,0 +1,116 @@ +--- +title: Ручне налаштування +description: Дізнайтеся, як налаштувати Starlight вручну для додавання його в існуючий проект Astro. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +Найшвидший спосіб створити новий сайт Starlight - це скористатися командою `create astro` як показано у [Вступі](/uk/getting-started/#створіть-новий-проєкт). +Якщо ви хочете додати Starlight до існуючого проекту Astro, цей посібник пояснить як. + +## Налаштування Starlight + +Щоб слідувати цьому посібнику, вам знадобиться існуючий проєкт Astro. + +### Додайте інтеґрацію Starlight + +Starlight є [інтеґрацією Astro](https://docs.astro.build/en/guides/integrations-guide/). Додайте її до свого сайту, виконавши команду `astro add` у кореневій директорії вашого проєкту: + +<Tabs syncKey="pkg"> + <TabItem label="npm">```sh npx astro add starlight ```</TabItem> + <TabItem label="pnpm">```sh pnpm astro add starlight ```</TabItem> + <TabItem label="Yarn">```sh yarn astro add starlight ```</TabItem> +</Tabs> + +Це встановить необхідні залежності та додасть Starlight до масиву integrations у вашому конфіґураційному файлі Astro. + +### Налаштуйте інтеґрацію + +Інтеґрація Starlight налаштовується у файлі `astro.config.mjs`. + +Додайте `title`, щоб почати: + +```js ins={8} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Мій чудовий сайт документації', + }), + ], +}); +``` + +Знайдіть усі доступні параметри в [документації з налаштування Starlight](/uk/reference/configuration/). + +### Налаштуйте колекції контенту + +Starlight побудований поверх [колекцій вмісту](https://docs.astro.build/en/guides/content-collections/) в Astro, які налаштовуються в файлі `src/content/config.ts`. + +Створіть або оновіть файл конфіґурації вмісту, додавши колекцію `docs`, яка використовує `docsSchema` від Starlight: + +```js ins={3,6} +// src/content/config.ts +import { defineCollection } from 'astro:content'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ schema: docsSchema() }), +}; +``` + +### Додайте вміст + +Starlight тепер налаштовано, і час додати трохи вмісту! + +Створіть директорію `src/content/docs/` і почніть з додавання файлу `index.md`. +Це буде домашня сторінка вашого нового сайту: + +```md +--- +# src/content/docs/index.md +title: Моя документація +description: Дізнайтеся більше про мій проєкт на цьому сайті документації, створеному за допомогою Starlight. +--- + +Ласкаво просимо до мого проєкту! +``` + +Starlight використовує маршрутизацію на основі файлів, що означає, що кожен файл Markdown, MDX або Markdoc у `src/content/docs/` стане сторінкою на вашому сайті. Метадані Frontmatter (поля `title` і `description` в наведеному вище прикладі) можуть змінити спосіб відображення кожної сторінки. +Перегляньте всі доступні параметри в [документації frontmatter](/uk/reference/frontmatter/). + +## Поради щодо існуючих сайтів + +Якщо у вас вже є існуючий проект Astro, ви можете використовувати Starlight для швидкого додавання розділу документації на ваш сайт. + +### Використання Starlight з підшляхами + +Щоб додати всі сторінки Starlight в підшлях, розмістіть весь свій вміст в підкаталозі `src/content/docs/`. + +Наприклад, якщо Starlight сторінки повинні всі починатися з `/guides/`, додайте свій вміст в `src/content/docs/guides/` каталог: + +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src/ + - content/ + - docs/ + - **guides/** + - guide.md + - index.md + - pages/ +- astro.config.mjs + +</FileTree> + +У майбутньому ми плануємо краще підтримувати цей випадок, щоб уникнути необхідності в додатковій вкладеній директорії в `src/content/docs/`. + +### Використання Starlight з SSR + +Щоб увімкнути SSR, дотримуйтесь посібника [“Адаптери для рендерингу на вимогу”](https://docs.astro.build/en/guides/server-side-rendering/) в документації Astro, щоб додати серверний адаптер до вашого проєкту Starlight. + +Сторінки документації, згенеровані Starlight, попередньо рендеряться за замовчуванням незалежно від режиму виводу вашого проєкту. Щоб вимкнути попередній рендеринг ваших сторінок Starlight, встановіть [параметр конфіґурації `prerender`](/uk/reference/configuration/#prerender) у значення `false`. diff --git a/docs/src/content/docs/zh/404.md b/docs/src/content/docs/zh-cn/404.md similarity index 88% rename from docs/src/content/docs/zh/404.md rename to docs/src/content/docs/zh-cn/404.md index c72eb160ec4..da90468e6bf 100644 --- a/docs/src/content/docs/zh/404.md +++ b/docs/src/content/docs/zh-cn/404.md @@ -2,12 +2,13 @@ title: 页面未找到 template: splash editUrl: false +lastUpdated: false hero: title: '404' tagline: <strong>休斯顿,我们遇到了一个问题。</strong>我们找不到该页面。<br>请检查 URL 或尝试使用搜索栏。 actions: - text: 返回首页 icon: right-arrow - link: /zh/ + link: /zh-cn/ variant: primary --- diff --git a/docs/src/content/docs/zh-cn/components/asides.mdx b/docs/src/content/docs/zh-cn/components/asides.mdx new file mode 100644 index 00000000000..8ad18d26f36 --- /dev/null +++ b/docs/src/content/docs/zh-cn/components/asides.mdx @@ -0,0 +1,158 @@ +--- +title: 旁白 +description: 了解如何在 Starlight 中使用旁白,从而在页面的主要内容旁边显示次要信息。 +--- + +import { Aside } from '@astrojs/starlight/components'; + +要在页面的主要内容旁边显示次要信息,请使用 `<Aside>` 组件。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Aside slot="preview"> + 在 `<Aside>` 中包含非必要的补充信息。 +</Aside> + +</Preview> + +## 导入 + +```tsx +import { Aside } from '@astrojs/starlight/components'; +``` + +## 用法 + +使用 `<Aside>` 组件以显示旁白(也称为“警告”或“标注”)。 + +`<Aside>` 有一个可选的 [`type`](#type) 属性,它控制着旁白的颜色、图标和默认标题。 + +<Preview> + +````mdx +import { Aside } from '@astrojs/starlight/components'; + +<Aside>一些在旁白中的内容。</Aside> + +<Aside type="caution">一些警示内容。</Aside> + +<Aside type="tip"> + +旁白中还支持其他内容。 + +```js +// 例如,代码片段。 +``` + +</Aside> + +<Aside type="danger">不要将你的密码告诉任何人。</Aside> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% aside %} +一些在旁白中的内容。 +{% /aside %} + +{% aside type="caution" %} +一些警示内容。 +{% /aside %} + +{% aside type="tip" %} +旁白中还支持其他内容。 + +```js +// 例如,代码片段。 +``` +{% /aside %} + +{% aside type="danger" %} +不要将你的密码告诉任何人。 +{% /aside %} +```` + +</Fragment> + +<Fragment slot="preview"> + + <Aside>一些在旁白中的内容。</Aside> + + <Aside type="caution">一些警示内容。</Aside> + + <Aside type="tip"> + + 旁白中还支持其他内容。 + + ```js + // 例如,代码片段。 + ``` + + </Aside> + + <Aside type="danger">不要将你的密码告诉任何人。</Aside> + +</Fragment> + +</Preview> + +Starlight 还提供了用于在 Markdown 和 MDX 中渲染旁白的自定义语法,以此作为 `<Aside>` 组件的替代方案。 +有关自定义语法的详细信息,请参阅 [“在 Markdown 中创作内容”](/zh-cn/guides/authoring-content/#旁白) 指南。 + +### 使用自定义标题 + +使用 [`title`](#title) 属性覆盖默认的旁白标题。 + +<Preview> + +```mdx 'title="当心!"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="caution" title="当心!"> + *带有* 自定义标题的警告。 +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'title="当心!"' +{% aside type="caution" title="当心!" %} +*带有* 自定义标题的警告。 +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="caution" title="当心!"> + *带有* 自定义标题的警告。 +</Aside> + +</Preview> + +## `<Aside>` 的属性 + +**实现:** [`Aside.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Aside.astro) + +`<Aside>` 组件接受以下属性: + +### `type` + +**类型:** `'note' | 'tip' | 'caution' | 'danger'` +**默认值:** `'note'` + +要显示的旁白类型: + +- `note` 旁白(默认)为蓝色,并带有一个信息的图标。 +- `tip` 旁白为紫色,并带有一个火箭的图标。 +- `caution` 旁白为黄色,并带有一个三角警示图标。 +- `danger` 旁白为红色。并带有一个八边形警示图标。 + +### `title` + +**类型:** `string` + +要显示的旁白的标题。 +如果未设置 `title`,则将使用当前旁白的 `type` 作为默认标题。 diff --git a/docs/src/content/docs/zh-cn/components/badges.mdx b/docs/src/content/docs/zh-cn/components/badges.mdx new file mode 100644 index 00000000000..ba1311292fd --- /dev/null +++ b/docs/src/content/docs/zh-cn/components/badges.mdx @@ -0,0 +1,150 @@ +--- +title: 徽章 +description: 了解如何在 Starlight 中使用徽章来显示额外的信息。 +--- + +import { Badge } from '@astrojs/starlight/components'; + +要显示小段信息,例如状态或类别,请使用 `<Badge>` 组件。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Badge slot="preview" text="新" /> + +</Preview> + +## 导入 + +```tsx +import { Badge } from '@astrojs/starlight/components'; +``` + +## 用法 + +使用 `<Badge>` 组件显示徽章,并将要显示的内容传递给 `<Badge>` 组件的 [`text`](#text) 属性。 + +默认情况下,徽章将使用你网站主题的强调色。 +要使用徽章内置的某一种颜色,请将 [`variant`](#variant) 属性设置为支持的值之一。 + +<Preview> + +```mdx +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="注释" variant="note" /> +- <Badge text="成功" variant="success" /> +- <Badge text="提示" variant="tip" /> +- <Badge text="注意" variant="caution" /> +- <Badge text="危险" variant="danger" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +- {% badge text="注释" variant="note" /%} +- {% badge text="成功" variant="success" /%} +- {% badge text="提示" variant="tip" /%} +- {% badge text="注意" variant="caution" /%} +- {% badge text="危险" variant="danger" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="注释" variant="note" /> + - <Badge text="成功" variant="success" /> + - <Badge text="提示" variant="tip" /> + - <Badge text="注意" variant="caution" /> + - <Badge text="危险" variant="danger" /> +</Fragment> + +</Preview> + +### 使用不同的尺寸 + +使用 [`size`](#size) 属性来控制徽章文本的大小。 + +<Preview> + +```mdx /size="\w+"/ +import { Badge } from '@astrojs/starlight/components'; + +- <Badge text="新" size="small" /> +- <Badge text="更新更强" size="medium" /> +- <Badge text="更新更强更逼格" size="large" /> +``` + +<Fragment slot="markdoc"> + +```markdoc /size="\w+"/ +- {% badge text="新" size="small" /%} +- {% badge text="更新更强" size="medium" /%} +- {% badge text="更新更强更逼格" size="large" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + - <Badge text="新" size="small" /> + - <Badge text="更新更强" size="medium" /> + - <Badge text="更新更强更逼格" size="large" /> +</Fragment> + +</Preview> + +### 自定义徽章 + +通过使用任何其他 `<span>` 属性(例如带有自定义 CSS 的 `class` 或 `style`)来自定义徽章。 + +<Preview> + +```mdx "style={{ fontStyle: 'italic' }}" +import { Badge } from '@astrojs/starlight/components'; + +<Badge text="自定义" variant="success" style={{ fontStyle: 'italic' }} /> +``` + +<Fragment slot="markdoc"> + +```markdoc 'style="font-style: italic;"' +{% badge text="自定义" variant="success" style="font-style: italic;" /%} +``` + +</Fragment> + +<Badge + slot="preview" + text="自定义" + variant="success" + style={{ fontStyle: 'italic' }} +/> + +</Preview> + +## `<Badge>` 的属性 + +**实现:** [`Badge.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Badge.astro) + +`<Badge>` 组件接受以下属性,以及所有 [其他的 `<span>` 属性](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Global_attributes): + +### `text` + +**必要属性** +**类型:** `string` + +要在徽章中显示的文本内容。 + +### `variant` + +**类型:** `'note' | 'danger' | 'success' | 'caution' | 'tip' | 'default'` +**默认值:** `'default'` + +要使用的徽章颜色变体:`note`(蓝色)、`tip`(紫色)、`danger`(红色)、`caution`(橙色)、`success`(绿色)或 `defaul`(主题强调色)。 + +### `size` + +**类型:** `'small' | 'medium' | 'large'` + +定义要显示的徽章的大小。 diff --git a/docs/src/content/docs/zh-cn/components/card-grids.mdx b/docs/src/content/docs/zh-cn/components/card-grids.mdx new file mode 100644 index 00000000000..09f4bab1752 --- /dev/null +++ b/docs/src/content/docs/zh-cn/components/card-grids.mdx @@ -0,0 +1,173 @@ +--- +title: 卡片网格 +description: 了解如何在 Starlight 中将多张卡片包裹在网格中。 +sidebar: + order: 4 +--- + +import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; + +要将多个 [`<Card>`](/zh-cn/components/cards/) 或 [`<LinkCard>`](/zh-cn/components/link-cards/) 组件包装在网格中,请使用 `<CardGrid>` 组件。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<CardGrid slot="preview"> + <Card title="星星" icon="star"> + 天狼星,织女星,参宿四 + </Card> + <Card title="卫星" icon="moon"> + 木卫一,木卫二,木卫三 + </Card> +</CardGrid> + +</Preview> + +## 导入 + +```tsx +import { CardGrid } from '@astrojs/starlight/components'; +``` + +## 用法 + +### 分组卡片 + +当有足够大的空间时,可以使用 `<CardGrid>` 组件对卡片进行分组,并排显示多个 [`<Card>`](/zh-cn/components/cards/) 组件。 + +<Preview> + +```mdx {3,10} +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <Card title="试试这个" icon="open-book"> + 一些你想着重展示的有趣内容。 + </Card> + <Card title="其他功能" icon="information"> + 更多你想分享的信息。 + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,9} +{% cardgrid %} +{% card title="试试这个" icon="open-book" %} +一些你想着重展示的有趣内容。 +{% /card %} + +{% card title="其他功能" icon="information" %} +更多你想分享的信息。 +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <Card title="试试这个" icon="open-book"> + 一些你想着重展示的有趣内容。 + </Card> + <Card title="其他功能" icon="information"> + 更多你想分享的信息。 + </Card> +</CardGrid> + +</Preview> + +### 分组链接卡片 + +当有足够大的空间时,可以使用 `<CardGrid>` 组件对链接卡片进行分组,并排显示多个 [`<LinkCard>`](/zh-cn/components/link-cards/) 组件。 + +<Preview> + +```mdx {3,6} +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid> + <LinkCard title="Markdown 创作" href="/zh-cn/guides/authoring-content/" /> + <LinkCard title="组件" href="/zh-cn/components/using-components/" /> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc {1,5} +{% cardgrid %} +{% linkcard title="Markdown 创作" href="/zh-cn/guides/authoring-content/" /%} + +{% linkcard title="组件" href="/zh-cn/components/using-components/" /%} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview"> + <LinkCard title="Markdown 创作" href="/zh-cn/guides/authoring-content/" /> + <LinkCard title="组件" href="/zh-cn/components/using-components/" /> +</CardGrid> + +</Preview> + +### 交错卡片 + +通过向 `<CardGrid>` 组件添加 [`stagger`](#stagger) 属性,使网格的第二列卡片向着垂直方向移动,从而增添视觉趣味。 + +该属性在主页上非常有用,可用于展示项目的核心功能。 + +<Preview> + +```mdx "stagger" +import { Card, CardGrid } from '@astrojs/starlight/components'; + +<CardGrid stagger> + <Card title="试试这个" icon="open-book"> + 一些你想着重展示的有趣内容。 + </Card> + <Card title="其他功能" icon="information"> + 更多你想分享的信息。 + </Card> +</CardGrid> +``` + +<Fragment slot="markdoc"> + +```markdoc "stagger=true" +{% cardgrid stagger=true %} +{% card title="试试这个" icon="open-book" %} +一些你想着重展示的有趣内容。 +{% /card %} + +{% card title="其他功能" icon="information" %} +更多你想分享的信息。 +{% /card %} +{% /cardgrid %} +``` + +</Fragment> + +<CardGrid slot="preview" stagger> + <Card title="试试这个" icon="open-book"> + 一些你想着重展示的有趣内容。 + </Card> + <Card title="其他功能" icon="information"> + 更多你想分享的信息。 + </Card> +</CardGrid> + +</Preview> + +## `<CardGrid>` 的属性 + +**实现:** [`CardGrid.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/CardGrid.astro) + +`<CardGrid>` 组件接受以下属性: + +### `stagger` + +**类型:** `boolean` + +定义是否在网格中交错卡片。 diff --git a/docs/src/content/docs/zh-cn/components/cards.mdx b/docs/src/content/docs/zh-cn/components/cards.mdx new file mode 100644 index 00000000000..d7606f88a69 --- /dev/null +++ b/docs/src/content/docs/zh-cn/components/cards.mdx @@ -0,0 +1,108 @@ +--- +title: 卡片 +description: 了解如何在 Starlight 中使用卡片来显示框中的内容。 +sidebar: + order: 2 +--- + +import { Card } from '@astrojs/starlight/components'; + +要在框中显示与 Starlight 样式匹配的内容,请使用 `<Card>` 组件。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Card slot="preview" title="卫星" icon="moon"> + 木卫一,木卫二,木卫三 +</Card> + +</Preview> + +## 导入 + +```tsx +import { Card } from '@astrojs/starlight/components'; +``` + +## 用法 + +使用 `<Card>` 组件来显示卡片,并为其提供一个 [`title`](#title)。 + +<Preview> + +```mdx +import { Card } from '@astrojs/starlight/components'; + +<Card title="试试这个">一些你想着重展示的有趣内容。</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% card title="试试这个" %} +一些你想着重展示的有趣内容。 +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="试试这个"> + 一些你想着重展示的有趣内容。 +</Card> + +</Preview> + +### 为卡片添加图标 + +要在卡片中包含一个图标,请把 [`icon`](#icon) 属性设置为 [Starlight 的内置图标名称之一](/zh-cn/reference/icons/#所有图标)。 + +<Preview> + +```mdx 'icon="star"' +import { Card } from '@astrojs/starlight/components'; + +<Card title="星星" icon="star"> + 天狼星,织女星,参宿四 +</Card> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="star"' +{% card title="星星" icon="star" %} +天狼星,织女星,参宿四 +{% /card %} +``` + +</Fragment> + +<Card slot="preview" title="星星" icon="star"> + 天狼星,织女星,参宿四 +</Card> + +</Preview> + +### 分组卡片 + +当有足够大的空间时,可以使用 [`<CardGrid>`](/zh-cn/components/card-grids/) 组件将多个卡片分组,并排显示多个卡片。 +有关示例,请参阅 [“分组卡片”](/zh-cn/components/card-grids/#分组卡片) 指南。 + +## `<Card>` 的属性 + +**实现:** [`Card.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Card.astro) + +`<Card>` 组件接受以下属性: + +### `title` + +**必要属性** +**类型:** `string` + +要显示的卡片标题。 + +### `icon` + +**类型:** `string` + +将 `icon` 属性设置为 [Starlight 的内置图标名称之一](/zh-cn/reference/icons/#所有图标),能够使卡片包含一个图标。 diff --git a/docs/src/content/docs/zh-cn/components/code.mdx b/docs/src/content/docs/zh-cn/components/code.mdx new file mode 100644 index 00000000000..5c56e4e9fe8 --- /dev/null +++ b/docs/src/content/docs/zh-cn/components/code.mdx @@ -0,0 +1,103 @@ +--- +title: 代码 +description: 了解如何在没有 Markdown 代码块的情况下,在 Starlight 中显示语法高亮的代码。 +--- + +import { Code } from '@astrojs/starlight/components'; + +`<Code>` 组件可以渲染出语法高亮的代码。 +当无法使用 [Markdown 代码块](/zh-cn/guides/authoring-content/#代码块) 时,它非常有用,例如,渲染来自文件、数据库或 API 等外部源的数据。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Code + slot="preview" + code={`## 欢迎 + +来自 **宇宙** 的问候!`} +lang="md" +title="example.md" +ins={3} +/> + +</Preview> + +## 导入 + +```tsx +import { Code } from '@astrojs/starlight/components'; +``` + +## 用法 + +使用 `<Code>` 组件的渲染能将代码语法高亮,例如在展示从外部源获取的代码时。 + +有关如何使用 `<Code>` 组件和可用属性的完整列表信息,请参阅 [Expressive Code “代码组件” 文档](https://expressive-code.com/key-features/code-component/)。 + +<Preview> + +```mdx +import { Code } from '@astrojs/starlight/components'; + +export const exampleCode = `console.log('这可能来自文件或 CMS!');`; +export const fileName = 'example.js'; +export const highlights = ['文件', 'CMS']; + +<Code code={exampleCode} lang="js" title={fileName} mark={highlights} /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% code + code="console.log('这可能来自文件或 CMS!');" + lang="js" + title="example.js" + meta="'文件' 'CMS'" /%} +``` + +</Fragment> + +export const exampleCode = `console.log('这可能来自文件或 CMS!');`; +export const fileName = 'example.js'; +export const highlights = ['文件', 'CMS']; + +<Code + slot="preview" + code={exampleCode} + lang="js" + title={fileName} + mark={highlights} +/> + +</Preview> + +### 显示导入的代码 + +在 MDX 文件和 Astro 组件中,使用 [Vite 的 `?raw` 导入后缀](https://cn.vite.dev/guide/assets#importing-asset-as-string) 将任何代码文件作为字符串导入。 +然后,你可以将此导入的字符串传递给 `<Code>` 组件,以将其包含在你的页面上。 + +<Preview> + +```mdx "?raw" +# src/content/docs/example.mdx + +import { Code } from '@astrojs/starlight/components'; +import importedCode from '/tsconfig.json?raw'; + +<Code code={importedCode} lang="json" title="tsconfig.json" /> +``` + +import importedCode from '../../../../../../examples/basics/tsconfig.json?raw'; + +<Code slot="preview" code={importedCode} lang="json" title="tsconfig.json" /> + +</Preview> + +## `<Code>` 的属性 + +**实现:** [`Code.astro`](https://github.com/expressive-code/expressive-code/blob/main/packages/astro-expressive-code/components/Code.astro) + +`<Code>` 组件接受 [Expressive Code “Code Component” 文档](https://expressive-code.com/key-features/code-component/#available-props) 中记录的所有 props。 diff --git a/docs/src/content/docs/zh-cn/components/file-tree.mdx b/docs/src/content/docs/zh-cn/components/file-tree.mdx new file mode 100644 index 00000000000..131ee8cfe05 --- /dev/null +++ b/docs/src/content/docs/zh-cn/components/file-tree.mdx @@ -0,0 +1,225 @@ +--- +title: 文件树 +description: 了解如何在 Starlight 中显示带有文件图标和可折叠子目录的目录结构。 +--- + +import { FileTree } from '@astrojs/starlight/components'; + +要显示带有文件图标和可折叠子目录的目录结构,请使用 `<FileTree>` 组件。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<FileTree slot="preview"> + +- astro.config.mjs 一个 **重要** 文件 +- package.json +- README.md +- src + - components + - **Header.astro** + - … +- pages/ + +</FileTree> + +</Preview> + +## 导入 + +```tsx +import { FileTree } from '@astrojs/starlight/components'; +``` + +## 用法 + +使用 `<FileTree>` 组件可以显示带有文件图标和可折叠子目录的文件树。 + +使用 `<FileTree>` 内的 [无序 Markdown 列表](https://www.markdownguide.org/basic-syntax/#unordered-lists) 来指定文件和目录的结构。 +使用嵌套列表可以创建子目录,或在列表项末尾添加 `/` 以将其渲染为没有特定内容的目录。 + +<Preview> + +```mdx +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% filetree %} +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- astro.config.mjs +- package.json +- src + - components + - Header.astro + - Title.astro + - pages/ + +</FileTree> + +</Preview> + +### 高亮显示条目 + +通过将文件或目录的名称加粗,来使文件或目录从中脱颖而出,例如 `**README.md**`。 + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - **Header.astro** + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - **Header.astro** + - Title.astro + +</FileTree> + +</Preview> + +### 添加注释 + +通过在名称后添加更多文本来向文件或目录添加注释。 +注释中支持内联 Markdown 格式,例如粗体和斜体。 + +<Preview> + +```mdx {7} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro 一个 **重要** 文件 + - Title.astro + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% filetree %} +- src + - components + - Header.astro 一个 **重要** 文件 + - Title.astro +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro 一个 **重要** 文件 + - Title.astro + +</FileTree> + +</Preview> + +### 添加占位符 + +将 `...` 或 `…` 作为名称来添加占位符文件和目录。 +这可用于向读者指示文件夹应包含更多项目,而无需明确指定所有项目。 + +<Preview> + +```mdx {8} +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src + - components + - Header.astro + - … + +</FileTree> +``` + +<Fragment slot="markdoc"> + +```markdoc {5} +{% filetree %} +- src + - components + - Header.astro + - … +{% /filetree %} +``` + +</Fragment> + +<FileTree slot="preview"> + +- src + - components + - Header.astro + - … + +</FileTree> + +</Preview> + +## `<FileTree>` 的属性 + +**实现:** [`FileTree.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/FileTree.astro) + +`<FileTree>` 组件不接受任何 props。 diff --git a/docs/src/content/docs/zh-cn/components/icons.mdx b/docs/src/content/docs/zh-cn/components/icons.mdx new file mode 100644 index 00000000000..b0121d59bd4 --- /dev/null +++ b/docs/src/content/docs/zh-cn/components/icons.mdx @@ -0,0 +1,128 @@ +--- +title: 图标 +description: 了解如何在 Starlight 中显示图标。 +--- + +import { Icon } from '@astrojs/starlight/components'; + +要显示 Starlight [内置图标集](/zh-cn/reference/icons/#所有图标) 中的图标,请使用 `<Icon>` 组件。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Icon + slot="preview" + name="open-book" + color="var(--sl-color-text-accent)" + size="4rem" +/> + +</Preview> + +## 导入 + +```tsx +import { Icon } from '@astrojs/starlight/components'; +``` + +## 用法 + +使用 `<Icon>` 组件来显示图标。 +图标需要将 [`name`](#name) 设置为 [Starlight 的内置图标之一](/zh-cn/reference/icons/#所有图标),并且可以选择是否包含 [`label`](#label) 来为屏幕阅读器提供上下文。 + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" /> +<Icon name="starlight" label="Starlight 的 logo" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" /%} +{% icon name="starlight" label="Starlight 的 logo" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" /> + <Icon name="starlight" label="Starlight 的 logo" /> +</Fragment> + +</Preview> + +### 自定义图标 + +[`size`](#size) 和 [`color`](#color) 属性可使用 CSS 单位和颜色值来调整图标的外观。 +[`class`](#class) 属性可用于向图标添加自定义 CSS 类。 + +<Preview> + +```mdx +import { Icon } from '@astrojs/starlight/components'; + +<Icon name="star" color="goldenrod" size="2rem" /> +<Icon name="rocket" color="var(--sl-color-text-accent)" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% icon name="star" color="goldenrod" size="2rem" /%} +{% icon name="rocket" color="var(--sl-color-text-accent)" /%} +``` + +</Fragment> + +<Fragment slot="preview"> + <Icon name="star" color="goldenrod" size="2rem" /> + <Icon name="rocket" color="var(--sl-color-text-accent)" /> +</Fragment> + +</Preview> + +## `<Icon>` 的属性 + +**实现:** [`Icon.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Icon.astro) + +`<Icon>` 组件接受以下属性: + +### `name` + +**必要属性** +**类型:** [`StarlightIcon`](/zh-cn/reference/icons/#starlighticon-类型) + +要显示的图标名称设置为 [Starlight 的内置图标之一](/zh-cn/reference/icons/#所有图标)。 + +### `label` + +**类型:** `string` + +一个可选标签,用于为无障碍技术(例如屏幕阅读器)提供上下文。 + +当未设置 `label` 时,该图标将在无障碍下完全隐藏。 +在这种情况下,请确保在没有图标的情况下,上下文仍然可以理解。 +例如,仅具有图标的链接 **必须** 包含 `label` 属性才能易于识读,但如果链接已经包含了文本,并且图标纯粹是装饰性的,那么省略 `label` 也许更有意义。 + +### `size` + +**类型:** `string` + +图标的大小使用 CSS 单位。 + +### `color` + +**类型:** `string` + +使用 CSS 颜色值的图标颜色。 + +### `class` + +**类型:** `string` + +要添加到图标的自定义 CSS 类。 diff --git a/docs/src/content/docs/zh-cn/components/link-buttons.mdx b/docs/src/content/docs/zh-cn/components/link-buttons.mdx new file mode 100644 index 00000000000..df74d777f4d --- /dev/null +++ b/docs/src/content/docs/zh-cn/components/link-buttons.mdx @@ -0,0 +1,145 @@ +--- +title: 链接按钮 +description: 了解如何在 Starlight 中创建链接按钮,以在视觉上获得独特的号召性用语链接。 +--- + +import { LinkButton } from '@astrojs/starlight/components'; + +要在视觉上展示不同的号召性用语链接,请使用 `<LinkBut​​ton>` 组件。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkButton slot="preview" href="/zh-cn/getting-started/"> + 阅读文档 +</LinkButton> + +</Preview> + +## 导入 + +```tsx +import { LinkButton } from '@astrojs/starlight/components'; +``` + +## 用法 + +使用 `<LinkBut​​ton>` 组件,以在视觉上展示独特的号召性用语链接。 +链接按钮可用于将用户引导至紧密关联或可操作的部分,并且通常在登陆页面上使用。 + +`<LinkButton>` 需要 [`href`](#href) 属性。 +可选部分有,使用 [`variant`](#variant) 属性来自定义链接按钮的外观,该属性可以设置为 `primary`(默认值)、`secondary` 或 `minimal`。 + +<Preview> + +```mdx +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton href="/zh-cn/getting-started/">开始使用</LinkButton> +<LinkButton href="/zh-cn/reference/configuration/" variant="secondary"> + 配置参考 +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkbutton href="/zh-cn/getting-started/" %}开始使用{% /linkbutton %} + +{% linkbutton href="/zh-cn/reference/configuration/" variant="secondary" %} +配置参考 +{% /linkbutton %} +``` + +</Fragment> + +<Fragment slot="preview"> + <LinkButton href="/zh-cn/getting-started/">开始使用</LinkButton> + <LinkButton href="/zh-cn/reference/configuration/" variant="secondary"> + 配置参考 + </LinkButton> +</Fragment> + +</Preview> + +### 向链接按钮添加图标 + +使用设置为 [Starlight 内置图标之一](/zh-cn/reference/icons/#所有图标) 名称的 [`icon`](#icon) 属性,以在链接按钮中包含图标。 + +可通过设置 [`iconPlacement`](#iconplacement) 属性为 `start`(默认为 `end`)来将图标放置在文本之前。 + +<Preview> + +```mdx {6-7} +import { LinkButton } from '@astrojs/starlight/components'; + +<LinkButton + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" +> + 有关内容:Astro +</LinkButton> +``` + +<Fragment slot="markdoc"> + +```markdoc {4-5} +{% linkbutton + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" %} +有关内容:Astro +{% /linkbutton %} +``` + +</Fragment> + +<LinkButton + slot="preview" + href="https://docs.astro.build" + variant="secondary" + icon="external" + iconPlacement="start" +> + 有关内容:Astro +</LinkButton> + +</Preview> + +## `<LinkButton>` 的属性 + +**实现:** [`LinkButton.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkButton.astro) + +`<LinkBut​​ton>` 组件接受以下属性以及任何 [其他 `<a>` 属性](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/a): + +### `href` + +**必要属性** +**类型:** `string` + +链接按钮指向的 URL。 + +### `variant` + +**类型:** `'primary' | 'secondary' | 'minimal'` +**默认值:** `'primary'` + +链接按钮的外观。 +将链接设置为 `primary` 用于显示主题强调色的号召性用语链接;设置为 `secondary` 用于显示不太显眼的链接;设置为 `minimal` 用于显示最低优先级的链接。 + +### `icon` + +**类型:** `string` + +链接按钮可以包含一个 `icon` 属性,该属性应设置为 [Starlight 的内置图标之一](/zh-cn/reference/icons/#所有图标) 的名称。 + +### `iconPlacement` + +**类型:** `'start' | 'end'` +**默认值:** `'end'` + +决定了图标相对于链接按钮文本的位置。 diff --git a/docs/src/content/docs/zh-cn/components/link-cards.mdx b/docs/src/content/docs/zh-cn/components/link-cards.mdx new file mode 100644 index 00000000000..3c3b8bc29c3 --- /dev/null +++ b/docs/src/content/docs/zh-cn/components/link-cards.mdx @@ -0,0 +1,125 @@ +--- +title: 链接卡片 +description: 了解如何在 Starlight 中将链接突出显示为卡片。 +sidebar: + order: 3 +--- + +import { LinkCard } from '@astrojs/starlight/components'; + +要突出显示不同页面的链接,请使用 `<LinkCard>` 组件。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<LinkCard + slot="preview" + title="自定义 Starlight" + description="学习如何通过自定义样式、字体等使你的 Starlight 网站变得与众不同。" + href="/zh-cn/guides/customization/" +/> + +</Preview> + +## 导入 + +```tsx +import { LinkCard } from '@astrojs/starlight/components'; +``` + +## 用法 + +使用 `<LinkCard>` 组件来突出显示链接。 +每个 `<LinkCard>` 都需要一个 [`title`](#title) 和一个 [`href`](#href) 属性。 + +<Preview> + +```mdx +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard title="Markdown 创作" href="/zh-cn/guides/authoring-content/" /> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% linkcard title="Markdown 创作" href="/zh-cn/guides/authoring-content/" /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="Markdown 创作" + href="/zh-cn/guides/authoring-content/" +/> + +</Preview> + +### 添加链接描述 + +使用 [`description`](#description) 属性向链接卡片添加一个简短的描述。 + +<Preview> + +```mdx {6} +import { LinkCard } from '@astrojs/starlight/components'; + +<LinkCard + title="国际化" + href="/zh-cn/guides/i18n/" + description="配置 Starlight 以支持多种语言。" +/> +``` + +<Fragment slot="markdoc"> + +```markdoc {4} +{% linkcard + title="国际化" + href="/zh-cn/guides/i18n/" + description="配置 Starlight 以支持多种语言。" /%} +``` + +</Fragment> + +<LinkCard + slot="preview" + title="国际化" + href="/zh-cn/guides/i18n/" + description="配置 Starlight 以支持多种语言。" +/> + +</Preview> + +### 分组链接卡片 + +当有足够大的空间时,可以使用 [`<CardGrid>`](/zh-cn/components/card-grids/) 组件对链接卡片进行分组,来并排显示多个链接卡片。 +有关示例,请参阅 [“分组链接卡片”](/zh-cn/components/card-grids/#分组链接卡片) 指南。 + +## `<LinkCard>` 的属性 + +**实现:** [`LinkCard.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/LinkCard.astro) + +`<LinkCard>` 组件接受以下属性,以及其他所有的 [`<a>` 元素属性](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/a): + +### `title` + +**必要属性** +**类型:** `string` + +要显示的链接卡片的标题。 + +### `href` + +**必要属性** +**类型:** `string` + +与卡片交互时所链接到的 URL。 + +### `description` + +**类型:** `string` + +一个可选描述,显示在标题的下方。 diff --git a/docs/src/content/docs/zh-cn/components/steps.mdx b/docs/src/content/docs/zh-cn/components/steps.mdx new file mode 100644 index 00000000000..67c68c50e4d --- /dev/null +++ b/docs/src/content/docs/zh-cn/components/steps.mdx @@ -0,0 +1,120 @@ +--- +title: 步骤 +description: 了解如何设计任务编号列表的样式,以在 Starlight 中创建分步指南。 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +要设置任务编号列表的样式以创建分步指南,请使用 `<Steps>` 组件。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Steps slot="preview"> + +1. 创建一个新的 Starlight 项目: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm create astro@latest -- --template starlight + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm create astro --template starlight + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn create astro --template starlight + ``` + + </TabItem> + + </Tabs> + +2. 编写你的第一个文档页面。 + +</Steps> + +</Preview> + +## 导入 + +```tsx +import { Steps } from '@astrojs/starlight/components'; +``` + +## 用法 + +使用 `<Steps>` 组件来设置任务编号列表的样式。 +这对于需要清楚地显示出有关每个步骤的、更复杂的分步指南来说,非常有用。 + +用 `<Steps>` 将标准的 Markdown 有序列表包裹起来。 +所有常用的 Markdown 语法都适用于 `<Steps>`。 + +<Preview> + +````mdx +import { Steps } from '@astrojs/starlight/components'; + +<Steps> + +1. 将组件导入到 MDX 文件中: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. 用 `<Steps>` 将你的有序列表包裹起来。 + +</Steps> +```` + +<Fragment slot="markdoc"> + +````markdoc +{% steps %} + +1. 将组件导入到 MDX 文件中: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. 用 `<Steps>` 将你的有序列表包裹起来。 + +{% /steps %} +```` + +</Fragment> + +<Steps slot="preview"> + +1. 将组件导入到 MDX 文件中: + + ```js + import { Steps } from '@astrojs/starlight/components'; + ``` + +2. 用 `<Steps>` 将你的有序列表包裹起来。 + +</Steps> + +</Preview> + +## `<Steps>` 的属性 + +**实现:** [`Steps.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Steps.astro) + +`<Steps>` 组件不接受任何 props。 diff --git a/docs/src/content/docs/zh-cn/components/tabs.mdx b/docs/src/content/docs/zh-cn/components/tabs.mdx new file mode 100644 index 00000000000..05663f89c2f --- /dev/null +++ b/docs/src/content/docs/zh-cn/components/tabs.mdx @@ -0,0 +1,221 @@ +--- +title: 选项卡 +description: 了解如何在 Starlight 中创建选项卡式的界面以对等效信息进行分组。 +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +要创建选项卡式界面,请使用 `<Tabs>` 和 `<TabItem>` 组件。 +选项卡对于给等效信息进行分组非常有用,用户只需查看多个选项之一即可。 + +import Preview from '~/components/component-preview.astro'; + +<Preview> + +<Tabs slot="preview"> + <TabItem label="恒星">天狼星,织女星,参宿四</TabItem> + <TabItem label="卫星">木卫一,木卫二,木卫三</TabItem> +</Tabs> + +</Preview> + +## 导入 + +```tsx +import { Tabs, TabItem } from '@astrojs/starlight/components'; +``` + +## 用法 + +使用 `<Tabs>` 和 `<TabItem>` 组件以显示选项卡式的界面。 +每个 `<TabItem>` 必须有一个 [`label`](#label) 来展示给用户。 + +<Preview> + +```mdx +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="恒星">天狼星,织女星,参宿四</TabItem> + <TabItem label="卫星">木卫一,木卫二,木卫三</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc +{% tabs %} +{% tabitem label="恒星" %} +天狼星,织女星,参宿四 +{% /tabitem %} + +{% tabitem label="卫星" %} +木卫一,木卫二,木卫三 +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="恒星">天狼星,织女星,参宿四</TabItem> + <TabItem label="卫星">木卫一,木卫二,木卫三</TabItem> +</Tabs> + +</Preview> + +### 同步选项卡 + +通过添加 [`syncKey`](#synckey) 属性来保持多个选项卡组之间的同步。 + +页面上具有相同 `syncKey` 值的所有 `<Tabs>` 将显示相同的活动标签。 +这允许你的读者只需选择一次(例如选择他们的操作系统或包管理器),就可以看到他们的选择在页面导航中保持一致。 + +要同步相关选项卡,请向每个 `<Tabs>` 组件添加相同的 `syncKey` 属性,并确保它们都使用相同的 `<TabItem>` labels 属性: + +<Preview> + +```mdx 'syncKey="星座"' +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +_一些恒星:_ + +<Tabs syncKey="星座"> + <TabItem label="猎户座">参宿五,参宿七,参宿四</TabItem> + <TabItem label="双子座">北河三,北河二 A,北河二 B</TabItem> +</Tabs> + +_一些系外行星:_ + +<Tabs syncKey="星座"> + <TabItem label="猎户座">HD 34445 b,格利泽 179b,Wasp-82 b</TabItem> + <TabItem label="双子座">北河三 b,HAT-P-24b,HD 50554 b</TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc 'syncKey="星座"' +_一些恒星:_ + +{% tabs syncKey="星座" %} +{% tabitem label="猎户座" %} +参宿五,参宿七,参宿四 +{% /tabitem %} + +{% tabitem label="双子座" %} +北河三,北河二 A,北河二 B +{% /tabitem %} +{% /tabs %} + +_一些系外行星:_ + +{% tabs syncKey="星座" %} +{% tabitem label="猎户座" %} +HD 34445 b,格利泽 179b,Wasp-82 b +{% /tabitem %} + +{% tabitem label="双子座" %} +北河三 b,HAT-P-24b,HD 50554 b +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Fragment slot="preview"> + +_一些恒星:_ + +<Tabs syncKey="星座"> + <TabItem label="猎户座">参宿五,参宿七,参宿四</TabItem> + <TabItem label="双子座">北河三,北河二 A,北河二 B</TabItem> +</Tabs> + +_一些系外行星:_ + +<Tabs syncKey="星座"> + <TabItem label="猎户座">HD 34445 b,格利泽 179b,Wasp-82 b</TabItem> + <TabItem label="双子座">北河三 b,HAT-P-24b,HD 50554 b</TabItem> +</Tabs> + +</Fragment> + +</Preview> + +### 为选项卡添加图标 + +在选项卡组件中,添加 [`icon`](#icon) 属性并将其设置为 [Starlight 内置图标之一](/zh-cn/reference/icons/#所有图标) 来为选项卡添加图标。 + +<Preview> + +```mdx /icon="\w+"/ +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +<Tabs> + <TabItem label="恒星" icon="star"> + 天狼星,织女星,参宿四 + </TabItem> + <TabItem label="卫星" icon="moon"> + 木卫一,木卫二,木卫三 + </TabItem> +</Tabs> +``` + +<Fragment slot="markdoc"> + +```markdoc /icon="\w+"/ +{% tabs %} +{% tabitem label="恒星" icon="star" %} +天狼星,织女星,参宿四 +{% /tabitem %} + +{% tabitem label="卫星" icon="moon" %} +木卫一,木卫二,木卫三 +{% /tabitem %} +{% /tabs %} +``` + +</Fragment> + +<Tabs slot="preview"> + <TabItem label="恒星" icon="star"> + 天狼星,织女星,参宿四 + </TabItem> + <TabItem label="卫星" icon="moon"> + 木卫一,木卫二,木卫三 + </TabItem> +</Tabs> + +</Preview> + +## `<Tabs>` 的属性 + +**实现:** [`Tabs.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Tabs.astro) + +`<Tabs>` 组件将多个 `<TabItem>` 组件组合在一起并接受以下属性: + +### `syncKey` + +**类型:** `string` + +一个用于使多个选项卡组在多个页面之间保持同步的键。 + +## `<TabItem>` 的属性 + +**实现:** [`TabItem.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/TabItem.astro) + +一组选项卡(tabs)由选项卡项(tab items)组成,每个选项卡项都具有以下属性: + +### `label` + +**必要属性** +**类型:** `string` + +选项卡项必须包含一个 `label` 属性,该属性决定了将在选项卡项中显示的文本。 + +### `icon` + +**类型:** `string` + +每个选项卡项都可以包含一个 `icon` 属性,该属性设置为 [Starlight 的内置图标之一](/zh-cn/reference/icons/#所有图标) 的名称,以在标签旁边显示图标。 diff --git a/docs/src/content/docs/zh-cn/components/using-components.mdx b/docs/src/content/docs/zh-cn/components/using-components.mdx new file mode 100644 index 00000000000..7aeacfc010b --- /dev/null +++ b/docs/src/content/docs/zh-cn/components/using-components.mdx @@ -0,0 +1,94 @@ +--- +title: 使用组件 +description: 通过 Starlight 使用 MDX 和 Markdoc 中的组件 +sidebar: + order: 1 +--- + +组件能让你更轻松、更连贯地复用部分 UI 或者样式。 +示例可能包括链接卡片或嵌入 YouTube。 +Starlight 支持使用 [MDX](https://mdxjs.com/) 和 [Markdoc](https://markdoc.dev/) 文件中的组件,并提供了一些常用组件供你使用。 + +[在 Astro 文档中了解有关构建组件的更多信息](https://docs.astro.build/zh-cn/basics/astro-components/)。 + +## 在 MDX 中使用组件 + +你可以通过将组件导入 MDX 文件然后将其渲染为 JSX 标签来使用该组件。 +这些组件看起来像 HTML 标签,但是以 `import` 语句中的大写字母开头,并与之名称相匹配: + +```mdx +--- +# src/content/docs/example.mdx +title: 欢迎来到我的文档 +--- + +import { Icon } from '@astrojs/starlight/components'; +import CustomCard from '../../components/CustomCard.astro'; + +<Icon name="open-book" /> + +<CustomCard>组件还可以包含 **嵌套内容**。</CustomCard> +``` + +由于 Starlight 由 Astro 提供支持,因此你可以在 MDX 文件中添加由 [受支持的 UI 框架(React、Preact、Svelte、Vue、Solid 和 Alpine)](https://docs.astro.build/zh-cn/guides/framework-components/) 构建的组件。 +在 Astro 文档中了解有关 [在 MDX 中使用组件](https://docs.astro.build/zh-cn/guides/integrations-guide/mdx/#在-mdx-中使用组件) 的更多信息。 + +## 在 Markdoc 中使用组件 + +跟随我们的 [Markdoc 设置指南](/zh-cn/guides/authoring-content/#markdoc) 来添加支持以在 Markdoc 中创作内容。 + +使用 Starlight 的 Markdoc 预设,你可以将 Starlight 的内置组件与 Markdoc 的 `{% %}` 标签语法结合使用。 +与 MDX 不同的是,Markdoc 中的组件不需要导入。 +以下示例为,在 Markdoc 文件中渲染 Starlight 的 [卡片组件](/zh-cn/components/cards/): + +```markdoc +--- +# src/content/docs/example.mdoc +title: 欢迎来到我的文档 +--- + +{% card title="星星" icon="star" %} +天狼星, 织女星, 参宿四 +{% /card %} +``` + +有关如何使用 Markdoc 文件中的组件的更多信息,请参阅 [Astro Markdoc 集成文档](https://docs.astro.build/zh-cn/guides/integrations-guide/markdoc/#渲染组件)。 + +## 内置组件 + +Starlight 为常见文档用例提供内置组件。 +这些组件可从 MDX 文件中的 `@astrojs/starlight/components` 包以及 Markdoc 文件中的 [Starlight Markdoc 预设](/zh-cn/guides/authoring-content/#markdoc) 中获取。 + +请参阅侧边栏以获取可用组件的列表以及使用方式。 + +## 和 Starlight 样式的兼容性 + +Starlight 将默认样式应用于 Markdown 内容,例如,在元素之间添加边距。 +如果这些样式与你的组件外观存在冲突,请在组件上设置 `not-content` 类来禁用它们。 + +```astro 'class="not-content"' +--- +// src/components/Example.astro +--- + +<div class="not-content"> + <p>不受 Starlight 默认内容样式的影响。</p> +</div> +``` + +## 组件 props + +使用 `astro/types` 中的 [`ComponentProps`](https://docs.astro.build/zh-cn/guides/typescript/#componentprops-类型) 类型来引用组件接受的 `Props`,即使它们不是由组件本身导出的。 +这在包装或扩展现有组件时非常有用。 + +以下示例为,使用 `ComponentProps` 获取 Starlight 内置 `Badge` 组件接受的 props 类型: + +```astro +--- +// src/components/Example.astro +import type { ComponentProps } from 'astro/types'; +import { Badge } from '@astrojs/starlight/components'; + +type BadgeProps = ComponentProps<typeof Badge>; +--- +``` diff --git a/docs/src/content/docs/zh/environmental-impact.md b/docs/src/content/docs/zh-cn/environmental-impact.md similarity index 82% rename from docs/src/content/docs/zh/environmental-impact.md rename to docs/src/content/docs/zh-cn/environmental-impact.md index 6576ad6aeba..ffa5636782b 100644 --- a/docs/src/content/docs/zh/environmental-impact.md +++ b/docs/src/content/docs/zh-cn/environmental-impact.md @@ -7,7 +7,7 @@ description: 了解 Starlight 如何帮助你构建更环保的文档站点并 计算网站生态影响的因素很多,但本指南包含了一些减少文档站点环境足迹的技巧。 好消息是,选择 Starlight 是一个很好的开始。 -根据网站碳计算器的数据,本站点[比 99% 的网页更环保][sl-carbon],每个页面访问产生 0.01g 的 CO₂。 +根据网站碳计算器的数据,本站点[比 98% 的网页更环保][sl-carbon],每个页面访问产生 0.01g 的 CO₂。 ## 页面大小 @@ -89,31 +89,37 @@ Cache-Control: public, max-age=604800, immutable 好奇和其他文档框架相比如何? 下面使用 [Website Carbon Calculator][wcc] 的测试比较了使用不同工具构建的类似页面。 -| 框架 | 每页访问量产生 CO₂ | -| --------------------------- | ------------------ | -| [Starlight][sl-carbon] | 0.01g | -| [VitePress][vp-carbon] | 0.05g | -| [Docus][dc-carbon] | 0.05g | -| [Sphinx][sx-carbon] | 0.07g | -| [MkDocs][mk-carbon] | 0.10g | -| [Nextra][nx-carbon] | 0.11g | -| [docsify][dy-carbon] | 0.11g | -| [Docusaurus][ds-carbon] | 0.24g | -| [Read the Docs][rtd-carbon] | 0.24g | -| [GitBook][gb-carbon] | 0.71g | - -<small>数据收集于 2023 年 5 月 14 日。点击链接查看最新数据。</small> +| 框架 | 每页访问量产生的 CO₂ | 评级 | +| --------------------------- | -------------------- | :--: | +| [Starlight][sl-carbon] | 0.01g | A+ | +| [Read the Docs][rtd-carbon] | 0.07g | A+ | +| [Sphinx][sx-carbon] | 0.07g | A+ | +| [VitePress][vp-carbon] | 0.07g | A+ | +| [Docus][dc-carbon] | 0.10g | A | +| [docsify][dy-carbon] | 0.11g | A | +| [mdBook][md-carbon] | 0.13g | A | +| [MkDocs][mk-carbon] | 0.15g | A | +| [Fumadocs][fs-carbon] | 0.16g | A | +| [Nextra][nx-carbon] | 0.16g | A | +| [Docusaurus][ds-carbon] | 0.25g | B | +| [Mintlify][mt-carbon] | 0.99g | F | +| [GitBook][gb-carbon] | 1.19g | F | + +<small>数据收集于 2025 年 4 月 12 日。点击链接查看最新数据。</small> [sl-carbon]: https://www.websitecarbon.com/website/starlight-astro-build-getting-started/ [vp-carbon]: https://www.websitecarbon.com/website/vitepress-dev-guide-what-is-vitepress/ [dc-carbon]: https://www.websitecarbon.com/website/docus-dev-introduction-getting-started/ [sx-carbon]: https://www.websitecarbon.com/website/sphinx-doc-org-en-master-usage-quickstart-html/ [mk-carbon]: https://www.websitecarbon.com/website/mkdocs-org-getting-started/ +[md-carbon]: https://www.websitecarbon.com/website/rust-lang-github-io-mdbook/ [nx-carbon]: https://www.websitecarbon.com/website/nextra-site-docs-docs-theme-start/ +[fs-carbon]: https://www.websitecarbon.com/website/fumadocs-vercel-app-docs-ui/ [dy-carbon]: https://www.websitecarbon.com/website/docsify-js-org/ [ds-carbon]: https://www.websitecarbon.com/website/docusaurus-io-docs/ [rtd-carbon]: https://www.websitecarbon.com/website/docs-readthedocs-io-en-stable-index-html/ [gb-carbon]: https://www.websitecarbon.com/website/docs-gitbook-com/ +[mt-carbon]: https://www.websitecarbon.com/website/mintlify-com-docs-quickstart/ ## 更多资源 @@ -135,6 +141,6 @@ Cache-Control: public, max-age=604800, immutable [sf]: https://www.sciencefocus.com/science/what-is-the-carbon-footprint-of-the-internet/ [bbc]: https://www.bbc.com/future/article/20200305-why-your-internet-habits-are-not-as-clean-as-you-think [http]: https://httparchive.org/reports/state-of-the-web -[assets]: https://docs.astro.build/zh-cn/guides/assets/ +[assets]: https://docs.astro.build/zh-cn/guides/images/ [islands]: https://docs.astro.build/zh-cn/concepts/islands/ [wcc]: https://www.websitecarbon.com/ diff --git a/docs/src/content/docs/zh-cn/getting-started.mdx b/docs/src/content/docs/zh-cn/getting-started.mdx new file mode 100644 index 00000000000..fc2bd13354d --- /dev/null +++ b/docs/src/content/docs/zh-cn/getting-started.mdx @@ -0,0 +1,141 @@ +--- +title: 开始使用 +description: 了解如何使用 Astro 的 Starlight 开始构建下一个文档站点。 +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +Starlight 是一个基于 [Astro](https://astro.build) 框架构建的全功能文档主题。 +这个指南将帮助你开始一个新项目。 +查看[手动配置](/zh-cn/manual-setup/)以将 Starlight 添加到现有的 Astro 项目中。 + +## 快速入门 + +### 创建一个新项目 + +在你的终端中运行以下命令来创建一个新的 Astro + Starlight 项目: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight +``` + +</TabItem> +</Tabs> + +这将创建一个新的[项目目录](/zh-cn/guides/project-structure/),其中包含你网站所需的所有文件和配置。 + +:::tip[查看实际效果] +在浏览器中尝试 Starlight: +[在 StackBlitz 上打开模板](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics)。 +::: + +### 启动开发服务器 + +在本地工作时,[Astro 的开发服务器](https://docs.astro.build/zh-cn/reference/cli-reference/#astro-dev)使你能预览你的工作,并在你进行更改时自动刷新你的浏览器。 + +在你的项目目录中,运行以下命令来启动开发服务器: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm run dev +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm dev +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dev +``` + +</TabItem> +</Tabs> + +这将在你的终端上记录一个包含本地预览网址的消息。 +打开这个网址开始浏览你的网站。 + +### 添加内容 + +Starlight 已经准备好让你添加新内容或导入你现有的文件! + +通过在 `src/content/docs/` 目录中创建 Markdown 文件来为你的网站添加新页面。 + +在 [“页面”](/zh-cn/guides/pages/) 指南中了解有关基于文件的路由和对 MDX 和 Markdoc 文件的支持的更多信息。 + +### 下一步 + +- **配置:** 在[自定义 Starlight](/zh-cn/guides/customization/)中了解常见选项。 +- **导航:** 使用[侧边栏导航](/zh-cn/guides/sidebar/)指南设置你的侧边栏。 +- **组件:** 在[组件](/zh-cn/components/using-components/)指南中发现内置的卡片、标签页等更多内容。 +- **部署:** 使用 Astro 文档中的[部署你的 Astro 站点](https://docs.astro.build/zh-cn/guides/deploy/)指南发布你的站点。 + +## 更新 Starlight + +:::tip[提示] +由于 Starlight 是 beta 软件,所以会经常更新和改进。 + +请务必定期更新 Starlight! +::: + +Starlight 是一个 Astro 集成。你可以通过在终端中运行以下命令来更新它和其他 Astro 软件包: + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npx @astrojs/upgrade +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm dlx @astrojs/upgrade +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn dlx @astrojs/upgrade +``` + +</TabItem> +</Tabs> + +查阅 [Starlight 更新日志](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md)中每个版本的变更列表。 + +## Starlight 故障排除 + +本站点的参考部分提供了 Starlight [项目配置](/zh-cn/reference/configuration/)和[单个页面 frontmatter 配置](/zh-cn/reference/frontmatter/)信息。使用这些页面来确保你的 Starlight 网站已正确配置和运行。 +请参阅侧边栏中的指南列表,以获取有关添加内容和自定义 Starlight 网站的帮助。 + +如果你在这些文档中找不到答案,请访问[完整的 Astro 文档](https://docs.astro.build/zh-cn/) 以获取完整的 Astro 文档。 +你的问题可能是通过了解 Starlight 主题下 Astro 的工作原理来解决的。 + +你也可以检查任何已知的 [GitHub 上的 Starlight issues](https://github.com/withastro/starlight/issues),并在 [Astro Discord](https://astro.build/chat/) 上从我们活跃的、友好的社区中获得帮助!在我们的 `#support` 论坛中发布带有 “starlight” 标签的问题,或者访问我们专门的 `#starlight` 频道来讨论当前的开发和更多内容! diff --git a/docs/src/content/docs/zh-cn/guides/authoring-content.mdx b/docs/src/content/docs/zh-cn/guides/authoring-content.mdx new file mode 100644 index 00000000000..7efd5505599 --- /dev/null +++ b/docs/src/content/docs/zh-cn/guides/authoring-content.mdx @@ -0,0 +1,669 @@ +--- +title: 在 Markdown 中创作内容 +description: Starlight 支持的 Markdown 语法概述 +--- + +Starlight 支持在 `.md` 文件中使用完整的 [Markdown](https://daringfireball.net/projects/markdown/) 语法,以及使用 [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) 定义metadata 元数据,例如标题和描述。 + +如果使用这些文件格式,请务必检查 [MDX 文档](https://mdxjs.com/docs/what-is-mdx/#markdown) 或 [Markdoc 文档](https://markdoc.dev/docs/syntax),因为 Markdown 的支持和用法可能会有所不同。 + +## Frontmatter + +你可以通过设置 frontmatter 中的值来自定义 Starlight 里每个页面。 +Frontmatter 是你的文件顶部在 `---` 中间的部分。 + +```md title="src/content/docs/example.md" +--- +title: 我的页面标题 +--- + +页面内容在第二个 `---` 后面。 +``` + +每个页面都必须包含一个 `title`。 +查看 [frontmatter 参考](/zh-cn/reference/frontmatter/) 了解所有可用字段以及如何添加自定义字段。 + +## 内联样式 + +文本可以是**粗体**,_斜体_,或~~删除线~~。 + +```md +文本可以是**粗体**,_斜体_,或~~删除线~~。 +``` + +你可以 [链接到另一个页面](/zh-cn/getting-started/)。 + +```md +你可以 [链接到另一个页面](/zh-cn/getting-started/)。 +``` + +你可以使用反引号高亮 `内联代码`。 + +```md +你可以使用反引号高亮 `内联代码`。 +``` + +## 图片 + +Starlight 中的图片使用 [Astro 的内置优化资源支持](https://docs.astro.build/zh-cn/guides/images/)。 + +Markdown 和 MDX 支持用于显示图片的 Markdown 语法,其中包括屏幕阅读器和辅助技术的 alt-text。 + +![一个星球和星星的插图,上面写着“astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) + +```md +![一个星球和星星的插图,上面写着“astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) +``` + +对于在项目中本地存储的图片,也支持图片的相对路径。 + +```md +// src/content/docs/page-1.md + +![A rocketship in space](../../assets/images/rocket.svg) +``` + +## 标题 + +你可以使用标题来组织内容。Markdown 中的标题由行首的 `#` 数量来表示。 + +### 如何在 Starlight 中组织页面内容 + +Starlight 配置为自动使用页面标题作为一级标题,并将在每个页面的目录中包含一个“概述”标题。我们建议每个页面都从常规段落文本内容开始,并从 `<h2>` 开始使用页面标题: + +```md +--- +title: Markdown 指南 +description: 如何在 Starlight 中使用 Markdown +--- + +本页面描述了如何在 Starlight 中使用 Markdown。 + +## 内联样式 + +## 标题 +``` + +### 自动生成标题锚点链接 + +使用 Markdown 中的标题将自动为你提供锚点链接,以便你可以直接链接到页面的某些部分: + +```md +--- +title: 我的页面内容 +description: 如何使用 Starlight 内置的锚点链接 +--- + +## 介绍 + +我可以链接到同一页下面的[结论](#结论)。 + +## 结论 + +`https://my-site.com/page1/#introduction` 直接导航到我的介绍。 +``` + +二级标题 (`<h2>`) 和 三级标题 (`<h3>`) 将自动出现在页面目录中。 + +在 [Astro 文档](https://docs.astro.build/zh-cn/guides/markdown-content/#标题-id)中了解 Astro 是如何处理标题 `id` 的。 + +## 旁白 + +旁白(也称为“警告”或“标注”)对于在页面的主要内容旁边显示辅助信息很有用。 + +Starlight 提供了一个自定义的 Markdown 语法来渲染旁白。旁白块使用一对三个冒号 `:::` 来包裹你的内容,并且可以是 `note`,`tip`,`caution` 或 `danger` 类型。 + +你可以在旁白中嵌套任何其他 Markdown 内容类型,但旁白最适合用于简短而简洁的内容块。 + +### Note 旁白 + +:::note +Starlight 是一个使用 [Astro](https://astro.build/) 构建的文档网站工具包。 你可以使用此命令开始: + +```sh +npm create astro@latest -- --template starlight +``` + +::: + +````md +:::note +Starlight 是一个使用 [Astro](https://astro.build/) 构建的文档网站工具包。 你可以使用此命令开始: + +```sh +npm create astro@latest -- --template starlight +``` + +::: +```` + +### 自定义旁白标题 + +你可以在旁白类型后面的方括号中指定旁白的自定义标题,例如 `:::tip[你知道吗?]`。 + +:::tip[你知道吗?] +Astro 帮助你使用 [“群岛架构”](https://docs.astro.build/zh-cn/concepts/islands/) 构建更快的网站。 +::: + +```md +:::tip[你知道吗?] +Astro 帮助你使用 [“群岛架构”](https://docs.astro.build/zh-cn/concepts/islands/) 构建更快的网站。 +::: +``` + +### 更多旁白类型 + +Caution 和 danger 旁白有助于吸引用户注意可能绊倒他们的细节。 如果你发现自己经常使用这些,这也可能表明你正在记录的内容可以从重新设计中受益。 + +:::caution +如果你不确定是否想要一个很棒的文档网站,请在使用 [Starlight](/zh-cn/) 之前三思。 +::: + +:::danger +借助有用的 Starlight 功能,你的用户可能会提高工作效率,并发现你的产品更易于使用。 + +- 清晰的导航 +- 用户可配置的颜色主题 +- [i18n 支持](/zh-cn/guides/i18n/) + +::: + +```md +:::caution +如果你不确定是否想要一个很棒的文档网站,请在使用 [Starlight](/zh-cn/) 之前三思。 +::: + +:::danger +借助有用的 Starlight 功能,你的用户可能会提高工作效率,并发现你的产品更易于使用。 + +- 清晰的导航 +- 用户可配置的颜色主题 +- [i18n 支持](/zh-cn/guides/i18n/) + +::: +``` + +## 块引用 + +> 这是块引用,通常在引用其他人或文档时使用。 +> +> 块引用以每行开头的 `>` 表示。 + +```md +> 这是块引用,通常在引用其他人或文档时使用。 +> +> 块引用以每行开头的 `>` 表示。 +``` + +## 代码块 + +代码块由三个反引号 <code>```</code> 开始和结束。你可以在开头的反引号后指定代码块的编程语言。 + +```js +// 带有语法高亮的 JavaScript 代码。 +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` + +````md +```js +// 带有语法高亮的 JavaScript 代码。 +var fun = function lang(l) { + dateformat.i18n = require('./lang/' + l); + return true; +}; +``` +```` + +### Expressive Code 功能 + +Starlight 使用 [Expressive Code](https://expressive-code.com/) 来扩展代码块的格式化功能。 +Expressive Code 的文本标记和窗口外框插件是默认启用的。 +可以使用 Starlight 的 [`expressiveCode` 配置选项](/zh-cn/reference/configuration/#expressivecode) 来配置代码块的渲染。 + +#### 文本标记 + +你可以通过在代码块的起始行上使用 [Expressive Code 文本标记 (text markers)](https://expressive-code.com/key-features/text-markers/) 在代码块里突出显示特定行或代码块的一部分。 +使用大括号 (`{ }`) 来突出显示整行,使用引号来突出显示文本字符串。 + +有三种突出显示样式:中性用于突出显示代码,绿色用于表示插入的代码,红色用于表示删除的代码。 +字符串和整行都可以使用默认的标记,也可以与 `ins=` 和 `del=` 结合使用产生所需的突出显示效果。 + +Expressive Code 提供了几种自定义你的代码示例视觉外观的选项。 +其中许多可以组合使用,以获得极具说明性的代码示例。 +请探索 [Expressive Code 文档](https://expressive-code.com/key-features/text-markers/#configuration) 以了解众多可用的设置项。 +下面显示了一些最常见的示例: + +- [使用 `{ }` 标记标出整行和行范围](https://expressive-code.com/key-features/text-markers/#marking-full-lines--line-ranges): + + ```js {2-3} + function demo() { + // 这一行 (#2) 以及下一行被高亮显示 + return '这是本代码段的第 3 行'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js {2-3} + function demo() { + // 这一行 (#2) 以及下一行被高亮显示 + return '这是本代码段的第 3 行'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````md + ```js {% meta="{2-3}" %} + function demo() { + // 这一行 (#2) 以及下一行被高亮显示 + return '这是本代码段的第 3 行'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [使用 `" "` 标记或正则表达式标出文本字符串](https://expressive-code.com/key-features/text-markers/#marking-individual-text-inside-lines): + + ```js "单个词组" /甚.*表达式/ + // 单个词组也能被高亮显示 + function demo() { + return '甚至支持使用正则表达式'; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "单个词组" /甚.*表达式/ + // 单个词组也能被高亮显示 + function demo() { + return '甚至支持使用正则表达式'; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'单个词组' /甚.*表达式/" %} + // 单个词组也能被高亮显示 + function demo() { + return '甚至支持使用正则表达式'; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [使用 `ins` 或 `del` 来标记行或文本为插入或删除](https://expressive-code.com/key-features/text-markers/#selecting-inline-marker-types-mark-ins-del): + + ```js "return true;" ins="插入" del="删除" + function demo() { + console.log('这是插入以及删除类型的标记'); + // 返回语句使用默认标记类型 + return true; + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js "return true;" ins="插入" del="删除" + function demo() { + console.log('这是插入以及删除类型的标记'); + // 返回语句使用默认标记类型 + return true; + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```js {% meta="'return true;' ins='插入' del='删除'" %} + function demo() { + console.log('这是插入以及删除类型的标记'); + // 返回语句使用默认标记类型 + return true; + } + ``` + ```` + + </TabItem> + + </Tabs> + +- [混合语法高亮和类 `diff` 语法](https://expressive-code.com/key-features/text-markers/#combining-syntax-highlighting-with-diff-like-syntax): + + ```diff lang="js" + function thisIsJavaScript() { + // 这整个代码块都会被作为 JavaScript 高亮 + // 而且我们还可以给它添加 diff 标记! + - console.log('旧的不去') + + console.log('新的不来') + } + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```diff lang="js" + function thisIsJavaScript() { + // 这整个代码块都会被作为 JavaScript 高亮 + // 而且我们还可以给它添加 diff 标记! + - console.log('旧的不去') + + console.log('新的不来') + } + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```diff {% meta="lang='js'" %} + function thisIsJavaScript() { + // 这整个代码块都会被作为 JavaScript 高亮 + // 而且我们还可以给它添加 diff 标记! + - console.log('旧的不去') + + console.log('新的不来') + } + ``` + ```` + + </TabItem> + + </Tabs> + +#### 边框和标题 + +代码块可以在类似窗口的框架中呈现。 +默认情况下 shell 脚本语言(例如 `bash` 或 `sh`)会使用一个看起来像终端窗口的边框。 +其他语言在提供了标题的情况下会在一个看起来像代码编辑器的边框中显示。 + +一个代码块的可选标题可以通过在代码块的开头反引号后面添加一个 `title="..."` 属性来设置,或者通过在代码的前几行中添加一个文件名注释来设置。 + +- [通过注释添加一个文件名标签](https://expressive-code.com/key-features/frames/#code-editor-frames) + + ```js + // my-test-file.js + console.log('Hello World!'); + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```js + // my-test-file.js + console.log('Hello World!'); + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````md + ```js + // my-test-file.js + console.log('Hello World!'); + ``` + ```` + + </TabItem> + + </Tabs> + +- [给终端窗口添加一个标题](https://expressive-code.com/key-features/frames/#terminal-frames) + + ```bash title="安装依赖…" + npm install + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash title="安装依赖…" + npm install + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% title="安装依赖…" %} + npm install + ``` + ```` + + </TabItem> + + </Tabs> + +- [使用 `frame="none"` 禁用边框](https://expressive-code.com/key-features/frames/#overriding-frame-types) + + ```bash frame="none" + echo "这个代码块即使使用了 bash 语言也不会被显示成终端窗口" + ``` + + <Tabs syncKey="content-type"> + + <TabItem label="Markdown/MDX"> + + ````md + ```bash frame="none" + echo "这个代码块即使使用了 bash 语言也不会被显示成终端窗口" + ``` + ```` + + </TabItem> + + <TabItem label="Markdoc"> + + ````markdoc + ```bash {% frame="none" %} + echo "这个代码块即使使用了 bash 语言也不会被显示成终端窗口" + ``` + ```` + + </TabItem> + + </Tabs> + +## 详细信息 + +详细信息(也称为“手风琴(accordion)”)用于隐藏不立即相关的内容。用户可以点击一个简短的摘要来展开并查看完整内容。 + +在你的 Markdown 内容中使用标准的 HTML [`<details>`](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/details) 和 [`<summary>`](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/summary) 元素来创建一个手风琴小组件。 + +你可以在 `<details>` 元素内嵌套任何其他 Markdown 语法。 + +<details> +<summary>何时何地可以最清楚地看到仙女座?</summary> + +在 11 月份的夜空中,[仙女座](https://zh.wikipedia.org/wiki/仙女座) 在 `+90°` 到 `-40°` 的纬度范围内最为明显。 + +</details> + +```md +<details> +<summary>何时何地可以最清楚地看到仙女座?</summary> + +在 11 月份的夜空中,[仙女座](https://zh.wikipedia.org/wiki/仙女座) 在 `+90°` 到 `-40°` 的纬度范围内最为明显。 + +</details> +``` + +## 其它通用 Markdown 语法 + +Starlight 支持所有其他 Markdown 语法,例如列表和表格。 请参阅 [Markdown 指南的 Markdown 速查表](https://www.markdownguide.org/cheat-sheet/) 以快速了解所有 Markdown 语法元素。 + +## 高级 Markdown 和 MDX 配置 + +Starlight 使用 Astro 的 Markdown 和 MDX 渲染器,该渲染器构建在 remark 和 rehype 之上。 你可以通过在 Astro 配置文件中添加 `remarkPlugins` 或 `rehypePlugins` 来添加对自定义语法和行为的支持。 请参阅 Astro 文档中的 [“Markdown 插件”](https://docs.astro.build/zh-cn/guides/markdown-content/#markdown-插件) 以了解更多信息。 + +## Markdoc + +Starlight 支持使用实验性 [Astro Markdoc 集成](https://docs.astro.build/zh-cn/guides/integrations-guide/markdoc/) 和 Starlight Markdoc 预设在 Markdoc 中创作内容。 + +### 使用 Markdoc 创建新项目 + +使用 Markdoc 的预配置 `create astro` 来启动一个新的 Starlight 项目: + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +<Tabs syncKey="pkg"> +<TabItem label="npm"> + +```sh +npm create astro@latest -- --template starlight/markdoc +``` + +</TabItem> +<TabItem label="pnpm"> + +```sh +pnpm create astro --template starlight/markdoc +``` + +</TabItem> +<TabItem label="Yarn"> + +```sh +yarn create astro --template starlight/markdoc +``` + +</TabItem> +</Tabs> + +### 添加 Markdoc 到现有项目 + +如果你已有一个 Starlight 网站并想要添加 Markdoc,请按照以下步骤操作。 + +<Steps> + +1. 添加 Astro 的 Markdoc 集成: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npx astro add markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm astro add markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn astro add markdoc + ``` + + </TabItem> + + </Tabs> + +2. 安装 Starlight Markdoc 预设: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-markdoc + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-markdoc + ``` + + </TabItem> + + </Tabs> + +3. 在 `markdoc.config.mjs` 创建一个 Markdoc 配置文件并使用 Starlight Markdoc 预设: + + ```js + import { defineMarkdocConfig } from '@astrojs/markdoc/config'; + import starlightMarkdoc from '@astrojs/starlight-markdoc'; + + export default defineMarkdocConfig({ + extends: [starlightMarkdoc()], + }); + ``` + +</Steps> + +要了解有关 Markdoc 语法和功能的更多信息,请参阅 [Markdoc 文档](https://markdoc.dev/docs/syntax) 或 [Astro Markdoc 集成指南](https://docs.astro.build/zh-cn/guides/integrations-guide/markdoc/)。 + +### 配置 Markdoc 预设 + +`starlightMarkdoc()` 预设接受以下配置选项: + +#### `headingLinks` + +**类型:** `boolean` +**默认值:** `true` + +控制是否使用可点击的锚链接渲染标题。 +等同于适用于 Markdown 和 MDX 文件的 [`markdown.headingLinks`](/zh-cn/reference/configuration/#markdown) 选项。 + +```js "headingLinks: false" +export default defineMarkdocConfig({ + // 禁用默认的标题锚点链接支持 + extends: [starlightMarkdoc({ headingLinks: false })], +}); +``` diff --git a/docs/src/content/docs/zh/guides/css-and-tailwind.mdx b/docs/src/content/docs/zh-cn/guides/css-and-tailwind.mdx similarity index 85% rename from docs/src/content/docs/zh/guides/css-and-tailwind.mdx rename to docs/src/content/docs/zh-cn/guides/css-and-tailwind.mdx index 71826b8901e..40b74f0e368 100644 --- a/docs/src/content/docs/zh/guides/css-and-tailwind.mdx +++ b/docs/src/content/docs/zh-cn/guides/css-and-tailwind.mdx @@ -3,12 +3,18 @@ title: CSS & 样式 description: 了解如何使用自定义 CSS 设置你的 Starlight 网站的样式或与 Tailwind CSS 集成。 --- +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + 你可以使用自定义 CSS 设置你的 Starlight 网站的样式或者使用 Starlight Tailwind 插件。 +有一种快速的方法可以更改你的网站的默认样式,请查看 [社区主题](/zh-cn/resources/themes/)。 + ## 自定义 CSS 样式 通过提供额外的 CSS 文件来修改或扩展 Starlight 的默认样式,从而自定义应用于 Starlight 网站的样式。 +<Steps> + 1. 在 `src/` 目录下添加一个 CSS 文件。 例如,你可以设置一个更宽的默认列宽和更大的页面标题文本大小: @@ -22,7 +28,7 @@ description: 了解如何使用自定义 CSS 设置你的 Starlight 网站的样 2. 在 `astro.config.mjs` 中的 `customCss` 数组中添加你的 CSS 文件的路径: - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -32,14 +38,16 @@ description: 了解如何使用自定义 CSS 设置你的 Starlight 网站的样 starlight({ title: 'Docs With Custom CSS', customCss: [ - // 你的自定义 CSS 文件的相对路径 - './src/styles/custom.css', + + // 你的自定义 CSS 文件的相对路径 + + './src/styles/custom.css', ], }), ], }); ``` +</Steps> + 你可以在[ GitHub 上的 `props.css` 文件](https://github.com/withastro/starlight/blob/main/packages/starlight/style/props.css) 中查看 Starlight 使用的所有 CSS 自定义属性,你可以设置这些属性来自定义你的网站。 ## Tailwind CSS @@ -55,11 +63,9 @@ Starlight Tailwind 插件应用了以下配置: ### 使用 Tailwind 创建新项目 -import { Tabs, TabItem } from '@astrojs/starlight/components'; - 使用 `create astro` 创建一个预配置了 Tailwind CSS 的新 Starlight 项目: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh @@ -87,9 +93,11 @@ yarn create astro --template starlight/tailwind 如果你已经有了一个 Starlight 网站,并且想要添加 Tailwind CSS,请按照以下步骤操作。 +<Steps> + 1. 将 Astro 的 Tailwind 集成添加到项目中: - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -119,7 +127,7 @@ yarn create astro --template starlight/tailwind 2. 安装 Starlight Tailwind 插件: - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -132,7 +140,7 @@ yarn create astro --template starlight/tailwind <TabItem label="pnpm"> ```sh - pnpm install @astrojs/starlight-tailwind + pnpm add @astrojs/starlight-tailwind ``` </TabItem> @@ -181,19 +189,21 @@ yarn create astro --template starlight/tailwind }); ``` -5. 将 Starlight Tailwind 插件添加到 `tailwind.config.cjs`: +5. 将 Starlight Tailwind 插件添加到 `tailwind.config.mjs`: ```js ins={2,7} - // tailwind.config.cjs - const starlightPlugin = require('@astrojs/starlight-tailwind'); + // tailwind.config.mjs + import starlightPlugin from '@astrojs/starlight-tailwind'; /** @type {import('tailwindcss').Config} */ - module.exports = { + export default { content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], plugins: [starlightPlugin()], }; ``` +</Steps> + ### 使用 Tailwind 设置 Starlight 的样式 Starlight 将使用你的 [Tailwind 主题配置](https://tailwindcss.com/docs/theme)中的值来设置其 UI。 @@ -206,12 +216,12 @@ Starlight 将使用你的 [Tailwind 主题配置](https://tailwindcss.com/docs/t - `fontFamily.mono` — 用于代码示例 ```js {12,14,18,20} -// tailwind.config.cjs -const starlightPlugin = require('@astrojs/starlight-tailwind'); -const colors = require('tailwindcss/colors'); +// tailwind.config.mjs +import starlightPlugin from '@astrojs/starlight-tailwind'; +import colors from 'tailwindcss/colors'; /** @type {import('tailwindcss').Config} */ -module.exports = { +export default { content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], theme: { extend: { @@ -242,9 +252,11 @@ Starlight 的颜色主题可以通过覆盖其默认的自定义属性来控制 使用下面的滑块来修改 Starlight 的强调色和灰色调色板。暗色和亮色的预览区域将显示结果颜色,整个页面也会更新以预览你的更改。 +使用“对比度级别”选项来指定要满足的 Web 内容无障碍功能指南的[颜色对比度标准](https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast)。 + 当你对你的更改满意时,复制下面的 CSS 或 Tailwind 代码并在你的项目中使用。 -import ThemeDesigner from '../../../../components/theme-designer.astro'; +import ThemeDesigner from '~/components/theme-designer.astro'; <ThemeDesigner labels={{ @@ -257,11 +269,14 @@ import ThemeDesigner from '../../../../components/theme-designer.astro'; default: '默认', random: '随机', }, + contrast: { + label: '对比度级别', + }, editor: { - accentColor: 'Accent', - grayColor: 'Gray', - hue: '颜色', - chroma: '色度', + accentColor: '强调色', + grayColor: '灰色', + hue: '色调', + chroma: '饱和度', pickColor: '选择颜色', }, preview: { diff --git a/docs/src/content/docs/zh/guides/customization.mdx b/docs/src/content/docs/zh-cn/guides/customization.mdx similarity index 75% rename from docs/src/content/docs/zh/guides/customization.mdx rename to docs/src/content/docs/zh-cn/guides/customization.mdx index 3eebca3a148..c358b447b32 100644 --- a/docs/src/content/docs/zh/guides/customization.mdx +++ b/docs/src/content/docs/zh-cn/guides/customization.mdx @@ -3,8 +3,7 @@ title: 自定义 Starlight description: 学习如何通过自定义样式、字体等使你的 Starlight 网站变得与众不同。 --- -import { Tabs, TabItem } from '@astrojs/starlight/components'; -import FileTree from '../../../../components/file-tree.astro'; +import { Tabs, TabItem, FileTree, Steps } from '@astrojs/starlight/components'; Starlight 提供了合理的默认样式和功能,因此你可以快速开始,无需配置即可进行操作。 当你想要开始自定义 Starlight 网站的外观时,本指南可以帮助你。 @@ -13,6 +12,8 @@ Starlight 提供了合理的默认样式和功能,因此你可以快速开始 将自定义 logo 添加到网站标题是将品牌形象添加到 Starlight 网站的快速方法。 +<Steps> + 1. 将你的 logo 图像文件添加到 `src/assets/` 目录: <FileTree> @@ -25,9 +26,9 @@ Starlight 提供了合理的默认样式和功能,因此你可以快速开始 </FileTree> -2. 在 `astro.config.mjs` 中,将 logo 的路径添加到 Starlight 的 [`logo.src`](/zh/reference/configuration/#logo) 选项: +2. 在 `astro.config.mjs` 中,将 logo 的路径添加到 Starlight 的 [`logo.src`](/zh-cn/reference/configuration/#logo) 选项: - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -37,18 +38,20 @@ Starlight 提供了合理的默认样式和功能,因此你可以快速开始 starlight({ title: '带有我的标志的页面', logo: { - src: './src/assets/my-logo.svg', + + src: './src/assets/my-logo.svg', }, }), ], }); ``` +</Steps> + 默认情况下,logo 将显示在网站的标题旁边。 如果你的 logo 图像已经包含了网站标题,你可以通过设置 `replacesTitle` 选项来在视觉上隐藏标题文本。 标题文本仍包含在屏幕阅读器中,以便标题保持可访问性。 -```js +```js {5} starlight({ title: '带有我的 logo 的页面', logo: { @@ -62,6 +65,8 @@ starlight({ 你可以在亮色和暗色模式下显示不同版本的 logo。 +<Steps> + 1. 将每个变体的图像文件添加到 `src/assets/`: <FileTree> @@ -77,21 +82,23 @@ starlight({ 2. 在 `astro.config.mjs` 中,将 logo 变体的路径添加为 `light` 和 `dark` 选项,而不是 `src`: - ```js + ```diff lang="js" starlight({ title: '带有我的标志的页面', logo: { - light: './src/assets/light-logo.svg', - dark: './src/assets/dark-logo.svg', + + light: './src/assets/light-logo.svg', + + dark: './src/assets/dark-logo.svg', }, }), ``` +</Steps> + ## 启用 sitemap Starlight 内置了生成站点地图(sitemap)的支持。通过在 `astro.config.mjs` 中把 `site` 字段设置为你的 URL 来启用站点地图生成: -```js +```js {4} // astro.config.mjs export default defineConfig({ site: 'https://stargazers.club', @@ -99,14 +106,16 @@ export default defineConfig({ }); ``` +在 Astro 文档中,了解如何 [将站点地图链接添加到 `robots.txt`](https://docs.astro.build/zh-cn/guides/integrations-guide/sitemap/#robotstxt-中的站点地图链接)。 + ## 页面布局 默认情况下,Starlight 页面使用带有全局导航侧边栏和显示当前页面标题的目录的布局。 -你可以通过在页面的正文中设置 [`template: splash`](/zh/reference/frontmatter/#template) 来应用更宽的页面布局,而去除侧边栏。 -这对于主页面特别有效,你可以在本站点的[主页](/zh/)上看到它的效果。 +你可以通过在页面的正文中设置 [`template: splash`](/zh-cn/reference/frontmatter/#template) 来应用更宽的页面布局,而去除侧边栏。 +这对于主页面特别有效,你可以在本站点的[主页](/zh-cn/)上看到它的效果。 -```md +```md {5} --- # src/content/docs/index.md @@ -121,10 +130,10 @@ Starlight 在每个页面上显示目录,使读者更容易跳转到他们正 默认情况下,目录中包含 `<h2>` 和 `<h3>` 标题。使用全局 `tableOfContents` 中的 `minHeadingLevel` 和 `maxHeadingLevel` 选项更改要包含的标题级别。通过添加相应的 frontmatter 中的 `tableOfContents` 属性,在单个页面上覆盖这些默认值: -<Tabs> +<Tabs syncKey="config-type"> <TabItem label="Frontmatter"> -```md +```md {4-6} --- # src/content/docs/example.md title: 只在目录中包含 H2 的页面 @@ -137,13 +146,13 @@ tableOfContents: </TabItem> <TabItem label="全局配置"> -```js +```js {7} // astro.config.mjs defineConfig({ integrations: [ starlight({ - title: '', + title: '具有自定义目录配置的文档', tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 2 }, }), ], @@ -155,10 +164,10 @@ defineConfig({ 通过将 `tableOfContents` 选项设置为 `false` 来完全禁用目录: -<Tabs> - <TabItem label=" frontmatter "> +<Tabs syncKey="config-type"> + <TabItem label="Frontmatter "> -```md +```md {4} --- # src/content/docs/example.md title: 没有目录的页面 @@ -169,7 +178,7 @@ tableOfContents: false </TabItem> <TabItem label="全局配置"> -```js +```js {7} // astro.config.mjs defineConfig({ @@ -187,11 +196,17 @@ defineConfig({ ## 社交链接 -Starlight 内置了对通过 Starlight 集成中的 [`social`](/zh/reference/configuration/#social) 选项将链接添加到网站标题的社交媒体帐户的支持。 +Starlight 内置了对通过 Starlight 集成中的 [`social`](/zh-cn/reference/configuration/#social) 选项将链接添加到网站标题的社交媒体账户的支持。 + +`social`数组中的每个条目都必须是具有以下三个属性的对象: + +- `icon`:Starlight [内置的图标](/zh-cn/reference/icons/)之一,例如 `"github"`。 +- `label`:链接的可访问标签,例如 `"GitHub"`。 +- `href`: 链接的 URL,例如 `"https://github.com/withastro/starlight"`。 -目前,支持链接到 Bitbucket、Codeberg、CodePen、Discord、GitHub、GitLab、Gitter、Instagram、LinkedIn、Mastodon、Microsoft Teams、Stack Overflow、Threads、Twitch、Twitter 和 YouTube。如果你需要支持其他服务,请在 GitHub 或 Discord 上告诉我们! +以下示例添加了指向 Astro Discord 和 Starlight GitHub 仓库的链接: -```js +```js {9-16} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -200,10 +215,14 @@ export default defineConfig({ integrations: [ starlight({ title: '带有社交链接的页面', - social: { - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - }, + social: [ + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { + icon: 'github', + label: 'GitHub', + href: 'https://github.com/withastro/starlight', + }, + ], }), ], }); @@ -213,7 +232,7 @@ export default defineConfig({ Starlight 可以在每个页面的页脚中显示“编辑此页”链接。这样读者就可以找到要编辑以改进你的文档的文件。特别是对于开源项目,这有助于鼓励社区的贡献。 -要启用编辑链接,请将 Starlight 集成配置中的 [`editLink.baseUrl`](/zh/reference/configuration/#editlink) 设置为用于编辑存储库的URL。`editLink.baseUrl` 的值将附加到当前页面的路径前面,形成完整的编辑链接。 +要启用编辑链接,请将 Starlight 集成配置中的 [`editLink.baseUrl`](/zh-cn/reference/configuration/#editlink) 设置为用于编辑存储库的URL。`editLink.baseUrl` 的值将附加到当前页面的路径前面,形成完整的编辑链接。 常见的模式包括: @@ -224,7 +243,7 @@ Starlight 可以在每个页面的页脚中显示“编辑此页”链接。这 下面的示例显示了为 Starlight 文档配置的编辑链接,这些文档位于 GitHub 上名为 `withastro/starlight` 的存储库的 `main` 分支的 `docs/` 子目录中: -```js +```js {9-11} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -256,10 +275,11 @@ Starlight 网站默认显示一个简单的 404 页面。你可以通过向 `src </FileTree> -你可以在 404 页面中使用 Starlight 的所有页面布局和自定义技术。例如,默认的404页面在 frontmatter 中使用 [`splash`](#页面布局) 模板和 [`hero`](/zh/reference/frontmatter/#hero) 组件: +你可以在 404 页面中使用 Starlight 的所有页面布局和自定义技术。例如,默认的404页面在 frontmatter 中使用 [`splash`](#页面布局) 模板和 [`hero`](/zh-cn/reference/frontmatter/#hero) 组件: -```md +```md {4,6-8} --- +# src/content/docs/404.md title: '404' template: splash editUrl: false @@ -269,6 +289,25 @@ hero: --- ``` +### 禁用默认 404 页面 + +如果你的项目需要完全自定义的 404 布局,你可以创建一个 `src/pages/404.astro` 路由,并设置 [`disable404Route`](/zh-cn/reference/configuration/#disable404route) 配置选项来禁用 Starlight 的默认路由: + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: '带有自定义 404 页面的文档', + disable404Route: true, + }), + ], +}); +``` + ## 自定义字体 默认情况下,Starlight 使用用户本地设备上可用的无衬线字体来显示所有文本。这样可以确保文档在加载时以每个用户熟悉的字体快速显示,而不需要额外的带宽下载大型字体文件。 @@ -281,6 +320,8 @@ hero: #### 设置本地字体文件 +<Steps> + 1. 将字体文件添加到 `src/fonts/` 目录中,并创建一个空的 `font-face.css` 文件: <FileTree> @@ -311,7 +352,7 @@ hero: 3. 将 `font-face.css` 文件的路径添加到 Starlight 的 `astro.config.mjs` 配置文件中的 `customCss` 数组中: - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -321,23 +362,27 @@ hero: starlight({ title: '使用自定义字体的页面', customCss: [ - // @font-face CSS文件的相对路径。 - './src/fonts/font-face.css', + + // @font-face CSS文件的相对路径。 + + './src/fonts/font-face.css', ], }), ], }); ``` +</Steps> + #### 设置 Fontsource 字体 [Fontsource](https://fontsource.org/) 项目简化了使用 Google Fonts 和其他开源字体的过程。它提供了可安装的 npm 模块,用于你想要使用的字体,并包含了可以添加到项目中的现成 CSS 文件。 +<Steps> + 1. 在 [Fontsource 目录](https://fontsource.org/)中找到你想要使用的字体。本示例将使用 [IBM Plex Serif](https://fontsource.org/fonts/ibm-plex-serif) 字体。 2. 安装所选字体的包。你可以通过在 Fontsource 字体页面上点击 “Install” 按钮来找到包名称。 - <Tabs> + <Tabs syncKey="pkg"> <TabItem label="npm"> @@ -350,7 +395,7 @@ hero: <TabItem label="pnpm"> ```sh - pnpm install @fontsource/ibm-plex-serif + pnpm add @fontsource/ibm-plex-serif ``` </TabItem> @@ -367,7 +412,7 @@ hero: 3. 将 Fontsource 的 CSS 文件添加到 Starlight 的 `astro.config.mjs` 配置文件中的 `customCss` 数组中: - ```js + ```diff lang="js" // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -377,9 +422,9 @@ hero: starlight({ title: '使用自定义字体的文档', customCss: [ - // 用于普通和半粗字重的Fontsource文件。 - '@fontsource/ibm-plex-serif/400.css', - '@fontsource/ibm-plex-serif/600.css', + + // 用于普通和半粗字重的 Fontsource 文件。 + + '@fontsource/ibm-plex-serif/400.css', + + '@fontsource/ibm-plex-serif/600.css', ], }), ], @@ -388,9 +433,11 @@ hero: Fontsource 为每个字体提供了多个 CSS 文件。请参阅 [Fontsource 文档](https://fontsource.org/docs/getting-started/install#4-weights-and-styles)以了解如何包含不同的字重和样式。 +</Steps> + ### 使用字体 -要将设置好的字体应用于你的站点,请在[自定义 CSS 文件](/zh/guides/css-and-tailwind/#custom-css-styles)中使用所选字体的名称。例如,要在整个站点上覆盖 Starlight 的默认字体,请设置`--sl-font`自定义属性: +要将设置好的字体应用于你的站点,请在[自定义 CSS 文件](/zh-cn/guides/css-and-tailwind/#自定义-css-样式)中使用所选字体的名称。例如,要在整个站点上覆盖 Starlight 的默认字体,请设置`--sl-font`自定义属性: ```css /* src/styles/custom.css */ @@ -410,4 +457,4 @@ main { } ``` -按照[自定义 CSS](/zh/guides/css-and-tailwind/#custom-css-styles)将样式添加到你的站点。 +按照[自定义 CSS](/zh-cn/guides/css-and-tailwind/#自定义-css-样式)将样式添加到你的站点。 diff --git a/docs/src/content/docs/zh-cn/guides/i18n.mdx b/docs/src/content/docs/zh-cn/guides/i18n.mdx new file mode 100644 index 00000000000..4750c55fd08 --- /dev/null +++ b/docs/src/content/docs/zh-cn/guides/i18n.mdx @@ -0,0 +1,408 @@ +--- +title: 国际化 (i18n) +description: 学习如何配置你的 Starlight 网站支持多种语言。 +--- + +import { FileTree, Steps } from '@astrojs/starlight/components'; + +Starlight 提供了内置的多语言支持,包括路由、回退内容和完整的从右到左(RTL)语言支持。 + +## 配置 i18n + +<Steps> + +1. 通过将 [`locales`](/zh-cn/reference/configuration/#locales) 和 [`defaultLocale`](/zh-cn/reference/configuration/#defaultlocale) 传递给 Starlight 集成,告诉 Starlight 你支持的语言: + + ```js {9-26} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: '我的文档', + // 为此网站设置英语为默认语言。 + defaultLocale: 'en', + locales: { + // 英文文档在 `src/content/docs/en/` 中。 + en: { + label: 'English', + }, + // 简体中文文档在 `src/content/docs/zh-cn/` 中。 + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + // 阿拉伯文档在 `src/content/docs/ar/` 中。 + ar: { + label: 'العربية', + dir: 'rtl', + }, + }, + }), + ], + }); + ``` + + 你的 `defaultLocale` 将用于回退内容和 UI 标签,所以选择你最有可能开始编写内容的语言,或者已经有内容的语言。 + +2. 在 `src/content/docs/` 中为每种语言创建一个目录。 + 例如,对于上面显示的配置,创建以下文件夹: + + <FileTree> + + - src/ + - content/ + - docs/ + - ar/ + - en/ + - zh-cn/ + + </FileTree> + +3. 现在你可以在你的语言目录中添加内容文件。使用相同的文件名来关联跨语言的页面,并利用 Starlight 的完整的 i18n 功能,包括回退内容、翻译通知等。 + + 举个例子,创建 `ar/index.md` 和 `en/index.md` 来分别表示阿拉伯语和英语的主页。 + +</Steps> + +对于更高级的 i18n 场景,Starlight 也支持使用 [Astro 的 `i18n` 配置](https://docs.astro.build/zh-cn/guides/internationalization/#配置-i18n-路由)选项来配置国际化。 + +### 使用 `root` 语言 + +你可以使用“root”语言来提供没有任何 i18n 前缀的语言。例如,如果英语是你的 root 语言,那么英语页面的路径将是 `/about` 而不是 `/en/about`。 + +要设置 root 语言,请在你的 `locales` 配置中使用 `root` 键。如果 root 语言也是你的内容的默认语言,请删除 `defaultLocale` 或将其设置为 `'root'`。 + +```js {9,11-14} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: '我的文档', + defaultLocale: 'root', // 可选 + locales: { + root: { + label: 'English', + lang: 'en', // lang 是 root 语言必须的 + }, + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + }, + }), + ], +}); +``` + +当使用 `root` 语言时,将页面直接放在 `src/content/docs/` 中,而不是在专用的语言文件夹中。例如,当使用上面的配置时,这里是英语和中文的主页文件: + +<FileTree> + +- src/ + - content/ + - docs/ + - **index.md** + - zh-cn/ + - **index.md** + +</FileTree> + +#### 单语言网站 + +默认情况下,Starlight 是一个单语言(英语)网站。要在其他语言中创建单语言网站,请将其设置为 `locales` 配置中的 `root`: + +```diff lang="js" {10-13} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'My Docs', + locales: { + root: { + label: '简体中文', + lang: 'zh-CN', + }, + }, + }), + ], +}); +``` + +这允许你在不启用其他多语言网站的国际化功能的情况下,覆盖 Starlight 的默认语言,例如语言选择器。 + +## 回退内容 + +Starlight 期望你在所有语言中创建等效的页面。例如,如果你有一个 `en/about.md` 文件,请为你支持的每种其他语言创建一个 `about.md`。这允许 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'; +import UIStringsList from '~/components/ui-strings-list.astro'; + +除了托管翻译的内容文件之外,Starlight 还允许你翻译默认的 UI 字符串(例如,目录中的“本页”标题),以便你的读者可以完全使用所选的语言体验你的网站。 + +默认提供了<LanguagesList/>的翻译 UI 字符串, +同时我们欢迎[贡献添加更多默认语言](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md)。 + +你可以通过 `i18n` 数据集合提供你支持的其他语言的翻译 - 或覆盖我们的默认标签。 + +<Steps> + +1. 如果尚未配置,请在 `src/content.config.ts` 中配置 `i18n` 数据集合: + + ```diff lang="js" ins=/, (i18nLoader|i18nSchema)/ + // src/content.config.ts + import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; + import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + + export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), + }; + ``` + +2. 为你想要提供 UI 翻译字符串的每种其他语言在 `src/content/i18n/` 中创建一个 JSON 文件。 + 例如,这将为阿拉伯语和简体中文添加翻译文件: + + <FileTree> + + - src/ + - content/ + - i18n/ + - ar.json + - zh-CN.json + + </FileTree> + +3. 在 JSON 文件中添加你想要翻译的键的翻译。只翻译值,将键保留为英语(例如 `"search.label": "搜索"`)。 + + 这些是 Starlight 附带的现有字符串的英文默认值: + + <UIStringsList /> + + Starlight 的代码块使用了 [Expressive Code](https://expressive-code.com/)。 + 你可以在同一个 JSON 文件中使用 `expressiveCode` 键来设置它的 UI 字符串翻译。 + + ```json + { + "expressiveCode.copyButtonCopied": "Copied!", + "expressiveCode.copyButtonTooltip": "Copy to clipboard", + "expressiveCode.terminalWindowFallbackTitle": "Terminal window" + } + ``` + + Starlight 的搜索模态框由 [Pagefind](https://pagefind.app/) 库提供支持。 + 你可以在同一个 JSON 文件中使用 `pagefind` 键来设置它的 UI 字符串翻译。 + + ```json + { + "pagefind.clear_search": "Clear", + "pagefind.load_more": "Load more results", + "pagefind.search_label": "Search this site", + "pagefind.filters_label": "Filters", + "pagefind.zero_results": "No results for [SEARCH_TERM]", + "pagefind.many_results": "[COUNT] results for [SEARCH_TERM]", + "pagefind.one_result": "[COUNT] result for [SEARCH_TERM]", + "pagefind.alt_search": "No results for [SEARCH_TERM]. Showing results for [DIFFERENT_TERM] instead", + "pagefind.search_suggestion": "No results for [SEARCH_TERM]. Try one of the following searches:", + "pagefind.searching": "Searching for [SEARCH_TERM]..." + } + ``` + + </Steps> + +### 拓展翻译 schema + +通过在 `i18nSchema()` 选项中设置 `extend` 可以向你网站的翻译字典中添加自定义键。 +在下面的示例中添加了一个新的可选的 `custom.label` 键: + +```diff lang="js" +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ ++ extend: z.object({ ++ 'custom.label': z.string().optional(), ++ }), + }), + }), +}; +``` + +在 Astro 文档的[“定义集合模式”](https://docs.astro.build/zh-cn/guides/content-collections/#定义集合模式schema)中了解有关内容集合 schema 的更多信息。 + +## 使用 UI 翻译 + +你可以使用由 [i18next](https://www.i18next.com/) 提供支持的统一 API 访问 Starlight 的 [内置 UI 字符串](/zh-cn/guides/i18n/#翻译-starlight-的-ui) 以及 [用户定义](/zh-cn/guides/i18n/#拓展翻译-schema) 和 [插件提供](/zh-cn/reference/plugins/#injecttranslations) 的 UI 字符串。 +其中包括了对 [插值](https://www.i18next.com/translation-function/interpolation) 和 [多元化](https://www.i18next.com/translation-function/plurals) 等功能的支持。 + +在 Astro 组件中,此 API 作为 [全局 `Astro` 对象](https://docs.astro.build/zh-cn/reference/api-reference/#locals) 的一部分提供,即 `Astro.locals.t`: + +```astro title="example.astro" +<p dir={Astro.locals.t.dir()}> + {Astro.locals.t('404.text')} +</p> +``` + +你还可以在 [端点](https://docs.astro.build/zh-cn/guides/endpoints/) 中使用 API,其中的 `locals` 对象可作为 [端点上下文](https://docs.astro.build/zh-cn/reference/api-reference/#locals) 的一部分使用: + +```ts title="src/pages/404.ts" +export const GET = (context) => { + return new Response(context.locals.t('404.text')); +}; +``` + +在 Starlight 插件的上下文中,你可以使用 [`useTranslations()`](/zh-cn/reference/plugins/#usetranslations) 助手函数来访问特定语言的此 API。 +有关更多信息,请参阅 [插件参考](/zh-cn/reference/plugins/)。 + +### 渲染 UI 字符串 + +使用 `locals.t()` 函数以渲染 UI 字符串。 +这是 i18next 的 `t()` 函数的一个实例,该函数将 UI 字符串键作为其第一个参数,并返回当前语言的相应翻译。 + +例如,给定一个包含以下内容的自定义翻译文件: + +```json title="src/content/i18n/en.json" +{ + "link.astro": "Astro documentation", + "link.astro.custom": "Astro documentation for {{feature}}" +} +``` + +第一个 UI 字符串可以通过将 `'link.astro'` 传递给 `t()` 函数来渲染: + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/"> + {Astro.locals.t('link.astro')} +</a> +<!-- 渲染结果:<a href="...">Astro documentation</a> --> +``` + +第二个 UI 字符串对 `{{feature}}` 占位符使用了 i18next 的 [插值语法](https://www.i18next.com/translation-function/interpolation)。 +`feature` 的值在被作为第二个参数传递给 `t()` 时,必须被设置在一个选项对象中: + +```astro {3} +<!-- src/components/Example.astro --> +<a href="https://docs.astro.build/en/guides/astro-db/"> + {Astro.locals.t('link.astro.custom', { feature: 'Astro DB' })} +</a> +<!-- 渲染结果:<a href="...">Astro documentation for Astro DB</a> --> +``` + +有关如何使用 `t()` 函数进行插值、格式化等更多信息,请参阅 [i18next 文档](https://www.i18next.com/overview/api#t)。 + +### 高级 API + +#### `t.all()` + +`locals.t.all()` 函数可返回一个对象,返回的对象中包含当前区域设置下所有可用的 UI 字符串。 + +```astro +--- +// src/components/Example.astro +const allStrings = Astro.locals.t.all(); +// ^ +// { +// "skipLink.label": "Skip to content", +// "search.label": "Search", +// … +// } +--- +``` + +#### `t.exists()` + +要检查某个区域设置是否存在某个翻译键,请使用 `locals.t.exists()` 函数,并将该翻译键作为第一个参数。 +如需覆盖当前的区域设置,请传递第二个可选参数。 + +```astro +--- +// src/components/Example.astro +const keyExistsInCurrentLocale = Astro.locals.t.exists('a.key'); +// ^ true +const keyExistsInFrench = Astro.locals.t.exists('another.key', { lng: 'fr' }); +// ^ false +--- +``` + +有关详细信息,请参阅 [i18next 文档中的 `exists()` 参考](https://www.i18next.com/overview/api#exists)。 + +#### `t.dir()` + +`locals.t.dir()` 函数可返回当前或特定语言环境的文本方向。 + +```astro +--- +// src/components/Example.astro +const currentDirection = Astro.locals.t.dir(); +// ^ +// 'ltr' +const arabicDirection = Astro.locals.t.dir('ar'); +// ^ +// 'rtl' +--- +``` + +有关详细信息,请参阅 [i18next 文档中的 `dir()` 参考](https://www.i18next.com/overview/api#dir)。 + +## 访问当前语言环境 + +你可以使用 [`Astro.currentLocale`](https://docs.astro.build/zh-cn/reference/api-reference/#currentlocale) 在 `.astro` 组件中读取当前的语言环境。 + +下面的示例读取当前语言环境,并使用它和 [`getRelativeLocaleUrl()`](https://docs.astro.build/zh-cn/reference/modules/astro-i18n/#getrelativelocaleurl) 助手函数以生成一个当前语言的关于页面的链接: + +```astro +--- +// src/components/AboutLink.astro +import { getRelativeLocaleUrl } from 'astro:i18n'; +--- + +<a href={getRelativeLocaleUrl(Astro.currentLocale ?? 'en', 'about')}>About</a> +``` diff --git a/docs/src/content/docs/zh-cn/guides/overriding-components.mdx b/docs/src/content/docs/zh-cn/guides/overriding-components.mdx new file mode 100644 index 00000000000..e857b0acdb6 --- /dev/null +++ b/docs/src/content/docs/zh-cn/guides/overriding-components.mdx @@ -0,0 +1,152 @@ +--- +title: 重写组件 +description: 学习如何通过替换 Starlight 的内置组件来给你的文档站点 UI 添加自定义元素。 +--- + +import { Steps } from '@astrojs/starlight/components'; + +Starlight 的默认 UI 和配置选项被设计成能灵活地适用于各种内容。大部分 Starlight 的默认外观可以通过 [CSS](/zh-cn/guides/css-and-tailwind/) 和 [配置选项](/zh-cn/guides/customization/) 进行自定义。 + +当你的需求超出了默认提供的功能时,Starlight 支持使用你自己的自定义组件来扩展或重写(完全替换)它的默认组件。 + +## 什么时候重写 + +重写 Starlight 的默认组件在以下情况下很有用: + +- 你想要修改 Starlight 的一部分 UI 的样式,但是无法通过使用[自定义 CSS](/zh-cn/guides/css-and-tailwind/) 实现。 +- 你想要修改 Starlight 的一部分 UI 的行为。 +- 你想要在 Starlight 的现有 UI 旁边添加一些额外的 UI。 + +## 如何重写 + +<Steps> + +1. 选择你想要重写的 Starlight 组件。 + 你可以在[重写参考](/zh-cn/reference/overrides/)中找到完整的组件列表。 + + :::tip + 不确定你需要重写哪个组件?使用 [交互式 Starlight 重写地图](https://starlight-overrides-map.netlify.app/) 来发现 Starlight UI 组件的名称。 + ::: + + 本示例将重写 Starlight 页面导航栏中的 [`SocialIcons`](/zh-cn/reference/overrides/#socialicons) 组件。 + +2. 创建一个 Astro 组件来替换 Starlight 组件。 + 本示例渲染了一个联系方式链接。 + + ```astro + --- + // src/components/EmailLink.astro + + const email = 'houston@example.com'; + --- + + <a href=`mailto:${email}`>E-mail Me</a> + ``` + +3. 在 `astro.config.mjs` 的 [`components`](/zh-cn/reference/configuration/#components) 配置选项中告诉 Starlight 使用你的自定义组件: + + ```js {9-12} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'My Docs with Overrides', + components: { + // 重写默认的 `SocialIcons` 组件。 + SocialIcons: './src/components/EmailLink.astro', + }, + }), + ], + }); + ``` + +</Steps> + +## 复用内置组件 + +你可以像使用自己的组件一样使用 Starlight 的默认 UI 组件:导入并在你自己的自定义组件中渲染它们。这样你就可以在你的设计中保留 Starlight 的基本 UI,同时在它们旁边添加额外的 UI。 + +下面的示例是一个自定义组件,它渲染了一个电子邮件链接以及默认的 `SocialIcons` 组件: + +```astro {3,7} +--- +// src/components/EmailLink.astro +import Default from '@astrojs/starlight/components/SocialIcons.astro'; +--- + +<a href="mailto:houston@example.com">E-mail Me</a> +<Default><slot /></Default> +``` + +在自定义组件中渲染内置组件时,在默认组件中添加一个 [`<slot />`](https://docs.astro.build/zh-cn/basics/astro-components/#插槽)。这样可以确保如果组件传入了任何子元素,Astro 就知道在哪里渲染它们。 + +如果你要复用包含 [命名插槽](https://docs.astro.build/zh-cn/basics/astro-components/#命名插槽) 的 [`PageFrame`](/zh-cn/reference/overrides/#pageframe) 或 [`TwoColumnContent`](/zh-cn/reference/overrides/#twocolumncontent) 组件,你还需要 [传递](https://docs.astro.build/zh-cn/basics/astro-components/#传递插槽) 这些插槽。 + +下面的示例展示了一个自定义组件,它复用了 `TwoColumnContent` 组件,该组件需要传递一个额外的 `right-sidebar` 命名插槽: + +```astro {8} +--- +// src/components/CustomContent.astro +import Default from '@astrojs/starlight/components/TwoColumnContent.astro'; +--- + +<Default> + <slot /> + <slot name="right-sidebar" slot="right-sidebar" /> +</Default> +``` + +## 使用页面数据 + +当重写 Starlight 组件时,你可以访问包含当前页面所有数据的全局 [`starlightRoute` 对象](/zh-cn/guides/route-data/)。 +这使得你可以使用这些值来控制你的组件模板的渲染方式。 + +在下面的示例中,一个 [`PageTitle`](/zh-cn/reference/overrides/#pagetitle) 组件显示当前页面的标题,该标题在内容的前端元数据中设置: + +```astro {4} "{title}" +--- +// src/components/Title.astro + +const { title } = Astro.locals.starlightRoute.entry.data; +--- + +<h1 id="_top">{title}</h1> + +<style> + h1 { + font-family: 'Comic Sans'; + } +</style> +``` + +了解更多关于所有可用属性的信息,请参阅 [路由数据参考](/zh-cn/reference/route-data/)。 + +### 仅在特定页面上重写 + +组件重写在所有页面上生效。但是,你可以使用 `starlightRoute` 中的值来条件性渲染,决定何时显示你的自定义 UI,何时显示 Starlight 的默认 UI,甚至何时显示完全不同的内容。 + +在下面的示例中,一个重写 [`Footer`](/zh-cn/reference/overrides/#footer) 的组件只在首页上显示“Built with Starlight 🌟”,在其他页面上显示默认的页脚: + +```astro +--- +// src/components/ConditionalFooter.astro +import Default from '@astrojs/starlight/components/Footer.astro'; + +const isHomepage = Astro.locals.starlightRoute.id === ''; +--- + +{ + isHomepage ? ( + <footer>Built with Starlight 🌟</footer> + ) : ( + <Default> + <slot /> + </Default> + ) +} +``` + +了解更多关于条件渲染的内容,请参阅 [Astro 模板语法指南](https://docs.astro.build/zh-cn/basics/astro-syntax/#动态-html)。 diff --git a/docs/src/content/docs/zh-cn/guides/pages.mdx b/docs/src/content/docs/zh-cn/guides/pages.mdx new file mode 100644 index 00000000000..2bf8b26fa6e --- /dev/null +++ b/docs/src/content/docs/zh-cn/guides/pages.mdx @@ -0,0 +1,230 @@ +--- +title: 页面 +description: 了解如何使用 Starlight 创建和管理文档站点页面。 +sidebar: + order: 1 +tableOfContents: + maxHeadingLevel: 4 +--- + +Starlight 根据你的内容生成站点的 HTML 页面,并通过 Markdown frontmatter 提供灵活的选项。 +此外,Starlight 项目可以完全使用 [Astro 强大的页面生成工具](https://docs.astro.build/zh-cn/basics/astro-pages/)。 +本指南介绍了 Starlight 中的页面生成工作原理。 + +## 内容页面 + +### 文件格式 + +Starlight 支持在 Markdown 和 MDX 中创作内容,无需任何配置。 +你可以按照 [“Markdoc” 指南](/zh-cn/guides/authoring-content/#markdoc) 添加对 Markdoc 的支持。 + +### 添加页面 + +通过在 `src/content/docs/` 中创建 `.md` 或 `.mdx` 文件来添加新页面。 +使用子文件夹来组织文件并创建多个路径段。 + +举个例子,以下文件结构将在 `example.com/hello-world` 和 `example.com/reference/faq` 生成页面: + +import { FileTree } from '@astrojs/starlight/components'; + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - reference/ + - faq.md + +</FileTree> + +### 类型安全的 frontmatter + +所有的 Starlight 页面都共享一个可定制的 [通用 frontmatter 属性集](/zh-cn/reference/frontmatter/),用于控制页面的外观: + +```md +--- +title: Hello, World! +description: 这是我的 Starlight 网站中的一个页面 +--- +``` + +如果你忘记了一些重要的东西,Starlight 会提醒你。 + +## 自定义页面 + +对于高级用例,你可以通过创建 `src/pages/` 目录来添加自定义页面。 +`src/pages/` 目录使用 [Astro 的基于文件的路由](https://docs.astro.build/zh-cn/basics/astro-pages/#基于文件的路由), 并支持 `.astro` 文件等其他页面格式。 + +这对于需要完全自定义布局或从其他数据源生成页面的情况非常有用。 + +举个例子,以下文件结构将在 `example.com/custom` 和 `example.com/archived` 生成页面: + +<FileTree> + +- src/ + - content/ + - docs/ + - hello-world.md + - pages/ + - custom.astro + - archived.html + +</FileTree> + +在 [Astro 文档中的“页面”指南](https://docs.astro.build/zh-cn/basics/astro-pages/) 中了解更多。 + +### 在自定义页面中使用 Starlight 的设计 + +要在自定义页面中使用 Starlight 布局,请使用 [`<StarlightPage />` 组件](#starlightpage-组件)包装页面内容。 + +如果你正在动态生成内容但仍想使用 Starlight 的设计,这会很有帮助。 + +要在标题中添加和 Starlight 的 Markdown 锚点链接样式一样的锚点链接,你可以在自定义页面中使用 [`<AnchorHeading>` 组件](#anchorheading-组件)。 + +```astro +--- +// src/pages/custom-page/example.astro +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +import CustomComponent from './CustomComponent.astro'; +--- + +<StarlightPage frontmatter={{ title: '我的自定义页面' }}> + <p>这是一个有自定义组件的自定义页面:</p> + <CustomComponent /> + + <AnchorHeading level="2" id="learn-more">了解更多</AnchorHeading> + <p> + <a href="https://starlight.astro.build/">在 Starlight 文档中阅读更多</a> + </p> +</StarlightPage> +``` + +#### `<StarlightPage>` 组件 + +`<StarlightPage />` 组件使用 Starlight 的布局和样式渲染完整页面内容。 + +```astro +--- +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +--- + +<StarlightPage frontmatter={{ title: '我的自定义页面' }}> + <!-- 自定义页面内容 --> +</StarlightPage> +``` + +`<StarlightPage />` 组件接受以下 props。 + +##### `frontmatter` + +**必填** +**类型:** `StarlightPageFrontmatter` + +为此页面设置 [frontmatter 属性](/zh-cn/reference/frontmatter/),类似于 Markdown 页面中的 frontmatter。 +[`title`](/zh-cn/reference/frontmatter/#title-必填) 属性是必填的,其他所有属性都是可选的。 + +以下是与 Markdown frontmatter 不同的属性: + +- [`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 属性不可用。使用 `<StarlightPage />` 组件的页面不是集合的一部分,不能添加到自动生成的侧边栏组中。 +- [`draft`](/zh-cn/reference/frontmatter/#draft) 选项仅会显示页面为草稿的 [通知](/zh-cn/reference/overrides/#draftcontentnotice),但不会自动将其从生产版本中排除。 + +##### `sidebar` + +**类型:**[`SidebarItem[]`](/zh-cn/reference/configuration/#sidebaritem) +**默认值:** 根据 [全局 `sidebar` 配置](/zh-cn/reference/configuration/#sidebar) 生成的侧边栏 + +为此页面提供自定义站点导航侧边栏。 +如果未设置,此页面将使用默认的全局侧边栏。 + +例如,以下页面使用指向主页的链接和一组指向各种其他自定义页面的链接覆盖了默认的侧边栏。 + +```astro {3-13} +<StarlightPage + frontmatter={{ title: '猎户座' }} + sidebar={[ + { label: '首页', link: '/' }, + { + label: '星座', + items: [ + { label: '仙女座', link: '/andromeda/' }, + { label: '猎户座', link: '/orion/' }, + { label: '射手座', link: '/sagittarius/', badge: 'Stub' }, + ], + }, + ]} +> + 示例内容。 +</StarlightPage> +``` + +了解更多有关自定义侧边栏的可用选项,请参阅[“侧边栏导航”](/zh-cn/guides/sidebar/)指南。 + +##### `hasSidebar` + +**类型:** `boolean` +**默认值:** 如果 [`frontmatter.template`](/zh-cn/reference/frontmatter/#template) 是 `'splash'`,为`false`,否则为 `true` + +控制是否在此页面上显示侧边栏。 + +##### `headings` + +**类型:** `{ depth: number; slug: string; text: string }[]` +**默认值:** `[]` + +提供此页面上所有标题的数组。 +如果提供了,Starlight 将从这些标题生成页面目录。 + +##### `dir` + +**类型:** `'ltr' | 'rtl'` +**默认值:** 当前语言环境的书写方向 + +设置此页面内容的书写方向。 + +##### `lang` + +**类型:** `string` +**默认值:** 当前语言环境的语言 + +为此页面的内容设置 BCP-47 语言标签,例如 `en`、`zh-CN` 或 `pt-BR`。 + +##### `isFallback` + +**类型:** `boolean` +**默认值:** `false` + +表示此页面是否使用了[回退内容](/zh-cn/guides/i18n/#回退内容),因为当前语言没有翻译。 + +#### `<AnchorHeading>` 组件 + +`<AnchorHeading />` 组件渲染一个 HTML 标题元素,并带有一个可点击的锚点链接,样式与 Starlight 的 Markdown 样式一样。 + +```astro +--- +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; +--- + +<AnchorHeading level="2" id="sub-heading">子标题</AnchorHeading> +``` + +它接受以下属性以及任何其他有效的[全局 HTML 属性](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Global_attributes)。 + +##### `level` + +**必填** +**类型:** `1 | 2 | 3 | 4 | 5 | 6` + +要渲染的标题级别。 +例如,`level="1"` 将渲染一个 `<h1>` 元素。 + +##### `id` + +**必填** +**类型:** `string` + +用于此标题的唯一 ID。 +这将用作渲染标题的 `id` 属性,并且锚点图标将链接到它。 diff --git a/docs/src/content/docs/zh/guides/project-structure.mdx b/docs/src/content/docs/zh-cn/guides/project-structure.mdx similarity index 78% rename from docs/src/content/docs/zh/guides/project-structure.mdx rename to docs/src/content/docs/zh-cn/guides/project-structure.mdx index dfef0d5948a..8e1ce3cb11b 100644 --- a/docs/src/content/docs/zh/guides/project-structure.mdx +++ b/docs/src/content/docs/zh-cn/guides/project-structure.mdx @@ -5,14 +5,14 @@ description: 了解如何组织 Starlight 项目中的文件。 本指南将向你展示 Starlight 项目的组织方式以及项目中的不同文件的作用。 -Starlight 项目通常遵循与其他 Astro 项目相同的文件和目录结构。有关更多详细信息,请参阅 [Astro 的项目结构文档](https://docs.astro.build/zh-cn/core-concepts/project-structure/)。 +Starlight 项目通常遵循与其他 Astro 项目相同的文件和目录结构。有关更多详细信息,请参阅 [Astro 的项目结构文档](https://docs.astro.build/zh-cn/basics/project-structure/)。 ## 文件和目录 - `astro.config.mjs` — Astro 配置文件;包括 Starlight 集成和配置。 -- `src/content/config.ts` — 内容集合配置文件;将 Starlight 的 frontmatter 模式添加到你的项目中。 +- `src/content.config.ts` — 内容集合配置文件;将 Starlight 的 frontmatter 模式添加到你的项目中。 - `src/content/docs/` — 内容文件。Starlight 将此目录中的每个 `.md`、`.mdx` 或 `.mdoc` 文件转换为站点上的一个页面。 -- `src/content/i18n/` (可选) — 支持[国际化](/guides/i18n/)的翻译数据。 +- `src/content/i18n/` (可选) — 支持[国际化](/zh-cn/guides/i18n/)的翻译数据。 - `src/` — 项目的其他源代码和文档(组件、样式、图像等)。 - `public/` — 静态资源(字体、网站图标、PDF 等)不会被 Astro 处理。 @@ -20,7 +20,7 @@ Starlight 项目通常遵循与其他 Astro 项目相同的文件和目录结构 一个 Starlight 项目目录可能如下所示: -import FileTree from '../../../../components/file-tree.astro'; +import { FileTree } from '@astrojs/starlight/components'; <FileTree> @@ -39,8 +39,7 @@ import FileTree from '../../../../components/file-tree.astro'; - 01-getting-started.md - 02-advanced.md - index.mdx - - config.ts - - env.d.ts + - content.config.ts - astro.config.mjs - package.json - tsconfig.json diff --git a/docs/src/content/docs/zh-cn/guides/route-data.mdx b/docs/src/content/docs/zh-cn/guides/route-data.mdx new file mode 100644 index 00000000000..421abe6293c --- /dev/null +++ b/docs/src/content/docs/zh-cn/guides/route-data.mdx @@ -0,0 +1,137 @@ +--- +title: 路由数据 +description: 了解 Starlight 的页面数据模型是如何用于渲染你的页面以及如何自定义它。 +--- + +import { Steps } from '@astrojs/starlight/components'; + +当 Starlight 渲染文档中的页面时,它首先创建一个路由数据对象来表示该页面上的内容。 +本指南解释了路由数据是如何生成的,如何使用它,以及如何自定义它来修改Starlight的默认行为。 + +有关可用属性的完整列表,请参阅 [“路由数据参考”](/zh-cn/reference/route-data/)。 + +## 什么是路由数据? + +Starlight 路由数据是一个包含渲染单个页面所需的所有信息的对象。 +它包括当前页面的信息以及从你的 Starlight 配置生成的数据。 + +## 使用路由数据 + +Starlight 的所有组件都使用路由数据来决定为每个页面渲染什么。 +例如,[`siteTitle`](/zh-cn/reference/route-data/#sitetitle) 字符串用于显示网站标题,[`sidebar`](/zh-cn/reference/route-data/#sidebar) 数组用于渲染全局侧边栏导航。 + +你可以在 Astro 组件中通过 `Astro.locals.starlightRoute` 全局变量访问这些数据: + +```astro title="example.astro" {2} +--- +const { siteTitle } = Astro.locals.starlightRoute; +--- + +<p>此网站的页面标题是 “{siteTitle}”</p> +``` + +例如,在 [重写组件](/zh-cn/guides/overriding-components/) 以自定义显示内容时,这会很有用。 + +## 自定义路由数据 + +Starlight 的路由数据是开箱即用的,不需要任何配置。但是,对于高级用例,你可能需要自定义某些或所有页面的路由数据,以修改你的网站显示方式。 + +这与 [重写组件](/zh-cn/guides/overriding-components/) 的概念类似,但不是修改 Starlight 渲染数据的方式,而是修改 Starlight 渲染的数据。 + +### 什么时候自定义路由数据 + +当你希望以现有配置选项无法实现的方式修改 Starlight 处理数据的方式时,自定义路由数据会很有用。 + +例如,你可能想要过滤侧边栏项目或自定义特定页面的标题。 +像这样的更改不需要修改 Starlight 的默认组件,只需要传递给这些组件的数据。 + +### 如何自定义路由数据 + +你可以使用一种特殊形式的 “中间件” 来自定义路由数据。 +这是一个每次 Starlight 渲染页面时都会调用的函数,可以修改路由数据对象中的值。 + +<Steps> + +1. 创建一个新文件,使用 Starlight 的 `defineRouteMiddleware()` 工具函数导出一个 `onRequest` 函数: + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware(() => {}); + ``` + +2. 告诉 Starlight 你的路由数据中间件文件在 `astro.config.mjs` 中的位置: + + ```js ins={9} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'My delightful docs site', + routeMiddleware: './src/routeData.ts', + }), + ], + }); + ``` + +3. 更新你的 `onRequest` 函数来修改路由数据。 + + 你的中间件接收的第一个参数是 [Astro 的上下文对象](https://docs.astro.build/zh-cn/reference/api-reference/)。 + 它包含关于当前页面渲染的完整信息,包括当前 URL 和 `locals`。 + + 在这个例子中,我们将在每页标题的末尾添加一个感叹号,使我们的文档更加精彩。 + + ```ts + // src/routeData.ts + import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + + export const onRequest = defineRouteMiddleware((context) => { + // 获取此页面的内容集合条目。 + const { entry } = context.locals.starlightRoute; + // 更新标题以添加感叹号。 + entry.data.title = entry.data.title + '!'; + }); + ``` + +</Steps> + +#### 多个路由中间件 + +Starlight 还支持提供多个中间件。 +将 `routeMiddleware` 设置为路径数组,以添加多个中间件处理程序: + +```js {9} +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'My site with multiple middleware', + routeMiddleware: ['./src/middleware-one.ts', './src/middleware-two.ts'], + }), + ], +}); +``` + +#### 等待稍后的路由中间件 + +为了在执行代码之前等待堆栈中稍后的中间件运行,你可以等待作为第二个参数传递给中间件函数的 `next()` 回调。这对于等待插件的中间件运行后再进行更改非常有用。 + +```ts "next" "await next();" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware(async (context, next) => { + // 等待后续中间件运行。 + await next(); + // 修改路由数据 + const { entry } = context.locals.starlightRoute; + entry.data.title = entry.data.title + '!'; +}); +``` diff --git a/docs/src/content/docs/zh-cn/guides/sidebar.mdx b/docs/src/content/docs/zh-cn/guides/sidebar.mdx new file mode 100644 index 00000000000..41ee7b93410 --- /dev/null +++ b/docs/src/content/docs/zh-cn/guides/sidebar.mdx @@ -0,0 +1,671 @@ +--- +title: 侧边栏导航 +description: 了解如何设置和自定义 Starlight 站点的侧边栏导航链接。 +--- + +import { FileTree } from '@astrojs/starlight/components'; +import SidebarPreview from '~/components/sidebar-preview.astro'; + +一个组织良好的侧边栏是良好文档的关键,因为它是用户浏览你的站点的主要方式之一。Starlight 提供了一整套选项来自定义侧边栏布局和内容。 + +## 默认侧边栏 + +默认情况查下,Starlight 会根据你的文档文件系统结构自动生成侧边栏,使用每个文件的 `title` 属性作为侧边栏条目。 + +例如,给定以下文件结构: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - andromeda.md + - orion.md + - stars/ + - betelgeuse.md + +</FileTree> + +将会自动生成以下侧边栏: + +<SidebarPreview + config={[ + { + label: 'constellations', + items: [ + { label: '仙女座', link: '' }, + { label: '猎户座', link: '' }, + ], + }, + { + label: 'stars', + items: [{ label: '参宿四', link: '' }], + }, + ]} +/> + +在 [自动生成的分组](#自动生成的分组) 章节了解更多关于自动生成侧边栏的内容。 + +## 添加链接和链接分组 + +要配置侧边栏链接和链接分组(在可折叠的标题中),请在 `astro.config.mjs` 中使用 [`starlight.sidebar`](/zh-cn/reference/configuration/#sidebar) 属性。 + +结合使用链接和链接分组,你可以创建各种侧边栏布局。 + +### 内部链接 + +使用带有 `slug` 属性的对象为 `src/content/docs/` 中的页面添加链接。 +默认情况下,链接页面的标题会被作为标签。 + +例如,进行以下的配置: + +```js "slug:" +starlight({ + sidebar: [ + { slug: 'constellations/andromeda' }, + { slug: 'constellations/orion' }, + ], +}); +``` + +并给定以下的文件结构: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - andromeda.md + - orion.md + +</FileTree> + +那么将会生成如下的侧边栏: + +<SidebarPreview + config={[ + { label: '仙女座', link: '' }, + { label: '猎户座', link: '' }, + ]} +/> + +而要想覆盖从链接页面的 frontmatter 所推断出来的值,你可以添加 `label`,[`translations`](#国际化),以及 [`attrs`](#自定义-html-属性) 属性。 + +想了解更多通过 frontmatter 控制侧边栏外观的内容,请参阅 [“在 frontmatter 中自定义自动生成的链接”](#在-frontmatter-中自定义自动生成的链接)。 + +#### 内部链接的简易写法 + +内部链接也可以通过只提供一个页面标题字符串来指定。 + +例如,以下的配置等同于上面使用 `slug` 的配置: + +```js "slug:" +starlight({ + sidebar: ['constellations/andromeda', 'constellations/orion'], +}); +``` + +### 其他链接 + +使用带有 `label` 和 `link` 属性的对象,添加指向外部或非文档页面的链接。 + +```js "label:" "link:" +starlight({ + sidebar: [ + // 指向网站中非文档页面的链接。 + { label: '流星商店', link: '/shop/' }, + // 指向 NASA 网站的外部链接。 + { label: 'NASA', link: 'https://www.nasa.gov/' }, + ], +}); +``` + +上面的配置生成以下侧边栏: + +<SidebarPreview + config={[ + { label: '流星商店', link: '' }, + { label: 'NASA', link: 'https://www.nasa.gov/' }, + ]} +/> + +### 分组 + +你可以通过在可折叠的标题下将相关链接组合在一起来为侧边栏添加结构。 +分组可以包含链接和其他子组。 + +使用具有 `label` 和 `items` 属性的对象添加一个分组。 +`label` 将用作分组的标题。 +将链接或子组添加到 `items` 数组中。 + +```js /^\s*(label:|items:)/ +starlight({ + sidebar: [ + // 一个名为 "星座" 的链接分组 + { + label: '星座', + items: [ + 'constellations/carina', + 'constellations/centaurus', + // 星座周期的嵌套链接分组。 + { + label: '周期', + items: [ + 'constellations/andromeda', + 'constellations/orion', + 'constellations/ursa-minor', + ], + }, + ], + }, + ], +}); +``` + +上面的配置生成以下侧边栏: + +<SidebarPreview + config={[ + { + label: '星座', + items: [ + { label: '船底座', link: '' }, + { label: '半人马座', link: '' }, + { + label: '周期', + items: [ + { label: '仙女座', link: '' }, + { label: '猎户座', link: '' }, + { label: '小熊座', link: '' }, + ], + }, + ], + }, + ]} +/> + +### 自动生成的分组 + +Starlight 可以根据文档目录在侧边栏中自动生成一个分组。当你不想手动输入分组中的每个侧边栏项目时,这很有用。 + +默认情况下,页面按照文件 [`slug`](/zh-cn/reference/route-data/#slug) 的字母顺序排序。 + +使用具有 `label` 和 `autogenerate` 属性的对象添加自动生成的分组。`autogenerate` 的配置必须指定用于侧边栏条目的 `directory` 。例如,使用以下配置: + +```js "label:" "autogenerate:" +starlight({ + sidebar: [ + { + label: '星座', + // 自动生成一个链接分组,用于 '星座' 目录。 + autogenerate: { directory: 'constellations' }, + }, + ], +}); +``` + +给定以下文件结构: + +<FileTree> + +- src/ + - content/ + - docs/ + - constellations/ + - carina.md + - centaurus.md + - seasonal/ + - andromeda.md + +</FileTree> + +将会自动生成以下侧边栏: + +<SidebarPreview + config={[ + { + label: '星座', + items: [ + { label: '船底座', link: '' }, + { label: '半人马座', link: '' }, + { + label: 'seasonal', + items: [{ label: '仙女座', link: '' }], + }, + ], + }, + ]} +/> + +## 在 frontmatter 中自定义自动生成的链接 + +在单个页面中使用 [`sidebar` frontmatter 字段](/zh-cn/reference/frontmatter/#sidebar) 来自定义自动生成的链接。 + +侧边栏 frontmatter 选项允许你设置 [自定义标签](/zh-cn/reference/frontmatter/#label) 或者为链接添加 [徽章](/zh-cn/reference/frontmatter/#badge),[隐藏](/zh-cn/reference/frontmatter/#hidden) 侧边栏中的链接,或者定义 [自定义排序权重](/zh-cn/reference/frontmatter/#order)。 + +```md "sidebar:" +--- +# src/content/docs/example.md +title: 我的页面 +sidebar: + # 为链接设置自定义标签 + label: 自定义侧边栏 label + # 为链接设置自定义顺序(数字越小显示在上方) + order: 2 + # 为链接添加徽章 + badge: + text: New + variant: tip +--- +``` + +一个包含上面 frontmatter 的页面的自动生成分组将会生成以下侧边栏: + +<SidebarPreview + config={[ + { + label: '指南', + items: [ + { label: '一个页面', link: '' }, + { + label: '自定义侧边栏 label ', + link: '', + badge: { text: 'New', variant: 'tip' }, + }, + { label: '其他页面', link: '' }, + ], + }, + ]} +/> + +:::note +`sidebar` frontmatter 配置仅用于自动生成分组中的链接和使用 `slug` 属性定义的文档链接。它并不适用于使用 `link` 属性定义的链接。 +::: + +## 徽章 + +链接、分组、自动生成的分组都可以包含一个 `badge` 属性,以在它们的标签旁边显示徽章。 + +```js {9,16} +starlight({ + sidebar: [ + { + label: '星星', + items: [ + // 带有 "Supergiant" 徽章的链接。 + { + slug: 'stars/persei', + badge: 'Supergiant', + }, + ], + }, + // 带有 "Outdated" 徽章的自动生成分组。 + { + label: '卫星', + badge: 'Outdated', + autogenerate: { directory: 'moons' }, + }, + ], +}); +``` + +以上配置将生成以下侧边栏: + +<SidebarPreview + config={[ + { + label: '星星', + items: [ + { + label: '英仙座', + link: '', + badge: { text: '超巨星', variant: 'default' }, + }, + ], + }, + { + label: '卫星', + badge: { text: 'Outdated', variant: 'default' }, + items: [ + { + label: '木卫一', + link: '', + }, + { + label: '木卫二', + link: '', + }, + { + label: '木卫三', + link: '', + }, + ], + }, + ]} +/> + +### 徽章种类和自定义样式 + +使用具有 `text`、`variant` 和 `class` 属性的对象自定义徽章样式。 + +`text` 属性表示要显示的内容(例如 "New")。 + +默认情况下,徽章将使用你的网站的强调色。要使用内置的徽章样式,请将 `variant` 属性设置为以下值之一:`note`、`tip`、`danger`、`caution` 或 `success`。 + +你还可以通过设置 `class` 属性为一个 CSS 类名来创建自定义的徽章样式。 + +```js {9} +starlight({ + sidebar: [ + { + label: '星星', + items: [ + // 一个带有黄色 "Stub" 徽章的链接。 + { + slug: 'stars/sirius', + badge: { text: 'Stub', variant: 'caution' }, + }, + ], + }, + ], +}); +``` + +以上配置将生成以下侧边栏: + +<SidebarPreview + config={[ + { + label: '星星', + items: [ + { + label: '天狼星', + link: '', + badge: { text: 'Stub', variant: 'caution' }, + }, + ], + }, + ]} +/> + +了解关于[使用和自定义徽章](/zh-cn/components/badges/#用法)的更多信息。 + +## 自定义 HTML 属性 + +可以通过在链接对象里添加 `attrs` 属性来自定义链接元素的 HTML 属性。 + +在下面的例子中,通过 `attrs` 添加了一个 `target="_blank"` 属性,使得链接在新标签页中打开,并应用了一个自定义的 `style` 属性使链接标签变为斜体: + +```js {10} +starlight({ + sidebar: [ + { + label: '资源', + items: [ + // 一个指向 NASA 网站的在新标签页打开的外部链接。 + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { target: '_blank', style: 'font-style: italic' }, + }, + ], + }, + ], +}); +``` + +以上配置将生成以下侧边栏: + +<SidebarPreview + config={[ + { + label: '资源', + items: [ + { + label: 'NASA', + link: 'https://www.nasa.gov/', + attrs: { + target: '_blank', + style: 'font-style: italic', + }, + }, + ], + }, + ]} +/> + +## 国际化 + +你可以使用链接和分组条目上的 `translations` 属性,通过指定 [BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags) 语言标签,为每种支持的语言翻译链接或分组标签,例如用 `"en"`、`"ar"` 或 `"zh-CN"` 作为键,翻译后的标签作为值。 + +`label` 属性将用于默认语言和没有翻译的语言。 + +```js {5-7,11-13,18-20} +starlight({ + sidebar: [ + { + label: '星座', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { + label: '仙女座', + translations: { + 'pt-BR': 'Andrômeda', + }, + slug: 'constellations/andromeda', + }, + { + label: '天蝎座', + translations: { + 'pt-BR': 'Escorpião', + }, + slug: 'constellations/scorpius', + }, + ], + }, + ], +}); +``` + +浏览巴西葡萄牙语文档将生成以下侧边栏: + +<SidebarPreview + config={[ + { + label: 'Constelação', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +### 通过内部链接实现国际化 + +默认情况下,[内部链接](#内部链接)将从 frontmatter 自动使用翻译页面的标题: + +```js {9-10} +starlight({ + sidebar: [ + { + label: '星座', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { slug: 'constellations/andromeda' }, + { slug: 'constellations/scorpius' }, + ], + }, + ], +}); +``` + +浏览巴西葡萄牙语文档将生成以下侧边栏: + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { label: 'Andrômeda', link: '' }, + { label: 'Escorpião', link: '' }, + ], + }, + ]} +/> + +在多语言网站中,`slug` 的值不会包含 URL 的语言部分。 +例如,如果页面位于 `en/intro` 和 `pt-br/intro`,则在配置侧边栏时,slug 为 `intro`。 + +### 通过徽章实现国际化 + +对于[徽章](#徽章),`text` 属性可以是字符串,而对于多语言网站,文本属性则可以是具有每个不同区域设置值的对象。 +使用对象形式时,键必须是 [BCP-47](https://www.w3.org/International/questions/qa-choosing-language-tags) 标签(例如 `en`、`ar` 或 `zh-CN`): + +```js {11-16} +starlight({ + sidebar: [ + { + label: '星座', + translations: { + 'pt-BR': 'Constelações', + }, + items: [ + { + slug: 'constellations/andromeda', + badge: { + text: { + 'zh-CN': '新', + 'pt-BR': 'Novo', + }, + }, + }, + ], + }, + ], +}); +``` + +浏览巴西葡萄牙语文档将生成以下侧边栏: + +<SidebarPreview + config={[ + { + label: 'Constelações', + items: [ + { + label: 'Andrômeda', + link: '', + badge: { text: 'Novo', variant: 'default' }, + }, + ], + }, + ]} +/> + +## 折叠分组 + +链接分组可以通过将 `collapsed` 属性设置为 `true` 来默认折叠。 + +```js {5-6} +starlight({ + sidebar: [ + { + label: '星座', + // 默认折叠分组 + collapsed: true, + items: ['constellations/andromeda', 'constellations/orion'], + }, + ], +}); +``` + +以上配置将生成以下侧边栏: + +<SidebarPreview + config={[ + { + label: '星座', + collapsed: true, + items: [ + { label: '仙女座', link: '' }, + { label: '猎户座', link: '' }, + ], + }, + ]} +/> + +[自动生成的分组](#自动生成的分组) 遵循其父级分组的 `collapsed` 值: + +```js {5-6} +starlight({ + sidebar: [ + { + label: '星座', + // 默认折叠分组及其自动生成的子组。 + collapsed: true, + autogenerate: { directory: 'constellations' }, + }, + ], +}); +``` + +以上配置将生成以下侧边栏: + +<SidebarPreview + config={[ + { + label: '星座', + collapsed: true, + items: [ + { label: '船底座', link: '' }, + { label: '半人马座', link: '' }, + { + label: 'seasonal', + collapsed: true, + items: [{ label: '仙女座', link: '' }], + }, + ], + }, + ]} +/> + +这个行为可以通过定义 `autogenerate.collapsed` 属性来覆盖。 + +```js {5-7} "collapsed: true" +starlight({ + sidebar: [ + { + label: '星座', + // 不折叠 "星座" 分组,但折叠其自动生成的子组。 + collapsed: false, + autogenerate: { directory: 'Constellations', collapsed: true }, + }, + ], +}); +``` + +以上配置将生成以下侧边栏: + +<SidebarPreview + config={[ + { + label: '星座', + items: [ + { label: '船底座', link: '' }, + { label: '半人马座', link: '' }, + { + label: 'seasonal', + collapsed: true, + items: [{ label: '仙女座', link: '' }], + }, + ], + }, + ]} +/> diff --git a/docs/src/content/docs/zh-cn/guides/site-search.mdx b/docs/src/content/docs/zh-cn/guides/site-search.mdx new file mode 100644 index 00000000000..cacbfd144e5 --- /dev/null +++ b/docs/src/content/docs/zh-cn/guides/site-search.mdx @@ -0,0 +1,234 @@ +--- +title: 全站搜索 +description: 了解 Starlight 的内置全站搜索功能和如何自定义它们。 +tableOfContents: + maxHeadingLevel: 4 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +默认情况下,Starlight 站点提供了基于 [Pagefind](https://pagefind.app/) 的全文搜索,它是一个为静态站点的快速且低带宽的搜索工具。 + +启用搜索不需要配置。构建并部署你的站点,然后使用网站顶部的搜索栏来查找内容。 + +## 从搜索结果中隐藏内容 + +### 排除一个页面 + +要从搜索结果中排除一个页面,需要将 [`pagefind: false`](/zh-cn/reference/frontmatter/#pagefind) 添加到页面的 frontmatter 中: + +```md title="src/content/docs/不被索引.md" ins={3} +--- +title: 要从搜索结果中隐藏的内容 +pagefind: false +--- +``` + +### 排除页面中的一部分 + +Pagefind 会忽略带有 [`data-pagefind-ignore`](https://pagefind.app/docs/indexing/#removing-individual-elements-from-the-index) 属性的元素内的内容。 + +在下面的示例中,第一个段落将显示在搜索结果中,但 `<div>` 的内容不会: + +```md title="src/content/docs/部分索引.md" ins="data-pagefind-ignore" +--- +title: 部分索引的页面 +--- + +这段文字会被搜索到。 + +<div data-pagefind-ignore> + +这段文字不会被搜索到。 + +</div> +``` + +## 其他搜索供应商 + +### Algolia DocSearch + +如果你加入了 [Algolia 的 DocSearch 计划](https://docsearch.algolia.com/)并且想要用它来替代 Pagefind,你可以使用官方的 Starlight DocSearch 插件。 + +<Steps> + +1. 安装 `@astrojs/starlight-docsearch`: + + <Tabs syncKey="pkg"> + + <TabItem label="npm"> + + ```sh + npm install @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="pnpm"> + + ```sh + pnpm add @astrojs/starlight-docsearch + ``` + + </TabItem> + + <TabItem label="Yarn"> + + ```sh + yarn add @astrojs/starlight-docsearch + ``` + + </TabItem> + + </Tabs> + +2. 把 DocSearch 加到 `astro.config.mjs` 里你的 Starlight [`plugins`](/zh-cn/reference/configuration/#plugins) 配置中,并传入你的 Algolia `appId`、`apiKey` 和 `indexName`: + + ```js ins={4,10-16} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: '使用 DocSearch 的网站', + plugins: [ + starlightDocSearch({ + appId: 'YOUR_APP_ID', + apiKey: 'YOUR_SEARCH_API_KEY', + indexName: 'YOUR_INDEX_NAME', + }), + ], + }), + ], + }); + ``` + +</Steps> + +像这样更新配置后,你站点上的搜索栏将会打开一个 Algolia 的模态框而不是默认的搜索模态框。 + +#### DocSearch 配置 + +Starlight DocSearch 插件支持通过下面这些内联的选项来自定义 DocSearch 组件: + +- `maxResultsPerGroup`:限制每个搜索组所显示的结果数。默认值为 `5`。 +- `disableUserPersonalization`:阻止 DocSearch 将用户的最近搜索和收藏夹保存到本地存储。默认值为 `false`。 +- `insights`:启用 Algolia Insights 插件并将搜索事件发送到你的 DocSearch 索引。默认值为 `false`。 +- `searchParameters`:一个可用于自定义 [Algolia 搜索参数](https://www.algolia.com/doc/api-reference/search-api-parameters/)的对象。 + +##### 其他 DocSearch 选项 + +为了将函数选项(如 `transformItems()` 或 `resultsFooterComponent()`)传递给 DocSearch 组件,需要创建一个单独的配置文件。 + +<Steps> + +1. 创建一个 TypeScript 文件,导出 DocSearch 选项。 + + ```ts + // src/config/docsearch.ts + import type { DocSearchClientOptions } from '@astrojs/starlight-docsearch'; + + export default { + appId: 'YOUR_APP_ID', + apiKey: 'YOUR_SEARCH_API_KEY', + indexName: 'YOUR_INDEX_NAME', + getMissingResultsUrl({ query }) { + return `https://github.com/algolia/docsearch/issues/new?title=${query}`; + }, + // ... + } satisfies DocSearchClientOptions; + ``` + +2. 在 `astro.config.mjs` 中将你的配置文件路径传递给 Starlight DocSearch 插件。 + + ```js {11-13} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: '使用 DocSearch 的网站', + plugins: [ + starlightDocSearch({ + clientOptionsModule: './src/config/docsearch.ts', + }), + ], + }), + ], + }); + ``` + +</Steps> + +请参阅 [DocSearch JavaScript 客户端 API 参考](https://docsearch.algolia.com/docs/api/) 以了解所有支持的选项。 + +#### 翻译 DocSearch UI + +DocSearch 默认只提供了英语 UI 文本。 +使用 Starlight 内置的[国际化系统](/zh-cn/guides/i18n/#翻译-starlight-的-ui)来添加你的语言的模态框 UI 的翻译。 + +<Steps> + +1. 在 `src/content.config.ts` 中给 Starlight 的 `i18n` 内容集合定义添加 DocSearch schema: + + ```js ins={5} ins=/{ extend: .+ }/ + // src/content.config.ts + import { defineCollection } from 'astro:content'; + import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; + import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + import { docSearchI18nSchema } from '@astrojs/starlight-docsearch/schema'; + + export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ + loader: i18nLoader(), + schema: i18nSchema({ extend: docSearchI18nSchema() }), + }), + }; + ``` + +2. 在 `src/content/i18n/` 里的 JSON 文件中添加翻译。 + + 这些是 DocSearch 使用的英文默认文本: + + ```json title="src/content/i18n/en.json" + { + "docsearch.searchBox.resetButtonTitle": "Clear the query", + "docsearch.searchBox.resetButtonAriaLabel": "Clear the query", + "docsearch.searchBox.cancelButtonText": "Cancel", + "docsearch.searchBox.cancelButtonAriaLabel": "Cancel", + "docsearch.searchBox.searchInputLabel": "Search", + + "docsearch.startScreen.recentSearchesTitle": "Recent", + "docsearch.startScreen.noRecentSearchesText": "No recent searches", + "docsearch.startScreen.saveRecentSearchButtonTitle": "Save this search", + "docsearch.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", + "docsearch.startScreen.favoriteSearchesTitle": "Favorite", + "docsearch.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + + "docsearch.errorScreen.titleText": "Unable to fetch results", + "docsearch.errorScreen.helpText": "You might want to check your network connection.", + + "docsearch.footer.selectText": "to select", + "docsearch.footer.selectKeyAriaLabel": "Enter key", + "docsearch.footer.navigateText": "to navigate", + "docsearch.footer.navigateUpKeyAriaLabel": "Arrow up", + "docsearch.footer.navigateDownKeyAriaLabel": "Arrow down", + "docsearch.footer.closeText": "to close", + "docsearch.footer.closeKeyAriaLabel": "Escape key", + "docsearch.footer.searchByText": "Search by", + + "docsearch.noResultsScreen.noResultsText": "No results for", + "docsearch.noResultsScreen.suggestedQueryText": "Try searching for", + "docsearch.noResultsScreen.reportMissingResultsText": "Believe this query should return results?", + "docsearch.noResultsScreen.reportMissingResultsLinkText": "Let us know." + } + ``` + +</Steps> diff --git a/docs/src/content/docs/zh-cn/index.mdx b/docs/src/content/docs/zh-cn/index.mdx new file mode 100644 index 00000000000..9fe4cc88711 --- /dev/null +++ b/docs/src/content/docs/zh-cn/index.mdx @@ -0,0 +1,162 @@ +--- +title: Starlight 🌟 使用 Astro 构建文档站点 +head: + - tag: title + content: Starlight 🌟 使用 Astro 构建文档站点 +description: Starlight 帮助你使用 Astro 构建漂亮、高性能的文档网站。 +template: splash +editUrl: false +lastUpdated: false +banner: + content: | + 更新到 Astro 5? + <a href="https://github.com/withastro/starlight/releases/tag/%40astrojs/starlight%400.30.0"> + 了解如何升级 + </a> +hero: + title: Starlight <br/> 使你的文档闪耀夺目 + tagline: 快速、易用、易于访问 —— 构建卓越文档网站所需的一切。 + image: + file: ~/assets/hero-star.webp + actions: + - text: 开始使用 + icon: right-arrow + link: /zh-cn/getting-started/ + - text: 在 GitHub 上查看 + icon: external + variant: minimal + link: https://github.com/withastro/starlight +--- + +import { CardGrid, Card } from '@astrojs/starlight/components'; +import AboutAstro from '~/components/about-astro.astro'; +import TestimonialGrid from '~/components/testimonial-grid.astro'; +import Testimonial from '~/components/testimonial.astro'; + +<CardGrid stagger> + <Card title="令人愉悦的文档" icon="open-book"> + 包括:网站导航、搜索、国际化、SEO、易于阅读的排版、代码高亮、深色模式等等。 + </Card> + <Card title="由 Astro 提供支持" icon="rocket"> + 充分利用 Astro 的全部功能和性能。使用你最喜欢的 Astro 集成和库扩展 + Starlight。 + </Card> + <Card title="Markdown、Markdoc 和 MDX" icon="document"> + 带上你最喜欢的标记语言。Starlight 为你提供了内置的 frontmatter 验证和 + TypeScript 类型安全。 + </Card> + <Card title="带上你自己的 UI 组件" icon="puzzle"> + Starlight 作为一个不依赖于框架的完整文档解决方案。可以使用 + React、Vue、Svelte、Solid 等进行扩展。 + </Card> +</CardGrid> + +<TestimonialGrid title="看看人们怎么说"> + <Testimonial + name="Rachel" + handle="rachelnabors" + cite="https://twitter.com/astrodotbuild/status/1724934718745915558" + > + Astro 团队通过他们的 Starlight 项目彻底改变了文档处理的方式,现在你可以一站式获取所有功能。 + </Testimonial> + <Testimonial + name="Flavio" + handle="flaviocopes" + cite="https://twitter.com/flaviocopes/status/1738237658717905108" + > + Astro 官方的入门工具 Starlight 是一款非常令人难以置信的构建文档网站的工具。 + </Testimonial> + <Testimonial + name="Tomek" + handle="sulco" + cite="https://twitter.com/sulco/status/1735610348730802342" + > + Starlight 是我们极力推荐的出色开发体验(DX)的典范:其速度、便捷性和对细节的关注令人鼓舞。它负责技术和外观,让你可以专注于你的内容。👏 + + StackBlitz 团队对它赞不绝口! + + </Testimonial> + <Testimonial + name="Roberto" + handle="RmeetsH" + cite="https://twitter.com/RmeetsH/status/1735783992018760090" + > + Starlight 对我来说是一个改变游戏规则的工具,让我能够专注于内容创作。 + + 它直观的设计不仅简化了我的工作流程,还缩短了开源开发者的入门时间。 + + </Testimonial> + <Testimonial + name="Joel" + handle="jhooks" + cite="https://twitter.com/jhooks/status/1727405160547418405" + > + 花了更多时间使用 Starlight 来创建课程构建文档,目前感觉非常不错。有很多巧妙的设计,可以专注于使用 Markdown 进行写作,而不必费心调整网站。 + </Testimonial> + <Testimonial + name="Rick" + handle="rick_viscomi" + cite="https://twitter.com/rick_viscomi/status/1665867447910510593" + > + 开始尝试使用 Starlight。不得不说,我对其开箱即用的性能感到非常印象深刻。 + + 💯💯💯💯 + + </Testimonial> + <Testimonial + name="Nicolas" + handle="beaussan" + cite="https://twitter.com/beaussan/status/1735625189583466893" + > + Starlight 是开始文档编写的最佳方式,结合了 Astro 的强大和速度,以及来自 Starlight 的工具,简直是天作之合。 + + 我已经使用它一段时间了,一直都很喜欢! + + </Testimonial> + <Testimonial + name="Sylwia" + handle="SylwiaVargas" + cite="https://x.com/SylwiaVargas/status/1726556825741578286" + > + 我在上一份工作中使用了 Starlight,非常喜欢它。拥有出色的组件、直观的设计,以及非常响应的社区(每当有人需要帮助时,他们会很快提供支持或告诉你解决方法)。非常愉快的体验。 + </Testimonial> + <Testimonial + name="Lou Cyx" + handle="loucyx" + cite="https://elk.zone/m.webtoo.ls/@loucyx@mastodon.social/111587380021362284" + > + 由于 Starlight 的帮助,我的 monorepo 站点上的文档看起来比以往任何时候都更好。它非常易于使用,同时不失Astro 的所有强大功能。感谢你们的努力工作! + </Testimonial> + <Testimonial + name="BowTiedWebReaper" + handle="BowTiedWebReapr" + cite="https://twitter.com/BowTiedWebReapr/status/1735633399501697517" + > + Starlight 是我用于文档编写的首选工具。相比于使用其他需要子域的工具,它使得将文档添加到我现有的 Astro产品网站变得非常容易。 + </Testimonial> + <Testimonial + name="Jeff" + handle="J_Everhart383" + cite="https://twitter.com/J_Everhart383/status/1691900590048292908" + > + 我一直在重建 WPEngine Atlas 平台文档。相信我,Starlight 拥有一切你需要打造 A+ 文档平台的要素。🙌 + </Testimonial> + <Testimonial + name="Chloe" + handle="solelychloe" + cite="https://twitter.com/solelychloe/status/1695115277602628082" + > + 试试 Starlight 吧! + + 我在我的几个网站上使用它,效果非常棒。 + + </Testimonial> +</TestimonialGrid> + +<AboutAstro title="由以下提供支持"> +Astro 是专为速度而设计的全能 Web 框架。 +从任何地方获取你的内容并在任何地方部署,所有这些都由你喜欢的 UI 组件和库提供支持。 + +[了解 Astro](https://astro.build/) + +</AboutAstro> diff --git a/docs/src/content/docs/zh/manual-setup.mdx b/docs/src/content/docs/zh-cn/manual-setup.mdx similarity index 69% rename from docs/src/content/docs/zh/manual-setup.mdx rename to docs/src/content/docs/zh-cn/manual-setup.mdx index bf02d5c9134..bcd26f5a59a 100644 --- a/docs/src/content/docs/zh/manual-setup.mdx +++ b/docs/src/content/docs/zh-cn/manual-setup.mdx @@ -5,7 +5,7 @@ description: 了解如何手动配置 Starlight 以将其添加到现有的 Astr import { Tabs, TabItem } from '@astrojs/starlight/components'; -创建新的 Starlight 站点的最快方法是使用 `create astro`,如[入门指南](/zh/getting-started/#创建一个新项目)所示。 +创建新的 Starlight 站点的最快方法是使用 `create astro`,如[入门指南](/zh-cn/getting-started/#创建一个新项目)所示。 如果你想将 Starlight 添加到现有的 Astro 项目中,本指南将解释如何操作。 ## 设置 Starlight @@ -16,7 +16,7 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; Starlight 是一个 [Astro 集成](https://docs.astro.build/zh-cn/guides/integrations-guide/)。通过在项目的根目录中运行 `astro add` 命令将其添加到你的站点中: -<Tabs> +<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh npx astro add starlight @@ -44,7 +44,7 @@ Starlight 集成在 `astro.config.mjs` 文件中配置。 添加一个 `title` 以开始: -```js {7-9} +```js ins={8} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -58,24 +58,28 @@ export default defineConfig({ }); ``` -在 [Starlight 配置参考](/zh/reference/configuration/) 中查找所有可用选项。 +在 [Starlight 配置参考](/zh-cn/reference/configuration/) 中查找所有可用选项。 ### 配置内容集合 -Starlight 是建立在 Astro 的[内容集合](https://docs.astro.build/zh-cn/guides/content-collections/)之上的,这些集合在 `src/content/config.ts` 文件中配置。 +Starlight 是建立在 Astro 的[内容集合](https://docs.astro.build/zh-cn/guides/content-collections/)之上的,这些集合在 `src/content.config.ts` 文件中配置。 -创建或更新内容配置文件,添加一个使用 Starlight 的 `docsSchema` 的 `docs` 集合: +创建或更新内容配置文件,添加一个使用 Starlight 的 `docsLoader` 和 `docsSchema` 的 `docs` 集合: -```js ins={3,6} -// src/content/config.ts +```js ins={3-4,7} +// src/content.config.ts import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; import { docsSchema } from '@astrojs/starlight/schema'; export const collections = { - docs: defineCollection({ schema: docsSchema() }), + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), }; ``` +Starlight 也支持 [`legacy.collections` 标志](https://docs.astro.build/zh-cn/reference/legacy-flags/),其中集合使用旧版的内容集合实现处理。 +这对于你有一个现有的 Astro 项目,目前无法对集合进行任何更改以使用加载器的情况非常有用。 + ### 添加内容 现在 Starlight 已经配置好了,是时候添加一些内容了! @@ -93,7 +97,7 @@ description: 通过 Starlight 构建的文档网站,了解有关我的项目 欢迎来到我的项目! ``` -Starlight 使用基于文件的路由,这意味着 `src/content/docs/` 中的每个 Markdown、MDX 或 Markdoc 文件都将变成你站点上的一个页面。前置元数据(上面示例中的 `title` 和 `description` 字段)可以更改每个页面的显示方式。在 [frontmatter 指南](/zh/reference/frontmatter/) 中查看所有可用选项。 +Starlight 使用基于文件的路由,这意味着 `src/content/docs/` 中的每个 Markdown、MDX 或 Markdoc 文件都将变成你站点上的一个页面。前置元数据(上面示例中的 `title` 和 `description` 字段)可以更改每个页面的显示方式。在 [frontmatter 指南](/zh-cn/reference/frontmatter/) 中查看所有可用选项。 ## 现有站点的提示 @@ -105,7 +109,7 @@ Starlight 使用基于文件的路由,这意味着 `src/content/docs/` 中的 例如,如果 Starlight 页面都应该以 `/guides/` 开头,请将内容添加到 `src/content/docs/guides/` 目录中: -import FileTree from '../../../components/file-tree.astro'; +import { FileTree } from '@astrojs/starlight/components'; <FileTree> @@ -124,4 +128,6 @@ import FileTree from '../../../components/file-tree.astro'; ### 结合 SSR 使用 Starlight -目前,Starlight 不支持使用 Astro 的服务器适配器进行 [SSR 部署](https://docs.astro.build/zh-cn/guides/server-side-rendering/) 。我们希望能够尽快支持这一点。 +要启用 SSR,请按照 Astro 文档中的 [“按需渲染适配器”](https://docs.astro.build/zh-cn/guides/on-demand-rendering/) 指南将服务器适配器添加到你的 Starlight 项目中。 + +无论项目的输出模式如何,Starlight 生成的文档页面都默认为预渲染。要选择不对 Starlight 页面进行预渲染,请将 [`prerender` 配置选项](/zh-cn/reference/configuration/#prerender) 设置为 `false`。 diff --git a/docs/src/content/docs/zh-cn/reference/configuration.mdx b/docs/src/content/docs/zh-cn/reference/configuration.mdx new file mode 100644 index 00000000000..31f51f8c316 --- /dev/null +++ b/docs/src/content/docs/zh-cn/reference/configuration.mdx @@ -0,0 +1,670 @@ +--- +title: 配置参考 +description: Starlight 支持的所有配置选项的概述。 +--- + +## 配置 `starlight` 集成 + +Starlight 是在 [Astro](https://astro.build) web 框架之上构建的集成。你可以在 `astro.config.mjs` 配置文件中配置你的项目: + +```js +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: '我的令人愉快的文档网站', + }), + ], +}); +``` + +你可以将以下选项传递给`starlight`集成。 + +### `title` (必填) + +**类型:** `string | Record<string, string>` + +设置你的网站标题。将用于元数据和浏览器标签标题。 + +这个值可以是一个字符串,或者对于多语言网站,可以是一个包含每种不同语言值的对象。 +当使用对象形式时,键必须是 BCP-47 标签(例如 `en`,`ar` 或 `zh-CN`): + +```ts +starlight({ + title: { + en: 'My delightful docs site', + de: 'Meine bezaubernde Dokumentationsseite', + }, +}); +``` + +### `description` + +**类型:** `string` + +设置你的网站描述。如果页面的 frontmatter 中没有设置 `description`,则在 `<meta name="description">` 标签中与搜索引擎共享元数据。 + +### `logo` + +**类型:** [`LogoConfig`](#logoconfig) + +在导航栏中设置一个 logo 图片,与网站标题一起显示或替代网站标题。你可以设置单个 `src` 属性,也可以为 `light` 和 `dark` 设置单独的图像源。 + +```js +starlight({ + logo: { + src: './src/assets/my-logo.svg', + }, +}); +``` + +#### `LogoConfig` + +```ts +type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( + | { src: string } + | { light: string; dark: string } +); +``` + +### `tableOfContents` + +**类型:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` +**默认值:** `{ minHeadingLevel: 2, maxHeadingLevel: 3; }` + +配置每个页面右侧显示的目录。默认情况下,`<h2>` 和 `<h3>` 标题将包含在此目录中。 + +### `editLink` + +**类型:** `{ baseUrl: string }` + +通过设置你要使用的 base URL 来启用 “编辑此页” 链接。最终链接将是`editLink.baseUrl` +当前页面路径。例如,要启用在 GitHub 上编辑`withastro/starlight` 仓库中的页面: + +```js +starlight({ + editLink: { + baseUrl: 'https://github.com/withastro/starlight/edit/main/', + }, +}); +``` + +使用此配置,`/introduction` 页面将具有指向 `https://github.com/withastro/starlight/edit/main/src/content/docs/introduction.md` 的编辑链接。 + +### `sidebar` + +**类型:** [`SidebarItem[]`](#sidebaritem) + +配置你的网站的侧边栏导航项目。 + +侧边栏是包含链接和链接组的数组。 +除了使用 `slug` 的项目之外,每个项目都必须具有 `label` 和以下属性之一: + +- `link` — 指向特定 URL 的单个链接,例如 `'/home'` 或 `'https://example.com'`。 + +- `slug` — 指向一个内部页面的引用, 例如 `'guides/getting-started'`。 + +- `items` — 包含更多侧边栏链接和子组的数组。 + +- `autogenerate` — 指定要从中自动生成一组链接的文档目录的对象。 + +内部链接也可以被指定为字符串,而不是带有 `slug` 属性的对象。 + +```js +starlight({ + sidebar: [ + // 标记为“Home”的单个链接项。 + { label: 'Home', link: '/' }, + // 一个标记为“Start Here”的组,其中包含四个链接。 + { + label: 'Start Here', + items: [ + // 在内部链接中使用 `slug`。 + { slug: 'intro' }, + { slug: 'installation' }, + // 或者使用内部链接的简易写法。 + 'tutorial', + 'next-steps', + ], + }, + // 一个链接到参考目录中所有页面的组。 + { + label: 'Reference', + autogenerate: { directory: 'reference' }, + }, + ], +}); +``` + +#### 排序 + +自动生成的侧边栏组按文档名字母顺序排序。例如,从 `astro.md` 生成的页面将显示在 `starlight.md`页面上方。 + +#### 折叠组 + +默认情况下,链接组是展开的。你可以通过将组的 `collapsed` 属性设置为 `true` 来更改此行为。 + +自动生成的子组默认情况下会遵守其父组的 `collapsed` 属性。设置 `autogenerate.collapsed` 属性以覆盖此行为。 + +```js {5,13} +sidebar: [ + // 一个折叠的链接组。 + { + label: 'Collapsed Links', + collapsed: true, + items: ['intro', 'next-steps'], + }, + // 一个展开的组,其中包含折叠的自动生成的子组。 + { + label: 'Reference', + autogenerate: { + directory: 'reference', + collapsed: true, + }, + }, +], +``` + +#### 翻译标签 + +如果你的网站是多语言的,每个项目的 `label` 被认为是默认语言。你可以设置一个 `translations` 属性来为你支持的其他语言提供标签: + +```js {5,9,14} +sidebar: [ + // 一个侧边栏示例,其中的标签被翻译成简体中文。 + { + label: 'Start Here', + translations: { 'zh-CN': '从这里开始' }, + items: [ + { + label: 'Getting Started', + translations: { 'zh-CN': '开始使用' }, + link: '/getting-started', + }, + { + label: 'Project Structure', + translations: { 'zh-CN': '项目结构' }, + link: '/structure', + }, + ], + }, +], +``` + +#### `SidebarItem` + +```ts +type SidebarItem = + | string + | ({ + translations?: Record<string, string>; + badge?: string | BadgeConfig; + } & ( + | { + // 链接 + link: string; + label: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // 内部链接 + slug: string; + label?: string; + attrs?: Record<string, string | number | boolean | undefined>; + } + | { + // 链接组 + label: string; + items: SidebarItem[]; + collapsed?: boolean; + } + | { + // 自动生成的链接组 + label: string; + autogenerate: { directory: string; collapsed?: boolean }; + collapsed?: boolean; + } + )); +``` + +#### `BadgeConfig` + +```ts +interface BadgeConfig { + text: string; + variant?: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; + class?: string; +} +``` + +### `locales` + +**类型:** <code>\{ \[dir: string\]: [LocaleConfig](#localeconfig) \}</code> + +为你的网站设置支持的 `locales` 来[配置国际化(i18n)](/zh-cn/guides/i18n/)。 + +每个条目都应该使用该语言文件保存的目录作为 key。 + +```js +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'My Site', + // 为这个网站设置英语作为默认语言。 + defaultLocale: 'en', + locales: { + // 英文文档在 `src/content/docs/en/` + en: { + label: 'English', + }, + // 简体中文文档在 `src/content/docs/zh-cn/` + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + // 阿拉伯文档在 `src/content/docs/ar/` + ar: { + label: 'العربية', + dir: 'rtl', + }, + }, + }), + ], +}); +``` + +#### `LocaleConfig` + +```ts +interface LocaleConfig { + label: string; + lang?: string; + dir?: 'ltr' | 'rtl'; +} +``` + +你可以为每个语言设置以下选项: + +##### `label` (必填) + +**类型:** `string` + +要向用户显示的此语言的标签,例如在语言切换器中。大多数情况下,你会希望这是该语言的名称,因为该语言的用户希望阅读它,例如`"English"`,`"العربية"`,或者 `"简体中文"`。 + +##### `lang` + +**类型:** `string` + +此语言的 BCP-47 标签,例如`"en"`,`"ar"`,或者 `"zh-CN"`。如果未设置,则默认使用该语言的目录名称。 如果没有找到特定于区域的翻译,带有区域子标签的语言标签(例如`pt-BR`或`en-US`)将使用内置的 UI 翻译作为其基本语言。 + +##### `dir` + +**类型:** `'ltr' | 'rtl'` + +这种语言的写作方向; `"ltr"`表示从左到右(默认值)或`"rtl"`表示从右到左。 + +#### root locale + +你可以通过设置 `root` locale 来提供不带 `/lang/` 目录的默认语言: + +```js {3-6} +starlight({ + locales: { + root: { + label: 'English', + lang: 'en', + }, + fr: { + label: 'Français', + }, + }, +}); +``` + +举例,这允许你将 `/getting-started/` 作为英语路由提供,并将 `/fr/getting-started/` 作为等效的法语页面。 + +### `defaultLocale` + +**类型:** `string` + +设置此站点的默认语言。 +该值应该与你的 [`locales`](#locales) 对象的键之一匹配。 +(如果你的默认语言是你的[root locale](#root-locale),你可以跳过这一步。) + +默认语言将用于在缺少翻译时提供回退内容。 + +### `social` + +**类型:** <code>{`Array<{ label: string; icon: `}[StarlightIcon](/zh-cn/reference/icons/){`; href: string }>`}</code> + +可选的社交媒体账户详情。 +每个条目将显示为网站 header 中的图标链接。 + +```js +starlight({ + social: [ + { icon: 'codeberg', label: 'Codeberg', href: 'https://codeberg.org/knut' }, + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro' }, + { icon: 'gitlab', label: 'GitLab', href: 'https://gitlab.com/delucis' }, + { icon: 'mastodon', label: 'Mastodon', href: 'https://m.webtoo.ls/@astro' }, + ], +}); +``` + +### `customCss` + +**类型:** `string[]` + +提供 CSS 文件来自定义你的 Starlight 网站的外观和风格。 + +支持相对于项目根目录的本地 CSS 文件,例如 `'./src/custom.css'`,以及你安装为 npm 模块的 CSS,例如 `'@fontsource/roboto'`。 + +```js +starlight({ + customCss: ['./src/custom-styles.css', '@fontsource/roboto'], +}); +``` + +### `markdown` + +**类型:** `{ headingLinks?: boolean }` +**默认值:** `{ headingLinks: true }` + +配置 Starlight 的 Markdown 处理。 + +#### `headingLinks` + +**类型:** `boolean` +**默认值:** `true` + +控制标题是否渲染为可点击的锚点链接。 + +```js +starlight({ + markdown: { + // 禁用 Starlight 的可点击标题锚点链接。 + headingLinks: false, + }, +}), +``` + +### `expressiveCode` + +**类型:** `StarlightExpressiveCodeOptions | boolean` +**默认值:** `true` + +Starlight 使用 [Expressive Code](https://expressive-code.com) 来渲染代码块,并添加对代码示例的高亮支持,向代码块添加文件名等。 +请参阅 [“代码块”指南](/zh-cn/guides/authoring-content/#代码块) 以了解如何在你的 Markdown 和 MDX 内容中使用 Expressive Code 语法。 + +你可以通过在 Starlight 的 `expressiveCode` 选项中设置任何标准的 [Expressive Code 配置选项](https://expressive-code.com/reference/configuration/) 以及一些特定于 Starlight 的属性。比如,设置 Expressive Code 的 `styleOverrides` 选项来覆盖默认的 CSS。这样就可以自定义代码块,比如给你的代码块添加圆角: + +```js ins={2-4} +starlight({ + expressiveCode: { + styleOverrides: { borderRadius: '0.5rem' }, + }, +}); +``` + +如果你想禁用 Expressive Code,请在 Starlight 配置中设置 `expressiveCode: false`: + +```js ins={2} +starlight({ + expressiveCode: false, +}); +``` + +除了标准的 Expressive Code 选项之外,你还可以在 `expressiveCode` 配置中设置以下 Starlight 特定属性,以进一步自定义代码块的主题行为: + +#### `themes` + +**类型:** `Array<string | ThemeObject | ExpressiveCodeTheme>` +**默认值:** `['starlight-dark', 'starlight-light']` + +设置用于代码块样式的主题。有关支持的主题格式的详细信息,请参阅 [Expressive Code `themes` 文档](https://expressive-code.com/guides/themes/)。 + +Starlight 默认使用 Sarah Drasner 的 [Night Owl 主题](https://github.com/sdras/night-owl-vscode-theme) 的深色和浅色变体。 + +如果你提供至少一个深色和一个浅色主题,Starlight 将自动将活动代码块主题与当前网站主题保持同步。 +使用 [`useStarlightDarkModeSwitch`](#usestarlightdarkmodeswitch) 选项配置此行为。 + +#### `useStarlightDarkModeSwitch` + +**类型:** `boolean` +**默认值:** `true` + +当设置为 `true` 时,代码块会在网站主题更改时自动在浅色和深色主题之间切换。 +当设置为 `false` 时,你必须手动添加 CSS 来处理多个主题之间的切换。 + +:::note +当设置 `themes` 时,你必须为 Starlight 暗黑模式切换提供至少一个深色和一个浅色主题。 +::: + +#### `useStarlightUiThemeColors` + +**类型:** `boolean` +**默认值:** 如果未设置 `themes`,则为 `true`,否则为 `false` + +当设置为 `true` 时,Starlight 的 CSS 变量用于代码块 UI 元素的颜色(背景、按钮、阴影等),与[网站颜色主题](/zh-cn/guides/css-and-tailwind/#主题)相匹配。 +当设置为 `false` 时,这些元素使用活动语法高亮主题提供的颜色。 + +:::note +当使用自定义主题并将其设置为 `true` 时,你必须提供至少一个深色和一个浅色主题,以确保正确的颜色对比度。 +::: + +### `pagefind` + +**类型:** <code>boolean | <a href="#pagefindoptions">PagefindOptions</a></code> +**默认值:** `true` + +配置 Starlight 的默认站点搜索 provider [Pagefind](https://pagefind.app/)。 + +将其设置为 `false` 以禁用使用 Pagefind 索引你的网站。这也将隐藏默认的搜索 UI。 + +当 [`prerender`](#prerender) 选项设置为 `false` 时,无法启用 Pagefind。 + +将 `pagefind` 设置为对象,以配置 Pagefind 搜索客户端。 + +- 查看 Pagefind 文档中的 [“自定义 Pagefind 的结果排序”](https://pagefind.app/docs/ranking/),了解如何使用 `pagefind.ranking` 选项来控制搜索结果排序的计算。 +- 查看 Pagefind 文档中的 [“搜索多个站点”](https://pagefind.app/docs/multisite/),了解如何使用 `pagefind.mergeIndex` 选项来控制如何跨多个站点搜索。 + +#### `PagefindOptions` + +```ts +interface PagefindOptions { + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + indexWeight?: number; + mergeIndex?: Array<{ + bundlePath: string; + indexWeight?: number; + basePath?: string; + baseUrl?: string; + mergeFilter?: Record<string, string | string[]>; + language?: string; + ranking?: { + pageLength?: number; + termFrequency?: number; + termSaturation?: number; + termSimilarity?: number; + }; + }>; +} +``` + +### `prerender` + +**类型:** `boolean` +**默认值:** `true` + +定义 Starlight 页面是应预渲染为静态 HTML 还是由 [SSR 适配器](https://docs.astro.build/zh-cn/guides/on-demand-rendering/) 按需渲染。 + +默认情况下,Starlight 页面是预渲染的。 +如果你正在使用 SSR 适配器并希望按需渲染 Starlight 页面,请设置为 `prerender: false`。 + +### `head` + +**类型:** [`HeadConfig[]`](#headconfig) + +添加自定义标签到你的 Starlight 网站的 `<head>` 中。 +可以用于添加分析和其他第三方脚本和资源。 + +```js +starlight({ + head: [ + // 示例:添加 Fathom 分析脚本标签。 + { + tag: 'script', + attrs: { + src: 'https://cdn.usefathom.com/script.js', + 'data-site': 'MY-FATHOM-ID', + defer: true, + }, + }, + ], +}); +``` + +在 `head` 中的条目会直接转换为 HTML 元素,并不会经过 Astro 的 [脚本](https://docs.astro.build/zh-cn/guides/client-side-scripts/#脚本处理) 或 [样式](https://docs.astro.build/zh-cn/guides/styling/#在-astro-进行设计) 处理。如果你需要导入本地资源,如脚本、样式或图片,请[重写 Head 组件](/zh-cn/guides/overriding-components/#复用内置组件)。 + +#### `HeadConfig` + +```ts +interface HeadConfig { + tag: string; + attrs?: Record<string, string | boolean | undefined>; + content?: string; +} +``` + +### `lastUpdated` + +**类型:** `boolean` +**默认值:** `false` + +控制页脚是否显示页面上次更新的时间。 + +默认情况下,此功能依赖于你的存储库的 Git 历史记录,并且在某些执行[浅克隆](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt)的部署平台上可能不准确。页面可以使用 [`lastUpdated` frontmatter 字段](/zh-cn/reference/frontmatter/#lastupdated)覆盖此设置或基于 Git 的日期。 + +### `pagination` + +**类型:** `boolean` +**默认值:** `true` + +定义页脚是否应包含上一页和下一页的链接。 + +页面可以使用 [`prev`](/zh-cn/reference/frontmatter/#prev) 和 [`next`](/zh-cn/reference/frontmatter/#next) frontmatter 字段覆盖此设置或链接文本和/或 URL。 + +### `favicon` + +**类型:** `string` +**默认值:** `'/favicon.svg'` + +设置网站的默认 favicon 的路径,它应该位于 `public/` 目录中,并且是一个有效的(`.ico`,`.gif`,`.jpg`,`.png` 或 `.svg`)图标文件。 + +```js +starlight({ + favicon: '/images/favicon.svg', +}), +``` + +如果你需要设置其他变体或回退的 favicon,你可以使用 [`head` 选项](#head)添加标签: + +```js +starlight({ + favicon: '/images/favicon.svg', + head: [ + // 为 Safari 添加 ICO favicon 回退。 + { + tag: 'link', + attrs: { + rel: 'icon', + href: '/images/favicon.ico', + sizes: '32x32', + }, + }, + ], +}); +``` + +### `titleDelimiter` + +**类型:** `string` +**默认值:** `'|'` + +设置在页面的 `<title>` 标签里页面标题和网站标题之间的分隔符,它会显示在浏览器标签上。 + +默认情况下,每个页面的 `<title>` 都是 `页面标题 | 网站标题`。 +举例,本页面的标题是“配置参考”,本站点的标题是“Starlight”,所以本页面的 `<title>` 是“配置参考 | Starlight”。 + +### `disable404Route` + +**类型:** `boolean` +**默认值:** `false` + +禁用注入 Starlight 的默认 [404 页面](https://docs.astro.build/zh-cn/basics/astro-pages/#自定义-404-错误页面)。要在项目中使用自定义的 `src/pages/404.astro` 路由,请将此选项设置为 `true`。 + +### `routeMiddleware` + +**类型:** `string | string[]` + +提供路由中间件的路径,可以修改 Starlight 处理数据的方式。 +这些文件路径不能与 [Astro 的中间件](https://docs.astro.build/zh-cn/guides/middleware/) 冲突。 + +在 [路由数据指南](/zh-cn/guides/route-data/#自定义路由数据) 中查看有关如何创建路由中间件的详细信息。 + +### `components` + +**类型:** `Record<string, string>` + +提供组件的路径来覆盖 Starlight 的默认实现。 + +```js +starlight({ + components: { + SocialLinks: './src/components/MySocialLinks.astro', + }, +}); +``` + +要查阅所有可覆盖的组件,请参阅[覆盖参考](/zh-cn/reference/overrides/)。 + +### `plugins` + +**类型:** [`StarlightPlugin[]`](/zh-cn/reference/plugins/#快速-api-参照) + +使用自定义插件扩展 Starlight。 +插件将更改应用到你的项目中,以修改或添加 Starlight 的功能。 + +访问 [插件 showcase](/zh-cn/resources/plugins/#插件) 查看可用插件列表。 + +```js +starlight({ + plugins: [starlightPlugin()], +}); +``` + +有关创建自己的插件的详细信息,请参阅[插件参考](/zh-cn/reference/plugins/)。 + +### `credits` + +**类型:** `boolean` +**默认值:** `false` + +启用在你的网站页脚显示 “基于 Starlight 构建” 的链接。 + +```js +starlight({ + credits: true, +}); +``` diff --git a/docs/src/content/docs/zh-cn/reference/frontmatter.md b/docs/src/content/docs/zh-cn/reference/frontmatter.md new file mode 100644 index 00000000000..2e17d916de6 --- /dev/null +++ b/docs/src/content/docs/zh-cn/reference/frontmatter.md @@ -0,0 +1,470 @@ +--- +title: Frontmatter 参考 +description: Starlight 支持的默认 frontmatter 字段的概述。 +--- + +你可以通过设置 frontmatter 中的值来自定义 Starlight 中的单个 Markdown 和 MDX 页面。例如,一个常规页面可能会设置 `title` 和 `description` 字段: + +```md {3-4} +--- +# src/content/docs/example.md +title: 关于此项目 +description: 了解更多关于此项目的信息。 +--- + +欢迎来到关于页面! +``` + +## Frontmatter 字段 + +### `title` (必填) + +**类型:** `string` + +你必须为每个页面提供标题。它将显示在页面顶部、浏览器标签中和页面元数据中。 + +### `description` + +**类型:** `string` + +页面描述用于页面元数据,将被搜索引擎和社交媒体预览捕获。 + +### `slug` + +**类型:** `string` + +覆盖页面的slug。有关更多详细信息,请参阅 Astro文档中的 [ "定义自定义 ID"](https://docs.astro.build/zh-cn/guides/content-collections/#定义自定义-id) 部分。 + +### `editUrl` + +**类型:** `string | boolean` + +覆盖[全局 `editLink` 配置](/zh-cn/reference/configuration/#editlink)。设置为 false 可禁用特定页面的 “编辑页面” 链接,或提供此页面内容可编辑的备用 URL。 + +### `head` + +**类型:** [`HeadConfig[]`](/zh-cn/reference/configuration/#headconfig) + +你可以使用 `<head>` frontmatter 字段向页面的`<head>`添加其他标签。这意味着你可以将自定义样式、元数据或其他标签添加到单个页面。类似于[全局 `head` 选项](/zh-cn/reference/configuration/#head)。 + +```md +--- +# src/content/docs/example.md +title: 关于我们 +head: + # 使用自定义 <title> 标签 + - tag: title + content: 自定义关于我们页面标题 +--- +``` + +### `tableOfContents` + +**类型:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` + +覆盖[全局 `tableOfContents` 配置](/zh-cn/reference/configuration/#tableofcontents)。自定义要包含的标题级别,或设置为 `false` 以在此页面上隐藏目录。 + +```md +--- +# src/content/docs/example.md +title: 目录中只有 H2 的页面 +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 2 +--- +``` + +```md +--- +# src/content/docs/example.md +title: 没有目录的页面 +tableOfContents: false +--- +``` + +### `template` + +**类型:** `'doc' | 'splash'` +**默认值:** `'doc'` + +为页面选择布局模板。 +页面默认使用 `'doc'` 布局。 +设置为 `'splash'` 以使用没有任何侧边栏的更宽的布局,该布局专为落地页设计。 + +### `hero` + +**类型:** [`HeroConfig`](#heroconfig) + +添加一个 hero 组件到页面顶部。与 `template: splash` 配合使用效果更佳。 + +例如,此配置显示了一些常见选项,包括从你的仓库加载图像。 + +```md +--- +# src/content/docs/example.md +title: 我的主页 +template: splash +hero: + title: '我的项目: Stellar Stuff Sooner' + tagline: 把你的东西带到月球上,眨眼间又回来。 + image: + alt: 一个闪闪发光、色彩鲜艳的标志 + file: ../../assets/logo.png + actions: + - text: 告诉我更多 + link: /getting-started/ + icon: right-arrow + - text: 在 GitHub 上查看 + link: https://github.com/astronaut/my-project + icon: external + variant: minimal + attrs: + rel: me +--- +``` + +你可以在浅色和深色模式下显示不同版本的 hero 图像。 + +```md +--- +# src/content/docs/example.md +hero: + image: + alt: 一个闪闪发光、色彩鲜艳的 logo + dark: ../../assets/logo-dark.png + light: ../../assets/logo-light.png +--- +``` + +#### `HeroConfig` + +```ts +interface HeroConfig { + title?: string; + tagline?: string; + image?: + | { + // 你的仓库中的图像的相对路径。 + file: string; + // 使图像对辅助技术可访问的 Alt 文本 + alt?: string; + } + | { + // 使用深色模式的图像的相对路径。 + dark: string; + // 使用浅色模式的图像的相对路径。 + light: string; + // 使图像对辅助技术可访问的 Alt 文本 + alt?: string; + } + | { + // 用于图像插槽的原始 HTML 。 + // 可以是自定义的 `<img>` 标签或内联的 `<svg>`。 + html: string; + }; + actions?: Array<{ + text: string; + link: string; + variant?: 'primary' | 'secondary' | 'minimal'; + icon?: string; + attrs?: Record<string, string | number | boolean>; + }>; +} +``` + +### `banner` + +**类型:** `{ content: string }` + +在此页面顶部显示公告横幅。 + +`content` 的值可以包含链接或其他内容的 HTML。 +例如,此页面显示了一个横幅,其中包含指向 `example.com` 的链接。 + +```md +--- +# src/content/docs/example.md +title: 带有横幅的页面 +banner: + content: | + 我们刚刚发布了一下非常酷的东西! + <a href="https://example.com">点击查看!</a> +--- +``` + +### `lastUpdated` + +**类型:** `Date | boolean` + +覆盖[全局 `lastUpdated` 配置](/zh-cn/reference/configuration/#lastupdated)。如果指定了日期,它必须是有效的 [YAML 时间戳](https://yaml.org/type/timestamp.html),并将覆盖存储在 Git 历史记录中的此页面的日期。 + +```md +--- +# src/content/docs/example.md +title: 带有自定义更新日期的页面 +lastUpdated: 2022-08-09 +--- +``` + +### `prev` + +**类型:** `boolean | string | { link?: string; label?: string }` + +覆盖[全局 `pagination` 配置](/zh-cn/reference/configuration/#pagination)。如果指定了字符串,则将替换生成的链接文本;如果指定了对象,则将同时覆盖链接和文本。 + +```md +--- +# src/content/docs/example.md +# 隐藏上一页链接 +prev: false +--- +``` + +```md +--- +# src/content/docs/example.md +# 将上一页链接更改为“继续教程” +prev: 继续教程 +--- +``` + +```md +--- +# src/content/docs/example.md +# 同时覆盖上一页的链接和文本 +prev: + link: /unrelated-page/ + label: 一个不相关的页面 +--- +``` + +### `next` + +**类型:** `boolean | string | { link?: string; label?: string }` + +和 [`prev`](#prev) 一样,但是用于下一页链接。 + +```md +--- +# src/content/docs/example.md +# 隐藏下一页链接 +next: false +--- +``` + +### `pagefind` + +**类型:** `boolean` +**默认值:** `true` + +设置此页面是否应包含在 [Pagefind](https://pagefind.app/) 搜索索引中。设置为 `false` 以从搜索结果中排除页面: + +```md +--- +# src/content/docs/example.md +# 在搜索索引中隐藏此页面 +pagefind: false +--- +``` + +### `draft` + +**类型:** `boolean` +**默认值:** `false` + +设置此页面是否应被视为草稿,并且不包含在 [生产版本](https://docs.astro.build/zh-cn/reference/cli-reference/#astro-build)。设置为 `true` 可将页面标记为草稿,并使其仅在开发过程中可见。 + +```md +--- +# src/content/docs/example.md +# 从生产版本中排除此页面 +draft: true +--- +``` + +因为草稿页面并不包含在构建输出中,所以你无法使用 [slug](/zh-cn/guides/sidebar/#内部链接) 直接将草稿页面添加到网页中。目录中用于 [自动生成侧边栏](/zh-cn/guides/sidebar/#自动生成的分组) 的草稿页面在生产版本中自动排除。 + +### `sidebar` + +**类型:** [`SidebarConfig`](#sidebarconfig) + +在使用自动生成的链接分组时,控制如何在[侧边栏](/zh-cn/reference/configuration/#sidebar)中显示此页面。 + +#### `SidebarConfig` + +```ts +interface SidebarConfig { + label?: string; + order?: number; + hidden?: boolean; + badge?: string | BadgeConfig; + attrs?: Record<string, string | number | boolean | undefined>; +} +``` + +#### `label` + +**类型:** `string` +**默认值:** 页面 [`title`](#title-必填) + +在自动生成的链接组中显示时,设置侧边栏中此页面的标签。 + +```md +--- +# src/content/docs/example.md +title: 关于此项目 +sidebar: + label: About +--- +``` + +#### `order` + +**类型:** `number` + +当对链接组进行自动生成排序时,控制此页面的顺序。 +数字越小,链接组中显示得越高。 + +```md +--- +# src/content/docs/example.md +title: 要首先显示的页面 +sidebar: + order: 1 +--- +``` + +#### `hidden` + +**类型:** `boolean` +**默认值:** `false` + +防止此页面包含在自动生成的侧边栏组中。 + +```md +--- +# src/content/docs/example.md +title: 从自动生成的侧边栏中隐藏的页面 +sidebar: + hidden: true +--- +``` + +#### `badge` + +**类型:** <code>string | <a href="/zh-cn/reference/configuration/#badgeconfig">BadgeConfig</a></code> + +当在自动生成的链接组中显示时,在侧边栏中为页面添加徽章。 + +当使用字符串时,徽章将显示为默认的强调色。可选择的,传递一个 [`BadgeConfig` 对象](/zh-cn/reference/configuration/#badgeconfig) ,其中包含 `text`、`variant` 和 `class` 字段,可以自定义徽章。 + +```md +--- +# src/content/docs/example.md +title: 带有徽章的页面 +sidebar: + # 使用与你的网站的强调色相匹配的默认类型 + badge: 新增 +--- +``` + +```md +--- +# src/content/docs/example.md +title: 带有徽章的页面 +sidebar: + badge: + text: 实验性 + variant: caution +--- +``` + +#### `attrs` + +**类型:** `Record<string, string | number | boolean | undefined>` + +给自动生成的侧边栏分组的链接添加的 HTML 属性。 + +```md +--- +# src/content/docs/example.md +title: 新标签页中打开页面 +sidebar: + # 在新标签页中打开页面 + attrs: + target: _blank +--- +``` + +## 自定义 frontmatter schema + +Starlight 的 `docs` 内容集合的 frontmatter schema 在 `src/content.config.ts` 中使用 `docsSchema()` 辅助函数进行配置: + +```ts {4,7} +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; +``` + +了解更多关于内容集合模式的信息,请参阅 Astro 文档中的 [“定义集合模式”](https://docs.astro.build/zh-cn/guides/content-collections/#定义集合模式schema) 部分。 + +`docsSchema()` 采用以下选项: + +### `extend` + +**类型:** Zod schema 或者返回 Zod schema 的函数 +**默认值:** `z.object({})` + +通过在 `docsSchema()` 选项中设置 `extend` 来使用其他字段扩展 Starlight 的 schema。 +值应该是一个 [Zod schema](https://docs.astro.build/zh-cn/guides/content-collections/#用-zod-定义数据类型)。 + +在下面的示例中,我们为 `description` 提供了一个更严格的类型,使其成为必填项,并添加了一个新的可选的 `category` 字段: + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: z.object({ + // 将内置字段设置为必填项。 + description: z.string(), + // 将新字段添加到 schema 中。 + category: z.enum(['tutorial', 'guide', 'reference']).optional(), + }), + }), + }), +}; +``` + +要利用 [Astro `image()` 辅助函数](https://docs.astro.build/zh-cn/guides/images/#内容集合中的图像),请使用返回 schema 扩展的函数: + +```ts {10-15} +// src/content.config.ts +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + extend: ({ image }) => { + return z.object({ + // 添加一个必须解析为本地图像的字段。 + cover: image(), + }); + }, + }), + }), +}; +``` diff --git a/docs/src/content/docs/zh-cn/reference/icons.mdx b/docs/src/content/docs/zh-cn/reference/icons.mdx new file mode 100644 index 00000000000..11701a82566 --- /dev/null +++ b/docs/src/content/docs/zh-cn/reference/icons.mdx @@ -0,0 +1,32 @@ +--- +title: 图标参考 +description: Starlight 中所有可用图标的概述。 +--- + +Starlight 提供了一组内置图标,你可以使用 `<Icon>` 组件在内容中显示这些图标。 + +## 使用图标 + +可以使用 [`<Icon>`](/zh-cn/components/icons/) 组件来显示图标。 +图标也常用于其他组件,例如 [卡片](/zh-cn/components/cards/) 或 [hero actions](/zh-cn/reference/frontmatter/#hero) 等设置。 + +## `StarlightIcon` 类型 + +使用 `StarlightIcon` TypeScript 类型来引用 [Starlight 的内置图标的名称](#所有图标)。 + +```ts {2} /icon: (StarlightIcon)/ +// src/icon.ts +import type { StarlightIcon } from '@astrojs/starlight/types'; + +function getIconLabel(icon: StarlightIcon) { + // … +} +``` + +## 所有图标 + +下面显示了所有可用图标,包括它们对应名称的列表。单击图标将其名称复制到剪贴板。 + +import IconsList from '~/components/icons-list.astro'; + +<IconsList labels={{ copied: '已复制!' }} /> diff --git a/docs/src/content/docs/zh-cn/reference/overrides.md b/docs/src/content/docs/zh-cn/reference/overrides.md new file mode 100644 index 00000000000..71cc7249be1 --- /dev/null +++ b/docs/src/content/docs/zh-cn/reference/overrides.md @@ -0,0 +1,261 @@ +--- +title: 重写参考 +description: Starlight 支持重写的组件以及组件参数的概述。 +tableOfContents: + maxHeadingLevel: 4 +--- + +你可以通过在 Starlight 的 [`components`](/zh-cn/reference/configuration/#components) 配置选项中提供替代组件的路径来替换掉 (即重写) Starlight 的内置组件。 +本页面列出了所有可被重写的组件和它们默认实现的 GitHub 链接。 + +在[重写组件指南](/zh-cn/guides/overriding-components/)中了解更多。 + +## 组件 + +### 头部 + +这些组件在每个页面的 `<head>` 元素内渲染。 +它们应只包含[允许在 `<head>` 中使用的元素](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/head#相关链接)。 + +#### `Head` + +**默认组件:** [`Head.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Head.astro) + +在每个页面的 `<head>` 元素内渲染的组件。 + +重写此组件应作为最后手段。 +如果可能,请优先使用 [`head` 配置项](/zh-cn/reference/configuration/#head),[`head` frontmatter 字段](/zh-cn/reference/frontmatter/#head),或者使用 [路由数据中间件](/zh-cn/guides/route-data/#自定义路由数据) 来自定义默认组件渲染的路由数据。 + +#### `ThemeProvider` + +**默认组件:** [`ThemeProvider.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeProvider.astro) + +在 `<head>` 内渲染的用于提供暗色/亮色主题支持的组件。 +默认实现包括一个内联脚本和一个 `<template>`,该脚本在 [`<ThemeSelect />`](#themeselect) 中使用该模板。 + +--- + +### 无障碍 + +#### `SkipLink` + +**默认组件:** [`SkipLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SkipLink.astro) + +在 `<body>` 内渲染的第一个元素,它链接到主页面内容以实现无障碍访问。 +默认实现默认为隐藏状态,只有在用户使用键盘通过 tab 键聚焦到它时才会显示。 + +--- + +### 布局 + +这些组件负责在不同的断点 (breakpoints) 上布局 Starlight 的组件、管理视图。 +重写这些组件会有很大的复杂性。 +如果可能,请优先重写较低级别的组件。 + +#### `PageFrame` + +**默认组件:** [`PageFrame.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageFrame.astro) +**命名插槽:** `header`, `sidebar` + +包在绝大部分页面内容外的布局组件。 +默认实现提供了头部—侧边栏—主内容的布局,并包含 `header` 和 `sidebar` 命名插槽以及主内容的默认插槽。 +它还渲染了 [`<MobileMenuToggle />`](#mobilemenutoggle) 以支持在小 (移动) 视口 (viewports) 上切换侧边栏导航。 + +#### `MobileMenuToggle` + +**默认组件:** [`MobileMenuToggle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuToggle.astro) + +在 [`<PageFrame>`](#pageframe) 内渲染的负责在小 (移动) 视口上切换侧边栏导航的组件。 + +#### `TwoColumnContent` + +**默认组件:** [`TwoColumnContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TwoColumnContent.astro) +**命名插槽:** `right-sidebar` + +包在主内容列和右侧栏 (目录) 外的布局组件。 +默认实现实现了在单列、小视口布局和两列、较大视口布局之间的切换。 + +--- + +### 导航 + +这些组件渲染 Starlight 的顶部导航栏。 + +#### `Header` + +**默认组件:** [`Header.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Header.astro) + +在每个页面顶部显示的导航栏组件。 +默认实现显示了 [`<SiteTitle />`](#sitetitle)、[`<Search />`](#search)、[`<SocialIcons />`](#socialicons)、[`<ThemeSelect />`](#themeselect) 和 [`<LanguageSelect />`](#languageselect)。 + +#### `SiteTitle` + +**默认组件:** [`SiteTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SiteTitle.astro) + +在导航栏开头渲染的组件,用于渲染站点标题。 +默认实现包含在 Starlight 配置中定义的 logo 的渲染逻辑。 + +#### `Search` + +**默认组件:** [`Search.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Search.astro) + +用于渲染 Starlight 搜索 UI 的组件。 +默认实现包含在导航栏中的按钮和在点击时显示搜索模态框以及加载 [Pagefind UI](https://pagefind.app/) 的代码。 + +当 [`pagefind`](/zh-cn/reference/configuration/#pagefind) 被禁用时,默认的搜索组件不会被渲染。 +然而,如果你重写了 `Search`,你的自定义组件将总是被渲染,即使 `pagefind` 配置选项是 `false`。 +这允许你在禁用 Pagefind 时为其他搜索提供商添加 UI。 + +#### `SocialIcons` + +**默认组件:** [`SocialIcons.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/SocialIcons.astro) + +在导航栏中渲染的组件,用于渲染社交图标链接。 +默认实现使用 Starlight 配置中的 [`social`](/zh-cn/reference/configuration/#social) 选项来渲染图标和链接。 + +#### `ThemeSelect` + +**默认组件:** [`ThemeSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeSelect.astro) + +在导航栏中渲染的组件,用于允许用户选择深浅主题偏好。 + +#### `LanguageSelect` + +**默认组件:** [`LanguageSelect.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LanguageSelect.astro) + +在导航栏中渲染的组件,用于允许用户切换到不同的语言。 + +--- + +### 全局侧边栏 + +Starlight 的全局侧边栏包含了主站点导航。 +在较窄的视口上,它会隐藏在下拉菜单中。 + +#### `Sidebar` + +**默认组件:** [`Sidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Sidebar.astro) + +在页面内容之前渲染的包含全局导航的组件。 +默认实现在足够宽的视口上显示为侧边栏,在小 (移动) 视口上显示为下拉菜单。 +它还渲染了 [`<MobileMenuFooter />`](#mobilemenufooter) 以在移动菜单中显示额外的项目。 + +#### `MobileMenuFooter` + +**默认组件:** [`MobileMenuFooter.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuFooter.astro) + +在移动下拉菜单最底部中渲染的组件。 +默认实现渲染了 [`<ThemeSelect />`](#themeselect) 和 [`<LanguageSelect />`](#languageselect)。 + +--- + +### 页面侧边栏 + +Starlight 的页面侧边栏负责显示当前页面的子标题的目录。 +在较窄的视口上,它会缩为一个固定的下拉菜单。 + +#### `PageSidebar` + +**默认组件:** [`PageSidebar.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageSidebar.astro) + +在页面内容之前渲染的包含目录的组件。 +默认实现渲染了 [`<TableOfContents />`](#tableofcontents) 和 [`<MobileTableOfContents />`](#mobiletableofcontents)。 + +#### `TableOfContents` + +**默认组件:** [`TableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/TableOfContents.astro) + +在较宽的视口上渲染当前页面的目录的组件。 + +#### `MobileTableOfContents` + +**默认组件:** [`MobileTableOfContents.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileTableOfContents.astro) + +在小 (移动) 视口上渲染当前页面的目录的组件。 + +--- + +### 内容 + +这些组件在页面主内容列中渲染。 + +#### `Banner` + +**默认组件:** [`Banner.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Banner.astro) + +横幅 (Banner) 组件在每个页面的顶部渲染。 +默认实现使用页面的 [`banner`](/zh-cn/reference/frontmatter/#banner) frontmatter 值来决定是否渲染。 + +#### `ContentPanel` + +**默认组件:** [`ContentPanel.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/ContentPanel.astro) + +包在页面主内容列中的段落外的布局组件。 + +#### `PageTitle` + +**默认组件:** [`PageTitle.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageTitle.astro) + +包含当前页面的 `<h1>` 元素的组件。 + +自定义实现应确保在 `<h1>` 元素上设置 `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) + +在本页面当前语言没有翻译时显示给用户的通知。 +仅在多语言站点中使用。 + +#### `Hero` + +**默认组件:** [`Hero.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Hero.astro) + +当设置了 frontmatter 中的 [`hero`](/zh-cn/reference/frontmatter/#hero) 时在页面顶部渲染的组件。 +默认实现显示了一个大标题、标语、动作链接 (call-to-action links) 和可选的图片。 + +#### `MarkdownContent` + +**默认组件:** [`MarkdownContent.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/MarkdownContent.astro) + +在页面主内容列中渲染 Markdown 内容的组件。 +默认实现为 Markdown 内容提供了基本的样式。 + +Markdown 内容样式也暴露在 `@astrojs/starlight/style/markdown.css` 中,并且作用域限制在 `.sl-markdown-content` CSS 类中。 + +--- + +### 页脚 + +这些组件在页面主内容列的底部渲染。 + +#### `Footer` + +**默认组件:** [`Footer.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Footer.astro) + +页脚 (Footer) 组件在每个页面的底部渲染。 +默认实现显示了 [`<LastUpdated />`](#lastupdated)、[`<Pagination />`](#pagination) 和 [`<EditLink />`](#editlink)。 + +#### `LastUpdated` + +**默认组件:** [`LastUpdated.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/LastUpdated.astro) + +在页脚中渲染的组件,用于显示最后更新日期。 + +#### `EditLink` + +**默认组件:** [`EditLink.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/EditLink.astro) + +在页脚中渲染的组件,用于显示指向页面编辑地址的链接。 + +#### `Pagination` + +**默认组件:** [`Pagination.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Pagination.astro) + +在页脚中渲染的组件,用于显示上一页和下一页的导航箭头。 diff --git a/docs/src/content/docs/zh-cn/reference/plugins.md b/docs/src/content/docs/zh-cn/reference/plugins.md new file mode 100644 index 00000000000..59d537597ce --- /dev/null +++ b/docs/src/content/docs/zh-cn/reference/plugins.md @@ -0,0 +1,375 @@ +--- +title: 插件参考 +description: Starlight 的插件 API 的概述 +tableOfContents: + maxHeadingLevel: 4 +--- + +Starlight 插件可以自定义 Starlight 的配置、UI 和行为,同时也易于共享和重用。 +本参考页面记录了插件可以使用的 API。 + +在 [配置参考](/zh-cn/reference/configuration/#plugins) 中了解更多关于使用 Starlight 插件的内容。 +或者访问 [插件 showcase](/zh-cn/resources/plugins/#插件) 来查看可用插件的列表。 + +## 快速 API 参照 + +一个 Starlight 插件的形状如下。 +请参阅下面的不同属性和钩子参数的详细信息。 + +<!-- prettier-ignore-start --> +```ts +interface StarlightPlugin { + name: string; + hooks: { + 'i18n:setup'?: (options: { + injectTranslations: ( + translations: Record<string, Record<string, string>> + ) => void; + }) => void | Promise<void>; + 'config:setup': (options: { + config: StarlightUserConfig; + updateConfig: (newConfig: StarlightUserConfig) => void; + addIntegration: (integration: AstroIntegration) => void; + addRouteMiddleware: (config: { entrypoint: string; order?: 'pre' | 'post' | 'default' }) => void; + astroConfig: AstroConfig; + command: 'dev' | 'build' | 'preview'; + isRestart: boolean; + logger: AstroIntegrationLogger; + useTranslations: (lang: string) => I18nT; + absolutePathToLang: (path: string) => string; + }) => void | Promise<void>; + }; +} +``` +<!-- prettier-ignore-end --> + +## `name` + +**类型:** `string` + +一个插件必须提供一个描述它的唯一名字。该名字会在[输出与本插件有关的日志消息](#logger)时使用,并且可能被其他插件用于检测此插件是否存在。 + +## `hooks` + +钩子是 Starlight 在特定时机调用的插件函数。 + +要获取钩子的参数类型,请使用 `HookParameters` 工具类型并传入钩子名称。 +在下面的例子中,`options` 参数被类型化为与 `config:setup` 钩子传递的参数匹配: + +```ts +import type { HookParameters } from '@astrojs/starlight/types'; + +function configSetup(options: HookParameters['config:setup']) { + options.useTranslations('en'); +} +``` + +### `i18n:setup` + +当 Starlight 初始化时会调用插件国际化设置函数。 +`i18n:setup` 钩子可以用于注入翻译字符串,以便插件可以支持不同的语言环境。这些翻译字符串可以通过 [`useTranslations()`](#usetranslations) 在 `config:setup` 钩子中使用,也可以在 UI 组件中通过 [`Astro.locals.t()`](/zh-cn/guides/i18n/#使用-ui-翻译) 使用。 + +`i18n:setup` 钩子会传入以下选项: + +#### `injectTranslations` + +**类型:** `(translations: Record<string, Record<string, string>>) => void` + +一个回调函数,用于添加或更新 Starlight 的 [本地化 API](/zh-cn/guides/i18n/#使用-ui-翻译) 中使用的翻译字符串。 + +在下面的例子中,一个插件为名为 `myPlugin.doThing` 的自定义 UI 字符串注入翻译字符串,用于 `en` 和 `fr` 语言环境: + +```ts {6-13} /(injectTranslations)[^(]/ +// plugin.ts +export default { + name: 'plugin-with-translations', + hooks: { + 'i18n:setup'({ injectTranslations }) { + injectTranslations({ + en: { + 'myPlugin.doThing': 'Do the thing', + }, + fr: { + 'myPlugin.doThing': 'Faire le truc', + }, + }); + }, + }, +}; +``` + +要在插件 UI 中使用注入的翻译字符串,请遵循 [“使用 UI 翻译”](/zh-cn/guides/i18n/#使用-ui-翻译) 指南。 +如果你需要在插件的 [`config:setup`](#configsetup) 钩子中使用 UI 字符串,可以使用 [`useTranslations()`](#usetranslations) 回调。 + +插件注入的翻译字符串的类型会自动在用户项目中生成,但当在插件的代码库中工作时还不可用。 +要在插件的上下文中类型化 `locals.t` 对象,请在 TypeScript 声明文件中声明以下全局命名空间: + +```ts +// env.d.ts +declare namespace App { + type StarlightLocals = import('@astrojs/starlight').StarlightLocals; + // 在插件的上下文中定义 `locals.t` 对象。 + interface Locals extends StarlightLocals {} +} + +declare namespace StarlightApp { + // 在 `I18n` 接口中定义额外的插件翻译。 + interface I18n { + 'myPlugin.doThing': string; + } +} +``` + +如果你有一个包含你的翻译的对象,你也可以从源文件推断 `StarlightApp.I18n` 接口的类型。 + +例如,给定以下源文件: + +```ts title="ui-strings.ts" +export const UIStrings = { + en: { 'myPlugin.doThing': 'Do the thing' }, + fr: { 'myPlugin.doThing': 'Faire le truc' }, +}; +``` + +以下声明会从源文件中推断类型: + +```ts title="env.d.ts" +declare namespace StarlightApp { + type UIStrings = typeof import('./ui-strings').UIStrings.en; + interface I18n extends UIStrings {} +} +``` + +### `config:setup` + +插件配置设置函数会在 Starlight 初始化时调用(在 [`astro:config:setup`](https://docs.astro.build/zh-cn/reference/integrations-reference/#astroconfigsetup) 集成钩子期间)。 +`config:setup` 钩子可以用于更新 Starlight 配置或添加 Astro 集成。 + +这个钩子会被传入以下选项: + +#### `config` + +**类型:** `StarlightUserConfig` + +一个用户提供的 [Starlight 配置](/zh-cn/reference/configuration/)的只读副本。 +这个配置可能已经被当前插件之前的其他插件更新过了。 + +#### `updateConfig` + +**类型:** `(newConfig: StarlightUserConfig) => void` + +一个可以更新用户提供的 [Starlight 配置](/zh-cn/reference/configuration/)的回调函数。 +传入你想要覆盖的根级配置键。 +要更新嵌套的配置值,你必须提供整个嵌套对象。 + +要扩展现有的配置选项而不是覆盖它,可以将现有值展开到新值中。 +在下面的例子中,通过将 `config.social` 展开到新的 `social` 数组中,向现有配置添加了一个新的 [`social`](/zh-cn/reference/configuration/#social) 媒体账号: + +```ts {6-15} +// plugin.ts +export default { + name: 'add-twitter-plugin', + hooks: { + 'config:setup'({ config, updateConfig }) { + updateConfig({ + social: [ + ...config.social, + { + icon: 'twitter', + label: 'Twitter', + href: 'https://twitter.com/astrodotbuild', + }, + ], + }); + }, + }, +}; +``` + +#### `addIntegration` + +**类型:** `(integration: AstroIntegration) => void` + +一个添加插件所需的 [Astro 集成](https://docs.astro.build/zh-cn/reference/integrations-reference/)的回调函数。 + +在下面的例子中,插件首先检查是否已经配置了 [Astro 的 React 集成](https://docs.astro.build/zh-cn/guides/integrations-guide/react/),如果没有,就使用 `addIntegration()` 来添加它: + +```ts {14} "addIntegration," +// plugin.ts +import react from '@astrojs/react'; + +export default { + name: 'plugin-using-react', + hooks: { + 'config:setup'({ addIntegration, astroConfig }) { + const isReactLoaded = astroConfig.integrations.find( + ({ name }) => name === '@astrojs/react' + ); + + // 只在 React 集成没有已经被添加的时候添加它。 + if (!isReactLoaded) { + addIntegration(react()); + } + }, + }, +}; +``` + +#### `addRouteMiddleware` + +**类型:** `(config: { entrypoint: string; order?: 'pre' | 'post' | 'default' }) => void` + +一个回调函数,用于向站点添加 [路由中间件处理程序](/zh-cn/guides/route-data/)。 + +`entrypoint` 属性必须符合插件的中间件文件的模块规范,该文件导出一个 `onRequest` 处理程序。 + +在下面的例子中,一个名为 `@example/starlight-plugin` 的插件使用 npm 模块规范添加了一个路由中间件: + +```js {6-9} +// plugin.ts +export default { + name: '@example/starlight-plugin', + hooks: { + 'config:setup'({ addRouteMiddleware }) { + addRouteMiddleware({ + entrypoint: '@example/starlight-plugin/route-middleware', + }); + }, + }, +}; +``` + +##### 控制执行顺序 + +默认情况下,插件中间件按插件添加的顺序运行。 + +如果你需要更精细地控制中间件的执行顺序,可以使用可选的 `order` 属性。 +设置 `order: "pre"` 在用户中间件之前运行。 +设置 `order: "post"` 在所有其他中间件之后运行。 + +如果两个插件添加了具有相同 `order` 值的中间件,则先添加的插件将先运行。 + +#### `astroConfig` + +**类型:** `AstroConfig` + +一个用户提供的 [Astro 配置](https://docs.astro.build/zh-cn/reference/configuration-reference/)的只读副本。 + +#### `command` + +**类型:** `'dev' | 'build' | 'preview'` + +被用于运行 Starlight 的命令: + +- `dev` - 项目是用 `astro dev` 运行的 +- `build` - 项目是用 `astro build` 运行的 +- `preview` - 项目是用 `astro preview` 运行的 + +#### `isRestart` + +**类型:** `boolean` + +当开发服务器启动时为 `false`,当触发重新加载时为 `true`。 +触发重新加载的常见原因包括用户在开发服务器运行时编辑了他们的 `astro.config.mjs`。 + +#### `logger` + +**类型:** `AstroIntegrationLogger` + +一个 [Astro 集成日志记录器](https://docs.astro.build/zh-cn/reference/integrations-reference/#astrointegrationlogger)的实例,你可以用它来写日志。 +所有被记录的消息都会带有插件名字的前缀。 + +```ts {6} +// plugin.ts +export default { + name: 'long-process-plugin', + hooks: { + 'config:setup'({ logger }) { + logger.info('启动一个长流程…'); + // 一些很长的流程… + }, + }, +}; +``` + +上面的例子会记录一条下面这样的消息: + +```shell +[long-process-plugin] 启动一个长流程… +``` + +#### `useTranslations` + +**类型:** `(lang: string) => I18nT` + +使用 BCP-47 语言标签调用 `useTranslations()` 以生成一个工具函数,该函数提供对特定语言的 UI 字符串的访问。 +`useTranslations()` 返回一个等效于 `Astro.locals.t()` API 的工具函数,该 API 在 Astro 组件中可用。 +要了解更多可用的 API,请参阅 [“使用 UI 翻译”](/zh-cn/guides/i18n/#使用-ui-翻译) 指南。 + +```ts {6} +// plugin.ts +export default { + name: 'plugin-use-translations', + hooks: { + 'config:setup'({ useTranslations, logger }) { + const t = useTranslations('zh-CN'); + logger.info(t('builtWithStarlight.label')); + }, + }, +}; +``` + +上面的例子会记录一条包含简体中文语言的默认 UI 字符串的消息: + +```shell +[plugin-use-translations] 基于 Starlight 构建 +``` + +#### `absolutePathToLang` + +**类型:** `(path: string) => string` + +使用绝对文件路径调用 `absolutePathToLang()` 以获取该文件的语言。 + +这在添加 [remark 或 rehype 插件](https://docs.astro.build/zh-cn/guides/markdown-content/#markdown-plugins) 以处理 Markdown 或 MDX 文件时特别有用。 +这些插件使用的 [虚拟文件格式](https://github.com/vfile/vfile) 包括正在处理的文件的 [绝对路径](https://github.com/vfile/vfile#filepath),可以与 `absolutePathToLang()` 一起使用以确定文件的语言。 +返回的语言可以与 [`useTranslations()`](#usetranslations) 工具函数一起使用以获取该语言的 UI 字符串。 + +例如,给定以下 Starlight 配置: + +```js +starlight({ + title: 'My Docs', + defaultLocale: 'en', + locales: { + // English docs in `src/content/docs/en/` + en: { label: 'English' }, + // French docs in `src/content/docs/fr/` + fr: { label: 'Français', lang: 'fr' }, + }, +}); +``` + +一个插件可以使用它的绝对路径来确定文件的语言: + +```ts {6-8} /fr/ +// plugin.ts +export default { + name: 'plugin-use-translations', + hooks: { + 'config:setup'({ absolutePathToLang, useTranslations, logger }) { + const lang = absolutePathToLang( + '/absolute/path/to/project/src/content/docs/fr/index.mdx' + ); + const t = useTranslations(lang); + logger.info(t('aside.tip')); + }, + }, +}; +``` + +上面的例子会记录一条包含法语语言的默认 UI 字符串的消息: + +```shell +[plugin-use-translations] Astuce +``` diff --git a/docs/src/content/docs/zh-cn/reference/route-data.mdx b/docs/src/content/docs/zh-cn/reference/route-data.mdx new file mode 100644 index 00000000000..23f60cb62d4 --- /dev/null +++ b/docs/src/content/docs/zh-cn/reference/route-data.mdx @@ -0,0 +1,199 @@ +--- +title: 路由数据参考 +description: Starlight 的路由数据对象的完整参考文档。 +--- + +Starlight 的路由数据对象包含有关当前页面的信息。请在 [“路由数据”指南](/zh-cn/guides/route-data/) 中了解更多关于 Starlight 的数据模型如何工作的信息。 + +在 Astro 组件中,从 `Astro.locals.starlightRoute` 访问路由数据: + +```astro {4} +--- +// src/components/Custom.astro + +const { hasSidebar } = Astro.locals.starlightRoute; +--- +``` + +在 [路由中间件](/zh-cn/guides/route-data/#自定义路由数据) 中,从传递给你的中间件函数的上下文对象中访问路由数据: + +```ts {5} +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + const { hasSidebar } = context.locals.starlightRoute; +}); +``` + +## `starlightRoute` + +`starlightRoute` 对象具有以下属性: + +### `dir` + +**类型:** `'ltr' | 'rtl'` + +页面书写方向。 + +### `lang` + +**类型:** `string` + +此页面区域设置的 BCP-47 语言标记,例如 `en`、`zh-CN` 或 `pt-BR`。 + +### `locale` + +**类型:** `string | undefined` + +提供语言的基本路径。对于根语言环境的 slug,返回 `undefined`。 + +### `siteTitle` + +**类型:** `string` + +该页面区域设置的站点标题。 + +### `siteTitleHref` + +**类型:** `string` + +网站标题的 `href` 属性值,链接回主页,例如 `/`。对于多语言站点,这将包括当前区域设置,例如 `/en/` 或 `/zh-cn/`。 + +### `slug` + +**类型:** `string` + +该页面的 slug 由内容文件名生成。 + +此属性已弃用,并将在 Starlight 的未来版本中删除。通过使用 [Starlight 的 `docsLoader`](/zh-cn/manual-setup/#配置内容集合) 迁移到新的内容层 API,并使用 [`id`](#id) 属性代替。 + +### `id` + +**类型:** `string` + +此页面的 slug,或者如果使用 [`legacy.collections`](https://docs.astro.build/zh-cn/reference/legacy-flags/#集合) 标志,则基于内容文件名的此页面的唯一 ID。 + +### `isFallback` + +**类型:** `boolean | undefined` + +如果此页面在当前语言中未翻译,并且正在使用来自默认语言环境的回退内容,则为 `true`。 +仅在多语言站点中使用。 + +### `entryMeta` + +**类型:** `{ dir: 'ltr' | 'rtl'; lang: string }` + +页面内容的区域设置元数据。当页面使用回退内容时,可以与顶级区域设置值不同。 + +### `entry` + +当前页面的 Astro 内容集合条目。 +包括当前页面在 `entry.data` 中的 frontmatter 值。 + +```ts +entry: { + data: { + title: string; + description: string | undefined; + // 等等 + } +} +``` + +在 [Astro的集合条目类型参考](https://docs.astro.build/zh-cn/reference/modules/astro-content/#collectionentry) 中了解更多关于此对象结构的信息。 + +### `sidebar` + +**类型:** `SidebarEntry[]` + +此页面的网站导航侧边栏条目。 + +### `hasSidebar` + +**类型:** `boolean` + +是否在此页面上显示侧边栏。 + +### `pagination` + +**类型:** `{ prev?: Link; next?: Link }` + +如果启用了侧边栏,则链接到侧边栏中的上一页和下一页。 + +### `toc` + +**类型:** `{ minHeadingLevel: number; maxHeadingLevel: number; items: TocItem[] } | undefined` + +如果启用,则为此页面的目录。 + +### `headings` + +**类型:** `{ depth: number; slug: string; text: string }[]` + +从当前页面提取的所有 Markdown 标题的数组。如果要构建一个遵循 Starlight 配置选项的目录组件,请使用 [`toc`](#toc) + +### `lastUpdated` + +**类型:** `Date | undefined` + +JavaScript `Date` 对象,表示启用时此页面上次更新的时间。 + +### `editUrl` + +**类型:** `URL | undefined` + +如果启用,则用于编辑此页面的地址的 `URL` 对象。 + +### `head` + +**类型:** [`HeadConfig[]`](/zh-cn/reference/configuration/#headconfig) + +包含在当前页面 `<head>` 中的所有标签的数组。包括重要的标签,如 `<title>` 和 `<meta charset="utf-8">`。 + +## 工具函数 + +### `defineRouteMiddleware()` + +使用 `defineRouteMiddleware()` 工具函数来帮助定义你的路由中间件模块: + +```ts "defineRouteMiddleware" +// src/routeData.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; + +export const onRequest = defineRouteMiddleware((context) => { + // ... +}); +``` + +### `StarlightRouteData` 类型 + +如果您正在编写需要使用 Starlight 路由数据的代码,您可以导入 `StarlightRouteData` 类型来匹配 `Astro.locals.starlightRoute` 的结构。 + +在下面的例子中,`usePageTitleInTOC()` 函数更新路由数据,以使用当前页面的标题作为目录中第一个项目的标签,替换默认的 “Overview” 标签。 +`StarlightRouteData` 类型允许你检查路由数据更改是否有效。 + +```ts "StarlightRouteData" +// src/route-utils.ts +import type { StarlightRouteData } from '@astrojs/starlight/route-data'; + +export function usePageTitleInTOC(starlightRoute: StarlightRouteData) { + const overviewLink = starlightRoute.toc?.items[0]; + if (overviewLink) { + overviewLink.text = starlightRoute.entry.data.title; + } +} +``` + +然后可以从路由中间件调用此函数: + +```ts {3,6} +// src/route-middleware.ts +import { defineRouteMiddleware } from '@astrojs/starlight/route-data'; +import { usePageTitleInTOC } from './route-utils'; + +export const onRequest = defineRouteMiddleware((context) => { + usePageTitleInTOC(context.locals.starlightRoute); +}); +``` diff --git a/docs/src/content/docs/zh-cn/resources/community-content.mdx b/docs/src/content/docs/zh-cn/resources/community-content.mdx new file mode 100644 index 00000000000..78b635ffcb6 --- /dev/null +++ b/docs/src/content/docs/zh-cn/resources/community-content.mdx @@ -0,0 +1,176 @@ +--- +title: 社区内容 +description: 发现社区制作的指南、文章和视频,以帮助你学习和构建 Starlight! +--- + +:::tip[添加你自己的!] +你是否制作过关于 Starlight 的内容? +创建一个 PR 来添加链接到此页面! +::: + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +## 文章和评论 + +以下是一系列帖子和文章,以了解有关 Starlight 和其他人的经历的更多信息: + +<CardGrid> + <LinkCard + href="https://devm.io/open-source/starlight-astro" + title="使用 Starlight 生成静态站点" + description="“在设计组件时,没有太大或太小的想法”——对 Starlight 负责人 Chris Swithinbank 的采访" + /> + <LinkCard + href="https://frontendatscale.com/blog/hybrid-frontend-architecture/" + title="使用 Astro 和 Starlight 的混合前端架构" + description="Maxi Ferreira 和 Ben Holmes 使用 Starlight、TinaCMS 和具有身份验证功能的交互式 API Playground 构建了一个文档站点。" + /> + <LinkCard + href="https://www.olets.dev/posts/comparing-docs-site-builders-vuepress-vs-starlight/" + title="比较文档网站构建工具:VuePress 与 Starlight" + description="这两个框架如何衡量?" + /> + <LinkCard + href="https://astro.build/case-studies/wp-engine/" + title="案例研究:削减开发成本" + description="WP Engine 是如何通过 Astro 的 Starlight 来降低超过 50% 的开发成本的。" + /> + <LinkCard + href="https://maciekpalmowski.dev/blog/building-a-documentation-site-using-astro-starlight/" + title="使用 Astro Starlight 来构建文档网站" + description="Maciek Palmowski 描述了他是如何将 Patchstack 的文档迁移到 Starlight 的。" + /> + <LinkCard + href="https://blog.cloudflare.com/open-source-all-the-way-down-upgrading-our-developer-documentation/" + title="一路开源" + description="Cloudflare 是如何使用 Starlight 来升级他们的开发者文档的。" + /> + <LinkCard + href="https://starlight-changelog.netlify.app/" + title="Starlight Changelog" + description="在一个精美的页面上查看 @astrojs/starlight 包的所有发布版本。" + /> +</CardGrid> + +## 方案和指南 + +方案通常是短小的、专注的指南,指导读者完成特定任务的工作示例。通过按照逐步说明完成,方案是向 Starlight 项目添加新功能或行为的绝佳方式!其他指南可能会解释与内容领域相关的概念,例如使用图像或使用 MDX。 + +浏览由 Starlight 用户维护的社区内容: + +<CardGrid> + <LinkCard + href="https://www.webpro.nl/scraps/versioned-docs-with-starlight-and-vercel" + title="Starlight & Vercel 的版本化文档" + description="为项目的每个主要版本实现单独版本的文档的指南" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-heading-links" + title="添加指向 Starlight 标题的链接" + description="使用 rehype 插件共享文档特定部分链接的指南" + /> + <LinkCard + href="https://blog.otterlord.dev/posts/starlight-sponsors/" + title="将赞助商添加到你的 Starlight 网站" + description="在文档侧边栏中实现自定义赞助商组件的指南" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-og-images" + title="将 Open Graph 图像添加到 Starlight" + description="为你的网页生成社交图像和相应 meta 标签的指南" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-third-party-icon-sets" + title="在 Starlight 中使用第三方图标集" + description="使用 unplugin-icons 扩展 Starlight 可用图标选择的指南" + /> + <LinkCard + href="https://hideoo.dev/notes/starlight-custom-html-head" + title="编辑 Starlight 页面的 HTML head 部分" + description="了解如何添加常见的 head 内容,例如 Web 分析、字体和脚本" + /> + <LinkCard + href="https://dev.to/mrrobot/publishing-documentation-with-astro-starlight-691" + title="使用 Astro Starlight 发布文档" + description="开始使用 Starlight 文档" + /> + <LinkCard + href="https://events-3bg.pages.dev/jotter/starlight/guide/" + title="启用视图过渡" + description="通过 Bag of Tricks 的视图过渡支持,获得 SPA 一样的观感" + /> + <LinkCard + href="https://jamcomments.com/posts/structured-data-with-starlight" + title="向 Starlight 页面添加结构化数据" + description="了解如何为你的文档页面构建动态的 JSON-LD 结构化数据。" + /> + <LinkCard + href="https://starlight-examples.netlify.app/" + title="Starlight 示例" + description="这是一组 StackBlitz 嵌入示例,展示了在 Starlight 文档网站中各种实用的操作方法。" + /> +</CardGrid> + +## 视频内容 + +发现 Starlight 内容的视频和频道,包括直播和教育内容。 + +import YouTubeGrid from '~/components/youtube-grid.astro'; + +### Astro 视频 + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=5u0Ds7wzUeI', + title: '基于 Astro 的 Starlight', + description: '观看 Starlight 官方发布视频', + }, + { + href: 'https://www.youtube.com/shorts/zjOWezSzd18', + title: '🌟 1分钟内启动', + description: '观看 Ben 在不到一分钟的时间内推出新的 Starlight 网站!', + }, + ]} +/> + +### 社区视频和直播 + +<YouTubeGrid + videos={[ + { + href: 'https://www.youtube.com/watch?v=sF6UcV3moZg', + title: '使用 Starlight 和 Astro 构建文档', + description: + '观看 Chris 和 Alex 通过 CodingCat.dev 深入研究 Starlight 代码。', + }, + { + href: 'https://www.youtube.com/watch?v=sWkkHbwDeQc', + title: 'Astro Starlight', + description: '在不到一分钟的时间内介绍 Starlight。', + }, + { + href: 'https://www.youtube.com/watch?v=-Ki-1E5gNCk', + title: 'Astro Starlight 文档模板(构建自定义 app 文档!)', + description: '在大约 5 分钟内启动并运行新的 Starlight 网站', + }, + { + href: 'https://www.youtube.com/watch?v=12o7WxjAxjM', + title: '使用代理将 Starlight 文档包含在 Next.js 项目中', + description: '将 Starlight 设置为 Next.js 网站内的子目录项目', + }, + { + href: 'https://www.youtube.com/watch?v=5pq80drDrNs', + title: '我用这个神奇的工具在 30 分钟内重建了 Shadcn 的文档', + description: + '在这个视频中,我将介绍 Starlight 的酷炫之处以及为什么你可能想在下一个项目中尝试它。', + }, + { + href: 'https://www.youtube.com/watch?v=Q1E4Gkt63ko', + title: + '与 Chris Swithinbank 一起试试联动 Astro Starlight 和 emoji-blast ', + description: + 'Astro Starlight 框架的开发者 Chris 引导我完成了一个全新的 emoji-blast 网站。 🌟 🎇', + }, + ]} +/> diff --git a/docs/src/content/docs/zh-cn/resources/plugins.mdx b/docs/src/content/docs/zh-cn/resources/plugins.mdx new file mode 100644 index 00000000000..4eac05fd337 --- /dev/null +++ b/docs/src/content/docs/zh-cn/resources/plugins.mdx @@ -0,0 +1,214 @@ +--- +title: 插件和集成 +description: 发现扩展 Starlight 的插件和集成等社区工具! +sidebar: + order: 1 +--- + +:::tip[添加你自己的!] +你是否构建过 Starlight 插件或 Starlight 工具? +创建一个 PR 来添加链接到此页面! +::: + +## 插件 + +[插件](/zh-cn/reference/plugins/) 可以自定义 Starlight 的配置、UI 和行为,同时也易于共享和复用。使用 Starlight 团队支持的官方插件和由 Starlight 用户维护的社区插件扩展你的网站。 + +### 官方插件 + +<CardGrid> + <LinkCard + href="/zh-cn/guides/site-search/#algolia-docsearch" + title="Algolia DocSearch" + description="将默认搜索 provider Pagefind 替换为 Algolia DocSearch。" + /> +</CardGrid> + +### 社区插件 + +<CardGrid> + <LinkCard + href="https://github.com/HiDeoo/starlight-links-validator" + title="starlight-links-validator" + description="在你的 Starlight 页面中检查损坏的链接" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-typedoc" + title="starlight-typedoc" + description=" 使用 TypeDoc 从 TypeScript 生成 Starlight 页面。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-blog" + title="starlight-blog" + description="添加一个博客到你的文档网站。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-openapi" + title="starlight-openapi" + description="从 OpenAPI/Swagger 规范创建文档页面。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-obsidian" + title="starlight-obsidian" + description="将 Obsidian vaults 发布到 Starlight 网站。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-image-zoom" + title="starlight-image-zoom" + description="为你的文档图像添加缩放功能。" + /> + <LinkCard + href="https://github.com/lorenzolewis/starlight-utils" + title="starlight-utils" + description="通过一系列常用工具扩展 Starlight。" + /> + <LinkCard + href="https://github.com/trueberryless/starlight-view-modes" + title="starlight-view-modes" + description="为你的文档网站添加不同的视图模式。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-versions" + title="starlight-versions" + description="版本化你的 Starlight 文档页面。" + /> + <LinkCard + href="https://inox-tools.fryuni.dev/star-warp" + title="star-warp" + description="为你的文档搜索结果添加曲速引擎。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-heading-badges" + title="starlight-heading-badges" + description="添加徽章到你的 Markdown 和 MDX 标题中。" + /> + <LinkCard + href="https://github.com/Fevol/starlight-site-graph" + title="starlight-site-graph" + description="在页面的侧边栏中添加一个交互式站点图。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-sidebar-topics" + title="starlight-sidebar-topics" + description="将你的文档分成不同的部分,每个部分都有自己的侧边栏。" + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown" + title="starlight-sidebar-topics-dropdown" + description="将你的文档页面拆分为多个子页面,并使用侧边栏中的下拉菜单在它们之间切换。" + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-cooler-credit" + title="starlight-cooler-credit" + description="为 Starlight 或 Astro 在目录的底部添加一个漂亮的 credit。" + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-contributor-list" + title="starlight-contributor-list" + description="在你项目中显示一个包含所有贡献者的列表。" + /> + <LinkCard + href="https://github.com/dragomano/starlight-giscus" + title="starlight-giscus" + description="将 Giscus 评论系统添加到你的文档网站。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-videos" + title="starlight-videos" + description="通过视频指南和课程增强你的文档。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-kbd" + title="starlight-kbd" + description="轻松绑定键盘快捷键。" + /> + <LinkCard + href="https://events-3bg.pages.dev/library/StarlightPlugin/" + title="starlight-view-transitions" + description="添加浏览器原生的跨文档视图过渡动画。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-auto-sidebar" + title="starlight-auto-sidebar" + description="调整自动生成的侧边栏组。" + /> + <LinkCard + href="https://github.com/delucis/starlight-llms-txt" + title="starlight-llms-txt" + description="基于 llmstxt.org 将 llms.txt 添加到你的文档站点。" + /> + <LinkCard + href="https://github.com/trueberryless-org/starlight-toc-overview-customizer" + title="starlight-toc-overview-customizer" + description="调整 Starlight的 目录,可自定义概述标题。" + /> + <LinkCard + href="https://delucis.github.io/starlight-markdown-blocks/" + title="starlight-markdown-blocks" + description="扩展 Starlight 的 Markdown 旁白语法,增加自定义块类型。" + /> + <LinkCard + href="https://github.com/WindMillCode/starlight-fullview-mode" + title="starlight-fullview-mode" + description="收起侧边栏,展开内容以获得全屏体验。" + /> + <LinkCard + href="https://github.com/frostybee/starlight-scroll-to-top" + title="starlight-scroll-to-top" + description="在你的文档网站添加一个滚动到顶部的按钮。" + /> +</CardGrid> + +## 社区工具和集成 + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +这些社区工具和集成可用于为你的 Starlight 网站添加新功能。 + +<CardGrid> + <LinkCard + href="https://www.feelback.dev/blog/new-astro-starlight-integration/" + title="FeelBack" + description="在文档页面中添加用户反馈系统。" + /> + <LinkCard + href="https://github.com/val-town/notion-to-astro" + title="notion-to-astro" + description="将 Notion 输出转换为 Astro Starlight 文档" + /> + <LinkCard + href="https://github.com/mattjennings/astro-live-code" + title="astro-live-code" + description="将你的 MDX 代码块渲染为交互式组件" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-i18n" + title="starlight-i18n" + description="帮助翻译 Starlight 页面的 Visual Studio Code 扩展" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-package-managers" + title="starlight-package-managers" + description="快速显示多个包管理器的 npm 相关命令。" + /> + <LinkCard + href="https://github.com/HiDeoo/starlight-showcases" + title="starlight-showcases" + description="一套 Starlight 组件,用于创建展示页面。" + /> + <LinkCard + href="https://github.com/HiDeoo/generator-starlight-plugin" + title="@hideoo/starlight-plugin" + description="一个快速搭建 Starlight 插件的生成器。" + /> + <LinkCard + href="https://github.com/Linkerin/starlight-to-pdf" + title="starlight-to-pdf" + description="一个用于将 Starlight 网页转换为 PDF 文件的命令行工具。" + /> + <LinkCard + href="https://github.com/joesaby/astro-plantuml" + title="astro-plantuml" + description="在 Markdown 代码块中渲染 PlantUML 内容。" + /> +</CardGrid> diff --git a/docs/src/content/docs/zh-cn/resources/showcase.mdx b/docs/src/content/docs/zh-cn/resources/showcase.mdx new file mode 100644 index 00000000000..8d43414b354 --- /dev/null +++ b/docs/src/content/docs/zh-cn/resources/showcase.mdx @@ -0,0 +1,21 @@ +--- +title: Starlight 展示 +description: 发现用 Starlight 构建的网站! +sidebar: + label: 网站展示 +--- + +:::tip[添加你自己的!] +你是否构建过 Starlight 网站? +[创建一个 PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#showcase) 来添加链接到此页面! +::: + +## 网站 + +import ShowcaseSites from '~/components/showcase-sites.astro'; + +Starlight 已投入生产。 这些是网络上的一些网站: + +<ShowcaseSites /> + +查看所有[在 GitHub 上使用 Starlight 的公共项目仓库](https://github.com/withastro/starlight/network/dependents)。 diff --git a/docs/src/content/docs/zh-cn/resources/themes.mdx b/docs/src/content/docs/zh-cn/resources/themes.mdx new file mode 100644 index 00000000000..8e43089b10a --- /dev/null +++ b/docs/src/content/docs/zh-cn/resources/themes.mdx @@ -0,0 +1,86 @@ +--- +title: 主题 +description: 使用社区主题为 Starlight 文档添加样式 +tableOfContents: false +sidebar: + order: 2 +head: + - tag: style + content: | + body { --sl-content-width: 66.75rem; } +--- + +import ThemeGrid from '~/components/theme-grid.astro'; + +主题是一个 Starlight 插件,它通过 [自定义 CSS](/zh-cn/guides/css-and-tailwind/)、[组件重写](/zh-cn/guides/overriding-components/) 或其他新功能来改变网站的视觉外观。 + +## 社区主题 + +安装由社区构建的主题,快速自定义网站的外观和风格。 + +<ThemeGrid + labels={{ + /** 主题切换按钮的无障碍标签。 */ + legend: '预览', + /** 深色配色方案变体的无障碍标签。 */ + dark: '深色', + /** 浅色主题变体的无障碍标签。 */ + light: '浅色', + }} + themes={[ + { + title: 'Starlight Rapide', + description: + 'Starlight 主题,灵感来源于 Visual Studio Code Vitesse 主题。', + href: 'https://starlight-theme-rapide.vercel.app/', + previews: { light: 'rapide-light.png', dark: 'rapide-dark.png' }, + }, + { + title: 'Starlight Obsidian Theme', + description: 'Starlight 主题,灵感来源于 Obsidian Publish 网站的风格。', + href: 'https://fevol.github.io/starlight-theme-obsidian/', + previews: { light: 'obsidian-light.png', dark: 'obsidian-dark.png' }, + }, + { + title: 'Catppuccin for Starlight', + description: '宁静的柔和色调的 Starlight 主题。', + href: 'https://starlight.catppuccin.com/', + previews: { light: 'catppuccin-light.png', dark: 'catppuccin-dark.png' }, + }, + { + title: 'Ion', + description: '一个时尚、现代的 Starlight 主题。', + href: 'https://louisescher.github.io/starlight-ion-theme/', + previews: { light: 'ion-light.png', dark: 'ion-dark.png' }, + }, + { + title: 'Starlight Black', + description: 'Starlight 主题,灵感来源于 shadcn 文档。', + href: 'https://starlight-theme-black.vercel.app/', + previews: { light: 'black-light.png', dark: 'black-dark.png' }, + }, + { + title: 'Starlight Flexoki', + description: '基于 Flexoki 配色方案的温暖友好主题。', + href: 'https://delucis.github.io/starlight-theme-flexoki/', + previews: { light: 'flexoki-light.png', dark: 'flexoki-dark.png' }, + }, + { + title: 'Starlight Nova', + description: '一个现代而美丽的 Starlight 主题。', + href: 'https://starlight-theme-nova.pages.dev/', + previews: { light: 'nova-light.png', dark: 'nova-dark.png' }, + }, + { + title: 'Starlight NextJS Theme', + description: 'Starlight 主题,灵感来源于 NextJS 文档。', + href: 'https://starlight-nextjs-theme.trueberryless.org/', + previews: { light: 'nextjs-light.png', dark: 'nextjs-dark.png' }, + }, + ]} +/> + +:::tip[添加你自己的!] +你构建了自己的 Starlight 主题吗? +[创建一个 PR](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#themes) 来添加你的主题到此页面! +::: diff --git a/docs/src/content/docs/zh/getting-started.mdx b/docs/src/content/docs/zh/getting-started.mdx deleted file mode 100644 index 0ac93fb94d5..00000000000 --- a/docs/src/content/docs/zh/getting-started.mdx +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: 开始使用 -description: 了解如何使用 Astro 的 Starlight 开始构建下一个文档站点。 ---- - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -## 创建一个新项目 - -Starlight 是一个基于 [Astro](https://astro.build) 框架构建的全功能文档主题。 - -你可以使用以下命令创建一个新的 Astro + Starlight 项目: - -<Tabs> -<TabItem label="npm"> - -```sh -# 使用 npm 创建一个新项目 -npm create astro@latest -- --template starlight -``` - -</TabItem> -<TabItem label="pnpm"> - -```sh -# 使用 pnpm 创建一个新项目 -pnpm create astro --template starlight -``` - -</TabItem> -<TabItem label="Yarn"> - -```sh -# 使用 yarn 创建一个新项目 -yarn create astro --template starlight -``` - -</TabItem> -</Tabs> - -这将创建一个新的 [项目目录](/zh/guides/project-structure/),其中包含你网站所需的所有文件和配置。 - -:::tip[查看实际效果] -在浏览器中尝试 Starlight: -[在 StackBlitz 上打开模板](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics)。 -::: - -## 使用 Starlight 创建内容 - -Starlight 已经准备好让你添加新的内容,或者将你现有的文件带过来! - -### 文件格式 - -Starlight 支持使用 Markdown 和 MDX 来编写内容。(你可以通过安装实验性的 [Astro Markdoc 集成](https://docs.astro.build/en/guides/integrations-guide/markdoc/) 来添加对 Markdoc 的支持。) - -### 添加页面 - -在 `src/content/docs/` 中创建 `.md` 或 `.mdx` 文件,就可以自动将新页面添加到你的站点中。添加子文件夹来组织你的文件,并创建多个路径段: - -``` -src/content/docs/hello-world.md => your-site.com/hello-world -src/content/docs/guides/faq.md => your-site.com/guides/faq -``` - -### 类型安全的 frontmatter - -所有 Starlight 页面都共享一个可自定义的 [frontmatter 属性集](/zh/reference/frontmatter/),用于控制页面的外观: - -```md ---- -title: Hello, World! -description: This is a page in my Starlight-powered site ---- -``` - -如果你忘记了任何重要的东西,Starlight 会提醒你。 - -## 部署你的 Starlight 网站 - -一旦你创建并自定义了你的 Starlight 网站,你就可以将它部署到你选择的 web 服务器或托管平台上,包括 Netlify、Vercel、GitHub Pages 等等。 - -[在 Astro 文档中了解如何部署 Astro 网站。](https://docs.astro.build/zh-cn/guides/deploy/) - -## 更新 Starlight - -:::tip[提示] -由于 Starlight 是 beta 软件,所以会经常更新和改进。请务必定期更新 Starlight! -::: - -Starlight 是一个 Astro 集成,可以像任何 `@astrojs/*` 集成一样更新: - -<Tabs> -<TabItem label="npm"> - -```sh -# 使用 npm 升级 Starlight -npm install @astrojs/starlight@latest -``` - -</TabItem> -<TabItem label="pnpm"> - -```sh -# 使用 pnpm 升级 Starlight -pnpm upgrade @astrojs/starlight --latest -``` - -</TabItem> -<TabItem label="Yarn"> - -```sh -# 使用 yarn 升级 Starlight -yarn upgrade @astrojs/starlight --latest -``` - -</TabItem> -</Tabs> - -你可以在 [Starlight 更新日志](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md) 中查看每个版本的变动列表。 - -## Starlight 故障排除 - -本站点的参考部分提供了 Starlight [项目配置](/zh/reference/configuration/)和[单个页面 frontmatter 配置](/zh/reference/frontmatter/)信息。使用这些页面来确保你的 Starlight 网站已正确配置和运行。 - -请参阅侧边栏中不断增长的指南列表,以获取有关添加内容和自定义 Starlight 网站的帮助。 - -如果你在这些文档中找不到答案,请访问[完整的 Astro 文档](https://docs.astro.build) 以获取完整的 Astro 文档。你的问题可能是通过了解 Starlight 主题下 Astro 的工作原理来解决的。 - -你也可以检查任何已知的 [GitHub 上的 Starlight issues](https://github.com/withastro/starlight/issues),并在 [Astro Discord](https://astro.build/chat/) 上从我们活跃的、友好的社区中获得帮助!在我们的 `#support` 论坛中发布带有 “starlight” 标签的问题,或者访问我们专门的 `#starlight` 频道来讨论当前的开发和更多内容! diff --git a/docs/src/content/docs/zh/guides/authoring-content.md b/docs/src/content/docs/zh/guides/authoring-content.md deleted file mode 100644 index 68eec5bd39b..00000000000 --- a/docs/src/content/docs/zh/guides/authoring-content.md +++ /dev/null @@ -1,208 +0,0 @@ ---- -title: 在 Markdown 中创作内容 -description: Starlight 支持的 Markdown 语法概述 ---- - -Starlight 支持在 `.md` 文件中使用完整的 [Markdown](https://daringfireball.net/projects/markdown/) 语法,以及使用 [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) 定义metadata 元数据,例如标题和描述。 - -如果使用这些文件格式,请务必检查 [MDX 文档](https://mdxjs.com/docs/what-is-mdx/#markdown) 或 [Markdoc 文档](https://markdoc.dev/docs/syntax),因为 Markdown 的支持和用法可能会有所不同。 - -## 内联样式 - -文本可以是**粗体**,_斜体_,或~~删除线~~。 - -```md -文本可以是**粗体**,_斜体_,或~~删除线~~。 -``` - -你可以 [链接到另一个页面](/zh/getting-started/)。 - -```md -你可以 [链接到另一个页面](/zh/getting-started/)。 -``` - -你可以使用反引号高亮 `内联代码`。 - -```md -你可以使用反引号高亮 `内联代码`。 -``` - -## 图片 - -Starlight 中的图片使用 [Astro 的内置优化资源支持](https://docs.astro.build/zh-cn/guides/assets/)。 - -Markdown 和 MDX 支持用于显示图片的 Markdown 语法,其中包括屏幕阅读器和辅助技术的 alt-text。 - -![一个星球和星星的插图,上面写着“astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) - -```md -![一个星球和星星的插图,上面写着“astro”](https://raw.githubusercontent.com/withastro/docs/main/public/default-og-image.png) -``` - -对于在项目中本地存储的图片,也支持图片的相对路径。 - -```md -// src/content/docs/page-1.md - -![A rocketship in space](../../assets/images/rocket.svg) -``` - -## 标题 - -你可以使用标题来组织内容。Markdown 中的标题由行首的 `#` 数量来表示。 - -### 如何在 Starlight 中组织页面内容 - -Starlight 配置为自动使用页面标题作为一级标题,并将在每个页面的目录中包含一个“概述”标题。我们建议每个页面都从常规段落文本内容开始,并从 `<h2>` 开始使用页面标题: - -```md ---- -title: Markdown 指南 -description: 如何在 Starlight 中使用 Markdown ---- - -本页面描述了如何在 Starlight 中使用 Markdown。 - -## 内联样式 - -## 标题 -``` - -### 自动生成标题锚点链接 - -使用 Markdown 中的标题将自动为你提供锚点链接,以便你可以直接链接到页面的某些部分: - -```md ---- -title: 我的页面内容 -description: 如何使用 Starlight 内置的锚点链接 ---- - -## 介绍 - -我可以链接到同一页下面的[结论](#结论)。 - -## 结论 - -`https://my-site.com/page1/#introduction` 直接导航到我的介绍。 -``` - -二级标题 (`<h2>`) 和 三级标题 (`<h3>`) 将自动出现在页面目录中。 - -## 旁白 - -旁白(也称为“警告”或“标注”)对于在页面的主要内容旁边显示辅助信息很有用。 - -Starlight 提供了一个自定义的 Markdown 语法来渲染旁白。旁白块使用一对三个冒号 `:::` 来包裹你的内容,并且可以是 `note`,`tip`,`caution` 或 `danger` 类型。 - -你可以在旁白中嵌套任何其他 Markdown 内容类型,但旁白最适合用于简短而简洁的内容块。 - -### Note 旁白 - -:::note -Starlight 是一个使用 [Astro](https://astro.build/) 构建的文档网站工具包。 你可以使用此命令开始: - -```sh -npm create astro@latest -- --template starlight -``` - -::: - -````md -:::note -Starlight 是一个使用 [Astro](https://astro.build/) 构建的文档网站工具包。 你可以使用此命令开始: - -```sh -npm create astro@latest -- --template starlight -``` - -::: -```` - -### 自定义旁白标题 - -你可以在旁白类型后面的方括号中指定旁白的自定义标题,例如 `:::tip[你知道吗?]`。 - -:::tip[你知道吗?] -Astro 帮助你使用 [“群岛架构”](https://docs.astro.build/zh-cn/concepts/islands/) 构建更快的网站。 -::: - -```md -:::tip[你知道吗?] -Astro 帮助你使用 [“群岛架构”](https://docs.astro.build/zh-cn/concepts/islands/) 构建更快的网站。 -::: -``` - -### 更多旁白类型 - -Caution 和 danger 旁白有助于吸引用户注意可能绊倒他们的细节。 如果你发现自己经常使用这些,这也可能表明你正在记录的内容可以从重新设计中受益。 - -:::caution -如果你不确定是否想要一个很棒的文档网站,请在使用 [Starlight](../../) 之前三思。 -::: - -:::danger -借助有用的 Starlight 功能,你的用户可能会提高工作效率,并发现你的产品更易于使用。 - -- 清晰的导航 -- 用户可配置的颜色主题 -- [i18n 支持](/zh/guides/i18n) - -::: - -```md -:::caution -如果你不确定是否想要一个很棒的文档网站,请在使用 [Starlight](../../) 之前三思。 -::: - -:::danger -借助有用的 Starlight 功能,你的用户可能会提高工作效率,并发现你的产品更易于使用。 - -- 清晰的导航 -- 用户可配置的颜色主题 -- [i18n 支持](/zh/guides/i18n) - -::: -``` - -## 块引用 - -> 这是块引用,通常在引用其他人或文档时使用。 -> -> 块引用以每行开头的 `>` 表示。 - -```md -> 这是块引用,通常在引用其他人或文档时使用。 -> -> 块引用以每行开头的 `>` 表示。 -``` - -## 代码块 - -代码块由三个反引号 <code>```</code> 开始和结束。你可以在开头的反引号后指定代码块的编程语言。 - -```js -// 带有语法高亮的 JavaScript 代码。 -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` - -````md -```js -// 带有语法高亮的 JavaScript 代码。 -var fun = function lang(l) { - dateformat.i18n = require('./lang/' + l); - return true; -}; -``` -```` - -```md -长单行代码块不应换行。如果它们太长,它们应该水平滚动。这一行应该足够长长长长长长长长长长长长来证明这一点。 -``` - -## 其它通用 Markdown 语法 - -Starlight 支持所有其他 Markdown 语法,例如列表和表格。 请参阅 [Markdown 指南的 Markdown 速查表](https://www.markdownguide.org/cheat-sheet/) 以快速了解所有 Markdown 语法元素。 diff --git a/docs/src/content/docs/zh/guides/components.mdx b/docs/src/content/docs/zh/guides/components.mdx deleted file mode 100644 index 7e2bc35370a..00000000000 --- a/docs/src/content/docs/zh/guides/components.mdx +++ /dev/null @@ -1,188 +0,0 @@ ---- -title: 组件 -description: 使用 Starlight 在 MDX 中使用组件 ---- - -组件让你可以轻松地重用 UI 或样式。 -例如,链接卡片或 YouTube 嵌入。 -Starlight 支持在 [MDX](https://mdxjs.com/) 文件中使用组件,并提供了一些常用组件供你使用。 - -[在 Astro 文档中了解更多关于构建组件的内容](https://docs.astro.build/zh-cn/core-concepts/astro-components/). - -## 使用组件 - -你可以通过在 MDX 文件中导入组件,然后像渲染 JSX 标签一样来使用组件。 -这些看起来像 HTML 标签,但是以大写字母开头,与你的 `import` 语句中的名称匹配: - -```mdx ---- -# src/content/docs/index.mdx -title: 欢迎来到我的文档 ---- - -import SomeComponent from '../../../components/SomeComponent.astro'; -import AnotherComponent from '../../../components/AnotherComponent.astro'; - -<SomeComponent prop="something" /> - -<AnotherComponent>组件也可以包含**嵌套内容**。</AnotherComponent> -``` - -因为 Starlight 是由 Astro 提供支持的,所以你可以在 MDX 文件中添加对任何 [支持的 UI 框架(React、Preact、Svelte、Vue、Solid、Lit 和 Alpine)](https://docs.astro.build/zh-cn/core-concepts/framework-components/) 构建的组件的支持。 -在 Astro 文档中了解更多关于 [在 MDX 中使用组件](https://docs.astro.build/zh-cn/guides/markdown-content/#在-mdx-中使用组件) 的内容。 - -### 与 Starlight 样式的兼容 - -Starlight 为你的 Markdown 内容应用了默认样式,例如在元素之间添加边距。 - -如果这些样式与你的组件的外观冲突,请在组件上设置 `not-content` 类来禁用它们。 - -```astro ---- -// src/components/Example.astro ---- - -<div class="not-content"> - <p>不受 Starlight 默认内容样式的影响。</p> -</div> -``` - -## 内置组件 - -Starlight 为常见的文档用例提供了一些内置组件。 -这些组件可以从 `@astrojs/starlight/components` 包中获取。 - -### 选项卡 - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -你可以使用 `<Tabs>` 和 `<TabItem>` 组件显示一个选项卡界面。 -每个 `<TabItem>` 必须有一个 `label` 来显示给用户。 - -```mdx -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -<Tabs> - <TabItem label="恒星">天狼星、织女星、参宿四</TabItem> - <TabItem label="卫星">木卫一、木卫二、木卫三</TabItem> -</Tabs> -``` - -以上代码在页面上生成了以下选项卡: - -<Tabs> - <TabItem label="恒星">天狼星、织女星、参宿四</TabItem> - <TabItem label="卫星">木卫一、木卫二、木卫三</TabItem> -</Tabs> - -### 卡片 - -import { Card, CardGrid } from '@astrojs/starlight/components'; - -你可以使用 `<Card>` 组件在与 Starlight 样式匹配的盒子中显示内容。 -当有足够的空间时,可以使用 `<CardGrid>` 组件将多个卡片封装在一起,以便并排显示卡片。 - -`<Card>` 需要一个 `title`,并且可以选择包含一个 `icon` 属性,该属性设置为 [Starlight 内置图标](#所有图标) 之一的名称。 - -```mdx -import { Card, CardGrid } from '@astrojs/starlight/components'; - -<Card title="看看这个">你想要突出显示的有趣内容。</Card> - -<CardGrid> - <Card title="恒星" icon="star"> - 天狼星、织女星、参宿四 - </Card> - <Card title="卫星" icon="moon"> - 木卫一、木卫二、木卫三 - </Card> -</CardGrid> -``` - -以上代码在页面上生成了以下内容: - -<Card title="看看这个">你想要突出显示的有趣内容。</Card> - -<CardGrid> - <Card title="恒星" icon="star"> - 天狼星、织女星、参宿四 - </Card> - <Card title="卫星" icon="moon"> - 木卫一、木卫二、木卫三 - </Card> -</CardGrid> - -:::tip[提示] -在主页上使用卡片网格来显示项目的关键特性。 -添加 `stagger` 属性来垂直移动第二列的卡片,并增加视觉效果: - -```astro -<CardGrid stagger> - <!-- 卡片组件 --> -</CardGrid> -``` - -::: - -### 链接卡片 - -使用 `<LinkCard>` 组件来突出显示链接到不同页面的内容。 - -`<LinkCard>` 需要一个 `title` 和一个 [`href`](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/a#href) 属性。你可以选择包含一个简短的 `description` 或其他链接属性,例如 `target`。 - -当有足够的空间时,将多个 `<LinkCard>` 组件组合在 `<CardGrid>` 中,以便并排显示卡片。 - -```mdx -import { LinkCard, CardGrid } from '@astrojs/starlight/components'; - -<LinkCard - title="自定义 Starlight" - description="了解如何使用自定义样式、字体等打造你自己的 Starlight 网站。" - href="/zh/guides/customization/" -/> - -<CardGrid> - <LinkCard title="创作 Markdown" href="/zh/guides/authoring-content/" /> - <LinkCard title="组件" href="/zh/guides/components/" /> -</CardGrid> -``` - -以上代码在页面上生成了以下内容: - -import { LinkCard } from '@astrojs/starlight/components'; - -<LinkCard - title="自定义 Starlight" - description="了解如何使用自定义样式、字体等打造你自己的 Starlight 网站。" - href="/zh/guides/customization/" -/> - -<CardGrid> - <LinkCard title="创作 Markdown" href="/zh/guides/authoring-content/" /> - <LinkCard title="组件" href="/zh/guides/components/" /> -</CardGrid> - -### 图标 - -import { Icon } from '@astrojs/starlight/components'; -import IconsList from '../../../../components/icons-list.astro'; - -Starlight 提供了一组常用的图标,你可以使用 `<Icon>` 组件在你的内容中显示。 - -每个 `<Icon>` 都需要一个 [`name`](#所有图标),并且可以选择包含 `label`、`size` 和 `color` 属性。 - -```mdx -import { Icon } from '@astrojs/starlight/components'; - -<Icon name="star" color="goldenrod" size="2rem" /> -``` - -以上代码在页面上生成了以下内容: - -<Icon name="star" color="goldenrod" size="2rem" /> - -#### 所有图标 - -下面显示了所有可用图标的列表及其关联的名称。点击图标以复制其组件代码。 - -<IconsList /> diff --git a/docs/src/content/docs/zh/guides/i18n.mdx b/docs/src/content/docs/zh/guides/i18n.mdx deleted file mode 100644 index 52134d82c13..00000000000 --- a/docs/src/content/docs/zh/guides/i18n.mdx +++ /dev/null @@ -1,217 +0,0 @@ ---- -title: 国际化 (i18n) -description: 学习如何配置你的 Starlight 网站支持多种语言。 ---- - -import FileTree from '../../../../components/file-tree.astro'; - -Starlight 提供了内置的多语言支持,包括路由、回退内容和完整的从右到左(RTL)语言支持。 - -## 配置 i18n - -1. 通过将 [`locales`](/reference/configuration/#locales) 和 [`defaultLocale`](/reference/configuration/#defaultlocale) 传递给 Starlight 集成,告诉 Starlight 你支持的语言: - - ```js - // astro.config.mjs - import { defineConfig } from 'astro/config'; - import starlight from '@astrojs/starlight'; - - export default defineConfig({ - integrations: [ - starlight({ - title: '我的文档', - // 为此网站设置英语为默认语言。 - defaultLocale: 'en', - locales: { - // 英文文档在 `src/content/docs/en/` 中。 - en: { - label: 'English', - }, - // 简体中文文档在 `src/content/docs/zh/` 中。 - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - // 阿拉伯文档在 `src/content/docs/ar/` 中。 - ar: { - label: 'العربية', - dir: 'rtl', - }, - }, - }), - ], - }); - ``` - - 你的 `defaultLocale` 将用于回退内容和 UI 标签,所以选择你最有可能开始编写内容的语言,或者已经有内容的语言。 - -2. 在 `src/content/docs/` 中为每种语言创建一个目录。例如,对于上面显示的配置,创建以下文件夹: - - <FileTree> - - - src/ - - content/ - - docs/ - - ar/ - - en/ - - zh/ - - </FileTree> - -3. 现在你可以在你的语言目录中添加内容文件。使用相同的文件名来关联跨语言的页面,并利用 Starlight 的完整的 i18n 功能,包括回退内容、翻译通知等。 - - 举个例子,创建 `ar/index.md` 和 `en/index.md` 来分别表示阿拉伯语和英语的主页。 - -### 使用 `root` 语言 - -你可以使用“root”语言来提供没有任何 i18n 前缀的语言。例如,如果英语是你的 root 语言,那么英语页面的路径将是 `/about` 而不是 `/en/about`。 - -要设置 root 语言,请在你的 `locales` 配置中使用 `root` 键。如果 root 语言也是你的内容的默认语言,请删除 `defaultLocale` 或将其设置为 `'root'`。 - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: '我的文档', - defaultLocale: 'root', // 可选 - locales: { - root: { - label: 'English', - lang: 'en', // lang 是 root 语言必须的 - }, - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - }, - }), - ], -}); -``` - -当使用 `root` 语言时,将页面直接放在 `src/content/docs/` 中,而不是在专用的语言文件夹中。例如,当使用上面的配置时,这里是英语和中文的主页文件: - -<FileTree> - -- src/ - - content/ - - docs/ - - **index.md** - - zh/ - - **index.md** - -</FileTree> - -#### 单语言网站 - -默认情况查下,Starlight 是一个单语言(英语)网站。要在其他语言中创建单语言网站,请将其设置为 `locales` 配置中的 `root`: - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'My Docs', - locales: { - root: { - label: '简体中文', - lang: 'zh-CN', - }, - }, - }), - ], -}); -``` - -这允许你在不启用其他多语言网站的国际化功能的情况下,覆盖 Starlight 的默认语言,例如语言选择器。 - -## 回退内容 - -Starlight 期望你在所有语言中创建等效的页面。例如,如果你有一个 `en/about.md` 文件,请为你支持的每种其他语言创建一个 `about.md`。这允许 Starlight 为尚未翻译的页面提供自动回退内容。 - -如果某种语言尚未提供翻译,Starlight 将为读者显示该页面的默认语言(通过 `defaultLocale` 设置)的内容。例如,如果你尚未创建关于你的法语版本,并且你的默认语言是英语,那么访问 `/fr/about` 的访问者将看到来自 `/en/about` 的英语内容,并显示该页面尚未翻译的通知。这有助于你在默认语言中添加内容,然后在翻译人员有时间时逐步翻译它。 - -## 翻译 Starlight 的 UI - -除了托管翻译的内容文件之外,Starlight 还允许你翻译默认的 UI 字符串(例如,目录中的“本页”标题),以便你的读者可以完全使用所选的语言体验你的网站。 - -默认提供了英语、捷克语、法语、德语、意大利语、日语、葡萄牙语、荷兰语、丹麦语、西班牙语、土耳其语、阿拉伯语、挪威语、波斯语、希伯来语、简体中文、韩语、印度尼西亚语、俄罗斯语和瑞典语的翻译 UI 字符串,我们欢迎[贡献添加更多默认语言](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md)。 - -你可以通过 `i18n` 数据集合提供你支持的其他语言的翻译 - 或覆盖我们的默认标签。 - -1. 如果尚未配置,请在 `src/content/config.ts` 中配置 `i18n` 数据集合: - - ```js - // src/content/config.ts - import { defineCollection } from 'astro:content'; - import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; - - export const collections = { - docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), - }; - ``` - -2. 为你想要提供 UI 翻译字符串的每种其他语言在 `src/content/i18n/` 中创建一个 JSON 文件。例如,这将为阿拉伯语和简体中文添加翻译文件: - - <FileTree> - - - src/ - - content/ - - i18n/ - - ar.json - - zh-CN.json - - </FileTree> - -3. 在 JSON 文件中添加你想要翻译的键的翻译。只翻译值,将键保留为英语(例如 `"search.label": "搜索"`)。 - - 这些是 Starlight 附带的现有字符串的英文默认值: - - ```json - { - "skipLink.label": "Skip to content", - "search.label": "Search", - "search.shortcutLabel": "(Press / to Search)", - "search.cancelLabel": "Cancel", - "search.devWarning": "Search is only available in production builds. \nTry building and previewing the site to test it out locally.", - "themeSelect.accessibleLabel": "Select theme", - "themeSelect.dark": "Dark", - "themeSelect.light": "Light", - "themeSelect.auto": "Auto", - "languageSelect.accessibleLabel": "Select language", - "menuButton.accessibleLabel": "Menu", - "sidebarNav.accessibleLabel": "Main", - "tableOfContents.onThisPage": "On this page", - "tableOfContents.overview": "Overview", - "i18n.untranslatedContent": "This content is not available in your language yet.", - "page.editLink": "Edit page", - "page.lastUpdated": "Last updated:", - "page.previousLink": "Next", - "page.nextLink": "Previous" - } - ``` - - Starlight 的搜索模式由 [Pagefind](https://pagefind.app/) 库提供支持。 你可以使用 pagefind 键在同一 JSON 文件中设置 Pagefind UI 的翻译: - - ```json - { - "pagefind.clear_search": "Clear", - "pagefind.load_more": "Load more results", - "pagefind.search_label": "Search this site", - "pagefind.filters_label": "Filters", - "pagefind.zero_results": "No results for [SEARCH_TERM]", - "pagefind.many_results": "[COUNT] results for [SEARCH_TERM]", - "pagefind.one_result": "[COUNT] result for [SEARCH_TERM]", - "pagefind.alt_search": "No results for [SEARCH_TERM]. Showing results for [DIFFERENT_TERM] instead", - "pagefind.search_suggestion": "No results for [SEARCH_TERM]. Try one of the following searches:", - "pagefind.searching": "Searching for [SEARCH_TERM]..." - } - ``` diff --git a/docs/src/content/docs/zh/guides/sidebar.mdx b/docs/src/content/docs/zh/guides/sidebar.mdx deleted file mode 100644 index 13a9d1a57c8..00000000000 --- a/docs/src/content/docs/zh/guides/sidebar.mdx +++ /dev/null @@ -1,471 +0,0 @@ ---- -title: 侧边栏导航 -description: 了解如何设置和自定义 Starlight 站点的侧边栏导航链接。 -sidebar: - badge: New ---- - -import FileTree from '../../../../components/file-tree.astro'; -import SidebarPreview from '../../../../components/sidebar-preview.astro'; - -一个组织良好的侧边栏是良好文档的关键,因为它是用户浏览你的站点的主要方式之一。Starlight 提供了一整套选项来自定义侧边栏布局和内容。 - -## 默认侧边栏 - -默认情况查下,Starlight 会根据你的文档文件系统结构自动生成侧边栏,使用每个文件的 `title` 属性作为侧边栏条目。 - -例如,给定以下文件结构: - -<FileTree> - -- src/ - - content/ - - docs/ - - guides/ - - components.md - - i18n.md - - reference/ - - configuration.md - -</FileTree> - -将会自动生成以下侧边栏: - -<SidebarPreview - config={[ - { - label: 'guides', - items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, - ], - }, - { - label: 'reference', - items: [ - { label: 'Configuration Reference', link: '/reference/configuration/' }, - ], - }, - ]} -/> - -在 [自动生成的分组](#自动生成的分组) 章节了解更多关于自动生成侧边栏的内容。 - -## 添加链接和链接分组 - -要配置侧边栏 [链接](#链接) 和 [链接分组](#分组)(在可折叠的标题中),请在 `astro.config.mjs` 中使用 [`starlight.sidebar`](/zh/reference/configuration/#sidebar) 属性。 - -结合使用链接和链接分组,你可以创建各种侧边栏布局。 - -### 链接 - -使用具有 `label` 和 `link` 属性的对象添加一个指向内部或外部页面的链接。 - -```js -starlight({ - sidebar: [ - // 指向 CSS & Styling 指南的链接 - { label: 'CSS & Styling', link: '/zh/guides/css-and-tailwind/' }, - // 指向 Astro 官网的外部链接 - { label: 'Astro', link: 'https://astro.build/' }, - ], -}); -``` - -上面的配置生成以下侧边栏: - -<SidebarPreview - config={[ - { label: 'CSS & Styling', link: '/zh/guides/css-and-tailwind/' }, - { label: 'Astro', link: 'https://astro.build/' }, - ]} -/> - -### 分组 - -你可以通过在可折叠的标题下将相关链接组合在一起来为侧边栏添加结构。 -分组可以包含链接和其他子组。 - -使用具有 `label` 和 `items` 属性的对象添加一个分组。 -`label` 将用作分组的标题。 -将链接或子组添加到 `items` 数组中。 - -```js -starlight({ - sidebar: [ - // 一个名为 "Guides" 的链接分组 - { - label: 'Guides', - items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, - // 一个嵌套的链接分组 - { - label: 'Styling', - items: [ - { label: 'CSS', link: '/guides/css-and-tailwind/' }, - { label: 'Tailwind', link: '/guides/css-and-tailwind/' }, - { label: 'Shiki', link: '/guides/css-and-tailwind/' }, - ], - }, - ], - }, - ], -}); -``` - -上面的配置生成以下侧边栏: - -<SidebarPreview - config={[ - { - label: 'Guides', - items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, - { - label: 'Styling', - items: [ - { label: 'CSS', link: '/guides/css-and-tailwind/' }, - { label: 'Tailwind', link: '/guides/css-and-tailwind/' }, - { label: 'Shiki', link: '/guides/css-and-tailwind/' }, - ], - }, - ], - }, - ]} -/> - -### 自动生成的分组 - -Starlight 可以根据文档目录在侧边栏中自动生成一个分组。当你不想手动输入分组中的每个侧边栏项目时,这很有用。默认情况下,页面将按文档名的字母顺序排序。 - -使用具有 `label` 和 `autogenerate` 属性的对象添加自动生成的分组。`autogenerate` 的配置必须指定用于侧边栏条目的 `directory` 。例如,使用以下配置: - -```js -starlight({ - sidebar: [ - { - label: 'Guides', - // 自动生成一个链接分组,用于 'guides' 目录。 - autogenerate: { directory: 'guides' }, - }, - ], -}); -``` - -给定以下文件结构: - -<FileTree> - -- src/ - - content/ - - docs/ - - guides/ - - components.md - - i18n.md - - advanced/ - - project-structure.md - -</FileTree> - -将会自动生成以下侧边栏: - -<SidebarPreview - config={[ - { - label: 'Guides', - items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, - { - label: 'advanced', - items: [ - { label: 'Project Structure', link: '/guides/project-structure/' }, - ], - }, - ], - }, - ]} -/> - -#### 在 frontmatter 中自定义自动生成的链接 - -在单个页面中使用 [`sidebar` frontmatter 字段](/zh/reference/frontmatter/#sidebar) 来自定义自动生成的链接。 - -侧边栏 frontmatter 选项允许你设置 [自定义标签](/zh/reference/frontmatter/#label) 或者为链接添加 [徽章](/zh/reference/frontmatter/#badge),[隐藏](/zh/reference/frontmatter/#hidden) 侧边栏中的链接,或者定义 [自定义排序权重](/zh/reference/frontmatter/#order)。 - -```md ---- -title: 我的页面 -sidebar: - # 为链接设置自定义标签 - label: 自定义侧边栏 label - # 为链接设置自定义顺序(数字越小显示在上方) - order: 2 - # 为链接添加徽章 - badge: - text: New - variant: tip ---- -``` - -一个包含上面 frontmatter 的页面的自动生成分组将会生成以下侧边栏: - -<SidebarPreview - config={[ - { - label: 'Guides', - items: [ - { label: '一个页面', link: '#' }, - { - label: '自定义侧边栏 label ', - link: '#', - badge: { text: 'New', variant: 'tip' }, - }, - { label: '其他页面', link: '#' }, - ], - }, - ]} -/> - -:::note -`sidebar` frontmatter 配置仅用于自动生成的链接,对于手动定义的链接将被忽略。 -::: - -## 徽章 - -链接也可以包含一个 `badge` 属性,以在链接标签旁边显示徽章。 - -```js -starlight({ - sidebar: [ - { - label: 'Guides', - items: [ - // 带有 "New" 徽章的链接。 - { - label: 'Components', - link: '/guides/components/', - badge: 'New', - }, - ], - }, - ], -}); -``` - -以上配置将生成以下侧边栏: - -<SidebarPreview - config={[ - { - label: 'Guides', - items: [ - { - label: 'Components', - link: '/guides/components/', - badge: { text: 'New', variant: 'default' }, - }, - ], - }, - ]} -/> - -### 徽章种类 - -使用具有 `text` 和 `variant` 属性的对象自定义徽章样式。 - -`text` 属性表示要显示的内容(例如 "New")。 -通过将 `variant` 属性设置为以下值之一:`note`、`tip`、`danger`、`caution` 或 `success`,可以覆盖 `default` 样式,默认样式使用你的网站的强调色。 - -```js -starlight({ - sidebar: [ - { - label: 'Guides', - items: [ - // 一个带有黄色 "Experimental" 徽章的链接。 - { - label: 'Components', - link: '/guides/components/', - badge: { text: 'Experimental', variant: 'caution' }, - }, - ], - }, - ], -}); -``` - -以上配置将生成以下侧边栏: - -<SidebarPreview - config={[ - { - label: 'Guides', - items: [ - { - label: 'Components', - link: '/guides/components/', - badge: { text: 'Experimental', variant: 'caution' }, - }, - ], - }, - ]} -/> - -## 国际化 - -使用链接和分组条目上的 `translations` 属性为每种支持的语言翻译链接或分组标签。 -`label` 属性将用于默认语言和没有翻译的语言。 - -```js -starlight({ - sidebar: [ - { - label: 'Guides', - translations: { - zh: '指南', - }, - items: [ - { - label: 'Components', - translations: { - zh: '组件', - }, - link: '/zh/guides/components/', - }, - { - label: 'Internationalization (i18n)', - translations: { - zh: '国际化 (i18n)', - }, - link: '/zh/guides/i18n/', - }, - ], - }, - ], -}); -``` - -浏览简体中文文档将生成以下侧边栏: - -<SidebarPreview - config={[ - { - label: '指南', - items: [ - { label: '组件', link: '/zh/guides/components/' }, - { label: '国际化 (i18n)', link: '/zh/guides/i18n/' }, - ], - }, - ]} -/> - -## 折叠分组 - -链接分组可以通过将 `collapsed` 属性设置为 `true` 来默认折叠。 - -```js -starlight({ - sidebar: [ - { - label: 'Guides', - // 默认折叠分组 - collapsed: true, - items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, - ], - }, - ], -}); -``` - -以上配置将生成以下侧边栏: - -<SidebarPreview - config={[ - { - label: 'Guides', - collapsed: true, - items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, - ], - }, - ]} -/> - -[自动生成的分组](#自动生成的分组) 遵循其父级分组的 `collapsed` 值: - -```js -starlight({ - sidebar: [ - { - label: 'Guides', - // 默认折叠分组及其自动生成的子组。 - collapsed: true, - autogenerate: { directory: 'guides' }, - }, - ], -}); -``` - -以上配置将生成以下侧边栏: - -<SidebarPreview - config={[ - { - label: 'Guides', - collapsed: true, - items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, - { - label: 'advanced', - collapsed: true, - items: [ - { label: 'Project Structure', link: '/guides/project-structure/' }, - ], - }, - ], - }, - ]} -/> - -这个行为可以通过定义 `autogenerate.collapsed` 属性来覆盖。 - -```js -starlight({ - sidebar: [ - { - label: 'Guides', - // 不折叠 "Guides" 分组,但折叠其自动生成的子组。 - collapsed: false, - autogenerate: { directory: 'guides', collapsed: true }, - }, - ], -}); -``` - -以上配置将生成以下侧边栏: - -<SidebarPreview - config={[ - { - label: 'Guides', - items: [ - { label: 'Components', link: '/guides/components/' }, - { label: 'Internationalization (i18n)', link: '/guides/i18n/' }, - { - label: 'advanced', - collapsed: true, - items: [ - { label: 'Project Structure', link: '/guides/project-structure/' }, - ], - }, - ], - }, - ]} -/> diff --git a/docs/src/content/docs/zh/index.mdx b/docs/src/content/docs/zh/index.mdx deleted file mode 100644 index 831103363f4..00000000000 --- a/docs/src/content/docs/zh/index.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Starlight 🌟 使用 Astro 构建文档站点 -description: Starlight 帮助你使用 Astro 构建漂亮、高性能的文档网站。 -template: splash -banner: - content: | - <span class="ph-banner"> - <span class="ph-houston"><img src="/ph-houston.svg" alt="" width="72" height="72"/></span> - <span class="ph-text"> - <strong>欢迎 Product Hunters 👋</strong> - <a href="https://www.producthunt.com/posts/starlight-by-astro">我们现在已上线!</a> - </span> - </span> -hero: - title: Starlight <br/> 使你的文档闪耀夺目 - tagline: 快速、易用、易于访问 —— 构建卓越文档网站所需的一切。 - image: - file: ../../../assets/hero-star.webp - actions: - - text: 开始使用 - icon: right-arrow - variant: primary - link: /zh/getting-started/ - - text: 在 GitHub 上查看 - icon: external - link: https://github.com/withastro/starlight ---- - -import { CardGrid, Card } from '@astrojs/starlight/components'; -import AboutAstro from '../../../components/about-astro.astro'; - -<CardGrid stagger> - <Card title="令人愉悦的文档" icon="open-book"> - 包括:网站导航、搜索、国际化、SEO、易于阅读的排版、代码高亮、深色模式等等。 - </Card> - <Card title="由 Astro 提供支持" icon="rocket"> - 充分利用 Astro 的全部功能和性能。使用你最喜欢的 Astro 集成和库扩展 - Starlight。 - </Card> - <Card title="Markdown、Markdoc 和 MDX" icon="document"> - 带上你最喜欢的标记语言。Starlight 为你提供了内置的 frontmatter 验证和 - TypeScript 类型安全。 - </Card> - <Card title="带上你自己的 UI 组件" icon="puzzle"> - Starlight 作为一个不依赖于框架的完整文档解决方案。可以使用 - React、Vue、Svelte、Solid 等进行扩展。 - </Card> -</CardGrid> - -<AboutAstro title="由以下提供支持"> -Astro 是专为速度而设计的全能 Web 框架。 -从任何地方获取你的内容并在任何地方部署,所有这些都由你喜欢的 UI 组件和库提供支持。 - -[了解 Astro](https://astro.build/) - -</AboutAstro> diff --git a/docs/src/content/docs/zh/reference/configuration.md b/docs/src/content/docs/zh/reference/configuration.md deleted file mode 100644 index b744720dc36..00000000000 --- a/docs/src/content/docs/zh/reference/configuration.md +++ /dev/null @@ -1,424 +0,0 @@ ---- -title: 配置参考 -description: Starlight 支持的所有配置选项的概述。 ---- - -## 配置 `starlight` 集成 - -Starlight 是在 [Astro](https://astro.build) web 框架之上构建的集成。你可以在 `astro.config.mjs` 配置文件中配置你的项目: - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: '我的令人愉快的文档网站', - }), - ], -}); -``` - -你可以将以下选项传递给`starlight`集成。 - -### `title` (必填) - -**类型:** `string` - -设置你的网站标题。将用于元数据和浏览器标签标题。 - -### `description` - -**类型:** `string` - -设置你的网站描述。如果页面的 frontmatter 中没有设置 `description`,则在 `<meta name="description">` 标签中与搜索引擎共享元数据。 - -### `logo` - -**类型:** [`LogoConfig`](#logoconfig) - -在导航栏中设置一个 logo 图片,与网站标题一起显示或替代网站标题。你可以设置单个 `src` 属性,也可以为 `light` 和 `dark` 设置单独的图像源。 - -```js -starlight({ - logo: { - src: './src/assets/my-logo.svg', - }, -}); -``` - -#### `LogoConfig` - -```ts -type LogoConfig = { alt?: string; replacesTitle?: boolean } & ( - | { src: string } - | { light: string; dark: string } -); -``` - -### `tableOfContents` - -**类型:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` -**默认值:** `{ minHeadingLevel: 2; maxHeadingLevel: 3; }` - -配置每个页面右侧显示的目录。默认情况下,`<h2>` 和 `<h3>` 标题将包含在此目录中。 - -### `editLink` - -**类型:** `{ baseUrl: string }` - -通过设置你要使用的 base URL 来启用 “编辑此页” 链接。最终链接将是`editLink.baseUrl` +当前页面路径。例如,要启用在 GitHub 上编辑`withastro/starlight` 仓库中的页面: - -```js -starlight({ - editLink: { - baseUrl: 'https://github.com/withastro/starlight/edit/main/', - }, -}); -``` - -使用此配置,`/introduction` 页面将具有指向 `https://github.com/withastro/starlight/edit/main/src/docs/introduction.md` 的编辑链接。 - -### `sidebar` - -**类型:** [`SidebarItem[]`](#sidebaritem) - -配置你的网站的侧边栏导航项目。 - -侧边栏是包含链接和链接组的数组。每个项目都必须具有 `label` 和以下属性之一: - -- `link` — 指向特定 URL 的单个链接,例如 `'/home'` 或 `'https://example.com'`。 - -- `items` — 包含更多侧边栏链接和子组的数组。 - -- `autogenerate` — 指定要从中自动生成一组链接的文档目录的对象。 - -```js -starlight({ - sidebar: [ - // 标记为“Home”的单个链接项。 - { label: 'Home', link: '/' }, - // 一个标记为“Start Here”的组,其中包含两个链接。 - { - label: 'Start Here', - items: [ - { label: 'Introduction', link: '/intro' }, - { label: 'Next Steps', link: '/next-steps' }, - ], - }, - // 一个链接到参考目录中所有页面的组。 - { - label: 'Reference', - autogenerate: { directory: 'reference' }, - }, - ], -}); -``` - -#### 排序 - -自动生成的侧边栏组按文档名字母顺序排序。例如,从 `astro.md` 生成的页面将显示在 `starlight.md`页面上方。 - -#### 折叠组 - -默认情况下,链接组是展开的。你可以通过将组的 `collapsed` 属性设置为 `true` 来更改此行为。 - -自动生成的子组默认情况下会遵守其父组的 `collapsed` 属性。设置 `autogenerate.collapsed` 属性以覆盖此行为。 - -```js -sidebar: [ - // 一个折叠的链接组。 - { - label: 'Collapsed Links', - collapsed: true, - items: [ - { label: 'Introduction', link: '/intro' }, - { label: 'Next Steps', link: '/next-steps' }, - ], - }, - // 一个展开的组,其中包含折叠的自动生成的子组。 - { - label: 'Reference', - autogenerate: { - directory: 'reference', - collapsed: true, - }, - }, -], -``` - -#### 翻译标签 - -如果你的网站是多语言的,每个项目的 `label` 被认为是默认语言。你可以设置一个 `translations` 属性来为你支持的其他语言提供标签: - -```js -sidebar: [ - // 一个侧边栏示例,其中的标签被翻译成法语。 - { - label: 'Start Here', - translations: { fr: 'Commencez ici' }, - items: [ - { - label: 'Getting Started', - translations: { fr: 'Bien démarrer' }, - link: '/getting-started', - }, - { - label: 'Project Structure', - translations: { fr: 'Structure du projet' }, - link: '/structure', - }, - ], - }, -], -``` - -#### `SidebarItem` - -```ts -type SidebarItem = { - label: string; - translations?: Record<string, string>; -} & ( - | { - link: string; - badge?: string | BadgeConfig; - } - | { items: SidebarItem[]; collapsed?: boolean } - | { - autogenerate: { directory: string; collapsed?: boolean }; - collapsed?: boolean; - } -); -``` - -#### `BadgeConfig` - -```ts -interface BadgeConfig { - text: string; - variant: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; -} -``` - -### `locales` - -**类型:** <code>{ \[dir: string\]: [LocaleConfig](#localeconfig) }</code> - -为你的网站设置支持的 `locales` 来[配置国际化(i18n)](/zh/guides/i18n/)。 - -每个条目都应该使用该语言文件保存的目录作为 key。 - -```js -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; - -export default defineConfig({ - integrations: [ - starlight({ - title: 'My Site', - // 为这个网站设置英语作为默认语言。 - defaultLocale: 'en', - locales: { - // 英文文档在 `src/content/docs/en/` - en: { - label: 'English', - }, - // 简体中文文档在 `src/content/docs/zh/` - zh: { - label: '简体中文', - lang: 'zh-CN', - }, - // 阿拉伯文档在 `src/content/docs/ar/` - ar: { - label: 'العربية', - dir: 'rtl', - }, - }, - }), - ], -}); -``` - -#### `LocaleConfig` - -```ts -interface LocaleConfig { - label: string; - lang?: string; - dir?: 'ltr' | 'rtl'; -} -``` - -你可以为每个语言设置以下选项: - -##### `label` (必填) - -**类型:** `string` - -要向用户显示的此语言的标签,例如在语言切换器中。大多数情况下,你会希望这是该语言的名称,因为该语言的用户希望阅读它,例如`"English"`,`"العربية"`,或者 `"简体中文"`。 - -##### `lang` - -**类型:** `string` - -此语言的 BCP-47 标签,例如`"en"`,`"ar"`,或者 `"zh-CN"`。如果未设置,则默认使用该语言的目录名称。 如果没有找到特定于区域的翻译,带有区域子标签的语言标签(例如`pt-BR`或`en-US`)将使用内置的 UI 翻译作为其基本语言。 - -##### `dir` - -**类型:** `'ltr' | 'rtl'` - -这种语言的写作方向; `"ltr"`表示从左到右(默认值)或`"rtl"`表示从右到左。 - -#### root locale - -你可以通过设置 `root` locale 来提供不带 `/lang/` 目录的默认语言: - -```js -starlight({ - locales: { - root: { - label: 'English', - lang: 'en', - }, - fr: { - label: 'Français', - }, - }, -}); -``` - -举例,这允许你将 `/getting-started/` 作为英语路由提供,并将 `/fr/getting-started/` 作为等效的法语页面。 - -### `defaultLocale` - -**类型:** `string` - -设置此站点的默认语言。 -该值应该与你的 [`locales`](#locales) 对象的键之一匹配。 -(如果你的默认语言是你的[root locale](#root-locale),你可以跳过这一步。) - -默认语言将用于在缺少翻译时提供回退内容。 - -### `social` - -**类型:** `Partial<Record<'bitbucket' | 'codeberg' | 'codePen' | 'discord' | 'github' | 'gitlab' | 'gitter' | 'instagram' | 'linkedin' | 'mastodon' | 'microsoftTeams' | 'stackOverflow' | 'threads' | 'twitch' | 'twitter' | 'youtube', string>>` - -可选的社交媒体账户详情。添加任何一个都会在网站标题中显示它们作为图标链接。 - -```js -starlight({ - social: { - codeberg: 'https://codeberg.org/knut/examples', - discord: 'https://astro.build/chat', - github: 'https://github.com/withastro/starlight', - gitlab: 'https://gitlab.com/delucis', - linkedin: 'https://www.linkedin.com/company/astroinc', - mastodon: 'https://m.webtoo.ls/@astro', - threads: 'https://www.threads.net/@nmoodev', - twitch: 'https://www.twitch.tv/bholmesdev', - twitter: 'https://twitter.com/astrodotbuild', - youtube: 'https://youtube.com/@astrodotbuild', - }, -}); -``` - -### `customCss` - -**类型:** `string[]` - -提供 CSS 文件来自定义你的 Starlight 网站的外观和风格。 - -支持相对于项目根目录的本地 CSS 文件,例如 `'./src/custom.css'`,以及你安装为 npm 模块的 CSS,例如 `'@fontsource/roboto'`。 - -```js -starlight({ - customCss: ['./src/custom-styles.css', '@fontsource/roboto'], -}); -``` - -### `head` - -**类型:** [`HeadConfig[]`](#headconfig) - -添加自定义标签到你的 Starlight 网站的 `<head>` 中。 -可以用于添加分析和其他第三方脚本和资源。 - -```js -starlight({ - head: [ - // 示例:添加 Fathom 分析脚本标签。 - { - tag: 'script', - attrs: { - src: 'https://cdn.usefathom.com/script.js', - 'data-site': 'MY-FATHOM-ID', - defer: true, - }, - }, - ], -}); -``` - -#### `HeadConfig` - -```ts -interface HeadConfig { - tag: string; - attrs?: Record<string, string | boolean | undefined>; - content?: string; -} -``` - -### `lastUpdated` - -**类型:** `boolean` -**默认值:** `false` - -控制页脚是否显示页面上次更新的时间。 - -默认情况下,此功能依赖于你的存储库的 Git 历史记录,并且在某些执行[浅克隆](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt)的部署平台上可能不准确。页面可以使用 [`lastUpdated` frontmatter 字段](/zh/reference/frontmatter/#lastupdated)覆盖此设置或基于 Git 的日期。 - -### `pagination` - -**类型:** `boolean` -**默认值:** `true` - -定义页脚是否应包含上一页和下一页的链接。 - -页面可以使用 [`prev`](/zh/reference/frontmatter/#prev) 和 [`next`](/zh/reference/frontmatter/#next) frontmatter 字段覆盖此设置或链接文本和/或 URL。 - -### `favicon` - -**类型:** `string` -**默认值:** `'/favicon.svg'` - -设置网站的默认 favicon 的路径,它应该位于 `public/` 目录中,并且是一个有效的(`.ico`,`.gif`,`.jpg`,`.png` 或 `.svg`)图标文件。 - -```js -starlight({ - favicon: '/images/favicon.svg', -}), -``` - -如果你需要设置其他变体或回退的 favicon,你可以使用 [`head` 选项](#head)添加标签: - -```js -starlight({ - favicon: '/images/favicon.svg'. - head: [ - // 为 Safari 添加 ICO favicon 回退。 - { - tag: 'link', - attrs: { - rel: 'icon', - href:'/images/favicon.ico', - sizes: '32x32', - }, - }, - ], -}); -``` diff --git a/docs/src/content/docs/zh/reference/frontmatter.md b/docs/src/content/docs/zh/reference/frontmatter.md deleted file mode 100644 index 313ae94a72a..00000000000 --- a/docs/src/content/docs/zh/reference/frontmatter.md +++ /dev/null @@ -1,301 +0,0 @@ ---- -title: Frontmatter 参考 -description: Starlight 支持的默认 frontmatter 字段的概述。 ---- - -你可以通过设置 frontmatter 中的值来自定义 Starlight 中的单个 Markdown 和 MDX 页面。例如,一个常规页面可能会设置 `title` 和 `description` 字段: - -```md ---- -title: 关于此项目 -description: 了解更多关于此项目的信息。 ---- - -欢迎来到关于页面! -``` - -## Frontmatter 字段 - -### `title` (必填) - -**类型:** `string` - -你必须为每个页面提供标题。它将显示在页面顶部、浏览器标签中和页面元数据中。 - -### `description` - -**类型:** `string` - -页面描述用于页面元数据,将被搜索引擎和社交媒体预览捕获。 - -### `editUrl` - -**类型:** `string | boolean` - -覆盖[全局 `editLink` 配置](/zh/reference/configuration/#editlink)。设置为 false 可禁用特定页面的 “编辑页面” 链接,或提供此页面内容可编辑的备用 URL。 - -### `head` - -**类型:** [`HeadConfig[]`](/zh/reference/configuration/#headconfig) - -你可以使用 `<head>` frontmatter 字段向页面的`<head>`添加其他标签。这意味着你可以将自定义样式、元数据或其他标签添加到单个页面。类似于[全局 `head` 选项](/zh/reference/configuration/#head)。 - -```md ---- -title: 关于我们 -head: - # 使用自定义 <title> 标签 - - tag: title - content: 自定义关于我们页面标题 ---- -``` - -### `tableOfContents` - -**类型:** `false | { minHeadingLevel?: number; maxHeadingLevel?: number; }` - -覆盖[全局 `tableOfContents` 配置](/zh/reference/configuration/#tableofcontents)。自定义要包含的标题级别,或设置为 `false` 以在此页面上隐藏目录。 - -```md ---- -title: 目录中只有 H2 的页面 -tableOfContents: - minHeadingLevel: 2 - maxHeadingLevel: 2 ---- -``` - -```md ---- -title: 没有目录的页面 -tableOfContents: false ---- -``` - -### `template` - -**类型:** `'doc' | 'splash'` -**默认值:** `'doc'` - -为页面选择布局模板。 -页面默认使用 `'doc'` 布局。 -设置为 `'splash'` 以使用没有任何侧边栏的更宽的布局,该布局专为落地页设计。 - -### `hero` - -**类型:** [`HeroConfig`](#heroconfig) - -添加一个 hero 组件到页面顶部。与 `template: splash` 配合使用效果更佳。 - -例如,此配置显示了一些常见选项,包括从你的仓库加载图像。 - -```md ---- -title: 我的主页 -template: splash -hero: - title: '我的项目: Stellar Stuff Sooner' - tagline: 把你的东西带到月球上,眨眼间又回来。 - image: - alt: 一个闪闪发光、色彩鲜艳的标志 - file: ../../assets/logo.png - actions: - - text: 告诉我更多 - link: /getting-started/ - icon: right-arrow - variant: primary - - text: 在 GitHub 上查看 - link: https://github.com/astronaut/my-project - icon: external ---- -``` - -#### `HeroConfig` - -```ts -interface HeroConfig { - title?: string; - tagline?: string; - image?: { - alt?: string; - // Relative path to an image in your repository. - // 你的仓库中的图像的相对路径。 - file?: string; - // 原始的 HTML 用于图像插槽。 - // 可以是自定义的 `<img>` 标签或内联的 `<svg>`。 - html?: string; - }; - actions?: Array<{ - text: string; - link: string; - variant: 'primary' | 'secondary' | 'minimal'; - icon: string; - }>; -} -``` - -### `banner` - -**类型:** `{ content: string }` - -在此页面顶部显示公告横幅。 - -`content` 的值可以包含链接或其他内容的 HTML。 -例如,此页面显示了一个横幅,其中包含指向 `example.com` 的链接。 - -```md ---- -title: 带有横幅的页面 -banner: - content: | - 我们刚刚发布了一下非常酷的东西! - <a href="https://example.com">点击查看!</a> ---- -``` - -### `lastUpdated` - -**类型:** `Date | boolean` - -覆盖[全局 `lastUpdated` 配置](/zh/reference/configuration/#lastupdated)。如果指定了日期,它必须是有效的 [YAML 时间戳](https://yaml.org/type/timestamp.html),并将覆盖存储在 Git 历史记录中的此页面的日期。 - -```md ---- -title: 带有自定义更新日期的页面 -lastUpdated: 2022-08-09 ---- -``` - -### `prev` - -**类型:** `boolean | string | { link?: string; label?: string }` - -覆盖[全局 `pagination` 配置](/zh/reference/configuration/#pagination)。如果指定了字符串,则将替换生成的链接文本;如果指定了对象,则将同时覆盖链接和文本。 - -```md ---- -# 隐藏上一页链接 -prev: false ---- -``` - -```md ---- -# 将上一页链接更改为“继续教程” -prev: 继续教程 ---- -``` - -```md ---- -# 同时覆盖上一页的链接和文本 -prev: - link: /unrelated-page/ - label: 一个不相关的页面 ---- -``` - -### `next` - -**类型:** `boolean | string | { link?: string; label?: string }` - -和 [`prev`](#prev) 一样,但是用于下一页链接。 - -```md ---- -# 隐藏下一页链接 -next: false ---- -``` - -### `pagefind` - -**类型:** `boolean` -**默认值:** `true` - -设置此页面是否应包含在 [Pagefind](https://pagefind.app/) 搜索索引中。设置为 `false` 以从搜索结果中排除页面: - -```md ---- -# 在搜索索引中隐藏此页面 -pagefind: false ---- -``` - -### `sidebar` - -**类型:** `{ label?: string; order?: number; hidden?: boolean; badge?: string | BadgeConfig }` - -在使用自动生成的链接组时,控制如何在[侧边栏](/zh/reference/configuration/#sidebar)中显示此页面。 - -#### `label` - -**类型:** `string` -**默认值:** 页面 [`title`](#title-必填) - -在自动生成的链接组中显示时,设置侧边栏中此页面的标签。 - -```md ---- -title: 关于此项目 -sidebar: - label: About ---- -``` - -#### `order` - -**类型:** `number` - -当对链接组进行自动生成排序时,控制此页面的顺序。 -数字越小,链接组中显示的越高。 - -```md ---- -title: 要首先显示的页面 -sidebar: - order: 1 ---- -``` - -#### `hidden` - -**类型:** `boolean` -**默认值:** `false` - -防止此页面包含在自动生成的侧边栏组中。 - -```md ---- -title: 从自动生成的侧边栏中隐藏的页面 -sidebar: - hidden: true ---- -``` - -#### `badge` - -**类型:** <code>string | <a href="/zh/reference/configuration/#badgeconfig">BadgeConfig</a></code> - -当在自动生成的链接组中显示时,在侧边栏中为页面添加徽章。 - -当使用字符串时,徽章将显示为默认的强调色。可选择的,传递一个 [`BadgeConfig` 对象](/zh/reference/configuration/#badgeconfig) ,其中包含 `text` 和 `variant` 字段,可以自定义徽章。 - -```md ---- -title: 带有徽章的页面 -sidebar: - # 使用与你的网站的强调色相匹配的默认类型 - badge: 新增 ---- -``` - -```md ---- -title: 带有徽章的页面 -sidebar: - badge: - text: 实验性 - variant: caution ---- -``` diff --git a/docs/src/content/docs/zh/showcase.mdx b/docs/src/content/docs/zh/showcase.mdx deleted file mode 100644 index 57d09216ae1..00000000000 --- a/docs/src/content/docs/zh/showcase.mdx +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Starlight Showcase -description: 发现使用 Starlight 构建的网站和扩展 Starlight 的社区工具! ---- - -:::tip[添加你自己的!] -你是否构建过 Starlight 网站或 Starlight 工具?创建一个 PR 来添加链接到此页面! -::: - -## 网站 - -import ShowcaseSites from '../../../components/showcase-sites.astro'; - -Starlight 已投入生产。 这些是网络上的一些网站: - -<ShowcaseSites /> - -查看所有[在 GitHub 上使用 Starlight 的公共项目仓库](https://github.com/withastro/starlight/network/dependents)。 - -## 社区插件 - -import { CardGrid, LinkCard } from '@astrojs/starlight/components'; - -这些社区工具、插件和集成与 Starlight 一起扩展其功能。 - -<CardGrid> - <LinkCard - href="https://www.feelback.dev/blog/new-astro-starlight-integration/" - title="FeelBack" - description="在文档页面中添加用户反馈系统。" - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-blog" - title="starlight-blog" - description="添加一个博客到你的文档网站。" - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-links-validator" - title="starlight-links-validator" - description="在你的 Starlight 页面中检查损坏的链接" - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-typedoc" - title="starlight-typedoc" - description=" 使用 TypeDoc 从 TypeScript 生成 Starlight 页面。" - /> - <LinkCard - href="https://github.com/HiDeoo/starlight-openapi" - title="starlight-openapi" - description="从 OpenAPI/Swagger 规范创建文档页面。" - /> -</CardGrid> diff --git a/docs/src/content/i18n/de.json b/docs/src/content/i18n/de.json new file mode 100644 index 00000000000..f7d0dfb87d7 --- /dev/null +++ b/docs/src/content/i18n/de.json @@ -0,0 +1,3 @@ +{ + "component.preview": "Vorschau" +} diff --git a/docs/src/content/i18n/en.json b/docs/src/content/i18n/en.json new file mode 100644 index 00000000000..e856b05d9bc --- /dev/null +++ b/docs/src/content/i18n/en.json @@ -0,0 +1,3 @@ +{ + "component.preview": "Preview" +} diff --git a/docs/src/content/i18n/fr.json b/docs/src/content/i18n/fr.json new file mode 100644 index 00000000000..c46cd41dfc3 --- /dev/null +++ b/docs/src/content/i18n/fr.json @@ -0,0 +1,3 @@ +{ + "component.preview": "Aperçu" +} diff --git a/docs/src/content/i18n/ja.json b/docs/src/content/i18n/ja.json new file mode 100644 index 00000000000..c0295758625 --- /dev/null +++ b/docs/src/content/i18n/ja.json @@ -0,0 +1,3 @@ +{ + "component.preview": "プレビュー" +} diff --git a/docs/src/content/i18n/ko.json b/docs/src/content/i18n/ko.json new file mode 100644 index 00000000000..a0704ff29c6 --- /dev/null +++ b/docs/src/content/i18n/ko.json @@ -0,0 +1,3 @@ +{ + "component.preview": "미리보기" +} diff --git a/docs/src/content/i18n/ru.json b/docs/src/content/i18n/ru.json new file mode 100644 index 00000000000..2f0ce28d68c --- /dev/null +++ b/docs/src/content/i18n/ru.json @@ -0,0 +1,3 @@ +{ + "component.preview": "Превью" +} diff --git a/docs/src/content/i18n/zh-CN.json b/docs/src/content/i18n/zh-CN.json new file mode 100644 index 00000000000..835f2488348 --- /dev/null +++ b/docs/src/content/i18n/zh-CN.json @@ -0,0 +1,3 @@ +{ + "component.preview": "预览" +} diff --git a/docs/tsconfig.json b/docs/tsconfig.json index fbc2f5fc190..04c1c278b8b 100644 --- a/docs/tsconfig.json +++ b/docs/tsconfig.json @@ -1,3 +1,9 @@ { - "extends": "astro/tsconfigs/strictest" + "extends": "astro/tsconfigs/strictest", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "~/*": ["src/*"] + } + } } diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000000..2e4df6cfbb2 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,87 @@ +// @ts-check +import { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import eslint from '@eslint/js'; +import tseslint from 'typescript-eslint'; +import { globalIgnores } from 'eslint/config'; +import globals from 'globals'; +import prettierConfig from 'eslint-config-prettier'; + +export default tseslint.config( + // Ignore hidden files and directories, `*.d.ts` files (as most recommendations are mostly for + // users rather than libraries), types testing files, example directories, and build directories. + globalIgnores([ + '**/.*', + '**/*.d.ts', + '**/*.test-d.ts', + '**/examples/', + '**/dist/', + '**/build/', + '**/examples/', + ]), + + // Setup Node.js globals from `globalThis` (does not include CommonJS arguments). + { + languageOptions: { + globals: { + ...globals.nodeBuiltin, + }, + }, + }, + + // Add ESLint recommended rules. + eslint.configs.recommended, + + // Add TypeScript ESLint recommended rules with type checking. + tseslint.configs.recommendedTypeChecked, + // Setup typed linting. + { + languageOptions: { + parserOptions: { + projectService: true, + tsconfigRootDir: dirname(fileURLToPath(import.meta.url)), + }, + }, + }, + // Disabled typed linting in JavaScript files. + { + files: ['**/*.js', '**/*.cjs', '**/*.mjs'], + extends: [tseslint.configs.disableTypeChecked], + }, + + // Disable all formatting rules. + prettierConfig, + + // Tweak some rules in all files. + { + rules: { + // Allow triple-slash references that we heavily use. + '@typescript-eslint/triple-slash-reference': 'off', + // Disable unbound method checks which requires another plugin to properly work with `expect` + // calls. + '@typescript-eslint/unbound-method': 'off', + // Allow empty catch blocks. + 'no-empty': ['error', { allowEmptyCatch: true }], + // Allow unused variables for sibling properties in destructuring (used to omit properties) + // or starting with `_`. + '@typescript-eslint/no-unused-vars': [ + 'error', + { + ignoreRestSiblings: true, + destructuredArrayIgnorePattern: '^_', + varsIgnorePattern: '^_', + argsIgnorePattern: '^_', + }, + ], + // Allow using `any` in rest parameter arrays, e.g. `(...args: any[]) => void`. + '@typescript-eslint/no-explicit-any': ['error', { ignoreRestArgs: true }], + // Allow duplicated types in unions as it's not an error and the extra verbosity can make it + // easier to understand some unions, e.g. for Zod input and output types. + '@typescript-eslint/no-duplicate-type-constituents': 'off', + // Allow redundant types in unions as it's not an error and we use such mechanisms to provide + // fallbacks for some types that may not be accessible in some user environments, e.g. i18n + // keys for plugins. + '@typescript-eslint/no-redundant-type-constituents': 'off', + }, + } +); diff --git a/examples/basics/README.md b/examples/basics/README.md index f95661b59b0..c387254c9c8 100644 --- a/examples/basics/README.md +++ b/examples/basics/README.md @@ -6,8 +6,14 @@ npm create astro@latest -- --template starlight ``` +<!-- ASTRO:REMOVE:START --> + [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics) [![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/starlight/tree/main/examples/basics) +[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/withastro/starlight&create_from_path=examples/basics) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fwithastro%2Fstarlight%2Ftree%2Fmain%2Fexamples%2Fbasics&project-name=my-starlight-docs&repository-name=my-starlight-docs) + +<!-- ASTRO:REMOVE:END --> > 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! @@ -21,9 +27,8 @@ Inside of your Astro + Starlight project, you'll see the following folders and f ├── src/ │ ├── assets/ │ ├── content/ -│ │ ├── docs/ -│ │ └── config.ts -│ └── env.d.ts +│ │ └── docs/ +│ └── content.config.ts ├── astro.config.mjs ├── package.json └── tsconfig.json diff --git a/examples/basics/astro.config.mjs b/examples/basics/astro.config.mjs index 9eacfd175f4..9a25601baa4 100644 --- a/examples/basics/astro.config.mjs +++ b/examples/basics/astro.config.mjs @@ -1,3 +1,4 @@ +// @ts-check import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; @@ -6,15 +7,13 @@ export default defineConfig({ integrations: [ starlight({ title: 'My Docs', - social: { - github: 'https://github.com/withastro/starlight', - }, + social: [{ icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' }], sidebar: [ { label: 'Guides', items: [ // Each item here is one entry in the navigation menu. - { label: 'Example Guide', link: '/guides/example/' }, + { label: 'Example Guide', slug: 'guides/example' }, ], }, { diff --git a/examples/basics/package.json b/examples/basics/package.json index b660c16893f..7d9815760cb 100644 --- a/examples/basics/package.json +++ b/examples/basics/package.json @@ -11,8 +11,8 @@ "astro": "astro" }, "dependencies": { - "@astrojs/starlight": "^0.10.3", - "astro": "^3.2.1", - "sharp": "^0.32.5" + "@astrojs/starlight": "^0.37.6", + "astro": "^5.6.1", + "sharp": "^0.34.2" } } diff --git a/examples/basics/src/content.config.ts b/examples/basics/src/content.config.ts new file mode 100644 index 00000000000..d9ee8c9d1c9 --- /dev/null +++ b/examples/basics/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/examples/basics/src/content/config.ts b/examples/basics/src/content/config.ts deleted file mode 100644 index 9df91b60444..00000000000 --- a/examples/basics/src/content/config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineCollection } from 'astro:content'; -import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; - -export const collections = { - docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), -}; diff --git a/examples/basics/src/content/docs/index.mdx b/examples/basics/src/content/docs/index.mdx index 117179dbb49..e6ed51fbc0e 100644 --- a/examples/basics/src/content/docs/index.mdx +++ b/examples/basics/src/content/docs/index.mdx @@ -1,7 +1,7 @@ --- title: Welcome to Starlight description: Get started building your docs site with Starlight. -template: splash +template: splash # Remove or comment out this line to display the site sidebar on this page. hero: tagline: Congrats on setting up a new Starlight project! image: @@ -10,10 +10,10 @@ hero: - text: Example Guide link: /guides/example/ icon: right-arrow - variant: primary - text: Read the Starlight docs link: https://starlight.astro.build icon: external + variant: minimal --- import { Card, CardGrid } from '@astrojs/starlight/components'; @@ -24,6 +24,10 @@ import { Card, CardGrid } from '@astrojs/starlight/components'; <Card title="Update content" icon="pencil"> Edit `src/content/docs/index.mdx` to see this page change. </Card> + <Card title="Change page layout" icon="document"> + Delete `template: splash` in `src/content/docs/index.mdx` to display a + sidebar on this page. + </Card> <Card title="Add new content" icon="add-document"> Add Markdown or MDX files to `src/content/docs` to create new pages. </Card> diff --git a/examples/basics/src/content/docs/reference/example.md b/examples/basics/src/content/docs/reference/example.md index ac8cfa8bc3a..0224f096ce6 100644 --- a/examples/basics/src/content/docs/reference/example.md +++ b/examples/basics/src/content/docs/reference/example.md @@ -4,7 +4,7 @@ description: A reference page in my new Starlight docs site. --- Reference pages are ideal for outlining how things work in terse and clear terms. -Less concerned with telling a story or addressing a specific use case, they should give a comprehensive outline of what your documenting. +Less concerned with telling a story or addressing a specific use case, they should give a comprehensive outline of what you're documenting. ## Further reading diff --git a/examples/basics/tsconfig.json b/examples/basics/tsconfig.json index bcbf8b50906..8bf91d3bb99 100644 --- a/examples/basics/tsconfig.json +++ b/examples/basics/tsconfig.json @@ -1,3 +1,5 @@ { - "extends": "astro/tsconfigs/strict" + "extends": "astro/tsconfigs/strict", + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] } diff --git a/docs-i18n-tracker/.gitignore b/examples/markdoc/.gitignore similarity index 100% rename from docs-i18n-tracker/.gitignore rename to examples/markdoc/.gitignore diff --git a/examples/markdoc/.vscode/extensions.json b/examples/markdoc/.vscode/extensions.json new file mode 100644 index 00000000000..a83595b151c --- /dev/null +++ b/examples/markdoc/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode", "stripe.markdoc-language-support"], + "unwantedRecommendations": [] +} diff --git a/docs/.vscode/launch.json b/examples/markdoc/.vscode/launch.json similarity index 100% rename from docs/.vscode/launch.json rename to examples/markdoc/.vscode/launch.json diff --git a/examples/markdoc/README.md b/examples/markdoc/README.md new file mode 100644 index 00000000000..b91ff83dfe1 --- /dev/null +++ b/examples/markdoc/README.md @@ -0,0 +1,59 @@ +# Starlight Starter Kit: Markdoc + +[![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.build) + +``` +npm create astro@latest -- --template starlight/markdoc +``` + +<!-- ASTRO:REMOVE:START --> + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/starlight/tree/main/examples/markdoc) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/starlight/tree/main/examples/markdoc) +[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/withastro/starlight&create_from_path=examples/markdoc) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fwithastro%2Fstarlight%2Ftree%2Fmain%2Fexamples%2Fmarkdoc&project-name=my-starlight-docs&repository-name=my-starlight-docs) + +<!-- ASTRO:REMOVE:END --> + +> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! + +## 🚀 Project Structure + +Inside of your Astro + Starlight project, you'll see the following folders and files: + +``` +. +├── public/ +├── src/ +│ ├── assets/ +│ ├── content/ +│ │ └── docs/ +│ └── content.config.ts +├── astro.config.mjs +├── markdoc.config.mjs +├── package.json +└── tsconfig.json +``` + +Starlight looks for `.md`, `.mdx` or `.mdoc` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name. + +Images can be added to `src/assets/` and embedded in Markdown with a relative link. + +Static assets, like favicons, can be placed in the `public/` directory. + +## 🧞 Commands + +All commands are run from the root of the project, from a terminal: + +| Command | Action | +| :------------------------ | :----------------------------------------------- | +| `npm install` | Installs dependencies | +| `npm run dev` | Starts local dev server at `localhost:4321` | +| `npm run build` | Build your production site to `./dist/` | +| `npm run preview` | Preview your build locally, before deploying | +| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | +| `npm run astro -- --help` | Get help using the Astro CLI | + +## 👀 Want to learn more? + +Check out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat). diff --git a/examples/markdoc/astro.config.mjs b/examples/markdoc/astro.config.mjs new file mode 100644 index 00000000000..949f3fcc1bc --- /dev/null +++ b/examples/markdoc/astro.config.mjs @@ -0,0 +1,28 @@ +// @ts-check +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; +import markdoc from '@astrojs/markdoc'; + +// https://astro.build/config +export default defineConfig({ + integrations: [ + markdoc(), + starlight({ + title: 'My Docs', + social: [{ icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' }], + sidebar: [ + { + label: 'Guides', + items: [ + // Each item here is one entry in the navigation menu. + { label: 'Example Guide', slug: 'guides/example' }, + ], + }, + { + label: 'Reference', + autogenerate: { directory: 'reference' }, + }, + ], + }), + ], +}); diff --git a/examples/markdoc/markdoc.config.mjs b/examples/markdoc/markdoc.config.mjs new file mode 100644 index 00000000000..ecda158d592 --- /dev/null +++ b/examples/markdoc/markdoc.config.mjs @@ -0,0 +1,7 @@ +import { defineMarkdocConfig } from '@astrojs/markdoc/config'; +import starlightMarkdoc from '@astrojs/starlight-markdoc'; + +// https://docs.astro.build/en/guides/integrations-guide/markdoc/ +export default defineMarkdocConfig({ + extends: [starlightMarkdoc()], +}); diff --git a/examples/markdoc/package.json b/examples/markdoc/package.json new file mode 100644 index 00000000000..dcb2ed4f7e4 --- /dev/null +++ b/examples/markdoc/package.json @@ -0,0 +1,20 @@ +{ + "name": "@example/starlight-markdoc", + "type": "module", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/markdoc": "^0.13.3", + "@astrojs/starlight": "^0.37.6", + "@astrojs/starlight-markdoc": "^0.5.1", + "astro": "^5.6.1", + "sharp": "^0.34.2" + } +} diff --git a/examples/markdoc/public/favicon.svg b/examples/markdoc/public/favicon.svg new file mode 100644 index 00000000000..cba5ac140a2 --- /dev/null +++ b/examples/markdoc/public/favicon.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M81 36 64 0 47 36l-1 2-9-10a6 6 0 0 0-9 9l10 10h-2L0 64l36 17h2L28 91a6 6 0 1 0 9 9l9-10 1 2 17 36 17-36v-2l9 10a6 6 0 1 0 9-9l-9-9 2-1 36-17-36-17-2-1 9-9a6 6 0 1 0-9-9l-9 10v-2Zm-17 2-2 5c-4 8-11 15-19 19l-5 2 5 2c8 4 15 11 19 19l2 5 2-5c4-8 11-15 19-19l5-2-5-2c-8-4-15-11-19-19l-2-5Z" clip-rule="evenodd"/><path d="M118 19a6 6 0 0 0-9-9l-3 3a6 6 0 1 0 9 9l3-3Zm-96 4c-2 2-6 2-9 0l-3-3a6 6 0 1 1 9-9l3 3c3 2 3 6 0 9Zm0 82c-2-2-6-2-9 0l-3 3a6 6 0 1 0 9 9l3-3c3-2 3-6 0-9Zm96 4a6 6 0 0 1-9 9l-3-3a6 6 0 1 1 9-9l3 3Z"/><style>path{fill:#000}@media (prefers-color-scheme:dark){path{fill:#fff}}</style></svg> \ No newline at end of file diff --git a/examples/markdoc/src/assets/houston.webp b/examples/markdoc/src/assets/houston.webp new file mode 100644 index 00000000000..930c164974a Binary files /dev/null and b/examples/markdoc/src/assets/houston.webp differ diff --git a/examples/markdoc/src/content.config.ts b/examples/markdoc/src/content.config.ts new file mode 100644 index 00000000000..d9ee8c9d1c9 --- /dev/null +++ b/examples/markdoc/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/examples/markdoc/src/content/docs/guides/example.mdoc b/examples/markdoc/src/content/docs/guides/example.mdoc new file mode 100644 index 00000000000..ebd0f3bc762 --- /dev/null +++ b/examples/markdoc/src/content/docs/guides/example.mdoc @@ -0,0 +1,11 @@ +--- +title: Example Guide +description: A guide in my new Starlight docs site. +--- + +Guides lead a user through a specific task they want to accomplish, often with a sequence of steps. +Writing a good guide requires thinking about what your users are trying to do. + +## Further reading + +- Read [about how-to guides](https://diataxis.fr/how-to-guides/) in the Diátaxis framework diff --git a/examples/markdoc/src/content/docs/index.mdoc b/examples/markdoc/src/content/docs/index.mdoc new file mode 100644 index 00000000000..11ba327bc00 --- /dev/null +++ b/examples/markdoc/src/content/docs/index.mdoc @@ -0,0 +1,44 @@ +--- +title: Welcome to Starlight +description: Get started building your docs site with Starlight. +template: splash # Remove or comment out this line to display the site sidebar on this page. +hero: + title: Welcome to Starlight with Markdoc + tagline: Congrats on setting up a new Starlight project! + image: + file: ../../assets/houston.webp + actions: + - text: Example Guide + link: /guides/example/ + icon: right-arrow + - text: Read the Starlight docs + link: https://starlight.astro.build + icon: external + variant: minimal +--- + +## Next steps + +{% cardgrid stagger=true %} + +{% card title="Update content" icon="pencil" %} +Edit `src/content/docs/index.mdoc` to see this page change. +{% /card %} + +{% card title="Change page layout" icon="document" %} +Delete `template: splash` in `src/content/docs/index.mdoc` to display a sidebar on this page. +{% /card %} + +{% card title="Add new content" icon="add-document" %} +Add Markdoc files to `src/content/docs` to create new pages. +{% /card %} + +{% card title="Configure your site" icon="setting" %} +Edit your `sidebar` and other config in `astro.config.mjs`. +{% /card %} + +{% card title="Read the docs" icon="open-book" %} +Learn more in [the Starlight Docs](https://starlight.astro.build/). +{% /card %} + +{% /cardgrid %} diff --git a/examples/markdoc/src/content/docs/reference/example.mdoc b/examples/markdoc/src/content/docs/reference/example.mdoc new file mode 100644 index 00000000000..0224f096ce6 --- /dev/null +++ b/examples/markdoc/src/content/docs/reference/example.mdoc @@ -0,0 +1,11 @@ +--- +title: Example Reference +description: A reference page in my new Starlight docs site. +--- + +Reference pages are ideal for outlining how things work in terse and clear terms. +Less concerned with telling a story or addressing a specific use case, they should give a comprehensive outline of what you're documenting. + +## Further reading + +- Read [about reference](https://diataxis.fr/reference/) in the Diátaxis framework diff --git a/examples/markdoc/tsconfig.json b/examples/markdoc/tsconfig.json new file mode 100644 index 00000000000..8bf91d3bb99 --- /dev/null +++ b/examples/markdoc/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "astro/tsconfigs/strict", + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] +} diff --git a/examples/tailwind/README.md b/examples/tailwind/README.md index 97352ede18a..ecdcadb9376 100644 --- a/examples/tailwind/README.md +++ b/examples/tailwind/README.md @@ -6,8 +6,14 @@ npm create astro@latest -- --template starlight/tailwind ``` +<!-- ASTRO:REMOVE:START --> + [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/starlight/tree/main/examples/tailwind) [![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/starlight/tree/main/examples/tailwind) +[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/withastro/starlight&create_from_path=examples/tailwind) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fwithastro%2Fstarlight%2Ftree%2Fmain%2Fexamples%2Ftailwind&project-name=my-starlight-docs&repository-name=my-starlight-docs) + +<!-- ASTRO:REMOVE:END --> > 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! @@ -21,12 +27,12 @@ Inside of your Astro + Starlight project, you'll see the following folders and f ├── src/ │ ├── assets/ │ ├── content/ -│ │ ├── docs/ -│ │ └── config.ts -│ └── env.d.ts +│ │ └── docs/ +│ ├── styles/ +│ │ └── global.css +│ └── content.config.ts ├── astro.config.mjs ├── package.json -├── tailwind.config.cjs └── tsconfig.json ``` @@ -36,6 +42,8 @@ Images can be added to `src/assets/` and embedded in Markdown with a relative li Static assets, like favicons, can be placed in the `public/` directory. +The project includes [Tailwind CSS](https://starlight.astro.build/guides/css-and-tailwind/#tailwind-css) for styling. Customize your design by modifying `src/styles/global.css`. + ## 🧞 Commands All commands are run from the root of the project, from a terminal: diff --git a/examples/tailwind/astro.config.mjs b/examples/tailwind/astro.config.mjs index 99448763e81..c9fd5e4ccc6 100644 --- a/examples/tailwind/astro.config.mjs +++ b/examples/tailwind/astro.config.mjs @@ -1,21 +1,20 @@ +// @ts-check import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; -import tailwind from '@astrojs/tailwind'; +import tailwindcss from '@tailwindcss/vite'; // https://astro.build/config export default defineConfig({ integrations: [ starlight({ title: 'Docs with Tailwind', - social: { - github: 'https://github.com/withastro/starlight', - }, + social: [{ icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' }], sidebar: [ { label: 'Guides', items: [ // Each item here is one entry in the navigation menu. - { label: 'Example Guide', link: '/guides/example/' }, + { label: 'Example Guide', slug: 'guides/example' }, ], }, { @@ -23,8 +22,10 @@ export default defineConfig({ autogenerate: { directory: 'reference' }, }, ], - customCss: ['./src/tailwind.css'], + customCss: ['./src/styles/global.css'], }), - tailwind({ applyBaseStyles: false }), ], + vite: { + plugins: [tailwindcss()], + }, }); diff --git a/examples/tailwind/package.json b/examples/tailwind/package.json index 7d425f3f332..804d523e853 100644 --- a/examples/tailwind/package.json +++ b/examples/tailwind/package.json @@ -11,11 +11,11 @@ "astro": "astro" }, "dependencies": { - "@astrojs/starlight": "^0.10.3", - "@astrojs/starlight-tailwind": "^2.0.0", - "@astrojs/tailwind": "^5.0.0", - "astro": "^3.2.1", - "sharp": "^0.32.5", - "tailwindcss": "^3.3.3" + "@astrojs/starlight": "^0.37.6", + "@astrojs/starlight-tailwind": "^4.0.2", + "@tailwindcss/vite": "^4.0.7", + "astro": "^5.6.1", + "sharp": "^0.34.2", + "tailwindcss": "^4.0.7" } } diff --git a/examples/tailwind/src/content.config.ts b/examples/tailwind/src/content.config.ts new file mode 100644 index 00000000000..d9ee8c9d1c9 --- /dev/null +++ b/examples/tailwind/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/examples/tailwind/src/content/config.ts b/examples/tailwind/src/content/config.ts deleted file mode 100644 index 9df91b60444..00000000000 --- a/examples/tailwind/src/content/config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineCollection } from 'astro:content'; -import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; - -export const collections = { - docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), -}; diff --git a/examples/tailwind/src/content/docs/index.mdx b/examples/tailwind/src/content/docs/index.mdx index aa8d1a65791..c88de4b6aa1 100644 --- a/examples/tailwind/src/content/docs/index.mdx +++ b/examples/tailwind/src/content/docs/index.mdx @@ -1,7 +1,7 @@ --- title: Welcome to Starlight description: Get started building your docs site with Starlight. -template: splash +template: splash # Remove or comment out this line to display the site sidebar on this page. hero: title: | Welcome to Starlight with @@ -20,10 +20,10 @@ hero: - text: Example Guide link: /guides/example/ icon: right-arrow - variant: primary - text: Read the Starlight docs link: https://starlight.astro.build icon: external + variant: minimal --- import { Card, CardGrid } from '@astrojs/starlight/components'; @@ -34,6 +34,10 @@ import { Card, CardGrid } from '@astrojs/starlight/components'; <Card title="Update content" icon="pencil"> Edit `src/content/docs/index.mdx` to see this page change. </Card> + <Card title="Change page layout" icon="document"> + Delete `template: splash` in `src/content/docs/index.mdx` to display a + sidebar on this page. + </Card> <Card title="Add new content" icon="add-document"> Add Markdown or MDX files to `src/content/docs` to create new pages. </Card> diff --git a/examples/tailwind/src/content/docs/reference/example.md b/examples/tailwind/src/content/docs/reference/example.md index ac8cfa8bc3a..0224f096ce6 100644 --- a/examples/tailwind/src/content/docs/reference/example.md +++ b/examples/tailwind/src/content/docs/reference/example.md @@ -4,7 +4,7 @@ description: A reference page in my new Starlight docs site. --- Reference pages are ideal for outlining how things work in terse and clear terms. -Less concerned with telling a story or addressing a specific use case, they should give a comprehensive outline of what your documenting. +Less concerned with telling a story or addressing a specific use case, they should give a comprehensive outline of what you're documenting. ## Further reading diff --git a/examples/tailwind/src/env.d.ts b/examples/tailwind/src/env.d.ts deleted file mode 100644 index acef35f175a..00000000000 --- a/examples/tailwind/src/env.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -/// <reference path="../.astro/types.d.ts" /> -/// <reference types="astro/client" /> diff --git a/examples/tailwind/src/styles/global.css b/examples/tailwind/src/styles/global.css new file mode 100644 index 00000000000..2d4c87dff33 --- /dev/null +++ b/examples/tailwind/src/styles/global.css @@ -0,0 +1,17 @@ +@layer base, starlight, theme, components, utilities; + +@import '@astrojs/starlight-tailwind'; +@import 'tailwindcss/theme.css' layer(theme); +@import 'tailwindcss/utilities.css' layer(utilities); + +@theme { + /* + Configure your Tailwind theme that will be used by Starlight. + https://starlight.astro.build/guides/css-and-tailwind/#styling-starlight-with-tailwind + */ +} + +/* +Add additional Tailwind styles to this file: +https://tailwindcss.com/docs/adding-custom-styles#using-custom-css +*/ diff --git a/examples/tailwind/src/tailwind.css b/examples/tailwind/src/tailwind.css deleted file mode 100644 index 26664bc8816..00000000000 --- a/examples/tailwind/src/tailwind.css +++ /dev/null @@ -1,8 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -/* -Add additional Tailwind styles to this file, for example with @layer: -https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer -*/ diff --git a/examples/tailwind/tailwind.config.cjs b/examples/tailwind/tailwind.config.cjs deleted file mode 100644 index 474874c6179..00000000000 --- a/examples/tailwind/tailwind.config.cjs +++ /dev/null @@ -1,18 +0,0 @@ -const colors = require('tailwindcss/colors'); -const starlightPlugin = require('@astrojs/starlight-tailwind'); - -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: { - colors: { - // Your preferred accent color. Indigo is closest to Starlight’s defaults. - accent: colors.indigo, - // Your preferred gray scale. Zinc is closest to Starlight’s defaults. - gray: colors.zinc, - }, - }, - }, - plugins: [starlightPlugin()], -}; diff --git a/examples/tailwind/tsconfig.json b/examples/tailwind/tsconfig.json index bcbf8b50906..8bf91d3bb99 100644 --- a/examples/tailwind/tsconfig.json +++ b/examples/tailwind/tsconfig.json @@ -1,3 +1,5 @@ { - "extends": "astro/tsconfigs/strict" + "extends": "astro/tsconfigs/strict", + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] } diff --git a/package.json b/package.json index a5e64923125..08bb9eebf47 100644 --- a/package.json +++ b/package.json @@ -4,37 +4,61 @@ "version": "1.0.0", "description": "", "scripts": { - "build:examples": "pnpm --filter '@example/*' build", + "build:examples": "pnpm --no-bail --workspace-concurrency 1 --filter '@example/*' build", + "lint": "eslint . --max-warnings 0", "size": "size-limit", "version": "pnpm changeset version && pnpm i --no-frozen-lockfile", - "format": "prettier -w --cache --plugin prettier-plugin-astro ." + "format": "prettier -w --cache --plugin prettier-plugin-astro .", + "typecheck": "astro check --minimumSeverity warning --noSync && pnpm --filter starlight-docs typecheck" }, "license": "MIT", "devDependencies": { - "@changesets/changelog-github": "^0.4.8", - "@changesets/cli": "^2.26.1", - "@size-limit/file": "^8.2.4", - "astro": "^3.2.1", - "prettier": "^3.0.0", - "prettier-plugin-astro": "^0.11.0", - "size-limit": "^8.2.4" + "@astrojs/check": "^0.9.4", + "@changesets/changelog-github": "^0.5.0", + "@changesets/cli": "^2.27.9", + "@eslint/js": "^9.33.0", + "@size-limit/file": "^11.1.6", + "astro": "^5.6.1", + "eslint": "^9.33.0", + "eslint-config-prettier": "^10.1.8", + "globals": "^16.3.0", + "prettier": "^3.3.3", + "prettier-plugin-astro": "^0.14.1", + "size-limit": "^11.1.6", + "typescript": "^5.6.3", + "typescript-eslint": "^8.39.1" }, - "packageManager": "pnpm@8.7.4", + "packageManager": "pnpm@9.15.9", "size-limit": [ { "name": "/index.html", "path": "examples/basics/dist/index.html", - "limit": "14 kB" + "limit": "10 kB", + "gzip": true }, { "name": "/_astro/*.js", "path": "examples/basics/dist/_astro/*.js", - "limit": "20 kB" + "limit": "27 kB", + "gzip": true }, { "name": "/_astro/*.css", - "path": "examples/basics/dist/_astro/*.css", - "limit": "12 kB" + "path": [ + "examples/basics/dist/_astro/*.css", + "!examples/basics/dist/_astro/print.*.css" + ], + "limit": "14.75 kB", + "gzip": true } - ] + ], + "pnpm": { + "peerDependencyRules": { + "ignoreMissing": [ + "@algolia/client-search", + "playwright", + "search-insights" + ] + } + } } diff --git a/packages/docsearch/CHANGELOG.md b/packages/docsearch/CHANGELOG.md new file mode 100644 index 00000000000..6e006b168e1 --- /dev/null +++ b/packages/docsearch/CHANGELOG.md @@ -0,0 +1,74 @@ +# @astrojs/starlight-docsearch + +## 0.6.1 + +### Patch Changes + +- [#3500](https://github.com/withastro/starlight/pull/3500) [`7700456`](https://github.com/withastro/starlight/commit/770045663c8ca3cc44983dd0d444955eba441243) Thanks [@delucis](https://github.com/delucis)! - This is the first release published with OIDC trusted publishing. + +## 0.6.0 + +### Minor Changes + +- [#2578](https://github.com/withastro/starlight/pull/2578) [`f895f75`](https://github.com/withastro/starlight/commit/f895f75b17f36c826cc871ba1826e5ae1dff44ca) and [#2390](https://github.com/withastro/starlight/pull/2390) [`f493361`](https://github.com/withastro/starlight/commit/f493361d7b64a3279980e0f046c3a52196ab94e0) Thanks [@HiDeoo](https://github.com/HiDeoo) and [@delucis](https://github.com/delucis)! + ⚠️ **BREAKING CHANGE:** The minimum supported version of Starlight is now 0.32.0 + + Please use the `@astrojs/upgrade` command to upgrade your project: + + ```sh + npx @astrojs/upgrade + ``` + +## 0.5.0 + +### Minor Changes + +- [#2822](https://github.com/withastro/starlight/pull/2822) [`e56586a`](https://github.com/withastro/starlight/commit/e56586add37188b43f3f4c8c15883724fe8fdf87) Thanks [@KianNH](https://github.com/KianNH)! - Adds a new `clientOptionsModule` plugin option to support configuring unserializable DocSearch options such as `resultsFooterComponent()`. + + See [“DocSearch configuration”](https://starlight.astro.build/guides/site-search/#docsearch-configuration) in the Starlight docs for more details. + +## 0.4.0 + +### Minor Changes + +- [#2612](https://github.com/withastro/starlight/pull/2612) [`8d5a4e8`](https://github.com/withastro/starlight/commit/8d5a4e8000d9e3a4bb9ca8178767cf3d8bc48773) Thanks [@HiDeoo](https://github.com/HiDeoo)! - ⚠️ **BREAKING CHANGE:** The minimum supported version of Starlight is now 0.30.0 + + Please use the `@astrojs/upgrade` command to upgrade your project: + + ```sh + npx @astrojs/upgrade + ``` + +### Patch Changes + +- [#2664](https://github.com/withastro/starlight/pull/2664) [`62ff007`](https://github.com/withastro/starlight/commit/62ff0074d9a3f82e46f5c62db85c04d87ff5e931) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Publishes provenance containing verifiable data to link a package back to its source repository and the specific build instructions used to publish it. + +## 0.3.0 + +### Minor Changes + +- [#2589](https://github.com/withastro/starlight/pull/2589) [`d4cf8cc`](https://github.com/withastro/starlight/commit/d4cf8cc5633dc87474f943657ec4846e821f7f5b) Thanks [@delucis](https://github.com/delucis)! - Adds support for some more of the DocSearch component’s configuration options + +## 0.2.0 + +### Minor Changes + +- [#1923](https://github.com/withastro/starlight/pull/1923) [`5269aad`](https://github.com/withastro/starlight/commit/5269aad928773ae08b35ba8e19c0f2832d0d2c89) Thanks [@HiDeoo](https://github.com/HiDeoo)! - ⚠️ **BREAKING CHANGE:** The minimum supported version of Starlight is now 0.28.0 + + Please use the `@astrojs/upgrade` command to upgrade your project: + + ```sh + npx @astrojs/upgrade + ``` + +## 0.1.1 + +### Patch Changes + +- [#2009](https://github.com/withastro/starlight/pull/2009) [`1e8bfe4`](https://github.com/withastro/starlight/commit/1e8bfe4b7bb8e958ce22e65c4719e7f281cd6e88) Thanks [@delucis](https://github.com/delucis)! - Updates Docsearch packages to 3.6.0 + +## 0.1.0 + +### Minor Changes + +- [#1168](https://github.com/withastro/starlight/pull/1168) [`8155d1a`](https://github.com/withastro/starlight/commit/8155d1a27c5a783c0abdfb6ce1ec066c6926290d) Thanks [@delucis](https://github.com/delucis)! - Adds a Starlight plugin to support using Algolia DocSearch as the Starlight search provider. diff --git a/packages/docsearch/DocSearch.astro b/packages/docsearch/DocSearch.astro new file mode 100644 index 00000000000..f50c208dc01 --- /dev/null +++ b/packages/docsearch/DocSearch.astro @@ -0,0 +1,143 @@ +--- +import '@docsearch/css/dist/modal.css'; +import type docsearch from '@docsearch/js'; +import './variables.css'; + +type DocSearchTranslationProps = Pick< + Parameters<typeof docsearch>[0], + 'placeholder' | 'translations' +>; + +const pick = (keyStart: string) => + Object.fromEntries( + Object.entries(Astro.locals.t.all()) + .filter(([key]) => key.startsWith(keyStart)) + .map(([key, value]) => [key.replace(keyStart, ''), value]) + ); + +const docsearchTranslations: DocSearchTranslationProps = { + placeholder: Astro.locals.t('search.label'), + translations: { + button: { + buttonText: Astro.locals.t('search.label'), + buttonAriaLabel: Astro.locals.t('search.label'), + }, + modal: { + searchBox: pick('docsearch.searchBox.'), + startScreen: pick('docsearch.startScreen.'), + errorScreen: pick('docsearch.errorScreen.'), + footer: pick('docsearch.footer.'), + noResultsScreen: pick('docsearch.noResultsScreen.'), + }, + }, +}; +--- + +<sl-doc-search data-translations={JSON.stringify(docsearchTranslations)}> + <button + type="button" + class="DocSearch DocSearch-Button" + aria-label={Astro.locals.t('search.label')} + > + <span class="DocSearch-Button-Container"> + <svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"> + <path + d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" + stroke="currentColor" + fill="none" + fill-rule="evenodd" + stroke-linecap="round" + stroke-linejoin="round"></path> + </svg> + <span class="DocSearch-Button-Placeholder">{Astro.locals.t('search.label')}</span> + </span> + <span class="DocSearch-Button-Keys"></span> + </button> +</sl-doc-search> + +<style is:global> + .DocSearch-Button { + display: flex; + align-items: center; + gap: 0.5rem; + border: 0; + background-color: transparent; + color: var(--sl-color-gray-1); + cursor: pointer; + height: 2.5rem; + font-size: var(--sl-text-xl); + } + .DocSearch-Button-Container { + display: contents; + } + .DocSearch-Search-Icon { + width: 0.875em; + height: 0.875em; + stroke-width: 0.125rem; + } + .DocSearch-Button-Placeholder, + .DocSearch-Button-Keys, + .DocSearch-Button-Key { + display: none; + } + + @media (min-width: 50rem) { + sl-doc-search { + width: 100%; + } + + .DocSearch-Button { + border: 1px solid var(--sl-color-gray-5); + border-radius: 0.5rem; + padding-inline-start: 0.75rem; + padding-inline-end: 1rem; + background-color: var(--sl-color-black); + color: var(--sl-color-gray-2); + font-size: var(--sl-text-sm); + width: 100%; + max-width: 22rem; + } + .DocSearch-Button:hover { + border-color: var(--sl-color-gray-2); + color: var(--sl-color-white); + } + + .DocSearch-Button-Placeholder, + .DocSearch-Button-Keys { + display: flex; + } + .DocSearch-Button-Keys { + margin-inline-start: auto; + } + .DocSearch-Button-Keys::before { + content: ''; + width: 1em; + height: 1em; + -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M17 2H7a5 5 0 0 0-5 5v10a5 5 0 0 0 5 5h10a5 5 0 0 0 5-5V7a5 5 0 0 0-5-5Zm3 15a3 3 0 0 1-3 3H7a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v10Z'%3E%3C/path%3E%3Cpath d='M15.293 6.707a1 1 0 1 1 1.414 1.414l-8.485 8.486a1 1 0 0 1-1.414-1.415l8.485-8.485Z'%3E%3C/path%3E%3C/svg%3E"); + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M17 2H7a5 5 0 0 0-5 5v10a5 5 0 0 0 5 5h10a5 5 0 0 0 5-5V7a5 5 0 0 0-5-5Zm3 15a3 3 0 0 1-3 3H7a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v10Z'%3E%3C/path%3E%3Cpath d='M15.293 6.707a1 1 0 1 1 1.414 1.414l-8.485 8.486a1 1 0 0 1-1.414-1.415l8.485-8.485Z'%3E%3C/path%3E%3C/svg%3E"); + -webkit-mask-size: 100%; + mask-size: 100%; + background-color: currentColor; + } + } +</style> + +<script> + import config from 'virtual:starlight/docsearch-config'; + + class StarlightDocSearch extends HTMLElement { + constructor() { + super(); + window.addEventListener('DOMContentLoaded', async () => { + const { default: docsearch } = await import('@docsearch/js'); + const options = { ...config, container: 'sl-doc-search' }; + try { + const translations = JSON.parse(this.dataset.translations || '{}'); + Object.assign(options, translations); + } catch {} + docsearch(options); + }); + } + } + customElements.define('sl-doc-search', StarlightDocSearch); +</script> diff --git a/packages/docsearch/README.md b/packages/docsearch/README.md new file mode 100644 index 00000000000..8620a36c6b2 --- /dev/null +++ b/packages/docsearch/README.md @@ -0,0 +1,18 @@ +# <img src="https://github.com/withastro/starlight/assets/357379/494fcd83-42aa-4891-87e0-87402fa0b6f3" alt="" align="left" width="40" height="40"> @astrojs/starlight-docsearch + +Algolia DocSearch plugin for the [Starlight][starlight] documentation theme for [Astro][astro]. + +## Documentation + +See the [Starlight site search guide][docs] for how to use this plugin. + +## License + +MIT + +Copyright (c) 2023–present [Starlight contributors][contributors] + +[starlight]: https://starlight.astro.build/ +[astro]: https://astro.build/ +[docs]: https://starlight.astro.build/guides/site-search/#algolia-docsearch +[contributors]: https://github.com/withastro/starlight/graphs/contributors diff --git a/packages/docsearch/index.ts b/packages/docsearch/index.ts new file mode 100644 index 00000000000..e8cc7e5df26 --- /dev/null +++ b/packages/docsearch/index.ts @@ -0,0 +1,164 @@ +import type { StarlightPlugin } from '@astrojs/starlight/types'; +import type docsearch from '@docsearch/js'; +import type { AstroUserConfig, ViteUserConfig } from 'astro'; +import { resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { z } from 'astro/zod'; + +export type DocSearchClientOptions = Omit< + Parameters<typeof docsearch>[0], + 'container' | 'translations' +>; + +type SearchOptions = DocSearchClientOptions['searchParameters']; + +/** DocSearch configuration options. */ +const DocSearchConfigSchema = z + .object({ + // Required config without which DocSearch won’t work. + /** Your Algolia application ID. */ + appId: z.string(), + /** Your Algolia Search API key. */ + apiKey: z.string(), + /** Your Algolia index name. */ + indexName: z.string(), + // Optional DocSearch component config (only the serializable properties can be included here) + /** + * The maximum number of results to display per search group. + * @default 5 + */ + maxResultsPerGroup: z.number().optional(), + /** + * Disable saving recent searches and favorites to the local storage. + * @default false + */ + disableUserPersonalization: z.boolean().optional(), + /** + * Whether to enable the Algolia Insights plugin and send search events to your DocSearch index. + * @default false + */ + insights: z.boolean().optional(), + /** + * The Algolia Search Parameters. + * @see https://www.algolia.com/doc/api-reference/search-api-parameters/ + */ + searchParameters: z.custom<SearchOptions>(), + }) + .strict() + .or( + z + .object({ + /** + * The path to a JavaScript or TypeScript file containing a default export of options to + * pass to the DocSearch client. + * + * The value can be a path to a local JS/TS file relative to the root of your project, + * e.g. `'/src/docsearch.js'`, or an npm module specifier for a package you installed, + * e.g. `'@company/docsearch-config'`. + * + * Use `clientOptionsModule` when you need to configure options that are not serializable, + * such as `transformSearchClient()` or `resultsFooterComponent()`. + * + * When `clientOptionsModule` is set, all options must be set via the module file. Other + * inline options passed to the plugin in `astro.config.mjs` will be ignored. + * + * @see https://docsearch.algolia.com/docs/api + * + * @example + * // astro.config.mjs + * // ... + * starlightDocSearch({ clientOptionsModule: './src/config/docsearch.ts' }), + * // ... + * + * // src/config/docsearch.ts + * import type { DocSearchClientOptions } from '@astrojs/starlight-docsearch'; + * + * export default { + * appId: '...', + * apiKey: '...', + * indexName: '...', + * getMissingResultsUrl({ query }) { + * return `https://github.com/algolia/docsearch/issues/new?title=${query}`; + * }, + * } satisfies DocSearchClientOptions; + */ + clientOptionsModule: z.string(), + }) + .strict() + ); + +type DocSearchUserConfig = z.infer<typeof DocSearchConfigSchema>; + +/** Starlight DocSearch plugin. */ +export default function starlightDocSearch(userConfig: DocSearchUserConfig): StarlightPlugin { + const opts = DocSearchConfigSchema.parse(userConfig); + return { + name: 'starlight-docsearch', + hooks: { + 'config:setup'({ addIntegration, config, logger, updateConfig }) { + // If the user has already has a custom override for the Search component, don't override it. + if (config.components?.Search) { + logger.warn( + 'It looks like you already have a `Search` component override in your Starlight configuration.' + ); + logger.warn( + 'To render `@astrojs/starlight-docsearch`, remove the override for the `Search` component.\n' + ); + } else { + // Otherwise, add the Search component override to the user's configuration. + updateConfig({ + pagefind: false, + components: { + ...config.components, + Search: '@astrojs/starlight-docsearch/DocSearch.astro', + }, + }); + } + + // Add an Astro integration that injects a Vite plugin to expose + // the DocSearch config via a virtual module. + addIntegration({ + name: 'starlight-docsearch', + hooks: { + 'astro:config:setup': ({ config, updateConfig }) => { + updateConfig({ + vite: { + plugins: [vitePluginDocSearch(config.root, opts)], + }, + } satisfies AstroUserConfig); + }, + }, + }); + }, + }, + }; +} + +/** Vite plugin that exposes the DocSearch config via virtual modules. */ +function vitePluginDocSearch(root: URL, config: DocSearchUserConfig): VitePlugin { + const moduleId = 'virtual:starlight/docsearch-config'; + const resolvedModuleId = `\0${moduleId}`; + + const resolveId = (id: string, base = root) => + JSON.stringify(id.startsWith('.') ? resolve(fileURLToPath(base), id) : id); + + const moduleContent = ` + ${ + 'clientOptionsModule' in config + ? `export { default } from ${resolveId(config.clientOptionsModule)};` + : `export default ${JSON.stringify(config)};` + } + `; + + return { + name: 'vite-plugin-starlight-docsearch-config', + load(id) { + return id === resolvedModuleId ? moduleContent : undefined; + }, + resolveId(id) { + return id === moduleId ? resolvedModuleId : undefined; + }, + }; +} + +type VitePlugin = NonNullable<ViteUserConfig['plugins']>[number]; diff --git a/packages/docsearch/package.json b/packages/docsearch/package.json new file mode 100644 index 00000000000..b2f7c380551 --- /dev/null +++ b/packages/docsearch/package.json @@ -0,0 +1,40 @@ +{ + "name": "@astrojs/starlight-docsearch", + "version": "0.6.1", + "description": "Algolia DocSearch plugin for the Starlight documentation theme for Astro", + "author": "Chris Swithinbank <swithinbank@gmail.com>", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/withastro/starlight", + "directory": "packages/docsearch" + }, + "bugs": "https://github.com/withastro/starlight/issues", + "homepage": "https://starlight.astro.build", + "type": "module", + "files": [ + "index.ts", + "DocSearch.astro", + "schema.ts", + "variables.css", + "virtual.d.ts" + ], + "exports": { + ".": "./index.ts", + "./DocSearch.astro": "./DocSearch.astro", + "./schema": "./schema.ts" + }, + "peerDependencies": { + "@astrojs/starlight": ">=0.32.0" + }, + "dependencies": { + "@docsearch/css": "^3.6.0", + "@docsearch/js": "^3.6.0" + }, + "devDependencies": { + "@astrojs/starlight": "workspace:*" + }, + "publishConfig": { + "provenance": true + } +} diff --git a/packages/docsearch/schema.ts b/packages/docsearch/schema.ts new file mode 100644 index 00000000000..b227946c686 --- /dev/null +++ b/packages/docsearch/schema.ts @@ -0,0 +1,113 @@ +import { z } from 'astro/zod'; + +/** + * Schema for the Algolia DocSearch modal’s strings. + * + * Add this to your `src/content.config.ts`: + * + * ```js + * import { defineCollection } from 'astro:content'; + * import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; + * import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + * import { docSearchI18nSchema } from '@astrojs/starlight-docsearch/schema'; + * + * export const collections = { + * docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + * i18n: defineCollection({ + * loader: i18nLoader(), + * schema: i18nSchema({ extend: docSearchI18nSchema() }), + * }), + * }; + * ``` + * + * DocSearch uses a nested object structure. + * This schema is a flattened version of DocSearch’s `modal` translations. + * + * For example, customizing DocSearch labels looks like this + * when using the component from JavaScript: + * + * ```js + * { + * modal: { + * footer: { + * selectKeyAriaLabel: 'Return key', + * }, + * }, + * }, + * ``` + * + * In your Starlight translation files, set this using the object path inside `modal` + * as the key for each string, prefixed with `docsearch`: + * + * ```json + * { + * "docsearch.footer.selectKeyAriaLabel": "Return key" + * } + * ``` + * + * @see https://docsearch.algolia.com/docs/api/#translations + */ +export const docSearchI18nSchema = () => + z + .object({ + // SEARCH BOX + /** Default: `Clear the query` */ + 'docsearch.searchBox.resetButtonTitle': z.string(), + /** Default: `Clear the query` */ + 'docsearch.searchBox.resetButtonAriaLabel': z.string(), + /** Default: `Cancel` */ + 'docsearch.searchBox.cancelButtonText': z.string(), + /** Default: `Cancel` */ + 'docsearch.searchBox.cancelButtonAriaLabel': z.string(), + /** Default: `Search` */ + 'docsearch.searchBox.searchInputLabel': z.string(), + + // START SCREEN + /** Default: `Recent` */ + 'docsearch.startScreen.recentSearchesTitle': z.string(), + /** Default: `No recent searches` */ + 'docsearch.startScreen.noRecentSearchesText': z.string(), + /** Default: `Save this search` */ + 'docsearch.startScreen.saveRecentSearchButtonTitle': z.string(), + /** Default: `Remove this search from history` */ + 'docsearch.startScreen.removeRecentSearchButtonTitle': z.string(), + /** Default: `Favorite` */ + 'docsearch.startScreen.favoriteSearchesTitle': z.string(), + /** Default: `Remove this search from favorites` */ + 'docsearch.startScreen.removeFavoriteSearchButtonTitle': z.string(), + + // ERROR SCREEN + /** Default: `Unable to fetch results` */ + 'docsearch.errorScreen.titleText': z.string(), + /** Default: `You might want to check your network connection.` */ + 'docsearch.errorScreen.helpText': z.string(), + + // FOOTER + /** Default: `to select` */ + 'docsearch.footer.selectText': z.string(), + /** Default: `Enter key` */ + 'docsearch.footer.selectKeyAriaLabel': z.string(), + /** Default: `to navigate` */ + 'docsearch.footer.navigateText': z.string(), + /** Default: `Arrow up` */ + 'docsearch.footer.navigateUpKeyAriaLabel': z.string(), + /** Default: `Arrow down` */ + 'docsearch.footer.navigateDownKeyAriaLabel': z.string(), + /** Default: `to close` */ + 'docsearch.footer.closeText': z.string(), + /** Default: `Escape key` */ + 'docsearch.footer.closeKeyAriaLabel': z.string(), + /** Default: `Search by` */ + 'docsearch.footer.searchByText': z.string(), + + // NO RESULTS SCREEN + /** Default: `No results for` */ + 'docsearch.noResultsScreen.noResultsText': z.string(), + /** Default: `Try searching for` */ + 'docsearch.noResultsScreen.suggestedQueryText': z.string(), + /** Default: `Believe this query should return results?` */ + 'docsearch.noResultsScreen.reportMissingResultsText': z.string(), + /** Default: `Let us know.` */ + 'docsearch.noResultsScreen.reportMissingResultsLinkText': z.string(), + }) + .partial(); diff --git a/packages/docsearch/variables.css b/packages/docsearch/variables.css new file mode 100644 index 00000000000..b1a0ebd665d --- /dev/null +++ b/packages/docsearch/variables.css @@ -0,0 +1,47 @@ +/* Variables */ +:root { + --docsearch-primary-color: var(--sl-color-text-accent); + --docsearch-text-color: var(--sl-color-text); + --docsearch-spacing: 12px; + --docsearch-icon-stroke-width: 1.4; + --docsearch-highlight-color: var(--docsearch-primary-color); + --docsearch-muted-color: var(--sl-color-gray-3); + --docsearch-container-background: var(--sl-color-backdrop-overlay); + + /* modal */ + --docsearch-modal-width: 560px; + --docsearch-modal-height: 600px; + --docsearch-modal-background: var(--sl-color-gray-6); + --docsearch-modal-shadow: var(--sl-shadow-lg); + + /* searchbox */ + --docsearch-searchbox-height: 56px; + --docsearch-searchbox-background: var(--sl-color-gray-7, var(--sl-color-gray-6)); + --docsearch-searchbox-focus-background: var(--sl-color-black); + --docsearch-searchbox-shadow: inset 0 0 0 1px var(--docsearch-primary-color); + + /* hit */ + --docsearch-hit-height: 56px; + --docsearch-hit-color: var(--sl-color-white); + --docsearch-hit-active-color: var(--sl-color-black); + --docsearch-hit-background: var(--sl-color-black); + + /* key */ + --docsearch-key-gradient: linear-gradient( + var(--sl-color-bg-inline-code) 0%, + var(--sl-color-bg-inline-code) 100% + ); + + /* footer */ + --docsearch-footer-height: 44px; + --docsearch-footer-background: var(--sl-color-black); + --docsearch-footer-shadow: 0 -1px 0 0 var(--sl-color-hairline-light); +} + +/* Custom style overrides */ +.DocSearch-Modal { + border: 1px solid var(--sl-color-hairline-light); +} +.DocSearch-Logo svg * { + fill: var(--docsearch-muted-color); +} diff --git a/packages/docsearch/virtual.d.ts b/packages/docsearch/virtual.d.ts new file mode 100644 index 00000000000..ff493d8e08d --- /dev/null +++ b/packages/docsearch/virtual.d.ts @@ -0,0 +1,4 @@ +declare module 'virtual:starlight/docsearch-config' { + const DocSearchClientOptions: import('./index').DocSearchClientOptions; + export default DocSearchClientOptions; +} diff --git a/packages/file-icons-generator/config.ts b/packages/file-icons-generator/config.ts new file mode 100644 index 00000000000..aa4bfddd366 --- /dev/null +++ b/packages/file-icons-generator/config.ts @@ -0,0 +1,94 @@ +import type { Definitions } from '../starlight/user-components/rehype-file-tree'; + +export const seti = { + /** The GitHub repository containing the Seti UI theme using the `username/repo` format. */ + repo: 'jesseweed/seti-ui', + /** The repository branch to use. */ + branch: 'master', + /** The path to the icon mapping file in the repository. */ + mapping: 'styles/components/icons/mapping.less', + /** The path to the icon font file in the repository. */ + font: 'styles/_fonts/seti/seti.woff', + /** + * Some Seti UI icons share identical SVG for multiple icons. When converted to a font, identical + * SVGs will be saved as one unique glyph with its name being the first icon encountered. The + * other names are lost in the process and only their associated unicode character will be kept. + * As we want to access icons by their name, we need to manually map the names of identical SVGs + * to the icon name that is embedded in the font glyph. + * Note that when this happens, an error will be thrown indicating which icon is affected. + */ + aliases: { + coffee: 'cjsx', + html_erb: 'html', + less: 'json', + }, + /** + * Seti UI icons can be overridden to use another Seti UI icon. + * The key is the icon name to override and the value is the Seti icon name to use instead. + * The reason to support aliasing to another Seti UI icon is that some Seti UI icons can be + * almost identical. For example, the `npm_ignored` icon used for `npm-debug.log` files is + * identical to the `npm` icon except the npm logo is shifted 1px to the right. There is no need + * to provide a separate icon for this case and we can just use the `npm` icon instead. + */ + overrides: { + ejs: 'html', + go: 'go2', + npm_ignored: 'npm', + }, + /** + * Allows for renaming Seti UI icons to another name. + * For example, the Visual Studio Code icon used for Go is named `go2` and this is not the name + * we want to expose to the user. + * Note that renaming an icon happens after overrides are applied. + */ + renames: { + go2: 'go', + }, + /** + * A list of Seti UI icons to ignore. + * Each entry should be commented with the reason why the icon is ignored. + */ + ignores: [ + // The ReasonML SVG icon contains a path issue that makes it render a plain square instead of a + // square with the "RE" letters when converted to a font. + // This is also an issue in Visual Studio Code but considering that in Starlight, all the icons + // are also available with the `<Icon>` component, it's better to ignore it for now instead of + // providing an icon with no meaning. + 'reasonml', + ], +}; + +export const starlight = { + /** The path of the generated file in the Starlight package directory. */ + output: 'user-components/file-tree-icons.ts', + /** A prefix to add to the Seti icon names. */ + prefix: 'seti:', + /** + * The Starlight `<Icon>` component viewBox size. + * @see {@link file://../starlight/user-components/Icon.astro} + */ + iconViewBoxSize: 24, + /** + * Extra definitions for the `<FileTree>` component that add mappings using built-in Starlight + * icons. + */ + definitions: { + files: { + 'astro.config.js': 'astro', + 'astro.config.mjs': 'astro', + 'astro.config.cjs': 'astro', + 'astro.config.ts': 'astro', + 'pnpm-debug.log': 'pnpm', + 'pnpm-lock.yaml': 'pnpm', + 'pnpm-workspace.yaml': 'pnpm', + 'biome.json': 'biome', + 'bun.lockb': 'bun', + }, + extensions: { + '.astro': 'astro', + '.mdx': 'mdx', + '.pkl': 'pkl', + }, + partials: {}, + } satisfies Definitions, +}; diff --git a/packages/file-icons-generator/index.ts b/packages/file-icons-generator/index.ts new file mode 100644 index 00000000000..11642ceebec --- /dev/null +++ b/packages/file-icons-generator/index.ts @@ -0,0 +1,28 @@ +import { writeDefinitionsAndSVGs } from './utils/file'; +import { getIconSvgPaths } from './utils/font'; +import { deleteRepo, parseMapping, setupRepo } from './utils/seti'; + +/** + * Script generating definitions used by the Starlight `<FileTree>` component and associated SVGs. + * + * To do so, it clones the Seti UI repository, installs dependencies, generates icons, parses the + * mapping to generate the definitions and a list of icons to extract as SVGs, and finally extracts + * the SVGs from the font and writes the definitions and SVGs to the Starlight package in a file + * ready to be consumed by Starlight. + * + * @see {@link file://./config.ts} for the configuration used by this script. + * @see {@link file://../starlight/user-components/file-tree-icons.ts} for the generated file. + * @see {@link https://opentype.js.org/glyph-inspector.html} for a font glyph inspector. + */ + +const repoPath = await setupRepo(); + +try { + const { definitions, icons } = await parseMapping(repoPath); + + const svgPaths = await getIconSvgPaths(repoPath, icons, definitions); + + await writeDefinitionsAndSVGs(definitions, svgPaths); +} finally { + await deleteRepo(repoPath); +} diff --git a/packages/file-icons-generator/package.json b/packages/file-icons-generator/package.json new file mode 100644 index 00000000000..3fd0bbe4de4 --- /dev/null +++ b/packages/file-icons-generator/package.json @@ -0,0 +1,18 @@ +{ + "name": "starlight-file-icons-generator", + "version": "0.1.0", + "description": "Generates Starlight file icons based on the Seti UI theme", + "private": true, + "scripts": { + "build": "tsx ." + }, + "license": "MIT", + "dependencies": { + "opentype.js": "^1.3.4", + "tsx": "^4.15.2" + }, + "devDependencies": { + "@types/opentype.js": "^1.3.8" + }, + "type": "module" +} diff --git a/packages/file-icons-generator/utils/file.ts b/packages/file-icons-generator/utils/file.ts new file mode 100644 index 00000000000..6a0a38b7519 --- /dev/null +++ b/packages/file-icons-generator/utils/file.ts @@ -0,0 +1,81 @@ +import { spawn } from 'node:child_process'; +import fs from 'node:fs/promises'; +import path from 'node:path'; +import { starlight } from '../config'; +import type { Definitions } from '../../starlight/user-components/rehype-file-tree'; + +const copyrightNotice = `/** +* Based on https://github.com/elviswolcott/seti-icons which +* is derived from https://github.com/jesseweed/seti-ui/ +* +* Copyright (c) 2014 Jesse Weed +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/`; + +const generatedFileHeader = `/** +* This file was generated by the \`file-icons-generator\` package. +* Do not edit this file directly as it will be overwritten. +*/`; + +/** Write the generated definitions and SVGs to the Starlight package. */ +export async function writeDefinitionsAndSVGs( + definitions: Definitions, + svgPaths: Record<string, string> +) { + const content = `${generatedFileHeader} + +import type { Definitions } from './rehype-file-tree.ts'; + +${copyrightNotice} +export const definitions: Definitions = ${JSON.stringify(definitions)}; + +export const FileIcons = ${JSON.stringify(svgPaths)}; +`; + + const filePath = path.join('..', 'starlight', starlight.output); + + await fs.writeFile(filePath, content); + + await prettifyFile(path.resolve(filePath)); +} + +/** Run Prettier on a generated file. */ +function prettifyFile(filePath: string) { + return new Promise<void>((resolve, reject) => { + const child = spawn('pnpm', ['prettier', '-w', filePath], { + cwd: '../..', + stdio: [], + }); + + const error = new Error('Failed to run Prettier on the generated file.'); + + child.on('error', () => reject(error)); + child.on('close', (code) => { + if (code !== 0) { + reject(error); + + return; + } + + resolve(); + }); + }); +} diff --git a/packages/file-icons-generator/utils/font.ts b/packages/file-icons-generator/utils/font.ts new file mode 100644 index 00000000000..fed24f93682 --- /dev/null +++ b/packages/file-icons-generator/utils/font.ts @@ -0,0 +1,129 @@ +import opentype, { type Font, Glyph } from 'opentype.js'; +import { seti, starlight } from '../config'; +import type { Definitions } from '../../starlight/user-components/rehype-file-tree'; +import { getFont, getSetiIconName } from './seti'; + +// This matches the default precision used by the SVGO default preset. +const pathDecimalPrecision = 3; + +/** Extract SVG paths from the Seti UI icon font from a list of icon names matching font glyphs. */ +export async function getIconSvgPaths(repoPath: string, icons: string[], definitions: Definitions) { + const fontBuffer = await getFont(repoPath); + + const iconSvgs: Record<string, string> = {}; + + let font: Font; + + try { + font = opentype.parse(fontBuffer); + } catch (error) { + throw new Error('Failed to parse icon SVGs.', { cause: error }); + } + + for (const icon of icons) { + let glyph: Glyph; + + try { + // Find the glyph matching the icon name. + glyph = font.nameToGlyph(icon); + } catch { + // If the glyph is not found, this means that multiple icons share the same glyph and we have + // a mapping for such case. + const alias = getFontGlyphAlias(icon); + + // When an alias is found, we update the definitions to use the alias instead of the original + // icon name and continue to the next icon as there is no need to extract an SVG. + updateDefinitionsWithAlias(definitions, icon, alias); + continue; + } + + // We need to compute various metrics to ensure the icon properly fits the viewBox size. + const { fontSize, offsetX, offsetY } = getComputedFontSizeToFit( + glyph, + starlight.iconViewBoxSize + ); + const path = glyph.getPath(offsetX, offsetY, fontSize); + const iconName = getSetiIconName(icon); + iconSvgs[iconName] = path.toSVG(pathDecimalPrecision); + } + + return iconSvgs; +} + +/** + * Compute the font size and offsets to fit a glyph in a viewBox of a given size. + * We first try to fit the glyph in the viewBox and increase the font size until it no longer fits + * to get the best fit possible. + */ +function getComputedFontSizeToFit(glyph: opentype.Glyph, size: number, fontSize = size) { + const { width, height } = getGlyphPathDimensions(glyph, fontSize); + + // If one of the glyph path dimensions is greater than the viewBox size, we can stop here and return + // the previous font size and offsets. + if (width > size || height > size) { + const fittingFontSize = fontSize - 1; + const { x1, y1, width, height } = getGlyphPathDimensions(glyph, fittingFontSize); + + return { + fontSize: fittingFontSize, + // We need to ensure that the glyph is centered in the viewBox. + offsetX: (x1 + (width - size) / 2) * -1, + offsetY: (y1 + (height - size) / 2) * -1, + }; + } + + // If the glyph path dimensions are smaller than the viewBox size, we can increase the font size + // and try again. + return getComputedFontSizeToFit(glyph, size, fontSize + 1); +} + +/** Returns the bounding box, width, and height of a glyph path. */ +function getGlyphPathDimensions(glyph: opentype.Glyph, fontSize: number) { + const path = glyph.getPath(0, 0, fontSize); + const boundingBox = path.getBoundingBox(); + + return { + ...boundingBox, + width: boundingBox.x2 - boundingBox.x1, + height: boundingBox.y2 - boundingBox.y1, + }; +} + +/** + * Return the alias of a font glyph when multiple icons share the same glyph or throw an error if + * no mapping is found. + */ +function getFontGlyphAlias(icon: string): string { + const alias = seti.aliases[icon as keyof typeof seti.aliases]; + + if (!alias) { + throw new Error( + `Failed to find a glyph for the icon '${icon}'. This usually means that the icon is sharing a glyph with another icon and such association must be defined in the 'seti.aliases' configuration.` + ); + } + + return alias; +} + +/** Update the definitions to use an alias instead of a specific icon name. */ +function updateDefinitionsWithAlias(definitions: Definitions, icon: string, alias: string) { + const prefixedIcon = getSetiIconName(icon); + const prefixedAlias = getSetiIconName(alias); + + updateDefinitionsRecordWithAlias(definitions.files, prefixedIcon, prefixedAlias); + updateDefinitionsRecordWithAlias(definitions.extensions, prefixedIcon, prefixedAlias); + updateDefinitionsRecordWithAlias(definitions.partials, prefixedIcon, prefixedAlias); +} + +/** Update a definitions record to use an alias instead of a specific icon name. */ +function updateDefinitionsRecordWithAlias( + record: Record<string, string>, + icon: string, + alias: string +) { + for (const [key, value] of Object.entries(record)) { + if (value === icon) { + record[key] = alias; + } + } +} diff --git a/packages/file-icons-generator/utils/seti.ts b/packages/file-icons-generator/utils/seti.ts new file mode 100644 index 00000000000..fa4d46421eb --- /dev/null +++ b/packages/file-icons-generator/utils/seti.ts @@ -0,0 +1,129 @@ +import { spawnSync, type SpawnSyncOptions } from 'node:child_process'; +import fs from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; +import { seti, starlight } from '../config'; +import type { Definitions } from '../../starlight/user-components/rehype-file-tree.ts'; + +// https://github.com/jesseweed/seti-ui/blob/master/styles/components/icons/mapping.less +// .icon-set(".bsl", "bsl", @red); +// .icon-partial("mix", "hex", @red); +const mappingRegex = + /^\.icon-(?<type>(set|partial))\((?<quote>['"])(?<identifier>.+)\k<quote>, \k<quote>(?<lang>.+)\k<quote>, @.+\);$/; + +/** Clone the Seti UI repository, install dependencies, and generate the Seti UI icons. */ +export async function setupRepo() { + try { + const repoPath = await fs.mkdtemp(path.join(os.tmpdir(), 'starlight-file-icons-')); + + const spawnOptions: SpawnSyncOptions = { + cwd: repoPath, + encoding: 'utf8', + }; + + let result = spawnSync('git', ['clone', `https://github.com/${seti.repo}`, '.'], spawnOptions); + if (result.error) throw new Error('Failed to clone the Seti UI repository.'); + + result = spawnSync('npm', ['install'], spawnOptions); + if (result.error) throw new Error('Failed to install the Seti UI dependencies.'); + + result = spawnSync('npm', ['run', 'createIcons'], spawnOptions); + if (result.error) throw new Error('Failed to generate the Seti UI icons.'); + + return repoPath; + } catch (error) { + throw new Error( + 'Failed to setup the Seti UI repo. Make sure the repository URL and font path are correct.', + { cause: error } + ); + } +} + +/** Delete the Seti UI repository. */ +export async function deleteRepo(repoPath: string) { + try { + await fs.rm(repoPath, { force: true, recursive: true }); + } catch (error) { + throw new Error('Failed to remove the Seti UI repo.', { cause: error }); + } +} + +/** + * Get the Seti UI icon font from a local repository. + * Note that the `woff` font format is used and not `woff2` as we would manually need to decompress + * it and we do not need the compression benefits for this use case. + */ +export async function getFont(repoPath: string) { + try { + const result = await fs.readFile(path.join(repoPath, seti.font)); + return new Uint8Array(result).buffer; + } catch (error) { + throw new Error('Failed to read Seti UI font. Make sure the font path is correct.', { + cause: error, + }); + } +} + +/** + * Parse the Seti UI icon mapping file to generate the definitions used by the `<FileTree>` + * component and a list of Seti UI icons to extract as SVGs. + * @see https://github.com/elviswolcott/seti-icons/blob/master/build/extract.ts + */ +export async function parseMapping(repoPath: string) { + const mapping = await getMapping(repoPath); + + const lines = mapping.split('\n'); + // Include the `folder` icon by default as it is not defined in the mapping file. + const icons = new Set<string>(['folder']); + const definitions: Definitions = { + files: { ...starlight.definitions.files }, + extensions: { ...starlight.definitions.extensions }, + partials: { ...starlight.definitions.partials }, + }; + + for (const line of lines) { + const match = line.match(mappingRegex); + if (!match) continue; + const { identifier, lang, type } = match.groups!; + if (!identifier || !lang || !type) continue; + if (seti.ignores.includes(lang)) continue; + + const maybeOverride: string | undefined = seti.overrides[lang as keyof typeof seti.overrides]; + + // Add the icon to the list of icons to extract as SVGs. + icons.add(maybeOverride ?? lang); + + const icon = getSetiIconName(lang); + + if (type === 'set') { + if (identifier?.startsWith('.')) { + definitions.extensions[identifier] = icon; + } else { + definitions.files[identifier] = icon; + } + } else { + definitions.partials[identifier] = icon; + } + } + + return { definitions, icons: [...icons] }; +} + +/** Return the name of an icon by taking rename configuration into account. */ +export function getSetiIconName(icon: string) { + const name = seti.renames[icon as keyof typeof seti.renames] ?? icon; + + return `${starlight.prefix}${name}`; +} + +/** Get the Seti UI icon mapping file from a local repository. */ +async function getMapping(repoPath: string) { + try { + return await fs.readFile(path.join(repoPath, seti.mapping), 'utf8'); + } catch (error) { + throw new Error( + 'Failed to read Seti UI icon mapping file. Make sure the mapping file path is correct.', + { cause: error } + ); + } +} diff --git a/packages/markdoc/.npmignore b/packages/markdoc/.npmignore new file mode 100644 index 00000000000..c8740c5e4f9 --- /dev/null +++ b/packages/markdoc/.npmignore @@ -0,0 +1 @@ +__tests__/ diff --git a/packages/markdoc/CHANGELOG.md b/packages/markdoc/CHANGELOG.md new file mode 100644 index 00000000000..d4d458b6681 --- /dev/null +++ b/packages/markdoc/CHANGELOG.md @@ -0,0 +1,99 @@ +# @astrojs/starlight-markdoc + +## 0.5.1 + +### Patch Changes + +- [#3500](https://github.com/withastro/starlight/pull/3500) [`7700456`](https://github.com/withastro/starlight/commit/770045663c8ca3cc44983dd0d444955eba441243) Thanks [@delucis](https://github.com/delucis)! - This is the first release published with OIDC trusted publishing. + +## 0.5.0 + +### Minor Changes + +- [#2261](https://github.com/withastro/starlight/pull/2261) [`778b743`](https://github.com/withastro/starlight/commit/778b743cdb832551ed576c745728358d8bbf9d7a) Thanks [@shubham-padia](https://github.com/shubham-padia)! - Adds support for the `icon` attribute in the `aside` tag, allowing the use of any of Starlight’s built-in icons. + +## 0.4.0 + +### Minor Changes + +- [#3033](https://github.com/withastro/starlight/pull/3033) [`8c19678`](https://github.com/withastro/starlight/commit/8c19678e57c0270d3d80d4678f23a6fc287ebf12) Thanks [@delucis](https://github.com/delucis)! - Adds support for generating clickable anchor links for headings. + + By default, the Starlight Markdoc preset now includes a default `heading` node, which renders an anchor link beside headings in your Markdoc content. + + If you want to disable this new feature, pass `headingLinks: false` in your Markdoc config: + + ```js + export default defineMarkdocConfig({ + // Disable the default heading anchor link support + extends: [starlightMarkdoc({ headingLinks: false })], + }); + ``` + + ⚠️ **BREAKING CHANGE:** The minimum supported peer version of Starlight is now v0.34.0. + + Please update Starlight and the Starlight Markdoc preset together: + + ```sh + npx @astrojs/upgrade + ``` + +## 0.3.1 + +### Patch Changes + +- [#3090](https://github.com/withastro/starlight/pull/3090) [`fc3ffa8`](https://github.com/withastro/starlight/commit/fc3ffa8e27a3113a8eb70a3d8e7bf69c2bb214e5) Thanks [@delucis](https://github.com/delucis)! - Adds support for newer versions of `@astrojs/markdoc` + +- [#3109](https://github.com/withastro/starlight/pull/3109) [`b5cc1b4`](https://github.com/withastro/starlight/commit/b5cc1b4d4ee7dc737616c6ada893369b13ddb9c6) Thanks [@dhruvkb](https://github.com/dhruvkb)! - Updates Expressive Code to v0.41.1 + +## 0.3.0 + +### Minor Changes + +- [#2931](https://github.com/withastro/starlight/pull/2931) [`10b93b3`](https://github.com/withastro/starlight/commit/10b93b336cf4e3500e3003635b5afc430284d1a7) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds support for the `title`, `frame`, and `meta` fence attributes to code blocks. + + These new optional attributes add support for Expressive Code [text & line markers](https://expressive-code.com/key-features/text-markers/). The following example renders a code block using a [terminal frame](https://expressive-code.com/key-features/frames/#terminal-frames) with a [title](https://expressive-code.com/key-features/frames/#code-editor-frames): + + ````mdoc + ```js {% title="editor.exe" frame="terminal" %} + console.log('Hello, world!'); + ``` + ```` + + Any other text or line markers should be specified using the `meta` fence attribute. For example, the following code block renders a code block using the `diff` syntax combined with the `js` language syntax highlighting and the `markers` text highlighted: + + ````mdoc + ```diff {% meta="lang=js 'markers'" %} + function thisIsJavaScript() { + // This entire block gets highlighted as JavaScript, + // and we can still add diff markers to it! + - console.log('Old code to be removed') + + console.log('New and shiny code!') + } + ``` + ```` + + To learn more about all the available options, check out the [Expressive Code documentation](https://expressive-code.com/key-features/text-markers/#usage-in-markdown--mdx). + +## 0.2.0 + +### Minor Changes + +- [#2612](https://github.com/withastro/starlight/pull/2612) [`8d5a4e8`](https://github.com/withastro/starlight/commit/8d5a4e8000d9e3a4bb9ca8178767cf3d8bc48773) Thanks [@HiDeoo](https://github.com/HiDeoo)! - ⚠️ **BREAKING CHANGE:** The minimum supported version of Starlight is now 0.30.0 + + Please use the `@astrojs/upgrade` command to upgrade your project: + + ```sh + npx @astrojs/upgrade + ``` + +### Patch Changes + +- [#2664](https://github.com/withastro/starlight/pull/2664) [`62ff007`](https://github.com/withastro/starlight/commit/62ff0074d9a3f82e46f5c62db85c04d87ff5e931) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Publishes provenance containing verifiable data to link a package back to its source repository and the specific build instructions used to publish it. + +## 0.1.0 + +### Minor Changes + +- [#2249](https://github.com/withastro/starlight/pull/2249) [`20cbf3b`](https://github.com/withastro/starlight/commit/20cbf3b6a4d1598a62fdb176ebaa849bc7b978f7) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds Starlight Markdoc preset. + + See the [“Markdoc”](https://starlight.astro.build/guides/authoring-content/#markdoc) guide to learn more on how to use this preset in a new or existing project. diff --git a/packages/markdoc/Code.astro b/packages/markdoc/Code.astro new file mode 100644 index 00000000000..8c8a0609fb7 --- /dev/null +++ b/packages/markdoc/Code.astro @@ -0,0 +1,16 @@ +--- +import { Code as Default } from '@astrojs/starlight/components'; + +interface Props { + code: string; + lang?: string; +} + +/** + * This component is a basic wrapper for the `<Code>` component from Starlight used for Markdoc + * fenced code blocks that ensures that we do not pass any child content to the `<Code>` component + * which is an usage not supported by Expressive Code and would throw an error. + */ +--- + +<Default {...Astro.props} /> diff --git a/packages/markdoc/README.md b/packages/markdoc/README.md new file mode 100644 index 00000000000..8141a004f07 --- /dev/null +++ b/packages/markdoc/README.md @@ -0,0 +1,18 @@ +# <img src="https://github.com/withastro/starlight/assets/357379/494fcd83-42aa-4891-87e0-87402fa0b6f3" alt="" align="left" width="40" height="40"> @astrojs/starlight-markdoc + +Markdoc preset for the [Starlight][starlight] documentation theme for [Astro][astro]. + +## Documentation + +See the [Starlight Markdoc docs][docs] for how to use this preset. + +## License + +MIT + +Copyright (c) 2024–present [Starlight contributors][contributors] + +[starlight]: https://starlight.astro.build/ +[astro]: https://astro.build/ +[docs]: https://starlight.astro.build/guides/authoring-content/#markdoc +[contributors]: https://github.com/withastro/starlight/graphs/contributors diff --git a/packages/markdoc/__tests__/markdoc.test-d.ts b/packages/markdoc/__tests__/markdoc.test-d.ts new file mode 100644 index 00000000000..e13e958beb6 --- /dev/null +++ b/packages/markdoc/__tests__/markdoc.test-d.ts @@ -0,0 +1,172 @@ +import type { ComponentProps, HTMLAttributes } from 'astro/types'; +import { describe, expectTypeOf, test } from 'vitest'; + +import { + Aside, + Badge, + Card, + CardGrid, + Code, + FileTree, + Icon, + LinkButton, + LinkCard, + Steps, + TabItem, + Tabs, +} from '@astrojs/starlight/components'; + +type UserComponents = keyof typeof import('@astrojs/starlight/components'); +type UserComponentProps<T extends (args: any) => any> = keyof RemoveIndexSignature< + ComponentProps<T> +>; + +type MarkdocPreset = typeof import('../index.mjs').StarlightMarkdocPreset; +type MarkdocNodes = keyof MarkdocPreset['nodes']; +type MarkdocNodeAttributes<T extends MarkdocNodes> = keyof MarkdocPreset['nodes'][T]['attributes']; +type MarkdocTags = keyof MarkdocPreset['tags']; +type MarkdocTagAttributes<T extends MarkdocTags> = keyof MarkdocPreset['tags'][T]['attributes']; + +describe('nodes', () => { + test('defines attributes for fenced code blocks with support for some text markers', () => { + type FenceAttributes = MarkdocNodeAttributes<'fence'>; + + // Markdoc default fence attributes are `content` and `language`. + type MarkdocFenceAttributes = 'content' | 'language'; + + // Ensure Markdoc default fence attributes are always mapped. + expectTypeOf< + Extract<FenceAttributes, MarkdocFenceAttributes> + >().toEqualTypeOf<MarkdocFenceAttributes>(); + + type UnsupportedCodeProps = + /** The `code` and `lang` attributes mapping is tested above. */ + | 'code' + | 'lang' + /** Not all `<Code>` component props are supported in code fences. */ + | 'class' + | 'hangingIndent' + | 'locale' + | 'preserveIndent' + | 'useDiffSyntax' + | 'wrap' + /** + * Some props cannot be described using Markdoc attribute validation syntax. + * @see {@link file://./../index.mjs} + */ + | 'mark' + | 'ins' + | 'del'; + + // Ensure all non-unsupported `<Code>` component props are mapped. + expectTypeOf<Exclude<FenceAttributes, MarkdocFenceAttributes>>().toEqualTypeOf< + Exclude<UserComponentProps<typeof Code>, UnsupportedCodeProps> + >(); + }); +}); + +describe('tags', () => { + test('defines a tag for each user components', () => { + expectTypeOf<MarkdocTags>().toEqualTypeOf<Lowercase<UserComponents>>(); + }); + + test('defines all `<Aside>` component attributes', () => { + expectTypeOf<MarkdocTagAttributes<'aside'>>().toEqualTypeOf<UserComponentProps<typeof Aside>>(); + }); + + test('defines all `<Badge>` component attributes', () => { + /** + * Only supports a list of well-known `<span>` attributes. + * @see {@link file://./../html.mjs} + */ + type UnsupportedBadgeProps = Exclude<keyof HTMLAttributes<'span'>, WellKnownElementAttributes>; + + expectTypeOf<MarkdocTagAttributes<'badge'>>().toEqualTypeOf< + Exclude<UserComponentProps<typeof Badge>, UnsupportedBadgeProps> + >(); + }); + + test('defines all `<Card>` component attributes', () => { + expectTypeOf<MarkdocTagAttributes<'card'>>().toEqualTypeOf<UserComponentProps<typeof Card>>(); + }); + + test('defines all `<CardGrid>` component attributes', () => { + expectTypeOf<MarkdocTagAttributes<'cardgrid'>>().toEqualTypeOf< + UserComponentProps<typeof CardGrid> + >(); + }); + + test('defines all `<Code>` component attributes', () => { + /** + * Some props cannot be described using Markdoc attribute validation syntax. + * @see {@link file://./../index.mjs} + */ + type UnsupportedCodeProps = 'mark' | 'ins' | 'del'; + + expectTypeOf<MarkdocTagAttributes<'code'>>().toEqualTypeOf< + Exclude<UserComponentProps<typeof Code>, UnsupportedCodeProps> + >(); + }); + + test('defines all `<FileTree>` component attributes', () => { + expectTypeOf<MarkdocTagAttributes<'filetree'>>().toEqualTypeOf< + UserComponentProps<typeof FileTree> + >(); + }); + + test('defines all `<Icon>` component attributes', () => { + expectTypeOf<MarkdocTagAttributes<'icon'>>().toEqualTypeOf<UserComponentProps<typeof Icon>>(); + }); + + test('defines all `<LinkButton>` component attributes', () => { + /** + * Only supports a list of well-known `<a>` attributes. + * @see {@link file://./../html.mjs} + */ + type UnsupportedLinkButtonProps = Exclude<keyof HTMLAttributes<'a'>, WellKnownAnchorAttributes>; + + expectTypeOf<MarkdocTagAttributes<'linkbutton'>>().toEqualTypeOf< + Exclude<UserComponentProps<typeof LinkButton>, UnsupportedLinkButtonProps> + >(); + }); + + test('defines all `<LinkCard>` component attributes', () => { + /** + * Only supports a list of well-known `<a>` attributes. + * @see {@link file://./../html.mjs} + */ + type UnsupportedLinkCardProps = Exclude<keyof HTMLAttributes<'a'>, WellKnownAnchorAttributes>; + + expectTypeOf<MarkdocTagAttributes<'linkcard'>>().toEqualTypeOf< + Exclude<UserComponentProps<typeof LinkCard>, UnsupportedLinkCardProps> + >(); + }); + + test('defines all `<Steps>` component attributes', () => { + expectTypeOf<MarkdocTagAttributes<'steps'>>().toEqualTypeOf<UserComponentProps<typeof Steps>>(); + }); + + test('defines all `<TabItem>` component attributes', () => { + expectTypeOf<MarkdocTagAttributes<'tabitem'>>().toEqualTypeOf< + UserComponentProps<typeof TabItem> + >(); + }); + + test('defines all `<Tabs>` component attributes', () => { + expectTypeOf<MarkdocTagAttributes<'tabs'>>().toEqualTypeOf<UserComponentProps<typeof Tabs>>(); + }); +}); + +type WellKnownElementAttributes = keyof typeof import('../html.mjs').WellKnownElementAttributes; +type WellKnownAnchorAttributes = keyof typeof import('../html.mjs').WellKnownAnchorAttributes; + +// https://stackoverflow.com/a/66252656/1945960 +type RemoveIndexSignature<T> = { + [K in keyof T as string extends K + ? never + : number extends K + ? never + : symbol extends K + ? never + : K]: T[K]; +}; diff --git a/packages/markdoc/components.ts b/packages/markdoc/components.ts new file mode 100644 index 00000000000..2eaa0b47ec5 --- /dev/null +++ b/packages/markdoc/components.ts @@ -0,0 +1,2 @@ +export { default as Code } from './Code.astro'; +export { default as Heading } from '@astrojs/starlight/components/AnchorHeading.astro'; diff --git a/packages/markdoc/html.mjs b/packages/markdoc/html.mjs new file mode 100644 index 00000000000..259471a71e1 --- /dev/null +++ b/packages/markdoc/html.mjs @@ -0,0 +1,44 @@ +/** + * A list of well-known HTML element global attributes that can be used on any HTML element. + * + * @satisfies {HTMLElementTagAttributes<'span'>} + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes + */ +export const WellKnownElementAttributes = { + class: { type: String }, + dir: { type: String, matches: ['ltr', 'rtl', 'auto'] }, + hidden: { type: String, matches: ['', 'hidden', 'until-found'] }, + id: { type: String }, + lang: { type: String }, + role: { type: String }, + style: { type: String }, + title: { type: String }, +}; + +/** + * A list of well-known HTML attributes that can be used on an `<a>` element. + * + * @satisfies {HTMLElementTagAttributes<'a'>} + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes + */ +export const WellKnownAnchorAttributes = { + ...WellKnownElementAttributes, + download: { type: String }, + href: { type: String }, + hreflang: { type: String }, + media: { type: String }, + ping: { type: String }, + rel: { type: String }, + target: { type: String, matches: ['_self', '_blank', '_parent', '_top'] }, +}; + +/** + * The configuration of a tag attribute. + * @typedef {NonNullable<NonNullable<import('@astrojs/markdoc/config').AstroMarkdocConfig['tags']>[string]['attributes']>[string]} TagAttributeConfig + */ + +/** + * A map of HTML attributes for a specific HTML element with their associated attribute configuration. + * @typedef {Partial<Record<keyof import('astro/types').HTMLAttributes<T>, TagAttributeConfig>>} HTMLElementTagAttributes + * @template {import('astro/types').HTMLTag} T + */ diff --git a/packages/markdoc/index.mjs b/packages/markdoc/index.mjs new file mode 100644 index 00000000000..32f19ecf335 --- /dev/null +++ b/packages/markdoc/index.mjs @@ -0,0 +1,313 @@ +import { component, nodes } from '@astrojs/markdoc/config'; +import { WellKnownElementAttributes, WellKnownAnchorAttributes } from './html.mjs'; + +/** + * The Markdoc preset for Starlight mapping Starlight components to Markdoc nodes and tags. + * + * - The icons are not using a `matches` to provide a list of supported icons as it is not possible + * to import a TypeScript file in this file (which can also not be a TypeScript file). When + * Starlight is bundled, this could be refactored to provide a list of supported icons. + * - Some components (`<Badge>`, `<LinkButton>`, and `<LinkCard>`) support extra attributes, e.g. + * all the attributes supported by the `<a>` tag. As Markdoc requires type definitions for each + * attribute, only some well-known attributes are supported in these tags. + * + * @satisfies {import('@astrojs/markdoc/config').AstroMarkdocConfig} + */ +export const StarlightMarkdocPreset = { + nodes: { + fence: { + render: component('@astrojs/starlight-markdoc/components', 'Code'), + attributes: { + content: { + type: String, + required: true, + render: 'code', + }, + language: { + type: String, + required: false, + render: 'lang', + }, + /** + * Markdoc ignores meta attributes (markers) after a fence block (e.g. + * ```js title="example.js" del={2} ins={3-4} {6} ). + * This means that Expressive Code markers defined after the fence block are ignored and + * users would need to either use the Markdoc syntax for fence attributes or the `code` tag + * instead. + * + * @see https://github.com/withastro/astro/blob/9f943c1344671b569a0d1ddba683b3cca0068adc/packages/integrations/markdoc/src/extensions/shiki.ts#L15-L17 + * @see https://github.com/markdoc/markdoc/discussions/318#discussioncomment-4821979 + */ + frame: { + type: String, + required: false, + default: 'auto', + matches: ['auto', 'code', 'terminal', 'none'], + }, + meta: { + type: String, + required: false, + }, + title: { + type: String, + required: false, + }, + /** + * `mark`, `ins`, `del`, and the label syntax are not supported as the Markdoc attribute + * validation syntax does not allow to describe properly all the possible values. + * Users should use the `meta` attribute instead. + * + * @see https://expressive-code.com/key-features/code-component/#mark--ins--del + * @see https://expressive-code.com/key-features/code-component/#meta + */ + }, + }, + }, + tags: { + aside: { + render: component('@astrojs/starlight/components', 'Aside'), + attributes: { + icon: { + type: String, + required: false, + }, + title: { + type: String, + required: false, + }, + type: { + type: String, + required: false, + default: 'note', + matches: ['note', 'danger', 'caution', 'tip'], + }, + }, + }, + badge: { + render: component('@astrojs/starlight/components', 'Badge'), + attributes: { + ...WellKnownElementAttributes, + text: { + type: String, + required: true, + }, + size: { + type: String, + required: false, + default: 'small', + matches: ['small', 'medium', 'large'], + }, + variant: { + type: String, + required: false, + matches: ['note', 'tip', 'danger', 'caution', 'success'], + }, + }, + }, + card: { + render: component('@astrojs/starlight/components', 'Card'), + attributes: { + icon: { + type: String, + required: false, + }, + title: { + type: String, + required: true, + }, + }, + }, + cardgrid: { + render: component('@astrojs/starlight/components', 'CardGrid'), + attributes: { + stagger: { + type: Boolean, + required: false, + default: false, + }, + }, + }, + code: { + render: component('@astrojs/starlight/components', 'Code'), + attributes: { + class: { + type: String, + required: false, + }, + code: { + type: String, + required: true, + }, + hangingIndent: { + type: Number, + required: false, + }, + lang: { + type: String, + required: false, + }, + meta: { + type: String, + required: false, + }, + locale: { + type: String, + required: false, + }, + frame: { + type: String, + required: false, + default: 'auto', + matches: ['auto', 'code', 'terminal', 'none'], + }, + preserveIndent: { + type: Boolean, + required: false, + default: true, + }, + title: { + type: String, + required: false, + }, + useDiffSyntax: { + type: Boolean, + required: false, + default: false, + }, + wrap: { + type: Boolean, + required: false, + default: false, + }, + /** + * `mark`, `ins`, `del`, and the label syntax are not supported as the Markdoc attribute + * validation syntax does not allow to describe properly all the possible values. + * Users should use the `meta` attribute instead. + * + * @see https://expressive-code.com/key-features/code-component/#mark--ins--del + * @see https://expressive-code.com/key-features/code-component/#meta + */ + }, + }, + filetree: { + render: component('@astrojs/starlight/components', 'FileTree'), + attributes: {}, + }, + icon: { + render: component('@astrojs/starlight/components', 'Icon'), + attributes: { + class: { + type: String, + required: false, + }, + color: { + type: String, + required: false, + }, + label: { + type: String, + required: false, + }, + name: { + type: String, + required: true, + }, + size: { + type: String, + required: false, + }, + }, + }, + linkbutton: { + render: component('@astrojs/starlight/components', 'LinkButton'), + attributes: { + ...WellKnownAnchorAttributes, + href: { + type: String, + required: true, + }, + icon: { + type: String, + required: false, + }, + iconPlacement: { + type: String, + required: false, + default: 'end', + matches: ['start', 'end'], + }, + variant: { + type: String, + required: false, + default: 'primary', + matches: ['primary', 'secondary', 'minimal'], + }, + }, + }, + linkcard: { + render: component('@astrojs/starlight/components', 'LinkCard'), + attributes: { + ...WellKnownAnchorAttributes, + description: { + type: String, + required: false, + }, + href: { + type: String, + required: true, + }, + title: { + type: String, + required: true, + }, + }, + }, + steps: { + render: component('@astrojs/starlight/components', 'Steps'), + attributes: {}, + }, + tabitem: { + render: component('@astrojs/starlight/components', 'TabItem'), + attributes: { + icon: { + type: String, + required: false, + }, + label: { + type: String, + required: true, + }, + }, + }, + tabs: { + render: component('@astrojs/starlight/components', 'Tabs'), + attributes: { + syncKey: { + type: String, + required: false, + }, + }, + }, + }, +}; + +/** + * Markdoc preset that configures Starlight’s built-in components. + * @return {import('@astrojs/markdoc/config').AstroMarkdocConfig} + */ +export default function starlightMarkdoc({ headingLinks = true } = {}) { + return { + ...StarlightMarkdocPreset, + nodes: { + ...StarlightMarkdocPreset.nodes, + ...(headingLinks + ? { + heading: { + ...nodes.heading, + render: component('@astrojs/starlight-markdoc/components', 'Heading'), + }, + } + : {}), + }, + }; +} diff --git a/packages/markdoc/package.json b/packages/markdoc/package.json new file mode 100644 index 00000000000..a69d69d9d1d --- /dev/null +++ b/packages/markdoc/package.json @@ -0,0 +1,31 @@ +{ + "name": "@astrojs/starlight-markdoc", + "version": "0.5.1", + "description": "Markdoc preset for the Starlight documentation theme for Astro", + "author": "Chris Swithinbank <swithinbank@gmail.com>", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/withastro/starlight", + "directory": "packages/markdoc" + }, + "bugs": "https://github.com/withastro/starlight/issues", + "homepage": "https://starlight.astro.build", + "type": "module", + "exports": { + ".": "./index.mjs", + "./components": "./components.ts" + }, + "devDependencies": { + "@astrojs/markdoc": "^0.13.3", + "@astrojs/starlight": "workspace:*", + "vitest": "^3.0.5" + }, + "peerDependencies": { + "@astrojs/markdoc": ">=0.12.1", + "@astrojs/starlight": ">=0.35.0" + }, + "publishConfig": { + "provenance": true + } +} diff --git a/packages/starlight/.gitignore b/packages/starlight/.gitignore index fed875b1411..004798ee53c 100644 --- a/packages/starlight/.gitignore +++ b/packages/starlight/.gitignore @@ -1,2 +1,4 @@ # Astro generates this during tests, but we want to ignore it. -src/env.d.ts +env.d.ts +__tests__/**/types.d.ts +.astro diff --git a/packages/starlight/.npmignore b/packages/starlight/.npmignore index 26babf74523..54ad20802ea 100644 --- a/packages/starlight/.npmignore +++ b/packages/starlight/.npmignore @@ -1,6 +1,8 @@ # Vitest __coverage__/ __tests__/ +__e2e__/ vitest.* +playwright.config.ts # Astro generates this during tests, but we want to ignore it. src/env.d.ts diff --git a/packages/starlight/404.astro b/packages/starlight/404.astro deleted file mode 100644 index 3b10bf45743..00000000000 --- a/packages/starlight/404.astro +++ /dev/null @@ -1,42 +0,0 @@ ---- -import { getEntry } from 'astro:content'; -import config from 'virtual:starlight/user-config'; -import EmptyContent from './components/EmptyMarkdown.md'; -import Page from './layout/Page.astro'; -import type { StarlightDocsEntry } from './utils/routing'; -import { useTranslations } from './utils/translations'; - -const { lang = 'en', dir = 'ltr' } = config.defaultLocale || {}; -let locale = config.defaultLocale?.locale; -if (locale === 'root') locale = undefined; - -const entryMeta = { dir, lang, locale }; -const t = useTranslations(locale); - -const fallbackEntry: StarlightDocsEntry = { - slug: '404', - id: '404.md' as StarlightDocsEntry['id'], - body: '', - collection: 'docs', - data: { - title: '404', - template: 'splash', - editUrl: false, - head: [], - hero: { tagline: t('404.text'), actions: [] }, - }, - render: async () => ({ - Content: EmptyContent, - headings: [], - remarkPluginFrontmatter: {}, - }), -}; - -const userEntry = await getEntry('docs', '404'); -const entry = userEntry || fallbackEntry; -const { Content, headings } = await entry.render(); ---- - -<Page {headings} entry={entry} id={entry.id} slug={entry.slug} {...entryMeta} {entryMeta}> - <Content /> -</Page> diff --git a/packages/starlight/CHANGELOG.md b/packages/starlight/CHANGELOG.md index 51ff7862f82..6f2b1adb7de 100644 --- a/packages/starlight/CHANGELOG.md +++ b/packages/starlight/CHANGELOG.md @@ -1,5 +1,2042 @@ # @astrojs/starlight +## 0.37.6 + +### Patch Changes + +- [#3645](https://github.com/withastro/starlight/pull/3645) [`a562096`](https://github.com/withastro/starlight/commit/a562096380287fa7fa925664d04071a5831f274b) Thanks [@mschoeffmann](https://github.com/mschoeffmann)! - Adds icons for Chrome, Edge, Firefox, and Safari + +## 0.37.5 + +### Patch Changes + +- [#3675](https://github.com/withastro/starlight/pull/3675) [`0ba556d`](https://github.com/withastro/starlight/commit/0ba556d7d49dd4904f8aa8524c105bf1ceeec85c) Thanks [@controversial](https://github.com/controversial)! - Excludes the accessible labels for heading anchor links from Pagefind results + +## 0.37.4 + +### Patch Changes + +- [#3534](https://github.com/withastro/starlight/pull/3534) [`703fab0`](https://github.com/withastro/starlight/commit/703fab085b99303c0c01325c9bb869ea7e1418c4) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes support for running builds when `npx` is unavailable. + + Previously, Starlight would spawn a process to run the Pagefind search indexing binary using `npx`. On platforms where `npx` isn’t available, this could cause issues. Starlight now runs Pagefind using its Node.js API to avoid a separate process. As a side effect, you may notice that logging during builds is now less verbose. + +- [#3656](https://github.com/withastro/starlight/pull/3656) [`a0e6368`](https://github.com/withastro/starlight/commit/a0e636838092d30cb6b8f80e5535ad842e52d759) Thanks [@delucis](https://github.com/delucis)! - Fixes several edge cases in highlighting the current page heading in Starlight’s table of contents + +- [#3663](https://github.com/withastro/starlight/pull/3663) [`00cbf00`](https://github.com/withastro/starlight/commit/00cbf001fee4fd59f351c7a6c0f8c353c7c41f13) Thanks [@lines-of-codes](https://github.com/lines-of-codes)! - Adds Thai language support + +- [#3658](https://github.com/withastro/starlight/pull/3658) [`ac79329`](https://github.com/withastro/starlight/commit/ac793290f0dbd21f9b9a5d6f60aa315043815227) Thanks [@delucis](https://github.com/delucis)! - Avoids adding redundant `aria-current="false"` attributes to sidebar entries + +- [#3382](https://github.com/withastro/starlight/pull/3382) [`db295c2`](https://github.com/withastro/starlight/commit/db295c2a3d75aad71a41702f33001195d89de5d2) Thanks [@trueberryless](https://github.com/trueberryless)! - Fixes an issue where the mobile table of contents is unable to find the first heading when a page has a tall banner. + +## 0.37.3 + +### Patch Changes + +- [#3648](https://github.com/withastro/starlight/pull/3648) [`292666c`](https://github.com/withastro/starlight/commit/292666cdcb9d81da2ee32ab5a3e83b2c44cea5cd) Thanks [@maxchang3](https://github.com/maxchang3)! - Prevents unwanted font size adjustments on iOS after orientation changes. + +## 0.37.2 + +### Patch Changes + +- [#3647](https://github.com/withastro/starlight/pull/3647) [`9f4efc3`](https://github.com/withastro/starlight/commit/9f4efc3c59ee41038b7c0550230a10bb35ad0e50) Thanks [@gerstenbergit](https://github.com/gerstenbergit)! - Adds Greek language support + +## 0.37.1 + +### Patch Changes + +- [#3603](https://github.com/withastro/starlight/pull/3603) [`30f6e7f`](https://github.com/withastro/starlight/commit/30f6e7fa83ca0a248b1b59d616f55a6f933334a2) Thanks [@delucis](https://github.com/delucis)! - Fixes support for providing an absolute URL to Starlight’s `favicon` configuration option + +## 0.37.0 + +### Minor Changes + +- [#3491](https://github.com/withastro/starlight/pull/3491) [`28810f0`](https://github.com/withastro/starlight/commit/28810f085faf017f3fedd1407e741bdf6c232848) Thanks [@JusticeMatthew](https://github.com/JusticeMatthew)! - Changes text overflow styling in Markdown content + + ⚠️ **Potentially breaking change:** This release switches the [`overflow-wrap`](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap) CSS style for common elements to `break-word`. In most cases, there should be little visual impact, but this change can impact how layouts with implicit sizing (such as tables) look, improving legibility in how words wrap. + + If you want to preserve the previous styling, you can add the following [custom CSS](https://starlight.astro.build/guides/css-and-tailwind/#custom-css-styles) to your site: + + ```css + p, + h1, + h2, + h3, + h4, + h5, + h6, + code { + overflow-wrap: anywhere; + } + ``` + +- [#3351](https://github.com/withastro/starlight/pull/3351) [`239698c`](https://github.com/withastro/starlight/commit/239698c53625f5411792e314994d20c20f9ede77) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Ensures that Starlight CSS layer order is predictable in custom pages using the `<StarlightPage>` component. + + Previously, due to how [import order](https://docs.astro.build/en/guides/styling/#import-order) works in Astro, the `<StarlightPage>` component had to be the first import in custom pages to set up [cascade layers](https://starlight.astro.build/guides/css-and-tailwind/#cascade-layers) used internally by Starlight to manage the order of its styles. + + With this change, this restriction no longer applies and Starlight’s styles will be applied correctly regardless of the import order of the `<StarlightPage>` component. + +- [#3521](https://github.com/withastro/starlight/pull/3521) [`ca7b771`](https://github.com/withastro/starlight/commit/ca7b771e5bd4da3fe500bbad562e69d5880690ea) Thanks [@shubham-padia](https://github.com/shubham-padia)! - Fixes an issue where a vertical scrollbar could be displayed on the Starlight `<Tabs>` component when zooming the page + + ⚠️ **Potentially breaking change:** The `<Tabs>` component no longer uses `margin-bottom` and `border-bottom` to highlight the current tab. This is now done with a `box-shadow`. If you have custom styling for your tabs, you may need to update it. + + If you want to preserve the previous styling, you can add the following custom CSS to your site: + + ```css + starlight-tabs .tab { + margin-bottom: -2px; + } + + starlight-tabs .tab > [role='tab'] { + border-bottom: 2px solid var(--sl-color-gray-5); + box-shadow: none; + } + + starlight-tabs .tab [role='tab'][aria-selected='true'] { + border-color: var(--sl-color-text-accent); + } + ``` + +- [#3549](https://github.com/withastro/starlight/pull/3549) [`1cf50eb`](https://github.com/withastro/starlight/commit/1cf50ebb18c0232be581cf0aff0c192e4c421e55) Thanks [@jacobdalamb](https://github.com/jacobdalamb)! - Updates the default sans-serif system font stack, dropping support for the `-apple-system` and `BlinkMacSystemFont` font names used in older browsers. These are no longer needed in [browsers officially supported by Starlight](https://browsersl.ist/#q=%3E+0.5%25%2C+not+dead%2C+Chrome+%3E%3D+105%2C+Edge+%3E%3D+105%2C+Firefox+%3E%3D+121%2C+Safari+%3E%3D+15.4%2C+iOS+%3E%3D+15.4%2C+not+op_mini+all). + + If you still need to support older browsers, you can add the following custom CSS to your site: + + ```css + :root { + --sl-font-system: ui-sans-serif, system-ui, -apple-system, + BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, + 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', + 'Segoe UI Symbol', 'Noto Color Emoji'; + } + ``` + +- [#3332](https://github.com/withastro/starlight/pull/3332) [`f61f99d`](https://github.com/withastro/starlight/commit/f61f99dc09c59d26761ffebc611969e20b866191) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds a new [`markdown.processedDirs`](https://starlight.astro.build/reference/configuration/#processeddirs) configuration option to specify additional directories where files should be processed by Starlight’s Markdown pipeline. + + By default, Starlight’s processing only applies to Markdown and MDX content loaded using Starlight’s `docsLoader()`. This new option allows to extend this processing to other directories, which can be useful if you are rendering content from a custom content collection using the `<StarlightPage>` component and expect Starlight’s Markdown processing to be applied to that content as well. + +## 0.36.3 + +### Patch Changes + +- [#3555](https://github.com/withastro/starlight/pull/3555) [`547dc30`](https://github.com/withastro/starlight/commit/547dc30558b388bfc0505ab0fd8269cecaed462a) Thanks [@Its-Just-Nans](https://github.com/Its-Just-Nans)! - Improves the error message thrown when using a file in the `public/` directory with Starlight’s `customCss` configuration option + +- [#3496](https://github.com/withastro/starlight/pull/3496) [`b78fda4`](https://github.com/withastro/starlight/commit/b78fda45be17be7a260309251e82504f9ac8e97a) Thanks [@delucis](https://github.com/delucis)! - Fixes invalid `<head>` output when configuration is missing: + + - Omits `<meta property="og:description" />` if Starlight’s `description` option is unset + - Omits `<link rel="canonical" />` and `<meta property="og:url" />` if Astro’s `site` option is unset + +- [#3511](https://github.com/withastro/starlight/pull/3511) [`8727df1`](https://github.com/withastro/starlight/commit/8727df1a1b1c82f1303613226000afd53ffe4e36) Thanks [@astrobot-houston](https://github.com/astrobot-houston)! - Updates the `seti:gitlab` icon to match latest version from Seti UI Icons + +## 0.36.2 + +### Patch Changes + +- [#3500](https://github.com/withastro/starlight/pull/3500) [`7700456`](https://github.com/withastro/starlight/commit/770045663c8ca3cc44983dd0d444955eba441243) Thanks [@delucis](https://github.com/delucis)! - This is the first release published with OIDC trusted publishing. + +- [#3484](https://github.com/withastro/starlight/pull/3484) [`620fb38`](https://github.com/withastro/starlight/commit/620fb3857e40a37a2f8bdf2d0430b106e8f80cdb) Thanks [@gboubeta-uvigo](https://github.com/gboubeta-uvigo)! - Improves Spanish UI translations + +## 0.36.1 + +### Patch Changes + +- [#3479](https://github.com/withastro/starlight/pull/3479) [`2fec483`](https://github.com/withastro/starlight/commit/2fec4833d4867db35b77079ce3026b79ba1e0441) Thanks [@gboubeta-uvigo](https://github.com/gboubeta-uvigo)! - Updates Galician UI translations + +- [#3457](https://github.com/withastro/starlight/pull/3457) [`c6c0c51`](https://github.com/withastro/starlight/commit/c6c0c5114a659b22ffcc4c2085ad8c1fc4f43a5d) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Deduplicates sitemap link tags in the head. + + When [enabling sitemap](https://starlight.astro.build/guides/customization/#enable-sitemap) in Starlight, a `<link rel="sitemap" href="/sitemap-index.xml">` tag is automatically added to the head of each page. Manually specifying sitemap link tags using the Starlight [`head` configuration option](https://starlight.astro.build/reference/configuration/#head) or the [`head` frontmatter field](https://starlight.astro.build/reference/frontmatter/#head) will now override the default sitemap link tag added by Starlight. + + This change ensures that users manually adding the `@astrojs/sitemap` integration to the Astro `integrations` array for more fine-grained control over sitemap generation and also using the [`filenameBase` integration option](https://docs.astro.build/en/guides/integrations-guide/sitemap/#filenamebase) can customize the sitemap link tag in the head. + +- [#3448](https://github.com/withastro/starlight/pull/3448) [`1fc7501`](https://github.com/withastro/starlight/commit/1fc7501d16218c7f156c5e90df25ae6fbb8abfea) Thanks [@dionysuzx](https://github.com/dionysuzx)! - Enlarges the Farcaster icon to better match other social icons + +- [#3473](https://github.com/withastro/starlight/pull/3473) [`07204dd`](https://github.com/withastro/starlight/commit/07204dd7b8b6ee71bf24ff9c7d70fc7306bf2076) Thanks [@gboubeta](https://github.com/gboubeta)! - Fixes a typo in Galician table of contents label + +## 0.36.0 + +### Minor Changes + +- [#3427](https://github.com/withastro/starlight/pull/3427) [`c3b2d0f`](https://github.com/withastro/starlight/commit/c3b2d0fc37bb9b7b6abc6c11b760a4114690ccd4) Thanks [@delucis](https://github.com/delucis)! - Fixes styling of labels that wrap across multiple lines in `<Tabs>` component + + ⚠️ **Potentially breaking change:** Tab labels now have a narrower line-height and additional vertical padding. If you have custom CSS targeting the `<Tabs>` component, you may want to double check the visual appearance of your tabs when updating. + + If you want to preserve the previous styling, you can add the following custom CSS to your site: + + ```css + .tab > [role='tab'] { + line-height: var(--sl-line-height); + padding-block: 0; + } + ``` + +- [#3380](https://github.com/withastro/starlight/pull/3380) [`3364af3`](https://github.com/withastro/starlight/commit/3364af31e535d62ee7b045e6d9cf97c7e58df981) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Makes head entry parsing stricter in Starlight config and content frontmatter. + + **⚠️ Potentially breaking change:** Previously Starlight would accept a head entry for a `meta` tag defining some `content` which generates invalid HTML as `<meta>` is a void element which cannot have any child nodes. Now, it is an error to define a `meta` tag including some `content`. + + If you see errors after updating, look for head entries in the Starlight configuration in the `astro.config.mjs` file or in the frontmatter of your content files that include a `content` property for a `meta` tag. To fix the error, move the `content` property to the `attrs` object with at least an additional attribute to identify the kind of metadata it represents: + + ```diff + head: { + tag: 'meta', + - content: 'foo', + attrs: { + name: 'my-meta', + + content: 'foo', + }, + }, + ``` + +- [#3340](https://github.com/withastro/starlight/pull/3340) [`2018c31`](https://github.com/withastro/starlight/commit/2018c31b0f559d51478bfbf9f12cfba76b4e74fc) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds missing vertical spacing between Markdown content and UI Framework components using [client directives](https://docs.astro.build/en/reference/directives-reference/#client-directives). + + **⚠️ Potentially breaking change:** By default, Starlight applies some vertical spacing (`--sl-content-gap-y`) between Markdown content blocks. This change introduces similar spacing between Markdown content blocks and UI Framework components using client directives which was not present before. + + If you were relying on the previous behavior, you can manually override the spacing by manually specifying the top margin on the component using [custom CSS](https://starlight.astro.build/guides/css-and-tailwind/#custom-css-styles), e.g. by relying on a CSS class to target the component. + + ```css + .my-custom-component { + margin-top: 0; + } + ``` + +### Patch Changes + +- [#3423](https://github.com/withastro/starlight/pull/3423) [`a0d0670`](https://github.com/withastro/starlight/commit/a0d0670bce5827b90fd0102fa3517814367760e7) Thanks [@andersk](https://github.com/andersk)! - Fixes HTML validity in sidebar groups by ensuring `<summary>` is the first child of `<details>` + +## 0.35.3 + +### Patch Changes + +- [#3416](https://github.com/withastro/starlight/pull/3416) [`fcc0633`](https://github.com/withastro/starlight/commit/fcc0633ab14fc602f5c540972446e22c79746042) Thanks [@randomguy-2650](https://github.com/randomguy-2650)! - Updates German UI translations to be more idiomatic. + +- [#1640](https://github.com/withastro/starlight/pull/1640) [`d1b3828`](https://github.com/withastro/starlight/commit/d1b3828cdfe8114884ab65049581e37624422ac4) Thanks [@hippotastic](https://github.com/hippotastic)! - Refactors various internal systems, improving code quality and maintainability. + +- [#3421](https://github.com/withastro/starlight/pull/3421) [`97e8103`](https://github.com/withastro/starlight/commit/97e8103c5793d583931575dbe17924ef88a5b6fd) Thanks [@andersk](https://github.com/andersk)! - Removes an invalid `value` attribute from the language and theme selectors + +- [#3422](https://github.com/withastro/starlight/pull/3422) [`9200fac`](https://github.com/withastro/starlight/commit/9200fac71ebe6e7bbbecee3d1893e744db01dc6e) Thanks [@andersk](https://github.com/andersk)! - Refactors collapsible sidebar sections and “on this page” dropdown to use `<span>` instead of `<div>` + +## 0.35.2 + +### Patch Changes + +- [#3341](https://github.com/withastro/starlight/pull/3341) [`10f6fe2`](https://github.com/withastro/starlight/commit/10f6fe22a981247293ee4de106736f1a6ae24b6a) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Prevents potential build issues with the Astro Cloudflare adapter due to the dependency on Node.js builtins. + +- [#3327](https://github.com/withastro/starlight/pull/3327) [`bf58c60`](https://github.com/withastro/starlight/commit/bf58c60b9c3d5f5efdafbdba83cefa0566a367dc) Thanks [@delucis](https://github.com/delucis)! - Fixes a routing bug for docs pages with a slug authored with non-normalized composition. This could occur for filenames containing diacritics in some circumstances, causing 404s. + +## 0.35.1 + +### Patch Changes + +- [#3325](https://github.com/withastro/starlight/pull/3325) [`4cf28f2`](https://github.com/withastro/starlight/commit/4cf28f2afd50fb2a3f8c9149a824aaac47c12af6) Thanks [@mniinio](https://github.com/mniinio)! - Adds Finnish language support + +## 0.35.0 + +### Minor Changes + +- [#2261](https://github.com/withastro/starlight/pull/2261) [`778b743`](https://github.com/withastro/starlight/commit/778b743cdb832551ed576c745728358d8bbf9d7a) Thanks [@shubham-padia](https://github.com/shubham-padia)! - Adds support for using any of Starlight’s built-in icons in asides. + +- [#3272](https://github.com/withastro/starlight/pull/3272) [`e7fe267`](https://github.com/withastro/starlight/commit/e7fe26720b7527c39e3aab42ea9fd0468f92167c) Thanks [@delucis](https://github.com/delucis)! - Adds a new `generateId` option to Starlight’s `docsLoader()` + + This enables overriding the default sluggifier used to convert content filenames to URLs. + +- [#3276](https://github.com/withastro/starlight/pull/3276) [`3917b20`](https://github.com/withastro/starlight/commit/3917b206da26522f73bbe0c1120de9acae5972c5) Thanks [@delucis](https://github.com/delucis)! - Excludes banner content from search results + + Previously, content set in [`banner`](https://starlight.astro.build/reference/frontmatter/#banner) in page frontmatter was indexed by Starlight’s default search provider Pagefind. This could cause unexpected search results, especially for sites setting a common banner content on multiple pages. Starlight’s default `Banner` component is now excluded from search indexing. + + This change does not impact `Banner` overrides using custom components. + +- [#3266](https://github.com/withastro/starlight/pull/3266) [`1161af0`](https://github.com/withastro/starlight/commit/1161af0c2fe26485da6123f8fd7205c53b0e45e5) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds support for custom HTML attributes on autogenerated sidebar links using the [`autogenerate.attrs`](https://starlight.astro.build/guides/sidebar/#custom-html-attributes-for-autogenerated-links) option. + +- [#3274](https://github.com/withastro/starlight/pull/3274) [`80ccff7`](https://github.com/withastro/starlight/commit/80ccff7c542794e04a4d2abb17227a076fa57c5d) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue where some Starlight remark and rehype plugins were transforming Markdown and MDX content in non-Starlight pages. + + ⚠️ **BREAKING CHANGE:** + + Previously, some of Starlight’s remark and rehype plugins, most notably the plugin transforming Starlight's custom Markdown syntax for [rendering asides](https://starlight.astro.build/guides/authoring-content/#asides), were applied to all Markdown and MDX content. This included content from [individual Markdown pages](https://docs.astro.build/en/guides/markdown-content/#individual-markdown-pages) and content from [content collections](https://docs.astro.build/en/guides/content-collections/) other than the `docs` collection used by Starlight. + + This change restricts the application of Starlight’s remark and rehype plugins to only Markdown and MDX content loaded using Starlight's [`docsLoader()`](https://starlight.astro.build/reference/configuration/#docsloader). If you were relying on this behavior, please let us know about your use case in the dedicated `#starlight` channel in the [Astro Discord](https://astro.build/chat/) or by [opening an issue](https://github.com/withastro/starlight/issues/new?template=---01-bug-report.yml). + +### Patch Changes + +- [#3266](https://github.com/withastro/starlight/pull/3266) [`1161af0`](https://github.com/withastro/starlight/commit/1161af0c2fe26485da6123f8fd7205c53b0e45e5) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Ensures invalid sidebar group configurations using the `attrs` option are properly reported as a type error. + + Previously, invalid sidebar group configurations using the `attrs` option were not reported as a type error but only surfaced at runtime. This change is only a type-level change and does not affect the runtime behavior of Starlight which does not support the `attrs` option for sidebar groups. + +- [#3274](https://github.com/withastro/starlight/pull/3274) [`80ccff7`](https://github.com/withastro/starlight/commit/80ccff7c542794e04a4d2abb17227a076fa57c5d) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Prevents Starlight remark and rehype plugins from transforming Markdown and MDX content when using the Astro [`renderMarkdown()`](https://docs.astro.build/en/reference/content-loader-reference/#rendermarkdown) content loader API. + +## 0.34.8 + +### Patch Changes + +- [#3306](https://github.com/withastro/starlight/pull/3306) [`21fcd94`](https://github.com/withastro/starlight/commit/21fcd944d528557b89fc8b351579beabdcc06ff6) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a regression in Starlight version `0.34.5` that caused multilingual sites with a default locale explicitly set to `root` to report a configuration error. + +## 0.34.7 + +### Patch Changes + +- [#3298](https://github.com/withastro/starlight/pull/3298) [`7bd02e3`](https://github.com/withastro/starlight/commit/7bd02e37650da59ed6cdfe275473ae2dac6a2d48) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a potential issue with [`absolutePathToLang()`](https://starlight.astro.build/reference/plugins/#absolutepathtolang) plugin API not handling paths with spaces correctly. + +## 0.34.6 + +### Patch Changes + +- [#3293](https://github.com/withastro/starlight/pull/3293) [`88f0d34`](https://github.com/withastro/starlight/commit/88f0d349ee4e8c42bd38adc01031edf4c7b92342) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue preventing to override the slug of a page with the [`slug` frontmatter property](https://starlight.astro.build/reference/frontmatter/#slug) using the `/` value. + +## 0.34.5 + +### Patch Changes + +- [#3282](https://github.com/withastro/starlight/pull/3282) [`7680e87`](https://github.com/withastro/starlight/commit/7680e878fc55eba3fe0cf90e793970d3b72d166a) Thanks [@alvinometric](https://github.com/alvinometric)! - Moves padding of `<main>` element to a `--sl-main-pad` CSS custom property to simplify setting custom values + +- [#3288](https://github.com/withastro/starlight/pull/3288) [`131371e`](https://github.com/withastro/starlight/commit/131371e0c897f9c7ea673d93e8f405200d04d312) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a potential configuration issue for multilingual sites with a default language including a regional subtag. + +## 0.34.4 + +### Patch Changes + +- [#3205](https://github.com/withastro/starlight/pull/3205) [`95d124a`](https://github.com/withastro/starlight/commit/95d124ae99f207afd83f305943fa29df32cbbfc9) Thanks [@sgalcheung](https://github.com/sgalcheung)! - Fixes an issue preventing to use the `<StarlightPage>` component when the `docs` content collection that Starlight uses does not exist. + +- [#3206](https://github.com/withastro/starlight/pull/3206) [`e6ea584`](https://github.com/withastro/starlight/commit/e6ea5848b20afbb654fd6684956336491b974dc7) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a text selection issue for heading with a clickable anchor link when using double click to select text in Chrome and Safari. + +- [#3233](https://github.com/withastro/starlight/pull/3233) [`3064c40`](https://github.com/withastro/starlight/commit/3064c40b54227b6309b35b6e44e397fae8f284a4) Thanks [@torn4dom4n](https://github.com/torn4dom4n)! - Updates Vietnamese UI translations. + +- [#3248](https://github.com/withastro/starlight/pull/3248) [`16c1239`](https://github.com/withastro/starlight/commit/16c1239b36346e84b794fab819d6ad7a9854a244) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Prevents [icons in the `<Card>` component](https://starlight.astro.build/components/cards/#add-icons-to-cards) from being shrunk in some narrow viewports. + +- [#3225](https://github.com/withastro/starlight/pull/3225) [`21b93b8`](https://github.com/withastro/starlight/commit/21b93b8ac1894c5ada99a641e516086ebee6ea37) Thanks [@randomguy-2650](https://github.com/randomguy-2650)! - Updates German UI translations + +## 0.34.3 + +### Patch Changes + +- [#3058](https://github.com/withastro/starlight/pull/3058) [`274cc06`](https://github.com/withastro/starlight/commit/274cc06112824384771b944f504ab0faab45e2b9) Thanks [@techfg](https://github.com/techfg)! - Fixes display of focus indicator around site title + +- [#3181](https://github.com/withastro/starlight/pull/3181) [`449c822`](https://github.com/withastro/starlight/commit/449c8229effaab19ece3c0a34e32595809c33cc8) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue where all headings in Markdown and MDX content were rendered with a [clickable anchor link](https://starlight.astro.build/reference/configuration/#headinglinks), even in non-Starlight pages. + +- [#3168](https://github.com/withastro/starlight/pull/3168) [`ca693fe`](https://github.com/withastro/starlight/commit/ca693feb4b6aa9f26b3d536d284288773b788ac6) Thanks [@jsparkdev](https://github.com/jsparkdev)! - Updates Korean language support with improvements and missing translations + +## 0.34.2 + +### Patch Changes + +- [#3153](https://github.com/withastro/starlight/pull/3153) [`ea31f46`](https://github.com/withastro/starlight/commit/ea31f46be4d43339417dac7fc135d2be97080c58) Thanks [@SuperKXT](https://github.com/SuperKXT)! - Fixes hover styles for highlighted directory in FileTree component. + +- [#2905](https://github.com/withastro/starlight/pull/2905) [`b5232bc`](https://github.com/withastro/starlight/commit/b5232bcd201c2e3904bde2d7717fe6cfa06d6c82) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a potential issue for projects with dynamic routes added by an user, an Astro integration, or a Starlight plugin where some styles could end up being missing. + +- [#3165](https://github.com/withastro/starlight/pull/3165) [`80a7871`](https://github.com/withastro/starlight/commit/80a7871ccad17aef8567a416a419669de6d5d3fd) Thanks [@KianNH](https://github.com/KianNH)! - Increases `maxBuffer` for an internal `spawnSync()` call to support larger Git commit histories when using Starlight's [`lastUpdated`](https://starlight.astro.build/reference/configuration/#lastupdated) feature. + +- [#3158](https://github.com/withastro/starlight/pull/3158) [`d1f3c8b`](https://github.com/withastro/starlight/commit/d1f3c8b6583b93968af3c568f7af44b1b10326ec) Thanks [@heisenberg0924](https://github.com/heisenberg0924)! - Adds Hungarian language support + +## 0.34.1 + +### Patch Changes + +- [#3140](https://github.com/withastro/starlight/pull/3140) [`f6eb1d5`](https://github.com/withastro/starlight/commit/f6eb1d5a776b007bec0f4b5fd7b160851daac9fc) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a text selection issue for heading with a clickable anchor link when using double or triple click to select text. + +- [#3148](https://github.com/withastro/starlight/pull/3148) [`dc8b6d5`](https://github.com/withastro/starlight/commit/dc8b6d5561eb90be9d31396ed1dc8f8258c9cbf7) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a regression of the Starlight icon color when using the [`credits`](https://starlight.astro.build/reference/configuration/#credits) configuration option. + +## 0.34.0 + +### Minor Changes + +- [#2322](https://github.com/withastro/starlight/pull/2322) [`f14eb0c`](https://github.com/withastro/starlight/commit/f14eb0cd7baa0391d6124379f6c5df4b9ab7cc44) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Groups all of Starlight's CSS declarations into a single `starlight` [cascade layer](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Cascade_layers). + + This change allows for easier customization of Starlight's CSS as any custom unlayered CSS will override the default styles. If you are using cascade layers in your custom CSS, you can use the [`@layer`](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) CSS at-rule to define the order of precedence for different layers including the ones used by Starlight. + + We recommend checking your site’s appearance when upgrading to make sure there are no style regressions caused by this change. + +- [#3122](https://github.com/withastro/starlight/pull/3122) [`3a087d8`](https://github.com/withastro/starlight/commit/3a087d8fbcd946336f8a0423203967e53e5678fe) Thanks [@delucis](https://github.com/delucis)! - Removes default `attrs` and `content` values from head entries parsed using Starlight’s schema. + + Previously when adding `head` metadata via frontmatter or user config, Starlight would automatically add values for `attrs` and `content` if not provided. Now, these properties are left `undefined`. + + This makes it simpler to add tags in route middleware for example as you no longer need to provide empty values for `attrs` and `content`: + + ```diff + head.push({ + tag: 'style', + content: 'div { color: red }' + - attrs: {}, + }); + head.push({ + tag: 'link', + - content: '' + attrs: { rel: 'me', href: 'https://example.com' }, + }); + ``` + + This is mostly an internal API but if you are overriding Starlight’s `Head` component or processing head entries in some way, you may wish to double check your handling of `Astro.locals.starlightRoute.head` is compatible with `attrs` and `content` potentially being `undefined`. + +- [#3033](https://github.com/withastro/starlight/pull/3033) [`8c19678`](https://github.com/withastro/starlight/commit/8c19678e57c0270d3d80d4678f23a6fc287ebf12) Thanks [@delucis](https://github.com/delucis)! - Adds support for generating clickable anchor links for headings. + + By default, Starlight now renders an anchor link beside headings in Markdown and MDX content. A new `<AnchorHeading>` component is available to achieve the same thing in custom pages built using `<StarlightPage>`. + + If you want to disable this new Markdown processing set the `markdown.headingLinks` option in your Starlight config to `false`: + + ```js + starlight({ + title: 'My docs', + markdown: { + headingLinks: false, + }, + }), + ``` + + ⚠️ **BREAKING CHANGE:** The minimum supported version of Astro is now v5.5.0. + + Please update Starlight and Astro together: + + ```sh + npx @astrojs/upgrade + ``` + +- [#2322](https://github.com/withastro/starlight/pull/2322) [`f14eb0c`](https://github.com/withastro/starlight/commit/f14eb0cd7baa0391d6124379f6c5df4b9ab7cc44) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Removes Shiki `css-variables` theme fallback. + + ⚠️ **BREAKING CHANGE:** + + Previously, Starlight used to automatically provide a fallback theme for Shiki, the default syntax highlighter built into Astro if the configured Shiki theme was not `github-dark`. + + This fallback was only relevant when the default Starlight code block renderer, Expressive Code, was disabled and Shiki was used. Starlight no longer provides this fallback. + + If you were relying on this behavior, you now manually need to update your Astro configuration to use the Shiki `css-variables` theme to match the previous behavior. + + ```diff + import { defineConfig } from 'astro/config'; + + export default defineConfig({ + + markdown: { + + shikiConfig: { + + theme: 'css-variables', + + }, + + }, + }); + ``` + + Additionally, you can use [custom CSS](https://starlight.astro.build/guides/css-and-tailwind/#custom-css-styles) to control the appearance of the code blocks. Here are the previously used CSS variables for the fallback theme: + + ```css + :root { + --astro-code-foreground: var(--sl-color-white); + --astro-code-background: var(--sl-color-gray-6); + --astro-code-token-constant: var(--sl-color-blue-high); + --astro-code-token-string: var(--sl-color-green-high); + --astro-code-token-comment: var(--sl-color-gray-2); + --astro-code-token-keyword: var(--sl-color-purple-high); + --astro-code-token-parameter: var(--sl-color-red-high); + --astro-code-token-function: var(--sl-color-red-high); + --astro-code-token-string-expression: var(--sl-color-green-high); + --astro-code-token-punctuation: var(--sl-color-gray-2); + --astro-code-token-link: var(--sl-color-blue-high); + } + ``` + +### Patch Changes + +- [#3118](https://github.com/withastro/starlight/pull/3118) [`77a1104`](https://github.com/withastro/starlight/commit/77a110461dffacd1d3ee3b8934fd48b20111f3c4) Thanks [@delucis](https://github.com/delucis)! - Fixes passing imported SVGs to the `frontmatter` prop of the `<StarlightPage>` component in Astro ≥5.7.0 + +## 0.33.2 + +### Patch Changes + +- [#3090](https://github.com/withastro/starlight/pull/3090) [`fc3ffa8`](https://github.com/withastro/starlight/commit/fc3ffa8e27a3113a8eb70a3d8e7bf69c2bb214e5) Thanks [@delucis](https://github.com/delucis)! - Updates internal `@astrojs/mdx`, `@astrojs/sitemap`, and `astro-expressive-code` dependencies + +- [#3109](https://github.com/withastro/starlight/pull/3109) [`b5cc1b4`](https://github.com/withastro/starlight/commit/b5cc1b4d4ee7dc737616c6ada893369b13ddb9c6) Thanks [@dhruvkb](https://github.com/dhruvkb)! - Updates Expressive Code to v0.41.1 + +## 0.33.1 + +### Patch Changes + +- [#3088](https://github.com/withastro/starlight/pull/3088) [`1885049`](https://github.com/withastro/starlight/commit/18850491905fc1bf9e467b1d65c7f1709daf3c30) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a regression in Starlight version `0.33.0` that caused the description and links to language alternates for multilingual websites to be missing from the` <head>` of the page. + +- [#3065](https://github.com/withastro/starlight/pull/3065) [`463adf5`](https://github.com/withastro/starlight/commit/463adf53b263a963736cb441bc1dd515f3c81894) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Updates the `social` configuration option TSDoc example to match the shape of the expected value. + +## 0.33.0 + +### Minor Changes + +- [#3026](https://github.com/withastro/starlight/pull/3026) [`82deb84`](https://github.com/withastro/starlight/commit/82deb847418aedb9c01e05bb9de4b9bd10a1a885) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a potential list styling issue if the last element of a list item is a `<script>` tag. + + ⚠️ **BREAKING CHANGE:** + + This release drops official support for Chromium-based browsers prior to version 105 (released 30 August 2022) and Firefox-based browsers prior to version 121 (released 19 December 2023). You can find a list of currently supported browsers and their versions using this [browserslist query](https://browsersl.ist/#q=%3E+0.5%25%2C+not+dead%2C+Chrome+%3E%3D+105%2C+Edge+%3E%3D+105%2C+Firefox+%3E%3D+121%2C+Safari+%3E%3D+15.4%2C+iOS+%3E%3D+15.4%2C+not+op_mini+all). + + With this release, Starlight-generated sites will still work fine on those older browsers except for this small detail in list item styling, but future releases may introduce further breaking changes for impacted browsers, including in patch releases. + +- [#3025](https://github.com/withastro/starlight/pull/3025) [`f87e9ac`](https://github.com/withastro/starlight/commit/f87e9acbf5090a31858c1cde568cc798140f1366) Thanks [@delucis](https://github.com/delucis)! - Makes `social` configuration more flexible. + + ⚠️ **BREAKING CHANGE:** The `social` configuration option has changed syntax. You will need to update this in `astro.config.mjs` when upgrading. + + Previously, a limited set of platforms were supported using a shorthand syntax with labels built in to Starlight. While convenient, this approach was less flexible and required dedicated code for each social platform added. + + Now, you must specify the icon and label for each social link explicitly and you can use any of [Starlight’s built-in icons](https://starlight.astro.build/reference/icons/) for social links. + + The following example shows updating the old `social` syntax to the new: + + ```diff + - social: { + - github: 'https://github.com/withastro/starlight', + - discord: 'https://astro.build/chat', + - }, + + social: [ + + { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' }, + + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + + ], + ``` + +- [#2927](https://github.com/withastro/starlight/pull/2927) [`c46904c`](https://github.com/withastro/starlight/commit/c46904c4a16cf1c7f4f895e42cb164474b2301b3) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds the [`head`](https://starlight.astro.build/reference/route-data/#head) route data property which contains an array of all tags to include in the `<head>` of the current page. + + Previously, the [`<Head>`](https://starlight.astro.build/reference/overrides/#head-1) component was responsible for generating a list of tags to include in the `<head>` of the current page and rendering them. + This data is now available as `Astro.locals.starlightRoute.head` instead and can be modified using [route data middleware](https://starlight.astro.build/guides/route-data/#customizing-route-data). + The `<Head>` component now only renders the tags provided in `Astro.locals.starlightRoute.head`. + +- [#2924](https://github.com/withastro/starlight/pull/2924) [`6a56d1b`](https://github.com/withastro/starlight/commit/6a56d1b80d9d67e63e930177cf085a25864e1952) Thanks [@HiDeoo](https://github.com/HiDeoo)! - ⚠️ **BREAKING CHANGE:** Ensures that the `<Badge>` and `<Icon>` components no longer render with a trailing space. + + In Astro, components that include styles render with a trailing space which can prevent some use cases from working as expected, e.g. when using such components inlined with text. This change ensures that the `<Badge>` and `<Icon>` components no longer render with a trailing space. + + If you were previously relying on that implementation detail, you may need to update your code to account for this change. For example, considering the following code: + + ```mdx + <Badge text="New" /> + Feature + ``` + + The rendered text would previously include a space between the badge and the text due to the trailing space automatically added by the component: + + ``` + New Feature + ``` + + Such code will now render the badge and text without a space: + + ``` + NewFeature + ``` + + To fix this, you can add a space between the badge and the text: + + ```diff + - <Badge text="New" />Feature + + <Badge text="New" /> Feature + ``` + +- [#2727](https://github.com/withastro/starlight/pull/2727) [`7c8fa30`](https://github.com/withastro/starlight/commit/7c8fa30f0ac2459c83b71a8a7b705b16dcf98d6f) Thanks [@techfg](https://github.com/techfg)! - Updates mobile menu toggle styles to display a close icon while the menu is open + +### Patch Changes + +- [#2927](https://github.com/withastro/starlight/pull/2927) [`c46904c`](https://github.com/withastro/starlight/commit/c46904c4a16cf1c7f4f895e42cb164474b2301b3) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue where overriding the [canonical URL](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel#canonical) of a page using the [`head` configuration option](https://starlight.astro.build/reference/configuration/#head) or [`head` frontmatter field](https://starlight.astro.build/reference/frontmatter/#head) would strip any other `<link>` tags from the `<head>`. + +- [#2927](https://github.com/withastro/starlight/pull/2927) [`c46904c`](https://github.com/withastro/starlight/commit/c46904c4a16cf1c7f4f895e42cb164474b2301b3) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue where generated [canonical URLs](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel#canonical) would include a trailing slash when using the [`trailingSlash` Astro option](https://docs.astro.build/en/reference/configuration-reference/#trailingslash) is set to `'never'`. + +- [#3025](https://github.com/withastro/starlight/pull/3025) [`f87e9ac`](https://github.com/withastro/starlight/commit/f87e9acbf5090a31858c1cde568cc798140f1366) Thanks [@delucis](https://github.com/delucis)! - Fixes Starlight’s autogenerated `<meta name="twitter:site">` tags when a Twitter link is set in `social` config. Previously these incorrectly rendered `content="/username"` and now correctly render `content="@username"`. + +## 0.32.6 + +### Patch Changes + +- [#3030](https://github.com/withastro/starlight/pull/3030) [`5bdf139`](https://github.com/withastro/starlight/commit/5bdf139191a20f19458b027617877c1063b46724) Thanks [@trueberryless](https://github.com/trueberryless)! - Updates the type of the `isFallback` field in route data from `true` to `boolean`, keeping it optional but allowing `false` as a possible value. + +- [#3018](https://github.com/withastro/starlight/pull/3018) [`188b8cf`](https://github.com/withastro/starlight/commit/188b8cfa8ad8761365b8b557c4b9fea671050ed6) Thanks [@trueberryless](https://github.com/trueberryless)! - Adds validation for user config `routeMiddleware` so it does not conflict with [Astro's middleware](https://docs.astro.build/en/guides/middleware/). + +## 0.32.5 + +### Patch Changes + +- [#3021](https://github.com/withastro/starlight/pull/3021) [`e3f881e`](https://github.com/withastro/starlight/commit/e3f881ec23019689b821c638b8f0863b8ced6908) Thanks [@jsparkdev](https://github.com/jsparkdev)! - Updates Korean language support + +- [#3020](https://github.com/withastro/starlight/pull/3020) [`58e3e84`](https://github.com/withastro/starlight/commit/58e3e84662167e43c4a8b707453898e047aa18fc) Thanks [@ayoayco](https://github.com/ayoayco)! - Add SourceHut social icon + +- [#3013](https://github.com/withastro/starlight/pull/3013) [`5b599dd`](https://github.com/withastro/starlight/commit/5b599dd6190d3b57f61ae48c8614395dda23ef13) Thanks [@oluwatobiss](https://github.com/oluwatobiss)! - Adds Substack icon to social links list + +## 0.32.4 + +### Patch Changes + +- [#2994](https://github.com/withastro/starlight/pull/2994) [`ca4ec8b`](https://github.com/withastro/starlight/commit/ca4ec8bc30b8e627bbc946736869ba67a2f4a6c6) Thanks [@XREvo](https://github.com/XREvo)! - Fixes default ranking of merged indexes when using multi-site search + +- [#2969](https://github.com/withastro/starlight/pull/2969) [`4682c7a`](https://github.com/withastro/starlight/commit/4682c7a4f248f53073a64ada671548709be49cd7) Thanks [@webpro](https://github.com/webpro)! - Add npm social icon + +## 0.32.3 + +### Patch Changes + +- [#2955](https://github.com/withastro/starlight/pull/2955) [`77b6a41`](https://github.com/withastro/starlight/commit/77b6a412c9daba8e6b856f3640204a1ca61c93b9) Thanks [@trueberryless](https://github.com/trueberryless)! - Adds 5 new icons: `figma`, `sketch`, `vim`, `vscode`, and `zed`. + +- [#2961](https://github.com/withastro/starlight/pull/2961) [`da57fab`](https://github.com/withastro/starlight/commit/da57fab3027048825e048384fe4aa773b5db3ebf) Thanks [@ematipico](https://github.com/ematipico)! - Adds 1 new icon: `jetbrains`. + +## 0.32.2 + +### Patch Changes + +- [#2926](https://github.com/withastro/starlight/pull/2926) [`c0170fd`](https://github.com/withastro/starlight/commit/c0170fd240a89ba4d0d4dd09817257903743dbe8) Thanks [@resoltico](https://github.com/resoltico)! - Adds Latvian language support + +- [#2918](https://github.com/withastro/starlight/pull/2918) [`790c000`](https://github.com/withastro/starlight/commit/790c000c4761f68b2782f1eef74568f210d4c619) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a trailing slash inconsistency in generated sidebar links when using the [`trailingSlash: 'ignore'`](https://docs.astro.build/en/reference/configuration-reference/#trailingslash) Astro option (the default) between [internal](https://starlight.astro.build/guides/sidebar/#internal-links) and [auto-generated](https://starlight.astro.build/guides/sidebar/#autogenerated-groups) links. Starlight behavior for this configuration value is to use a trailing slash as many common hosting providers redirect to URLs with a trailing slash by default. + +## 0.32.1 + +### Patch Changes + +- [#2904](https://github.com/withastro/starlight/pull/2904) [`ec5ca59`](https://github.com/withastro/starlight/commit/ec5ca5953e62b6ad2de78996d37e08522aa4aa76) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue preventing the use of [rewrites](https://docs.astro.build/en/guides/routing/#rewrites). + +## 0.32.0 + +### Minor Changes + +- [#2390](https://github.com/withastro/starlight/pull/2390) [`f493361`](https://github.com/withastro/starlight/commit/f493361d7b64a3279980e0f046c3a52196ab94e0) Thanks [@delucis](https://github.com/delucis)! - Moves route data to `Astro.locals` instead of passing it down via component props + + ⚠️ **Breaking change:** + Previously, all of Starlight’s templating components, including user or plugin overrides, had access to a data object for the current route via `Astro.props`. + This data is now available as `Astro.locals.starlightRoute` instead. + + To update, refactor any component overrides you have: + + - Remove imports of `@astrojs/starlight/props`, which is now deprecated. + - Update code that accesses `Astro.props` to use `Astro.locals.starlightRoute` instead. + - Remove any spreading of `{...Astro.props}` into child components, which is no longer required. + + In the following example, a custom override for Starlight’s `LastUpdated` component is updated for the new style: + + ```diff + --- + import Default from '@astrojs/starlight/components/LastUpdated.astro'; + - import type { Props } from '@astrojs/starlight/props'; + + - const { lastUpdated } = Astro.props; + + const { lastUpdated } = Astro.locals.starlightRoute; + + const updatedThisYear = lastUpdated?.getFullYear() === new Date().getFullYear(); + --- + + {updatedThisYear && ( + - <Default {...Astro.props}><slot /></Default> + + <Default><slot /></Default> + )} + ``` + + _Community Starlight plugins may also need to be manually updated to work with Starlight 0.32. If you encounter any issues, please reach out to the plugin author to see if it is a known issue or if an updated version is being worked on._ + +- [#2578](https://github.com/withastro/starlight/pull/2578) [`f895f75`](https://github.com/withastro/starlight/commit/f895f75b17f36c826cc871ba1826e5ae1dff44ca) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Deprecates the Starlight plugin `setup` hook in favor of the new `config:setup` hook which provides the same functionality. + + ⚠️ **BREAKING CHANGE:** + + The Starlight plugin `setup` hook is now deprecated and will be removed in a future release. Please update your plugins to use the new `config:setup` hook instead. + + ```diff + export default { + name: 'plugin-with-translations', + hooks: { + - 'setup'({ config }) { + + 'config:setup'({ config }) { + // Your plugin configuration setup code + }, + }, + }; + ``` + +- [#2578](https://github.com/withastro/starlight/pull/2578) [`f895f75`](https://github.com/withastro/starlight/commit/f895f75b17f36c826cc871ba1826e5ae1dff44ca) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Exposes the built-in localization system in the Starlight plugin `config:setup` hook. + + ⚠️ **BREAKING CHANGE:** + + This addition changes how Starlight plugins add or update translation strings used in Starlight’s localization APIs. + Plugins previously using the [`injectTranslations()`](https://starlight.astro.build/reference/plugins/#injecttranslations) callback function from the plugin [`config:setup`](https://starlight.astro.build/reference/plugins/#configsetup) hook should now use the same function available in the [`i18n:setup`](https://starlight.astro.build/reference/plugins/#i18nsetup) hook. + + ```diff + export default { + name: 'plugin-with-translations', + hooks: { + - 'config:setup'({ injectTranslations }) { + + 'i18n:setup'({ injectTranslations }) { + injectTranslations({ + en: { + 'myPlugin.doThing': 'Do the thing', + }, + fr: { + 'myPlugin.doThing': 'Faire le truc', + }, + }); + }, + }, + }; + ``` + +- [#2858](https://github.com/withastro/starlight/pull/2858) [`2df9d05`](https://github.com/withastro/starlight/commit/2df9d05fe7b61282809aa85a1d77662fdd3b748f) Thanks [@XREvo](https://github.com/XREvo)! - Adds support for Pagefind’s multisite search features + +- [#2578](https://github.com/withastro/starlight/pull/2578) [`f895f75`](https://github.com/withastro/starlight/commit/f895f75b17f36c826cc871ba1826e5ae1dff44ca) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds a new [`HookParameters`](https://starlight.astro.build/reference/plugins/#hooks) utility type to get the type of a plugin hook’s arguments. + +- [#2578](https://github.com/withastro/starlight/pull/2578) [`f895f75`](https://github.com/withastro/starlight/commit/f895f75b17f36c826cc871ba1826e5ae1dff44ca) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds a new [`useTranslations()`](https://starlight.astro.build/reference/plugins/#usetranslations) callback function to the Starlight plugin `config:setup` hook to generate a utility function to access UI strings for a given language. + +- [#2578](https://github.com/withastro/starlight/pull/2578) [`f895f75`](https://github.com/withastro/starlight/commit/f895f75b17f36c826cc871ba1826e5ae1dff44ca) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds a new [`absolutePathToLang()`](https://starlight.astro.build/reference/plugins/#absolutepathtolang) callback function to the Starlight plugin `config:setup` to get the language for a given absolute file path. + +### Patch Changes + +- [#2848](https://github.com/withastro/starlight/pull/2848) [`9b32ba9`](https://github.com/withastro/starlight/commit/9b32ba967c5741354bc99ba0bcff3f454b8117ad) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes styling of [filter](https://pagefind.app/docs/filtering/) and [metadata](https://pagefind.app/docs/metadata/) elements in Pagefind search UI. + +## 0.31.1 + +### Patch Changes + +- [#2805](https://github.com/withastro/starlight/pull/2805) [`ed6f9fd`](https://github.com/withastro/starlight/commit/ed6f9fd77334c02a75240087d0800ef32f159583) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Exposes the [`StarlightIcon`](https://starlight.astro.build/reference/icons/#starlighticon-type) TypeScript type referencing the names of Starlight’s built-in icons. + +## 0.31.0 + +### Minor Changes + +- [#2777](https://github.com/withastro/starlight/pull/2777) [`88f4214`](https://github.com/withastro/starlight/commit/88f42145888f3a04f20898fcb700c1e65be48bb2) Thanks [@hippotastic](https://github.com/hippotastic)! - Updates `astro-expressive-code` dependency to the latest version (0.40). + + This includes an update to the latest Shiki version (1.26.1), providing access to all current Shiki themes and syntax highlighting languages, and adding the config options `shiki.engine`, `shiki.bundledLangs`, `shiki.langAlias` and `removeUnusedThemes`. It also adds new style variants to the optional collapsible sections plugin. + + See the [Expressive Code release notes](https://expressive-code.com/releases/#0400) for full details. + +- [#2736](https://github.com/withastro/starlight/pull/2736) [`29a885b`](https://github.com/withastro/starlight/commit/29a885be43f29150d6abd905f3ef7e1dccb99c98) Thanks [@delucis](https://github.com/delucis)! - ⚠️ **BREAKING CHANGE:** The minimum supported version of Astro is now 5.1.5 + + Please update Astro and Starlight together: + + ```sh + npx @astrojs/upgrade + ``` + +- [#2728](https://github.com/withastro/starlight/pull/2728) [`e187383`](https://github.com/withastro/starlight/commit/e1873834d4a4328084a9ac056a089ee5b8f13103) Thanks [@delucis](https://github.com/delucis)! - Updates minimum Pagefind dependency to v1.3.0, sets new defaults for Pagefind’s ranking options, and adds support for manually configuring the ranking options + + The new ranking option defaults have been evaluated against Starlight’s own docs to improve the quality of search results. See [“Customize Pagefind's result ranking”](https://pagefind.app/docs/ranking/) for more details about how they work. + +- [#157](https://github.com/withastro/starlight/pull/157) [`23bf960`](https://github.com/withastro/starlight/commit/23bf960aed36445600b6ccecb2138a5b461e2929) Thanks [@tony-sull](https://github.com/tony-sull)! - Adds a print stylesheet to improve the appearance of Starlight docs pages when printed + +- [#2728](https://github.com/withastro/starlight/pull/2728) [`e187383`](https://github.com/withastro/starlight/commit/e1873834d4a4328084a9ac056a089ee5b8f13103) Thanks [@delucis](https://github.com/delucis)! - Fixes Pagefind logging to respect the Astro log level. When using Astro’s `--verbose` or `--silent` CLI flags, these are now respected by Pagefind as well. + +### Patch Changes + +- [#2792](https://github.com/withastro/starlight/pull/2792) [`412effb`](https://github.com/withastro/starlight/commit/412effb5a63c6026ea4faa0d09bcbd4a3c9fad4d) Thanks [@dhruvkb](https://github.com/dhruvkb)! - Uses semantic `var(--sl-color-hairline)` for the page sidebar border instead of `var(--sl-color-gray-6)`. This is visually the same as previously but makes it easier to override the hairline color consistently across a site. + +- [#2736](https://github.com/withastro/starlight/pull/2736) [`29a885b`](https://github.com/withastro/starlight/commit/29a885be43f29150d6abd905f3ef7e1dccb99c98) Thanks [@delucis](https://github.com/delucis)! - Updates internal dependencies `@astrojs/sitemap` and `@astrojs/mdx` to the latest versions + +- [#2782](https://github.com/withastro/starlight/pull/2782) [`d9d415b`](https://github.com/withastro/starlight/commit/d9d415b4558c7995319299e9c9e1520c87c3078e) Thanks [@delucis](https://github.com/delucis)! - Fixes a documentation link in the JSDoc comment for the `StarlightExpressiveCodeOptions` type + +- [#2708](https://github.com/withastro/starlight/pull/2708) [`442c819`](https://github.com/withastro/starlight/commit/442c8194dbcbe58e155d4c1f8d897a04605666e5) Thanks [@delucis](https://github.com/delucis)! - Fixes colour contrast correction in code blocks + +## 0.30.6 + +### Patch Changes + +- [#2722](https://github.com/withastro/starlight/pull/2722) [`0b206d3`](https://github.com/withastro/starlight/commit/0b206d3a23f0876146dc17f5e507984362917696) Thanks [@techfg](https://github.com/techfg)! - Fixes display of long site title on mobile + +- [#2762](https://github.com/withastro/starlight/pull/2762) [`7ab1576`](https://github.com/withastro/starlight/commit/7ab157639da62fdc6b444b0280ad4c9d5ee4872f) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Prevents the header title from being translated by automatic translation systems. + +## 0.30.5 + +### Patch Changes + +- [#2757](https://github.com/withastro/starlight/pull/2757) [`e7b0e74`](https://github.com/withastro/starlight/commit/e7b0e742dffb7c4a8f4619297e4bd6e5a8015edb) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a UI string translation issue for languages with a region subtag. + +- [#2760](https://github.com/withastro/starlight/pull/2760) [`aec9edd`](https://github.com/withastro/starlight/commit/aec9edd14827a45fbc92d82db83dd713571e0c2d) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds 5 new icons: `left-caret`, `up-arrow`, `down-arrow`, `download`, and `cloud-download`. + +## 0.30.4 + +### Patch Changes + +- [#2747](https://github.com/withastro/starlight/pull/2747) [`474c27e`](https://github.com/withastro/starlight/commit/474c27e28d79794ac78d36e3384f0c0da6f2dfed) Thanks [@bbag](https://github.com/bbag)! - Ensures `<Tab>` component toggling is stable when smooth scrolling is enabled via custom CSS + +- [#2740](https://github.com/withastro/starlight/pull/2740) [`0e169c9`](https://github.com/withastro/starlight/commit/0e169c9fd9fbfc16d86225db6b00448edf39ffad) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue preventing Pagefind to be disabled using the `pagefind` frontmatter field. + +- [#2732](https://github.com/withastro/starlight/pull/2732) [`a10b466`](https://github.com/withastro/starlight/commit/a10b46680810882b029dd1d578cc86e22bc97af5) Thanks [@Sidnioulz](https://github.com/Sidnioulz)! - Adds Storybook, Confluence and Jira social icons + +## 0.30.3 + +### Patch Changes + +- [#2717](https://github.com/withastro/starlight/pull/2717) [`c5fcbb3`](https://github.com/withastro/starlight/commit/c5fcbb33a7a0511ac372f5d006a69f4195d1e266) Thanks [@delucis](https://github.com/delucis)! - Fixes a list item spacing issue where line break elements (`<br>`) could receive a margin, breaking layout in Firefox + +- [#2724](https://github.com/withastro/starlight/pull/2724) [`02d7ac6`](https://github.com/withastro/starlight/commit/02d7ac66a0bdca3f26001f556de070027d4e0faf) Thanks [@dionysuzx](https://github.com/dionysuzx)! - Adds social link support for Farcaster + +- [#2635](https://github.com/withastro/starlight/pull/2635) [`ec4b851`](https://github.com/withastro/starlight/commit/ec4b85154ea301d9144ff49f3abd009e3a929387) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue where the language picker in multilingual sites could display the wrong language when navigating between pages with the browser back/forward buttons. + +- [#2726](https://github.com/withastro/starlight/pull/2726) [`e54ebd5`](https://github.com/withastro/starlight/commit/e54ebd5c879deb3fdff2180426b377181773b85f) Thanks [@techfg](https://github.com/techfg)! - Adds icon for phone + +## 0.30.2 + +### Patch Changes + +- [#2702](https://github.com/withastro/starlight/pull/2702) [`02d16f3`](https://github.com/withastro/starlight/commit/02d16f3638db609501897c5e3647cc20eb5ec142) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue with autogenerated sidebars when using Starlight with Astro's new Content Layer API with directories containing spaces or special characters. + +- [#2704](https://github.com/withastro/starlight/pull/2704) [`fd16470`](https://github.com/withastro/starlight/commit/fd164704b25ec5c000a2765eb0930b87e9a4e61e) Thanks [@delucis](https://github.com/delucis)! - Fixes display of focus indicator around site title + +## 0.30.1 + +### Patch Changes + +- [#2688](https://github.com/withastro/starlight/pull/2688) [`5c6996c`](https://github.com/withastro/starlight/commit/5c6996cd248e9da735a14e7fcaf638b51f2796bc) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue with autogenerated sidebars when using Starlight with Astro's new Content Layer API where group names would be sluggified. + +## 0.30.0 + +### Minor Changes + +- [#2612](https://github.com/withastro/starlight/pull/2612) [`8d5a4e8`](https://github.com/withastro/starlight/commit/8d5a4e8000d9e3a4bb9ca8178767cf3d8bc48773) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds support for Astro v5, drops support for Astro v4. + + #### Upgrade Astro and dependencies + + ⚠️ **BREAKING CHANGE:** Astro v4 is no longer supported. Make sure you [update Astro](https://docs.astro.build/en/guides/upgrade-to/v5/) and any other official integrations at the same time as updating Starlight: + + ```sh + npx @astrojs/upgrade + ``` + + _Community Starlight plugins and Astro integrations may also need to be manually updated to work with Astro v5. If you encounter any issues, please reach out to the plugin or integration author to see if it is a known issue or if an updated version is being worked on._ + + #### Update your collections + + ⚠️ **BREAKING CHANGE:** Starlight's internal [content collections](https://docs.astro.build/en/guides/content-collections/), which organize, validate, and render your content, have been updated to use Astro's new Content Layer API and require configuration changes in your project. + + 1. **Move the content config file.** This file no longer lives within the `src/content/config.ts` folder and should now exist at `src/content.config.ts`. + 1. **Edit the collection definition(s).** To update the `docs` collection, a `loader` is now required: + + ```diff + // src/content.config.ts + import { defineCollection } from "astro:content"; + +import { docsLoader } from "@astrojs/starlight/loaders"; + import { docsSchema } from "@astrojs/starlight/schema"; + + export const collections = { + - docs: defineCollection({ schema: docsSchema() }), + + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + }; + ``` + + If you are using the [`i18n` collection](https://starlight.astro.build/guides/i18n/#translate-starlights-ui) to provide translations for additional languages you support or override our default labels, you will need to update the collection definition in a similar way and remove the collection `type` which is no longer available: + + ```diff + // src/content.config.ts + import { defineCollection } from "astro:content"; + +import { docsLoader, i18nLoader } from "@astrojs/starlight/loaders"; + import { docsSchema, i18nSchema } from "@astrojs/starlight/schema"; + + export const collections = { + - docs: defineCollection({ schema: docsSchema() }), + + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), + + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), + }; + ``` + + 1. **Update other collections.** To update any other collections you may have, follow the [“Updating existing collections”](https://docs.astro.build/en/guides/upgrade-to/v5/#updating-existing-collections) section in the Astro 5 upgrade guide. + + If you are unable to make any changes to your collections at this time, including Starlight's default `docs` and `i18n` collections, you can enable the [`legacy.collections` flag](https://docs.astro.build/en/reference/legacy-flags/) to upgrade to v5 without updating your collections. This legacy flag exists to provide temporary backwards compatibility, and will allow you to keep your collections in their current state until the legacy flag is no longer supported. + +### Patch Changes + +- [#2669](https://github.com/withastro/starlight/pull/2669) [`310df7d`](https://github.com/withastro/starlight/commit/310df7d6b01f5c4a56540bdba9243fb60dace323) Thanks [@aaronperezaguilera](https://github.com/aaronperezaguilera)! - Adds Catalan UI translations + +- [#2664](https://github.com/withastro/starlight/pull/2664) [`62ff007`](https://github.com/withastro/starlight/commit/62ff0074d9a3f82e46f5c62db85c04d87ff5e931) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Publishes provenance containing verifiable data to link a package back to its source repository and the specific build instructions used to publish it. + +- [#2670](https://github.com/withastro/starlight/pull/2670) [`0223b42`](https://github.com/withastro/starlight/commit/0223b425249f8d1fa468e367c632467276c9c208) Thanks [@aaronperezaguilera](https://github.com/aaronperezaguilera)! - Adds Spanish UI translations for the Pagefind search modal + +## 0.29.3 + +### Patch Changes + +- [#2642](https://github.com/withastro/starlight/pull/2642) [`12750ae`](https://github.com/withastro/starlight/commit/12750ae1bc303f2c53efd25adf01428e54aced90) Thanks [@dragomano](https://github.com/dragomano)! - Updates Russian UI translations + +- [#2656](https://github.com/withastro/starlight/pull/2656) [`4d543be`](https://github.com/withastro/starlight/commit/4d543bec280f3b5e00e21727d78f25756a1ced75) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Improves error message when an invalid configuration or no configuration is provided to the Starlight integration. + +- [#2645](https://github.com/withastro/starlight/pull/2645) [`cf12beb`](https://github.com/withastro/starlight/commit/cf12beb91b4cb2f212dbcc0cc1ed56e79d055ff0) Thanks [@techfg](https://github.com/techfg)! - Fixes support for favicon URLs that contain a search query and/or hash + +- [#2650](https://github.com/withastro/starlight/pull/2650) [`38db4ec`](https://github.com/withastro/starlight/commit/38db4ecfdb572b1f6362aca544f72f5128f5fe08) Thanks [@raviqqe](https://github.com/raviqqe)! - Moves `@types/js-yaml` package to non-dev dependencies + +- [#2633](https://github.com/withastro/starlight/pull/2633) [`5adb720`](https://github.com/withastro/starlight/commit/5adb720afd354d99b3682d045b9dc8729a1ff274) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a VoiceOver issue with Safari where the content of a `<script>` element could be read before the sidebar content. + +- [#2663](https://github.com/withastro/starlight/pull/2663) [`34755f9`](https://github.com/withastro/starlight/commit/34755f9c5f2fa451e8a56aecf3ff5a6ff499767b) Thanks [@astrobot-houston](https://github.com/astrobot-houston)! - Adds a new `seti:vite` icon for Vite configuration files in the `<FileTree>` component + +## 0.29.2 + +### Patch Changes + +- [#2616](https://github.com/withastro/starlight/pull/2616) [`128cc51`](https://github.com/withastro/starlight/commit/128cc51b416a1a934eabb1989c04b76517e77a04) Thanks [@delucis](https://github.com/delucis)! - Fixes an edge case to correctly avoid a trailing slash when navigating from a root locale homepage to another language via Starlight’s language switcher when `trailingSlash: 'never'` is set + +## 0.29.1 + +### Patch Changes + +- [#2611](https://github.com/withastro/starlight/pull/2611) [`6059d96`](https://github.com/withastro/starlight/commit/6059d961a6b31fd7848b0c59411fc6370e62abab) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a UI string type issue in projects with multiple data content collections. + +- [#2606](https://github.com/withastro/starlight/pull/2606) [`10b15a7`](https://github.com/withastro/starlight/commit/10b15a7fcda4805dda622f893b6671b96a349161) Thanks [@delucis](https://github.com/delucis)! - Makes `<CardGrid>` more resilient to complex child content on smaller viewports + +- [#2605](https://github.com/withastro/starlight/pull/2605) [`ec7ab4f`](https://github.com/withastro/starlight/commit/ec7ab4f1df83052aa00c5f560adf7e7b8d61c9db) Thanks [@brianzelip](https://github.com/brianzelip)! - Exposes `SidebarPersister` component in package exports for use in custom overrides + +- [#2614](https://github.com/withastro/starlight/pull/2614) [`9a31980`](https://github.com/withastro/starlight/commit/9a319807c698f65b461f456c54c413081ab551f0) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue with custom pages using the `<StarlightPage />` component and a custom sidebar missing highlighting for the active page and navigation links. + +- [#2600](https://github.com/withastro/starlight/pull/2600) [`49aef17`](https://github.com/withastro/starlight/commit/49aef173811d05ae132729c92c3920a142ceeb7d) Thanks [@jdevega](https://github.com/jdevega)! - Adds Backstage social icon + +- [#2613](https://github.com/withastro/starlight/pull/2613) [`a73780f`](https://github.com/withastro/starlight/commit/a73780fb280feb5b96ffa94539633b2930bd8e76) Thanks [@delucis](https://github.com/delucis)! - Fixes support for `sidebar` frontmatter options in sidebar entries using `slug` or the string shorthand for internal links + +## 0.29.0 + +### Minor Changes + +- [#2551](https://github.com/withastro/starlight/pull/2551) [`154c8e3`](https://github.com/withastro/starlight/commit/154c8e337819c7d7ebf4ff4dd55db0d10607620b) Thanks [@hippotastic](https://github.com/hippotastic)! - Updates the `astro-expressive-code` dependency to the latest version (0.38). + + The new version allows using `ec.config.mjs` to selectively override individual Expressive Code styles and settings provided by Starlight themes and plugins, speeds up Shiki language loading, and adds the config option `expressiveCode.shiki.injectLangsIntoNestedCodeBlocks`. See the [Expressive Code release notes](https://expressive-code.com/releases/#0380) for full details. + +- [#2252](https://github.com/withastro/starlight/pull/2252) [`6116db0`](https://github.com/withastro/starlight/commit/6116db03a4157c0f0caa210690ef0dcdd001a287) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Improves build performance for sites with large sidebars + + This release adds a caching layer to Starlight’s sidebar generation logic, reducing the number of times sidebars need to be regenerated while building a site. Some benchmarks for projects with a complex sidebar saw builds complete more than 35% faster with this change. + +- [#2503](https://github.com/withastro/starlight/pull/2503) [`a4c8edd`](https://github.com/withastro/starlight/commit/a4c8eddc53993068c0f60159fecc123013827ef0) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Improves the accessibility of asides and tabs by removing some unnecessary HTML landmarks. + +### Patch Changes + +- [#2579](https://github.com/withastro/starlight/pull/2579) [`241966b`](https://github.com/withastro/starlight/commit/241966bd0523a2e82891d622b2a97b2f3646bc41) Thanks [@RafidMuhymin](https://github.com/RafidMuhymin)! - Adds social link icon for Nostr + +## 0.28.6 + +### Patch Changes + +- [#2565](https://github.com/withastro/starlight/pull/2565) [`236467b`](https://github.com/withastro/starlight/commit/236467bb745cea7a284ae3d398874d3edbcd846e) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue with custom UI strings defined in YAML files not being loaded in some contexts. + +## 0.28.5 + +### Patch Changes + +- [#2546](https://github.com/withastro/starlight/pull/2546) [`bf42300`](https://github.com/withastro/starlight/commit/bf42300e76241a2df888dc458c59a7478a8b2d61) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue where i18n content collection related errors, e.g. malformed JSON or YAML, would not be reported. + +- [#2548](https://github.com/withastro/starlight/pull/2548) [`07673c8`](https://github.com/withastro/starlight/commit/07673c80114021a269065e451e660337237f76e1) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a URL localization edge case. In projects without a root locale configured, slugs without a locale prefix did not fall back to the default locale as expected. + +- [#2547](https://github.com/withastro/starlight/pull/2547) [`91e1dd7`](https://github.com/withastro/starlight/commit/91e1dd731a06657890a68b2d474199455df2756f) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a Firefox Markdown content rendering issue for text sentences separated by a line break. + +- [#2524](https://github.com/withastro/starlight/pull/2524) [`1b46783`](https://github.com/withastro/starlight/commit/1b4678325fb10714fc3508bd87a7563b10a0f803) Thanks [@jsparkdev](https://github.com/jsparkdev)! - Fixes a broken link to Astro’s Docs in an error message + +## 0.28.4 + +### Patch Changes + +- [#2444](https://github.com/withastro/starlight/pull/2444) [`d585b3e`](https://github.com/withastro/starlight/commit/d585b3e0485dd55b2ffab985a6c06d267d22fe51) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a UI string translation issue for languages with a region subtag. + +- [#2518](https://github.com/withastro/starlight/pull/2518) [`0f69db8`](https://github.com/withastro/starlight/commit/0f69db8b806833a7160570a469ddcdc8c0dec5e0) Thanks [@morinokami](https://github.com/morinokami)! - Updates Japanese UI translations + +- [#2507](https://github.com/withastro/starlight/pull/2507) [`bd6ced5`](https://github.com/withastro/starlight/commit/bd6ced5bc46310b217c7bfe83a0f68ba4a03da45) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a table of contents highlighting issue after resizing the window. + +- [#2444](https://github.com/withastro/starlight/pull/2444) [`d585b3e`](https://github.com/withastro/starlight/commit/d585b3e0485dd55b2ffab985a6c06d267d22fe51) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Refactors various components to use the new built-in localization system to access translated UI strings. + +## 0.28.3 + +### Patch Changes + +- [#2408](https://github.com/withastro/starlight/pull/2408) [`0b4823d`](https://github.com/withastro/starlight/commit/0b4823d534abe517fac5efd97f6febb5965714fe) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a link formatting issue when using the Astro `build.format` option set to `file` with a `base`. + +- [#2380](https://github.com/withastro/starlight/pull/2380) [`7b451cf`](https://github.com/withastro/starlight/commit/7b451cff6979bef1c817f3a84392221ac884ba3d) Thanks [@delucis](https://github.com/delucis)! - Loosen Starlight’s i18n schema to pass through unknown keys + +- [#2388](https://github.com/withastro/starlight/pull/2388) [`6bba3d8`](https://github.com/withastro/starlight/commit/6bba3d8e02b95ecee7f9c945b6ee33b4c4ba755d) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a potential type-checking issue in Starlight projects. + +- [#2443](https://github.com/withastro/starlight/pull/2443) [`a0f40b3`](https://github.com/withastro/starlight/commit/a0f40b3c3c7ab0cb9f0f5f11b94e3679547f6ab4) Thanks [@kevinzunigacuellar](https://github.com/kevinzunigacuellar)! - Fixes CSS issue where bottom padding is not applied in the search dialog. + +## 0.28.2 + +### Patch Changes + +- [#2377](https://github.com/withastro/starlight/pull/2377) [`a257b83`](https://github.com/withastro/starlight/commit/a257b83f1e5704ff41bcbe85482ac81a1a61ce1f) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue with synced `<Tabs>` components containing nested `<Tabs>` causing tab panels to not render correctly. + +## 0.28.1 + +### Patch Changes + +- [#2334](https://github.com/withastro/starlight/pull/2334) [`79b9ade`](https://github.com/withastro/starlight/commit/79b9ade194cf704dad79267715a6970e0d7a7277) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue with Expressive Code UI labels not displaying correctly. + +## 0.28.0 + +### Minor Changes + +- [#1923](https://github.com/withastro/starlight/pull/1923) [`5269aad`](https://github.com/withastro/starlight/commit/5269aad928773ae08b35ba8e19c0f2832d0d2c89) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Overhauls the built-in localization system which is now powered by the [`i18next`](https://www.i18next.com/) library and available to use anywhere in your documentation website. + + See the [“Using UI translations”](https://starlight.astro.build/guides/i18n/#using-ui-translations) guide to learn more about how to access built-in UI labels or your own custom strings in your project. Plugin authors can also use the new [`injectTranslations()`](https://starlight.astro.build/reference/plugins/#injecttranslations) helper to add or update translation strings. + + ⚠️ **BREAKING CHANGE:** The `Astro.props.labels` props has been removed from the props passed down to custom component overrides. + + If you are relying on `Astro.props.labels` (for example to read a built-in UI label), you will need to update your code to use the new [`Astro.locals.t()`](https://starlight.astro.build/guides/i18n/#using-ui-translations) helper instead. + + ```astro + --- + import type { Props } from '@astrojs/starlight/props'; + // The `search.label` UI label for this page’s language: + const searchLabel = Astro.locals.t('search.label'); + --- + ``` + +- [#2285](https://github.com/withastro/starlight/pull/2285) [`7286220`](https://github.com/withastro/starlight/commit/728622037602999ed67dedc2757ca5654236feb8) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds support for translating sidebar badges. + +- [#1923](https://github.com/withastro/starlight/pull/1923) [`5269aad`](https://github.com/withastro/starlight/commit/5269aad928773ae08b35ba8e19c0f2832d0d2c89) Thanks [@HiDeoo](https://github.com/HiDeoo)! - ⚠️ **BREAKING CHANGE:** The minimum supported version of Astro is now 4.14.0 + + Please update Astro and Starlight together: + + ```sh + npx @astrojs/upgrade + ``` + +### Patch Changes + +- [#2327](https://github.com/withastro/starlight/pull/2327) [`d7a295e`](https://github.com/withastro/starlight/commit/d7a295e5f63171c7eee9fc11333157d8c7e6c803) Thanks [@tritao](https://github.com/tritao)! - Fixes restoration of remark directives for nodes with custom data attached. + +## 0.27.1 + +### Patch Changes + +- [#2303](https://github.com/withastro/starlight/pull/2303) [`f92791a`](https://github.com/withastro/starlight/commit/f92791aa1d1ec3d5498e445a078f7143fef60553) Thanks [@delucis](https://github.com/delucis)! - Fixes resolution for the internal module Git virtual module in projects with special characters in the file path + +## 0.27.0 + +### Minor Changes + +- [#1255](https://github.com/withastro/starlight/pull/1255) [`6f3202b`](https://github.com/withastro/starlight/commit/6f3202b3eb747de8a1cfcba001ab618d5fdee44a) Thanks [@Fryuni](https://github.com/Fryuni)! - Adds support for server-rendered Starlight pages. + + When building a project with `hybrid` or `server` output mode, a new `prerender` option on Starlight config can be set to `false` to make all Starlight pages be rendered on-demand: + + ```ts + export default defineConfig({ + output: 'server', + integrations: [ + starlight({ + prerender: false, + }), + ], + }); + ``` + +### Patch Changes + +- [#2242](https://github.com/withastro/starlight/pull/2242) [`756e85e`](https://github.com/withastro/starlight/commit/756e85e8e814657c42c4a6f9c299b5bef32aee22) Thanks [@delucis](https://github.com/delucis)! - Refactors the logic for persisting and restoring sidebar state across navigations for better performance on slow or busy devices + +- [#1255](https://github.com/withastro/starlight/pull/1255) [`6f3202b`](https://github.com/withastro/starlight/commit/6f3202b3eb747de8a1cfcba001ab618d5fdee44a) Thanks [@Fryuni](https://github.com/Fryuni)! - Improves performance of computing the last updated times from Git history. + + Instead of executing `git` for each docs page, it is now executed twice regardless of the number of pages. + +- [#1255](https://github.com/withastro/starlight/pull/1255) [`6f3202b`](https://github.com/withastro/starlight/commit/6f3202b3eb747de8a1cfcba001ab618d5fdee44a) Thanks [@Fryuni](https://github.com/Fryuni)! - Fixes last updated times on projects with custom `srcDir` + +## 0.26.4 + +### Patch Changes + +- [#2288](https://github.com/withastro/starlight/pull/2288) [`b15f725`](https://github.com/withastro/starlight/commit/b15f725ead981387f80f089d0523d9c2748b184e) Thanks [@matthewp](https://github.com/matthewp)! - Safely handle Zod errors + + Prevents bugs where errors without the `.received` props would through and cause builds to fail unnecessarily. + +## 0.26.3 + +### Patch Changes + +- [#2281](https://github.com/withastro/starlight/pull/2281) [`5062d30`](https://github.com/withastro/starlight/commit/5062d30c08f6ede9e6c39174537bb61280e7c23d) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a potential text rendering issue that could include extra whitespaces for text containing colons. + +- [#2279](https://github.com/withastro/starlight/pull/2279) [`62d59e2`](https://github.com/withastro/starlight/commit/62d59e29d2621d834c28c764a02c58b1e1b49243) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue with frontmatter schemas containing collection references used with the `<StarlightPage />` component and an Astro version greater than `4.14.0`. + +## 0.26.2 + +### Patch Changes + +- [#2273](https://github.com/withastro/starlight/pull/2273) [`746e0cd`](https://github.com/withastro/starlight/commit/746e0cd301f4ac4a182e8c45b36865c61d208b77) Thanks [@delucis](https://github.com/delucis)! - Fixes type error when using Starlight with Astro v4.15 + +- [#2265](https://github.com/withastro/starlight/pull/2265) [`25b661e`](https://github.com/withastro/starlight/commit/25b661e238cdc6c08ef79504fa5507d879c0f62d) Thanks [@SeraphicRav](https://github.com/SeraphicRav)! - Adds TikTok social icon + +- [#2272](https://github.com/withastro/starlight/pull/2272) [`d1969dd`](https://github.com/withastro/starlight/commit/d1969dde2ea8ece6ce9d439eae12d9c63c2201d7) Thanks [@o-az](https://github.com/o-az)! - Adds new icon: `jsr` + +- [#2250](https://github.com/withastro/starlight/pull/2250) [`c0a6166`](https://github.com/withastro/starlight/commit/c0a6166bb280e2d70060b68cdf6ee166812c82d2) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Removes internal E2E tests from the package published to the npm registry. + +- [#2253](https://github.com/withastro/starlight/pull/2253) [`72bc76a`](https://github.com/withastro/starlight/commit/72bc76a28f5c1b050d8125d80c6146526b699600) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue preventing to use the `class` attribute in hero action link buttons. + +## 0.26.1 + +### Patch Changes + +- [#2219](https://github.com/withastro/starlight/pull/2219) [`74d4716`](https://github.com/withastro/starlight/commit/74d4716f6a70fbef486e1057b81d2280c40251df) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a sidebar persistence issue when navigating between pages with different sidebar content. + +## 0.26.0 + +### Minor Changes + +- [#1784](https://github.com/withastro/starlight/pull/1784) [`68f56a7`](https://github.com/withastro/starlight/commit/68f56a7ffd314b760443a057db9ed1a982dbe191) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds `<LinkButton>` component for visually distinct and emphasized call to action links + +- [#2150](https://github.com/withastro/starlight/pull/2150) [`9368494`](https://github.com/withastro/starlight/commit/9368494210dbcd80ada5b410340814fe36c4eb6c) Thanks [@delucis](https://github.com/delucis)! - Adds state persistence across page navigations to the main site sidebar + +- [#2087](https://github.com/withastro/starlight/pull/2087) [`caa84ea`](https://github.com/withastro/starlight/commit/caa84eaa7dc653d27d539fd3a93df346a9f0f149) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds persistence to synced `<Tabs>` so that a user's choices are reflected across page navigations. + +- [#2051](https://github.com/withastro/starlight/pull/2051) [`ec3b579`](https://github.com/withastro/starlight/commit/ec3b5794cac55a5755620fa5e205f0d54c9e343b) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds a guideline to the last step of the `<Steps>` component. + + If you want to preserve the previous behaviour and hide the guideline on final steps, you can add the following custom CSS to your site: + + ```css + /* Hide the guideline for the final step in <Steps> lists. */ + .sl-steps > li:last-of-type::after { + background: transparent; + } + ``` + +- [#1784](https://github.com/withastro/starlight/pull/1784) [`68f56a7`](https://github.com/withastro/starlight/commit/68f56a7ffd314b760443a057db9ed1a982dbe191) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Changes the hero component action button default [variant](https://starlight.astro.build/reference/frontmatter/#heroconfig) from `minimal` to `primary`. + + ⚠️ **BREAKING CHANGE:** If you want to preserve the previous appearance, hero component action buttons previously declared without a `variant` will need to be updated to include the `variant` property with the value `minimal`. + + ```diff + hero: + actions: + - text: View on GitHub + link: https://github.com/astronaut/my-project + icon: external + + variant: minimal + ``` + +- [#2168](https://github.com/withastro/starlight/pull/2168) [`e044fee`](https://github.com/withastro/starlight/commit/e044feeae9a336a87db526107e5772b54ddc567f) Thanks [@HiDeoo](https://github.com/HiDeoo)! - ⚠️ **BREAKING CHANGE:** Updates the `<StarlightPage />` component `sidebar` prop to accept an array of [`SidebarItem`](https://starlight.astro.build/reference/configuration/#sidebaritem)s like the main Starlight `sidebar` configuration in `astro.config.mjs`. + + This change simplifies the definition of sidebar items in the `<StarlightPage />` component, allows for shared sidebar configuration between the global `sidebar` option and `<StarlightPage />` component, and also enables the usage of autogenerated sidebar groups with the `<StarlightPage />` component. + If you are using the `<StarlightPage />` component with a custom `sidebar` configuration, you will need to update the `sidebar` prop to an array of [`SidebarItem`](https://starlight.astro.build/reference/configuration/#sidebaritem) objects. + + For example, the following custom page with a custom `sidebar` configuration defines a “Resources” group with a “New” badge, a link to the “Showcase” page which is part of the `docs` content collection, and a link to the Starlight website: + + ```astro + --- + // src/pages/custom-page/example.astro + --- + + <StarlightPage + frontmatter={{ title: 'My custom page' }} + sidebar={[ + { + type: 'group', + label: 'Resources', + badge: { text: 'New' }, + items: [ + { type: 'link', label: 'Showcase', href: '/showcase/' }, + { + type: 'link', + label: 'Starlight', + href: 'https://starlight.astro.build/', + }, + ], + }, + ]} + > + <p>This is a custom page with a custom component.</p> + </StarlightPage> + ``` + + This configuration will now need to be updated to the following: + + ```astro + --- + // src/pages/custom-page/example.astro + --- + + <StarlightPage + frontmatter={{ title: 'My custom page' }} + sidebar={[ + { + label: 'Resources', + badge: { text: 'New' }, + items: [ + 'showcase', + { label: 'Starlight', link: 'https://starlight.astro.build/' }, + ], + }, + ]} + > + <p>This is a custom page with a custom component.</p> + </StarlightPage> + ``` + + See the [“Sidebar Navigation”](https://starlight.astro.build/guides/sidebar/) guide to learn more about the available options for customizing the sidebar. + +## 0.25.5 + +### Patch Changes + +- [#2171](https://github.com/withastro/starlight/pull/2171) [`c8258d7`](https://github.com/withastro/starlight/commit/c8258d7ef9264a0f85710d463a83d16013dc1934) Thanks [@delucis](https://github.com/delucis)! - Improves build performance slightly for bigger sites + +- [#2199](https://github.com/withastro/starlight/pull/2199) [`91557fd`](https://github.com/withastro/starlight/commit/91557fd73a43ab596f0fefb7c9aa0218b9a0b208) Thanks [@connorjs](https://github.com/connorjs)! - Adds Azure DevOps (`azureDevOps`) icon for use in social links. + +## 0.25.4 + +### Patch Changes + +- [#2155](https://github.com/withastro/starlight/pull/2155) [`8bed886`](https://github.com/withastro/starlight/commit/8bed88674c732040cf66d392372386a8917a2eeb) Thanks [@delucis](https://github.com/delucis)! - Improves page load performance on slower devices + +- [#2167](https://github.com/withastro/starlight/pull/2167) [`9ac7725`](https://github.com/withastro/starlight/commit/9ac7725dbe84f3fab9b191452471d8eaffd55048) Thanks [@delucis](https://github.com/delucis)! - Fixes an issue detecting the built-in locale when running Starlight in a web container environment on Firefox + +- [#2166](https://github.com/withastro/starlight/pull/2166) [`4f12049`](https://github.com/withastro/starlight/commit/4f120490e914fb308e909b97890a11bb95ae964c) Thanks [@delucis](https://github.com/delucis)! - Updates `@astrojs/mdx`, `@astrojs/sitemap`, `astro-expressive-code`, `unified`, and `vfile` dependencies to the latest version + +## 0.25.3 + +### Patch Changes + +- [#2154](https://github.com/withastro/starlight/pull/2154) [`0b381d5`](https://github.com/withastro/starlight/commit/0b381d53f23c31492cf415057d960f9a5eaa2f3d) Thanks [@mktbsh](https://github.com/mktbsh)! - Updates `<head>` logic to deduplicate `<link rel="canonical">` tags. This means that custom canonicals set via frontmatter now override the default canonical generated by Starlight. + +- [#2157](https://github.com/withastro/starlight/pull/2157) [`6757d97`](https://github.com/withastro/starlight/commit/6757d97b0ae789e0c61a776ad9af742858c663b0) Thanks [@astrobot-houston](https://github.com/astrobot-houston)! - Updates file tree icon mapping to correctly map `.cjs` and `.mjs` extensions in several contexts + +- [#2156](https://github.com/withastro/starlight/pull/2156) [`904ad47`](https://github.com/withastro/starlight/commit/904ad47ea9588c0b1d8c583f3f04e4ae199474d9) Thanks [@delucis](https://github.com/delucis)! - Fixes builds for projects with a space in their pathname + +- [#2137](https://github.com/withastro/starlight/pull/2137) [`703903b`](https://github.com/withastro/starlight/commit/703903bb782c3fabd3fe914e40494c00f12ec945) Thanks [@cevdetardaharan](https://github.com/cevdetardaharan)! - Removes `twitter:title` and `twitter:description` meta tags from `<head>` + +## 0.25.2 + +### Patch Changes + +- [#2126](https://github.com/withastro/starlight/pull/2126) [`ada51ee`](https://github.com/withastro/starlight/commit/ada51ee1500d07c1819059f57e97dc6e97b4d2ba) Thanks [@essential-randomness](https://github.com/essential-randomness)! - Adds support for markdown formatting in aside titles + +- [#2135](https://github.com/withastro/starlight/pull/2135) [`9bbb969`](https://github.com/withastro/starlight/commit/9bbb9690616f79a80f3d286082b2500457bbcae9) Thanks [@oluwatobiss](https://github.com/oluwatobiss)! - Adds Pinterest social icon + +## 0.25.1 + +### Patch Changes + +- [#2122](https://github.com/withastro/starlight/pull/2122) [`359a642`](https://github.com/withastro/starlight/commit/359a64219288795936f18fd50fb5f195c412a748) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an i18n configuration issue for multilingual sites when using Astro’s `i18n` config with `prefixDefaultLocale` set to `false`. + +- [#2107](https://github.com/withastro/starlight/pull/2107) [`61e223b`](https://github.com/withastro/starlight/commit/61e223b153cb10958f3fbaa77acf6ac07d982944) Thanks [@sanabel-al-firdaws](https://github.com/sanabel-al-firdaws)! - Updates Arabic UI translations + +- [#2105](https://github.com/withastro/starlight/pull/2105) [`81f8a2c`](https://github.com/withastro/starlight/commit/81f8a2c9580ec07dd17e2f596b9b1b50fae8237a) Thanks [@delucis](https://github.com/delucis)! - Fixes an edge case in custom pagination link processing + + Custom link values for `prev`/`next` in page frontmatter are now always used as authored. + Previously this was not the case in some edge cases such as for the first and final pages in the sidebar. + +- [#2119](https://github.com/withastro/starlight/pull/2119) [`464685a`](https://github.com/withastro/starlight/commit/464685a3ce33e7ccc8d1d7365935732c87ba95e9) Thanks [@evadecker](https://github.com/evadecker)! - Improves styling of `<hr>`, `<blockquote>`, and `<code>` within asides + +## 0.25.0 + +### Minor Changes + +- [#2025](https://github.com/withastro/starlight/pull/2025) [`47f32c1`](https://github.com/withastro/starlight/commit/47f32c196c5d840a6a45799ddf123d17c77274b0) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Removes the `/` search shortcut for [accessibility reasons](https://www.w3.org/WAI/WCAG21/Understanding/character-key-shortcuts.html). + + ⚠️ **Potentially breaking change:** The `search.shortcutLabel` UI string has been removed. If you were using this string in your custom UI, you will need to update your code. + +- [#2064](https://github.com/withastro/starlight/pull/2064) [`c5b47cb`](https://github.com/withastro/starlight/commit/c5b47cbe1242f0b29b9212db72fe26590ab57d88) Thanks [@SnowDingo](https://github.com/SnowDingo)! - Improves styling of Markdown tables to work better in different contexts, including against different background colours like when used in asides. + +- [#2031](https://github.com/withastro/starlight/pull/2031) [`2bab648`](https://github.com/withastro/starlight/commit/2bab648be9ddc6bfe05562650b773f5158a9ed42) Thanks [@delucis](https://github.com/delucis)! - Makes sidebar entry parsing stricter in Starlight config + + **⚠️ Potentially breaking change:** Previously Starlight would accept a sidebar entry that matched one of its expected shapes, even if it included additional properties. For example, including both `link` and `items` was considered valid, with `items` being ignored. Now, it is an error to include more than one of `link`, `items`, or `autogenerate` in a sidebar entry. + + If you see errors after updating, look for sidebar entries in the Starlight configuration in `astro.config.mjs` that include too many keys and remove the one that was previously ignored. + +- [#1874](https://github.com/withastro/starlight/pull/1874) [`eeba06e`](https://github.com/withastro/starlight/commit/eeba06ea7df962e8f0520e145d28b8c17cd32c18) Thanks [@lorenzolewis](https://github.com/lorenzolewis)! - Adds a new syntax for specifying sidebar link items for internal links + + You can now specify an internal page using only its slug, either as a string, or as an object with a `slug` property: + + ```js + starlight({ + title: 'Docs with easier sidebars', + sidebar: ['getting-started', { slug: 'guides/installation' }], + }); + ``` + + Starlight will use the linked page’s frontmatter to configure the sidebar link. + +### Patch Changes + +- [#2081](https://github.com/withastro/starlight/pull/2081) [`f0181d2`](https://github.com/withastro/starlight/commit/f0181d2689248a46ff3eb6fc604bfcd95d4cb1aa) Thanks [@andrii-bodnar](https://github.com/andrii-bodnar)! - Updates the Ukrainian UI translations + +## 0.24.5 + +### Patch Changes + +- [#2062](https://github.com/withastro/starlight/pull/2062) [`5ac0ac6`](https://github.com/withastro/starlight/commit/5ac0ac6614e3c45d810a1594a2009d3febfa2793) Thanks [@evadecker](https://github.com/evadecker)! - Increase theme and language select inline padding + +- [#2056](https://github.com/withastro/starlight/pull/2056) [`87e9ad0`](https://github.com/withastro/starlight/commit/87e9ad029c9730fca8df66e35828b57cd0872a61) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue preventing remark plugins injected by Starlight plugins to handle Markdown text and leaf directives. + +- [#2063](https://github.com/withastro/starlight/pull/2063) [`3ee1a94`](https://github.com/withastro/starlight/commit/3ee1a9404db25f5776a3c1ecd248614f64db46ae) Thanks [@delucis](https://github.com/delucis)! - Translate `fileTree.directory` and `aside.*` UI string into Norwegian (Bokmål). + +- [#2054](https://github.com/withastro/starlight/pull/2054) [`dbfd3ee`](https://github.com/withastro/starlight/commit/dbfd3eeccacb5f5b77d75213dac3b30dc0be6deb) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue when using the `<StarlightPage>` component in a custom page with a user-defined `srcDir` configuration. + +## 0.24.4 + +### Patch Changes + +- [#2038](https://github.com/withastro/starlight/pull/2038) [`87f3f92`](https://github.com/withastro/starlight/commit/87f3f925be6f9897b71b09a3041ec6d54be483b2) Thanks [@dragomano](https://github.com/dragomano)! - Updates Russian UI translations + +- [#2043](https://github.com/withastro/starlight/pull/2043) [`53f4cd4`](https://github.com/withastro/starlight/commit/53f4cd443cf31b6135ff16eb74b5f26ee93ee2d5) Thanks [@playmr365](https://github.com/playmr365)! - Updates Czech UI translations + +- [#2041](https://github.com/withastro/starlight/pull/2041) [`8af5a60`](https://github.com/withastro/starlight/commit/8af5a60ab14f4dae7f5a5e4ee535ae927273368b) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes `<Steps>` numbering bug caused by Chrome v126 CSS counter rewrite + +## 0.24.3 + +### Patch Changes + +- [#2028](https://github.com/withastro/starlight/pull/2028) [`af81ad3`](https://github.com/withastro/starlight/commit/af81ad38fd26c375c0372718fd3e152b7f1a0fa6) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a search dialog height issue in Safari. + +- [#2022](https://github.com/withastro/starlight/pull/2022) [`80f82b1`](https://github.com/withastro/starlight/commit/80f82b15afae1366676e0c25e674210a19606df5) Thanks [@playmr365](https://github.com/playmr365)! - Updates Czech UI translations + +## 0.24.2 + +### Patch Changes + +- [#2008](https://github.com/withastro/starlight/pull/2008) [`40359c7`](https://github.com/withastro/starlight/commit/40359c7b73d9c7d60f0b44a870dbc93ba941228f) Thanks [@vnepogodin](https://github.com/vnepogodin)! - Add Slovak language UI translation. + +- [#2004](https://github.com/withastro/starlight/pull/2004) [`0aa2f06`](https://github.com/withastro/starlight/commit/0aa2f06d3a35a3c5182b4d461c8f3489ac145301) Thanks [@liruifengv](https://github.com/liruifengv)! - Removes an outdated export in `package.json` + +- [#2007](https://github.com/withastro/starlight/pull/2007) [`44ca490`](https://github.com/withastro/starlight/commit/44ca490f36ecd6789d0865dd2506e5ea03dfa0fb) Thanks [@delucis](https://github.com/delucis)! - Updates internal dependencies + +- [#1993](https://github.com/withastro/starlight/pull/1993) [`60165b2`](https://github.com/withastro/starlight/commit/60165b20c9d11a08c4c4793615778e045b41b7de) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an i18n configuration issue when using a single root locale. + +## 0.24.1 + +### Patch Changes + +- [#1978](https://github.com/withastro/starlight/pull/1978) [`a5ab8cd6`](https://github.com/withastro/starlight/commit/a5ab8cd6a0095cb48b65b9784054714f87bd7e4d) Thanks [@kylewlacy](https://github.com/kylewlacy)! - Add new social icon for Zulip + +- [#1962](https://github.com/withastro/starlight/pull/1962) [`2ef19a94`](https://github.com/withastro/starlight/commit/2ef19a947c54c7d2c085bf8820c862737e2ab08b) Thanks [@torn4dom4n](https://github.com/torn4dom4n)! - Updates Vietnamese UI translations + +- [#1976](https://github.com/withastro/starlight/pull/1976) [`5a61f73c`](https://github.com/withastro/starlight/commit/5a61f73c198a33b27342c9b0371dd5fd22da2190) Thanks [@jsparkdev](https://github.com/jsparkdev)! - Updates Korean UI translations + +- [#1987](https://github.com/withastro/starlight/pull/1987) [`0b8a8439`](https://github.com/withastro/starlight/commit/0b8a843936bd8506ac228608b07c54a76a7add19) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes issues with the locale text direction detection mechanism in some environments like WebContainers or Bun. + +## 0.24.0 + +### Minor Changes + +- [#1841](https://github.com/withastro/starlight/pull/1841) [`ee0cd38a`](https://github.com/withastro/starlight/commit/ee0cd38a1fae31717fe820e779baeabe693cd67a) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds support for `Astro.currentLocale` and Astro’s i18n routing. + + ⚠️ **Potentially breaking change:** Starlight now configures Astro’s `i18n` option for you based on its `locales` config. + + If you are currently using Astro’s `i18n` option as well as Starlight’s `locales` option, you will need to remove one of these. + In general we recommend using Starlight’s `locales`, but if you have a more advanced configuration you may choose to keep Astro’s `i18n` config instead. + +- [#1958](https://github.com/withastro/starlight/pull/1958) [`081d1a96`](https://github.com/withastro/starlight/commit/081d1a969462633e41ca95a18a1ec121cb4af5d2) Thanks [@delucis](https://github.com/delucis)! - Allows users to opt into displaying a “Built with Starlight” link in the site footer + +- [#1530](https://github.com/withastro/starlight/pull/1530) [`dd64836a`](https://github.com/withastro/starlight/commit/dd64836af45f33df4a99ab864eabb91fc9b8e204) Thanks [@kevinzunigacuellar](https://github.com/kevinzunigacuellar)! - Adds a new `<Badge>` component + +## 0.23.4 + +### Patch Changes + +- [#1955](https://github.com/withastro/starlight/pull/1955) [`15ef1f4b`](https://github.com/withastro/starlight/commit/15ef1f4bdbf7174134121f4bbdf82ca3903c802a) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Reverts a [change](https://github.com/withastro/starlight/pull/1948) to prevent a numbering issue with the `<Steps>` component in future versions of Chrome. + +## 0.23.3 + +### Patch Changes + +- [#1948](https://github.com/withastro/starlight/pull/1948) [`68c0c077`](https://github.com/withastro/starlight/commit/68c0c077a9ca5ec2a8206e99b70236043a74c3b8) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a `<Steps>` component numbering issue with the next Chrome stable version when a step contains a nested list. + +- [#1909](https://github.com/withastro/starlight/pull/1909) [`c98c7088`](https://github.com/withastro/starlight/commit/c98c7088ee3ecd43522dac0916fd41c417693f65) Thanks [@joshka](https://github.com/joshka)! - Adds Discourse to social icons + +## 0.23.2 + +### Patch Changes + +- [#1913](https://github.com/withastro/starlight/pull/1913) [`7ebe8f75`](https://github.com/withastro/starlight/commit/7ebe8f7599d473cdd22c80bb0fe115fe6120cab7) Thanks [@delucis](https://github.com/delucis)! - Fixes support for Astro’s `build: { format: 'preserve' }` configuration option + +- [#1941](https://github.com/withastro/starlight/pull/1941) [`2f3240c9`](https://github.com/withastro/starlight/commit/2f3240c91c09dfc411d93a71eeb75ad6d704e14b) Thanks [@astrobot-houston](https://github.com/astrobot-houston)! - Adds icon support for `.otf` files in `<FileTree>` + +## 0.23.1 + +### Patch Changes + +- [#1892](https://github.com/withastro/starlight/pull/1892) [`01de9be8`](https://github.com/withastro/starlight/commit/01de9be89c85bcd0022e87465182ee1aba501687) Thanks [@delucis](https://github.com/delucis)! - Internal refactor: simplify some CSS for the `<details>` element + +## 0.23.0 + +### Minor Changes + +- [#1846](https://github.com/withastro/starlight/pull/1846) [`2de67039`](https://github.com/withastro/starlight/commit/2de6703971908cfc0df2915ebf89a63e0141f954) Thanks [@delucis](https://github.com/delucis)! - Updates `@astrojs/mdx` to v3 and enables MDX optimization by default + + ⚠️ **Potentially breaking change:** MDX optimization speeds up builds (Starlight’s docs are building ~40% faster for example), but restricts some advanced MDX features. See full details in the [MDX optimization documentation](https://docs.astro.build/en/guides/integrations-guide/mdx/#optimize). + + Most Starlight users should be unaffected, but if you are using MDX files outside of Starlight pages with the `components` prop, you may see issues. You can disable optimization by adding MDX manually to your `integrations` array in `astro.config.mjs`: + + ```diff + import { defineConfig } from 'astro/config'; + + import mdx from '@astrojs/mdx'; + import starlight from '@astrojs/starlight'; + + // https://astro.build/config + export default defineConfig({ + integrations: [ + starlight({ + title: 'My docs', + // ... + }), + + mdx(), + ], + }); + ``` + +- [#1735](https://github.com/withastro/starlight/pull/1735) [`1a9ab50d`](https://github.com/withastro/starlight/commit/1a9ab50d458d6274994ffe66a23fe7a30681337a) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds custom styles for `<details>` and `<summary>` elements in Markdown content. + +- [#1846](https://github.com/withastro/starlight/pull/1846) [`2de67039`](https://github.com/withastro/starlight/commit/2de6703971908cfc0df2915ebf89a63e0141f954) Thanks [@delucis](https://github.com/delucis)! - ⚠️ **BREAKING CHANGE:** The minimum supported version of Astro is now 4.8.6 + + Please update Astro and Starlight together: + + ```sh + npx @astrojs/upgrade + ``` + +## 0.22.4 + +### Patch Changes + +- [#1871](https://github.com/withastro/starlight/pull/1871) [`03bb126b`](https://github.com/withastro/starlight/commit/03bb126b74d9adaba1be2f0df3f34566815dd77f) Thanks [@delucis](https://github.com/delucis)! - Adds a `blueSky` icon and social link option + +- [#1873](https://github.com/withastro/starlight/pull/1873) [`13f33b81`](https://github.com/withastro/starlight/commit/13f33b81fd51d18165eb52f2a0c02b890084e4bd) Thanks [@ekfuhrmann](https://github.com/ekfuhrmann)! - Adds 1 new icon: `alpine` + +- [#1857](https://github.com/withastro/starlight/pull/1857) [`32cdfaf0`](https://github.com/withastro/starlight/commit/32cdfaf0155e65ff6fbe9c0cfacd6969ab0015d9) Thanks [@tarikcoskun](https://github.com/tarikcoskun)! - Updates Turkish UI translations + +- [#1736](https://github.com/withastro/starlight/pull/1736) [`cfa94a34`](https://github.com/withastro/starlight/commit/cfa94a346ef10804b90db28d217be175e1c1d5ed) Thanks [@julien-deramond](https://github.com/julien-deramond)! - Prevent list items from overflowing Markdown content + +## 0.22.3 + +### Patch Changes + +- [#1838](https://github.com/withastro/starlight/pull/1838) [`9fe84754`](https://github.com/withastro/starlight/commit/9fe847544f1edb85bf5b25cd81db39227814335e) Thanks [@delucis](https://github.com/delucis)! - Adds extra information to the errors thrown by the `<Steps>` component to help locate misformatted code + +- [#1863](https://github.com/withastro/starlight/pull/1863) [`50be60bb`](https://github.com/withastro/starlight/commit/50be60bbc5cbc42db42e868b9e8f128b4dcbd6a5) Thanks [@torn4dom4n](https://github.com/torn4dom4n)! - Update Vietnamese translation + +- [#1837](https://github.com/withastro/starlight/pull/1837) [`a33a1223`](https://github.com/withastro/starlight/commit/a33a12231772c1dc4b7cc2db3477a6802f3ef53e) Thanks [@delucis](https://github.com/delucis)! - Adds three new icons: `comment`, `comment-alt`, `heart` + +- [#1842](https://github.com/withastro/starlight/pull/1842) [`c7838636`](https://github.com/withastro/starlight/commit/c7838636edb8d60a2422ce76a2db511b9cebbb70) Thanks [@delucis](https://github.com/delucis)! - Moves the `href` used in the site title link to Starlight’s route data object. This makes it possible for overrides to change the title link while reusing Starlight’s default component implementation. + +- [#1840](https://github.com/withastro/starlight/pull/1840) [`cb85563c`](https://github.com/withastro/starlight/commit/cb85563c9a3d4eb2925ad884e6a4e8698a15381b) Thanks [@MiahaCybersec](https://github.com/MiahaCybersec)! - Adds 1 new icon: `hackerone` + +## 0.22.2 + +### Patch Changes + +- [#1811](https://github.com/withastro/starlight/pull/1811) [`fe06aa13`](https://github.com/withastro/starlight/commit/fe06aa1307208ef9f5b249181ec29837f96940c2) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a `<Tabs>` sync issue when inconsistently using the `icon` prop or not on `<TabItem>` components. + +- [#1826](https://github.com/withastro/starlight/pull/1826) [`52ea7381`](https://github.com/withastro/starlight/commit/52ea7381e131338a03cffb3499ba1699951cea1e) Thanks [@dragomano](https://github.com/dragomano)! - Updates Russian UI translations + +## 0.22.1 + +### Patch Changes + +- [`1c0fc384`](https://github.com/withastro/starlight/commit/1c0fc3849771713d5a3e7a572bdbf1483ae5551b) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue where the `siteTitle` property would not be set when using the `<StarlightPage />` component. + +## 0.22.0 + +### Minor Changes + +- [#640](https://github.com/withastro/starlight/pull/640) [`7dc503ea`](https://github.com/withastro/starlight/commit/7dc503ea7993123a4aeff453d08de41cac887353) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds support for syncing multiple sets of tabs on the same page. + +- [#1620](https://github.com/withastro/starlight/pull/1620) [`ca0678ca`](https://github.com/withastro/starlight/commit/ca0678ca556d739bda9648edc1b79c764fdea851) Thanks [@emjio](https://github.com/emjio)! - Adds support for translating the site title + + ⚠️ **Potentially breaking change:** The shape of the `title` field on Starlight’s internal config object has changed. This used to be a string, but is now an object. + + If you are relying on `config.title` (for example in a custom `<SiteTitle>` or `<Head>` component), you will need to update your code. We recommend using the new [`siteTitle` prop](https://starlight.astro.build/reference/overrides/#sitetitle) available to component overrides: + + ```astro + --- + import type { Props } from '@astrojs/starlight/props'; + + // The site title for this page’s language: + const { siteTitle } = Astro.props; + --- + ``` + +- [#1613](https://github.com/withastro/starlight/pull/1613) [`61493e55`](https://github.com/withastro/starlight/commit/61493e55f1a80362af13f98d665018376e987439) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds new `draft` frontmatter option to exclude a page from production builds. + +- [#640](https://github.com/withastro/starlight/pull/640) [`7dc503ea`](https://github.com/withastro/starlight/commit/7dc503ea7993123a4aeff453d08de41cac887353) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Updates the default `line-height` from `1.8` to `1.75`. This change avoids having a line height with a fractional part which can cause scripts accessing dimensions involving the line height to get an inconsistent rounded value in various browsers. + + If you want to preserve the previous `line-height`, you can add the following custom CSS to your site: + + ```css + :root { + --sl-line-height: 1.8; + } + ``` + +- [#1720](https://github.com/withastro/starlight/pull/1720) [`749ddf85`](https://github.com/withastro/starlight/commit/749ddf85a21d8ed1bfedbe60dee676cdd8784e96) Thanks [@jacobdalamb](https://github.com/jacobdalamb)! - Updates `astro-expressive-code` dependency to the latest minor release (0.35) and exposes a new `@astrojs/starlight/expressive-code/hast` module for users who need to use Expressive Code’s version of `hast`. + + This includes a potentially breaking change if you use custom Expressive Code plugins. See the [Expressive Code release notes](https://expressive-code.com/releases/#0340) for full details. + +- [#1769](https://github.com/withastro/starlight/pull/1769) [`bd5f1cbd`](https://github.com/withastro/starlight/commit/bd5f1cbd5aef9e2d78e7f7187eb07deee87399d0) Thanks [@ncjones](https://github.com/ncjones)! - Adds support for [accessing frontmatter data as a variable](https://docs.astro.build/en/guides/integrations-guide/markdoc/#access-frontmatter-from-your-markdoc-content) when using Markdoc + +### Patch Changes + +- [#1788](https://github.com/withastro/starlight/pull/1788) [`681a4273`](https://github.com/withastro/starlight/commit/681a427366755fec71ba65d45e36f7d1267cf387) Thanks [@dragomano](https://github.com/dragomano)! - Adds Russian translations for Expressive Code labels + +- [#1780](https://github.com/withastro/starlight/pull/1780) [`4db6025a`](https://github.com/withastro/starlight/commit/4db6025a1c5c56cac2e3a98bd2e13124402445c7) Thanks [@MiahaCybersec](https://github.com/MiahaCybersec)! - Adds 1 new icon: `signal` + +- [#1785](https://github.com/withastro/starlight/pull/1785) [`65009c9c`](https://github.com/withastro/starlight/commit/65009c9cf8b0570303ecb87713e1c2968a704437) Thanks [@dreyfus92](https://github.com/dreyfus92)! - Adds 5 new icons: `node`, `cloudflare`, `vercel`, `netlify` and `deno` + +- [#1786](https://github.com/withastro/starlight/pull/1786) [`d05d693a`](https://github.com/withastro/starlight/commit/d05d693afcf1771b8269dfe2ccc94f8952c643e8) Thanks [@delucis](https://github.com/delucis)! - Fixes type inference for i18n strings added by extending the default schema + +- [#1777](https://github.com/withastro/starlight/pull/1777) [`6949404b`](https://github.com/withastro/starlight/commit/6949404b24a1c8254fd32d75122fdfbaf896fe29) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue where TypeScript could fail to serialize the frontmatter schema when configured to emit declaration files + +- [#1734](https://github.com/withastro/starlight/pull/1734) [`4493dcfa`](https://github.com/withastro/starlight/commit/4493dcfac5171f839b1b0e39444a15ce696adee4) Thanks [@delucis](https://github.com/delucis)! - Refactors `<ThemeSelect>` custom element logic to improve performance + +- [#1731](https://github.com/withastro/starlight/pull/1731) [`f08b0dff`](https://github.com/withastro/starlight/commit/f08b0dff9638bbe7704ac2ba2e855d8d1464ba76) Thanks [@techfg](https://github.com/techfg)! - Fixes responding to system color scheme changes when theme is `auto` + +- [#1793](https://github.com/withastro/starlight/pull/1793) [`2616f0c7`](https://github.com/withastro/starlight/commit/2616f0c7acf39a99c9f92b3db4108cae81120034) Thanks [@Mrahmani71](https://github.com/Mrahmani71)! - Updates the Farsi UI translations + +## 0.21.5 + +### Patch Changes + +- [#1728](https://github.com/withastro/starlight/pull/1728) [`0a75680d`](https://github.com/withastro/starlight/commit/0a75680ddd2f3325ab9ad7ac910f7c884b89a9ed) Thanks [@delucis](https://github.com/delucis)! - Adds 1 new icon: `pkl` + +- [#1709](https://github.com/withastro/starlight/pull/1709) [`c5cd1811`](https://github.com/withastro/starlight/commit/c5cd181186b42422f3e47052bf8182cb490bda6b) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a UI strings translation issue for sites configured with a single non-root language different from English. + +- [#1723](https://github.com/withastro/starlight/pull/1723) [`3b29b3ab`](https://github.com/withastro/starlight/commit/3b29b3ab824f538f27e20310cb08786a92c7bd65) Thanks [@OliverSpeir](https://github.com/OliverSpeir)! - Fixes accessibility by using `aria-selected="false"` for inactive tabs instead of removing `aria-selected="true"` in the tablist of Starlight’s `<Tabs>` component + +- [#1706](https://github.com/withastro/starlight/pull/1706) [`f171ac4d`](https://github.com/withastro/starlight/commit/f171ac4d6396eb2538598d85957670df50938b6a) Thanks [@jorenbroekema](https://github.com/jorenbroekema)! - Fixes some minor type errors + +## 0.21.4 + +### Patch Changes + +- [#1703](https://github.com/withastro/starlight/pull/1703) [`b26238f2`](https://github.com/withastro/starlight/commit/b26238f22990dcf8ba002bea6a50c66f20ad5786) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes aside custom titles rendering for nested asides. + +- [#1708](https://github.com/withastro/starlight/pull/1708) [`a72cb966`](https://github.com/withastro/starlight/commit/a72cb96600798c1fbc7558f8fd24556ca442d312) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes translation issues with Expressive Code when using a default language other than English + +## 0.21.3 + +### Patch Changes + +- [#1622](https://github.com/withastro/starlight/pull/1622) [`3a074bad`](https://github.com/withastro/starlight/commit/3a074bad6c139bb9d6169d95ec79bc0fc1ecbdfe) Thanks [@SamuelLHuber](https://github.com/SamuelLHuber)! - Adds 1 new icon: `farcaster` + +- [#1616](https://github.com/withastro/starlight/pull/1616) [`a86f9b71`](https://github.com/withastro/starlight/commit/a86f9b71b795fb6dcd0409ca568e43d25525b964) Thanks [@dragomano](https://github.com/dragomano)! - Updates Russian UI strings + +- [#1698](https://github.com/withastro/starlight/pull/1698) [`67b892fd`](https://github.com/withastro/starlight/commit/67b892fd5290dfd0eeb95f4e60b6427bdc82110f) Thanks [@liruifengv](https://github.com/liruifengv)! - Adds 1 new icon: `starlight` + +- [#1687](https://github.com/withastro/starlight/pull/1687) [`6fa9ea7e`](https://github.com/withastro/starlight/commit/6fa9ea7e8d4d601cf8f49b61dafb1ebb557d1718) Thanks [@mingjunlu](https://github.com/mingjunlu)! - Translates `fileTree.directory` UI string into Traditional Chinese. + +## 0.21.2 + +### Patch Changes + +- [#1628](https://github.com/withastro/starlight/pull/1628) [`24c0823c`](https://github.com/withastro/starlight/commit/24c0823c61b1e9850575766876f2e1035541cfd1) Thanks [@o-az](https://github.com/o-az)! - Adds 1 new icon: `nix` + +- [#1614](https://github.com/withastro/starlight/pull/1614) [`78fc9042`](https://github.com/withastro/starlight/commit/78fc90426d58d6c36dcb8215e3181476d0702f50) Thanks [@kpodurgiel](https://github.com/kpodurgiel)! - Adds Polish UI translations + +- [#1596](https://github.com/withastro/starlight/pull/1596) [`13ed30cd`](https://github.com/withastro/starlight/commit/13ed30cd335798177dfe24a27851d2c14d2fe80a) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds support for toggling the built-in search modal using the `Ctrl+k` keyboard shortcut. + +- [#1608](https://github.com/withastro/starlight/pull/1608) [`4096e1b7`](https://github.com/withastro/starlight/commit/4096e1b77b3464338e5489d00cec4c29a1cd3c32) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Removes nested CSS from the `<FileTree>` component to prevent a potential warning when using Tailwind CSS. + +- [#1626](https://github.com/withastro/starlight/pull/1626) [`67459cb4`](https://github.com/withastro/starlight/commit/67459cb4021859f4a45d50a5f993d2c849f340a3) Thanks [@hippotastic](https://github.com/hippotastic)! - Fixes a bundling issue that caused imports from `@astrojs/starlight/components` to fail when using the config setting `expressiveCode: false`. + +## 0.21.1 + +### Patch Changes + +- [#1584](https://github.com/withastro/starlight/pull/1584) [`8851d5cd`](https://github.com/withastro/starlight/commit/8851d5cd0d8f8439320ef729ca57a59418db52b9) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds 2 new icons: `apple` and `linux`. + +- [#1577](https://github.com/withastro/starlight/pull/1577) [`0ba77890`](https://github.com/withastro/starlight/commit/0ba77890e0dcf54a849c735efd870327c10972aa) Thanks [@morinokami](https://github.com/morinokami)! - Translates `fileTree.directory` UI string into Japanese. + +- [#1593](https://github.com/withastro/starlight/pull/1593) [`fa7ed245`](https://github.com/withastro/starlight/commit/fa7ed2458caf6261d16c5f43365cedbcb8572a48) Thanks [@liruifengv](https://github.com/liruifengv)! - Translates `fileTree.directory` UI string into simplified Chinese. + +- [#1585](https://github.com/withastro/starlight/pull/1585) [`bd4e278f`](https://github.com/withastro/starlight/commit/bd4e278f7fe7d7335494602db29a63002fd45059) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Translates `fileTree.directory` UI string into French. + +- [#1587](https://github.com/withastro/starlight/pull/1587) [`c5794260`](https://github.com/withastro/starlight/commit/c5794260251ed414a396089782a1788539c92dd3) Thanks [@Eveeifyeve](https://github.com/Eveeifyeve)! - Adds 1 new icon: `homebrew`. + +## 0.21.0 + +### Minor Changes + +- [#1568](https://github.com/withastro/starlight/pull/1568) [`5f99a71d`](https://github.com/withastro/starlight/commit/5f99a71ddfe92568b1cd3c0bfe5ebfd139797c1a) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds support for optionally setting an icon on a `<TabItem>` component to make it easier to visually distinguish between tabs. + +- [#1308](https://github.com/withastro/starlight/pull/1308) [`9a918a5b`](https://github.com/withastro/starlight/commit/9a918a5b4902f43729f4d023257772710af3a12b) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds `<FileTree>` component to display the structure of a directory. + +- [#1308](https://github.com/withastro/starlight/pull/1308) [`9a918a5b`](https://github.com/withastro/starlight/commit/9a918a5b4902f43729f4d023257772710af3a12b) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds 144 new file-type icons from the [Seti UI icon set](https://github.com/jesseweed/seti-ui#current-icons), available with the `seti:` prefix, e.g. `seti:javascript`. + +- [#1564](https://github.com/withastro/starlight/pull/1564) [`d880065e`](https://github.com/withastro/starlight/commit/d880065e29a632823a08adcb6158a59fd9557270) Thanks [@delucis](https://github.com/delucis)! - Adds a `<Steps>` component for styling more complex guided tasks. + +- [#1308](https://github.com/withastro/starlight/pull/1308) [`9a918a5b`](https://github.com/withastro/starlight/commit/9a918a5b4902f43729f4d023257772710af3a12b) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds 5 new icons: `astro`, `biome`, `bun`, `mdx`, and `pnpm`. + +## 0.20.1 + +### Patch Changes + +- [#1553](https://github.com/withastro/starlight/pull/1553) [`8e091147`](https://github.com/withastro/starlight/commit/8e09114755d37322d6e97b0dc90a5dfd781de8cc) Thanks [@hippotastic](https://github.com/hippotastic)! - Updates Expressive Code to v0.33.4 to fix potential race condition bug in Shiki. + +## 0.20.0 + +### Minor Changes + +- [#1541](https://github.com/withastro/starlight/pull/1541) [`1043052f`](https://github.com/withastro/starlight/commit/1043052f3890a577a73276472f3773924909406b) Thanks [@hippotastic](https://github.com/hippotastic)! - Updates `astro-expressive-code` dependency to the latest minor release (0.33). + + This unlocks support for [word wrap](https://expressive-code.com/key-features/word-wrap/) and [line numbers](https://expressive-code.com/plugins/line-numbers/), as well as updating the syntax highlighter to the latest Shiki release, which includes new and updated language grammars. + + See the [Expressive Code release notes](https://expressive-code.com/releases/) for more information including details of potentially breaking changes. + +### Patch Changes + +- [#1542](https://github.com/withastro/starlight/pull/1542) [`b3b7a606`](https://github.com/withastro/starlight/commit/b3b7a6069952d5f27a49b2fd097aa4db065e1718) Thanks [@delucis](https://github.com/delucis)! - Improves error messages shown by Starlight for configuration errors. + +- [#1544](https://github.com/withastro/starlight/pull/1544) [`65dc6586`](https://github.com/withastro/starlight/commit/65dc6586ef7c1754875db1d48c49e709051a0b13) Thanks [@torn4dom4n](https://github.com/torn4dom4n)! - Update Vietnamese UI translations + +## 0.19.1 + +### Patch Changes + +- [#1527](https://github.com/withastro/starlight/pull/1527) [`163bc84`](https://github.com/withastro/starlight/commit/163bc848e173eecca92d1cb034045fdb42aa4ff1) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Exports the `StarlightPageProps` TypeScript type representing the props expected by the `<StarlightPage />` component. + +- [#1504](https://github.com/withastro/starlight/pull/1504) [`fc83a05`](https://github.com/withastro/starlight/commit/fc83a05235b74be2bfe6ba8e7f95a8a5a618ead3) Thanks [@mingjunlu](https://github.com/mingjunlu)! - Adds Traditional Chinese UI translations + +- [#1534](https://github.com/withastro/starlight/pull/1534) [`aada680`](https://github.com/withastro/starlight/commit/aada6805abc0068f07393585b86978ef5200439c) Thanks [@delucis](https://github.com/delucis)! - Improves DX of the `sidebar` prop used by the new `<StarlightPage>` component. + +## 0.19.0 + +### Minor Changes + +- [#1485](https://github.com/withastro/starlight/pull/1485) [`2cb3578`](https://github.com/withastro/starlight/commit/2cb35782dace67c7c418a31005419fa95493b3d3) Thanks [@timokoessler](https://github.com/timokoessler)! - Add support for setting html attributes of hero action links + +- [#1175](https://github.com/withastro/starlight/pull/1175) [`dd11b95`](https://github.com/withastro/starlight/commit/dd11b9538abdf4b5ba2ef70e07c0edda03e95add) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds a new `<StarlightPage>` component to use the Starlight layout in custom pages. + + To learn more about this new feature, check out the new [“Using Starlight’s design in custom pages” guide](https://starlight.astro.build/guides/pages/#using-starlights-design-in-custom-pages). + +- [#1499](https://github.com/withastro/starlight/pull/1499) [`97bf523`](https://github.com/withastro/starlight/commit/97bf523923fb9678c12f58fcdbe36757f0e56ceb) Thanks [@delucis](https://github.com/delucis)! - Adds a new `<Aside>` component + + The new component is in addition to the existing custom Markdown syntax. + +## 0.18.1 + +### Patch Changes + +- [#1487](https://github.com/withastro/starlight/pull/1487) [`6a72bda`](https://github.com/withastro/starlight/commit/6a72bda8c5569e2eda68fdf258ae9b1dc8b320d6) Thanks [@NavyStack](https://github.com/NavyStack)! - Improves Korean UI translations + +- [#1489](https://github.com/withastro/starlight/pull/1489) [`b0d36de`](https://github.com/withastro/starlight/commit/b0d36de3398d4895603a787b612b1f0747defbdc) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes a potential text rendering issue with text containing colons. + +## 0.18.0 + +### Minor Changes + +- [#1454](https://github.com/withastro/starlight/pull/1454) [`1d9ef56`](https://github.com/withastro/starlight/commit/1d9ef567907bed7210e75ab3460f536c0768a87f) Thanks [@Fryuni](https://github.com/Fryuni)! - Makes Starlight compatible with [on-demand server rendering](https://docs.astro.build/en/guides/server-side-rendering/) (sometimes referred to as server-side rendering or SSR). + + Starlight pages are always prerendered, even when using `output: 'server'`. + +- [#1454](https://github.com/withastro/starlight/pull/1454) [`1d9ef56`](https://github.com/withastro/starlight/commit/1d9ef567907bed7210e75ab3460f536c0768a87f) Thanks [@Fryuni](https://github.com/Fryuni)! - Enables Astro’s [`experimental.globalRoutePriority`](https://docs.astro.build/en/reference/configuration-reference/#experimentalglobalroutepriority) option and bumps the minimum required Astro version. + + ⚠️ **BREAKING CHANGE** The minimum supported Astro version is now 4.2.7. Upgrade Astro and Starlight together: + + ```sh + npx @astrojs/upgrade + ``` + +## 0.17.4 + +### Patch Changes + +- [#1473](https://github.com/withastro/starlight/pull/1473) [`29da505`](https://github.com/withastro/starlight/commit/29da505474174fefaec4e27a2c2c3e90e3f68a31) Thanks [@delucis](https://github.com/delucis)! - Fixes a CSS bug for users with JavaScript disabled + +- [#1465](https://github.com/withastro/starlight/pull/1465) [`ce3108c`](https://github.com/withastro/starlight/commit/ce3108cf6ecb77d12db973485d21e0fc7fd63ca6) Thanks [@delucis](https://github.com/delucis)! - Updates internal MDX, sitemap, and Expressive Code dependencies to the latest versions + +## 0.17.3 + +### Patch Changes + +- [#1461](https://github.com/withastro/starlight/pull/1461) [`2e17880`](https://github.com/withastro/starlight/commit/2e17880957d1aae2a84c77500afa9b66e5292a6a) Thanks [@liruifengv](https://github.com/liruifengv)! - Improves the table of contents title translation in Simplified Chinese + +- [#1462](https://github.com/withastro/starlight/pull/1462) [`4741ccc`](https://github.com/withastro/starlight/commit/4741cccc8adbef500bcaf95416a1c61a90761c06) Thanks [@delucis](https://github.com/delucis)! - Fixes overflow of very long site titles on narrow viewports + +- [#1459](https://github.com/withastro/starlight/pull/1459) [`9a8e0ec`](https://github.com/withastro/starlight/commit/9a8e0ec59cba0e088512ea9b6d17224085f3a178) Thanks [@delucis](https://github.com/delucis)! - Fixes a bug where table of contents highlighting could break given very specific combinations of content and viewport size + +- [#1458](https://github.com/withastro/starlight/pull/1458) [`8c88642`](https://github.com/withastro/starlight/commit/8c88642875e8344396074a780e28fb0860b249f8) Thanks [@delucis](https://github.com/delucis)! - Silences i18n content collection warnings for projects without custom translations. + +## 0.17.2 + +### Patch Changes + +- [#1442](https://github.com/withastro/starlight/pull/1442) [`1a642e4`](https://github.com/withastro/starlight/commit/1a642e4d74ee4c30e85bce37b41888b1eae0544a) Thanks [@delucis](https://github.com/delucis)! - Fixes URLs in language picker for sites with `build.format: 'file'` + +- [#1440](https://github.com/withastro/starlight/pull/1440) [`2ea1e88`](https://github.com/withastro/starlight/commit/2ea1e883186660b48f0ea8c4da7fead5fb74e313) Thanks [@hippotastic](https://github.com/hippotastic)! - Adds JS support to the `@astrojs/starlight/expressive-code` export to allow importing from non-TS environments. + +## 0.17.1 + +### Patch Changes + +- [#1437](https://github.com/withastro/starlight/pull/1437) [`655aed4`](https://github.com/withastro/starlight/commit/655aed4840cae59e9abd64b4b585e60f1cfab209) Thanks [@hippotastic](https://github.com/hippotastic)! - Adds Starlight-specific types to `defineEcConfig` function and exports `StarlightExpressiveCodeOptions`. + + This provides Starlight types and IntelliSense support for your Expressive Code configuration options inside an `ec.config.mjs` file. See the [Expressive Code documentation](https://expressive-code.com/key-features/code-component/#using-an-ecconfigmjs-file) for more information. + +- [#1420](https://github.com/withastro/starlight/pull/1420) [`275f87f`](https://github.com/withastro/starlight/commit/275f87fd7fc676b9ab323354078c06894e0832c7) Thanks [@abdelhalimjean](https://github.com/abdelhalimjean)! - Fix rare `font-family` issue if users have a font installed with a name of `""` + +- [#1365](https://github.com/withastro/starlight/pull/1365) [`a0af7cc`](https://github.com/withastro/starlight/commit/a0af7cc696da987a76edab96cdd2329779e87724) Thanks [@kevinzunigacuellar](https://github.com/kevinzunigacuellar)! - Correctly format Pagefind search result links when `trailingSlash: 'never'` is used + +## 0.17.0 + +### Minor Changes + +- [#1389](https://github.com/withastro/starlight/pull/1389) [`21b3620`](https://github.com/withastro/starlight/commit/21b36201aa1e01c8395d0f24b2fa4e32b90550bb) Thanks [@connor-baer](https://github.com/connor-baer)! - Adds new `disable404Route` config option to disable injection of Astro’s default 404 route + +- [#1395](https://github.com/withastro/starlight/pull/1395) [`ce05dfb`](https://github.com/withastro/starlight/commit/ce05dfb4b1e9b90fad057d5d4328e4445f986b3b) Thanks [@hippotastic](https://github.com/hippotastic)! - Adds a new [`<Code>` component](https://starlight.astro.build/guides/components/#code) to render dynamic code strings with Expressive Code + +## 0.16.0 + +### Minor Changes + +- [#1383](https://github.com/withastro/starlight/pull/1383) [`490c6ef`](https://github.com/withastro/starlight/commit/490c6eff34ab408c4f55777b7b0caa16787dd3d4) Thanks [@delucis](https://github.com/delucis)! - Refactors Starlight’s internal virtual module system for components to avoid circular references + + This is a change to an internal API. + If you were importing the internal `virtual:starlight/components` module, this no longer exists. + Update your imports to use the individual virtual modules now available for each component, for example `virtual:starlight/components/EditLink`. + +- [#1151](https://github.com/withastro/starlight/pull/1151) [`134292d`](https://github.com/withastro/starlight/commit/134292ddd89683007d7de25545d39738a82c626c) Thanks [@kevinzunigacuellar](https://github.com/kevinzunigacuellar)! - Fixes sidebar auto-generation issue when a file and a directory, located at the same level, have identical names. + + For example, `src/content/docs/guides.md` and `src/content/docs/guides/example.md` will now both be included and `src/content/docs/guides.md` is treated in the same way a `src/content/docs/guides/index.md` file would be. + +- [#1386](https://github.com/withastro/starlight/pull/1386) [`0163634`](https://github.com/withastro/starlight/commit/0163634abb8578ce7a3d7ceea36432e98ea70e78) Thanks [@delucis](https://github.com/delucis)! - Tightens `line-height` on `<LinkCard>` titles to fix regression from original design + + If you want to preserve the previous `line-height`, you can add the following custom CSS to your site: + + ```css + .sl-link-card a { + line-height: 1.6; + } + ``` + +- [#1376](https://github.com/withastro/starlight/pull/1376) [`8398432`](https://github.com/withastro/starlight/commit/8398432aa4a0f38e2dd4452dfcdf7033c5713334) Thanks [@delucis](https://github.com/delucis)! - Tweaks vertical spacing in Markdown content styles. + + This is a subtle change to Starlight’s default content styling that should improve most sites: + + - Default vertical spacing between content items is reduced from `1.5rem` to `1rem`. + - Spacing before headings is now relative to font size, meaning higher-level headings have slightly more spacing and lower-level headings slightly less. + + The overall impact is to tighten up content that belongs together and improve the visual hierarchy of headings to break up sections. + + Although this is a subtle change, we recommend visually inspecting your site in case this impacts layout of any custom CSS or components. + + If you want to preserve the previous spacing, you can add the following custom CSS to your site: + + ```css + /* Restore vertical spacing to match Starlight v0.15 and below. */ + .sl-markdown-content + :not(a, strong, em, del, span, input, code) + + :not(a, strong, em, del, span, input, code, :where(.not-content *)) { + margin-top: 1.5rem; + } + .sl-markdown-content + :not(h1, h2, h3, h4, h5, h6) + + :is(h1, h2, h3, h4, h5, h6):not(:where(.not-content *)) { + margin-top: 2.5rem; + } + ``` + +- [#1372](https://github.com/withastro/starlight/pull/1372) [`773880d`](https://github.com/withastro/starlight/commit/773880de87b79bf3107dbc32df29a86dd11e4e6f) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Updates the table of contents highlighting styles to prevent UI shifts when scrolling through a page. + + If you want to preserve the previous, buggy styling, you can add the following custom CSS to your site: + + ```css + starlight-toc a[aria-current='true'], + starlight-toc a[aria-current='true']:hover, + starlight-toc a[aria-current='true']:focus { + font-weight: 600; + color: var(--sl-color-text-invert); + background-color: var(--sl-color-text-accent); + } + ``` + +## 0.15.4 + +### Patch Changes + +- [#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` + +## 0.15.3 + +### Patch Changes + +- [#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 + +- [#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 + +- [#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 + +- [#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`. + +- [#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 + +## 0.15.2 + +### Patch Changes + +- [#1254](https://github.com/withastro/starlight/pull/1254) [`e9659e8`](https://github.com/withastro/starlight/commit/e9659e869cd0c9ad0b7388397b0fff8e2a9db27a) Thanks [@Pukimaa](https://github.com/Pukimaa)! - Adds Open Collective social link icon + +- [#1295](https://github.com/withastro/starlight/pull/1295) [`c3732a9`](https://github.com/withastro/starlight/commit/c3732a9bb5cb7907f00a3ed5e65534f48a5ff6b9) Thanks [@juchym](https://github.com/juchym)! - Improve Ukrainian UI translations + +## 0.15.1 + +### Patch Changes + +- [#1273](https://github.com/withastro/starlight/pull/1273) [`ae53155`](https://github.com/withastro/starlight/commit/ae531557aa4d42bd27c15f8f08bb3ca8242c9beb) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Updates `<SocialIcon />` styling for improved accessibility. Specifically, the component now meets the [Target Size (Minimum)](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html) success criteria defined by [Web Content Accessibility Guidelines (WCAG) 2.2](https://www.w3.org/TR/WCAG22/). + +- [#1289](https://github.com/withastro/starlight/pull/1289) [`9bd343f`](https://github.com/withastro/starlight/commit/9bd343fb1efab90a0aa03a95b1928a53c1674000) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds French translations for Expressive Code UI + +- [#1280](https://github.com/withastro/starlight/pull/1280) [`6b1693d`](https://github.com/withastro/starlight/commit/6b1693d55552a48316a31d986e1cbaf695f10a61) Thanks [@kevinzunigacuellar](https://github.com/kevinzunigacuellar)! - Adds Spanish translations for Expressive Code UI + +- [#1276](https://github.com/withastro/starlight/pull/1276) [`667f23d`](https://github.com/withastro/starlight/commit/667f23d615742b44bb18ace39d981f8797b8ac55) Thanks [@hippotastic](https://github.com/hippotastic)! - Updates `astro-expressive-code` dependency to the latest version + +- [#1266](https://github.com/withastro/starlight/pull/1266) [`c9edf30`](https://github.com/withastro/starlight/commit/c9edf30b16f66757797dcaa5161b4afc18027476) Thanks [@alex-way](https://github.com/alex-way)! - Removes redundant subprocess calls in git last-updated time utility to improve performance + +- [#1278](https://github.com/withastro/starlight/pull/1278) [`e88abb0`](https://github.com/withastro/starlight/commit/e88abb0cc8b329500c15bc77aaed3907ec7dc507) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Exports the `StarlightUserConfig` TypeScript type representing the user's Starlight configuration received by plugins. + +## 0.15.0 + +### Minor Changes + +- [#1238](https://github.com/withastro/starlight/pull/1238) [`02a808e`](https://github.com/withastro/starlight/commit/02a808e4a0b9ac2383576e3495f6a766b663d773) Thanks [@delucis](https://github.com/delucis)! - Add support for Astro v4, drop support for Astro v3 + + ⚠️ **BREAKING CHANGE** Astro v3 is no longer supported. Make sure you [update Astro](https://docs.astro.build/en/guides/upgrade-to/v4/) and any other integrations at the same time as updating Starlight. + + Use the new `@astrojs/upgrade` command to upgrade Astro and Starlight together: + + ```sh + npx @astrojs/upgrade + ``` + +- [#1242](https://github.com/withastro/starlight/pull/1242) [`d8fc9e1`](https://github.com/withastro/starlight/commit/d8fc9e15bd2ae4c945b5a3856a6ce3b5629e8b29) Thanks [@delucis](https://github.com/delucis)! - Enables link prefetching on hover by default + + Astro v4’s [prefetch](https://docs.astro.build/en/guides/prefetch) support is now enabled by default. If `prefetch` is not set in `astro.config.mjs`, Starlight will use `prefetch: { prefetchAll: true, defaultStrategy: 'hover' }` by default. + + If you want to preserve previous behaviour, disable link prefetching in `astro.config.mjs`: + + ```js + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + // Disable link prefetching: + prefetch: false, + + integrations: [ + starlight({ + // ... + }), + ], + }); + ``` + +### Patch Changes + +- [#1226](https://github.com/withastro/starlight/pull/1226) [`909afa2`](https://github.com/withastro/starlight/commit/909afa2d468099e237bfbd25eda56270b7b00082) Thanks [@tlandmangh](https://github.com/tlandmangh)! - Add Dutch translations of default aside labels + +- [#1243](https://github.com/withastro/starlight/pull/1243) [`ee234eb`](https://github.com/withastro/starlight/commit/ee234ebddcba8d07e2c879f33e38631c8955ffcf) Thanks [@khajimatov](https://github.com/khajimatov)! - Fix typo in Russian untranslated content notice + +- [#1170](https://github.com/withastro/starlight/pull/1170) [`bcc2301`](https://github.com/withastro/starlight/commit/bcc2301c06796edec3923c666078e82eaf5a1990) Thanks [@tmcw](https://github.com/tmcw)! - Fix timezone-reliance in LastUpdated + +- [#1203](https://github.com/withastro/starlight/pull/1203) [`4601449`](https://github.com/withastro/starlight/commit/4601449894bbbd619e4149788113090b67697fe1) Thanks [@orhun](https://github.com/orhun)! - Adds Matrix social link icon + +## 0.14.0 + +### Minor Changes + +- [#1144](https://github.com/withastro/starlight/pull/1144) [`7c0b8cb`](https://github.com/withastro/starlight/commit/7c0b8cb334c501678f7ab87cce372cddfdde34ed) Thanks [@delucis](https://github.com/delucis)! - Adds a configuration option to disable site indexing with Pagefind and the default search UI + +- [#942](https://github.com/withastro/starlight/pull/942) [`efd7fdc`](https://github.com/withastro/starlight/commit/efd7fdcb55b39988f157c1a4b2c368c86a39520f) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds plugin API + + See the [plugins reference](https://starlight.astro.build/reference/plugins/) to learn more about creating plugins for Starlight using this new API. + +- [#1135](https://github.com/withastro/starlight/pull/1135) [`e5a863a`](https://github.com/withastro/starlight/commit/e5a863a98b2e5335e122ca440dcb84e9426939b4) Thanks [@delucis](https://github.com/delucis)! - Exposes localized UI strings in route data + + Component overrides can now access a `labels` object in their props which includes all the localized UI strings for the current page. + +- [#1162](https://github.com/withastro/starlight/pull/1162) [`00d101b`](https://github.com/withastro/starlight/commit/00d101b159bfa4bb307a66ccae53dd417d9564e0) Thanks [@delucis](https://github.com/delucis)! - Adds support for extending Starlight’s content collection schemas + +## 0.13.1 + +### Patch Changes + +- [#1111](https://github.com/withastro/starlight/pull/1111) [`cb19d07`](https://github.com/withastro/starlight/commit/cb19d07d6192ffb732ac6fcf9df04d4f098bfc1f) Thanks [@at-the-vr](https://github.com/at-the-vr)! - Fix minor punctuation typo in Hindi UI string + +- [#1156](https://github.com/withastro/starlight/pull/1156) [`631c5ae`](https://github.com/withastro/starlight/commit/631c5aeccba60254ff649712f93ba30495775edf) Thanks [@votemike](https://github.com/votemike)! - Updates `@astrojs/sitemap` dependency to the latest version + +- [#1109](https://github.com/withastro/starlight/pull/1109) [`0c25c1f`](https://github.com/withastro/starlight/commit/0c25c1f33bbfe311724784530c30ada44eb5de19) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Internal: fix import issue with expressive-code + +## 0.13.0 + +### Minor Changes + +- [#1023](https://github.com/withastro/starlight/pull/1023) [`a3b80f7`](https://github.com/withastro/starlight/commit/a3b80f71037504f2b8d7f1a641924215091122bb) Thanks [@kevinzunigacuellar](https://github.com/kevinzunigacuellar)! - Respect the `trailingSlash` and `build.format` Astro options when creating Starlight navigation links. + + ⚠️ **Potentially breaking change:** + This change will cause small changes in link formatting for most sites. + These are unlikely to break anything, but if you care about link formatting, you may want to change some Astro settings. + + If you want to preserve Starlight’s previous behavior, set `trailingSlash: 'always'` in your `astro.config.mjs`: + + ```js + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + + export default defineConfig({ + trailingSlash: 'always', + integrations: [ + starlight({ + // ... + }), + ], + }); + ``` + +- [#742](https://github.com/withastro/starlight/pull/742) [`c6a4bcb`](https://github.com/withastro/starlight/commit/c6a4bcb7982c54c513f20c96a9b2aaf9ac09094b) Thanks [@hippotastic](https://github.com/hippotastic)! - Adds Expressive Code as Starlight’s default code block renderer + + ⚠️ **Potentially breaking change:** + This addition changes how Markdown code blocks are rendered. By default, Starlight will now use [Expressive Code](https://github.com/expressive-code/expressive-code/tree/main/packages/astro-expressive-code). + If you were already customizing how code blocks are rendered and don't want to use the [features provided by Expressive Code](https://starlight.astro.build/guides/authoring-content/#expressive-code-features), you can preserve the previous behavior by setting the new config option `expressiveCode` to `false`. + + If you had previously added Expressive Code manually to your Starlight project, you can now remove the manual set-up in `astro.config.mjs`: + + - Move your configuration to Starlight’s new `expressiveCode` option. + - Remove the `astro-expressive-code` integration. + + For example: + + ```diff + import starlight from '@astrojs/starlight'; + import { defineConfig } from 'astro/config'; + - import expressiveCode from 'astro-expressive-code'; + + export default defineConfig({ + integrations: [ + - expressiveCode({ + - themes: ['rose-pine'], + - }), + starlight({ + title: 'My docs', + + expressiveCode: { + + themes: ['rose-pine'], + + }, + }), + ], + }); + ``` + + Note that the built-in Starlight version of Expressive Code sets some opinionated defaults that are different from the `astro-expressive-code` defaults. You may need to set some `styleOverrides` if you wish to keep styles exactly the same. + +- [#517](https://github.com/withastro/starlight/pull/517) [`5b549cb`](https://github.com/withastro/starlight/commit/5b549cb634f51d28bf9a7f92ad0d82c1671e788a) Thanks [@liruifengv](https://github.com/liruifengv)! - Add i18n support for default aside labels + +### Patch Changes + +- [#1088](https://github.com/withastro/starlight/pull/1088) [`4fe5537`](https://github.com/withastro/starlight/commit/4fe553749a6708fdb119b12a2dbc6b10a980bde1) Thanks [@Lootjs](https://github.com/Lootjs)! - i18n(ru): added Russian aside labels translation + +- [#1083](https://github.com/withastro/starlight/pull/1083) [`e03a653`](https://github.com/withastro/starlight/commit/e03a65313365b7dbe6095727b28b4e639c446f68) Thanks [@at-the-vr](https://github.com/at-the-vr)! - i18n(hi): Add Hindi language support + +- [#1075](https://github.com/withastro/starlight/pull/1075) [`2f2adf2`](https://github.com/withastro/starlight/commit/2f2adf29f2a13d5ff0f1577207210745a5ae7405) Thanks [@russbiggs](https://github.com/russbiggs)! - Add Slack social link icon + +- [#1065](https://github.com/withastro/starlight/pull/1065) [`2d72ed6`](https://github.com/withastro/starlight/commit/2d72ed67c666b26eae44649e70aecef3db815d19) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Ignore search keyboard shortcuts for elements with contents that are editable + +- [#1081](https://github.com/withastro/starlight/pull/1081) [`f27f781`](https://github.com/withastro/starlight/commit/f27f781556d37e73d0b1d902de745b67f8e4f24d) Thanks [@farisphp](https://github.com/farisphp)! - i18n(id): Add Indonesian aside labels translation + +- [#1082](https://github.com/withastro/starlight/pull/1082) [`ce27486`](https://github.com/withastro/starlight/commit/ce27486fabd3884ed4bca9372ebd72a0597ab765) Thanks [@bogdaaamn](https://github.com/bogdaaamn)! - i18n(ro): Add Romanian UI translations + +## 0.12.1 + +### Patch Changes + +- [#1069](https://github.com/withastro/starlight/pull/1069) [`b86f360`](https://github.com/withastro/starlight/commit/b86f3608f03be9455ec1d5ba11820c9bf601ad1e) Thanks [@Genteure](https://github.com/Genteure)! - Fix sidebar highlighting and navigation buttons for pages with path containing non-ASCII characters + +- [#1025](https://github.com/withastro/starlight/pull/1025) [`0d1e75e`](https://github.com/withastro/starlight/commit/0d1e75e17269ddac3eb15b7dfb4480da1bb01c6c) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Internal: fix import issue in translation string loading mechanism + +- [#1044](https://github.com/withastro/starlight/pull/1044) [`a5a9754`](https://github.com/withastro/starlight/commit/a5a9754f111b97abfd277d99759e9857aa0fb22b) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fix last updated dates for pages displaying fallback content + +- [#1049](https://github.com/withastro/starlight/pull/1049) [`c27495d`](https://github.com/withastro/starlight/commit/c27495da61f9376236519ed3f08a169f245a189c) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Expose Markdown content styles in `@astrojs/starlight/style/markdown.css` + +## 0.12.0 + +### Minor Changes + +- [#995](https://github.com/withastro/starlight/pull/995) [`5bf4457`](https://github.com/withastro/starlight/commit/5bf44577634935b9fa6d50b040abcd680035075f) Thanks [@kevinzunigacuellar](https://github.com/kevinzunigacuellar)! - Adds support for adding sidebar badges to group headings + +- [#988](https://github.com/withastro/starlight/pull/988) [`977fe13`](https://github.com/withastro/starlight/commit/977fe135a74661300589898abe98aec73cad9ed3) Thanks [@magicDGS](https://github.com/magicDGS)! - Include social icon links in mobile menu + +- [#280](https://github.com/withastro/starlight/pull/280) [`72cca2d`](https://github.com/withastro/starlight/commit/72cca2d07644f00595da6ebf7d603adb282f359d) Thanks [@cbontems](https://github.com/cbontems)! - Support light & dark variants of the hero image. + + ⚠️ **Potentially breaking change:** The `hero.image` schema is now slightly stricter than previously. + + The `hero.image.html` property can no longer be used alongside the `hero.image.alt` or `hero.image.file` properties. + Previously, `html` was ignored when used with `file` and `alt` was ignored when used with `html`. + Now, those combinations will throw errors. + If you encounter errors, remove the `image.hero` property that is not in use. + +### Patch Changes + +- [#1004](https://github.com/withastro/starlight/pull/1004) [`7f92213`](https://github.com/withastro/starlight/commit/7f92213a0b93de5a844816841a6bc9cdd371de0c) Thanks [@nunhes](https://github.com/nunhes)! - Add Galician language support + +- [#1003](https://github.com/withastro/starlight/pull/1003) [`f1fdb50`](https://github.com/withastro/starlight/commit/f1fdb50daebe79548c7789d3f7dd968b261d2da7) Thanks [@delucis](https://github.com/delucis)! - Internal: refactor translation string loading to make translations available to Starlight integration code + +## 0.11.2 + +### Patch Changes + +- [#944](https://github.com/withastro/starlight/pull/944) [`7a6446e`](https://github.com/withastro/starlight/commit/7a6446ebc61ba9cc36d1dcfd13db15c1533751ab) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fix issue with sidebar autogenerated groups configured with a directory containing leading or trailing slash + +- [#985](https://github.com/withastro/starlight/pull/985) [`92b3b57`](https://github.com/withastro/starlight/commit/92b3b575404d0dc34f720c0ba29d8ed50be98f58) Thanks [@delucis](https://github.com/delucis)! - Fix edit URLs for pages displaying fallback content + +- [#986](https://github.com/withastro/starlight/pull/986) [`0470734`](https://github.com/withastro/starlight/commit/0470734e0dc323f9945e06bee4338c2f777ba0d6) Thanks [@dreyfus92](https://github.com/dreyfus92)! - Prevent overscrolling on mobile table of contents by setting 'overscroll-behavior: contain'. + +- [#924](https://github.com/withastro/starlight/pull/924) [`39d6302`](https://github.com/withastro/starlight/commit/39d6302db42ee1105d690bbd3a66053e6b21e15a) Thanks [@kevinzunigacuellar](https://github.com/kevinzunigacuellar)! - Remove extra margin from markdown lists that uses inline code + +- [#814](https://github.com/withastro/starlight/pull/814) [`1e517d9`](https://github.com/withastro/starlight/commit/1e517d92a4cf146d2dcae58f7c4299d6f25ea73e) Thanks [@julien-deramond](https://github.com/julien-deramond)! - Prevent text from overflowing pagination items + +## 0.11.1 + +### Patch Changes + +- [#892](https://github.com/withastro/starlight/pull/892) [`2b30321`](https://github.com/withastro/starlight/commit/2b30321bde801bb9945d73dc954e25b40f4324fa) Thanks [@delucis](https://github.com/delucis)! - Add Patreon social link icon + +- [#854](https://github.com/withastro/starlight/pull/854) [`71a52a1`](https://github.com/withastro/starlight/commit/71a52a16c44e3568128c83070541235133c44436) Thanks [@mehalter](https://github.com/mehalter)! - Add Reddit icon + +- [#852](https://github.com/withastro/starlight/pull/852) [`344c92e`](https://github.com/withastro/starlight/commit/344c92e1b8bca5f92ec087df6cccf5c611eefdff) Thanks [@Lootjs](https://github.com/Lootjs)! - Improve Russian language support + +- [#891](https://github.com/withastro/starlight/pull/891) [`395920c`](https://github.com/withastro/starlight/commit/395920c46e7b24cfff31800b3426ab375078e5c1) Thanks [@Frikadellios](https://github.com/Frikadellios)! - Add Ukrainian language support + +- [#890](https://github.com/withastro/starlight/pull/890) [`63ea8e8`](https://github.com/withastro/starlight/commit/63ea8e86643b050c6be6f9a6167f6642b039c709) Thanks [@delucis](https://github.com/delucis)! - Update `execa` dependency to v8 + +- [#859](https://github.com/withastro/starlight/pull/859) [`eaa7a90`](https://github.com/withastro/starlight/commit/eaa7a902c7b7638b326709fd5203d932b20ed3fa) Thanks [@oggnimodd](https://github.com/oggnimodd)! - Improve Indonesian language support + +- [#864](https://github.com/withastro/starlight/pull/864) [`b84aff2`](https://github.com/withastro/starlight/commit/b84aff2b9cccbc35c8619763c7f36841abe6344b) Thanks [@mehalter](https://github.com/mehalter)! - Optimize UI icon SVG paths + +## 0.11.0 + +### Minor Changes + +- [#774](https://github.com/withastro/starlight/pull/774) [`903a579`](https://github.com/withastro/starlight/commit/903a57942ceb99b68672c3fa54622b39cc5d76f8) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Support adding HTML attributes to sidebar links from config and frontmatter + +- [#796](https://github.com/withastro/starlight/pull/796) [`372ec96`](https://github.com/withastro/starlight/commit/372ec96d31d0c1a9aa8bc1605de2b424bf9bd5af) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Add the `@astrojs/sitemap` and `@astrojs/mdx` integrations only if they are not detected in the Astro configuration. + + ⚠️ **BREAKING CHANGE** The minimum supported version of Astro is now v3.2.0. Make sure you update Astro at the same time as updating Starlight: + + ```sh + npm install astro@latest + ``` + +- [#447](https://github.com/withastro/starlight/pull/447) [`b45719b`](https://github.com/withastro/starlight/commit/b45719b581353f8d8f0ce0a9b5c89132e902377b) Thanks [@andremralves](https://github.com/andremralves)! - Add `titleDelimiter` configuration option and include site title in page `<title>` tags + + ⚠️ **BREAKING CHANGE** — Previously, every page’s `<title>` only included its individual frontmatter title. + Now, `<title>` tags include the page title, a delimiter character (`|` by default), and the site title. + For example, in the Startlight docs, `<title>Configuration Reference` is now `Configuration Reference | Starlight`. + + If you have a page where you need to override this new behaviour, set a custom title using the `head` frontmatter property: + + ```md + --- + title: My Page + head: + - tag: title + content: Custom Title + --- + ``` + +- [#709](https://github.com/withastro/starlight/pull/709) [`140e729`](https://github.com/withastro/starlight/commit/140e729a8bf12f805ae0b7e2b5ad959cf68d8e22) Thanks [@delucis](https://github.com/delucis)! - Add support for overriding Starlight’s built-in components + + ⚠️ **BREAKING CHANGE** — The page footer is now included on pages with `template: splash` in their frontmatter. Previously, this was not the case. If you are using `template: splash` and want to continue to hide footer elements, disable them in your frontmatter: + + ```md + --- + title: Landing page + template: splash + # Disable unwanted footer elements as needed + editUrl: false + lastUpdated: false + prev: false + next: false + --- + ``` + + ⚠️ **BREAKING CHANGE** — This change involved refactoring the structure of some of Starlight’s built-in components slightly. If you were previously overriding these using other techniques, you may need to adjust your code. + +### Patch Changes + +- [#815](https://github.com/withastro/starlight/pull/815) [`b7b23a2`](https://github.com/withastro/starlight/commit/b7b23a2c90a25fe8ea08338379b83d19c74d9037) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Add Facebook and email icons + +- [#810](https://github.com/withastro/starlight/pull/810) [`dbe977b`](https://github.com/withastro/starlight/commit/dbe977b6ce3efcffefab850eca08bef316b41e53) Thanks [@hasham-qaiser](https://github.com/hasham-qaiser)! - Use `` instead of `

` in sidebar group headings + +- [#807](https://github.com/withastro/starlight/pull/807) [`7c73dd1`](https://github.com/withastro/starlight/commit/7c73dd146ee294f9092346a0b0041990cc648a13) Thanks [@torn4dom4n](https://github.com/torn4dom4n)! - Add Vietnamese translations for Starlight UI + +- [#756](https://github.com/withastro/starlight/pull/756) [`f55a8f0`](https://github.com/withastro/starlight/commit/f55a8f014a7addc46e971dd6b7148f4545acd16c) Thanks [@julien-deramond](https://github.com/julien-deramond)! - Prevent text from overflowing in several cases + +## 0.10.4 + +### Patch Changes + +- [#752](https://github.com/withastro/starlight/pull/752) [`6833ee1`](https://github.com/withastro/starlight/commit/6833ee12159ea5be23885c41da80569a89aafa33) Thanks [@apinet](https://github.com/apinet)! - Add X social link logo + +- [#789](https://github.com/withastro/starlight/pull/789) [`2528fb0`](https://github.com/withastro/starlight/commit/2528fb011a388f3920af9994012bd7db2b1654c3) Thanks [@delucis](https://github.com/delucis)! - Update bundled version of `@astrojs/mdx` to v1.1.0 + +- [#794](https://github.com/withastro/starlight/pull/794) [`a0de12d`](https://github.com/withastro/starlight/commit/a0de12d596ab2b1c0d79d6d63d2d6cb9fe6d2644) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Add Telegram icon + +- [#792](https://github.com/withastro/starlight/pull/792) [`a8358df`](https://github.com/withastro/starlight/commit/a8358df7849b342de342a4a2e88e019c39d5bbe8) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Add RSS icon + +- [#778](https://github.com/withastro/starlight/pull/778) [`957d2c3`](https://github.com/withastro/starlight/commit/957d2c32123ab0c223fcef03f91ce3ad7be7aa21) Thanks [@jermanuts](https://github.com/jermanuts)! - Improve Arabic UI translations + ## 0.10.3 ### Patch Changes diff --git a/packages/starlight/__e2e__/.gitignore b/packages/starlight/__e2e__/.gitignore new file mode 100644 index 00000000000..eed07661e3e --- /dev/null +++ b/packages/starlight/__e2e__/.gitignore @@ -0,0 +1,4 @@ +# generated types +.astro/ +dist/ +build/ diff --git a/packages/starlight/__e2e__/basics.test.ts b/packages/starlight/__e2e__/basics.test.ts new file mode 100644 index 00000000000..6cd0a5cd510 --- /dev/null +++ b/packages/starlight/__e2e__/basics.test.ts @@ -0,0 +1,859 @@ +import type { Page } from '@playwright/test'; +import fs from 'node:fs/promises'; +import { expect, testFactory, type Locator, type StarlightPage } from './test-utils'; + +const test = testFactory('./fixtures/basics/'); + +test.describe('components', () => { + test.describe('tabs', () => { + test('syncs tabs with a click event', async ({ page, getProdServer }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabsA = tabs.nth(0); + const pkgTabsB = tabs.nth(2); + + // Select the pnpm tab in the first set of synced tabs. + await pkgTabsA.getByRole('tab').filter({ hasText: 'pnpm' }).click(); + + await expectSelectedTab(pkgTabsA, 'pnpm', 'pnpm command'); + await expectSelectedTab(pkgTabsB, 'pnpm', 'another pnpm command'); + + // Select the yarn tab in the second set of synced tabs. + await pkgTabsB.getByRole('tab').filter({ hasText: 'yarn' }).click(); + + await expectSelectedTab(pkgTabsB, 'yarn', 'another yarn command'); + await expectSelectedTab(pkgTabsA, 'yarn', 'yarn command'); + }); + + test('syncs tabs with a keyboard event', async ({ page, getProdServer }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabsA = tabs.nth(0); + const pkgTabsB = tabs.nth(2); + + // Select the pnpm tab in the first set of synced tabs with the keyboard. + await pkgTabsA.getByRole('tab', { selected: true }).press('ArrowRight'); + + await expectSelectedTab(pkgTabsA, 'pnpm', 'pnpm command'); + await expectSelectedTab(pkgTabsB, 'pnpm', 'another pnpm command'); + + // Select back the npm tab in the second set of synced tabs with the keyboard. + const selectedTabB = pkgTabsB.getByRole('tab', { selected: true }); + await selectedTabB.press('ArrowRight'); + await selectedTabB.press('ArrowLeft'); + await selectedTabB.press('ArrowLeft'); + + await expectSelectedTab(pkgTabsA, 'npm', 'npm command'); + await expectSelectedTab(pkgTabsB, 'npm', 'another npm command'); + }); + + test('syncs only tabs using the same sync key', async ({ page, getProdServer }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabsA = tabs.nth(0); + const unsyncedTabs = tabs.nth(1); + const styleTabs = tabs.nth(3); + const osTabsA = tabs.nth(5); + const osTabsB = tabs.nth(6); + + // Select the pnpm tab in the set of tabs synced with the 'pkg' key. + await pkgTabsA.getByRole('tab').filter({ hasText: 'pnpm' }).click(); + + await expectSelectedTab(unsyncedTabs, 'one', 'tab 1'); + await expectSelectedTab(styleTabs, 'css', 'css code'); + await expectSelectedTab(osTabsA, 'macos', 'macOS'); + await expectSelectedTab(osTabsB, 'macos', 'ls'); + }); + + test('supports synced tabs with different tab items', async ({ page, getProdServer }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabsA = tabs.nth(0); + const pkgTabsB = tabs.nth(2); // This set contains an extra tab item. + + // Select the bun tab in the second set of synced tabs. + await pkgTabsB.getByRole('tab').filter({ hasText: 'bun' }).click(); + + await expectSelectedTab(pkgTabsA, 'npm', 'npm command'); + await expectSelectedTab(pkgTabsB, 'bun', 'another bun command'); + }); + + test('persists the focus when syncing tabs', async ({ page, getProdServer }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs'); + + const pkgTabsA = page.locator('starlight-tabs').nth(0); + + // Focus the selected tab in the set of tabs synced with the 'pkg' key. + await pkgTabsA.getByRole('tab', { selected: true }).focus(); + // Select the pnpm tab in the set of tabs synced with the 'pkg' key using the keyboard. + await page.keyboard.press('ArrowRight'); + + expect( + await pkgTabsA + .getByRole('tab', { selected: true }) + .evaluate((node) => document.activeElement === node) + ).toBe(true); + }); + + test('preserves tabs position when alternating between tabs with different content heights', async ({ + page, + getProdServer, + }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs-variable-height'); + + const tabs = page.locator('starlight-tabs').nth(1); + const selectedTab = tabs.getByRole('tab', { selected: true }); + + // Scroll to the second set of synced tabs and focus the selected tab. + await tabs.scrollIntoViewIfNeeded(); + await selectedTab.focus(); + + // Get the bounding box of the tabs. + const initialBoundingBox = await tabs.boundingBox(); + + // Select the second tab which has a different height. + await selectedTab.press('ArrowRight'); + + // Ensure the tabs vertical position is exactly the same after selecting the second tab. + // Note that a small difference could be the result of the base line-height having a fractional part which can cause a + // sub-pixel difference in some browsers like Chrome or Firefox. + expect((await tabs.boundingBox())?.y).toBe(initialBoundingBox?.y); + }); + + test('syncs tabs with the same sync key if they do not consistently use icons', async ({ + page, + getProdServer, + }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabsA = tabs.nth(0); // This set does not use icons for tab items. + const pkgTabsB = tabs.nth(4); // This set uses icons for tab items. + + // Select the pnpm tab in the first set of synced tabs. + await pkgTabsA.getByRole('tab').filter({ hasText: 'pnpm' }).click(); + + await expectSelectedTab(pkgTabsA, 'pnpm', 'pnpm command'); + await expectSelectedTab(pkgTabsB, 'pnpm', 'another pnpm command'); + + // Select the yarn tab in the second set of synced tabs. + await pkgTabsB.getByRole('tab').filter({ hasText: 'yarn' }).click(); + + await expectSelectedTab(pkgTabsB, 'yarn', 'another yarn command'); + await expectSelectedTab(pkgTabsA, 'yarn', 'yarn command'); + }); + + test('restores tabs only for synced tabs with a persisted state', async ({ + page, + getProdServer, + }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabsA = tabs.nth(0); + const pkgTabsB = tabs.nth(2); + const pkgTabsC = tabs.nth(4); + const unsyncedTabs = tabs.nth(1); + const styleTabs = tabs.nth(3); + const osTabsA = tabs.nth(5); + const osTabsB = tabs.nth(6); + + // Select the pnpm tab in the set of tabs synced with the 'pkg' key. + await pkgTabsA.getByRole('tab').filter({ hasText: 'pnpm' }).click(); + + await expectSelectedTab(pkgTabsA, 'pnpm', 'pnpm command'); + await expectSelectedTab(pkgTabsB, 'pnpm', 'another pnpm command'); + await expectSelectedTab(pkgTabsC, 'pnpm', 'another pnpm command'); + + await page.reload(); + + // The synced tabs with a persisted state should be restored. + await expectSelectedTab(pkgTabsA, 'pnpm', 'pnpm command'); + await expectSelectedTab(pkgTabsB, 'pnpm', 'another pnpm command'); + await expectSelectedTab(pkgTabsC, 'pnpm', 'another pnpm command'); + + // Other tabs should not be affected. + await expectSelectedTab(unsyncedTabs, 'one', 'tab 1'); + await expectSelectedTab(styleTabs, 'css', 'css code'); + await expectSelectedTab(osTabsA, 'macos', 'macOS'); + await expectSelectedTab(osTabsB, 'macos', 'ls'); + }); + + test('restores tabs for a single set of synced tabs with a persisted state', async ({ + page, + getProdServer, + }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs'); + + const tabs = page.locator('starlight-tabs'); + const styleTabs = tabs.nth(3); + + // Select the tailwind tab in the set of tabs synced with the 'style' key. + await styleTabs.getByRole('tab').filter({ hasText: 'tailwind' }).click(); + + await expectSelectedTab(styleTabs, 'tailwind', 'tailwind code'); + + await page.reload(); + + // The synced tabs with a persisted state should be restored. + await expectSelectedTab(styleTabs, 'tailwind', 'tailwind code'); + }); + + test('restores tabs for multiple synced tabs with different sync keys', async ({ + page, + getProdServer, + }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabsA = tabs.nth(0); + const pkgTabsB = tabs.nth(2); + const pkgTabsC = tabs.nth(4); + const osTabsA = tabs.nth(5); + const osTabsB = tabs.nth(6); + + // Select the pnpm tab in the set of tabs synced with the 'pkg' key. + await pkgTabsA.getByRole('tab').filter({ hasText: 'pnpm' }).click(); + + await expectSelectedTab(pkgTabsA, 'pnpm', 'pnpm command'); + await expectSelectedTab(pkgTabsB, 'pnpm', 'another pnpm command'); + await expectSelectedTab(pkgTabsC, 'pnpm', 'another pnpm command'); + + // Select the windows tab in the set of tabs synced with the 'os' key. + await osTabsB.getByRole('tab').filter({ hasText: 'windows' }).click(); + + await page.reload(); + + // The synced tabs with a persisted state for the `pkg` sync key should be restored. + await expectSelectedTab(pkgTabsA, 'pnpm', 'pnpm command'); + await expectSelectedTab(pkgTabsB, 'pnpm', 'another pnpm command'); + await expectSelectedTab(pkgTabsC, 'pnpm', 'another pnpm command'); + + // The synced tabs with a persisted state for the `os` sync key should be restored. + await expectSelectedTab(osTabsA, 'windows', 'Windows'); + await expectSelectedTab(osTabsB, 'windows', 'Get-ChildItem'); + }); + + test('includes the `` element only for synced tabs', async ({ + page, + getProdServer, + }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs'); + + // The page includes 7 sets of tabs. + await expect(page.locator('starlight-tabs')).toHaveCount(7); + // Only 6 sets of tabs are synced. + await expect(page.locator('starlight-tabs-restore')).toHaveCount(6); + }); + + test('includes the synced tabs restore script only when needed and at most once', async ({ + page, + getProdServer, + }) => { + const starlight = await getProdServer(); + const syncedTabsRestoreScriptRegex = /customElements\.define\('starlight-tabs-restore',/g; + + await starlight.goto('/tabs'); + + // The page includes at least one set of synced tabs. + expect((await page.content()).match(syncedTabsRestoreScriptRegex)?.length).toBe(1); + + await starlight.goto('/tabs-unsynced'); + + // The page includes no set of synced tabs. + expect((await page.content()).match(syncedTabsRestoreScriptRegex)).toBeNull(); + }); + + test('gracefully handles invalid persisted state for synced tabs', async ({ + page, + getProdServer, + }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabsA = tabs.nth(0); + + // Select the pnpm tab in the set of tabs synced with the 'pkg' key. + await pkgTabsA.getByRole('tab').filter({ hasText: 'pnpm' }).click(); + + await expectSelectedTab(pkgTabsA, 'pnpm', 'pnpm command'); + + // Replace the persisted state with a new invalid value. + await page.evaluate( + (value) => localStorage.setItem('starlight-synced-tabs__pkg', value), + 'invalid-value' + ); + + await page.reload(); + + // The synced tabs should not be restored due to the invalid persisted state. + await expectSelectedTab(pkgTabsA, 'npm', 'npm command'); + + // Select the pnpm tab in the set of tabs synced with the 'pkg' key. + await pkgTabsA.getByRole('tab').filter({ hasText: 'pnpm' }).click(); + + await expectSelectedTab(pkgTabsA, 'pnpm', 'pnpm command'); + + // The synced tabs should be restored with the new valid persisted state. + expect(await page.evaluate(() => localStorage.getItem('starlight-synced-tabs__pkg'))).toBe( + 'pnpm' + ); + }); + + test('syncs and restores nested tabs', async ({ page, getProdServer }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs-nested'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabs = tabs.nth(0); + const osTabsA = tabs.nth(1); + const osTabsB = tabs.nth(2); + + // Select the linux tab in the npm tab. + await osTabsA.getByRole('tab').filter({ hasText: 'linux' }).click(); + + await expectSelectedTab(osTabsA, 'linux', 'npm GNU/Linux'); + + // Select the pnpm tab. + await pkgTabs.getByRole('tab').filter({ hasText: 'pnpm' }).click(); + + await expectSelectedTab(pkgTabs, 'pnpm'); + await expectSelectedTab(osTabsB, 'linux', 'pnpm GNU/Linux'); + + await page.reload(); + + // The synced tabs should be restored. + await expectSelectedTab(pkgTabs, 'pnpm'); + await expectSelectedTab(osTabsB, 'linux', 'pnpm GNU/Linux'); + }); + }); + + test.describe('whitespaces', () => { + /** + * Components including styles include a trailing whitespace which can be problematic when used + * inline, e.g.: + * + * ```mdx + * Badge () + * ``` + * + * The example above would render as: + * + * ``` + * Badge (test ) + * ``` + * + * Having a component being responsible for its own spacing is not ideal and should be avoided + * especially when used inline. + * To work around this issue, such components can be wrapped in a fragment. + * + * @see https://github.com/withastro/compiler/issues/1003 + */ + test('does not include components having trailing whitespaces when used inline', async ({ + page, + getProdServer, + }) => { + const starlight = await getProdServer(); + await starlight.goto('/whitespaces'); + + expect(await page.getByTestId('badge').textContent()).toContain('Badge (Note)'); + expect(await page.getByTestId('icon').textContent()).toContain('Icon ()'); + }); + }); + + test.describe('anchor headings', () => { + test('renders the same content for Markdown headings and Astro component', async ({ + getProdServer, + page, + }) => { + const starlight = await getProdServer(); + + await starlight.goto('/anchor-heading'); + const markdownContent = page.locator('.sl-markdown-content'); + const markdownHtml = await markdownContent.innerHTML(); + + await starlight.goto('/anchor-heading-component'); + const componentContent = page.locator('.sl-markdown-content'); + const componentHtml = await componentContent.innerHTML(); + + expect(markdownHtml).toEqual(componentHtml); + }); + + test('does not render headings anchor links for individual Markdown pages and entries not part of the `docs` collection', async ({ + getProdServer, + page, + }) => { + const starlight = await getProdServer(); + + // Individual Markdown page + await starlight.goto('/markdown-page'); + await expect(page.locator('.sl-anchor-link')).not.toBeAttached(); + + // Content entry from the `reviews` content collection + await starlight.goto('/reviews/alice'); + await expect(page.locator('.sl-anchor-link')).not.toBeAttached(); + }); + + test('renders headings anchor links for entries not part of the `docs` collection matching the `markdown.processedDirs` option', async ({ + getProdServer, + page, + }) => { + const starlight = await getProdServer(); + + // Content entry from the `comments` content collection + await starlight.goto('/comments/bob'); + await expect(page.locator('.sl-anchor-link').first()).toBeAttached(); + }); + }); + + test.describe('asides', () => { + test('does not render Markdown asides for individual Markdown pages and entries not part of the `docs` collection', async ({ + getProdServer, + page, + }) => { + const starlight = await getProdServer(); + + // Individual Markdown page + await starlight.goto('/markdown-page'); + await expect(page.locator('.starlight-aside')).not.toBeAttached(); + + // Content entry from the `reviews` content collection + await starlight.goto('/reviews/alice'); + await expect(page.locator('.starlight-aside')).not.toBeAttached(); + }); + + test('renders Markdown asides for entries not part of the `docs` collection matching the `markdown.processedDirs` option', async ({ + getProdServer, + page, + }) => { + const starlight = await getProdServer(); + + // Content entry from the `comments` content collection + await starlight.goto('/comments/bob'); + await expect(page.locator('.starlight-aside')).toBeAttached(); + }); + }); + + test.describe('RTL support', () => { + test('does not add RTL support to code and preformatted text elements for individual Markdown pages and entries not part of the `docs` collection', async ({ + getProdServer, + page, + }) => { + const starlight = await getProdServer(); + + // Individual Markdown page + await starlight.goto('/markdown-page'); + await expect(page.locator('code[dir="auto"]')).not.toBeAttached(); + + // Content entry from the `reviews` content collection + await starlight.goto('/reviews/alice'); + await expect(page.locator('code[dir="auto"]')).not.toBeAttached(); + }); + + test('adds RTL support to code and preformatted text elements for entries not part of the `docs` collection matching the `markdown.processedDirs` option', async ({ + getProdServer, + page, + }) => { + const starlight = await getProdServer(); + + // Content entry from the `comments` content collection + await starlight.goto('/comments/bob'); + await expect(page.locator('code[dir="auto"]').first()).toBeAttached(); + }); + }); + + test.describe('head propagation', () => { + /** + * Due to a head propagation issue in development mode, dynamic routes alphabetically sorted + * before Starlight route (`[...slug]`) rendering the `` component can result in + * missing styles. The issue is workaround by having our call to `render` from `astro:content` to + * be in a specific file. + * + * @see https://github.com/withastro/astro/issues/13724 + */ + test('does not prevent head propagation in dev mode when rendering a dynamic route using the `` component', async ({ + page, + makeServer, + }) => { + const starlight = await makeServer('dev', { mode: 'dev' }); + await starlight.goto('/head-propagation'); + + await expect(page.getByTestId('purple-card')).toHaveCSS( + 'background-color', + 'rgb(128, 0, 128)' + ); + }); + }); + + test.describe('css layer order', () => { + test('ensures that the StarlightPage component is always imported first to ensure a predictable CSS layer order in custom pages', async ({ + page, + makeServer, + }) => { + const starlight = await makeServer('dev', { mode: 'dev' }); + await starlight.goto('/starlight-page-css-layer-order'); + + const firstStyleContent = await page.evaluate( + () => document.head.querySelector('style')?.textContent ?? '' + ); + + const expectedLayersOrder = await fs.readFile( + new URL('../style/layers.css', import.meta.url), + 'utf-8' + ); + + // Ensure that the first style block in the head contains the expected layers order rather + // the styles of the link button wrapped in a `@layer` block at-rule automatically declaring + // a new layer and thus potentially breaking the intended layers order as the initial order + // in which layers are declared indicates which layer has precedence. + expect(firstStyleContent).toBe(expectedLayersOrder); + }); + }); + + async function expectSelectedTab(tabs: Locator, label: string, panel?: string) { + expect( + ( + await tabs.locator(':scope > div:first-child [role=tab][aria-selected=true]').textContent() + )?.trim() + ).toBe(label); + + if (panel) { + const tabPanel = tabs.locator(':scope > [role=tabpanel]:not([hidden])'); + await expect(tabPanel).toBeVisible(); + expect((await tabPanel.textContent())?.trim()).toBe(panel); + } + } +}); + +test.describe('param normalization', () => { + test('renders the correct content for a file with Arabic diacritics', async ({ + page, + getProdServer, + }) => { + const starlight = await getProdServer(); + await starlight.goto('/اللُّغَةُ-الْعَرَبِيَّةُ'); + const content = page.locator('main'); + await expect(content).toHaveText(/This file contains Arabic diacritics in the file name./); + }); +}); + +test.describe('ToC highlighting', () => { + test.describe('highlights overview', () => { + test( + 'desktop viewport (1280×720)', + testTOCHighlighting({ + width: 1280, + height: 720, + path: '/headings', + pattern: /Overview/, + }) + ); + test( + 'tablet viewport (810×1080)', + testTOCHighlighting({ + width: 810, + height: 1080, + path: '/headings', + pattern: /Overview/, + }) + ); + test( + 'mobile viewport (375×667)', + testTOCHighlighting({ + width: 375, + height: 667, + path: '/headings', + pattern: /Overview/, + }) + ); + }); + + test.describe('highlights overview when scrolled to opening paragraph', () => { + test( + 'desktop viewport (1280×720)', + testTOCHighlighting({ + width: 1280, + height: 720, + path: '/headings', + pattern: /Overview/, + scrollBy: 200, + }) + ); + test( + 'tablet viewport (810×1080)', + testTOCHighlighting({ + width: 810, + height: 1080, + path: '/headings', + pattern: /Overview/, + scrollBy: 200, + }) + ); + test( + 'mobile viewport (375×667)', + testTOCHighlighting({ + width: 375, + height: 667, + path: '/headings', + pattern: /Overview/, + scrollBy: 200, + }) + ); + }); + + test.describe('highlights overview when a high banner is present', () => { + test( + 'desktop viewport (1280×720)', + testTOCHighlighting({ + width: 1280, + height: 720, + path: '/headings-banner', + pattern: /Overview/, + }) + ); + test( + 'tablet viewport (810×1080)', + testTOCHighlighting({ + width: 810, + height: 1080, + path: '/headings-banner', + pattern: /Overview/, + }) + ); + test( + 'mobile viewport (375×667)', + testTOCHighlighting({ + width: 375, + height: 667, + path: '/headings-banner', + pattern: /Overview/, + }) + ); + }); + + test.describe('highlights heading 1', () => { + test( + 'desktop viewport (1280×720)', + testTOCHighlighting({ + width: 1280, + height: 720, + path: '/headings#heading-1', + pattern: /Heading 1/, + }) + ); + test( + 'tablet viewport (810×1080)', + testTOCHighlighting({ + width: 810, + height: 1080, + path: '/headings#heading-1', + pattern: /Heading 1/, + }) + ); + test( + 'mobile viewport (375×667)', + testTOCHighlighting({ + width: 375, + height: 667, + path: '/headings#heading-1', + pattern: /Heading 1/, + }) + ); + }); + + test.describe('highlights heading 1 when scrolled to paragraph below', () => { + test( + 'desktop viewport (1280×720)', + testTOCHighlighting({ + width: 1280, + height: 720, + path: '/headings#heading-1', + pattern: /Heading 1/, + scrollBy: 250, + }) + ); + test( + 'tablet viewport (810×1080)', + testTOCHighlighting({ + width: 810, + height: 1080, + path: '/headings#heading-1', + pattern: /Heading 1/, + scrollBy: 250, + }) + ); + test( + 'mobile viewport (375×667)', + testTOCHighlighting({ + width: 375, + height: 667, + path: '/headings#heading-1', + pattern: /Heading 1/, + scrollBy: 250, + }) + ); + }); + + test.describe('highlights heading 3', () => { + test( + 'desktop viewport (1280×720)', + testTOCHighlighting({ + width: 1280, + height: 720, + path: '/headings#heading-3', + pattern: /Heading 3/, + }) + ); + test( + 'tablet viewport (810×1080)', + testTOCHighlighting({ + width: 810, + height: 1080, + path: '/headings#heading-3', + pattern: /Heading 3/, + }) + ); + test( + 'mobile viewport (375×667)', + testTOCHighlighting({ + width: 375, + height: 667, + path: '/headings#heading-3', + pattern: /Heading 3/, + }) + ); + }); + + test.describe('highlights heading 3 from focusing on a list item', () => { + test( + 'desktop viewport (1280×720)', + testTOCHighlighting({ + width: 1280, + height: 720, + path: '/headings#non-heading-id', + pattern: /Heading 3/, + }) + ); + test( + 'tablet viewport (810×1080)', + testTOCHighlighting({ + width: 810, + height: 1080, + path: '/headings#non-heading-id', + pattern: /Heading 3/, + }) + ); + test( + 'mobile viewport (375×667)', + testTOCHighlighting({ + width: 375, + height: 667, + path: '/headings#non-heading-id', + pattern: /Heading 3/, + }) + ); + }); + + test.describe('highlights h3 above an h4', () => { + test( + 'desktop viewport (1280×720)', + testTOCHighlighting({ + width: 1280, + height: 720, + path: '/headings#heading-4', + pattern: /Heading 3/, + }) + ); + test( + 'tablet viewport (810×1080)', + testTOCHighlighting({ + width: 810, + height: 1080, + path: '/headings#heading-4', + pattern: /Heading 3/, + }) + ); + test( + 'mobile viewport (375×667)', + testTOCHighlighting({ + width: 375, + height: 667, + path: '/headings#heading-4', + pattern: /Heading 3/, + }) + ); + }); +}); + +/** + * Loads the given `path` in a window of the specified `width` and `height` and checks that the + * Starlight table of contents is highlighting an item with contents matching `pattern`. + * The optional `scrollBy` parameter scrolls the page by that number of pixels before testing. + */ +function testTOCHighlighting({ + width, + height, + path, + pattern, + scrollBy, +}: { + width: number; + height: number; + path: string; + pattern: RegExp; + scrollBy?: number; +}) { + return async ({ + page, + getProdServer, + }: { + page: Page; + getProdServer: () => Promise; + }) => { + const test = async () => { + if (width > 1150) { + // On “desktop” viewports check the correct link is set as aria-current in the page sidebar. + const overviewLink = page.locator('starlight-toc [aria-current="true"]'); + await expect(overviewLink).toHaveText(pattern); + } else { + // On smaller viewports, check the component. + // The table of contents bar should display the current heading. + const currentSectionLabel = page.locator('mobile-starlight-toc .display-current'); + await expect(currentSectionLabel).toHaveText(pattern); + // Within the table of contents drop down, the highlighted link should be correct. + const overviewLink = page.locator('mobile-starlight-toc [aria-current="true"]'); + await expect(overviewLink).toHaveText(pattern); + } + }; + + await page.setViewportSize({ width, height }); + const starlight = await getProdServer(); + await starlight.goto(path); + if (scrollBy) { + await page.mouse.wheel(0, scrollBy); + } + + // Test highlighting on initial load + await test(); + + // Test highlighting on page refresh (which maintains scroll position) + await page.reload(); + await test(); + }; +} diff --git a/packages/starlight/__e2e__/collection-config.test.ts b/packages/starlight/__e2e__/collection-config.test.ts new file mode 100644 index 00000000000..feeadfe3326 --- /dev/null +++ b/packages/starlight/__e2e__/collection-config.test.ts @@ -0,0 +1,15 @@ +import { expect, testFactory } from './test-utils'; + +// This fixture contains a space in the directory so that we have a smoke test for building +// Starlight projects with pathnames like this, which are a common source of bugs. +const test = testFactory('./fixtures/custom src-dir/'); + +test('builds a custom page using the `` component and a custom `srcDir`', async ({ + page, + getProdServer, +}) => { + const starlight = await getProdServer(); + await starlight.goto('/custom'); + + await expect(page.getByText('Hello')).toBeVisible(); +}); diff --git a/packages/starlight/__e2e__/fixtures/basics/astro.config.mjs b/packages/starlight/__e2e__/fixtures/basics/astro.config.mjs new file mode 100644 index 00000000000..c30f11fdd33 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/astro.config.mjs @@ -0,0 +1,13 @@ +// @ts-check +import starlight from '@astrojs/starlight'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Basics', + pagefind: false, + markdown: { processedDirs: ['./src/content/comments/'] }, + }), + ], +}); diff --git a/packages/starlight/__e2e__/fixtures/basics/package.json b/packages/starlight/__e2e__/fixtures/basics/package.json new file mode 100644 index 00000000000..1880d32fd4a --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/package.json @@ -0,0 +1,9 @@ +{ + "name": "@e2e/basics", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/starlight": "workspace:*", + "astro": "^5.6.1" + } +} diff --git a/packages/starlight/__e2e__/fixtures/basics/src/components/PurpleCard.astro b/packages/starlight/__e2e__/fixtures/basics/src/components/PurpleCard.astro new file mode 100644 index 00000000000..932cb3f3877 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/components/PurpleCard.astro @@ -0,0 +1,8 @@ +
I am a purple card with white text.
+ + diff --git a/packages/starlight/__e2e__/fixtures/basics/src/components/Test.astro b/packages/starlight/__e2e__/fixtures/basics/src/components/Test.astro new file mode 100644 index 00000000000..e04d26faa02 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/components/Test.astro @@ -0,0 +1,11 @@ +--- +interface Props { + id: string; +} + +const { id } = Astro.props; +--- + +
+ +
diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content.config.ts b/packages/starlight/__e2e__/fixtures/basics/src/content.config.ts new file mode 100644 index 00000000000..471dfd376d6 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content.config.ts @@ -0,0 +1,18 @@ +import { defineCollection, z } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; +import { glob } from 'astro/loaders'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + // A collection not handled by Starlight. + reviews: defineCollection({ + loader: glob({ base: './src/content/reviews', pattern: `**/[^_]*.{md,mdx}` }), + schema: z.object({ title: z.string() }), + }), + // A collection opted in to Starlight’s Markdown processing. + comments: defineCollection({ + loader: glob({ base: './src/content/comments', pattern: `**/[^_]*.{md,mdx}` }), + schema: z.object({ title: z.string() }), + }), +}; diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/comments/bob.mdx b/packages/starlight/__e2e__/fixtures/basics/src/content/comments/bob.mdx new file mode 100644 index 00000000000..78104f760a0 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/comments/bob.mdx @@ -0,0 +1,18 @@ +--- +title: Comment from Bob +--- + +# Comment from Bob + +This is a comment from Bob. + +## Description + +This content collection entry is not part of the Starlight `docs` collection. +It is used to test that various remark/rehype plugins are transforming non-docs collection entries matching the `markdown.processedDirs` option. + +:::note +This is a note using Starlight Markdown aside syntax. +::: + +This is an `inline code` example. diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/anchor-heading-component.mdx b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/anchor-heading-component.mdx new file mode 100644 index 00000000000..245ce62c1ac --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/anchor-heading-component.mdx @@ -0,0 +1,9 @@ +--- +title: Anchor Headings Component +--- + +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; + +An anchor heading + +Another anchor heading diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/anchor-heading.md b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/anchor-heading.md new file mode 100644 index 00000000000..ce659560f01 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/anchor-heading.md @@ -0,0 +1,7 @@ +--- +title: Anchor Headings +--- + +## An anchor heading + +### Another anchor heading diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/head-propagation.mdx b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/head-propagation.mdx new file mode 100644 index 00000000000..dd16e472548 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/head-propagation.mdx @@ -0,0 +1,7 @@ +--- +title: Head Propagation +--- + +import PurpleCard from '../../components/PurpleCard.astro'; + + diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/headings-banner.md b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/headings-banner.md new file mode 100644 index 00000000000..9c81edd0fec --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/headings-banner.md @@ -0,0 +1,13 @@ +--- +title: Testing table of contents behaviour with a taller banner +banner: + content: 'Hello, I am big' +head: + - tag: style + content: | + :root .sl-banner { + padding-block: 2rem; + } +--- + +This is a page with a very tall banner. diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/headings.md b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/headings.md new file mode 100644 index 00000000000..172d841785b --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/headings.md @@ -0,0 +1,48 @@ +--- +title: Testing table of contents behaviour +--- + +This page is used to test table of contents highlighting behaviour in end-to-end tests. +It contains a mix of content and various headings to test it works as expected under a range of conditions. + +## Heading 1 + +Scrolling to this section should highlight “Heading 1” in the table of contents. + +Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. + +Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. + +## Heading 2 + +### Heading 3 + +Scrolling to this section should highlight “Heading 3” in the table of contents, not “Heading 2”. + +Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. + +:::note[Test note] +An example note. +::: + +1. List item one + +2. List item two + + Scrolling to `#non-heading-id` should still find and highlight “Heading 3”. + +3. List item three + +Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. + +#### Heading 4 + +Scrolling to this section should still highlight “Heading 3” in the table of contents, because level-four headings are not in the ToC. + +Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. + +Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. + +Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. + +Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-nested.mdx b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-nested.mdx new file mode 100644 index 00000000000..1be29663b4c --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-nested.mdx @@ -0,0 +1,47 @@ +--- +title: Tabs +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +A set of tabs using the `pkg` sync key with some nested tabs using an `os` sync key. + + + + + + npm content + + + npm macOS + npm Windows + npm GNU/Linux + + + + + + + pnpm content + + + pnpm macOS + pnpm Windows + pnpm GNU/Linux + + + + + + + yarn content + + + yarn macOS + yarn Windows + yarn GNU/Linux + + + + + diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-unsynced.mdx b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-unsynced.mdx new file mode 100644 index 00000000000..fa94b6cae8f --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-unsynced.mdx @@ -0,0 +1,21 @@ +--- +title: Tabs unsynced +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +A basic set of tabs. + + + npm command + pnpm command + yarn command + + +Another basic set of tabs. + + + tab 1 + tab 2 + tab 3 + diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-variable-height.mdx b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-variable-height.mdx new file mode 100644 index 00000000000..7c7a0485864 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-variable-height.mdx @@ -0,0 +1,151 @@ +--- +title: Tabs with varying content heights +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +**A set of tabs using a sync key with content of different heights between tabs.** + + + + +A little bit of text. + + + + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + + + + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +**Another set of tabs using the same sync key with content of different heights between tabs.** + + + + +A little bit of text. + + + + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + + + + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs.mdx b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs.mdx new file mode 100644 index 00000000000..ea542494830 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs.mdx @@ -0,0 +1,70 @@ +--- +title: Tabs +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +A set of tabs using the `pkg` sync key. + + + npm command + pnpm command + yarn command + + +A basic set of tabs. + + + tab 1 + tab 2 + tab 3 + + +Another set of tabs using the `pkg` sync key and an extra tab. + + + another npm command + another pnpm command + another bun command + another yarn command + + +A set of tabs using the `style` sync key. + + + css code + tailwind code + + +Another set of tabs using the `pkg` sync key and using icons. + + + + another npm command + + + another pnpm command + + + another bun command + + + another yarn command + + + +A set of tabs using the `os` sync key. + + + macOS + Windows + GNU/Linux + + +Another set of tabs using the `os` sync key. + + + ls + Get-ChildItem + ls + diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/whitespaces.mdx b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/whitespaces.mdx new file mode 100644 index 00000000000..0ee24b83e04 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/whitespaces.mdx @@ -0,0 +1,14 @@ +--- +title: Whitespaces +--- + +import { Badge, Icon } from '@astrojs/starlight/components'; +import Test from '../../components/Test.astro'; + + + Badge () + + + + Icon () + diff --git "a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/\330\247\331\204\331\204\331\221\331\217\330\272\331\216\330\251\331\217-\330\247\331\204\331\222\330\271\331\216\330\261\331\216\330\250\331\220\331\212\331\221\331\216\330\251\331\217.md" "b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/\330\247\331\204\331\204\331\221\331\217\330\272\331\216\330\251\331\217-\330\247\331\204\331\222\330\271\331\216\330\261\331\216\330\250\331\220\331\212\331\221\331\216\330\251\331\217.md" new file mode 100644 index 00000000000..2bec9479c25 --- /dev/null +++ "b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/\330\247\331\204\331\204\331\221\331\217\330\272\331\216\330\251\331\217-\330\247\331\204\331\222\330\271\331\216\330\261\331\216\330\250\331\220\331\212\331\221\331\216\330\251\331\217.md" @@ -0,0 +1,7 @@ +--- +title: اللُّغَةُ-الْعَرَبِيَّةُ +--- + +This file contains Arabic diacritics in the file name. +Astro normalizes params, which can cause differences between a content collection slug and the requested param for file names like this. +This file helps us test that Starlight correctly matches a content collection entry to Astro’s normalized param. diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/reviews/alice.mdx b/packages/starlight/__e2e__/fixtures/basics/src/content/reviews/alice.mdx new file mode 100644 index 00000000000..938357bf849 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/reviews/alice.mdx @@ -0,0 +1,18 @@ +--- +title: Review from Alice +--- + +# Review from Alice + +This is a review from Alice. + +## Description + +This content collection entry is not part of the Starlight `docs` collection. +It is used to test that various remark/rehype plugins are not transforming non-docs collection entries. + +:::note +This is a note using Starlight Markdown aside syntax. +::: + +This is an `inline code` example. diff --git a/docs/src/env.d.ts b/packages/starlight/__e2e__/fixtures/basics/src/env.d.ts similarity index 100% rename from docs/src/env.d.ts rename to packages/starlight/__e2e__/fixtures/basics/src/env.d.ts diff --git a/packages/starlight/__e2e__/fixtures/basics/src/pages/[...param].astro b/packages/starlight/__e2e__/fixtures/basics/src/pages/[...param].astro new file mode 100644 index 00000000000..db5d8675da7 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/pages/[...param].astro @@ -0,0 +1,17 @@ +--- +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; + +/** + * The name of this dynamic route is intentionally set to `[...param]` to test a head propagation + * issue that occurs for dynamic routes alphabetically sorted before the Starlight default route + * (`[...slug]`) rendering the `` component. + */ + +export function getStaticPaths() { + return [{ params: { param: 'custom-page' } }]; +} +--- + + +

This is a custom page

+
diff --git a/packages/starlight/__e2e__/fixtures/basics/src/pages/comments/[...comment].astro b/packages/starlight/__e2e__/fixtures/basics/src/pages/comments/[...comment].astro new file mode 100644 index 00000000000..e5b7d9f1e4f --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/pages/comments/[...comment].astro @@ -0,0 +1,21 @@ +--- +import { getEntry, render } from 'astro:content'; + +/** + * This route is used to test that remark/rehype plugins are transofming non-docs collection + * entries matching the `markdown.processedDirs` option. + */ + +export function getStaticPaths() { + return [{ params: { comment: 'bob' } }]; +} + +// @ts-expect-error - we don't generate types for this test fixture before type-checking the entire +// project. +const entry = await getEntry('comments', 'bob'); +if (!entry) throw new Error('Could not find Bob review entry.'); + +const { Content } = await render(entry); +--- + + diff --git a/packages/starlight/__e2e__/fixtures/basics/src/pages/markdown-page.md b/packages/starlight/__e2e__/fixtures/basics/src/pages/markdown-page.md new file mode 100644 index 00000000000..085dd68ca3d --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/pages/markdown-page.md @@ -0,0 +1,16 @@ +--- +title: Individual Markdown Page +--- + +# Individual Markdown Page + +## Description + +This page is an [individual Markdown page](https://docs.astro.build/en/guides/markdown-content/#individual-markdown-pages). +It is used to test that various remark/rehype plugins are not transforming individual Markdown pages. + +:::note +This is a note using Starlight Markdown aside syntax. +::: + +This is an `inline code` example. diff --git a/packages/starlight/__e2e__/fixtures/basics/src/pages/reviews/[...review].astro b/packages/starlight/__e2e__/fixtures/basics/src/pages/reviews/[...review].astro new file mode 100644 index 00000000000..a5ad3c1b694 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/pages/reviews/[...review].astro @@ -0,0 +1,21 @@ +--- +import { getEntry, render } from 'astro:content'; + +/** + * This route is used to test that remark/rehype plugins are not transforming non-docs collection + * entries. + */ + +export function getStaticPaths() { + return [{ params: { review: 'alice' } }]; +} + +// @ts-expect-error - we don't generate types for this test fixture before type-checking the entire +// project. +const entry = await getEntry('reviews', 'alice'); +if (!entry) throw new Error('Could not find Alice review entry.'); + +const { Content } = await render(entry); +--- + + diff --git a/packages/starlight/__e2e__/fixtures/basics/src/pages/starlight-page-css-layer-order.astro b/packages/starlight/__e2e__/fixtures/basics/src/pages/starlight-page-css-layer-order.astro new file mode 100644 index 00000000000..b5071965a52 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/pages/starlight-page-css-layer-order.astro @@ -0,0 +1,23 @@ +--- +import { LinkButton } from '@astrojs/starlight/components'; + +import AnchorHeading from '@astrojs/starlight/components/AnchorHeading.astro'; + +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; + +/** + * This page is used to test the CSS layer order in custom pages using the StarlightPage> component + * where we cannot ensure a correct import order of CSS. + * Note that the order of imports in this file is important and should not be changed. + */ +--- + + + A Sub heading + +

Custom page content and a link to another page.

+ +

+ Tabs link button +

+
diff --git a/packages/starlight/__e2e__/fixtures/custom src-dir/astro.config.mjs b/packages/starlight/__e2e__/fixtures/custom src-dir/astro.config.mjs new file mode 100644 index 00000000000..68689f1b768 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/custom src-dir/astro.config.mjs @@ -0,0 +1,13 @@ +// @ts-check +import starlight from '@astrojs/starlight'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + srcDir: './www', + integrations: [ + starlight({ + title: 'Custom src directory', + pagefind: false, + }), + ], +}); diff --git a/packages/starlight/__e2e__/fixtures/custom src-dir/package.json b/packages/starlight/__e2e__/fixtures/custom src-dir/package.json new file mode 100644 index 00000000000..9edbcca8267 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/custom src-dir/package.json @@ -0,0 +1,9 @@ +{ + "name": "@e2e/custom-src-dir", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/starlight": "workspace:*", + "astro": "^5.6.1" + } +} diff --git a/packages/starlight/__e2e__/fixtures/custom src-dir/www/content.config.ts b/packages/starlight/__e2e__/fixtures/custom src-dir/www/content.config.ts new file mode 100644 index 00000000000..d9ee8c9d1c9 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/custom src-dir/www/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/examples/basics/src/env.d.ts b/packages/starlight/__e2e__/fixtures/custom src-dir/www/env.d.ts similarity index 100% rename from examples/basics/src/env.d.ts rename to packages/starlight/__e2e__/fixtures/custom src-dir/www/env.d.ts diff --git a/packages/starlight/__e2e__/fixtures/custom src-dir/www/pages/custom.astro b/packages/starlight/__e2e__/fixtures/custom src-dir/www/pages/custom.astro new file mode 100644 index 00000000000..680eaaef6a7 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/custom src-dir/www/pages/custom.astro @@ -0,0 +1,7 @@ +--- +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +--- + + +

Hello

+
diff --git a/packages/starlight/__e2e__/fixtures/git/.gitignore b/packages/starlight/__e2e__/fixtures/git/.gitignore new file mode 100644 index 00000000000..1fb22bd5a93 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/git/.gitignore @@ -0,0 +1,10 @@ +# This fixture is used for the E2E tests related to Git where +# a new repo is created. Nested repos do not inherit the .gitignore +# options from the parent repo, so even though these files are +# already ignored on the package they have to be re-declared here. +# Do not delete this file or the Git tests will try to index and +# and commit all the node_modules and generated files from the test. +env.d.ts +.astro +/node_modules/ +/dist/ diff --git a/packages/starlight/__e2e__/fixtures/git/astro.config.mjs b/packages/starlight/__e2e__/fixtures/git/astro.config.mjs new file mode 100644 index 00000000000..c3433485c39 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/git/astro.config.mjs @@ -0,0 +1,12 @@ +// @ts-check +import starlight from '@astrojs/starlight'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Git', + pagefind: false, + }), + ], +}); diff --git a/packages/starlight/__e2e__/fixtures/git/package.json b/packages/starlight/__e2e__/fixtures/git/package.json new file mode 100644 index 00000000000..ca06d7c9ec2 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/git/package.json @@ -0,0 +1,9 @@ +{ + "name": "@e2e/git", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/starlight": "workspace:*", + "astro": "^5.6.1" + } +} diff --git a/packages/starlight/__e2e__/fixtures/git/src/content.config.ts b/packages/starlight/__e2e__/fixtures/git/src/content.config.ts new file mode 100644 index 00000000000..d9ee8c9d1c9 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/git/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/packages/starlight/__e2e__/fixtures/git/src/content/docs/index.md b/packages/starlight/__e2e__/fixtures/git/src/content/docs/index.md new file mode 100644 index 00000000000..9a02f87ca4f --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/git/src/content/docs/index.md @@ -0,0 +1,6 @@ +--- +title: Home Page +lastUpdated: true +--- + +Home page content diff --git a/packages/starlight/__e2e__/fixtures/legacy-collection-config-file/astro.config.mjs b/packages/starlight/__e2e__/fixtures/legacy-collection-config-file/astro.config.mjs new file mode 100644 index 00000000000..02d3655e401 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/legacy-collection-config-file/astro.config.mjs @@ -0,0 +1,12 @@ +// @ts-check +import starlight from '@astrojs/starlight'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Legacy collection config file', + pagefind: false, + }), + ], +}); diff --git a/packages/starlight/__e2e__/fixtures/legacy-collection-config-file/package.json b/packages/starlight/__e2e__/fixtures/legacy-collection-config-file/package.json new file mode 100644 index 00000000000..09c3991e254 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/legacy-collection-config-file/package.json @@ -0,0 +1,9 @@ +{ + "name": "@e2e/legacy-collection-config-file", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/starlight": "workspace:*", + "astro": "^5.6.1" + } +} diff --git a/packages/starlight/__e2e__/fixtures/legacy-collection-config-file/src/content/config.ts b/packages/starlight/__e2e__/fixtures/legacy-collection-config-file/src/content/config.ts new file mode 100644 index 00000000000..d9ee8c9d1c9 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/legacy-collection-config-file/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/packages/starlight/__e2e__/fixtures/legacy-collection-config-file/src/pages/custom.astro b/packages/starlight/__e2e__/fixtures/legacy-collection-config-file/src/pages/custom.astro new file mode 100644 index 00000000000..680eaaef6a7 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/legacy-collection-config-file/src/pages/custom.astro @@ -0,0 +1,7 @@ +--- +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +--- + + +

Hello

+
diff --git a/packages/starlight/__e2e__/fixtures/no-node-builtins/astro.config.mjs b/packages/starlight/__e2e__/fixtures/no-node-builtins/astro.config.mjs new file mode 100644 index 00000000000..2d6eeed08ef --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/no-node-builtins/astro.config.mjs @@ -0,0 +1,16 @@ +// @ts-check +import starlight from '@astrojs/starlight'; +import { defineConfig } from 'astro/config'; +import { preventNodeBuiltinDependencyPlugin } from './src/noNodeModule'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'No Node Builtins', + pagefind: false, + }), + ], + vite: { + plugins: [preventNodeBuiltinDependencyPlugin()], + }, +}); diff --git a/packages/starlight/__e2e__/fixtures/no-node-builtins/package.json b/packages/starlight/__e2e__/fixtures/no-node-builtins/package.json new file mode 100644 index 00000000000..5555ae1fdf8 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/no-node-builtins/package.json @@ -0,0 +1,9 @@ +{ + "name": "@e2e/no-node-builtins", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/starlight": "workspace:*", + "astro": "^5.6.1" + } +} diff --git a/packages/starlight/__e2e__/fixtures/no-node-builtins/src/content.config.ts b/packages/starlight/__e2e__/fixtures/no-node-builtins/src/content.config.ts new file mode 100644 index 00000000000..d9ee8c9d1c9 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/no-node-builtins/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/packages/starlight/__e2e__/fixtures/no-node-builtins/src/content/docs/index.md b/packages/starlight/__e2e__/fixtures/no-node-builtins/src/content/docs/index.md new file mode 100644 index 00000000000..fa27b816bd8 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/no-node-builtins/src/content/docs/index.md @@ -0,0 +1,5 @@ +--- +title: Home Page +--- + +Home page content diff --git a/packages/starlight/__e2e__/fixtures/no-node-builtins/src/noNodeModule.ts b/packages/starlight/__e2e__/fixtures/no-node-builtins/src/noNodeModule.ts new file mode 100644 index 00000000000..1089e19462f --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/no-node-builtins/src/noNodeModule.ts @@ -0,0 +1,36 @@ +import type { ViteUserConfig } from 'astro'; +import { builtinModules } from 'node:module'; + +const nodeModules = builtinModules.map((name) => [name, `node:${name}`]).flat(); + +/** + * A Vite plugin used to verify that the final bundle does not have a hard dependency on Node.js + * builtins due to Starlight. + * This is to ensure that Starlight can run on platforms like Cloudflare. + * + * @see https://github.com/withastro/astro/blob/8491aa56e8685677af8458ff1c5a80d6461413f8/packages/astro/test/test-plugins.js + */ +export function preventNodeBuiltinDependencyPlugin(): NonNullable< + ViteUserConfig['plugins'] +>[number] { + return { + name: 'verify-no-node-stuff', + generateBundle() { + nodeModules.forEach((name) => { + const importers = this.getModuleInfo(name)?.importers || []; + const starlightPath = new URL('../../../../', import.meta.url).pathname; + const nodeStarlightImport = importers.find((importer) => + importer.startsWith(starlightPath) + ); + + if (nodeStarlightImport) { + throw new Error( + 'A node builtin dependency imported by Starlight was found in the production bundle:\n\n' + + ` - Node builtin: '${name}'\n` + + ` - Importer: ${nodeStarlightImport}\n` + ); + } + }); + }, + }; +} diff --git a/packages/starlight/__e2e__/fixtures/ssr/astro.config.mjs b/packages/starlight/__e2e__/fixtures/ssr/astro.config.mjs new file mode 100644 index 00000000000..1b30d0243ee --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/ssr/astro.config.mjs @@ -0,0 +1,26 @@ +// @ts-check +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; +import node from '@astrojs/node'; + +const prerendering = process.env.STARLIGHT_PRERENDER === 'yes'; + +export default defineConfig({ + output: 'server', + adapter: node({ mode: 'standalone' }), + compressHTML: false, // for easier debugging + // Output to different folders and expose on different ports + // on each case so the servers don't conflict with + // each other during tests. + outDir: prerendering ? 'dist' : 'build', + server: { + port: prerendering ? 4322 : 4321, + }, + integrations: [ + starlight({ + title: 'SSR', + prerender: prerendering, + pagefind: false, + }), + ], +}); diff --git a/packages/starlight/__e2e__/fixtures/ssr/package.json b/packages/starlight/__e2e__/fixtures/ssr/package.json new file mode 100644 index 00000000000..d93d95aa3c7 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/ssr/package.json @@ -0,0 +1,10 @@ +{ + "name": "@e2e/ssr", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/node": "^9.0.0", + "@astrojs/starlight": "workspace:*", + "astro": "^5.6.1" + } +} diff --git a/packages/starlight/__e2e__/fixtures/ssr/src/component/ServerCheck.astro b/packages/starlight/__e2e__/fixtures/ssr/src/component/ServerCheck.astro new file mode 100644 index 00000000000..f6450a75058 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/ssr/src/component/ServerCheck.astro @@ -0,0 +1,15 @@ +--- +function checkServer() { + try { + Astro.clientAddress; + + return true; + } catch { + // Accessing `clientAddress` during build time + // fails, so it is not SSR. + return false; + } +} +--- + +
{checkServer() ? 'On server' : 'Not server'}
diff --git a/packages/starlight/__e2e__/fixtures/ssr/src/content.config.ts b/packages/starlight/__e2e__/fixtures/ssr/src/content.config.ts new file mode 100644 index 00000000000..d9ee8c9d1c9 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/ssr/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/packages/starlight/__e2e__/fixtures/ssr/src/content/docs/404.mdx b/packages/starlight/__e2e__/fixtures/ssr/src/content/docs/404.mdx new file mode 100644 index 00000000000..522e0072917 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/ssr/src/content/docs/404.mdx @@ -0,0 +1,9 @@ +--- +title: Not Found +template: splash +lastUpdate: true +--- + +import ServerCheck from '../../component/ServerCheck.astro'; + + diff --git a/packages/starlight/__e2e__/fixtures/ssr/src/content/docs/content.mdx b/packages/starlight/__e2e__/fixtures/ssr/src/content/docs/content.mdx new file mode 100644 index 00000000000..be10b182948 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/ssr/src/content/docs/content.mdx @@ -0,0 +1,6 @@ +--- +title: Content +lastUpdate: true +--- + +Example page diff --git a/packages/starlight/__e2e__/fixtures/ssr/src/content/docs/demo.mdx b/packages/starlight/__e2e__/fixtures/ssr/src/content/docs/demo.mdx new file mode 100644 index 00000000000..e475b6fd875 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/ssr/src/content/docs/demo.mdx @@ -0,0 +1,8 @@ +--- +title: Server Check +lastUpdate: true +--- + +import ServerCheck from '../../component/ServerCheck.astro'; + + diff --git a/packages/starlight/__e2e__/fixtures/ssr/src/content/docs/index.md b/packages/starlight/__e2e__/fixtures/ssr/src/content/docs/index.md new file mode 100644 index 00000000000..f61f5cd3588 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/ssr/src/content/docs/index.md @@ -0,0 +1,18 @@ +--- +title: Home Page +template: splash +lastUpdate: true +hero: + title: Make your docs shine with Starlight + tagline: Everything you need to build a stellar documentation website. Fast, accessible, and easy-to-use. + actions: + - text: Get started + icon: right-arrow + variant: primary + link: /getting-started/ + - text: View on GitHub + icon: external + link: https://github.com/withastro/starlight +--- + +Home page content diff --git a/packages/starlight/__e2e__/fixtures/ssr/src/middleware.ts b/packages/starlight/__e2e__/fixtures/ssr/src/middleware.ts new file mode 100644 index 00000000000..621cb87a0f2 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/ssr/src/middleware.ts @@ -0,0 +1,8 @@ +import { defineMiddleware } from 'astro:middleware'; + +export const onRequest = defineMiddleware((context, next) => { + if (context.url.pathname === '/content') { + return context.rewrite('/demo'); + } + return next(); +}); diff --git a/packages/starlight/__e2e__/git.test.ts b/packages/starlight/__e2e__/git.test.ts new file mode 100644 index 00000000000..f73075fe474 --- /dev/null +++ b/packages/starlight/__e2e__/git.test.ts @@ -0,0 +1,36 @@ +import { makeTestRepo } from '../__tests__/git-utils'; +import { expect, testFactory } from './test-utils'; +import { rm } from 'node:fs/promises'; +import { fileURLToPath } from 'node:url'; +import { join } from 'node:path'; + +const repoPath = fileURLToPath(new URL('./fixtures/git/', import.meta.url)); + +const test = testFactory(repoPath); + +test.beforeAll(async () => { + // Clears existing nested repo to account for previously interrupted tests. + await rm(join(repoPath, '.git'), { recursive: true, force: true }); + const testRepo = makeTestRepo(repoPath); + + testRepo.commitAllChanges('Add home page', '2024-02-03'); +}); + +test.afterAll(async () => { + // Remove nested repo after test runs + await rm(join(repoPath, '.git'), { recursive: true, force: true }); +}); + +test('include last updated date from git in the footer', async ({ page, getProdServer }) => { + const starlight = await getProdServer(); + await starlight.goto('/'); + + await expect(page.locator('footer')).toContainText('Last updated: Feb 3, 2024'); +}); + +test('include git information while developing', async ({ page, makeServer }) => { + const starlight = await makeServer('dev', { mode: 'dev' }); + await starlight.goto('/'); + + await expect(page.locator('footer')).toContainText('Last updated: Feb 3, 2024'); +}); diff --git a/packages/starlight/__e2e__/legacy-collection-config-file.test.ts b/packages/starlight/__e2e__/legacy-collection-config-file.test.ts new file mode 100644 index 00000000000..71b67f4136f --- /dev/null +++ b/packages/starlight/__e2e__/legacy-collection-config-file.test.ts @@ -0,0 +1,15 @@ +import { expect, testFactory } from './test-utils'; + +// This fixture uses a legacy collection config file (`src/content/config.ts`) instead of the new +// one (`src/content.config.ts`). +const test = testFactory('./fixtures/legacy-collection-config-file/'); + +test('builds a custom page using the `` component and a legacy collection config file', async ({ + page, + getProdServer, +}) => { + const starlight = await getProdServer(); + await starlight.goto('/custom'); + + await expect(page.getByText('Hello')).toBeVisible(); +}); diff --git a/packages/starlight/__e2e__/no-node-builtins.test.ts b/packages/starlight/__e2e__/no-node-builtins.test.ts new file mode 100644 index 00000000000..00ade3b8b4d --- /dev/null +++ b/packages/starlight/__e2e__/no-node-builtins.test.ts @@ -0,0 +1,10 @@ +import { expect, testFactory } from './test-utils'; + +const test = testFactory('./fixtures/no-node-builtins/'); + +test('builds without any dependencies on Node.js builtins', async ({ page, getProdServer }) => { + const starlight = await getProdServer(); + await starlight.goto('/'); + + await expect(page.getByText('Home page content')).toBeVisible(); +}); diff --git a/packages/starlight/__e2e__/ssr.test.ts b/packages/starlight/__e2e__/ssr.test.ts new file mode 100644 index 00000000000..1c21e0a1870 --- /dev/null +++ b/packages/starlight/__e2e__/ssr.test.ts @@ -0,0 +1,74 @@ +import { expect, testFactory } from './test-utils'; +import assert from 'node:assert'; +import { parseHTML } from 'linkedom'; + +const test = testFactory('./fixtures/ssr/'); + +test.beforeEach(() => { + delete process.env.STARLIGHT_PRERENDER; +}); + +test('Render page on the server', async ({ page, getProdServer }) => { + const starlight = await getProdServer(); + await starlight.goto('/demo'); + + await expect(page.locator('#server-check')).toHaveText('On server'); +}); + +test('Render 404 page on the server', async ({ page, getProdServer }) => { + const starlight = await getProdServer(); + await starlight.goto('/not-found'); + + await expect(page.locator('#server-check')).toHaveText('On server'); +}); + +test('SSR mode renders the same content page as prerendering', async ({ + getProdServer, + makeServer, +}) => { + const starlight = await getProdServer(); + const ssrContent = await starlight.goto('/content').then((res) => res?.text()); + assert(ssrContent); + + process.env.STARLIGHT_PRERENDER = 'yes'; + const prerenderStarlight = await makeServer('prerender'); + const prerenderContent = await prerenderStarlight.goto('/content').then((res) => res?.text()); + assert(prerenderContent); + + expectEquivalentHTML(prerenderContent, ssrContent); +}); + +test('SSR mode renders the same splash page as prerendering', async ({ + getProdServer, + makeServer, +}) => { + const starlight = await getProdServer(); + const ssrContent = await starlight.goto('/').then((res) => res?.text()); + assert(ssrContent); + + process.env.STARLIGHT_PRERENDER = 'yes'; + const prerenderStarlight = await makeServer('prerender'); + const prerenderContent = await prerenderStarlight.goto('/').then((res) => res?.text()); + assert(prerenderContent); + + expectEquivalentHTML(prerenderContent, ssrContent); +}); + +test('supports middleware rewriting', async ({ page, getProdServer }) => { + const starlight = await getProdServer(); + const response = await starlight.goto('/content'); + + expect(response?.status()).toBe(200); + await expect(page.locator('#server-check')).toHaveText('On server'); +}); + +function expectEquivalentHTML(a: string, b: string) { + expect(getNormalizedHTML(a)).toEqual(getNormalizedHTML(b)); +} + +function getNormalizedHTML(html: string) { + const window = parseHTML(html); + window.document.querySelectorAll('script[src]').forEach((el) => el.setAttribute('src', '')); + window.document.querySelectorAll('link[href]').forEach((el) => el.setAttribute('href', '')); + return window.toString(); +} diff --git a/packages/starlight/__e2e__/test-utils.ts b/packages/starlight/__e2e__/test-utils.ts new file mode 100644 index 00000000000..ffbc305f2f1 --- /dev/null +++ b/packages/starlight/__e2e__/test-utils.ts @@ -0,0 +1,103 @@ +import { fileURLToPath } from 'node:url'; +import { test as baseTest, type Page } from '@playwright/test'; +import { build, dev, preview } from 'astro'; + +export { expect, type Locator } from '@playwright/test'; + +process.env.ASTRO_TELEMETRY_DISABLED = 'true'; +process.env.ASTRO_DISABLE_UPDATE_CHECK = 'true'; + +// Setup a test environment that will build and start a preview server for a given fixture path and +// provide a Starlight Playwright fixture accessible from within all tests. +export function testFactory(fixturePath: string) { + const fixturePathUrl = new URL(fixturePath, import.meta.url); + // Combining absolute paths with a `file:` base URL on Windows results + // in a URL with the drive letter as the protocol. + // In that case, use the URL as is instead of interpreting the `file:` protocol. + const root = + fixturePathUrl.protocol === 'file:' + ? fileURLToPath(new URL(fixturePath, import.meta.url)) + : fixturePathUrl.toString(); + + async function makeServer( + options: { + mode?: 'build' | 'dev'; + } = {} + ): Promise { + const { mode } = options; + if (mode === 'dev') { + return await dev({ + logLevel: 'error', + root, + // Vite's dev server hangs on the optimization discovery phase when + // trying to stop the server programmatically at the end of the test. + // Disabling this optimization here allows the test to run properly + // on CI and fresh clones of the project. + vite: { optimizeDeps: { noDiscovery: true } }, + }); + } else { + await build({ logLevel: 'error', root }); + return await preview({ logLevel: 'error', root }); + } + } + + // Optimization for tests that don't customize any server options + // to not rebuild the fixture for each test. + let prodServer: Server | null = null; + const servers = new Map(); + + const test = baseTest.extend<{ + getProdServer: () => Promise; + makeServer: (name: string, ...params: Parameters) => Promise; + }>({ + getProdServer: ({ page }, use) => + use(async () => { + const server = (prodServer ??= await makeServer({ + mode: 'build', + })); + return new StarlightPage(server, page); + }), + makeServer: ({ page }, use) => + use(async (name, ...params) => { + const server = servers.get(name) ?? (await makeServer(...params)); + servers.set(name, server); + return new StarlightPage(server, page); + }), + }); + + test.afterAll(async () => { + await prodServer?.stop(); + for (const server of servers.values()) { + await server.stop(); + } + }); + + return test; +} + +// A Playwright test fixture accessible from within all tests. +export class StarlightPage { + private readonly server: Server; + private readonly page: Page; + + constructor(server: Server, page: Page) { + this.server = server; + this.page = page; + } + + // Navigate to a URL relative to the server used during a test run and return the resource response. + goto(url: string) { + return this.page.goto(this.resolveUrl(url)); + } + + // Resolve a URL relative to the server used during a test run. + resolveUrl(url: string) { + const port = 'address' in this.server ? this.server.address.port : this.server.port; + + return `http://localhost:${port}${url.replace(/^\/?/, '/')}`; + } +} + +type PreviewServer = Awaited>; +type DevServer = Awaited>; +type Server = PreviewServer | DevServer; diff --git a/packages/starlight/__tests__/absolute-favicon/absolute-favicon.test.ts b/packages/starlight/__tests__/absolute-favicon/absolute-favicon.test.ts new file mode 100644 index 00000000000..de880fd03bf --- /dev/null +++ b/packages/starlight/__tests__/absolute-favicon/absolute-favicon.test.ts @@ -0,0 +1,20 @@ +import { expect, test, vi } from 'vitest'; +import { routes } from '../../utils/routing'; +import { generateRouteData } from '../../utils/routing/data'; +import { getRouteDataTestContext } from '../test-utils'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [['index.mdx', { title: 'Home Page' }]], + }) +); + +test('places the default favicon below any user provided icons', () => { + const { head } = generateRouteData({ + props: { ...routes[0]!, headings: [] }, + context: getRouteDataTestContext(), + }); + const faviconEntry = head.find((tag) => tag.tag === 'link' && tag.attrs?.rel === 'shortcut icon'); + + expect(faviconEntry?.attrs?.href).toBe('https://example.com/favicon.ico'); +}); diff --git a/packages/starlight/__tests__/absolute-favicon/vitest.config.ts b/packages/starlight/__tests__/absolute-favicon/vitest.config.ts new file mode 100644 index 00000000000..604ae0b2d63 --- /dev/null +++ b/packages/starlight/__tests__/absolute-favicon/vitest.config.ts @@ -0,0 +1,6 @@ +import { defineVitestConfig } from '../test-config'; + +export default defineVitestConfig({ + title: 'Docs With Absolute favicon', + favicon: 'https://example.com/favicon.ico', +}); diff --git a/packages/starlight/__tests__/basics/base.test.ts b/packages/starlight/__tests__/basics/base.test.ts index c8a79b63e21..72cabe6539d 100644 --- a/packages/starlight/__tests__/basics/base.test.ts +++ b/packages/starlight/__tests__/basics/base.test.ts @@ -11,14 +11,21 @@ describe('fileWithBase()', () => { }); }); - // TODO: Stubbing BASE_URL is not currently possible. - // Astro controls BASE_URL via its `vite-plugin-env`, which prevents Vitest’s stubbing from - // working and there’s also no way to pass in Astro config in Astro’s `getViteConfig` helper. - describe.todo('with base', () => { - test('prepends base', () => { + describe('with base', () => { + test('prepends base', async () => { + // Reset the modules registry so that re-importing `../../utils/base` re-evaluates the module + // and re-computes the base. Re-importing the module is necessary because top-level imports + // cannot be re-evaluated. + vi.resetModules(); + // Set the base URL. vi.stubEnv('BASE_URL', '/base/'); + // Re-import the module to re-evaluate it. + const { fileWithBase } = await import('../../utils/base'); + expect(fileWithBase('/img.svg')).toBe('/base/img.svg'); + vi.unstubAllEnvs(); + vi.resetModules(); }); }); }); @@ -28,10 +35,22 @@ describe('pathWithBase()', () => { test('does not prepend anything', () => { expect(pathWithBase('/path/')).toBe('/path/'); }); - test('adds leading and trailing slashes if needed', () => { - expect(pathWithBase('path')).toBe('/path/'); + test('adds leading slash if needed', () => { + expect(pathWithBase('path')).toBe('/path'); }); }); - describe.todo('with base'); + describe('with base', () => { + test('prepends base', async () => { + // See the first test with a base in this file for an explanation of the environment stubbing. + vi.resetModules(); + vi.stubEnv('BASE_URL', '/base/'); + const { pathWithBase } = await import('../../utils/base'); + + expect(pathWithBase('/path/')).toBe('/base/path/'); + + vi.unstubAllEnvs(); + vi.resetModules(); + }); + }); }); diff --git a/packages/starlight/__tests__/basics/config-errors.test.ts b/packages/starlight/__tests__/basics/config-errors.test.ts new file mode 100644 index 00000000000..e4772813719 --- /dev/null +++ b/packages/starlight/__tests__/basics/config-errors.test.ts @@ -0,0 +1,315 @@ +import { expect, test } from 'vitest'; +import { parseWithFriendlyErrors } from '../../utils/error-map'; +import { StarlightConfigSchema, type StarlightUserConfig } from '../../utils/user-config'; + +function parseStarlightConfigWithFriendlyErrors(config: StarlightUserConfig) { + return parseWithFriendlyErrors( + StarlightConfigSchema, + config, + 'Invalid config passed to starlight integration' + ); +} + +test('parses bare minimum valid config successfully', () => { + const data = parseStarlightConfigWithFriendlyErrors({ title: '' }); + expect(data).toMatchInlineSnapshot(` + { + "components": { + "Banner": "@astrojs/starlight/components/Banner.astro", + "ContentPanel": "@astrojs/starlight/components/ContentPanel.astro", + "DraftContentNotice": "@astrojs/starlight/components/DraftContentNotice.astro", + "EditLink": "@astrojs/starlight/components/EditLink.astro", + "FallbackContentNotice": "@astrojs/starlight/components/FallbackContentNotice.astro", + "Footer": "@astrojs/starlight/components/Footer.astro", + "Head": "@astrojs/starlight/components/Head.astro", + "Header": "@astrojs/starlight/components/Header.astro", + "Hero": "@astrojs/starlight/components/Hero.astro", + "LanguageSelect": "@astrojs/starlight/components/LanguageSelect.astro", + "LastUpdated": "@astrojs/starlight/components/LastUpdated.astro", + "MarkdownContent": "@astrojs/starlight/components/MarkdownContent.astro", + "MobileMenuFooter": "@astrojs/starlight/components/MobileMenuFooter.astro", + "MobileMenuToggle": "@astrojs/starlight/components/MobileMenuToggle.astro", + "MobileTableOfContents": "@astrojs/starlight/components/MobileTableOfContents.astro", + "PageFrame": "@astrojs/starlight/components/PageFrame.astro", + "PageSidebar": "@astrojs/starlight/components/PageSidebar.astro", + "PageTitle": "@astrojs/starlight/components/PageTitle.astro", + "Pagination": "@astrojs/starlight/components/Pagination.astro", + "Search": "@astrojs/starlight/components/Search.astro", + "Sidebar": "@astrojs/starlight/components/Sidebar.astro", + "SiteTitle": "@astrojs/starlight/components/SiteTitle.astro", + "SkipLink": "@astrojs/starlight/components/SkipLink.astro", + "SocialIcons": "@astrojs/starlight/components/SocialIcons.astro", + "TableOfContents": "@astrojs/starlight/components/TableOfContents.astro", + "ThemeProvider": "@astrojs/starlight/components/ThemeProvider.astro", + "ThemeSelect": "@astrojs/starlight/components/ThemeSelect.astro", + "TwoColumnContent": "@astrojs/starlight/components/TwoColumnContent.astro", + }, + "credits": false, + "customCss": [], + "defaultLocale": { + "dir": "ltr", + "label": "English", + "lang": "en", + "locale": undefined, + }, + "disable404Route": false, + "editLink": {}, + "favicon": { + "href": "/favicon.svg", + "type": "image/svg+xml", + }, + "head": [], + "isMultilingual": false, + "isUsingBuiltInDefaultLocale": true, + "lastUpdated": false, + "locales": undefined, + "markdown": { + "headingLinks": true, + "processedDirs": [], + }, + "pagefind": { + "ranking": { + "pageLength": 0.1, + "termFrequency": 0.1, + "termSaturation": 2, + "termSimilarity": 9, + }, + }, + "pagination": true, + "prerender": true, + "routeMiddleware": [], + "tableOfContents": { + "maxHeadingLevel": 3, + "minHeadingLevel": 2, + }, + "title": { + "en": "", + }, + "titleDelimiter": "|", + } + `); +}); + +test('errors if title is missing', () => { + expect(() => + // @ts-expect-error - Testing invalid config + parseStarlightConfigWithFriendlyErrors({}) + ).toThrowErrorMatchingInlineSnapshot( + ` + "[AstroUserError]: + Invalid config passed to starlight integration + Hint: + **title**: Did not match union. + > Required" + ` + ); +}); + +test('errors if title value is not a string or an Object', () => { + expect(() => + // @ts-expect-error - Testing invalid config + parseStarlightConfigWithFriendlyErrors({ title: 5 }) + ).toThrowErrorMatchingInlineSnapshot( + ` + "[AstroUserError]: + Invalid config passed to starlight integration + Hint: + **title**: Did not match union. + > Expected type \`"string" | "object"\`, received \`"number"\`" + ` + ); +}); + +test('errors with bad social icon config', () => { + expect(() => + // @ts-expect-error - Testing invalid config + parseStarlightConfigWithFriendlyErrors({ title: 'Test', social: { unknown: '' } }) + ).toThrowErrorMatchingInlineSnapshot( + ` + "[AstroUserError]: + Invalid config passed to starlight integration + Hint: + Starlight v0.33.0 changed the \`social\` configuration syntax. Please specify an array of link items instead of an object. + See the Starlight changelog for details: https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md#0330 + + **social**: Expected type \`"array"\`, received \`"object"\`" + ` + ); +}); + +test('errors with bad logo config', () => { + expect(() => + // @ts-expect-error - Testing invalid config + parseStarlightConfigWithFriendlyErrors({ title: 'Test', logo: { html: '' } }) + ).toThrowErrorMatchingInlineSnapshot( + ` + "[AstroUserError]: + Invalid config passed to starlight integration + Hint: + **logo**: Did not match union. + > Expected type \`{ src: string } | { dark: string; light: string }\` + > Received \`{ "html": "" }\`" + ` + ); +}); + +test('errors with bad head config', () => { + expect(() => + parseStarlightConfigWithFriendlyErrors({ + title: 'Test', + // @ts-expect-error - Testing invalid config + head: [{ tag: 'unknown', attrs: { prop: null }, content: 20 }], + }) + ).toThrowErrorMatchingInlineSnapshot( + ` + "[AstroUserError]: + Invalid config passed to starlight integration + Hint: + **head.0.tag**: Invalid enum value. Expected 'title' | 'base' | 'link' | 'style' | 'meta' | 'script' | 'noscript' | 'template', received 'unknown' + **head.0.attrs.prop**: Did not match union. + > Expected type \`"string" | "boolean" | "undefined"\`, received \`"null"\` + **head.0.content**: Expected type \`"string"\`, received \`"number"\`" + ` + ); +}); + +test('errors with bad sidebar config', () => { + expect(() => + parseStarlightConfigWithFriendlyErrors({ + title: 'Test', + // @ts-expect-error - Testing invalid config + sidebar: [{ label: 'Example', href: '/' }], + }) + ).toThrowErrorMatchingInlineSnapshot( + ` + "[AstroUserError]: + Invalid config passed to starlight integration + Hint: + **sidebar.0**: Did not match union. + > Expected type \`{ link: string; } | { items: array; } | { autogenerate: object; } | { slug: string } | string\` + > Received \`{ "label": "Example", "href": "/" }\`" + ` + ); +}); + +test('errors with bad nested sidebar config', () => { + expect(() => + parseStarlightConfigWithFriendlyErrors({ + title: 'Test', + sidebar: [ + { + label: 'Example', + items: [ + { label: 'Nested Example 1', link: '/' }, + // @ts-expect-error - Testing invalid config + { label: 'Nested Example 2', link: true }, + ], + }, + ], + }) + ).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Invalid config passed to starlight integration + Hint: + **sidebar.0.items.1**: Did not match union. + > Expected type \`{ link: string } | { items: array; } | { autogenerate: object; } | { slug: string } | string\` + > Received \`{ "label": "Example", "items": [ { "label": "Nested Example 1", "link": "/" }, { "label": "Nested Example 2", "link": true } ] }\`" + `); +}); + +test('errors with sidebar entry that includes `link` and `items`', () => { + expect(() => + parseStarlightConfigWithFriendlyErrors({ + title: 'Test', + sidebar: [ + { label: 'Parent', link: '/parent', items: [{ label: 'Child', link: '/parent/child' }] }, + ], + }) + ).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Invalid config passed to starlight integration + Hint: + **sidebar.0**: Unrecognized key(s) in object: 'items'" + `); +}); + +test('errors with sidebar entry that includes `link` and `autogenerate`', () => { + expect(() => + parseStarlightConfigWithFriendlyErrors({ + title: 'Test', + sidebar: [{ label: 'Parent', link: '/parent', autogenerate: { directory: 'test' } }], + }) + ).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Invalid config passed to starlight integration + Hint: + **sidebar.0**: Unrecognized key(s) in object: 'autogenerate'" + `); +}); + +test('errors with sidebar entry that includes `items` and `autogenerate`', () => { + expect(() => + parseStarlightConfigWithFriendlyErrors({ + title: 'Test', + sidebar: [ + { + label: 'Parent', + items: [{ label: 'Child', link: '/parent/child' }], + autogenerate: { directory: 'test' }, + }, + ], + }) + ).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Invalid config passed to starlight integration + Hint: + **sidebar.0**: Unrecognized key(s) in object: 'autogenerate'" + `); +}); + +test('parses route middleware config successfully', () => { + const data = parseStarlightConfigWithFriendlyErrors({ + title: '', + routeMiddleware: './src/routeData.ts', + }); + expect(data.routeMiddleware).toEqual(['./src/routeData.ts']); +}); + +test('errors if a route middleware path will conflict with Astro middleware', () => { + expect(() => + parseStarlightConfigWithFriendlyErrors({ + title: 'Test', + routeMiddleware: ['./src/middleware.ts', './src/routeData.ts'], + }) + ).toThrowErrorMatchingInlineSnapshot( + ` + "[AstroUserError]: + Invalid config passed to starlight integration + Hint: + The \`"./src/middleware.ts"\` path in your Starlight \`routeMiddleware\` config conflicts with Astro’s middleware locations. + + You should rename \`./src/middleware.ts\` to something else like \`./src/starlightRouteData.ts\` and update the \`routeMiddleware\` file path to match. + + - More about Starlight route middleware: https://starlight.astro.build/guides/route-data/#how-to-customize-route-data + - More about Astro middleware: https://docs.astro.build/en/guides/middleware/" + ` + ); +}); + +test('errors if an invalid customCss file path is provided', () => { + expect(() => + parseStarlightConfigWithFriendlyErrors({ + title: 'Test', + customCss: ['./public/styles.css', '/public/other-styles.css'], + }) + ).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Invalid config passed to starlight integration + Hint: + These paths in your Starlight \`customCss\` config are invalid: \`"./public/styles.css"\`, \`"/public/other-styles.css"\` + + CSS files specified in \`customCss\` should be in the \`src/\` directory, not the \`public/\` directory. + + You should move these CSS files into the \`src/\` directory and update the path in \`customCss\` to match." + `); +}); diff --git a/packages/starlight/__tests__/basics/config.test-d.ts b/packages/starlight/__tests__/basics/config.test-d.ts new file mode 100644 index 00000000000..8e1e4ebf1d9 --- /dev/null +++ b/packages/starlight/__tests__/basics/config.test-d.ts @@ -0,0 +1,51 @@ +import { describe, expectTypeOf, test } from 'vitest'; +import type { StarlightUserConfig } from '../../utils/user-config'; + +describe('sidebar', () => { + test('emits a type error for custom attributes on groups', () => { + type SidebarUserItem = NonNullable[number]; + + // Links + expectTypeOf('getting-started').toExtend(); + expectTypeOf({ slug: 'getting-started' }).toExtend(); + expectTypeOf({ + label: 'Getting Started', + link: '/getting-started/', + }).toExtend(); + + // Groups + expectTypeOf({ + label: 'References', + items: [], + }).toExtend(); + expectTypeOf({ + label: 'References', + autogenerate: { directory: 'references' }, + }).toExtend(); + + // Links with attributes + expectTypeOf({ + slug: 'getting-started', + attrs: { class: 'test' }, + }).toExtend(); + expectTypeOf({ + label: 'Getting Started', + link: '/getting-started/', + attrs: { class: 'test' }, + }).toExtend(); + + // Groups with attributes which are not supported + expectTypeOf({ + label: 'References', + items: [], + attrs: { class: 'test' }, + // @ts-expect-error - Attributes are not supported on groups + }).toExtend(); + expectTypeOf({ + label: 'References', + autogenerate: { directory: 'references' }, + attrs: { class: 'test' }, + // @ts-expect-error - Attributes are not supported on groups + }).toExtend(); + }); +}); diff --git a/packages/starlight/__tests__/basics/config.test.ts b/packages/starlight/__tests__/basics/config.test.ts index 43293c825b5..1d5852ac9ef 100644 --- a/packages/starlight/__tests__/basics/config.test.ts +++ b/packages/starlight/__tests__/basics/config.test.ts @@ -2,7 +2,7 @@ import config from 'virtual:starlight/user-config'; import { expect, test } from 'vitest'; test('test suite is using correct env', () => { - expect(config.title).toBe('Basics'); + expect(config.title).toMatchObject({ en: 'Basics' }); }); test('isMultilingual is false when no locales configured ', () => { diff --git a/packages/starlight/__tests__/basics/format-canonical.test.ts b/packages/starlight/__tests__/basics/format-canonical.test.ts new file mode 100644 index 00000000000..83dd6cd1e04 --- /dev/null +++ b/packages/starlight/__tests__/basics/format-canonical.test.ts @@ -0,0 +1,75 @@ +import { describe, expect, test } from 'vitest'; +import { formatCanonical, type FormatCanonicalOptions } from '../../utils/canonical'; + +describe.each<{ + options: FormatCanonicalOptions; + tests: Array<{ href: string; expected: string }>; +}>([ + { + options: { format: 'file', trailingSlash: 'ignore' }, + tests: [ + { href: 'https://example.com/index.html', expected: 'https://example.com/index.html' }, + { + href: 'https://example.com/reference/configuration.html', + expected: 'https://example.com/reference/configuration.html', + }, + ], + }, + { + options: { format: 'file', trailingSlash: 'always' }, + tests: [ + { href: 'https://example.com/index.html', expected: 'https://example.com/index.html' }, + { + href: 'https://example.com/reference/configuration.html', + expected: 'https://example.com/reference/configuration.html', + }, + ], + }, + { + options: { format: 'file', trailingSlash: 'never' }, + tests: [ + { href: 'https://example.com/index.html', expected: 'https://example.com/index.html' }, + { + href: 'https://example.com/reference/configuration.html', + expected: 'https://example.com/reference/configuration.html', + }, + ], + }, + { + options: { format: 'directory', trailingSlash: 'always' }, + tests: [ + { href: 'https://example.com/', expected: 'https://example.com/' }, + { + href: 'https://example.com/reference/configuration/', + expected: 'https://example.com/reference/configuration/', + }, + ], + }, + { + options: { format: 'directory', trailingSlash: 'never' }, + tests: [ + { href: 'https://example.com/', expected: 'https://example.com' }, + { + href: 'https://example.com/reference/configuration/', + expected: 'https://example.com/reference/configuration', + }, + ], + }, + { + options: { format: 'directory', trailingSlash: 'ignore' }, + tests: [ + { href: 'https://example.com/', expected: 'https://example.com/' }, + { + href: 'https://example.com/reference/configuration/', + expected: 'https://example.com/reference/configuration/', + }, + ], + }, +])( + 'formatCanonical() with { format: $options.format, trailingSlash: $options.trailingSlash }', + ({ options, tests }) => { + test.each(tests)('returns $expected for $href', ({ href, expected }) => { + expect(formatCanonical(href, options)).toBe(expected); + }); + } +); diff --git a/packages/starlight/__tests__/basics/format-path.test.ts b/packages/starlight/__tests__/basics/format-path.test.ts new file mode 100644 index 00000000000..0a148404230 --- /dev/null +++ b/packages/starlight/__tests__/basics/format-path.test.ts @@ -0,0 +1,139 @@ +import { describe, expect, test, vi } from 'vitest'; +import { createPathFormatter } from '../../utils/createPathFormatter'; + +type FormatPathOptions = Parameters[0]; +const formatPath = (href: string, opts: FormatPathOptions) => createPathFormatter(opts)(href); + +describe.each<{ + options: FormatPathOptions; + tests: Array<{ path: string; base?: string; expected: string }>; +}>([ + { + options: { format: 'file', trailingSlash: 'ignore' }, + tests: [ + // index page + { path: '/', expected: '/index.html' }, + // index page with base + { path: '/', base: '/base/', expected: '/base/index.html' }, + // with trailing slash + { path: '/reference/configuration/', expected: '/reference/configuration.html' }, + // without trailing slash + { path: '/api/v1/users', expected: '/api/v1/users.html' }, + // with file extension + { path: '/guides/project-structure.html', expected: '/guides/project-structure.html' }, + // with file extension and trailing slash + { path: '/guides/project-structure.html/', expected: '/guides/project-structure.html' }, + ], + }, + { + options: { format: 'file', trailingSlash: 'always' }, + tests: [ + // index page + { path: '/', expected: '/index.html' }, + // index page with base + { path: '/', base: '/base/', expected: '/base/index.html' }, + // with trailing slash + { path: '/reference/configuration/', expected: '/reference/configuration.html' }, + // without trailing slash + { path: '/api/v1/users', expected: '/api/v1/users.html' }, + // with file extension + { path: '/guides/project-structure.html', expected: '/guides/project-structure.html' }, + // with file extension and trailing slash + { path: '/guides/project-structure.html/', expected: '/guides/project-structure.html' }, + ], + }, + { + options: { format: 'file', trailingSlash: 'never' }, + tests: [ + // index page + { path: '/', expected: '/index.html' }, + // index page with base + { path: '/', base: '/base/', expected: '/base/index.html' }, + // with trailing slash + { path: '/reference/configuration/', expected: '/reference/configuration.html' }, + // without trailing slash + { path: '/api/v1/users', expected: '/api/v1/users.html' }, + // with file extension + { path: '/guides/project-structure.html', expected: '/guides/project-structure.html' }, + // with file extension and trailing slash + { path: '/guides/project-structure.html/', expected: '/guides/project-structure.html' }, + ], + }, + { + options: { format: 'directory', trailingSlash: 'always' }, + tests: [ + // index page + { path: '/', expected: '/' }, + // index page with base + { path: '/', base: '/base/', expected: '/base/' }, + // with trailing slash + { path: '/reference/configuration/', expected: '/reference/configuration/' }, + // without trailing slash + { path: '/api/v1/users', expected: '/api/v1/users/' }, + // with file extension + { path: '/guides/project-structure.html', expected: '/guides/project-structure/' }, + // with file extension and trailing slash + { path: '/guides/project-structure.html/', expected: '/guides/project-structure/' }, + ], + }, + { + options: { format: 'directory', trailingSlash: 'never' }, + tests: [ + // index page + { path: '/', expected: '/' }, + // index page with base + { path: '/', base: '/base/', expected: '/base' }, + // with trailing slash + { path: '/reference/configuration/', expected: '/reference/configuration' }, + // without trailing slash + { path: '/api/v1/users', expected: '/api/v1/users' }, + // with file extension + { path: '/guides/project-structure.html', expected: '/guides/project-structure' }, + // with file extension and trailing slash + { path: '/guides/project-structure.html/', expected: '/guides/project-structure' }, + ], + }, + { + options: { format: 'directory', trailingSlash: 'ignore' }, + tests: [ + // index page + { path: '/', expected: '/' }, + // index page with base + { path: '/', base: '/base/', expected: '/base/' }, + // with trailing slash + { path: '/reference/configuration/', expected: '/reference/configuration/' }, + // without trailing slash + { path: '/api/v1/users', expected: '/api/v1/users' }, + // with file extension + { path: '/guides/project-structure.html', expected: '/guides/project-structure' }, + // with file extension and trailing slash + { path: '/guides/project-structure.html/', expected: '/guides/project-structure' }, + ], + }, +])( + 'formatPath() with { format: $options.format, trailingSlash: $options.trailingSlash }', + ({ options, tests }) => { + test.each(tests)('returns $expected for $path', async ({ path, base, expected }) => { + // If the base is not set, test the path formatter and end the test. + if (!base) { + expect(formatPath(path, options)).toBe(expected); + return; + } + + // Otherwise, reset the modules registry so that re-importing `../../utils/createPathFormatter` + // re-evaluates the module and re-computes the base. Re-importing the module is necessary + // because top-level imports cannot be re-evaluated. + vi.resetModules(); + // Set the base URL. + vi.stubEnv('BASE_URL', base); + // Re-import the module to re-create the path formatter. + const { createPathFormatter } = await import('../../utils/createPathFormatter'); + const formatPathWithBase: typeof formatPath = (href, opts) => createPathFormatter(opts)(href); + + expect(formatPathWithBase(path, options)).toBe(expected); + + vi.unstubAllEnvs(); + vi.resetModules(); + }); + } +); diff --git a/packages/starlight/__tests__/basics/git.test.ts b/packages/starlight/__tests__/basics/git.test.ts new file mode 100644 index 00000000000..0f88eb427f2 --- /dev/null +++ b/packages/starlight/__tests__/basics/git.test.ts @@ -0,0 +1,160 @@ +import { assert, describe, expect, test } from 'vitest'; +import { + getAllNewestCommitDate, + getNewestCommitDate, + makeAPI as makeLiveGitAPI, +} from '../../utils/git'; +import { makeAPI as makeInlineGitAPI } from '../../utils/gitInlined'; +import { makeTestRepo, type ISODate } from '../git-utils'; + +describe('getNewestCommitDate', () => { + const { commitAllChanges, getFilePath, writeFile } = makeTestRepo(); + + test('returns the newest commit date', () => { + const file = 'updated.md'; + const lastCommitDate = '2023-06-25'; + + writeFile(file, 'content 0'); + commitAllChanges('add updated.md', '2023-06-21'); + writeFile(file, 'content 1'); + commitAllChanges('update updated.md', lastCommitDate); + + expectCommitDateToEqual(getNewestCommitDate(getFilePath(file)), lastCommitDate); + }); + + test('returns the newest commit date from the wrapped API', () => { + const api = makeLiveGitAPI(getFilePath('')); + + const file = 'updated.md'; + const lastCommitDate = '2023-06-25'; + + writeFile(file, 'content 0'); + commitAllChanges('add updated.md', '2023-06-21'); + writeFile(file, 'content 1'); + commitAllChanges('update updated.md', lastCommitDate); + + expectCommitDateToEqual(api.getNewestCommitDate(file), lastCommitDate); + }); + + test('returns the initial commit date for a file never updated', () => { + const file = 'added.md'; + const commitDate = '2022-09-18'; + + writeFile(file, 'content'); + commitAllChanges('add added.md', commitDate); + + expectCommitDateToEqual(getNewestCommitDate(getFilePath(file)), commitDate); + }); + + test('returns the newest commit date for a file with a name that contains a space', () => { + const file = 'updated with space.md'; + const lastCommitDate = '2021-01-02'; + + writeFile(file, 'content 0'); + commitAllChanges('add updated.md', '2021-01-01'); + writeFile(file, 'content 1'); + commitAllChanges('update updated.md', lastCommitDate); + + expectCommitDateToEqual(getNewestCommitDate(getFilePath(file)), lastCommitDate); + }); + + test('returns the newest commit date for a file updated the same day', () => { + const file = 'updated-same-day.md'; + const lastCommitDate = '2023-06-25T14:22:35Z'; + + writeFile(file, 'content 0'); + commitAllChanges('add updated.md', '2023-06-25T12:34:56Z'); + writeFile(file, 'content 1'); + commitAllChanges('update updated.md', lastCommitDate); + + expectCommitDateToEqual(getNewestCommitDate(getFilePath(file)), lastCommitDate); + }); + + test('throws when failing to retrieve the git history for a file', () => { + expect(() => getNewestCommitDate(getFilePath('../not-a-starlight-test-repo/test.md'))).toThrow( + /^Failed to retrieve the git history for file "[/\\:-\w ]+[/\\]test\.md"/ + ); + }); + + test('throws when trying to get the history of a non-existing or untracked file', () => { + const expectedError = + /^Failed to validate the timestamp for file "[/\\:-\w ]+[/\\](?:unknown|untracked)\.md"$/; + writeFile('untracked.md', 'content'); + + expect(() => getNewestCommitDate(getFilePath('unknown.md'))).toThrow(expectedError); + expect(() => getNewestCommitDate(getFilePath('untracked.md'))).toThrow(expectedError); + }); +}); + +describe('getAllNewestCommitDate', () => { + const { commitAllChanges, getRepoPath, getFilePath, writeFile } = makeTestRepo(); + + test('returns the newest commit date', () => { + writeFile('added.md', 'content'); + commitAllChanges('add added.md', '2022-09-18'); + + writeFile('updated.md', 'content 0'); + commitAllChanges('add updated.md', '2023-06-21'); + writeFile('updated.md', 'content 1'); + commitAllChanges('update updated.md', '2023-06-25'); + + writeFile('updated with space.md', 'content 0'); + commitAllChanges('add updated.md', '2021-01-01'); + writeFile('updated with space.md', 'content 1'); + commitAllChanges('update updated.md', '2021-01-02'); + + writeFile('updated-same-day.md', 'content 0'); + commitAllChanges('add updated.md', '2023-06-25T12:34:56Z'); + writeFile('updated-same-day.md', 'content 1'); + commitAllChanges('update updated.md', '2023-06-25T14:22:35Z'); + + const latestDates = new Map(getAllNewestCommitDate(getRepoPath(), getFilePath(''))); + + const expectedDates = new Map([ + ['added.md', '2022-09-18'], + ['updated.md', '2023-06-25'], + ['updated with space.md', '2021-01-02'], + ['updated-same-day.md', '2023-06-25T14:22:35Z'], + ]); + + for (const [file, date] of latestDates.entries()) { + const expectedDate = expectedDates.get(file); + assert.ok(expectedDate, `Unexpected tracked file: ${file}`); + expectCommitDateToEqual(new Date(date), expectedDate); + } + + for (const file of expectedDates.keys()) { + const latestDate = latestDates.get(file); + assert.ok(latestDate, `Missing tracked file: ${file}`); + } + }); + + test('returns the newest commit date from inlined API', () => { + const api = makeInlineGitAPI(getAllNewestCommitDate(getRepoPath(), getFilePath(''))); + + const expectedDates = new Map([ + ['added.md', '2022-09-18'], + ['updated.md', '2023-06-25'], + ['updated with space.md', '2021-01-02'], + ['updated-same-day.md', '2023-06-25T14:22:35Z'], + ]); + + for (const [file, expectedDate] of expectedDates.entries()) { + const latestDate = api.getNewestCommitDate(file); + expectCommitDateToEqual(latestDate, expectedDate); + } + }); + + test('returns an empty list when the git history for the directory cannot be retrieved', () => { + expect( + getAllNewestCommitDate(getRepoPath(), getFilePath('../not-a-starlight-test-repo')) + ).toStrictEqual([]); + }); +}); + +function expectCommitDateToEqual(commitDate: CommitDate, expectedDateStr: ISODate) { + const expectedDate = new Date(expectedDateStr); + expect(commitDate).toStrictEqual(expectedDate); +} + +type CommitDate = ReturnType; diff --git a/packages/starlight/__tests__/basics/head.test.ts b/packages/starlight/__tests__/basics/head.test.ts deleted file mode 100644 index db5a454b738..00000000000 --- a/packages/starlight/__tests__/basics/head.test.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { describe, expect, test } from 'vitest'; -import { createHead } from '../../utils/head'; - -describe('createHead', () => { - test('merges two tags', () => { - expect( - createHead( - [{ tag: 'title', content: 'Default' }], - [{ tag: 'title', content: 'Override', attrs: {} }] - ) - ).toEqual([{ tag: 'title', content: 'Override', attrs: {} }]); - }); - - for (const prop of ['name', 'property', 'http-equiv']) { - test(`merges two <meta> tags with same ${prop} value`, () => { - expect( - createHead( - [{ tag: 'meta', attrs: { [prop]: 'x', content: 'Default' } }], - [{ tag: 'meta', attrs: { [prop]: 'x', content: 'Test' }, content: '' }] - ) - ).toEqual([{ tag: 'meta', content: '', attrs: { [prop]: 'x', content: 'Test' } }]); - }); - } - - for (const prop of ['name', 'property', 'http-equiv']) { - test(`does not merge <meta> tags with different ${prop} values`, () => { - expect( - createHead( - [{ tag: 'meta', attrs: { [prop]: 'x', content: 'X' } }], - [{ tag: 'meta', attrs: { [prop]: 'y', content: 'Y' }, content: '' }] - ) - ).toEqual([ - { tag: 'meta', content: '', attrs: { [prop]: 'x', content: 'X' } }, - { tag: 'meta', content: '', attrs: { [prop]: 'y', content: 'Y' } }, - ]); - }); - } - - test('sorts head by tag importance', () => { - expect( - createHead([ - // SEO meta tags - { tag: 'meta', attrs: { name: 'x' } }, - // Others - { tag: 'link', attrs: { rel: 'stylesheet' } }, - // Important meta tags - { tag: 'meta', attrs: { charset: 'utf-8' } }, - { tag: 'meta', attrs: { name: 'viewport' } }, - { tag: 'meta', attrs: { 'http-equiv': 'x' } }, - // <title> - { tag: 'title', content: 'Title' }, - ]) - ).toEqual([ - // Important meta tags - { tag: 'meta', attrs: { charset: 'utf-8' }, content: '' }, - { tag: 'meta', attrs: { name: 'viewport' }, content: '' }, - { tag: 'meta', attrs: { 'http-equiv': 'x' }, content: '' }, - // <title> - { tag: 'title', attrs: {}, content: 'Title' }, - // Others - { tag: 'link', attrs: { rel: 'stylesheet' }, content: '' }, - // SEO meta tags - { tag: 'meta', attrs: { name: 'x' }, content: '' }, - ]); - }); - - test('places the default favicon below any user provided icons', () => { - const defaultFavicon = { - tag: 'link', - attrs: { - rel: 'shortcut icon', - href: '/favicon.svg', - type: 'image/svg+xml', - }, - } as const; - - const userFavicon = { - tag: 'link', - attrs: { - rel: 'icon', - href: '/favicon.ico', - sizes: '32x32', - }, - content: '', - } as const; - - expect(createHead([defaultFavicon], [userFavicon])).toMatchObject([ - userFavicon, - defaultFavicon, - ]); - }); -}); diff --git a/packages/starlight/__tests__/basics/i18n.test.ts b/packages/starlight/__tests__/basics/i18n.test.ts index 1ab6262fa6c..98e09205d40 100644 --- a/packages/starlight/__tests__/basics/i18n.test.ts +++ b/packages/starlight/__tests__/basics/i18n.test.ts @@ -1,5 +1,8 @@ -import { describe, expect, test } from 'vitest'; -import { pickLang } from '../../utils/i18n'; +import { assert, describe, expect, test, vi } from 'vitest'; +import config from 'virtual:starlight/user-config'; +import { processI18nConfig, pickLang } from '../../utils/i18n'; +import type { AstroConfig, AstroUserConfig } from 'astro'; +import type { StarlightConfig } from '../../types'; describe('pickLang', () => { const dictionary = { en: 'Hello', fr: 'Bonjour' }; @@ -10,6 +13,306 @@ describe('pickLang', () => { }); test('returns undefined for unknown languages', () => { - expect(pickLang(dictionary, 'ar' as any)).toBeUndefined(); + // @ts-expect-error - Testing unknown language + expect(pickLang(dictionary, 'ar')).toBeUndefined(); }); }); + +describe('processI18nConfig', () => { + test('returns the Astro i18n config for an unconfigured monolingual site using the built-in default locale', () => { + const { astroI18nConfig, starlightConfig } = processI18nConfig(config, undefined); + + expect(astroI18nConfig.defaultLocale).toBe('en'); + expect(astroI18nConfig.locales).toEqual(['en']); + assert(typeof astroI18nConfig.routing !== 'string'); + expect(astroI18nConfig.routing?.prefixDefaultLocale).toBe(false); + + // The Starlight configuration should not be modified. + expect(config).toStrictEqual(starlightConfig); + }); + + describe('with a provided Astro i18n config', () => { + test('throws an error when an Astro i18n `manual` routing option is used', () => { + expect(() => + processI18nConfig( + config, + getAstroI18nTestConfig({ + defaultLocale: 'en', + locales: ['en', 'fr'], + routing: 'manual', + }) + ) + ).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Starlight is not compatible with the \`manual\` routing option in the Astro i18n configuration. + Hint: + " + `); + }); + + test('throws an error when an Astro i18n config contains an invalid locale', () => { + expect(() => + processI18nConfig( + config, + getAstroI18nTestConfig({ + defaultLocale: 'en', + locales: ['en', 'foo'], + }) + ) + ).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Failed to get locale information for the 'foo' locale. + Hint: + Make sure to provide a valid BCP-47 tags (e.g. en, ar, or zh-CN)." + `); + }); + + type AstroI18nTestEachConfig = { + i18nConfig: AstroUserConfig['i18n']; + expected: { + defaultLocale: StarlightConfig['defaultLocale']; + locales?: StarlightConfig['locales']; + }; + }; + + test.each<AstroI18nTestEachConfig>([ + { + i18nConfig: { defaultLocale: 'en', locales: ['en'] }, + expected: { + defaultLocale: { label: 'English', lang: 'en', dir: 'ltr', locale: undefined }, + }, + }, + { + i18nConfig: { defaultLocale: 'fr', locales: [{ codes: ['fr'], path: 'fr' }] }, + expected: { + defaultLocale: { label: 'Français', lang: 'fr', dir: 'ltr', locale: undefined }, + }, + }, + { + i18nConfig: { + defaultLocale: 'fa', + locales: ['fa'], + routing: { prefixDefaultLocale: false }, + }, + expected: { + defaultLocale: { label: 'فارسی', lang: 'fa', dir: 'rtl', locale: undefined }, + }, + }, + ])( + 'updates the Starlight i18n config for a monolingual site with a single root locale', + ({ i18nConfig, expected }) => { + const astroI18nTestConfig = getAstroI18nTestConfig(i18nConfig); + + const { astroI18nConfig, starlightConfig } = processI18nConfig(config, astroI18nTestConfig); + + expect(starlightConfig.isMultilingual).toBe(false); + expect(starlightConfig.locales).not.toBeDefined(); + expect(starlightConfig.defaultLocale).toStrictEqual(expected.defaultLocale); + + // The Astro i18n configuration should not be modified. + expect(astroI18nConfig).toStrictEqual(astroI18nConfig); + } + ); + + test.each<AstroI18nTestEachConfig>([ + { + i18nConfig: { + defaultLocale: 'en', + locales: ['en'], + routing: { prefixDefaultLocale: true }, + }, + expected: { + defaultLocale: { label: 'English', lang: 'en', dir: 'ltr', locale: 'en' }, + locales: { en: { label: 'English', lang: 'en', dir: 'ltr' } }, + }, + }, + { + i18nConfig: { + defaultLocale: 'french', + locales: [{ codes: ['fr'], path: 'french' }], + routing: { prefixDefaultLocale: true }, + }, + expected: { + defaultLocale: { label: 'Français', lang: 'fr', dir: 'ltr', locale: 'fr' }, + locales: { french: { label: 'Français', lang: 'fr', dir: 'ltr' } }, + }, + }, + { + i18nConfig: { + defaultLocale: 'farsi', + locales: [{ codes: ['fa'], path: 'farsi' }], + routing: { prefixDefaultLocale: true }, + }, + expected: { + defaultLocale: { label: 'فارسی', lang: 'fa', dir: 'rtl', locale: 'fa' }, + locales: { farsi: { label: 'فارسی', lang: 'fa', dir: 'rtl' } }, + }, + }, + ])( + 'updates the Starlight i18n config for a monolingual site with a single non-root locale', + ({ i18nConfig, expected }) => { + const astroI18nTestConfig = getAstroI18nTestConfig(i18nConfig); + + const { astroI18nConfig, starlightConfig } = processI18nConfig(config, astroI18nTestConfig); + + expect(starlightConfig.isMultilingual).toBe(false); + expect(starlightConfig.locales).toStrictEqual(expected.locales); + expect(starlightConfig.defaultLocale).toStrictEqual(expected.defaultLocale); + + // The Astro i18n configuration should not be modified. + expect(astroI18nConfig).toStrictEqual(astroI18nConfig); + } + ); + + test.each<AstroI18nTestEachConfig>([ + { + i18nConfig: { + defaultLocale: 'en', + locales: ['en', { codes: ['fr'], path: 'french' }], + }, + expected: { + defaultLocale: { label: 'English', lang: 'en', dir: 'ltr', locale: undefined }, + locales: { + root: { label: 'English', lang: 'en', dir: 'ltr' }, + french: { label: 'Français', lang: 'fr', dir: 'ltr' }, + }, + }, + }, + { + i18nConfig: { + defaultLocale: 'farsi', + // This configuration is a bit confusing as `prefixDefaultLocale` is `false` but the + // default locale is defined with a custom path. + // In this case, the default locale is considered to be a root locale and the custom path + // is ignored. + locales: [{ codes: ['fa'], path: 'farsi' }, 'de'], + routing: { prefixDefaultLocale: false }, + }, + expected: { + defaultLocale: { label: 'فارسی', lang: 'fa', dir: 'rtl', locale: undefined }, + locales: { + root: { label: 'فارسی', lang: 'fa', dir: 'rtl' }, + de: { label: 'Deutsch', lang: 'de', dir: 'ltr' }, + }, + }, + }, + ])( + 'updates the Starlight i18n config for a multilingual site with a root locale', + ({ i18nConfig, expected }) => { + const astroI18nTestConfig = getAstroI18nTestConfig(i18nConfig); + + const { astroI18nConfig, starlightConfig } = processI18nConfig(config, astroI18nTestConfig); + + expect(starlightConfig.isMultilingual).toBe(true); + expect(starlightConfig.locales).toEqual(expected.locales); + expect(starlightConfig.defaultLocale).toEqual(expected.defaultLocale); + + // The Astro i18n configuration should not be modified. + expect(astroI18nConfig).toEqual(astroI18nConfig); + } + ); + + test.each<AstroI18nTestEachConfig>([ + { + i18nConfig: { + defaultLocale: 'en', + locales: ['en', { codes: ['fr'], path: 'french' }], + routing: { prefixDefaultLocale: true }, + }, + expected: { + defaultLocale: { label: 'English', lang: 'en', dir: 'ltr', locale: 'en' }, + locales: { + en: { label: 'English', lang: 'en', dir: 'ltr' }, + french: { label: 'Français', lang: 'fr', dir: 'ltr' }, + }, + }, + }, + { + i18nConfig: { + defaultLocale: 'farsi', + locales: [{ codes: ['fa'], path: 'farsi' }, 'de'], + routing: { prefixDefaultLocale: true }, + }, + expected: { + defaultLocale: { label: 'فارسی', lang: 'fa', dir: 'rtl', locale: 'fa' }, + locales: { + farsi: { label: 'فارسی', lang: 'fa', dir: 'rtl' }, + de: { label: 'Deutsch', lang: 'de', dir: 'ltr' }, + }, + }, + }, + ])( + 'updates the Starlight i18n config for a multilingual site with no root locale', + ({ i18nConfig, expected }) => { + const astroI18nTestConfig = getAstroI18nTestConfig(i18nConfig); + + const { astroI18nConfig, starlightConfig } = processI18nConfig(config, astroI18nTestConfig); + + expect(starlightConfig.isMultilingual).toBe(true); + expect(starlightConfig.locales).toEqual(expected.locales); + expect(starlightConfig.defaultLocale).toEqual(expected.defaultLocale); + + // The Astro i18n configuration should not be modified. + expect(astroI18nConfig).toEqual(astroI18nConfig); + } + ); + }); +}); + +describe('getLocaleDir', () => { + test('uses the Node.js implementation to figure out the text direction', () => { + const { starlightConfig } = processI18nConfig( + config, + getAstroI18nTestConfig({ + defaultLocale: 'en', + locales: ['en'], + }) + ); + + expect(starlightConfig.defaultLocale.dir).toBe('ltr'); + }); + + test('uses `getTextInfo()` when `textInfo` is not available', () => { + // @ts-expect-error - `getTextInfo` is not typed but is available in some non-v8 based environments. + vi.spyOn(global.Intl, 'Locale').mockImplementation(() => ({ + getTextInfo: () => ({ direction: 'rtl' }), + })); + + const { starlightConfig } = processI18nConfig( + config, + getAstroI18nTestConfig({ + defaultLocale: 'en', + locales: ['en'], + }) + ); + + expect(starlightConfig.defaultLocale.dir).toBe('rtl'); + }); + + test('fallbacks to a list of well-known RTL languages when `textInfo` and `getTextInfo()` are not available', () => { + // @ts-expect-error - We are simulating the absence of `textInfo` and `getTextInfo()`. + vi.spyOn(global.Intl, 'Locale').mockImplementation((tag) => ({ language: tag })); + + const { starlightConfig } = processI18nConfig( + config, + getAstroI18nTestConfig({ + defaultLocale: 'en', + locales: ['en', 'fa'], + }) + ); + + expect(starlightConfig.defaultLocale.dir).toBe('ltr'); + expect(starlightConfig.locales?.root?.dir).toBe('ltr'); + expect(starlightConfig.locales?.fa?.dir).toBe('rtl'); + }); +}); + +function getAstroI18nTestConfig(i18nConfig: AstroUserConfig['i18n']): AstroConfig['i18n'] { + return { + ...i18nConfig, + routing: + typeof i18nConfig?.routing !== 'string' + ? { prefixDefaultLocale: false, fallbackType: 'redirect', ...i18nConfig?.routing } + : i18nConfig.routing, + } as AstroConfig['i18n']; +} diff --git a/packages/starlight/__tests__/basics/localizedUrl.test.ts b/packages/starlight/__tests__/basics/localizedUrl.test.ts index 0c56a2915fc..480699cde73 100644 --- a/packages/starlight/__tests__/basics/localizedUrl.test.ts +++ b/packages/starlight/__tests__/basics/localizedUrl.test.ts @@ -1,7 +1,26 @@ -import { expect, test } from 'vitest'; +import { describe, expect, test } from 'vitest'; import { localizedUrl } from '../../utils/localizedUrl'; -test('it has no effect in a monolingual project', () => { - const url = new URL('https://example.com/en/guide/'); - expect(localizedUrl(url, undefined).href).toBe(url.href); +describe('with `build.output: "directory"`', () => { + test('it has no effect in a monolingual project', () => { + const url = new URL('https://example.com/en/guide/'); + expect(localizedUrl(url, undefined, 'ignore').href).toBe(url.href); + }); + + test('has no effect on index route in a monolingual project', () => { + const url = new URL('https://example.com/'); + expect(localizedUrl(url, undefined, 'ignore').href).toBe(url.href); + }); +}); + +describe('with `build.output: "file"`', () => { + test('it has no effect in a monolingual project', () => { + const url = new URL('https://example.com/en/guide.html'); + expect(localizedUrl(url, undefined, 'ignore').href).toBe(url.href); + }); + + test('has no effect on index route in a monolingual project', () => { + const url = new URL('https://example.com/index.html'); + expect(localizedUrl(url, undefined, 'ignore').href).toBe(url.href); + }); }); diff --git a/packages/starlight/__tests__/basics/navigation-labels.test.ts b/packages/starlight/__tests__/basics/navigation-labels.test.ts index f51cac35b63..7784c04b00f 100644 --- a/packages/starlight/__tests__/basics/navigation-labels.test.ts +++ b/packages/starlight/__tests__/basics/navigation-labels.test.ts @@ -9,8 +9,11 @@ vi.mock('astro:content', async () => 'environmental-impact.md', { title: 'Eco-friendly docs', sidebar: { label: 'Environmental impact' } }, ], - ['guides/authoring-content.md', { title: 'Authoring Markdown' }], - ['guides/components.mdx', { title: 'Using components', sidebar: { label: 'Components' } }], + ['guides/authoring-content.mdx', { title: 'Authoring Markdown' }], + [ + 'guides/project-structure.mdx', + { title: 'Project Structure', sidebar: { label: 'Structure' } }, + ], ], }) ); @@ -20,6 +23,7 @@ describe('getSidebar', () => { expect(getSidebar('/', undefined)).toMatchInlineSnapshot(` [ { + "attrs": {}, "badge": undefined, "href": "/", "isCurrent": true, @@ -27,6 +31,7 @@ describe('getSidebar', () => { "type": "link", }, { + "attrs": {}, "badge": undefined, "href": "/environmental-impact/", "isCurrent": false, @@ -34,9 +39,11 @@ describe('getSidebar', () => { "type": "link", }, { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, "badge": undefined, "href": "/guides/authoring-content/", "isCurrent": false, @@ -44,10 +51,11 @@ describe('getSidebar', () => { "type": "link", }, { + "attrs": {}, "badge": undefined, - "href": "/guides/components/", + "href": "/guides/project-structure/", "isCurrent": false, - "label": "Components", + "label": "Structure", "type": "link", }, ], diff --git a/packages/starlight/__tests__/basics/navigation-order.test.ts b/packages/starlight/__tests__/basics/navigation-order.test.ts index 2eb2c88d734..f1935e7c208 100644 --- a/packages/starlight/__tests__/basics/navigation-order.test.ts +++ b/packages/starlight/__tests__/basics/navigation-order.test.ts @@ -6,8 +6,8 @@ vi.mock('astro:content', async () => docs: [ ['index.mdx', { title: 'Home Page' }], ['environmental-impact.md', { title: 'Eco-friendly docs', sidebar: { order: 1 } }], - ['guides/authoring-content.md', { title: 'Authoring Markdown' }], - ['guides/components.mdx', { title: 'Components', sidebar: { order: 0 } }], + ['guides/authoring-content.mdx', { title: 'Authoring Markdown' }], + ['guides/project-structure.mdx', { title: 'Project Structure', sidebar: { order: 0 } }], ], }) ); @@ -17,16 +17,19 @@ describe('getSidebar', () => { expect(getSidebar('/', undefined)).toMatchInlineSnapshot(` [ { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, "badge": undefined, - "href": "/guides/components/", + "href": "/guides/project-structure/", "isCurrent": false, - "label": "Components", + "label": "Project Structure", "type": "link", }, { + "attrs": {}, "badge": undefined, "href": "/guides/authoring-content/", "isCurrent": false, @@ -38,6 +41,7 @@ describe('getSidebar', () => { "type": "group", }, { + "attrs": {}, "badge": undefined, "href": "/environmental-impact/", "isCurrent": false, @@ -45,6 +49,7 @@ describe('getSidebar', () => { "type": "link", }, { + "attrs": {}, "badge": undefined, "href": "/", "isCurrent": true, diff --git a/packages/starlight/__tests__/basics/navigation.test.ts b/packages/starlight/__tests__/basics/navigation.test.ts index 023edb766eb..0b4e5bd7d4e 100644 --- a/packages/starlight/__tests__/basics/navigation.test.ts +++ b/packages/starlight/__tests__/basics/navigation.test.ts @@ -6,9 +6,10 @@ vi.mock('astro:content', async () => docs: [ ['index.mdx', { title: 'Home Page' }], ['environmental-impact.md', { title: 'Eco-friendly docs' }], - ['guides/authoring-content.md', { title: 'Authoring Markdown' }], + ['guides/authoring-content.mdx', { title: 'Authoring Markdown' }], ['reference/frontmatter.md', { title: 'Frontmatter Reference', sidebar: { hidden: true } }], - ['guides/components.mdx', { title: 'Components' }], + ['guides/project-structure.mdx', { title: 'Project Structure' }], + ['Getting Started/intro.md', { title: 'Introduction' }], ], }) ); @@ -18,6 +19,7 @@ describe('getSidebar', () => { expect(getSidebar('/', undefined)).toMatchInlineSnapshot(` [ { + "attrs": {}, "badge": undefined, "href": "/", "isCurrent": true, @@ -25,6 +27,7 @@ describe('getSidebar', () => { "type": "link", }, { + "attrs": {}, "badge": undefined, "href": "/environmental-impact/", "isCurrent": false, @@ -32,9 +35,27 @@ describe('getSidebar', () => { "type": "link", }, { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, + "badge": undefined, + "href": "/getting-started/intro/", + "isCurrent": false, + "label": "Introduction", + "type": "link", + }, + ], + "label": "Getting Started", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, "badge": undefined, "href": "/guides/authoring-content/", "isCurrent": false, @@ -42,10 +63,11 @@ describe('getSidebar', () => { "type": "link", }, { + "attrs": {}, "badge": undefined, - "href": "/guides/components/", + "href": "/guides/project-structure/", "isCurrent": false, - "label": "Components", + "label": "Project Structure", "type": "link", }, ], @@ -56,9 +78,9 @@ describe('getSidebar', () => { `); }); - test('marks current path with isCurrent', () => { - const paths = ['/', '/environmental-impact/', '/guides/authoring-content/']; - for (const currentPath of paths) { + test.each(['/', '/environmental-impact/', '/guides/authoring-content/'])( + 'marks current path with isCurrent: %s', + (currentPath) => { const items = flattenSidebar(getSidebar(currentPath, undefined)); const currentItems = items.filter((item) => item.type === 'link' && item.isCurrent); expect(currentItems).toHaveLength(1); @@ -66,13 +88,24 @@ describe('getSidebar', () => { if (currentItem?.type !== 'link') throw new Error('Expected current item to be link'); expect(currentItem.href).toBe(currentPath); } - }); + ); test('ignore trailing slashes when marking current path with isCurrent', () => { - const pathWithoutTrailingSlash = '/environmental-impact'; - const items = flattenSidebar(getSidebar(pathWithoutTrailingSlash, undefined)); + const pathWithTrailingSlash = '/environmental-impact/'; + const items = flattenSidebar(getSidebar(pathWithTrailingSlash, undefined)); const currentItems = items.filter((item) => item.type === 'link' && item.isCurrent); - expect(currentItems).toMatchObject([{ href: `${pathWithoutTrailingSlash}/`, type: 'link' }]); + expect(currentItems).toMatchInlineSnapshot(` + [ + { + "attrs": {}, + "badge": undefined, + "href": "/environmental-impact/", + "isCurrent": true, + "label": "Eco-friendly docs", + "type": "link", + }, + ] + `); }); test('nests files in subdirectory in group when autogenerating', () => { @@ -89,6 +122,24 @@ describe('getSidebar', () => { const homeLink = sidebar.find((item) => item.type === 'link' && item.href === '/'); expect(homeLink?.label).toBe('Home Page'); }); + + test('uses cached intermediate sidebars', async () => { + // Reset the modules registry so that re-importing `utils/navigation.ts` re-evaluates the + // module and clears the cache of intermediate sidebars from previous tests in this file. + vi.resetModules(); + const navigation = await import('../../utils/navigation'); + const routing = await import('../../utils/routing'); + + const getLocaleRoutes = vi.spyOn(routing, 'getLocaleRoutes'); + + navigation.getSidebar('/', undefined); + navigation.getSidebar('/environmental-impact/', undefined); + navigation.getSidebar('/guides/authoring-content/', undefined); + + expect(getLocaleRoutes).toHaveBeenCalledOnce(); + + getLocaleRoutes.mockRestore(); + }); }); describe('flattenSidebar', () => { @@ -103,6 +154,7 @@ describe('flattenSidebar', () => { expect(flattened).toMatchInlineSnapshot(` [ { + "attrs": {}, "badge": undefined, "href": "/", "isCurrent": true, @@ -110,6 +162,7 @@ describe('flattenSidebar', () => { "type": "link", }, { + "attrs": {}, "badge": undefined, "href": "/environmental-impact/", "isCurrent": false, @@ -117,6 +170,15 @@ describe('flattenSidebar', () => { "type": "link", }, { + "attrs": {}, + "badge": undefined, + "href": "/getting-started/intro/", + "isCurrent": false, + "label": "Introduction", + "type": "link", + }, + { + "attrs": {}, "badge": undefined, "href": "/guides/authoring-content/", "isCurrent": false, @@ -124,10 +186,11 @@ describe('flattenSidebar', () => { "type": "link", }, { + "attrs": {}, "badge": undefined, - "href": "/guides/components/", + "href": "/guides/project-structure/", "isCurrent": false, - "label": "Components", + "label": "Project Structure", "type": "link", }, ] @@ -142,13 +205,15 @@ describe('getPrevNextLinks', () => { expect(links).toMatchInlineSnapshot(` { "next": { + "attrs": {}, "badge": undefined, - "href": "/guides/authoring-content/", + "href": "/getting-started/intro/", "isCurrent": false, - "label": "Authoring Markdown", + "label": "Introduction", "type": "link", }, "prev": { + "attrs": {}, "badge": undefined, "href": "/", "isCurrent": false, @@ -172,7 +237,7 @@ describe('getPrevNextLinks', () => { }); test('returns no next link for last item', () => { - const sidebar = getSidebar('/guides/components/', undefined); + const sidebar = getSidebar('/guides/project-structure/', undefined); const links = getPrevNextLinks(sidebar, true, {}); expect(links.next).toBeUndefined(); }); @@ -232,9 +297,10 @@ describe('getPrevNextLinks', () => { expect(withDefaults.prev).toBeUndefined(); expect(withCustomLinks.prev).toEqual({ type: 'link', - href: '/x/', + href: 'x', label: 'X', isCurrent: false, + attrs: {}, }); }); diff --git a/packages/starlight/__tests__/basics/omit-canonical.test.ts b/packages/starlight/__tests__/basics/omit-canonical.test.ts new file mode 100644 index 00000000000..4defce17758 --- /dev/null +++ b/packages/starlight/__tests__/basics/omit-canonical.test.ts @@ -0,0 +1,32 @@ +import { expect, test, vi } from 'vitest'; +import { getRouteDataTestContext } from '../test-utils'; +import { generateRouteData } from '../../utils/routing/data'; +import { routes } from '../../utils/routing'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'Home Page' }], + [ + 'environmental-impact.md', + { + title: 'Eco-friendly docs', + description: + 'Learn how Starlight can help you build greener documentation sites and reduce your carbon footprint.', + }, + ], + ], + }) +); + +test('omits link canonical tag when site is not set', () => { + const route = routes[0]!; + const { head } = generateRouteData({ + props: { ...route, headings: [] }, + context: getRouteDataTestContext({ setSite: false }), + }); + + const canonicalExists = head.some((tag) => tag.tag === 'link' && tag.attrs?.rel === 'canonical'); + + expect(canonicalExists).toBe(false); +}); diff --git a/packages/starlight/__tests__/basics/pagefind.test.ts b/packages/starlight/__tests__/basics/pagefind.test.ts new file mode 100644 index 00000000000..3e4ac3a2e85 --- /dev/null +++ b/packages/starlight/__tests__/basics/pagefind.test.ts @@ -0,0 +1,69 @@ +import { fileURLToPath } from 'node:url'; +import { afterEach, expect, test, vi } from 'vitest'; +import * as pagefind from 'pagefind'; +import { starlightPagefind } from '../../integrations/pagefind'; +import { TestAstroIntegrationLogger } from '../test-plugin-utils'; + +vi.mock('pagefind'); + +afterEach(() => { + vi.clearAllMocks(); +}); + +async function runStarlightPagefind(outputDir: URL) { + const index = createMockIndex(); + + vi.mocked(pagefind.createIndex).mockResolvedValue({ index, errors: [] }); + + await starlightPagefind({ dir: outputDir, logger: new TestAstroIntegrationLogger() }); + + return index; +} + +function createMockIndex(): pagefind.PagefindIndex { + return { + addDirectory: vi.fn().mockResolvedValue({ page_count: 10, errors: [] }), + writeFiles: vi.fn().mockResolvedValue({ errors: [] }), + } as unknown as pagefind.PagefindIndex; +} + +const outputDir = new URL('file:///build/output/dir/'); + +test('runs and closes Pagefind successfully', async () => { + const index = await runStarlightPagefind(outputDir); + + // Create an index. + expect(pagefind.createIndex).toHaveBeenCalled(); + + // Add the build output directory to the index using a file path. + expect(index.addDirectory).toHaveBeenCalledWith({ + path: fileURLToPath(outputDir), + }); + + // Write files to the `./pagefind/` directory inside the build output directory. + expect(index.writeFiles).toHaveBeenCalledWith({ + outputPath: fileURLToPath(new URL('./pagefind/', outputDir)), + }); + + // Close Pagefind. + expect(pagefind.close).toHaveBeenCalled(); +}); + +test('logs Pagefind errors and closes Pagefind', async () => { + const errorMessage = 'Failed to create index'; + + const logger = new TestAstroIntegrationLogger(); + vi.spyOn(logger, 'error'); + vi.spyOn(logger, 'fork').mockReturnValue(logger); + + vi.mocked(pagefind.createIndex).mockResolvedValue({ + index: createMockIndex(), + errors: [errorMessage], + }); + + await expect(starlightPagefind({ dir: outputDir, logger })).rejects.toThrow(); + + expect(logger.error).toHaveBeenCalledWith(`Pagefind error: ${errorMessage}`); + + expect(pagefind.close).toHaveBeenCalled(); +}); diff --git a/packages/starlight/__tests__/basics/pagination-with-base.test.ts b/packages/starlight/__tests__/basics/pagination-with-base.test.ts new file mode 100644 index 00000000000..c96b8a22f03 --- /dev/null +++ b/packages/starlight/__tests__/basics/pagination-with-base.test.ts @@ -0,0 +1,80 @@ +import { afterAll, beforeAll, describe, expect, test, vi } from 'vitest'; +import type { + getPrevNextLinks as getPrevNextLinksType, + getSidebar as getSidebarType, +} from '../../utils/navigation'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'Home Page' }], + ['environmental-impact.md', { title: 'Eco-friendly docs' }], + ['guides/authoring-content.mdx', { title: 'Authoring Markdown' }], + ['guides/project-structure.mdx', { title: 'Project Structure' }], + ['reference/frontmatter.md', { title: 'Frontmatter Reference' }], + ], + }) +); + +describe('without base', () => { + let getPrevNextLinks: typeof getPrevNextLinksType; + let getSidebar: typeof getSidebarType; + let sidebar: ReturnType<typeof getSidebar>; + + beforeAll(async () => { + ({ getPrevNextLinks, getSidebar } = await import('../../utils/navigation')); + sidebar = getSidebar('/reference/frontmatter/', undefined); + }); + + test('pagination links are inferred correctly with no frontmatter', () => { + const links = getPrevNextLinks(sidebar, true, {}); + expect(links.prev?.href).toBe('/guides/project-structure/'); + expect(links.next?.href).toBeUndefined(); + }); + + test('pagination links are used as authored with custom links in frontmatter', () => { + const prevLink = '/other-page'; + const nextLink = '/extra-page'; + const links = getPrevNextLinks(sidebar, true, { + prev: { link: prevLink, label: 'Other Page' }, + next: { link: nextLink, label: 'Extra Page' }, + }); + expect(links.prev?.href).toBe(prevLink); + expect(links.next?.href).toBe(nextLink); + }); +}); + +describe('with base', () => { + let getPrevNextLinks: typeof getPrevNextLinksType; + let getSidebar: typeof getSidebarType; + let sidebar: ReturnType<typeof getSidebar>; + + beforeAll(async () => { + vi.resetModules(); + vi.stubEnv('BASE_URL', '/test-base/'); + ({ getPrevNextLinks, getSidebar } = await import('../../utils/navigation')); + sidebar = getSidebar('/test-base/reference/frontmatter/', undefined); + }); + + afterAll(() => { + vi.unstubAllEnvs(); + vi.resetModules(); + }); + + test('pagination links are inferred correctly with no frontmatter', () => { + const links = getPrevNextLinks(sidebar, true, {}); + expect(links.prev?.href).toBe('/test-base/guides/project-structure/'); + expect(links.next?.href).toBeUndefined(); + }); + + test('pagination links are used as authored with custom links in frontmatter', () => { + const prevLink = '/other-page'; + const nextLink = '/extra-page'; + const links = getPrevNextLinks(sidebar, true, { + prev: { link: prevLink, label: 'Other Page' }, + next: { link: nextLink, label: 'Extra Page' }, + }); + expect(links.prev?.href).toBe(prevLink); + expect(links.next?.href).toBe(nextLink); + }); +}); diff --git a/packages/starlight/__tests__/basics/route-data.test.ts b/packages/starlight/__tests__/basics/route-data.test.ts new file mode 100644 index 00000000000..feb5377f2bd --- /dev/null +++ b/packages/starlight/__tests__/basics/route-data.test.ts @@ -0,0 +1,88 @@ +import { expect, test, vi } from 'vitest'; +import { getRouteDataTestContext } from '../test-utils'; +import { generateRouteData } from '../../utils/routing/data'; +import { routes } from '../../utils/routing'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'Home Page' }], + ['getting-started.mdx', { title: 'Splash', template: 'splash' }], + ['showcase.mdx', { title: 'ToC Disabled', tableOfContents: false }], + ['environmental-impact.md', { title: 'Explicit update date', lastUpdated: new Date() }], + ], + }) +); + +test('adds data to route shape', () => { + const route = routes[0]!; + const data = generateRouteData({ + props: { ...route, headings: [{ depth: 1, slug: 'heading-1', text: 'Heading 1' }] }, + context: getRouteDataTestContext(), + }); + expect(data.hasSidebar).toBe(true); + expect(data).toHaveProperty('lastUpdated'); + expect(data.toc).toMatchInlineSnapshot(` + { + "items": [ + { + "children": [], + "depth": 2, + "slug": "_top", + "text": "Overview", + }, + ], + "maxHeadingLevel": 3, + "minHeadingLevel": 2, + } + `); + expect(data.pagination).toMatchInlineSnapshot(` + { + "next": { + "attrs": {}, + "badge": undefined, + "href": "/environmental-impact/", + "isCurrent": false, + "label": "Explicit update date", + "type": "link", + }, + "prev": undefined, + } + `); + expect(data.sidebar.map((entry) => entry.label)).toMatchInlineSnapshot(` + [ + "Home Page", + "Explicit update date", + "Splash", + "ToC Disabled", + ] + `); +}); + +test('disables table of contents for splash template', () => { + const route = routes[1]!; + const data = generateRouteData({ + props: { ...route, headings: [{ depth: 1, slug: 'heading-1', text: 'Heading 1' }] }, + context: getRouteDataTestContext({ pathname: '/getting-started/' }), + }); + expect(data.toc).toBeUndefined(); +}); + +test('disables table of contents if frontmatter includes `tableOfContents: false`', () => { + const route = routes[2]!; + const data = generateRouteData({ + props: { ...route, headings: [{ depth: 1, slug: 'heading-1', text: 'Heading 1' }] }, + context: getRouteDataTestContext({ pathname: '/showcase/' }), + }); + expect(data.toc).toBeUndefined(); +}); + +test('uses explicit last updated date from frontmatter', () => { + const route = routes[3]!; + const data = generateRouteData({ + props: { ...route, headings: [{ depth: 1, slug: 'heading-1', text: 'Heading 1' }] }, + context: getRouteDataTestContext({ pathname: '/showcase/' }), + }); + expect(data.lastUpdated).toBeInstanceOf(Date); + expect(data.lastUpdated).toEqual(route.entry.data.lastUpdated); +}); diff --git a/packages/starlight/__tests__/basics/routing.test.ts b/packages/starlight/__tests__/basics/routing.test.ts index a33dd441063..8d1ecac53e4 100644 --- a/packages/starlight/__tests__/basics/routing.test.ts +++ b/packages/starlight/__tests__/basics/routing.test.ts @@ -1,36 +1,54 @@ +import { type GetStaticPathsResult } from 'astro'; import { getCollection } from 'astro:content'; import config from 'virtual:starlight/user-config'; +import project from 'virtual:starlight/project-context'; import { expect, test, vi } from 'vitest'; -import { routes } from '../../utils/routing'; +import { routes, paths, getRouteBySlugParam } from '../../utils/routing'; +import { slugToParam } from '../../utils/slugs'; +import type { Route } from '../../utils/routing/types'; vi.mock('astro:content', async () => (await import('../test-utils')).mockedAstroContent({ docs: [ ['404.md', { title: 'Not found' }], ['index.mdx', { title: 'Home page' }], - ['guides/authoring-content.md', { title: 'Authoring content' }], + ['guides/authoring-content.mdx', { title: 'Authoring content', draft: true }], ], }) ); test('test suite is using correct env', () => { - expect(config.title).toBe('Basics'); + expect(config.title).toMatchObject({ en: 'Basics' }); }); test('route slugs are normalized', () => { - const indexRoute = routes.find((route) => route.id.startsWith('index.md')); + const indexRoute = routes.find( + (route) => route.id === (project.legacyCollections ? 'index.mdx' : '') + ); expect(indexRoute?.slug).toBe(''); }); test('routes contain copy of original doc as entry', async () => { const docs = await getCollection('docs'); for (const route of routes) { - const doc = docs.find((doc) => doc.id === route.id); + const doc = docs.find((doc) => doc.id === route.id || (doc.id === 'index' && route.id === '')); if (!doc) throw new Error('Expected to find doc for route ' + route.id); // Compare without slug as slugs can be normalized. const { slug: _, ...entry } = route.entry; - const { slug: __, ...input } = doc; - expect(entry).toEqual(input); + if (project.legacyCollections) { + // When using legacy collections, the `filePath` property is added to the route entry. + expect(entry.filePath).toBeDefined(); + const { filePath: _, ...legacyEntry } = entry; + // @ts-expect-error - When using legacy collections, the `slug` property is available but can + // be normalized. + const { slug: __, ...legacyInput } = doc; + expect(legacyEntry).toEqual(legacyInput); + } else { + // Compare without ids as ids can be normalized when using loaders. + const { id: _, ...loaderEntry } = entry; + const { id: __, ...loaderInput } = doc; + expect(loaderEntry).toEqual(loaderInput); + } } }); @@ -41,3 +59,53 @@ test('routes have locale data added', () => { expect(route.locale).toBeUndefined(); } }); + +test('paths contain normalized slugs for path parameters', () => { + const expectedPaths: GetStaticPathsResult = [ + { + params: { slug: '404' }, + props: routes[0]!, + }, + { + params: { slug: undefined }, + props: routes[1]!, + }, + { + params: { slug: 'guides/authoring-content' }, + props: routes[2]!, + }, + ]; + + expect(paths).toEqual(expectedPaths); +}); + +test('routes can be retrieved from their path parameters', () => { + for (const route of routes) { + const params = slugToParam(route.slug); + const routeFromParams = getRouteBySlugParam(params); + + expect(routeFromParams).toBe(route); + } +}); + +test('routes includes drafts except in production', async () => { + const routeMatcher = (route: Route) => + route.id === + (project.legacyCollections ? 'guides/authoring-content.mdx' : 'guides/authoring-content'); + + expect(routes.find(routeMatcher)).toBeTruthy(); + + // Reset the modules registry so that re-importing `utils/routing.ts` re-evaluates the module and + // re-computes the routes. Re-importing the module is necessary because top-level imports cannot + // be re-evaluated. + vi.resetModules(); + // Set the mode to production. + vi.stubEnv('MODE', 'production'); + // Re-import the module to re-evaluate it. + const { routes: prodRoutes } = await import('../../utils/routing'); + + expect(prodRoutes.find(routeMatcher)).toBeFalsy(); + + vi.unstubAllEnvs(); + vi.resetModules(); +}); diff --git a/packages/starlight/__tests__/basics/schema.test.ts b/packages/starlight/__tests__/basics/schema.test.ts index 85526db919c..2e274a1524e 100644 --- a/packages/starlight/__tests__/basics/schema.test.ts +++ b/packages/starlight/__tests__/basics/schema.test.ts @@ -1,5 +1,8 @@ import { describe, expect, test } from 'vitest'; import { FaviconSchema } from '../../schemas/favicon'; +import { TitleTransformConfigSchema } from '../../schemas/site-title'; +import { HeadConfigSchema, type HeadUserConfig } from '../../schemas/head'; +import { parseWithFriendlyErrors } from '../../utils/error-map'; describe('FaviconSchema', () => { test('returns the proper href and type attributes', () => { @@ -11,7 +14,160 @@ describe('FaviconSchema', () => { expect(favicon.type).toBe('image/jpeg'); }); + test('returns the proper href and type attributes when contains query', () => { + const icon = '/custom-icon.gif?v=123456&x=987654'; + + const favicon = FaviconSchema().parse(icon); + + expect(favicon.href).toBe(icon); + expect(favicon.type).toBe('image/gif'); + }); + + test('returns the proper href and type attributes when contains fragment', () => { + const icon = '/custom-icon.png#favicon'; + + const favicon = FaviconSchema().parse(icon); + + expect(favicon.href).toBe(icon); + expect(favicon.type).toBe('image/png'); + }); + + test('returns the proper href and type attributes when contains query and fragment', () => { + const icon = '/custom-icon.ico?v=123456&x=987654#favicon'; + + const favicon = FaviconSchema().parse(icon); + + expect(favicon.href).toBe(icon); + expect(favicon.type).toBe('image/x-icon'); + }); + test('throws on invalid favicon extensions', () => { expect(() => FaviconSchema().parse('/favicon.pdf')).toThrow(); }); }); + +describe('TitleTransformConfigSchema', () => { + test('title can be a string', () => { + const title = 'My Site'; + const defaultLang = 'en'; + + const siteTitle = TitleTransformConfigSchema(defaultLang).parse(title); + + expect(siteTitle).toEqual({ + en: title, + }); + }); + + test('title can be an object', () => { + const title = { + en: 'My Site', + es: 'Mi Sitio', + }; + const defaultLang = 'en'; + + const siteTitle = TitleTransformConfigSchema(defaultLang).parse(title); + + expect(siteTitle).toEqual(title); + }); + + test('throws on missing default language key', () => { + const title = { + es: 'Mi Sitio', + }; + const defaultLang = 'en'; + + expect(() => TitleTransformConfigSchema(defaultLang).parse(title)).toThrow(); + }); +}); + +describe('HeadConfigSchema', () => { + function parseHeadConfigWithFriendlyErrors( + source: Parameters<typeof HeadConfigSchema>[0]['source'], + data: HeadUserConfig + ) { + return parseWithFriendlyErrors( + HeadConfigSchema({ source }), + data, + 'Data does not match schema' + ); + } + + const headConfigWithoutAttrs: HeadUserConfig = [{ tag: 'meta', content: '1234' }]; + const headConfigWithAttrs: HeadUserConfig = [ + { tag: 'meta', attrs: { property: 'test:id' }, content: '1234' }, + ]; + + describe('source: config', () => { + test('errors with head `meta` tag with `content` and attributes', () => { + expect(() => parseHeadConfigWithFriendlyErrors('config', headConfigWithoutAttrs)) + .toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Data does not match schema + Hint: + The \`head\` configuration includes a \`meta\` tag with \`content\` which is invalid HTML. + You should instead use a \`content\` attribute with an additional attribute such as \`name\`, \`property\`, or \`http-equiv\` to identify the kind of metadata it represents in the \`attrs\` object: + + { + "tag": "meta", + "attrs": { + "name": "identifier", + "content": "1234" + } + }" + `); + }); + test('errors with head `meta` tag with `content` and no attributes', () => { + expect(() => parseHeadConfigWithFriendlyErrors('config', headConfigWithAttrs)) + .toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Data does not match schema + Hint: + The \`head\` configuration includes a \`meta\` tag with \`content\` which is invalid HTML. + You should instead use a \`content\` attribute in the \`attrs\` object: + + { + "tag": "meta", + "attrs": { + "property": "test:id", + "content": "1234" + } + }" + `); + }); + }); + + describe('source: content', () => { + test('errors with head `meta` tag with `content` and attributes', () => { + expect(() => parseHeadConfigWithFriendlyErrors('content', headConfigWithoutAttrs)) + .toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Data does not match schema + Hint: + The \`head\` configuration includes a \`meta\` tag with \`content\` which is invalid HTML. + You should instead use a \`content\` attribute with an additional attribute such as \`name\`, \`property\`, or \`http-equiv\` to identify the kind of metadata it represents in the \`attrs\` object: + + - tag: meta + attrs: + name: identifier + content: '1234' + " + `); + }); + test('errors with head `meta` tag with `content` and no attributes', () => { + expect(() => parseHeadConfigWithFriendlyErrors('content', headConfigWithAttrs)) + .toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Data does not match schema + Hint: + The \`head\` configuration includes a \`meta\` tag with \`content\` which is invalid HTML. + You should instead use a \`content\` attribute in the \`attrs\` object: + + - tag: meta + attrs: + property: test:id + content: '1234' + " + `); + }); + }); +}); diff --git a/packages/starlight/__tests__/basics/sitemap.test.ts b/packages/starlight/__tests__/basics/sitemap.test.ts new file mode 100644 index 00000000000..d33820402be --- /dev/null +++ b/packages/starlight/__tests__/basics/sitemap.test.ts @@ -0,0 +1,40 @@ +import { describe, expect, test } from 'vitest'; +import { getSitemapConfig, starlightSitemap } from '../../integrations/sitemap'; +import type { StarlightConfig } from '../../types'; +import { StarlightConfigSchema, type StarlightUserConfig } from '../../utils/user-config'; + +describe('starlightSitemap', () => { + test('returns @astrojs/sitemap integration', () => { + const integration = starlightSitemap({} as StarlightConfig); + expect(integration.name).toBe('@astrojs/sitemap'); + }); +}); + +describe('getSitemapConfig', () => { + test('configures i18n config', () => { + const config = getSitemapConfig( + StarlightConfigSchema.parse({ + title: 'i18n test', + locales: { root: { lang: 'en', label: 'English' }, fr: { label: 'French' } }, + } satisfies StarlightUserConfig) + ); + expect(config).toMatchInlineSnapshot(` + { + "i18n": { + "defaultLocale": "root", + "locales": { + "fr": "fr", + "root": "en", + }, + }, + } + `); + }); + + test('no config for monolingual sites', () => { + const config = getSitemapConfig( + StarlightConfigSchema.parse({ title: 'i18n test' } satisfies StarlightUserConfig) + ); + expect(config).toMatchInlineSnapshot('{}'); + }); +}); diff --git a/packages/starlight/__tests__/basics/slugs.test.ts b/packages/starlight/__tests__/basics/slugs.test.ts index 6c17414bee3..0806a0bdf76 100644 --- a/packages/starlight/__tests__/basics/slugs.test.ts +++ b/packages/starlight/__tests__/basics/slugs.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, test } from 'vitest'; +import { describe, expect, test, vi } from 'vitest'; import { localeToLang, localizedId, @@ -6,6 +6,7 @@ import { slugToLocaleData, slugToParam, slugToPathname, + urlToSlug, } from '../../utils/slugs'; describe('slugToLocaleData', () => { @@ -30,6 +31,9 @@ describe('slugToParam', () => { test('returns undefined for root index', () => { expect(slugToParam('index')).toBeUndefined(); }); + test('returns undefined for /', () => { + expect(slugToParam('/')).toBeUndefined(); + }); test('strips index from end of nested slug', () => { expect(slugToParam('dir/index')).toBe('dir'); expect(slugToParam('dir/index/sub-dir/index')).toBe('dir/index/sub-dir'); @@ -39,6 +43,12 @@ describe('slugToParam', () => { expect(slugToParam('dir/page')).toBe('dir/page'); expect(slugToParam('dir/sub-dir/page')).toBe('dir/sub-dir/page'); }); + test('normalizes unnormalized strings', () => { + // The input and output contain visually indistinguishable glyphs with different code point + // representation that are canonically equivalent that should be normalized using NFC + // normalization matching Astro's behavior. + expect(slugToParam('اللُّغَةُ-الْعَرَبِيَّةُ')).toBe('اللُّغَةُ-الْعَرَبِيَّةُ'); + }); }); describe('slugToPathname', () => { @@ -76,3 +86,32 @@ describe('localizedSlug', () => { expect(localizedSlug('test', undefined)).toBe('test'); }); }); + +describe('urlToSlug', () => { + test('returns slugs with `build.output: "directory"`', () => { + expect(urlToSlug(new URL('https://example.com'))).toBe(''); + expect(urlToSlug(new URL('https://example.com/slug'))).toBe('slug'); + expect(urlToSlug(new URL('https://example.com/dir/page/'))).toBe('dir/page'); + expect(urlToSlug(new URL('https://example.com/dir/sub-dir/page/'))).toBe('dir/sub-dir/page'); + }); + + test('returns slugs with `build.output: "file"`', () => { + expect(urlToSlug(new URL('https://example.com/index.html'))).toBe(''); + expect(urlToSlug(new URL('https://example.com/slug.html'))).toBe('slug'); + expect(urlToSlug(new URL('https://example.com/dir/page/index.html'))).toBe('dir/page'); + expect(urlToSlug(new URL('https://example.com/dir/sub-dir/page.html'))).toBe( + 'dir/sub-dir/page' + ); + }); + + test('returns slugs with a custom `base` option', () => { + vi.stubEnv('BASE_URL', '/base/'); + expect(urlToSlug(new URL('https://example.com/base'))).toBe(''); + expect(urlToSlug(new URL('https://example.com/base/slug'))).toBe('slug'); + expect(urlToSlug(new URL('https://example.com/base/dir/page/'))).toBe('dir/page'); + expect(urlToSlug(new URL('https://example.com/base/dir/sub-dir/page/'))).toBe( + 'dir/sub-dir/page' + ); + vi.unstubAllEnvs(); + }); +}); diff --git a/packages/starlight/__tests__/basics/sorting.test.ts b/packages/starlight/__tests__/basics/sorting.test.ts new file mode 100644 index 00000000000..978ebd2448d --- /dev/null +++ b/packages/starlight/__tests__/basics/sorting.test.ts @@ -0,0 +1,31 @@ +import { expect, test, vi } from 'vitest'; +import { flattenSidebar, getSidebar } from '../../utils/navigation'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'first' }], + ['guides/example.md', { title: 'second' }], + ['reference/example.md', { title: 'third' }], + ['reference/rod/foo.md', { title: 'fourth' }], + ['reference/rod/zip.md', { title: 'fifth' }], + ['reference/zoo.md', { title: 'sixth' }], + ], + }) +); + +test('autogenerated sidebar is sorted alphabetically by filename', () => { + const sidebar = getSidebar('/', undefined); + const flattened = flattenSidebar(sidebar); + + expect(flattened.map((e) => e.label)).toMatchInlineSnapshot(` + [ + "first", + "second", + "third", + "fourth", + "fifth", + "sixth", + ] + `); +}); diff --git a/packages/starlight/__tests__/basics/starlight-page-route-data-extend.test.ts b/packages/starlight/__tests__/basics/starlight-page-route-data-extend.test.ts new file mode 100644 index 00000000000..4db04f67898 --- /dev/null +++ b/packages/starlight/__tests__/basics/starlight-page-route-data-extend.test.ts @@ -0,0 +1,56 @@ +import { expect, test, vi } from 'vitest'; +import { getRouteDataTestContext } from '../test-utils'; +import { + generateStarlightPageRouteData, + type StarlightPageProps, +} from '../../utils/starlight-page'; + +vi.mock('virtual:starlight/collection-config', async () => { + const { z } = await vi.importActual<typeof import('astro:content')>('astro:content'); + return (await import('../test-utils')).mockedCollectionConfig({ + extend: z.object({ + // Make the built-in description field required. + description: z.string(), + // Add a new optional field. + category: z.string().optional(), + }), + }); +}); + +const starlightPageProps: StarlightPageProps = { + frontmatter: { title: 'This is a test title' }, +}; + +test('throws a validation error if a built-in field required by the user schema is not passed down', async () => { + // The first line should be a user-friendly error message describing the exact issue and the second line should be + // the missing description field. + await expect(() => + generateStarlightPageRouteData({ + props: starlightPageProps, + context: getRouteDataTestContext({ pathname: '/test-slug' }), + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Invalid frontmatter props passed to the \`<StarlightPage/>\` component. + Hint: + **description**: Required" + `); +}); + +test('returns new field defined in the user schema', async () => { + const category = 'test category'; + const data = await generateStarlightPageRouteData({ + props: { + ...starlightPageProps, + frontmatter: { + ...starlightPageProps.frontmatter, + description: 'test description', + // @ts-expect-error - Custom field defined in the user schema. + category, + }, + }, + context: getRouteDataTestContext({ pathname: '/test-slug' }), + }); + // @ts-expect-error - Custom field defined in the user schema. + expect(data.entry.data.category).toBe(category); +}); diff --git a/packages/starlight/__tests__/basics/starlight-page-route-data.test.ts b/packages/starlight/__tests__/basics/starlight-page-route-data.test.ts new file mode 100644 index 00000000000..077c91a9494 --- /dev/null +++ b/packages/starlight/__tests__/basics/starlight-page-route-data.test.ts @@ -0,0 +1,626 @@ +import type { ImageMetadata } from 'astro'; +import { expect, test, vi } from 'vitest'; +import { routes } from '../../utils/routing'; +import { generateRouteData } from '../../utils/routing/data'; +import { + generateStarlightPageRouteData, + type StarlightPageProps, +} from '../../utils/starlight-page'; +import { getRouteDataTestContext } from '../test-utils'; + +vi.mock('virtual:starlight/collection-config', async () => + (await import('../test-utils')).mockedCollectionConfig() +); + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'Home Page' }], + ['getting-started.mdx', { title: 'Getting Started' }], + ['guides/authoring-content.mdx', { title: 'Authoring Markdown' }], + ['guides/project-structure.mdx', { title: 'Project Structure' }], + ['reference/frontmatter.md', { title: 'Frontmatter Reference' }], + ], + }) +); + +const starlightPageProps: StarlightPageProps = { + frontmatter: { title: 'This is a test title' }, +}; + +const starlightPagePathname = '/test-slug'; + +test('adds data to route shape', async () => { + const data = await generateStarlightPageRouteData({ + props: starlightPageProps, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + // Starlight pages infer the slug from the URL. + expect(data.slug).toBe('test-slug'); + // Starlight pages generate an ID based on their slug. + expect(data.id).toBeDefined(); + // Starlight pages cannot be fallbacks. + expect(data.isFallback).toBeUndefined(); + // Starlight pages are not editable if no edit URL is passed. + expect(data.editUrl).toBeUndefined(); + expect(data.entry.data.editUrl).toBe(false); + // Starlight pages are part of the docs collection. + expect(data.entry.collection).toBe('docs'); + // Starlight pages get dedicated frontmatter defaults. + expect(data.entry.data.head).toEqual([]); + expect(data.entry.data.pagefind).toBe(true); + expect(data.entry.data.template).toBe('doc'); + // Starlight pages respect the passed data. + expect(data.entry.data.title).toBe(starlightPageProps.frontmatter.title); + // Starlight pages get expected defaults. + expect(data.siteTitle).toBe('Basics'); + expect(data.hasSidebar).toBe(true); + expect(data.headings).toEqual([]); + expect(data.entryMeta.dir).toBe('ltr'); + expect(data.entryMeta.lang).toBe('en'); +}); + +test('adds custom data to route shape', async () => { + const props: StarlightPageProps = { + ...starlightPageProps, + hasSidebar: false, + dir: 'rtl', + lang: 'ks', + isFallback: true, + }; + const data = await generateStarlightPageRouteData({ + props, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect(data.hasSidebar).toBe(props.hasSidebar); + expect(data.entryMeta.dir).toBe(props.dir); + expect(data.entryMeta.lang).toBe(props.lang); + expect(data.isFallback).toBe(props.isFallback); +}); + +test('adds custom frontmatter data to route shape', async () => { + const props: StarlightPageProps = { + ...starlightPageProps, + frontmatter: { + ...starlightPageProps.frontmatter, + head: [{ tag: 'meta', attrs: { name: 'og:test', content: 'test' } }], + lastUpdated: new Date(), + pagefind: false, + template: 'splash', + }, + }; + const data = await generateStarlightPageRouteData({ + props, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect(data.entry.data.head).toMatchInlineSnapshot(` + [ + { + "attrs": { + "content": "test", + "name": "og:test", + }, + "tag": "meta", + }, + ] + `); + expect(data.entry.data.lastUpdated).toEqual(props.frontmatter.lastUpdated); + expect(data.entry.data.pagefind).toBe(props.frontmatter.pagefind); + expect(data.entry.data.template).toBe(props.frontmatter.template); +}); + +test('uses generated sidebar when no sidebar is provided', async () => { + const data = await generateStarlightPageRouteData({ + props: starlightPageProps, + context: getRouteDataTestContext({ pathname: '/getting-started/' }), + }); + expect(data.sidebar).toMatchInlineSnapshot(` + [ + { + "attrs": {}, + "badge": undefined, + "href": "/", + "isCurrent": false, + "label": "Home Page", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/getting-started/", + "isCurrent": true, + "label": "Getting Started", + "type": "link", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/guides/authoring-content/", + "isCurrent": false, + "label": "Authoring Markdown", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/guides/project-structure/", + "isCurrent": false, + "label": "Project Structure", + "type": "link", + }, + ], + "label": "guides", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/reference/frontmatter/", + "isCurrent": false, + "label": "Frontmatter Reference", + "type": "link", + }, + ], + "label": "reference", + "type": "group", + }, + ] + `); +}); + +test('uses provided sidebar if any', async () => { + const data = await generateStarlightPageRouteData({ + props: { + ...starlightPageProps, + sidebar: [ + { + label: 'Custom link 1', + link: '/test/1', + badge: 'New', + }, + { + label: 'Custom link 2', + link: '/test/2', + }, + { + label: 'Guides', + autogenerate: { directory: 'guides' }, + }, + 'reference/frontmatter', + ], + }, + context: getRouteDataTestContext({ pathname: '/test/2' }), + }); + expect(data.sidebar).toMatchInlineSnapshot(` + [ + { + "attrs": {}, + "badge": { + "text": "New", + "variant": "default", + }, + "href": "/test/1", + "isCurrent": false, + "label": "Custom link 1", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/test/2", + "isCurrent": true, + "label": "Custom link 2", + "type": "link", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/guides/authoring-content/", + "isCurrent": false, + "label": "Authoring Markdown", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/guides/project-structure/", + "isCurrent": false, + "label": "Project Structure", + "type": "link", + }, + ], + "label": "Guides", + "type": "group", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/reference/frontmatter/", + "isCurrent": false, + "label": "Frontmatter Reference", + "type": "link", + }, + ] + `); + expect(data.pagination.prev?.href).toBe('/test/1'); + expect(data.pagination.next?.href).toBe('/guides/authoring-content/'); +}); + +test('throws error if sidebar is malformated', async () => { + await expect(() => + generateStarlightPageRouteData({ + props: { + ...starlightPageProps, + sidebar: [ + { + label: 'Custom link 1', + //@ts-expect-error Intentionally bad type to cause error. + href: '/test/1', + }, + ], + }, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Invalid sidebar prop passed to the \`<StarlightPage/>\` component. + Hint: + **0**: Did not match union. + > Expected type \`{ link: string; } | { items: array; } | { autogenerate: object; } | { slug: string } | string\` + > Received \`{ "label": "Custom link 1", "href": "/test/1" }\`" + `); +}); + +test('uses provided pagination if any', async () => { + const data = await generateStarlightPageRouteData({ + props: { + ...starlightPageProps, + frontmatter: { + ...starlightPageProps.frontmatter, + prev: { + label: 'Previous link', + link: '/test/prev', + }, + next: { + label: 'Next link', + link: '/test/next', + }, + }, + }, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect(data.pagination).toMatchInlineSnapshot(` + { + "next": { + "attrs": {}, + "badge": undefined, + "href": "/test/next", + "isCurrent": false, + "label": "Next link", + "type": "link", + }, + "prev": { + "attrs": {}, + "badge": undefined, + "href": "/test/prev", + "isCurrent": false, + "label": "Previous link", + "type": "link", + }, + } + `); +}); + +test('uses provided headings if any', async () => { + const headings = [ + { depth: 2, slug: 'heading-1', text: 'Heading 1' }, + { depth: 3, slug: 'heading-2', text: 'Heading 2' }, + ]; + const data = await generateStarlightPageRouteData({ + props: { ...starlightPageProps, headings }, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect(data.headings).toEqual(headings); +}); + +test('generates the table of contents for provided headings', async () => { + const data = await generateStarlightPageRouteData({ + props: { + ...starlightPageProps, + headings: [ + { depth: 2, slug: 'heading-1', text: 'Heading 1' }, + { depth: 3, slug: 'heading-2', text: 'Heading 2' }, + // Should be ignored as it's too deep with default config. + { depth: 4, slug: 'heading-3', text: 'Heading 3' }, + ], + }, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect(data.toc).toMatchInlineSnapshot(` + { + "items": [ + { + "children": [], + "depth": 2, + "slug": "_top", + "text": "Overview", + }, + { + "children": [ + { + "children": [], + "depth": 3, + "slug": "heading-2", + "text": "Heading 2", + }, + ], + "depth": 2, + "slug": "heading-1", + "text": "Heading 1", + }, + ], + "maxHeadingLevel": 3, + "minHeadingLevel": 2, + } + `); +}); + +test('respects the `tableOfContents` level configuration', async () => { + const data = await generateStarlightPageRouteData({ + props: { + ...starlightPageProps, + headings: [ + // Should be ignored as it's not deep enough. + { depth: 2, slug: 'heading-1', text: 'Heading 1' }, + { depth: 3, slug: 'heading-2', text: 'Heading 2' }, + { depth: 4, slug: 'heading-3', text: 'Heading 3' }, + ], + frontmatter: { + ...starlightPageProps.frontmatter, + tableOfContents: { + minHeadingLevel: 3, + maxHeadingLevel: 4, + }, + }, + }, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect(data.toc).toMatchInlineSnapshot(` + { + "items": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depth": 4, + "slug": "heading-3", + "text": "Heading 3", + }, + ], + "depth": 3, + "slug": "heading-2", + "text": "Heading 2", + }, + ], + "depth": 2, + "slug": "_top", + "text": "Overview", + }, + ], + "maxHeadingLevel": 4, + "minHeadingLevel": 3, + } + `); +}); + +test('disables table of contents if frontmatter includes `tableOfContents: false`', async () => { + const data = await generateStarlightPageRouteData({ + props: { + ...starlightPageProps, + headings: [ + { depth: 2, slug: 'heading-1', text: 'Heading 1' }, + { depth: 3, slug: 'heading-2', text: 'Heading 2' }, + ], + frontmatter: { + ...starlightPageProps.frontmatter, + tableOfContents: false, + }, + }, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect(data.toc).toBeUndefined(); +}); + +test('disables table of contents for splash template', async () => { + const data = await generateStarlightPageRouteData({ + props: { + ...starlightPageProps, + headings: [ + { depth: 2, slug: 'heading-1', text: 'Heading 1' }, + { depth: 3, slug: 'heading-2', text: 'Heading 2' }, + ], + frontmatter: { + ...starlightPageProps.frontmatter, + template: 'splash', + }, + }, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect(data.toc).toBeUndefined(); +}); + +test('hides the sidebar if the `hasSidebar` option is not specified and the splash template is used', async () => { + const { hasSidebar, ...otherProps } = starlightPageProps; + const data = await generateStarlightPageRouteData({ + props: { + ...otherProps, + frontmatter: { + ...otherProps.frontmatter, + template: 'splash', + }, + }, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect(data.hasSidebar).toBe(false); +}); + +test('uses provided edit URL if any', async () => { + const editUrl = 'https://example.com/edit'; + const data = await generateStarlightPageRouteData({ + props: { + ...starlightPageProps, + frontmatter: { + ...starlightPageProps.frontmatter, + editUrl, + }, + }, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect(data.editUrl).toEqual(new URL(editUrl)); + expect(data.entry.data.editUrl).toEqual(editUrl); +}); + +test('strips unknown frontmatter properties', async () => { + const data = await generateStarlightPageRouteData({ + props: { + ...starlightPageProps, + frontmatter: { + ...starlightPageProps.frontmatter, + // @ts-expect-error - This is an unknown property. + unknown: 'test', + }, + }, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect('unknown' in data.entry.data).toBe(false); +}); + +test('generates data with a similar root shape to regular route data', async () => { + const route = routes[0]!; + const context = getRouteDataTestContext({ pathname: starlightPagePathname }); + const data = generateRouteData({ + props: { ...route, headings: [{ depth: 1, slug: 'heading-1', text: 'Heading 1' }] }, + context, + }); + + const starlightPageData = await generateStarlightPageRouteData({ + props: starlightPageProps, + context, + }); + + expect(Object.keys(data).sort()).toEqual(Object.keys(starlightPageData).sort()); +}); + +test('parses an ImageMetadata object successfully', async () => { + const fakeImportedImage: ImageMetadata = { + src: '/image-src.png', + width: 100, + height: 100, + format: 'png', + }; + const data = await generateStarlightPageRouteData({ + props: { + ...starlightPageProps, + frontmatter: { + ...starlightPageProps.frontmatter, + hero: { + image: { file: fakeImportedImage }, + }, + }, + }, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect(data.entry.data.hero?.image).toBeDefined(); + // @ts-expect-error — image’s type can be different shapes but we know it’s this one here + expect(data.entry.data.hero?.image!['file']).toMatchInlineSnapshot(` + { + "format": "png", + "height": 100, + "src": "/image-src.png", + "width": 100, + } + `); +}); + +test('parses an image that is also a function successfully', async () => { + const fakeImportedSvg = (() => {}) as unknown as ImageMetadata; + Object.assign(fakeImportedSvg, { src: '/image-src.svg', width: 100, height: 100, format: 'svg' }); + const data = await generateStarlightPageRouteData({ + props: { + ...starlightPageProps, + frontmatter: { + ...starlightPageProps.frontmatter, + hero: { + image: { file: fakeImportedSvg }, + }, + }, + }, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect(data.entry.data.hero?.image).toBeDefined(); + // @ts-expect-error — image’s type can be different shapes but we know it’s this one here + expect(data.entry.data.hero?.image!['file']).toMatchInlineSnapshot(`[Function]`); + // @ts-expect-error — see above + expect(data.entry.data.hero?.image!['file']).toHaveProperty('src'); + // @ts-expect-error — see above + expect(data.entry.data.hero?.image!['file']).toHaveProperty('width'); + // @ts-expect-error — see above + expect(data.entry.data.hero?.image!['file']).toHaveProperty('height'); + // @ts-expect-error — see above + expect(data.entry.data.hero?.image!['file']).toHaveProperty('format'); +}); + +test('fails to parse an image without the expected metadata properties', async () => { + await expect(() => + generateStarlightPageRouteData({ + props: { + ...starlightPageProps, + frontmatter: { + ...starlightPageProps.frontmatter, + hero: { + image: { + // @ts-expect-error intentionally incorrect input + file: () => {}, + }, + }, + }, + }, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Invalid frontmatter props passed to the \`<StarlightPage/>\` component. + Hint: + **hero.image**: Did not match union. + > Expected type \`file | { dark; light } | { html: string }\` + > Received \`{}\`" + `); +}); + +test('adds data to route shape when the `docs` collection is not defined', async () => { + // Mock the collection config in this test to simulate the absence of the `docs` collection. + vi.doMock('virtual:starlight/collection-config', () => ({ collections: {} })); + + const data = await generateStarlightPageRouteData({ + props: starlightPageProps, + context: getRouteDataTestContext({ pathname: starlightPagePathname }), + }); + expect(data.entry.data.title).toBe(starlightPageProps.frontmatter.title); + + // Undo the mock to restore the original behavior. + vi.doUnmock('virtual:starlight/collection-config'); +}); diff --git a/packages/starlight/__tests__/basics/toc.test.ts b/packages/starlight/__tests__/basics/toc.test.ts index 51745d7b81c..ae1136f9693 100644 --- a/packages/starlight/__tests__/basics/toc.test.ts +++ b/packages/starlight/__tests__/basics/toc.test.ts @@ -1,5 +1,5 @@ import { expect, test } from 'vitest'; -import { generateToC } from '../../components/TableOfContents/generateToC'; +import { generateToC } from '../../utils/generateToC'; const defaultOpts = { minHeadingLevel: 2, maxHeadingLevel: 3, title: 'Overview' }; diff --git a/packages/starlight/__tests__/basics/translations.test.ts b/packages/starlight/__tests__/basics/translations.test.ts new file mode 100644 index 00000000000..3552e9cc6f8 --- /dev/null +++ b/packages/starlight/__tests__/basics/translations.test.ts @@ -0,0 +1,145 @@ +import { describe, expect, test, vi } from 'vitest'; +import { useTranslations } from '../../utils/translations'; +import translations from '../../translations'; + +describe('useTranslations()', () => { + test('includes localized UI strings', () => { + const t = useTranslations(undefined); + expect(t).toBeTypeOf('function'); + expect(t('skipLink.label')).toBe('Skip to content'); + }); +}); + +describe('t()', async () => { + // The mocked user-defined translations are scoped to this `describe` block so that they do not + // affect other tests (`vi.mock` → `vi.doMock`). + vi.doMock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + i18n: [ + [ + 'en', + { + 'test.interpolation': '{{subject}} is {{adjective}}', + 'test.dataModel': 'Powered by {{integration.name}}', + 'test.escape': 'The tag is {{tag}}', + 'test.unescape': 'The tag is {{- tag}}', + 'test.currency': 'The price is {{price, currency(USD)}}', + 'test.list': '{{subjects, list}} are awesome', + 'test.count_one': '{{count}} project', + 'test.count_other': '{{count}} projects', + 'test.nesting1': '$t(test.nesting2) is nested', + 'test.nesting2': 'this UI string', + }, + ], + ], + }) + ); + // Reset the modules registry so that re-importing `../../utils/translations` re-evaluates the + // module and re-computes `useTranslations`. Re-importing the module is necessary because + // top-level imports cannot be re-evaluated. + vi.resetModules(); + const { useTranslations } = await import('../../utils/translations'); + const t = useTranslations(undefined); + + test('supports using interpolation', () => { + expect(t).toBeTypeOf('function'); + // @ts-expect-error - using a mocked translation key. + expect(t('test.interpolation', { subject: 'Starlight', adjective: 'amazing' })).toBe( + 'Starlight is amazing' + ); + }); + + test('supports using data models', () => { + expect(t).toBeTypeOf('function'); + // @ts-expect-error - using a mocked translation key. + expect(t('test.dataModel', { integration: { name: 'Starlight' } })).toBe( + 'Powered by Starlight' + ); + }); + + test('escapes by default', () => { + expect(t).toBeTypeOf('function'); + // @ts-expect-error - using a mocked translation key. + expect(t('test.escape', { tag: '<img />' })).toBe('The tag is <img />'); + }); + + test('supports unescaped strings', () => { + expect(t).toBeTypeOf('function'); + // @ts-expect-error - using a mocked translation key. + expect(t('test.unescape', { tag: '<img />' })).toBe('The tag is <img />'); + }); + + test('supports currencies', () => { + expect(t).toBeTypeOf('function'); + // @ts-expect-error - using a mocked translation key. + expect(t('test.currency', { price: 1000 })).toBe('The price is $1,000.00'); + }); + + test('supports lists', () => { + expect(t).toBeTypeOf('function'); + // @ts-expect-error - using a mocked translation key. + expect(t('test.list', { subjects: ['Astro', 'Starlight', 'Astro DB'] })).toBe( + 'Astro, Starlight, and Astro DB are awesome' + ); + }); + + test('supports counts', () => { + expect(t).toBeTypeOf('function'); + // @ts-expect-error - using a mocked translation key. + expect(t('test.count', { count: 1 })).toBe('1 project'); + // @ts-expect-error - using a mocked translation key. + expect(t('test.count', { count: 20 })).toBe('20 projects'); + }); + + test('supports nesting', () => { + expect(t).toBeTypeOf('function'); + // @ts-expect-error - using a mocked translation key. + expect(t('test.nesting1')).toBe('this UI string is nested'); + }); + + test('returns the UI string key if the translation is missing', () => { + expect(t).toBeTypeOf('function'); + // @ts-expect-error - using a missing translation key. + expect(t('test.unknown')).toBe('test.unknown'); + }); +}); + +describe('t.all()', async () => { + // See the `t()` tests for an explanation of how the user-defined translations are mocked. + vi.doMock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + i18n: [['en', { 'test.foo': 'bar' }]], + }) + ); + vi.resetModules(); + const { useTranslations } = await import('../../utils/translations'); + const t = useTranslations(undefined); + + test('returns all translations including custom ones', () => { + expect(t.all).toBeTypeOf('function'); + expect(t.all()).toEqual({ ...translations.en, 'test.foo': 'bar' }); + }); +}); + +describe('t.exists()', async () => { + // See the `t()` tests for an explanation of how the user-defined translations are mocked. + vi.doMock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + i18n: [['en', { 'test.foo': 'bar' }]], + }) + ); + vi.resetModules(); + const { useTranslations } = await import('../../utils/translations'); + const t = useTranslations(undefined); + + test('returns `true` for existing translations', () => { + expect(t.exists).toBeTypeOf('function'); + expect(t.exists('skipLink.label')).toBe(true); + expect(t.exists('test.foo')).toBe(true); + }); + + test('returns `false` for unknown translations', () => { + expect(t.exists).toBeTypeOf('function'); + expect(t.exists('test.unknown')).toBe(false); + }); +}); diff --git a/packages/starlight/__tests__/basics/user-config.test.ts b/packages/starlight/__tests__/basics/user-config.test.ts index e3eeb723df3..c0f115f65c4 100644 --- a/packages/starlight/__tests__/basics/user-config.test.ts +++ b/packages/starlight/__tests__/basics/user-config.test.ts @@ -4,11 +4,11 @@ import { StarlightConfigSchema } from '../../utils/user-config'; test('preserve social config order', () => { const config = StarlightConfigSchema.parse({ title: 'Test', - social: { - twitch: 'https://www.twitch.tv/bholmesdev', - github: 'https://github.com/withastro/starlight', - discord: 'https://astro.build/chat', - }, + social: [ + { icon: 'twitch', label: 'Twitch', href: 'https://www.twitch.tv/bholmesdev' }, + { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' }, + { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + ], }); - expect(Object.keys(config.social || {})).toEqual(['twitch', 'github', 'discord']); + expect((config.social || []).map(({ icon }) => icon)).toEqual(['twitch', 'github', 'discord']); }); diff --git a/packages/starlight/__tests__/build-format-file/navigation.test.ts b/packages/starlight/__tests__/build-format-file/navigation.test.ts new file mode 100644 index 00000000000..16445cb64c2 --- /dev/null +++ b/packages/starlight/__tests__/build-format-file/navigation.test.ts @@ -0,0 +1,124 @@ +import { describe, expect, test, vi } from 'vitest'; +import { getSidebar } from '../../utils/navigation'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'Home Page' }], + ['environmental-impact.md', { title: 'Eco-friendly docs' }], + ['reference/configuration.mdx', { title: 'Config Reference' }], + ['reference/frontmatter.md', { title: 'Frontmatter Reference' }], + ['api/v1/users.md', { title: 'Users API' }], + ['guides/project-structure.mdx', { title: 'Project Structure' }], + ], + }) +); + +describe('getSidebar with build.format = "file"', () => { + test('returns an array of sidebar entries with its file extension', () => { + expect(getSidebar('/index.html', undefined)).toMatchInlineSnapshot(` + [ + { + "attrs": {}, + "badge": undefined, + "href": "/index.html", + "isCurrent": true, + "label": "Home", + "type": "link", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": { + "text": "New", + "variant": "success", + }, + "href": "/intro.html", + "isCurrent": false, + "label": "Introduction", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Deprecated", + "variant": "default", + }, + "href": "/next-steps.html", + "isCurrent": false, + "label": "Next Steps", + "type": "link", + }, + { + "attrs": { + "class": "showcase-link", + "target": "_blank", + }, + "badge": undefined, + "href": "/showcase.html", + "isCurrent": false, + "label": "Showcase", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "https://astro.build/", + "isCurrent": false, + "label": "Astro", + "type": "link", + }, + ], + "label": "Start Here", + "type": "group", + }, + { + "badge": { + "text": "Experimental", + "variant": "default", + }, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/reference/configuration.html", + "isCurrent": false, + "label": "Config Reference", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/reference/frontmatter.html", + "isCurrent": false, + "label": "Frontmatter Reference", + "type": "link", + }, + ], + "label": "Reference", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/api/v1/users.html", + "isCurrent": false, + "label": "Users API", + "type": "link", + }, + ], + "label": "API v1", + "type": "group", + }, + ] + `); + }); +}); diff --git a/packages/starlight/__tests__/build-format-file/vitest.config.ts b/packages/starlight/__tests__/build-format-file/vitest.config.ts new file mode 100644 index 00000000000..6d91108183a --- /dev/null +++ b/packages/starlight/__tests__/build-format-file/vitest.config.ts @@ -0,0 +1,51 @@ +import { defineVitestConfig } from '../test-config'; + +export default defineVitestConfig( + { + title: 'Sidebar Test', + sidebar: [ + // A single link item labelled “Home”. + { label: 'Home', link: '/' }, + // A group labelled “Start Here” containing two links. + { + label: 'Start Here', + items: [ + { + label: 'Introduction', + link: '/intro', + badge: { + variant: 'success', + text: 'New', + }, + }, + { label: 'Next Steps', link: '/next-steps', badge: 'Deprecated' }, + { + label: 'Showcase', + link: '/showcase', + attrs: { class: 'showcase-link', target: '_blank' }, + }, + { + label: 'Astro', + link: 'https://astro.build/', + }, + ], + }, + // A group linking to all pages in the reference directory. + { + label: 'Reference', + badge: 'Experimental', + autogenerate: { directory: 'reference' }, + }, + // A group linking to all pages in the api/v1 directory. + { + label: 'API v1', + autogenerate: { directory: '/api/v1/' }, + }, + ], + }, + { + build: { + format: 'file', + }, + } +); diff --git a/packages/starlight/__tests__/edit-url/edit-url.test.ts b/packages/starlight/__tests__/edit-url/edit-url.test.ts new file mode 100644 index 00000000000..197be334bb6 --- /dev/null +++ b/packages/starlight/__tests__/edit-url/edit-url.test.ts @@ -0,0 +1,49 @@ +import { expect, test, vi } from 'vitest'; +import { getRouteDataTestContext } from '../test-utils'; +import { generateRouteData } from '../../utils/routing/data'; +import { routes } from '../../utils/routing'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'Home Page' }], + ['getting-started.mdx', { title: 'Getting Started' }], + [ + 'showcase.mdx', + { title: 'Custom edit link', editUrl: 'https://example.com/custom-edit?link' }, + ], + ], + }) +); + +test('synthesizes edit URL using file location and `editLink.baseUrl`', () => { + { + const route = routes[0]!; + const data = generateRouteData({ + props: { ...route, headings: [] }, + context: getRouteDataTestContext(), + }); + expect(data.editUrl?.href).toBe( + 'https://github.com/withastro/starlight/edit/main/docs/src/content/docs/index.mdx' + ); + } + { + const route = routes[1]!; + const data = generateRouteData({ + props: { ...route, headings: [] }, + context: getRouteDataTestContext(), + }); + expect(data.editUrl?.href).toBe( + 'https://github.com/withastro/starlight/edit/main/docs/src/content/docs/getting-started.mdx' + ); + } +}); + +test('uses frontmatter `editUrl` if defined', () => { + const route = routes[2]!; + const data = generateRouteData({ + props: { ...route, headings: [] }, + context: getRouteDataTestContext(), + }); + expect(data.editUrl?.href).toBe('https://example.com/custom-edit?link'); +}); diff --git a/packages/starlight/__tests__/edit-url/vitest.config.ts b/packages/starlight/__tests__/edit-url/vitest.config.ts new file mode 100644 index 00000000000..4035c23406c --- /dev/null +++ b/packages/starlight/__tests__/edit-url/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineVitestConfig } from '../test-config'; + +export default defineVitestConfig({ + title: 'Docs With Edit Links', + editLink: { + baseUrl: 'https://github.com/withastro/starlight/edit/main/docs/', + }, +}); diff --git a/packages/starlight/__tests__/git-utils.ts b/packages/starlight/__tests__/git-utils.ts new file mode 100644 index 00000000000..75f0054b568 --- /dev/null +++ b/packages/starlight/__tests__/git-utils.ts @@ -0,0 +1,79 @@ +import { join } from 'node:path'; +import { mkdtempSync, mkdirSync, writeFileSync, realpathSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { spawnSync } from 'node:child_process'; + +export function makeTestRepo(onPath?: string) { + const repoPath = realpathSync(onPath ?? mkdtempSync(join(tmpdir(), 'starlight-test-git-'))); + + function runInRepo(command: string, args: string[], env: NodeJS.ProcessEnv = process.env) { + // Format arguments to be shell-friendly for Windows. + const formattedArgs = process.platform === 'win32' ? args.map((arg) => `"${arg}"`) : args; + const result = spawnSync(command, formattedArgs, { + cwd: repoPath, + env, + encoding: 'utf8', + // Run commands using shell on Windows to ensure proper path resolution. + shell: process.platform === 'win32', + windowsVerbatimArguments: true, + }); + + if (result.status !== 0) { + console.log(result.stdout); + console.error(result.stderr); + console.error(result.error); + throw new Error(`Failed to execute test repository command: '${command} ${args.join(' ')}'`); + } + } + + // Configure git specifically for this test repository. + runInRepo('git', ['init']); + runInRepo('git', ['config', 'user.name', 'starlight-test']); + runInRepo('git', ['config', 'user.email', 'starlight-test@example.com']); + runInRepo('git', ['config', 'commit.gpgsign', 'false']); + + return { + runInRepo, + // The `dateStr` argument should be in the `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SSZ` format. + commitAllChanges(message: string, dateStr: ISODate) { + const date = dateStr.endsWith('Z') ? dateStr : `${dateStr}T00:00:00Z`; + + runInRepo('git', ['add', '-A']); + // This sets both the author and committer dates to the provided date. + runInRepo('git', ['commit', '-m', message, '--date', date], { GIT_COMMITTER_DATE: date }); + }, + getRepoPath() { + return repoPath; + }, + getFilePath(name: string) { + return join(repoPath, name); + }, + writeFile(name: string, content: string) { + writeFileSync(join(repoPath, name), content); + }, + writeFileTree(fileTree: FileTree) { + writeFileTree(repoPath, fileTree); + }, + }; +} + +export type ISODate = + | `${number}-${number}-${number}` + | `${number}-${number}-${number}T${number}:${number}:${number}Z`; + +// Receive a file tree instead of a flattened list of files so it better works on Windows. +export type FileTree = { [name in string]: TreeEntry }; +type TreeEntry = string | FileTree; + +function writeFileTree(root: string, fileTree: FileTree) { + for (const [name, entry] of Object.entries(fileTree)) { + const path = join(root, name); + + if (typeof entry === 'string') { + writeFileSync(path, entry); + } else { + mkdirSync(path, { recursive: true }); + writeFileTree(path, entry); + } + } +} diff --git a/packages/starlight/__tests__/head/head.test.ts b/packages/starlight/__tests__/head/head.test.ts new file mode 100644 index 00000000000..14040dd25cb --- /dev/null +++ b/packages/starlight/__tests__/head/head.test.ts @@ -0,0 +1,230 @@ +import { describe, expect, test, vi } from 'vitest'; +import { getRouteDataTestContext } from '../test-utils'; +import { generateRouteData } from '../../utils/routing/data'; +import { routes } from '../../utils/routing'; +import type { HeadConfig } from '../../schemas/head'; +import { type Route } from '../../utils/routing/types'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'Home Page' }], + [ + 'environmental-impact.md', + { + title: 'Eco-friendly docs', + description: + 'Learn how Starlight can help you build greener documentation sites and reduce your carbon footprint.', + }, + ], + ], + }) +); + +test('includes custom tags defined in the Starlight configuration', () => { + const head = getTestHead(); + expect(head).toContainEqual({ + attrs: { + 'data-site': 'TEST-ANALYTICS-ID', + defer: true, + src: 'https://example.com/analytics', + }, + tag: 'script', + }); +}); + +test('includes description based on Starlight `description` configuration', () => { + const head = getTestHead(); + expect(head).toContainEqual({ + tag: 'meta', + attrs: { + name: 'description', + content: 'Docs with a custom head', + }, + }); +}); + +test('includes description based on page `description` frontmatter field if provided', () => { + const head = getTestHead({ heads: [], route: routes[1]! }); + expect(head).toContainEqual({ + tag: 'meta', + attrs: { + name: 'description', + content: + 'Learn how Starlight can help you build greener documentation sites and reduce your carbon footprint.', + }, + }); +}); + +test('includes `twitter:site` based on Starlight `social` configuration', () => { + const head = getTestHead(); + expect(head).toContainEqual({ + tag: 'meta', + attrs: { + name: 'twitter:site', + content: '@astrodotbuild', + }, + }); +}); + +test('merges two <title> tags', () => { + const head = getTestHead({ heads: [{ tag: 'title', content: 'Override' }] }); + expect(head.filter((tag) => tag.tag === 'title')).toEqual([ + { tag: 'title', content: 'Override' }, + ]); +}); + +test('merges two <link rel="canonical" href="" /> tags', () => { + const customLink = { + tag: 'link', + attrs: { rel: 'canonical', href: 'https://astro.build' }, + } as const; + const head = getTestHead({ heads: [customLink] }); + expect(head.filter((tag) => tag.tag === 'link' && tag.attrs?.rel === 'canonical')).toEqual([ + customLink, + ]); +}); + +test('merges two <link rel="sitemap" href="" /> tags', () => { + const customLink = { + tag: 'link', + attrs: { rel: 'sitemap', href: '/sitemap-custom.xml' }, + } as const; + const head = getTestHead({ heads: [customLink] }); + expect(head.filter((tag) => tag.tag === 'link' && tag.attrs?.rel === 'sitemap')).toEqual([ + customLink, + ]); +}); + +test('does not merge same link tags', () => { + const customLink = { + tag: 'link', + attrs: { rel: 'stylesheet', href: 'secondary.css' }, + } as const; + const head = getTestHead({ heads: [customLink] }); + expect(head.filter((tag) => tag.tag === 'link' && tag.attrs?.rel === 'stylesheet')).toEqual([ + { tag: 'link', attrs: { rel: 'stylesheet', href: 'primary.css' } }, + customLink, + ]); +}); + +describe.each([['name'], ['property'], ['http-equiv']])( + "<meta> tags with '%s' attributes", + (prop) => { + test(`merges two <meta> tags with same ${prop} values`, () => { + const customMeta = { + tag: 'meta', + attrs: { [prop]: 'x', content: 'Test' }, + } as const; + const head = getTestHead({ heads: [customMeta] }); + expect(head.filter((tag) => tag.tag === 'meta' && tag.attrs?.[prop] === 'x')).toEqual([ + customMeta, + ]); + }); + + test(`does not merge two <meta> tags with different ${prop} values`, () => { + const customMeta = { + tag: 'meta', + attrs: { [prop]: 'y', content: 'Test' }, + } as const; + const head = getTestHead({ heads: [customMeta] }); + expect( + head.filter( + (tag) => tag.tag === 'meta' && (tag.attrs?.[prop] === 'x' || tag.attrs?.[prop] === 'y') + ) + ).toEqual([{ tag: 'meta', attrs: { [prop]: 'x', content: 'Default' } }, customMeta]); + }); + } +); + +test('sorts head by tag importance', () => { + const head = getTestHead(); + + // `expect.objectContaining` returns `any`. + /* eslint-disable @typescript-eslint/no-unsafe-assignment */ + const expectedHeadStart = [ + // Important meta tags + { tag: 'meta', attrs: { charset: 'utf-8' } }, + { tag: 'meta', attrs: expect.objectContaining({ name: 'viewport' }) }, + { tag: 'meta', attrs: expect.objectContaining({ 'http-equiv': 'x' }) }, + // <title> + { tag: 'title', content: 'Home Page | Docs With Custom Head' }, + // Sitemap + { tag: 'link', attrs: { rel: 'sitemap', href: '/sitemap-index.xml' } }, + // Canonical link + { tag: 'link', attrs: { rel: 'canonical', href: 'https://example.com/test' } }, + // Others + { tag: 'link', attrs: expect.objectContaining({ rel: 'stylesheet' }) }, + ]; + + expect(head.slice(0, expectedHeadStart.length)).toEqual(expectedHeadStart); + + const expectedHeadEnd = [ + // SEO meta tags + { tag: 'meta', attrs: expect.objectContaining({ name: 'x' }) }, + { tag: 'meta', attrs: expect.objectContaining({ property: 'x' }) }, + ]; + /* eslint-enable @typescript-eslint/no-unsafe-assignment */ + + expect(head.slice(-expectedHeadEnd.length)).toEqual(expectedHeadEnd); +}); + +test('places the default favicon below any user provided icons', () => { + const head = getTestHead({ + heads: [ + { + tag: 'link', + attrs: { + rel: 'icon', + href: '/favicon.ico', + sizes: '32x32', + }, + }, + ], + }); + + const defaultFaviconIndex = head.findIndex( + (tag) => tag.tag === 'link' && tag.attrs?.rel === 'shortcut icon' + ); + const userFaviconIndex = head.findIndex((tag) => tag.tag === 'link' && tag.attrs?.rel === 'icon'); + + expect(defaultFaviconIndex).toBeGreaterThan(userFaviconIndex); +}); + +test('omits meta og:url tag when site is not set', () => { + const head = getTestHead({ setSite: false }); + + const ogUrlExists = head.some((tag) => tag.tag === 'meta' && tag.attrs?.property === 'og:url'); + + expect(ogUrlExists).toBe(false); +}); + +type GetTestHeadOptions = { + heads?: HeadConfig; + route?: Route; + setSite?: boolean; +}; + +function getTestHead({ + heads = [], + route = routes[0]!, + setSite, +}: GetTestHeadOptions = {}): HeadConfig { + return generateRouteData({ + props: { + ...route, + headings: [], + entry: { + ...route.entry, + data: { + ...route.entry.data, + head: [...route.entry.data.head, ...heads], + }, + }, + }, + context: + setSite === undefined + ? getRouteDataTestContext() + : getRouteDataTestContext({ setSite: setSite }), + }).head; +} diff --git a/packages/starlight/__tests__/head/vitest.config.ts b/packages/starlight/__tests__/head/vitest.config.ts new file mode 100644 index 00000000000..23642b5aea4 --- /dev/null +++ b/packages/starlight/__tests__/head/vitest.config.ts @@ -0,0 +1,22 @@ +import { defineVitestConfig } from '../test-config'; + +export default defineVitestConfig({ + title: 'Docs With Custom Head', + description: 'Docs with a custom head', + head: [ + { tag: 'link', attrs: { rel: 'canonical', href: 'https://example.com/test' } }, + { tag: 'link', attrs: { rel: 'stylesheet', href: 'primary.css' } }, + { tag: 'meta', attrs: { name: 'x', content: 'Default' } }, + { tag: 'meta', attrs: { property: 'x', content: 'Default' } }, + { tag: 'meta', attrs: { 'http-equiv': 'x', content: 'Default' } }, + { + tag: 'script', + attrs: { + src: 'https://example.com/analytics', + 'data-site': 'TEST-ANALYTICS-ID', + defer: true, + }, + }, + ], + social: [{ icon: 'twitter', label: 'Twitter', href: 'https://twitter.com/astrodotbuild' }], +}); diff --git a/packages/starlight/__tests__/i18n-non-root-single-locale/config.test.ts b/packages/starlight/__tests__/i18n-non-root-single-locale/config.test.ts new file mode 100644 index 00000000000..962cbcb62d4 --- /dev/null +++ b/packages/starlight/__tests__/i18n-non-root-single-locale/config.test.ts @@ -0,0 +1,17 @@ +import config from 'virtual:starlight/user-config'; +import { expect, test } from 'vitest'; + +test('test suite is using correct env', () => { + expect(config.title).toMatchObject({ 'fr-CA': 'i18n with a non-root single locale' }); +}); + +test('config.isMultilingual is false with a single locale', () => { + expect(config.isMultilingual).toBe(false); + expect(config.locales).keys('fr'); +}); + +test('config.defaultLocale is populated from default locale', () => { + expect(config.defaultLocale.lang).toBe('fr-CA'); + expect(config.defaultLocale.dir).toBe('ltr'); + expect(config.defaultLocale.locale).toBe('fr'); +}); diff --git a/packages/starlight/__tests__/i18n-non-root-single-locale/i18n.test.ts b/packages/starlight/__tests__/i18n-non-root-single-locale/i18n.test.ts new file mode 100644 index 00000000000..776c7177788 --- /dev/null +++ b/packages/starlight/__tests__/i18n-non-root-single-locale/i18n.test.ts @@ -0,0 +1,40 @@ +import { assert, describe, expect, test } from 'vitest'; +import type { AstroConfig } from 'astro'; +import config from 'virtual:starlight/user-config'; +import { processI18nConfig } from '../../utils/i18n'; + +describe('processI18nConfig', () => { + test('returns the Astro i18n config for a monolingual site with a non-root single locale', () => { + const { astroI18nConfig, starlightConfig } = processI18nConfig(config, undefined); + + // The default locale should match its associated custom locale `path`. + expect(astroI18nConfig.defaultLocale).toBe('fr'); + expect(astroI18nConfig.locales).toMatchInlineSnapshot(` + [ + { + "codes": [ + "fr-CA", + ], + "path": "fr", + }, + ] + `); + assert(typeof astroI18nConfig.routing !== 'string'); + expect(astroI18nConfig.routing?.prefixDefaultLocale).toBe(true); + + // The Starlight configuration should not be modified. + expect(config).toStrictEqual(starlightConfig); + }); + + test('throws an error when an Astro i18n config is also provided', () => { + expect(() => + processI18nConfig(config, { defaultLocale: 'en', locales: ['en'] } as AstroConfig['i18n']) + ).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Cannot provide both an Astro \`i18n\` configuration and a Starlight \`locales\` configuration. + Hint: + Remove one of the two configurations. + See more at https://starlight.astro.build/guides/i18n/" + `); + }); +}); diff --git a/packages/starlight/__tests__/i18n-non-root-single-locale/localizedUrl.test.ts b/packages/starlight/__tests__/i18n-non-root-single-locale/localizedUrl.test.ts new file mode 100644 index 00000000000..3ebf6de570f --- /dev/null +++ b/packages/starlight/__tests__/i18n-non-root-single-locale/localizedUrl.test.ts @@ -0,0 +1,26 @@ +import { describe, expect, test } from 'vitest'; +import { localizedUrl } from '../../utils/localizedUrl'; + +describe('with `build.output: "directory"`', () => { + test('it has no effect in a monolingual project with a non-root single locale', () => { + const url = new URL('https://example.com/fr/guide/'); + expect(localizedUrl(url, 'fr', 'ignore').href).toBe(url.href); + }); + + test('has no effect on index route in a monolingual project with a non-root single locale', () => { + const url = new URL('https://example.com/fr/'); + expect(localizedUrl(url, 'fr', 'ignore').href).toBe(url.href); + }); +}); + +describe('with `build.output: "file"`', () => { + test('it has no effect in a monolingual project with a non-root single locale', () => { + const url = new URL('https://example.com/fr/guide.html'); + expect(localizedUrl(url, 'fr', 'ignore').href).toBe(url.href); + }); + + test('has no effect on index route in a monolingual project with a non-root single locale', () => { + const url = new URL('https://example.com/fr.html'); + expect(localizedUrl(url, 'fr', 'ignore').href).toBe(url.href); + }); +}); diff --git a/packages/starlight/__tests__/i18n-non-root-single-locale/routing.test.ts b/packages/starlight/__tests__/i18n-non-root-single-locale/routing.test.ts new file mode 100644 index 00000000000..216b17b50fb --- /dev/null +++ b/packages/starlight/__tests__/i18n-non-root-single-locale/routing.test.ts @@ -0,0 +1,39 @@ +import { expect, test, vi } from 'vitest'; +import project from 'virtual:starlight/project-context'; +import { routes } from '../../utils/routing'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['fr/index.mdx', { title: 'Accueil' }], + ['en/index.mdx', { title: 'Home page' }], + ['404.md', { title: '404' }], + ], + }) +); + +test('route slugs are normalized', () => { + const indexRoute = routes.find( + (route) => route.entry.id === (project.legacyCollections ? 'fr/index.mdx' : 'fr') + ); + expect(indexRoute?.slug).toBe('fr'); +}); + +test('routes for the configured locale have locale data added', () => { + expect(routes[0]?.lang).toBe('fr-CA'); + expect(routes[0]?.dir).toBe('ltr'); + expect(routes[0]?.locale).toBe('fr'); +}); + +test('routes not matching the configured locale fall back to the default locale', () => { + for (const route of routes.slice(1)) { + expect(route.lang).toBe('fr-CA'); + expect(route.dir).toBe('ltr'); + expect(route.locale).toBe('fr'); + } +}); + +test('does not mark any route as fallback routes', () => { + const fallbacks = routes.filter((route) => route.isFallback); + expect(fallbacks.length).toBe(0); +}); diff --git a/packages/starlight/__tests__/i18n-non-root-single-locale/slugs.test.ts b/packages/starlight/__tests__/i18n-non-root-single-locale/slugs.test.ts new file mode 100644 index 00000000000..1d4e5b4189d --- /dev/null +++ b/packages/starlight/__tests__/i18n-non-root-single-locale/slugs.test.ts @@ -0,0 +1,37 @@ +import { describe, expect, test } from 'vitest'; +import { localeToLang, localizedId, localizedSlug, slugToLocaleData } from '../../utils/slugs'; + +describe('slugToLocaleData', () => { + test('returns default "fr" locale', () => { + expect(slugToLocaleData('fr/test').locale).toBe('fr'); + expect(slugToLocaleData('fr/dir/test').locale).toBe('fr'); + }); + test('returns default locale "fr" lang', () => { + expect(slugToLocaleData('fr/test').lang).toBe('fr-CA'); + expect(slugToLocaleData('fr/dir/test').lang).toBe('fr-CA'); + }); + test('returns default locale "ltr" dir', () => { + expect(slugToLocaleData('fr/test').dir).toBe('ltr'); + expect(slugToLocaleData('fr/dir/test').dir).toBe('ltr'); + }); +}); + +describe('localeToLang', () => { + test('returns lang for default locale', () => { + expect(localeToLang('fr')).toBe('fr-CA'); + }); +}); + +describe('localizedId', () => { + test('returns unchanged for default locale', () => { + expect(localizedId('fr/test.md', 'fr')).toBe('fr/test.md'); + }); +}); + +describe('localizedSlug', () => { + test('returns unchanged for default locale', () => { + expect(localizedSlug('fr', 'fr')).toBe('fr'); + expect(localizedSlug('fr/test', 'fr')).toBe('fr/test'); + expect(localizedSlug('fr/dir/test', 'fr')).toBe('fr/dir/test'); + }); +}); diff --git a/packages/starlight/__tests__/i18n-non-root-single-locale/src/content/i18n/fr.json b/packages/starlight/__tests__/i18n-non-root-single-locale/src/content/i18n/fr.json new file mode 100644 index 00000000000..2b27eb1edfd --- /dev/null +++ b/packages/starlight/__tests__/i18n-non-root-single-locale/src/content/i18n/fr.json @@ -0,0 +1,3 @@ +{ + "page.editLink": "Changer cette page" +} diff --git a/packages/starlight/__tests__/i18n-non-root-single-locale/translations-fs.test.ts b/packages/starlight/__tests__/i18n-non-root-single-locale/translations-fs.test.ts new file mode 100644 index 00000000000..76aac8f71c1 --- /dev/null +++ b/packages/starlight/__tests__/i18n-non-root-single-locale/translations-fs.test.ts @@ -0,0 +1,43 @@ +import { describe, expect, test } from 'vitest'; +import { createTranslationSystemFromFs } from '../../utils/translations-fs'; + +describe('createTranslationSystemFromFs', () => { + test('creates a translation system that returns default strings', async () => { + const useTranslations = await createTranslationSystemFromFs( + { + locales: { fr: { label: 'Français', dir: 'ltr' } }, + defaultLocale: { label: 'Français', locale: 'fr', dir: 'ltr' }, + }, + // Using non-existent `_src/` to ignore custom files in this test fixture. + { srcDir: new URL('./_src/', import.meta.url) } + ); + const t = useTranslations('fr'); + expect(t('page.editLink')).toMatchInlineSnapshot('"Modifier cette page"'); + }); + + test('creates a translation system that uses custom strings', async () => { + const useTranslations = await createTranslationSystemFromFs( + { + locales: { fr: { label: 'Français', dir: 'ltr' } }, + defaultLocale: { label: 'Français', locale: 'fr', dir: 'ltr' }, + }, + // Using `src/` to load custom files in this test fixture. + { srcDir: new URL('./src/', import.meta.url) } + ); + const t = useTranslations('fr'); + expect(t('page.editLink')).toMatchInlineSnapshot('"Changer cette page"'); + }); + + test('returns translation for unknown language', async () => { + const useTranslations = await createTranslationSystemFromFs( + { + locales: { fr: { label: 'Français', dir: 'ltr', lang: 'fr' } }, + defaultLocale: { label: 'Français', locale: 'fr', dir: 'ltr' }, + }, + // Using `src/` to load custom files in this test fixture. + { srcDir: new URL('./src/', import.meta.url) } + ); + const t = useTranslations('ar'); + expect(t('page.editLink')).toMatchInlineSnapshot('"Changer cette page"'); + }); +}); diff --git a/packages/starlight/__tests__/i18n-non-root-single-locale/translations-with-user-config.test.ts b/packages/starlight/__tests__/i18n-non-root-single-locale/translations-with-user-config.test.ts new file mode 100644 index 00000000000..8a472d04803 --- /dev/null +++ b/packages/starlight/__tests__/i18n-non-root-single-locale/translations-with-user-config.test.ts @@ -0,0 +1,17 @@ +import { describe, expect, test, vi } from 'vitest'; +import translations from '../../translations'; +import { useTranslations } from '../../utils/translations'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + i18n: [['fr-CA', { 'page.editLink': 'Modifier cette doc!' }]], + }) +); + +describe('useTranslations()', () => { + test('uses user-defined translations', () => { + const t = useTranslations('fr'); + expect(t('page.editLink')).toBe('Modifier cette doc!'); + expect(t('page.editLink')).not.toBe(translations.fr?.['page.editLink']); + }); +}); diff --git a/packages/starlight/__tests__/i18n-non-root-single-locale/translations.test.ts b/packages/starlight/__tests__/i18n-non-root-single-locale/translations.test.ts new file mode 100644 index 00000000000..3287cdf27a3 --- /dev/null +++ b/packages/starlight/__tests__/i18n-non-root-single-locale/translations.test.ts @@ -0,0 +1,24 @@ +import { describe, expect, test } from 'vitest'; +import translations from '../../translations'; +import { useTranslations } from '../../utils/translations'; + +describe('built-in translations', () => { + test('includes French', () => { + expect(translations).toHaveProperty('fr'); + }); +}); + +describe('useTranslations()', () => { + test('works when no i18n collection is available', () => { + const t = useTranslations('fr'); + expect(t).toBeTypeOf('function'); + expect(t('page.editLink')).toBe(translations.fr?.['page.editLink']); + }); + + test('returns default locale for unknown language', () => { + const locale = 'xx'; + expect(translations).not.toHaveProperty(locale); + const t = useTranslations(locale); + expect(t('page.editLink')).toBe(translations.fr?.['page.editLink']); + }); +}); diff --git a/packages/starlight/__tests__/i18n-non-root-single-locale/vitest.config.ts b/packages/starlight/__tests__/i18n-non-root-single-locale/vitest.config.ts new file mode 100644 index 00000000000..f82baa258ac --- /dev/null +++ b/packages/starlight/__tests__/i18n-non-root-single-locale/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineVitestConfig } from '../test-config'; + +export default defineVitestConfig({ + title: 'i18n with a non-root single locale', + defaultLocale: 'fr', + locales: { + fr: { label: 'Français', lang: 'fr-CA' }, + }, +}); diff --git a/packages/starlight/__tests__/i18n-root-default-locale/i18n.test.ts b/packages/starlight/__tests__/i18n-root-default-locale/i18n.test.ts new file mode 100644 index 00000000000..fb48dcf4afc --- /dev/null +++ b/packages/starlight/__tests__/i18n-root-default-locale/i18n.test.ts @@ -0,0 +1,39 @@ +import { assert, describe, expect, test } from 'vitest'; +import config from 'virtual:starlight/user-config'; +import { processI18nConfig } from '../../utils/i18n'; + +describe('processI18nConfig', () => { + test('returns Astro i18n config for a multilingual site with a root default locale', () => { + const { astroI18nConfig, starlightConfig } = processI18nConfig(config, undefined); + + // The default locale matches the root locale's `lang` property. + expect(astroI18nConfig.defaultLocale).toBe('fr'); + expect(astroI18nConfig.locales).toMatchInlineSnapshot(` + [ + { + "codes": [ + "fr", + ], + "path": "fr", + }, + { + "codes": [ + "en-US", + ], + "path": "en", + }, + { + "codes": [ + "ar", + ], + "path": "ar", + }, + ] + `); + assert(typeof astroI18nConfig.routing !== 'string'); + expect(astroI18nConfig.routing?.prefixDefaultLocale).toBe(false); + + // The Starlight configuration should not be modified. + expect(config).toStrictEqual(starlightConfig); + }); +}); diff --git a/packages/starlight/__tests__/i18n-root-default-locale/vitest.config.ts b/packages/starlight/__tests__/i18n-root-default-locale/vitest.config.ts new file mode 100644 index 00000000000..a677045a41c --- /dev/null +++ b/packages/starlight/__tests__/i18n-root-default-locale/vitest.config.ts @@ -0,0 +1,11 @@ +import { defineVitestConfig } from '../test-config'; + +export default defineVitestConfig({ + title: 'i18n with root default locale', + defaultLocale: 'root', + locales: { + root: { label: 'French', lang: 'fr' }, + en: { label: 'English', lang: 'en-US' }, + ar: { label: 'Arabic', dir: 'rtl' }, + }, +}); diff --git a/packages/starlight/__tests__/i18n-root-locale/config.test.ts b/packages/starlight/__tests__/i18n-root-locale/config.test.ts index 25e5ac32e11..fca94f3b685 100644 --- a/packages/starlight/__tests__/i18n-root-locale/config.test.ts +++ b/packages/starlight/__tests__/i18n-root-locale/config.test.ts @@ -2,7 +2,7 @@ import config from 'virtual:starlight/user-config'; import { expect, test } from 'vitest'; test('test suite is using correct env', () => { - expect(config.title).toBe('i18n with root locale'); + expect(config.title).toMatchObject({ fr: 'i18n with root locale' }); }); test('config.isMultilingual is true with multiple locales', () => { diff --git a/packages/starlight/__tests__/i18n-root-locale/i18n.test.ts b/packages/starlight/__tests__/i18n-root-locale/i18n.test.ts new file mode 100644 index 00000000000..049fad8fc23 --- /dev/null +++ b/packages/starlight/__tests__/i18n-root-locale/i18n.test.ts @@ -0,0 +1,51 @@ +import { assert, describe, expect, test } from 'vitest'; +import type { AstroConfig } from 'astro'; +import config from 'virtual:starlight/user-config'; +import { processI18nConfig } from '../../utils/i18n'; + +describe('processI18nConfig', () => { + test('returns Astro i18n config for a multilingual site with a root locale', () => { + const { astroI18nConfig, starlightConfig } = processI18nConfig(config, undefined); + + expect(astroI18nConfig.defaultLocale).toBe('fr'); + expect(astroI18nConfig.locales).toMatchInlineSnapshot(` + [ + { + "codes": [ + "fr", + ], + "path": "fr", + }, + { + "codes": [ + "en-US", + ], + "path": "en", + }, + { + "codes": [ + "ar", + ], + "path": "ar", + }, + ] + `); + assert(typeof astroI18nConfig.routing !== 'string'); + expect(astroI18nConfig.routing?.prefixDefaultLocale).toBe(false); + + // The Starlight configuration should not be modified. + expect(config).toStrictEqual(starlightConfig); + }); + + test('throws an error when an Astro i18n config is also provided', () => { + expect(() => + processI18nConfig(config, { defaultLocale: 'en', locales: ['en'] } as AstroConfig['i18n']) + ).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Cannot provide both an Astro \`i18n\` configuration and a Starlight \`locales\` configuration. + Hint: + Remove one of the two configurations. + See more at https://starlight.astro.build/guides/i18n/" + `); + }); +}); diff --git a/packages/starlight/__tests__/i18n-root-locale/localizedUrl.test.ts b/packages/starlight/__tests__/i18n-root-locale/localizedUrl.test.ts index fb1b0aacf89..326a6c3d692 100644 --- a/packages/starlight/__tests__/i18n-root-locale/localizedUrl.test.ts +++ b/packages/starlight/__tests__/i18n-root-locale/localizedUrl.test.ts @@ -1,22 +1,113 @@ -import { expect, test } from 'vitest'; +import { describe, expect, test } from 'vitest'; import { localizedUrl } from '../../utils/localizedUrl'; -test('it has no effect if locale matches', () => { - const url = new URL('https://example.com/en/guide/'); - expect(localizedUrl(url, 'en').href).toBe(url.href); -}); +describe('with `build.output: "directory"`', () => { + test('it has no effect if locale matches', () => { + const url = new URL('https://example.com/en/guide/'); + expect(localizedUrl(url, 'en', 'ignore').href).toBe(url.href); + }); + + test('it has no effect if locale matches for index', () => { + const url = new URL('https://example.com/en/'); + expect(localizedUrl(url, 'en', 'ignore').href).toBe(url.href); + }); + + test('it changes locale to requested locale', () => { + const url = new URL('https://example.com/en/guide/'); + expect(localizedUrl(url, 'ar', 'ignore').href).toBe('https://example.com/ar/guide/'); + }); + + test('it changes locale to requested locale for index', () => { + const url = new URL('https://example.com/en/'); + expect(localizedUrl(url, 'ar', 'ignore').href).toBe('https://example.com/ar/'); + }); + + test('it can change to root locale', () => { + const url = new URL('https://example.com/en/guide/'); + expect(localizedUrl(url, undefined, 'ignore').href).toBe('https://example.com/guide/'); + }); -test('it changes locale to requested locale', () => { - const url = new URL('https://example.com/en/guide/'); - expect(localizedUrl(url, 'ar').href).toBe('https://example.com/ar/guide/'); + test('it can change from root locale', () => { + const url = new URL('https://example.com/guide/'); + expect(localizedUrl(url, 'en', 'ignore').href).toBe('https://example.com/en/guide/'); + }); }); -test('it can change to root locale', () => { - const url = new URL('https://example.com/en/guide/'); - expect(localizedUrl(url, undefined).href).toBe('https://example.com/guide/'); +describe('with `trailingSlash: "never"`', () => { + test('it has no effect if locale matches', () => { + const url = new URL('https://example.com/en/guide'); + expect(localizedUrl(url, 'en', 'never').href).toBe(url.href); + }); + + test('it has no effect if locale matches for index', () => { + const url = new URL('https://example.com/en'); + expect(localizedUrl(url, 'en', 'never').href).toBe(url.href); + }); + + test('it changes locale to requested locale', () => { + const url = new URL('https://example.com/en/guide'); + expect(localizedUrl(url, 'ar', 'never').href).toBe('https://example.com/ar/guide'); + }); + + test('it changes locale to requested locale for index', () => { + const url = new URL('https://example.com/en'); + expect(localizedUrl(url, 'ar', 'never').href).toBe('https://example.com/ar'); + }); + + test('it can change to root locale', () => { + const url = new URL('https://example.com/en/guide'); + expect(localizedUrl(url, undefined, 'ignore').href).toBe('https://example.com/guide'); + }); + + test('it can change from root locale', () => { + const url = new URL('https://example.com/guide'); + expect(localizedUrl(url, 'en', 'ignore').href).toBe('https://example.com/en/guide'); + }); + + test('it can change from root index', () => { + const url = new URL('https://example.com'); + expect(localizedUrl(url, 'en', 'never').href).toBe('https://example.com/en'); + }); }); -test('it can change from root locale', () => { - const url = new URL('https://example.com/guide/'); - expect(localizedUrl(url, 'en').href).toBe('https://example.com/en/guide/'); +describe('with `build.output: "file"`', () => { + test('it has no effect if locale matches', () => { + const url = new URL('https://example.com/en/guide.html'); + expect(localizedUrl(url, 'en', 'ignore').href).toBe(url.href); + }); + + test('it has no effect if locale matches for index', () => { + const url = new URL('https://example.com/en.html'); + expect(localizedUrl(url, 'en', 'ignore').href).toBe(url.href); + }); + + test('it changes locale to requested locale', () => { + const url = new URL('https://example.com/en/guide.html'); + expect(localizedUrl(url, 'ar', 'ignore').href).toBe('https://example.com/ar/guide.html'); + }); + + test('it changes locale to requested locale for index', () => { + const url = new URL('https://example.com/en.html'); + expect(localizedUrl(url, 'ar', 'ignore').href).toBe('https://example.com/ar.html'); + }); + + test('it can change to root locale', () => { + const url = new URL('https://example.com/en/guide.html'); + expect(localizedUrl(url, undefined, 'ignore').href).toBe('https://example.com/guide.html'); + }); + + test('it can change to root locale from index', () => { + const url = new URL('https://example.com/en.html'); + expect(localizedUrl(url, undefined, 'ignore').href).toBe('https://example.com/index.html'); + }); + + test('it can change from root locale', () => { + const url = new URL('https://example.com/guide.html'); + expect(localizedUrl(url, 'en', 'ignore').href).toBe('https://example.com/en/guide.html'); + }); + + test('it can change from root locale from index', () => { + const url = new URL('https://example.com/index.html'); + expect(localizedUrl(url, 'en', 'ignore').href).toBe('https://example.com/en.html'); + }); }); diff --git a/packages/starlight/__tests__/i18n-root-locale/routing.test.ts b/packages/starlight/__tests__/i18n-root-locale/routing.test.ts index 759ad79052e..6130eeaafc5 100644 --- a/packages/starlight/__tests__/i18n-root-locale/routing.test.ts +++ b/packages/starlight/__tests__/i18n-root-locale/routing.test.ts @@ -1,23 +1,28 @@ +import project from 'virtual:starlight/project-context'; +import { getRouteDataTestContext } from '../test-utils'; import config from 'virtual:starlight/user-config'; -import { expect, test, vi } from 'vitest'; +import { assert, expect, test, vi } from 'vitest'; import { routes } from '../../utils/routing'; +import { generateRouteData } from '../../utils/routing/data'; +import * as git from 'virtual:starlight/git-info'; vi.mock('astro:content', async () => (await import('../test-utils')).mockedAstroContent({ docs: [ ['404.md', { title: 'Page introuvable' }], ['index.mdx', { title: 'Accueil' }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['en/index.mdx', { title: 'Home page' }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['ar/index.mdx', { title: 'الصفحة الرئيسية' }], - ['guides/authoring-content.md', { title: 'Création de contenu en Markdown' }], + [ + 'guides/authoring-content.mdx', + { title: 'Création de contenu en Markdown', lastUpdated: true }, + ], ], }) ); test('test suite is using correct env', () => { - expect(config.title).toBe('i18n with root locale'); + expect(config.title).toMatchObject({ fr: 'i18n with root locale' }); }); test('routes includes fallback entries for untranslated pages', () => { @@ -56,8 +61,37 @@ test('fallback routes have fallback locale data in entryMeta', () => { }); test('fallback routes use their own locale data', () => { - const enGuide = routes.find((route) => route.id === 'en/guides/authoring-content.md'); - if (!enGuide) throw new Error('Expected to find English fallback route for authoring-content.md'); + const enGuide = routes.find( + (route) => + route.id === + (project.legacyCollections + ? 'en/guides/authoring-content.mdx' + : 'en/guides/authoring-content') + ); + if (!enGuide) + throw new Error('Expected to find English fallback route for authoring-content.mdx'); expect(enGuide.locale).toBe('en'); expect(enGuide.lang).toBe('en-US'); }); + +test('fallback routes use fallback entry last updated dates', () => { + const getNewestCommitDate = vi.spyOn(git, 'getNewestCommitDate'); + const route = routes.find((route) => route.entry.id === routes[4]!.id && route.locale === 'en'); + assert(route, 'Expected to find English fallback route for `guides/authoring-content.mdx`.'); + + generateRouteData({ + props: { + ...route, + headings: [{ depth: 1, slug: 'heading-1', text: 'Heading 1' }], + }, + context: getRouteDataTestContext({ pathname: '/en' }), + }); + + expect(getNewestCommitDate).toHaveBeenCalledOnce(); + expect(getNewestCommitDate).toHaveBeenCalledWith( + 'src/content/docs/guides/authoring-content.mdx' + // ^ no `en/` prefix + ); + + getNewestCommitDate.mockRestore(); +}); diff --git a/packages/starlight/__tests__/i18n-sidebar-badge-error/i18n-sidebar-badge-error.test.ts b/packages/starlight/__tests__/i18n-sidebar-badge-error/i18n-sidebar-badge-error.test.ts new file mode 100644 index 00000000000..fddea454474 --- /dev/null +++ b/packages/starlight/__tests__/i18n-sidebar-badge-error/i18n-sidebar-badge-error.test.ts @@ -0,0 +1,20 @@ +import { describe, expect, test, vi } from 'vitest'; +import { getSidebar } from '../../utils/navigation'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [['getting-started.mdx', { title: 'Getting Started' }]], + }) +); + +describe('getSidebar', () => { + test('throws an error if an i18n badge doesn’t have a key for the default language', () => { + expect(() => getSidebar('/', undefined)).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + The badge text for "Getting Started" must have a key for the default language "en-US". + Hint: + Update the Starlight config to include a badge text for the default language. + Learn more about sidebar badges internationalization at https://starlight.astro.build/guides/sidebar/#internationalization-with-badges" + `); + }); +}); diff --git a/packages/starlight/__tests__/i18n-sidebar-badge-error/vitest.config.ts b/packages/starlight/__tests__/i18n-sidebar-badge-error/vitest.config.ts new file mode 100644 index 00000000000..a741e609357 --- /dev/null +++ b/packages/starlight/__tests__/i18n-sidebar-badge-error/vitest.config.ts @@ -0,0 +1,15 @@ +import { defineVitestConfig } from '../test-config'; + +export default defineVitestConfig({ + title: 'i18n sidebar badge error', + locales: { + fr: { label: 'French' }, + root: { label: 'English', lang: 'en-US' }, + }, + sidebar: [ + { + slug: 'getting-started', + badge: { text: { fr: 'Nouveau' } }, + }, + ], +}); diff --git a/packages/starlight/__tests__/i18n-sidebar/i18n-sidebar-fallback-slug.test.ts b/packages/starlight/__tests__/i18n-sidebar/i18n-sidebar-fallback-slug.test.ts new file mode 100644 index 00000000000..725a312da0c --- /dev/null +++ b/packages/starlight/__tests__/i18n-sidebar/i18n-sidebar-fallback-slug.test.ts @@ -0,0 +1,177 @@ +import { describe, expect, test, vi } from 'vitest'; +import { getSidebar } from '../../utils/navigation'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'Starlight 🌟 Build documentation sites with Astro' }], + ['getting-started.mdx', { title: 'Getting Started' }], + ['manual-setup.mdx', { title: 'Manual Setup' }], + ['environmental-impact.md', { title: 'Eco-friendly docs' }], + ['guides/pages.mdx', { title: 'Pages' }], + ['guides/authoring-content.mdx', { title: 'Authoring Content in Markdown' }], + ['resources/plugins.mdx', { title: 'Plugins and Integrations' }], + ], + }) +); + +describe('getSidebar', () => { + test('returns an array of sidebar entries', () => { + expect(getSidebar('/', undefined)).toMatchInlineSnapshot(` + [ + { + "attrs": {}, + "badge": undefined, + "href": "/", + "isCurrent": true, + "label": "Starlight 🌟 Build documentation sites with Astro", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/getting-started/", + "isCurrent": false, + "label": "Getting Started", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "New", + "variant": "default", + }, + "href": "/manual-setup/", + "isCurrent": false, + "label": "Do it yourself", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Eco-friendly", + "variant": "success", + }, + "href": "/environmental-impact/", + "isCurrent": false, + "label": "Eco-friendly docs", + "type": "link", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/guides/pages/", + "isCurrent": false, + "label": "Pages", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Deprecated", + "variant": "default", + }, + "href": "/guides/authoring-content/", + "isCurrent": false, + "label": "Authoring Content in Markdown", + "type": "link", + }, + ], + "label": "Guides", + "type": "group", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/resources/plugins/", + "isCurrent": false, + "label": "Plugins and Integrations", + "type": "link", + }, + ] + `); + }); + test('uses fallback labels from the default locale', () => { + expect(getSidebar('/fr', 'fr')).toMatchInlineSnapshot(` + [ + { + "attrs": {}, + "badge": undefined, + "href": "/fr/", + "isCurrent": true, + "label": "Starlight 🌟 Build documentation sites with Astro", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/fr/getting-started/", + "isCurrent": false, + "label": "Getting Started", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Nouveau", + "variant": "default", + }, + "href": "/fr/manual-setup/", + "isCurrent": false, + "label": "Fait maison", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Écologique", + "variant": "success", + }, + "href": "/fr/environmental-impact/", + "isCurrent": false, + "label": "Eco-friendly docs", + "type": "link", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/fr/guides/pages/", + "isCurrent": false, + "label": "Pages", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Deprecated", + "variant": "default", + }, + "href": "/fr/guides/authoring-content/", + "isCurrent": false, + "label": "Authoring Content in Markdown", + "type": "link", + }, + ], + "label": "Guides", + "type": "group", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/fr/resources/plugins/", + "isCurrent": false, + "label": "Plugins and Integrations", + "type": "link", + }, + ] + `); + }); +}); diff --git a/packages/starlight/__tests__/i18n-sidebar/i18n-sidebar.test.ts b/packages/starlight/__tests__/i18n-sidebar/i18n-sidebar.test.ts new file mode 100644 index 00000000000..9d7e005ee66 --- /dev/null +++ b/packages/starlight/__tests__/i18n-sidebar/i18n-sidebar.test.ts @@ -0,0 +1,306 @@ +import { describe, expect, test, vi } from 'vitest'; +import { getSidebar } from '../../utils/navigation'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'Starlight 🌟 Build documentation sites with Astro' }], + ['fr/index.mdx', { title: 'Starlight 🌟 Construire des sites de documentation avec Astro' }], + ['getting-started.mdx', { title: 'Getting Started' }], + ['fr/getting-started.mdx', { title: 'Mise en route' }], + ['manual-setup.mdx', { title: 'Manual Setup' }], + ['fr/manual-setup.mdx', { title: 'Installation manuelle' }], + ['environmental-impact.md', { title: 'Eco-friendly docs' }], + ['fr/environmental-impact.md', { title: 'Documents écologiques' }], + [ + 'guides/pages.mdx', + { + title: 'Pages', + sidebar: { label: 'Pages Guide', badge: 'Test', attrs: { class: 'test' } }, + }, + ], + ['fr/guides/pages.mdx', { title: 'Pages' }], + ['guides/authoring-content.mdx', { title: 'Authoring Content in Markdown' }], + ['fr/guides/authoring-content.mdx', { title: 'Création de contenu en Markdown' }], + ['resources/plugins.mdx', { title: 'Plugins and Integrations' }], + ['fr/resources/plugins.mdx', { title: "Modules d'extension et outils" }], + ], + }) +); + +describe('getSidebar', () => { + test('returns an array of sidebar entries', () => { + expect(getSidebar('/', undefined)).toMatchInlineSnapshot(` + [ + { + "attrs": {}, + "badge": undefined, + "href": "/", + "isCurrent": true, + "label": "Starlight 🌟 Build documentation sites with Astro", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/getting-started/", + "isCurrent": false, + "label": "Getting Started", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "New", + "variant": "default", + }, + "href": "/manual-setup/", + "isCurrent": false, + "label": "Do it yourself", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Eco-friendly", + "variant": "success", + }, + "href": "/environmental-impact/", + "isCurrent": false, + "label": "Eco-friendly docs", + "type": "link", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": { + "class": "test", + }, + "badge": { + "text": "Test", + "variant": "default", + }, + "href": "/guides/pages/", + "isCurrent": false, + "label": "Pages Guide", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Deprecated", + "variant": "default", + }, + "href": "/guides/authoring-content/", + "isCurrent": false, + "label": "Authoring Content in Markdown", + "type": "link", + }, + ], + "label": "Guides", + "type": "group", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/resources/plugins/", + "isCurrent": false, + "label": "Plugins and Integrations", + "type": "link", + }, + ] + `); + }); + test('returns an array of sidebar entries for a locale', () => { + expect(getSidebar('/fr', 'fr')).toMatchInlineSnapshot(` + [ + { + "attrs": {}, + "badge": undefined, + "href": "/fr/", + "isCurrent": true, + "label": "Starlight 🌟 Construire des sites de documentation avec Astro", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/fr/getting-started/", + "isCurrent": false, + "label": "Mise en route", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Nouveau", + "variant": "default", + }, + "href": "/fr/manual-setup/", + "isCurrent": false, + "label": "Fait maison", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Écologique", + "variant": "success", + }, + "href": "/fr/environmental-impact/", + "isCurrent": false, + "label": "Documents écologiques", + "type": "link", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/fr/guides/pages/", + "isCurrent": false, + "label": "Pages", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Deprecated", + "variant": "default", + }, + "href": "/fr/guides/authoring-content/", + "isCurrent": false, + "label": "Création de contenu en Markdown", + "type": "link", + }, + ], + "label": "Guides", + "type": "group", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/fr/resources/plugins/", + "isCurrent": false, + "label": "Modules d'extension et outils", + "type": "link", + }, + ] + `); + }); + test('returns an array of sidebar entries for a locale on current page', () => { + expect(getSidebar('/fr/getting-started', 'fr')).toMatchInlineSnapshot(` + [ + { + "attrs": {}, + "badge": undefined, + "href": "/fr/", + "isCurrent": false, + "label": "Starlight 🌟 Construire des sites de documentation avec Astro", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/fr/getting-started/", + "isCurrent": true, + "label": "Mise en route", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Nouveau", + "variant": "default", + }, + "href": "/fr/manual-setup/", + "isCurrent": false, + "label": "Fait maison", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Écologique", + "variant": "success", + }, + "href": "/fr/environmental-impact/", + "isCurrent": false, + "label": "Documents écologiques", + "type": "link", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/fr/guides/pages/", + "isCurrent": false, + "label": "Pages", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Deprecated", + "variant": "default", + }, + "href": "/fr/guides/authoring-content/", + "isCurrent": false, + "label": "Création de contenu en Markdown", + "type": "link", + }, + ], + "label": "Guides", + "type": "group", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/fr/resources/plugins/", + "isCurrent": false, + "label": "Modules d'extension et outils", + "type": "link", + }, + ] + `); + }); + test('uses label from config for internal links', () => { + const sidebar = getSidebar('/', undefined); + const entry = sidebar.find((item) => item.type === 'link' && item.href === '/manual-setup/'); + expect(entry?.label).toBe('Do it yourself'); + }); + test('uses translation from config for internal links', () => { + const sidebar = getSidebar('/fr', 'fr'); + const entry = sidebar.find((item) => item.type === 'link' && item.href === '/fr/manual-setup/'); + expect(entry?.label).toBe('Fait maison'); + }); + test('uses intermediate sidebars cached by locales', async () => { + // Reset the modules registry so that re-importing `utils/navigation.ts` re-evaluates the + // module and clears the cache of intermediate sidebars from previous tests in this file. + vi.resetModules(); + const navigation = await import('../../utils/navigation'); + const routing = await import('../../utils/routing'); + + const getLocaleRoutes = vi.spyOn(routing, 'getLocaleRoutes'); + + const paths = ['/', '/environmental-impact/', '/guides/authoring-content/']; + + for (const path of paths) { + navigation.getSidebar(path, undefined); + navigation.getSidebar(path, 'fr'); + } + + expect(getLocaleRoutes).toHaveBeenCalledTimes(2); + expect(getLocaleRoutes).toHaveBeenNthCalledWith(1, undefined); + expect(getLocaleRoutes).toHaveBeenNthCalledWith(2, 'fr'); + + getLocaleRoutes.mockRestore(); + }); +}); diff --git a/packages/starlight/__tests__/i18n-sidebar/sidebar-internal-link-error.test.ts b/packages/starlight/__tests__/i18n-sidebar/sidebar-internal-link-error.test.ts new file mode 100644 index 00000000000..65058558cf0 --- /dev/null +++ b/packages/starlight/__tests__/i18n-sidebar/sidebar-internal-link-error.test.ts @@ -0,0 +1,33 @@ +import { describe, expect, test, vi } from 'vitest'; +import { getSidebar } from '../../utils/navigation'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'Starlight 🌟 Build documentation sites with Astro' }], + ['fr/index.mdx', { title: 'Starlight 🌟 Construire des sites de documentation avec Astro' }], + ['manual-setup.mdx', { title: 'Manual Setup' }], + ['fr/manual-setup.mdx', { title: 'Installation manuelle' }], + ['environmental-impact.md', { title: 'Eco-friendly docs' }], + ['fr/environmental-impact.md', { title: 'Documents écologiques' }], + ['guides/pages.mdx', { title: 'Pages' }], + ['fr/guides/pages.mdx', { title: 'Pages' }], + ['guides/authoring-content.mdx', { title: 'Authoring Content in Markdown' }], + ['fr/guides/authoring-content.mdx', { title: 'Création de contenu en Markdown' }], + ['resources/plugins.mdx', { title: 'Plugins and Integrations' }], + ['fr/resources/plugins.mdx', { title: "Modules d'extension et outils" }], + ], + }) +); + +describe('getSidebar', () => { + test('throws an error if slug doesn’t match a content collection entry', () => { + expect(() => getSidebar('/', undefined)).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + The slug \`"getting-started"\` specified in the Starlight sidebar config does not exist. + Hint: + Update the Starlight config to reference a valid entry slug in the docs content collection. + Learn more about Astro content collection slugs at https://docs.astro.build/en/reference/modules/astro-content/#getentry" + `); + }); +}); diff --git a/packages/starlight/__tests__/i18n-sidebar/vitest.config.ts b/packages/starlight/__tests__/i18n-sidebar/vitest.config.ts new file mode 100644 index 00000000000..6cdb4d746f6 --- /dev/null +++ b/packages/starlight/__tests__/i18n-sidebar/vitest.config.ts @@ -0,0 +1,31 @@ +import { defineVitestConfig } from '../test-config'; + +export default defineVitestConfig({ + title: 'i18n sidebar', + locales: { + fr: { label: 'French' }, + root: { label: 'English', lang: 'en-US' }, + }, + sidebar: [ + { slug: 'index' }, + 'getting-started', + { + slug: 'manual-setup', + label: 'Do it yourself', + translations: { fr: 'Fait maison' }, + badge: { text: { 'en-US': 'New', fr: 'Nouveau' } }, + }, + { + slug: 'environmental-impact', + badge: { + variant: 'success', + text: { 'en-US': 'Eco-friendly', fr: 'Écologique' }, + }, + }, + { + label: 'Guides', + items: [{ slug: 'guides/pages' }, { slug: 'guides/authoring-content', badge: 'Deprecated' }], + }, + 'resources/plugins', + ], +}); diff --git a/packages/starlight/__tests__/i18n-single-root-locale/config.test.ts b/packages/starlight/__tests__/i18n-single-root-locale/config.test.ts new file mode 100644 index 00000000000..f004d1b4e1d --- /dev/null +++ b/packages/starlight/__tests__/i18n-single-root-locale/config.test.ts @@ -0,0 +1,17 @@ +import config from 'virtual:starlight/user-config'; +import { expect, test } from 'vitest'; + +test('test suite is using correct env', () => { + expect(config.title).toMatchObject({ 'fr-CA': 'i18n with a single root locale' }); +}); + +test('config.isMultilingual is false with a single root locale', () => { + expect(config.isMultilingual).toBe(false); + expect(config.locales).toBeUndefined(); +}); + +test('config.defaultLocale is populated from the single root locale', () => { + expect(config.defaultLocale.lang).toBe('fr-CA'); + expect(config.defaultLocale.dir).toBe('ltr'); + expect(config.defaultLocale.locale).toBeUndefined(); +}); diff --git a/packages/starlight/__tests__/i18n-single-root-locale/i18n.test.ts b/packages/starlight/__tests__/i18n-single-root-locale/i18n.test.ts new file mode 100644 index 00000000000..232689156e6 --- /dev/null +++ b/packages/starlight/__tests__/i18n-single-root-locale/i18n.test.ts @@ -0,0 +1,17 @@ +import { assert, describe, expect, test } from 'vitest'; +import config from 'virtual:starlight/user-config'; +import { processI18nConfig } from '../../utils/i18n'; + +describe('processI18nConfig', () => { + test('returns the Astro i18n config for a monolingual site with a single root locale', () => { + const { astroI18nConfig, starlightConfig } = processI18nConfig(config, undefined); + + expect(astroI18nConfig.defaultLocale).toBe('fr-CA'); + expect(astroI18nConfig.locales).toEqual(['fr-CA']); + assert(typeof astroI18nConfig.routing !== 'string'); + expect(astroI18nConfig.routing?.prefixDefaultLocale).toBe(false); + + // The Starlight configuration should not be modified. + expect(config).toStrictEqual(starlightConfig); + }); +}); diff --git a/packages/starlight/__tests__/i18n-single-root-locale/routing.test.ts b/packages/starlight/__tests__/i18n-single-root-locale/routing.test.ts new file mode 100644 index 00000000000..a356dd4b671 --- /dev/null +++ b/packages/starlight/__tests__/i18n-single-root-locale/routing.test.ts @@ -0,0 +1,33 @@ +import { expect, test, vi } from 'vitest'; +import project from 'virtual:starlight/project-context'; +import { routes } from '../../utils/routing'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'Accueil' }], + ['guides/authoring-content.mdx', { title: 'Authoring content' }], + ['en/index.mdx', { title: 'Not the home page' }], + ], + }) +); + +test('route slugs are normalized', () => { + const indexRoute = routes.find( + (route) => route.id === (project.legacyCollections ? 'index.mdx' : '') + ); + expect(indexRoute?.slug).toBe(''); +}); + +test('routes have locale data added', () => { + for (const route of routes) { + expect(route.lang).toBe('fr-CA'); + expect(route.dir).toBe('ltr'); + expect(route.locale).toBeUndefined(); + } +}); + +test('does not mark any route as fallback routes', () => { + const fallbacks = routes.filter((route) => route.isFallback); + expect(fallbacks.length).toBe(0); +}); diff --git a/packages/starlight/__tests__/i18n-single-root-locale/slugs.test.ts b/packages/starlight/__tests__/i18n-single-root-locale/slugs.test.ts new file mode 100644 index 00000000000..ba32999802b --- /dev/null +++ b/packages/starlight/__tests__/i18n-single-root-locale/slugs.test.ts @@ -0,0 +1,36 @@ +import { describe, expect, test } from 'vitest'; +import { localeToLang, localizedId, localizedSlug, slugToLocaleData } from '../../utils/slugs'; + +describe('slugToLocaleData', () => { + test('returns an undefined locale for root locale slugs', () => { + expect(slugToLocaleData('test').locale).toBeUndefined(); + expect(slugToLocaleData('dir/test').locale).toBeUndefined(); + }); + test('returns default locale "fr" lang', () => { + expect(slugToLocaleData('test').lang).toBe('fr-CA'); + expect(slugToLocaleData('dir/test').lang).toBe('fr-CA'); + }); + test('returns default locale "ltr" dir', () => { + expect(slugToLocaleData('test').dir).toBe('ltr'); + expect(slugToLocaleData('dir/test').dir).toBe('ltr'); + }); +}); + +describe('localeToLang', () => { + test('returns lang for default locale', () => { + expect(localeToLang(undefined)).toBe('fr-CA'); + }); +}); + +describe('localizedId', () => { + test('returns unchanged for default locale', () => { + expect(localizedId('test.md', undefined)).toBe('test.md'); + }); +}); + +describe('localizedSlug', () => { + test('returns unchanged for default locale', () => { + expect(localizedSlug('test', undefined)).toBe('test'); + expect(localizedSlug('dir/test', undefined)).toBe('dir/test'); + }); +}); diff --git a/packages/starlight/__tests__/i18n-single-root-locale/src/content/i18n/fr.json b/packages/starlight/__tests__/i18n-single-root-locale/src/content/i18n/fr.json new file mode 100644 index 00000000000..2b27eb1edfd --- /dev/null +++ b/packages/starlight/__tests__/i18n-single-root-locale/src/content/i18n/fr.json @@ -0,0 +1,3 @@ +{ + "page.editLink": "Changer cette page" +} diff --git a/packages/starlight/__tests__/i18n-single-root-locale/translations-fs.test.ts b/packages/starlight/__tests__/i18n-single-root-locale/translations-fs.test.ts new file mode 100644 index 00000000000..843490f9934 --- /dev/null +++ b/packages/starlight/__tests__/i18n-single-root-locale/translations-fs.test.ts @@ -0,0 +1,43 @@ +import { describe, expect, test } from 'vitest'; +import { createTranslationSystemFromFs } from '../../utils/translations-fs'; + +describe('createTranslationSystemFromFs', () => { + test('creates a translation system that returns default strings', async () => { + const useTranslations = await createTranslationSystemFromFs( + { + locales: undefined, + defaultLocale: { label: 'Français', locale: 'fr', dir: 'ltr' }, + }, + // Using non-existent `_src/` to ignore custom files in this test fixture. + { srcDir: new URL('./_src/', import.meta.url) } + ); + const t = useTranslations('fr'); + expect(t('page.editLink')).toMatchInlineSnapshot('"Modifier cette page"'); + }); + + test('creates a translation system that uses custom strings', async () => { + const useTranslations = await createTranslationSystemFromFs( + { + locales: undefined, + defaultLocale: { label: 'Français', locale: 'fr', dir: 'ltr' }, + }, + // Using `src/` to load custom files in this test fixture. + { srcDir: new URL('./src/', import.meta.url) } + ); + const t = useTranslations('fr'); + expect(t('page.editLink')).toMatchInlineSnapshot('"Changer cette page"'); + }); + + test('returns translation for unknown language', async () => { + const useTranslations = await createTranslationSystemFromFs( + { + locales: undefined, + defaultLocale: { label: 'Français', locale: 'fr', dir: 'ltr' }, + }, + // Using `src/` to load custom files in this test fixture. + { srcDir: new URL('./src/', import.meta.url) } + ); + const t = useTranslations('ar'); + expect(t('page.editLink')).toMatchInlineSnapshot('"Changer cette page"'); + }); +}); diff --git a/packages/starlight/__tests__/i18n-single-root-locale/translations-with-user-config.test.ts b/packages/starlight/__tests__/i18n-single-root-locale/translations-with-user-config.test.ts new file mode 100644 index 00000000000..8a472d04803 --- /dev/null +++ b/packages/starlight/__tests__/i18n-single-root-locale/translations-with-user-config.test.ts @@ -0,0 +1,17 @@ +import { describe, expect, test, vi } from 'vitest'; +import translations from '../../translations'; +import { useTranslations } from '../../utils/translations'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + i18n: [['fr-CA', { 'page.editLink': 'Modifier cette doc!' }]], + }) +); + +describe('useTranslations()', () => { + test('uses user-defined translations', () => { + const t = useTranslations('fr'); + expect(t('page.editLink')).toBe('Modifier cette doc!'); + expect(t('page.editLink')).not.toBe(translations.fr?.['page.editLink']); + }); +}); diff --git a/packages/starlight/__tests__/i18n-single-root-locale/translations.test.ts b/packages/starlight/__tests__/i18n-single-root-locale/translations.test.ts new file mode 100644 index 00000000000..3287cdf27a3 --- /dev/null +++ b/packages/starlight/__tests__/i18n-single-root-locale/translations.test.ts @@ -0,0 +1,24 @@ +import { describe, expect, test } from 'vitest'; +import translations from '../../translations'; +import { useTranslations } from '../../utils/translations'; + +describe('built-in translations', () => { + test('includes French', () => { + expect(translations).toHaveProperty('fr'); + }); +}); + +describe('useTranslations()', () => { + test('works when no i18n collection is available', () => { + const t = useTranslations('fr'); + expect(t).toBeTypeOf('function'); + expect(t('page.editLink')).toBe(translations.fr?.['page.editLink']); + }); + + test('returns default locale for unknown language', () => { + const locale = 'xx'; + expect(translations).not.toHaveProperty(locale); + const t = useTranslations(locale); + expect(t('page.editLink')).toBe(translations.fr?.['page.editLink']); + }); +}); diff --git a/packages/starlight/__tests__/i18n-single-root-locale/vitest.config.ts b/packages/starlight/__tests__/i18n-single-root-locale/vitest.config.ts new file mode 100644 index 00000000000..4c2f6cf6b6a --- /dev/null +++ b/packages/starlight/__tests__/i18n-single-root-locale/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineVitestConfig } from '../test-config'; + +export default defineVitestConfig({ + title: 'i18n with a single root locale', + locales: { + root: { label: 'Français', lang: 'fr-CA' }, + }, +}); diff --git a/packages/starlight/__tests__/i18n/config.test.ts b/packages/starlight/__tests__/i18n/config.test.ts index 0e8e9c8db26..193595bf614 100644 --- a/packages/starlight/__tests__/i18n/config.test.ts +++ b/packages/starlight/__tests__/i18n/config.test.ts @@ -2,7 +2,7 @@ import config from 'virtual:starlight/user-config'; import { expect, test } from 'vitest'; test('test suite is using correct env', () => { - expect(config.title).toBe('i18n with no root locale'); + expect(config.title).toMatchObject({ 'en-US': 'i18n with no root locale' }); }); test('config.isMultilingual is true with multiple locales', () => { diff --git a/packages/starlight/components/EmptyMarkdown.md b/packages/starlight/__tests__/i18n/empty-src/content/i18n/.gitkeep similarity index 100% rename from packages/starlight/components/EmptyMarkdown.md rename to packages/starlight/__tests__/i18n/empty-src/content/i18n/.gitkeep diff --git a/packages/starlight/__tests__/i18n/head.test.ts b/packages/starlight/__tests__/i18n/head.test.ts new file mode 100644 index 00000000000..755a0b68bd2 --- /dev/null +++ b/packages/starlight/__tests__/i18n/head.test.ts @@ -0,0 +1,29 @@ +import { expect, test, vi } from 'vitest'; +import config from 'virtual:starlight/user-config'; +import { getRouteDataTestContext } from '../test-utils'; +import { generateRouteData } from '../../utils/routing/data'; +import { routes } from '../../utils/routing'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [['index.mdx', { title: 'Home Page' }]], + }) +); + +test('includes links to language alternates', () => { + const route = routes[0]!; + const { head } = generateRouteData({ + props: { ...route, headings: [] }, + context: getRouteDataTestContext(), + }); + for (const [locale, localeConfig] of Object.entries(config.locales!)) { + expect(head).toContainEqual({ + tag: 'link', + attrs: { + rel: 'alternate', + href: `https://example.com/${locale}/`, + hreflang: localeConfig?.lang, + }, + }); + } +}); diff --git a/packages/starlight/__tests__/i18n/i18n.test.ts b/packages/starlight/__tests__/i18n/i18n.test.ts new file mode 100644 index 00000000000..770cb379711 --- /dev/null +++ b/packages/starlight/__tests__/i18n/i18n.test.ts @@ -0,0 +1,58 @@ +import { assert, describe, expect, test } from 'vitest'; +import type { AstroConfig } from 'astro'; +import config from 'virtual:starlight/user-config'; +import { processI18nConfig } from '../../utils/i18n'; + +describe('processI18nConfig', () => { + test('returns the Astro i18n config for a multilingual site with no root locale', () => { + const { astroI18nConfig, starlightConfig } = processI18nConfig(config, undefined); + + // The default locale should match its associated custom locale `path`. + expect(astroI18nConfig.defaultLocale).toBe('en'); + expect(astroI18nConfig.locales).toMatchInlineSnapshot(` + [ + { + "codes": [ + "fr", + ], + "path": "fr", + }, + { + "codes": [ + "en-US", + ], + "path": "en", + }, + { + "codes": [ + "ar", + ], + "path": "ar", + }, + { + "codes": [ + "pt-BR", + ], + "path": "pt-br", + }, + ] + `); + assert(typeof astroI18nConfig.routing !== 'string'); + expect(astroI18nConfig.routing?.prefixDefaultLocale).toBe(true); + + // The Starlight configuration should not be modified. + expect(config).toStrictEqual(starlightConfig); + }); + + test('throws an error when an Astro i18n config is also provided', () => { + expect(() => + processI18nConfig(config, { defaultLocale: 'en', locales: ['en'] } as AstroConfig['i18n']) + ).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Cannot provide both an Astro \`i18n\` configuration and a Starlight \`locales\` configuration. + Hint: + Remove one of the two configurations. + See more at https://starlight.astro.build/guides/i18n/" + `); + }); +}); diff --git a/packages/starlight/__tests__/i18n/localizedUrl.test.ts b/packages/starlight/__tests__/i18n/localizedUrl.test.ts index 5bdc5e084f9..b138af3752b 100644 --- a/packages/starlight/__tests__/i18n/localizedUrl.test.ts +++ b/packages/starlight/__tests__/i18n/localizedUrl.test.ts @@ -1,12 +1,46 @@ -import { expect, test } from 'vitest'; +import { describe, expect, test } from 'vitest'; import { localizedUrl } from '../../utils/localizedUrl'; -test('it has no effect if locale matches', () => { - const url = new URL('https://example.com/en/guide/'); - expect(localizedUrl(url, 'en').href).toBe(url.href); +describe('with `build.output: "directory"`', () => { + test('it has no effect if locale matches', () => { + const url = new URL('https://example.com/en/guide/'); + expect(localizedUrl(url, 'en', 'ignore').href).toBe(url.href); + }); + + test('it has no effect if locale matches for index', () => { + const url = new URL('https://example.com/en/'); + expect(localizedUrl(url, 'en', 'ignore').href).toBe(url.href); + }); + + test('it changes locale to requested locale', () => { + const url = new URL('https://example.com/en/guide/'); + expect(localizedUrl(url, 'fr', 'ignore').href).toBe('https://example.com/fr/guide/'); + }); + + test('it changes locale to requested locale for index', () => { + const url = new URL('https://example.com/en/'); + expect(localizedUrl(url, 'fr', 'ignore').href).toBe('https://example.com/fr/'); + }); }); -test('it changes locale to requested locale', () => { - const url = new URL('https://example.com/en/guide/'); - expect(localizedUrl(url, 'fr').href).toBe('https://example.com/fr/guide/'); +describe('with `build.output: "file"`', () => { + test('it has no effect if locale matches', () => { + const url = new URL('https://example.com/en/guide.html'); + expect(localizedUrl(url, 'en', 'ignore').href).toBe(url.href); + }); + + test('it has no effect if locale matches for index', () => { + const url = new URL('https://example.com/en.html'); + expect(localizedUrl(url, 'en', 'ignore').href).toBe(url.href); + }); + + test('it changes locale to requested locale', () => { + const url = new URL('https://example.com/en/guide.html'); + expect(localizedUrl(url, 'fr', 'ignore').href).toBe('https://example.com/fr/guide.html'); + }); + + test('it changes locale to requested locale for index', () => { + const url = new URL('https://example.com/en.html'); + expect(localizedUrl(url, 'fr', 'ignore').href).toBe('https://example.com/fr.html'); + }); }); diff --git a/packages/starlight/__tests__/i18n/malformed-json-src/content/i18n/en.json b/packages/starlight/__tests__/i18n/malformed-json-src/content/i18n/en.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/starlight/__tests__/i18n/malformed-yaml-src/content/i18n/en.yml b/packages/starlight/__tests__/i18n/malformed-yaml-src/content/i18n/en.yml new file mode 100644 index 00000000000..6fa1f17258a --- /dev/null +++ b/packages/starlight/__tests__/i18n/malformed-yaml-src/content/i18n/en.yml @@ -0,0 +1 @@ +test: 'Malformed YAML file with dangling trailing comma', diff --git a/packages/starlight/__tests__/i18n/navigation-order.test.ts b/packages/starlight/__tests__/i18n/navigation-order.test.ts index 989f8a99542..96e60f9ca73 100644 --- a/packages/starlight/__tests__/i18n/navigation-order.test.ts +++ b/packages/starlight/__tests__/i18n/navigation-order.test.ts @@ -5,21 +5,13 @@ vi.mock('astro:content', async () => (await import('../test-utils')).mockedAstroContent({ docs: [ ['fr/index.mdx', { title: 'Accueil' }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['en/index.mdx', { title: 'Home page', sidebar: { order: 1 } }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['ar/index.mdx', { title: 'الصفحة الرئيسية' }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['en/guides/authoring-content.md', { title: 'Authoring Markdown' }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['en/404.md', { title: 'Not found' }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['fr/route/distribuer.mdx', { title: 'Distribuer' }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['fr/route/décoder.mdx', { title: 'Décoder' }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['fr/référence/bricolage.mdx', { title: 'Bricolage' }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['fr/référence/bénéfice.mdx', { title: 'Bénéfice' }], ], }) @@ -30,6 +22,7 @@ describe('getSidebar', () => { expect(getSidebar('/en/', 'en')).toMatchInlineSnapshot(` [ { + "attrs": {}, "badge": undefined, "href": "/en/", "isCurrent": true, @@ -37,6 +30,7 @@ describe('getSidebar', () => { "type": "link", }, { + "attrs": {}, "badge": undefined, "href": "/en/404/", "isCurrent": false, @@ -44,9 +38,11 @@ describe('getSidebar', () => { "type": "link", }, { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, "badge": undefined, "href": "/en/guides/authoring-content/", "isCurrent": false, @@ -65,6 +61,7 @@ describe('getSidebar', () => { expect(getSidebar('/fr/', 'fr')).toMatchInlineSnapshot(` [ { + "attrs": {}, "badge": undefined, "href": "/fr/", "isCurrent": true, @@ -72,6 +69,7 @@ describe('getSidebar', () => { "type": "link", }, { + "attrs": {}, "badge": undefined, "href": "/fr/404/", "isCurrent": false, @@ -79,9 +77,11 @@ describe('getSidebar', () => { "type": "link", }, { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, "badge": undefined, "href": "/fr/guides/authoring-content/", "isCurrent": false, @@ -93,9 +93,11 @@ describe('getSidebar', () => { "type": "group", }, { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, "badge": undefined, "href": "/fr/référence/bénéfice/", "isCurrent": false, @@ -103,6 +105,7 @@ describe('getSidebar', () => { "type": "link", }, { + "attrs": {}, "badge": undefined, "href": "/fr/référence/bricolage/", "isCurrent": false, @@ -114,9 +117,11 @@ describe('getSidebar', () => { "type": "group", }, { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, "badge": undefined, "href": "/fr/route/décoder/", "isCurrent": false, @@ -124,6 +129,7 @@ describe('getSidebar', () => { "type": "link", }, { + "attrs": {}, "badge": undefined, "href": "/fr/route/distribuer/", "isCurrent": false, diff --git a/packages/starlight/__tests__/i18n/routing.test.ts b/packages/starlight/__tests__/i18n/routing.test.ts index 18d8ed89792..7e9f254a06e 100644 --- a/packages/starlight/__tests__/i18n/routing.test.ts +++ b/packages/starlight/__tests__/i18n/routing.test.ts @@ -1,4 +1,5 @@ import config from 'virtual:starlight/user-config'; +import project from 'virtual:starlight/project-context'; import { expect, test, vi } from 'vitest'; import { routes } from '../../utils/routing'; @@ -6,20 +7,18 @@ vi.mock('astro:content', async () => (await import('../test-utils')).mockedAstroContent({ docs: [ ['fr/index.mdx', { title: 'Accueil' }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['en/index.mdx', { title: 'Home page' }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['ar/index.mdx', { title: 'الصفحة الرئيسية' }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['en/guides/authoring-content.md', { title: 'Création de contenu en Markdown' }], - // @ts-expect-error — Using a slug not present in Starlight docs site ['en/404.md', { title: 'Page introuvable' }], + ['it/index.mdx', { title: 'Pagina iniziale' }], + ['404.md', { title: '404' }], ], }) ); test('test suite is using correct env', () => { - expect(config.title).toBe('i18n with no root locale'); + expect(config.title).toMatchObject({ 'en-US': 'i18n with no root locale' }); }); test('routes includes fallback entries for untranslated pages', () => { @@ -42,6 +41,14 @@ test('routes have locale data added', () => { expect(lang).toBe('fr'); expect(dir).toBe('ltr'); expect(locale).toBe('fr'); + } else if (id.startsWith('pt-br')) { + expect(lang).toBe('pt-BR'); + expect(dir).toBe('ltr'); + expect(locale).toBe('pt-br'); + } else { + expect(lang).toBe('en-US'); + expect(dir).toBe('ltr'); + expect(locale).toBe('en'); } } }); @@ -58,7 +65,11 @@ test('fallback routes have fallback locale data in entryMeta', () => { }); test('fallback routes use their own locale data', () => { - const arGuide = routes.find((route) => route.id === 'ar/guides/authoring-content.md'); + const arGuide = routes.find( + (route) => + route.id === + (project.legacyCollections ? 'ar/guides/authoring-content.md' : 'ar/guides/authoring-content') + ); if (!arGuide) throw new Error('Expected to find Arabic fallback route for authoring-content.md'); expect(arGuide.locale).toBe('ar'); expect(arGuide.lang).toBe('ar'); diff --git a/packages/starlight/__tests__/i18n/src/content/i18n/en.json b/packages/starlight/__tests__/i18n/src/content/i18n/en.json new file mode 100644 index 00000000000..099e4c00f8f --- /dev/null +++ b/packages/starlight/__tests__/i18n/src/content/i18n/en.json @@ -0,0 +1,3 @@ +{ + "page.editLink": "Make this page different" +} diff --git a/packages/starlight/__tests__/i18n/src/content/i18n/fr.yml b/packages/starlight/__tests__/i18n/src/content/i18n/fr.yml new file mode 100644 index 00000000000..df8ac1bd57b --- /dev/null +++ b/packages/starlight/__tests__/i18n/src/content/i18n/fr.yml @@ -0,0 +1 @@ +page.editLink: Rendre cette page différente diff --git a/packages/starlight/__tests__/i18n/translations-ec.test.ts b/packages/starlight/__tests__/i18n/translations-ec.test.ts new file mode 100644 index 00000000000..8e09b7ea4bc --- /dev/null +++ b/packages/starlight/__tests__/i18n/translations-ec.test.ts @@ -0,0 +1,130 @@ +import { pluginFramesTexts } from 'astro-expressive-code'; +import { afterEach, expect, test, vi } from 'vitest'; +import { addTranslations } from '../../integrations/expressive-code/translations'; +import { StarlightConfigSchema, type StarlightUserConfig } from '../../utils/user-config'; + +vi.mock('astro-expressive-code', async () => { + const mod = + await vi.importActual<typeof import('astro-expressive-code')>('astro-expressive-code'); + return { + ...mod, + pluginFramesTexts: { + ...mod.pluginFramesTexts, + overrideTexts: vi.fn(), + }, + }; +}); + +afterEach(() => { + vi.clearAllMocks(); +}); + +test('adds default english translations with no i18n config', () => { + const [config, useTranslations] = getStarlightConfigAndUseTranslations(undefined); + + addTranslations(config, useTranslations); + + expect(getExpressiveCodeOverriddenLanguages()).toEqual(['en']); +}); + +test('adds translations in a monolingual site with english as root locale', () => { + const [config, useTranslations] = getStarlightConfigAndUseTranslations({ + root: { label: 'English', lang: 'en' }, + }); + + addTranslations(config, useTranslations); + + expect(getExpressiveCodeOverriddenLanguages()).toEqual(['en']); +}); + +test('adds translations in a monolingual site with french as root locale', () => { + const [config, useTranslations] = getStarlightConfigAndUseTranslations({ + root: { label: 'Français', lang: 'fr' }, + }); + + addTranslations(config, useTranslations); + + expect(getExpressiveCodeOverriddenLanguages()).toEqual(['fr']); +}); + +test('add translations in a multilingual site with english as root locale', () => { + const [config, useTranslations] = getStarlightConfigAndUseTranslations({ + root: { label: 'English', lang: 'en' }, + fr: { label: 'French' }, + }); + + addTranslations(config, useTranslations); + + expect(getExpressiveCodeOverriddenLanguages()).toEqual(['en', 'fr']); +}); + +test('add translations in a multilingual site with french as root locale', () => { + const [config, useTranslations] = getStarlightConfigAndUseTranslations({ + root: { label: 'French', lang: 'fr' }, + ru: { label: 'Русский', lang: 'ru' }, + }); + + addTranslations(config, useTranslations); + + expect(getExpressiveCodeOverriddenLanguages()).toEqual(['fr', 'ru']); +}); + +test('add translations in a multilingual site with english as default locale', () => { + const [config, useTranslations] = getStarlightConfigAndUseTranslations( + { + en: { label: 'English', lang: 'en' }, + fr: { label: 'French' }, + }, + 'en' + ); + + addTranslations(config, useTranslations); + + expect(getExpressiveCodeOverriddenLanguages()).toEqual(['en', 'fr']); +}); + +test('add translations in a multilingual site with french as default locale', () => { + const [config, useTranslations] = getStarlightConfigAndUseTranslations( + { + fr: { label: 'French', lang: 'fr' }, + ru: { label: 'Русский', lang: 'ru' }, + }, + 'fr' + ); + + addTranslations(config, useTranslations); + + expect(getExpressiveCodeOverriddenLanguages()).toEqual(['fr', 'ru']); +}); + +test('does not add translations if the label does not exist', () => { + const [config] = getStarlightConfigAndUseTranslations(undefined); + + addTranslations(config, getUseTranslations(false)); + + expect(vi.mocked(pluginFramesTexts.overrideTexts)).not.toHaveBeenCalled(); +}); + +function getUseTranslations(exists: boolean = true) { + const t = () => 'test UI string'; + t.exists = vi.fn().mockReturnValue(exists); + return vi.fn().mockReturnValue(t); +} + +function getStarlightConfigAndUseTranslations( + locales: StarlightUserConfig['locales'], + defaultLocale?: StarlightUserConfig['defaultLocale'] +) { + return [ + StarlightConfigSchema.parse({ + title: 'Expressive Code Translations Test', + locales, + defaultLocale, + }), + getUseTranslations(), + ] as const; +} + +function getExpressiveCodeOverriddenLanguages() { + return [...new Set(vi.mocked(pluginFramesTexts.overrideTexts).mock.calls.map(([lang]) => lang))]; +} diff --git a/packages/starlight/__tests__/i18n/translations-fs.test.ts b/packages/starlight/__tests__/i18n/translations-fs.test.ts new file mode 100644 index 00000000000..f715bf126c6 --- /dev/null +++ b/packages/starlight/__tests__/i18n/translations-fs.test.ts @@ -0,0 +1,122 @@ +import { describe, expect, test } from 'vitest'; +import { createTranslationSystemFromFs } from '../../utils/translations-fs'; +import { YAMLException } from 'js-yaml'; + +describe('createTranslationSystemFromFs', () => { + test('creates a translation system that returns default strings', async () => { + const useTranslations = await createTranslationSystemFromFs( + { + locales: { en: { label: 'English', dir: 'ltr' } }, + defaultLocale: { label: 'English', locale: 'en', dir: 'ltr' }, + }, + // Using non-existent `_src/` to ignore custom files in this test fixture. + { srcDir: new URL('./_src/', import.meta.url) } + ); + const t = useTranslations('en'); + expect(t('page.editLink')).toMatchInlineSnapshot('"Edit page"'); + }); + + test('creates a translation system that uses custom strings', async () => { + const useTranslations = await createTranslationSystemFromFs( + { + locales: { + en: { label: 'English', dir: 'ltr', lang: 'en' }, + fr: { label: 'Français', dir: 'ltr', lang: 'fr' }, + }, + defaultLocale: { label: 'English', locale: 'en', dir: 'ltr' }, + }, + // Using `src/` to load custom files in this test fixture. + { srcDir: new URL('./src/', import.meta.url) } + ); + // From an i18n JSON file + let t = useTranslations('en'); + expect(t('page.editLink')).toMatchInlineSnapshot('"Make this page different"'); + // From an i18n YAML file + t = useTranslations('fr'); + expect(t('page.editLink')).toMatchInlineSnapshot('"Rendre cette page différente"'); + }); + + test('supports root locale', async () => { + const useTranslations = await createTranslationSystemFromFs( + { + locales: { root: { label: 'English', dir: 'ltr', lang: 'en' } }, + defaultLocale: { label: 'English', locale: 'root', lang: 'en', dir: 'ltr' }, + }, + // Using `src/` to load custom files in this test fixture. + { srcDir: new URL('./src/', import.meta.url) } + ); + const t = useTranslations(undefined); + expect(t('page.editLink')).toMatchInlineSnapshot('"Make this page different"'); + }); + + test('returns translation for unknown language', async () => { + const useTranslations = await createTranslationSystemFromFs( + { + locales: { root: { label: 'English', dir: 'ltr', lang: 'en' } }, + defaultLocale: { label: 'English', locale: undefined, dir: 'ltr' }, + }, + // Using `src/` to load custom files in this test fixture. + { srcDir: new URL('./src/', import.meta.url) } + ); + const t = useTranslations('fr'); + expect(t('page.editLink')).toMatchInlineSnapshot('"Make this page different"'); + }); + + test('handles empty i18n directory', async () => { + const useTranslations = await createTranslationSystemFromFs( + { locales: {}, defaultLocale: { label: 'English', locale: 'en', dir: 'ltr' } }, + // Using `empty-src/` to emulate empty `src/content/i18n/` directory. + { srcDir: new URL('./empty-src/', import.meta.url) } + ); + const t = useTranslations('en'); + expect(t('page.editLink')).toMatchInlineSnapshot('"Edit page"'); + }); + + test('throws on malformed i18n JSON', async () => { + await expect(() => + createTranslationSystemFromFs( + { locales: {}, defaultLocale: { label: 'English', locale: 'en', dir: 'ltr' } }, + // Using `malformed-json-src/` to trigger syntax error in bad JSON file. + { srcDir: new URL('./malformed-json-src/', import.meta.url) } + ) + ).rejects.toThrow(SyntaxError); + }); + + test('throws on malformed i18n YAML', async () => { + await expect(() => + createTranslationSystemFromFs( + { locales: {}, defaultLocale: { label: 'English', locale: 'en', dir: 'ltr' } }, + // Using `malformed-yaml-src/` to trigger syntax error in bad YAML file. + { srcDir: new URL('./malformed-yaml-src/', import.meta.url) } + ) + ).rejects.toThrow(YAMLException); + }); + + test('creates a translation system that uses custom strings injected by plugins', async () => { + const useTranslations = await createTranslationSystemFromFs( + { + locales: { en: { label: 'English', dir: 'ltr' } }, + defaultLocale: { label: 'English', locale: 'en', dir: 'ltr' }, + }, + // Using non-existent `_src/` to ignore custom files in this test fixture. + { srcDir: new URL('./_src/', import.meta.url) }, + { en: { 'page.editLink': 'Make this page even more different' } } + ); + const t = useTranslations('en'); + expect(t('page.editLink')).toMatchInlineSnapshot('"Make this page even more different"'); + }); + + test('creates a translation system that prioritizes user translations over plugin translations', async () => { + const useTranslations = await createTranslationSystemFromFs( + { + locales: { en: { label: 'English', dir: 'ltr' } }, + defaultLocale: { label: 'English', locale: 'en', dir: 'ltr' }, + }, + // Using `src/` to load custom files in this test fixture. + { srcDir: new URL('./src/', import.meta.url) }, + { en: { 'page.editLink': 'Make this page even more different' } } + ); + const t = useTranslations('en'); + expect(t('page.editLink')).toMatchInlineSnapshot('"Make this page different"'); + }); +}); diff --git a/packages/starlight/__tests__/i18n/translations-with-user-config.test.ts b/packages/starlight/__tests__/i18n/translations-with-user-config.test.ts index 4335aa030af..c11cb25e95f 100644 --- a/packages/starlight/__tests__/i18n/translations-with-user-config.test.ts +++ b/packages/starlight/__tests__/i18n/translations-with-user-config.test.ts @@ -19,7 +19,7 @@ describe('useTranslations()', () => { }); test('uses user-defined regional translations when available', () => { - const t = useTranslations('pt-br'); + const t = useTranslations('pt-BR'); expect(t('page.editLink')).toBe('Modifique esse doc!'); expect(t('page.editLink')).not.toBe(translations.pt?.['page.editLink']); }); diff --git a/packages/starlight/__tests__/i18n/translations.test.ts b/packages/starlight/__tests__/i18n/translations.test.ts index a8442166f83..54899092fe9 100644 --- a/packages/starlight/__tests__/i18n/translations.test.ts +++ b/packages/starlight/__tests__/i18n/translations.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, test, vi } from 'vitest'; +import { describe, expect, test } from 'vitest'; import translations from '../../translations'; import { useTranslations } from '../../utils/translations'; @@ -22,17 +22,17 @@ describe('useTranslations()', () => { expect(t('page.editLink')).toBe(translations.en?.['page.editLink']); }); - test('returns a pick method for filtering by key', () => { - const t = useTranslations('en'); - expect(t.pick('tableOfContents.')).toEqual({ - 'tableOfContents.onThisPage': 'On this page', - 'tableOfContents.overview': 'Overview', - }); - }); - test('uses built-in translations for regional variants', () => { - const t = useTranslations('pt-br'); + const t = useTranslations('pt-BR'); expect(t('page.nextLink')).toBe(translations.pt?.['page.nextLink']); expect(t('page.nextLink')).not.toBe(translations.en?.['page.nextLink']); }); }); + +describe('t.dir()', () => { + test('returns text directions', () => { + expect(useTranslations(undefined).dir()).toBe('ltr'); + expect(useTranslations('fr').dir()).toBe('ltr'); + expect(useTranslations('ar').dir()).toBe('rtl'); + }); +}); diff --git a/packages/starlight/__tests__/middleware/middleware.test.ts b/packages/starlight/__tests__/middleware/middleware.test.ts new file mode 100644 index 00000000000..94d55c3bc2b --- /dev/null +++ b/packages/starlight/__tests__/middleware/middleware.test.ts @@ -0,0 +1,33 @@ +import type { APIContext } from 'astro'; +import { expect, test } from 'vitest'; +import { onRequest } from '../../locals'; +import type { StarlightRouteData } from '../../route-data'; + +test('starlightRoute throws when accessed outside of a Starlight page', async () => { + const context = { locals: {}, currentLocale: 'en' } as APIContext; + await onRequest(context, () => Promise.resolve(new Response())); + expect(() => { + // We are testing that accessing `starlightRoute` outside of a Starlight page throws. + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + context.locals.starlightRoute; + }).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + \`locals.starlightRoute\` is not defined + Hint: + This usually means a component that accesses \`locals.starlightRoute\` is being rendered outside of a Starlight page, which is not supported. + + If this is a component you authored, you can do one of the following: + + 1. Avoid using this component in non-Starlight pages. + 2. Wrap the code that reads \`locals.starlightRoute\` in a \`try/catch\` block and handle the cases where \`starlightRoute\` is not available. + + If this is a Starlight built-in or third-party component, you may need to report a bug or avoid this use of the component." + `); +}); + +test('starlightRoute returns as expected if it has been set', async () => { + const context = { locals: {}, currentLocale: 'en' } as APIContext; + await onRequest(context, () => Promise.resolve(new Response())); + context.locals.starlightRoute = { siteTitle: 'Test title' } as StarlightRouteData; + expect(context.locals.starlightRoute.siteTitle).toBe('Test title'); +}); diff --git a/packages/starlight/__tests__/middleware/vitest.config.ts b/packages/starlight/__tests__/middleware/vitest.config.ts new file mode 100644 index 00000000000..9050e41dc22 --- /dev/null +++ b/packages/starlight/__tests__/middleware/vitest.config.ts @@ -0,0 +1,3 @@ +import { defineVitestConfig } from '../test-config'; + +export default defineVitestConfig({ title: 'Middleware' }); diff --git a/packages/starlight/__tests__/plugins/config.test.ts b/packages/starlight/__tests__/plugins/config.test.ts new file mode 100644 index 00000000000..a206206f13d --- /dev/null +++ b/packages/starlight/__tests__/plugins/config.test.ts @@ -0,0 +1,211 @@ +import { describe, expect, test } from 'vitest'; +import config from 'virtual:starlight/user-config'; +import { getSidebar } from '../../utils/navigation'; +import { runPlugins } from '../../utils/plugins'; +import { createTestPluginContext } from '../test-plugin-utils'; +import pkg from '../../package.json'; + +test('reads and updates a configuration option', () => { + expect(config.title).toMatchObject({ en: 'Plugins - Custom' }); +}); + +test('overwrites a configuration option', () => { + expect(getSidebar('/', undefined)).toMatchObject([{ href: '/showcase', label: 'Showcase' }]); +}); + +test('runs plugins in the order that they are configured and always passes down the latest user config', () => { + expect(config.description).toBe('plugin 1 - plugin 2 - plugin 3'); +}); + +test('receives the user provided configuration without any Zod `transform`s applied', () => { + /** + * If the `transform` associated to the favicon schema was applied, the favicon `href` would be + * `invalid.svg`. + * @see {@link file://./vitest.config.ts} for more details in the `test-plugin-1` plugin. + */ + expect(config.favicon.href).toBe('valid.svg'); +}); + +test('receives the user provided configuration including the plugins list', async () => { + expect.assertions(1); + + await runPlugins( + { title: 'Test Docs' }, + [ + { name: 'test-plugin-1', hooks: { 'config:setup'() {} } }, + { name: 'test-plugin-2', hooks: { 'config:setup'() {} } }, + { + name: 'test-plugin-3', + hooks: { + 'config:setup'({ config }) { + expect(config.plugins?.map(({ name }) => name)).toMatchObject([ + 'test-plugin-1', + 'test-plugin-2', + 'test-plugin-3', + ]); + }, + }, + }, + ], + createTestPluginContext() + ); +}); + +describe('validation', () => { + test('validates starlight configuration before running plugins', async () => { + await expect( + async () => + await runPlugins( + // @ts-expect-error - invalid sidebar config. + { title: 'Test Docs', sidebar: true }, + [], + createTestPluginContext() + ) + ).rejects.toThrowError(/Invalid config passed to starlight integration/); + }); + + test('validates plugins configuration before running them', async () => { + await expect( + async () => + await runPlugins( + { title: 'Test Docs' }, + // @ts-expect-error - invalid plugin with no `hooks` defined. + [{ name: 'invalid-plugin' }], + createTestPluginContext() + ) + ).rejects.toThrowError(/Invalid plugins config passed to starlight integration/); + }); + + test('validates configuration updates from plugins do not update the `plugins` config key', async () => { + await expect( + async () => + await runPlugins( + { title: 'Test Docs' }, + [ + { + name: 'test-plugin', + hooks: { + setup: ({ updateConfig }) => { + // @ts-expect-error - plugins cannot update the `plugins` config key. + updateConfig({ plugins: [{ name: 'invalid-plugin' }] }); + }, + }, + }, + ], + createTestPluginContext() + ) + ).rejects.toThrowError( + /The `test-plugin` plugin tried to update the `plugins` config key which is not supported./ + ); + }); + + test('validates configuration updates from plugins do not update the `routeMiddleware` config key', async () => { + await expect( + async () => + await runPlugins( + { title: 'Test Docs' }, + [ + { + name: 'test-plugin', + hooks: { + setup: ({ updateConfig }) => { + // @ts-expect-error - plugins cannot update the `routeMiddleware` config key. + updateConfig({ routeMiddleware: './test-middleware.ts' }); + }, + }, + }, + ], + createTestPluginContext() + ) + ).rejects.toThrowError( + /The `test-plugin` plugin tried to update the `routeMiddleware` config key which is not supported./ + ); + }); + + test('validates configuration updates from plugins', async () => { + await expect( + async () => + await runPlugins( + { title: 'Test Docs' }, + [ + { + name: 'test-plugin', + hooks: { + setup: ({ updateConfig }) => { + // @ts-expect-error - invalid sidebar config update. + updateConfig({ description: true }); + }, + }, + }, + ], + createTestPluginContext() + ) + ).rejects.toThrowError(/Invalid config update provided by the 'test-plugin' plugin/); + }); +}); + +describe('deprecated `setup` hook', () => { + test('supports the legacy `setup` hook in pre v1 versions', async () => { + const isPreV1 = pkg.version[0] === '0'; + + const pluginResult = runPlugins( + { title: 'Test Docs' }, + [ + { + name: 'valid-plugin', + hooks: { setup() {} }, + }, + ], + createTestPluginContext() + ); + + if (isPreV1) { + await expect(pluginResult).resolves.not.toThrow(); + } else { + await expect(pluginResult).rejects.toThrow(); + } + }); + + test('validates plugins have at least a `config:setup` or the deprecated `setup` hook', async () => { + await expect( + runPlugins( + { title: 'Test Docs' }, + [{ name: 'invalid-plugin', hooks: {} }], + createTestPluginContext() + ) + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Invalid plugins config passed to starlight integration + Hint: + A plugin must define at least a \`config:setup\` hook." + `); + }); + + test('validates plugins does not have both a `config:setup` or the deprecated `setup` hook', async () => { + await expect( + runPlugins( + { title: 'Test Docs' }, + [ + { + name: 'invalid-plugin', + hooks: { + 'config:setup'() {}, + setup() {}, + }, + }, + ], + createTestPluginContext() + ) + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + Invalid plugins config passed to starlight integration + Hint: + A plugin cannot define both a \`config:setup\` and \`setup\` hook. As \`setup\` is deprecated and will be removed in a future version, consider using \`config:setup\` instead." + `); + }); +}); + +test('does not expose plugins to the config virtual module', () => { + // @ts-expect-error - plugins are not serializable and thus not in the config virtual module. + expect(config.plugins).not.toBeDefined(); +}); diff --git a/packages/starlight/__tests__/plugins/integration.test.ts b/packages/starlight/__tests__/plugins/integration.test.ts new file mode 100644 index 00000000000..8b3005a7c77 --- /dev/null +++ b/packages/starlight/__tests__/plugins/integration.test.ts @@ -0,0 +1,77 @@ +import type { AstroIntegration } from 'astro'; +import { expect, test } from 'vitest'; +import { runPlugins } from '../../utils/plugins'; +import { createTestPluginContext } from '../test-plugin-utils'; + +test('returns all integrations added by plugins without deduping them', async () => { + const integration1: AstroIntegration = { + name: 'test-integration-1', + hooks: {}, + }; + + const integration2: AstroIntegration = { + name: 'test-integration-2', + hooks: {}, + }; + + const { integrations } = await runPlugins( + { title: 'Test Docs' }, + [ + { + name: 'test-plugin-1', + hooks: { + 'config:setup'({ addIntegration, updateConfig }) { + updateConfig({ description: 'test' }); + addIntegration(integration1); + }, + }, + }, + { + name: 'test-plugin-2', + hooks: { + 'config:setup'({ addIntegration }) { + addIntegration(integration1); + addIntegration(integration2); + }, + }, + }, + ], + createTestPluginContext() + ); + + expect(integrations).toMatchObject([ + { name: 'test-integration-1' }, + { name: 'test-integration-1' }, + { name: 'test-integration-2' }, + ]); +}); + +test('receives the Astro config with a list of integrations including the ones added by previous plugins', async () => { + expect.assertions(1); + + await runPlugins( + { title: 'Test Docs' }, + [ + { + name: 'test-plugin-1', + hooks: { + 'config:setup'({ addIntegration }) { + addIntegration({ + name: 'test-integration', + hooks: {}, + }); + }, + }, + }, + { + name: 'test-plugin-2', + hooks: { + 'config:setup'({ astroConfig }) { + expect(astroConfig.integrations).toMatchObject([{ name: 'test-integration' }]); + }, + }, + }, + ], + createTestPluginContext() + ); +}); diff --git a/packages/starlight/__tests__/plugins/route-middleware.test.ts b/packages/starlight/__tests__/plugins/route-middleware.test.ts new file mode 100644 index 00000000000..2eb08fe1656 --- /dev/null +++ b/packages/starlight/__tests__/plugins/route-middleware.test.ts @@ -0,0 +1,46 @@ +import { expect, test } from 'vitest'; +import { runPlugins } from '../../utils/plugins'; +import { createTestPluginContext } from '../test-plugin-utils'; + +test('adds route middleware entrypoints added by plugins respecting order', async () => { + const { starlightConfig } = await runPlugins( + { title: 'Test Docs', routeMiddleware: 'user' }, + [ + { + name: 'test-plugin-1', + hooks: { + setup({ addRouteMiddleware }) { + addRouteMiddleware({ entrypoint: 'one' }); + }, + }, + }, + { + name: 'test-plugin-2', + hooks: { + setup({ addRouteMiddleware }) { + addRouteMiddleware({ entrypoint: 'two', order: 'pre' }); + }, + }, + }, + { + name: 'test-plugin-3', + hooks: { + setup({ addRouteMiddleware }) { + addRouteMiddleware({ entrypoint: 'three', order: 'post' }); + }, + }, + }, + { + name: 'test-plugin-4', + hooks: { + setup({ addRouteMiddleware }) { + addRouteMiddleware({ entrypoint: 'four' }); + }, + }, + }, + ], + createTestPluginContext() + ); + + expect(starlightConfig.routeMiddleware).toMatchObject(['two', 'user', 'one', 'four', 'three']); +}); diff --git a/packages/starlight/__tests__/plugins/translations.test.ts b/packages/starlight/__tests__/plugins/translations.test.ts new file mode 100644 index 00000000000..2b2e7ae83c2 --- /dev/null +++ b/packages/starlight/__tests__/plugins/translations.test.ts @@ -0,0 +1,73 @@ +import { describe, expect, test, vi } from 'vitest'; +import config from 'virtual:starlight/user-config'; +import { useTranslations } from '../../utils/translations'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + // We do not strip unknown translations in this test so that user-defined translations can + // override plugin translations like it would in a real- world scenario were the plugin would + // have provided a custom schema to extend the translations. + i18n: [['ar', { 'testPlugin3.doThing': 'افعل الشيء' }]], + }) +); + +describe('can access UI string in an Astro context', () => { + test('includes UI strings injected by plugins for the default locale', () => { + const t = useTranslations(undefined); + expect(t).toBeTypeOf('function'); + // Include the default locale strings. + expect(t('skipLink.label')).toBe('Skip to content'); + // Include a built-in translation overridden by a plugin. + expect(t('search.label')).toBe('Search the thing'); + // Include a translation injected by a plugin. + // @ts-expect-error - translation key injected by a test plugin. + expect(t('testPlugin3.doThing')).toBe('Do the Plugin 3 thing'); + }); + + test('includes UI strings injected by plugins', () => { + const t = useTranslations('fr'); + // Include the default locale strings. + expect(t('skipLink.label')).toBe('Aller au contenu'); + // Include a built-in translation overridden by a plugin. + expect(t('search.label')).toBe('Rechercher le truc'); + // Include a translation injected by a plugin. + // @ts-expect-error - translation key injected by a test plugin. + expect(t('testPlugin3.doThing')).toBe('Faire la chose du plugin 3'); + }); + + test('uses user-defined translations for untranslated strings injected by plugins', () => { + const t = useTranslations('pt-BR'); + // @ts-expect-error - translation key injected by a test plugin. + expect(t('testPlugin3.doThing')).toBe('Do the Plugin 3 thing'); + }); + + test('prefers user-defined translations over plugin translations', () => { + const t = useTranslations('ar'); + // @ts-expect-error - translation key injected by a test plugin. + expect(t('testPlugin3.doThing')).toBe('افعل الشيء'); + }); +}); + +test('can access UI strings in the plugin context using useTranslations()', () => { + const { uiStrings } = JSON.parse(config.titleDelimiter) as { uiStrings: string[] }; + + // A built-in UI string. + expect(uiStrings[0]).toBe('Skip to content'); + // A built-in UI string overridden by a plugin. + expect(uiStrings[1]).toBe('Rechercher le truc'); + // A UI string injected by a plugin. + expect(uiStrings[2]).toBe('Do the Plugin 3 thing'); +}); + +test('can infer langs from an absolute path in the plugin context using absolutePathToLang()', () => { + const { langs } = JSON.parse(config.titleDelimiter) as { langs: string[] }; + + // The default language. + expect(langs[0]).toBe('en'); + // A language with a regional subtag. + expect(langs[1]).toBe('pt-BR'); + // A page not matching any language defaults to the default language. + expect(langs[2]).toBe('en'); + // A known language and an absolute path containing spaces. + expect(langs[3]).toBe('ar'); +}); diff --git a/packages/starlight/__tests__/plugins/vitest.config.ts b/packages/starlight/__tests__/plugins/vitest.config.ts new file mode 100644 index 00000000000..d5aef6f9984 --- /dev/null +++ b/packages/starlight/__tests__/plugins/vitest.config.ts @@ -0,0 +1,98 @@ +import { fileURLToPath } from 'node:url'; +import { defineVitestConfig } from '../test-config'; + +export default defineVitestConfig({ + title: 'Plugins', + sidebar: [{ label: 'Getting Started', link: 'getting-started' }], + defaultLocale: 'en', + locales: { + en: { label: 'English', lang: 'en' }, + fr: { label: 'French' }, + ar: { label: 'Arabic', dir: 'rtl' }, + 'pt-br': { label: 'Brazilian Portuguese', lang: 'pt-BR' }, + }, + plugins: [ + { + name: 'test-plugin-1', + hooks: { + 'config:setup'({ config, updateConfig }) { + updateConfig({ + title: `${typeof config.title === 'string' ? config.title : ''} - Custom`, + description: 'plugin 1', + /** + * The configuration received by a plugin should be the user provided configuration as-is + * before any Zod `transform`s are applied. + * To test this, we use this plugin to update the `favicon` value to a specific value if + * the `favicon` config value is an object, which would mean that the associated Zod + * `transform` was applied. + */ + favicon: typeof config.favicon === 'object' ? 'invalid.svg' : 'valid.svg', + }); + }, + }, + }, + { + name: 'test-plugin-2', + hooks: { + 'config:setup'({ config, updateConfig }) { + updateConfig({ + description: `${config.description} - plugin 2`, + sidebar: [{ label: 'Showcase', link: 'showcase' }], + }); + }, + }, + }, + { + name: 'test-plugin-3', + hooks: { + 'i18n:setup'({ injectTranslations }) { + injectTranslations({ + en: { + 'search.label': 'Search the thing', + 'testPlugin3.doThing': 'Do the Plugin 3 thing', + }, + fr: { + 'search.label': 'Rechercher le truc', + 'testPlugin3.doThing': 'Faire la chose du plugin 3', + }, + ar: { + 'testPlugin3.doThing': 'قم بعمل المكون الإضافي 3', + }, + }); + }, + async 'config:setup'({ config, updateConfig, useTranslations, absolutePathToLang }) { + // Fake an async operation to ensure that the plugin system can handle async hooks. + await Promise.resolve(); + + const docsUrl = new URL('../src/content/docs/', import.meta.url); + + // To test that a plugin can access UI strings in the plugin context using the + // `useTranslations()` helper and also use the `absolutePathToLang()` helper, we generate + // a bunch of expected values that are JSON stringified, passed to the config through the + // `titleDelimiter` option, and later parsed and verified in a test. + const result = { + uiStrings: [ + useTranslations('en')('skipLink.label'), + useTranslations('fr')('search.label'), + // @ts-expect-error - `testPlugin3.doThing` is a translation key injected by a test plugin + useTranslations('en')('testPlugin3.doThing'), + ], + langs: [ + // We convert URLs to file paths to avoid potential issues with URL encoded paths, + // e.g. running tests with a path that contains spaces and would be `%20` encoded. + absolutePathToLang(fileURLToPath(new URL('./en/index.md', docsUrl))), + absolutePathToLang(fileURLToPath(new URL('./pt-br/index.md', docsUrl))), + absolutePathToLang(fileURLToPath(new URL('./index.md', docsUrl))), + absolutePathToLang(fileURLToPath(new URL('./ar/path with spaces/index.md', docsUrl))), + ], + }; + + updateConfig({ + description: `${config.description} - plugin 3`, + titleDelimiter: JSON.stringify(result), + }); + }, + }, + }, + ], +}); diff --git a/packages/starlight/__tests__/remark-rehype/anchor-links.test.ts b/packages/starlight/__tests__/remark-rehype/anchor-links.test.ts new file mode 100644 index 00000000000..40f21c970a0 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/anchor-links.test.ts @@ -0,0 +1,68 @@ +import { createMarkdownProcessor, type MarkdownProcessor } from '@astrojs/markdown-remark'; +import { expect, test } from 'vitest'; +import type { StarlightUserConfig } from '../../utils/user-config'; +import { starlightRehypePlugins } from '../../integrations/remark-rehype'; +import { createRemarkRehypePluginTestOptions } from './utils'; + +const starlightConfig = { + title: 'Anchor Links Tests', + locales: { en: { label: 'English' }, fr: { label: 'French' } }, + defaultLocale: 'en', +} satisfies StarlightUserConfig; + +const processor = await createMarkdownProcessor({ + rehypePlugins: [ + ...starlightRehypePlugins(await createRemarkRehypePluginTestOptions(starlightConfig)), + ], +}); + +function renderMarkdown( + content: string, + options: { fileURL?: URL; processor?: MarkdownProcessor } = {} +) { + return (options.processor ?? processor).render( + content, + // @ts-expect-error fileURL is part of MarkdownProcessor's options + { fileURL: options.fileURL ?? new URL(`./_src/content/docs/index.md`, import.meta.url) } + ); +} + +test('generates anchor link markup', async () => { + const res = await renderMarkdown(` +## Some text +`); + await expect(res.code).toMatchFileSnapshot('./snapshots/generates-anchor-link-markup.html'); +}); + +test('generates an accessible link label', async () => { + const res = await renderMarkdown(` +## Some text +`); + expect(res.code).includes( + '<span class="sr-only" data-pagefind-ignore="">Section titled “Some text”</span>' + ); +}); + +test('strips HTML markup in accessible link label', async () => { + const res = await renderMarkdown(` +## Some _important nested \`HTML\`_ +`); + // Heading renders HTML + expect(res.code).includes('Some <em>important nested <code dir="auto">HTML</code></em>'); + // Visually hidden label renders plain text + expect(res.code).includes( + '<span class="sr-only" data-pagefind-ignore="">Section titled “Some important nested HTML”</span>' + ); +}); + +test('localizes accessible label for the current language', async () => { + const res = await renderMarkdown( + ` +## Some text +`, + { fileURL: new URL('./_src/content/docs/fr/index.md', import.meta.url) } + ); + expect(res.code).includes( + '<span class="sr-only" data-pagefind-ignore="">Section intitulée « Some text »</span>' + ); +}); diff --git a/packages/starlight/__tests__/remark-rehype/asides.test.ts b/packages/starlight/__tests__/remark-rehype/asides.test.ts new file mode 100644 index 00000000000..6f1ae767931 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/asides.test.ts @@ -0,0 +1,373 @@ +import { createMarkdownProcessor, type MarkdownProcessor } from '@astrojs/markdown-remark'; +import type { Root } from 'mdast'; +import { visit } from 'unist-util-visit'; +import { describe, expect, test, vi } from 'vitest'; +import { remarkDirectivesRestoration } from '../../integrations/asides'; +import { starlightRemarkPlugins } from '../../integrations/remark-rehype'; +import type { StarlightUserConfig } from '../../utils/user-config'; +import { BuiltInDefaultLocale } from '../../utils/i18n'; +import { createRemarkRehypePluginTestOptions } from './utils'; + +const starlightConfig = { + title: 'Asides Tests', + locales: { en: { label: 'English' }, fr: { label: 'French' } }, + defaultLocale: 'en', +} satisfies StarlightUserConfig; + +const processor = await createMarkdownProcessor({ + remarkPlugins: [ + ...starlightRemarkPlugins(await createRemarkRehypePluginTestOptions(starlightConfig)), + // The restoration plugin is run after the asides and any other plugin that may have been + // injected by Starlight plugins. + remarkDirectivesRestoration, + ], +}); + +function renderMarkdown( + content: string, + options: { fileURL?: URL; processor?: MarkdownProcessor } = {} +) { + return (options.processor ?? processor).render( + content, + // @ts-expect-error fileURL is part of MarkdownProcessor's options + { fileURL: options.fileURL ?? new URL(`./_src/content/docs/index.md`, import.meta.url) } + ); +} + +test('generates aside', async () => { + const res = await renderMarkdown(` +:::note +Some text +::: +`); + await expect(res.code).toMatchFileSnapshot('./snapshots/generates-aside.html'); +}); + +describe('default labels', () => { + test.each([ + ['note', 'Note'], + ['tip', 'Tip'], + ['caution', 'Caution'], + ['danger', 'Danger'], + ])('%s has label %s', async (type, label) => { + const res = await renderMarkdown(` +:::${type} +Some text +::: +`); + expect(res.code).includes(`aria-label="${label}"`); + expect(res.code).includes(`</svg>${label}</p>`); + }); +}); + +describe('custom labels', () => { + test.each(['note', 'tip', 'caution', 'danger'])('%s with custom label', async (type) => { + const label = 'Custom Label'; + const res = await renderMarkdown(` +:::${type}[${label}] +Some text +::: + `); + expect(res.code).includes(`aria-label="${label}"`); + expect(res.code).includes(`</svg>${label}</p>`); + }); +}); + +describe('custom labels with nested markdown', () => { + test.each(['note', 'tip', 'caution', 'danger'])('%s with custom code label', async (type) => { + const label = 'Custom `code` Label'; + const labelWithoutMarkdown = 'Custom code Label'; + const labelHtml = 'Custom <code>code</code> Label'; + const res = await renderMarkdown(` +:::${type}[${label}] +Some text +::: + `); + expect(res.code).includes(`aria-label="${labelWithoutMarkdown}"`); + expect(res.code).includes(`</svg>${labelHtml}</p>`); + }); +}); + +describe('custom labels with doubly-nested markdown', () => { + test.each(['note', 'tip', 'caution', 'danger'])( + '%s with custom doubly-nested label', + async (type) => { + const label = 'Custom **strong with _emphasis_** Label'; + const labelWithoutMarkdown = 'Custom strong with emphasis Label'; + const labelHtml = 'Custom <strong>strong with <em>emphasis</em></strong> Label'; + const res = await renderMarkdown(` +:::${type}[${label}] +Some text +::: + `); + expect(res.code).includes(`aria-label="${labelWithoutMarkdown}"`); + expect(res.code).includes(`</svg>${labelHtml}</p>`); + } + ); +}); + +describe('custom icons', () => { + test.each(['note', 'tip', 'caution', 'danger'])('%s with custom icon', async (type) => { + const res = await renderMarkdown(` +:::${type}{icon="heart"} +Some text +::: + `); + await expect(res.code).toMatchFileSnapshot( + `./snapshots/generates-aside-${type}-custom-icon.html` + ); + }); + + test.each(['note', 'tip', 'caution', 'danger'])('%s with invalid custom icon', async (type) => { + // Temporarily mock console.error to avoid cluttering test output when the Astro Markdown + // processor logs an error before rethrowing it. + // https://github.com/withastro/astro/blob/98853ce7e31a8002fd7be83d7932a53cfec84d27/packages/markdown/remark/src/index.ts#L161 + const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {}); + + await expect(async () => + renderMarkdown( + ` +:::${type}{icon="invalid-icon-name"} +Some text +::: + ` + ) + ).rejects.toThrowError( + // We are not relying on `toThrowErrorMatchingInlineSnapshot()` and our custom snapshot + // serializer in this specific test as error thrown in a remark plugin includes a dynamic file + // path. + // `expect.objectContaining` returns `any`. + /* eslint-disable @typescript-eslint/no-unsafe-argument */ + expect.objectContaining({ + type: 'AstroUserError', + // `expect.stringMatching` returns `any`. + /* eslint-disable @typescript-eslint/no-unsafe-assignment */ + hint: expect.stringMatching( + /An aside custom icon must be set to the name of one of Starlight’s built-in icons, but received `invalid-icon-name`/ + ), + }) + ); + + // Restore the original console.error implementation. + consoleError.mockRestore(); + }); + + test('test custom icon with multiple paths inside the svg', async () => { + const res = await renderMarkdown(` +:::note{icon="external"} +Some text +::: + `); + await expect(res.code).toMatchFileSnapshot( + `./snapshots/generates-aside-note-multiple-path-custom-icon.html` + ); + const pathCount = (res.code.match(/path/g) || []).length; + // If we have two pairs of opening and closing tags of path, + // we will have 4 occurrences of that word. + expect(pathCount).eq(4); + }); +}); + +describe('custom labels with custom icons', () => { + test.each(['note', 'tip', 'caution', 'danger'])('%s with custom label', async (type) => { + const label = 'Custom Label'; + const res = await renderMarkdown(` +:::${type}[${label}]{icon="heart"} +Some text +::: + `); + expect(res.code).includes(`aria-label="${label}"`); + expect(res.code).includes(`</svg>${label}</p>`); + await expect(res.code).toMatchFileSnapshot( + `./snapshots/generates-aside-${type}-custom-label-and-icon.html` + ); + }); +}); + +test('ignores unknown directive variants', async () => { + const res = await renderMarkdown(` +:::unknown +Some text +::: +`); + expect(res.code).toMatchInlineSnapshot('"<div><p>Some text</p></div>"'); +}); + +test('handles complex children', async () => { + const res = await renderMarkdown(` +:::note +Paragraph [link](/href/). + +![alt](/img.jpg) + +<details> +<summary>See more</summary> + +More. + +</details> +::: +`); + await expect(res.code).toMatchFileSnapshot('./snapshots/handles-complex-children.html'); +}); + +test('nested asides', async () => { + const res = await renderMarkdown(` +::::note +Note contents. + +:::tip +Nested tip. +::: + +:::: +`); + await expect(res.code).toMatchFileSnapshot('./snapshots/nested-asides.html'); +}); + +test('nested asides with custom titles', async () => { + const res = await renderMarkdown(` +:::::caution[Caution with a custom title] +Nested caution. + +::::note +Nested note. + +:::tip[Tip with a custom title] +Nested tip. +::: + +:::: + +::::: +`); + const labels = [...res.code.matchAll(/aria-label="(?<label>[^"]+)"/g)].map( + (match) => match.groups?.label + ); + expect(labels).toMatchInlineSnapshot(` + [ + "Caution with a custom title", + "Note", + "Tip with a custom title", + ] + `); + await expect(res.code).toMatchFileSnapshot('./snapshots/nested-asides-custom-titles.html'); +}); + +describe('translated labels in French', () => { + test.each([ + ['note', 'Note'], + ['tip', 'Astuce'], + ['caution', 'Attention'], + ['danger', 'Danger'], + ])('%s has label %s', async (type, label) => { + const res = await renderMarkdown( + ` +:::${type} +Some text +::: +`, + { fileURL: new URL('./_src/content/docs/fr/index.md', import.meta.url) } + ); + expect(res.code).includes(`aria-label="${label}"`); + expect(res.code).includes(`</svg>${label}</p>`); + }); +}); + +test('runs without locales config', async () => { + const processor = await createMarkdownProcessor({ + remarkPlugins: [ + ...starlightRemarkPlugins( + await createRemarkRehypePluginTestOptions({ + ...starlightConfig, + // With no locales config, the default built-in locale is used. + defaultLocale: BuiltInDefaultLocale.lang, + locales: undefined, + }) + ), + remarkDirectivesRestoration, + ], + }); + const res = await renderMarkdown(':::note\nTest\n::', { processor }); + expect(res.code.includes('aria-label=Note"')); +}); + +test('transforms back unhandled text directives', async () => { + const res = await renderMarkdown( + `This is a:test of a sentence with a text:name[content]{key=val} directive.` + ); + expect(res.code).toMatchInlineSnapshot(` + "<p>This is a:test of a sentence with a text:name[content]{key="val"} directive.</p>" + `); +}); + +test('transforms back unhandled leaf directives', async () => { + const res = await renderMarkdown(`::video[Title]{v=xxxxxxxxxxx}`); + expect(res.code).toMatchInlineSnapshot(` + "<p>::video[Title]{v="xxxxxxxxxxx"}</p>" + `); +}); + +test('does not add any whitespace character after any unhandled directive', async () => { + const res = await renderMarkdown(`## Environment variables (astro:env)`); + expect(res.code).toMatchInlineSnapshot( + `"<h2 id="environment-variables-astroenv">Environment variables (astro:env)</h2>"` + ); + expect(res.code).not.toMatch(/\n/); +}); + +test('lets remark plugin injected by Starlight plugins handle text and leaf directives', async () => { + const processor = await createMarkdownProcessor({ + remarkPlugins: [ + ...starlightRemarkPlugins(await createRemarkRehypePluginTestOptions(starlightConfig)), + // A custom remark plugin injected by a Starlight plugin through an Astro integration would + // run before the restoration plugin. + function customRemarkPlugin() { + return function transformer(tree: Root) { + visit(tree, (node, index, parent) => { + if (node.type !== 'textDirective' || typeof index !== 'number' || !parent) return; + if (node.name === 'abbr') { + parent.children.splice(index, 1, { type: 'text', value: 'TEXT FROM REMARK PLUGIN' }); + } + }); + }; + }, + remarkDirectivesRestoration, + ], + }); + + const res = await renderMarkdown( + `This is a:test of a sentence with a :abbr[SL]{name="Starlight"} directive handled by another remark plugin and some other text:name[content]{key=val} directives not handled by any plugin.`, + { processor } + ); + expect(res.code).toMatchInlineSnapshot(` + "<p>This is a:test of a sentence with a TEXT FROM REMARK PLUGIN directive handled by another remark plugin and some other text:name[content]{key="val"} directives not handled by any plugin.</p>" + `); +}); + +test('does not transform back directive nodes with data', async () => { + const processor = await createMarkdownProcessor({ + remarkPlugins: [ + ...starlightRemarkPlugins(await createRemarkRehypePluginTestOptions(starlightConfig)), + // A custom remark plugin updating the node with data that should be consumed by rehype. + function customRemarkPlugin() { + return function transformer(tree: Root) { + visit(tree, (node) => { + if (node.type !== 'textDirective') return; + node.data ??= {}; + node.data.hName = 'span'; + node.data.hProperties = { class: `api` }; + }); + }; + }, + remarkDirectivesRestoration, + ], + }); + + const res = await renderMarkdown(`This method is available in the :api[thing] API.`, { + processor, + }); + expect(res.code).toMatchInlineSnapshot( + `"<p>This method is available in the <span class="api">thing</span> API.</p>"` + ); +}); diff --git a/packages/starlight/__tests__/remark-rehype/code-rtl-support.test.ts b/packages/starlight/__tests__/remark-rehype/code-rtl-support.test.ts index 69aa85ad8e2..f917c81674e 100644 --- a/packages/starlight/__tests__/remark-rehype/code-rtl-support.test.ts +++ b/packages/starlight/__tests__/remark-rehype/code-rtl-support.test.ts @@ -1,25 +1,38 @@ import { rehype } from 'rehype'; +import { VFile } from 'vfile'; import { expect, test } from 'vitest'; -import { rehypeRtlCodeSupport } from '../../integrations/code-rtl-support'; +import { starlightRehypePlugins } from '../../integrations/remark-rehype'; +import { createRemarkRehypePluginTestOptions } from './utils'; -const processor = rehype().data('settings', { fragment: true }).use(rehypeRtlCodeSupport()); +const processor = rehype() + .data('settings', { fragment: true }) + .use(starlightRehypePlugins(await createRemarkRehypePluginTestOptions())); + +function renderMarkdown(content: string, options: { fileURL?: URL } = {}) { + return processor.process( + new VFile({ + path: options.fileURL ?? new URL(`./_src/content/docs/index.md`, import.meta.url), + value: content, + }) + ); +} test('applies `dir="auto"` to inline code', async () => { const input = `<p>Some text with <code>inline code</code>.</p>`; - const output = String(await processor.process(input)); + const output = String(await renderMarkdown(input)); expect(output).not.toEqual(input); expect(output).includes('dir="auto"'); expect(output).toMatchInlineSnapshot( - '"<p>Some text with <code dir=\\"auto\\">inline code</code>.</p>"' + `"<p>Some text with <code dir="auto">inline code</code>.</p>"` ); }); test('applies `dir="ltr"` to code blocks', async () => { const input = `<p>Some text in a paragraph:</p><pre><code>console.log('test')</code></pre>`; - const output = String(await processor.process(input)); + const output = String(await renderMarkdown(input)); expect(output).not.toEqual(input); expect(output).includes('dir="ltr"'); expect(output).toMatchInlineSnapshot( - '"<p>Some text in a paragraph:</p><pre dir=\\"ltr\\"><code>console.log(\'test\')</code></pre>"' + `"<p>Some text in a paragraph:</p><pre dir="ltr"><code>console.log('test')</code></pre>"` ); }); diff --git a/packages/starlight/__tests__/remark-rehype/rehype-file-tree.test.ts b/packages/starlight/__tests__/remark-rehype/rehype-file-tree.test.ts new file mode 100644 index 00000000000..5c94c7e5c82 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/rehype-file-tree.test.ts @@ -0,0 +1,181 @@ +import { describe, expect, test } from 'vitest'; +import { processFileTree } from '../../user-components/rehype-file-tree'; +import { Icons, type StarlightIcon } from '../../components/Icons'; + +describe('validation', () => { + test('throws an error with no content', () => { + expect(() => processTestFileTree('')).toThrowErrorMatchingInlineSnapshot( + ` + "[AstroUserError]: + The \`<FileTree>\` component expects its content to be a single unordered list but found no child elements. + Hint: + To learn more about the \`<FileTree>\` component, see https://starlight.astro.build/components/file-tree/" + ` + ); + }); + + test('throws an error with multiple root elements', () => { + expect(() => + processTestFileTree('<p>test</p><ul><li>file</li></ul>') + ).toThrowErrorMatchingInlineSnapshot( + ` + "[AstroUserError]: + The \`<FileTree>\` component expects its content to be a single unordered list but found multiple child elements: \`<p>\` - \`<ul>\`. + Hint: + To learn more about the \`<FileTree>\` component, see https://starlight.astro.build/components/file-tree/" + ` + ); + }); + + test('throws an error with no root ordered list', () => { + expect(() => processTestFileTree('<ol><li>file</li></ol>')).toThrowErrorMatchingInlineSnapshot( + ` + "[AstroUserError]: + The \`<FileTree>\` component expects its content to be an unordered list but found the following element: \`<ol>\`. + Hint: + To learn more about the \`<FileTree>\` component, see https://starlight.astro.build/components/file-tree/" + ` + ); + }); + + test('throws an error with no list item', () => { + expect(() => processTestFileTree('<ul></ul>')).toThrowErrorMatchingInlineSnapshot( + ` + "[AstroUserError]: + The \`<FileTree>\` component expects its content to be an unordered list with at least one list item. + Hint: + To learn more about the \`<FileTree>\` component, see https://starlight.astro.build/components/file-tree/" + ` + ); + }); +}); + +describe('processor', () => { + test('processes a basic tree', async () => { + const html = processTestFileTree(`<ul> + <li>root_file</li> + <li>root_directory/ + <ul> + <li>nested_file</li> + </ul> + <li> +</ul>`); + + await expect(extractFileTree(html)).toMatchFileSnapshot('./snapshots/file-tree-basic.html'); + }); + + test('does not add a comment node with no comments', () => { + const html = processTestFileTree(`<ul><li>file</li></ul>`); + + expect(extractFileTree(html)).not.toContain('<span class="comment">'); + }); + + test('processes text comments following the file name', async () => { + const html = processTestFileTree(`<ul><li>file this is a comment</li></ul>`); + + await expect(extractFileTree(html)).toMatchFileSnapshot( + './snapshots/file-tree-comment-text.html' + ); + }); + + test('processes comment nodes', async () => { + const html = processTestFileTree( + `<ul><li>file this is an <strong>important</strong> comment</li></ul>` + ); + + await expect(extractFileTree(html)).toMatchFileSnapshot( + './snapshots/file-tree-comment-nodes.html' + ); + }); + + test('identifies directory with either a file name ending with a slash or a nested list', () => { + const html = processTestFileTree(`<ul> + <li>directory/</li> + <li>another_directory + <ul> + <li>file</li> + </ul> + </li> +</ul>`); + + expect(extractFileTree(html).match(/<li class="directory">/g)).toHaveLength(2); + }); + + test('identifies placeholder with either 3 dots or an ellipsis', () => { + const html = processTestFileTree(`<ul><li>...</li><li>…</li></ul>`); + + expect(extractFileTree(html).match(/<li class="[\w\s]*empty[\w\s]*">/g)).toHaveLength(2); + }); + + test('adds a placeholder to empty directories', () => { + const html = processTestFileTree(`<ul><li>directory/</li></ul>`); + + expect(extractFileTree(html)).toContain('<li class="file empty">'); + }); + + test('identifies highlighted with a strong tag', () => { + const html = processTestFileTree(`<ul><li><strong>file</strong></li></ul>`); + + expect(extractFileTree(html)).toContain('<span class="highlight">'); + }); +}); + +describe('icons', () => { + test('adds a folder icon to directories with a screen-reader only label', () => { + const html = processTestFileTree(`<ul><li>directory/</li></ul>`); + + expectHtmlToIncludeIcon(html, Icons['seti:folder']); + expect(extractFileTree(html)).toContain('<span class="sr-only">Directory</span>'); + }); + + test('adds a default file icon to unknown files', () => { + const html = processTestFileTree(`<ul><li>test_file</li></ul>`); + + expectHtmlToIncludeIcon(html, Icons['seti:default']); + }); + + test('adds an icon to known files', () => { + const html = processTestFileTree(`<ul><li>README.md</li></ul>`); + + expectHtmlToIncludeIcon(html, Icons['seti:info']); + }); + + test('adds an icon to known file extensions', () => { + const html = processTestFileTree(`<ul><li>test.astro</li></ul>`); + + expectHtmlToIncludeIcon(html, Icons.astro); + }); + + test('adds an icon to known file partials', () => { + const html = processTestFileTree(`<ul><li>TODO</li></ul>`); + + expectHtmlToIncludeIcon(html, Icons['seti:todo']); + }); + + test('does not add a special icon to file based on the last letter of the file name', () => { + // The last letter of the file name is "c" and should not be matched to the icon for C files. + const html = processTestFileTree(`<ul><li>testc</li></ul>`); + + expectHtmlToIncludeIcon(html, Icons['seti:default']); + }); +}); + +/** Calls the file tree processor with the given HTML and a default label. */ +function processTestFileTree(html: string) { + return processFileTree(html, 'Directory'); +} + +/** Extracts the file tree from the given HTML and optionally strips out the icon SVGs. */ +function extractFileTree(html: string, stripIcons = true) { + let tree = html.match(/<ul>.*<\/ul>/s)?.[0] ?? ''; + + if (stripIcons) { + tree = tree.replace(/<svg.*?<\/svg>/g, '<svg></svg>'); + } + + return tree; +} + +function expectHtmlToIncludeIcon(html: string, icon: (typeof Icons)[StarlightIcon]) { + return expect(extractFileTree(html, false)).toContain(icon.replace('/>', '>')); +} diff --git a/packages/starlight/__tests__/remark-rehype/rehype-steps.test.ts b/packages/starlight/__tests__/remark-rehype/rehype-steps.test.ts new file mode 100644 index 00000000000..262cdbff5ba --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/rehype-steps.test.ts @@ -0,0 +1,113 @@ +import { expect, test } from 'vitest'; +import { processSteps } from '../../user-components/rehype-steps'; + +test('empty component throws an error', () => { + expect(() => processSteps('')).toThrowErrorMatchingInlineSnapshot( + ` + "[AstroUserError]: + The \`<Steps>\` component expects its content to be a single ordered list (\`<ol>\`) but found no child elements. + Hint: + To learn more about the \`<Steps>\` component, see https://starlight.astro.build/components/steps/" + ` + ); +}); + +test('component with non-element content throws an error', () => { + expect(() => processSteps('<!-- comment -->Text node')).toThrowErrorMatchingInlineSnapshot( + ` + "[AstroUserError]: + The \`<Steps>\` component expects its content to be a single ordered list (\`<ol>\`) but found no child elements. + Hint: + To learn more about the \`<Steps>\` component, see https://starlight.astro.build/components/steps/" + ` + ); +}); + +test('component with non-`<ol>` content throws an error', () => { + expect(() => processSteps('<p>A paragraph is not an ordered list</p>')) + .toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + The \`<Steps>\` component expects its content to be a single ordered list (\`<ol>\`) but found the following element: \`<p>\`. + Hint: + To learn more about the \`<Steps>\` component, see https://starlight.astro.build/components/steps/ + + Full HTML passed to \`<Steps>\`: + + <p>A paragraph is not an ordered list</p> + " + `); +}); + +test('component with multiple children throws an error', () => { + expect(() => + processSteps( + '<ol><li>List item</li></ol><p>I intended this to be part of the same list item</p><ol><li>Other list item</li></ol>' + ) + ).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + The \`<Steps>\` component expects its content to be a single ordered list (\`<ol>\`) but found multiple child elements: \`<ol>\`, \`<p>\`, \`<ol>\`. + Hint: + To learn more about the \`<Steps>\` component, see https://starlight.astro.build/components/steps/ + + Full HTML passed to \`<Steps>\`: + + <ol> + <li>List item</li> + </ol> + <p>I intended this to be part of the same list item</p> + <ol> + <li>Other list item</li> + </ol> + " + `); +}); + +// This tests a workaround added for https://github.com/withastro/astro/issues/15627 +// See rehype-steps.ts for more details. +test('component with top-level script child is processed successfully', () => { + const { html } = processSteps( + '<script type="module" src="/test-script.js"></script><ol><li>List item</li></ol>' + ); + expect(html).toMatchInlineSnapshot( + `"<script type="module" src="/test-script.js"></script><ol role="list" class="sl-steps"><li>List item</li></ol>"` + ); +}); + +test('applies `role="list"` to child list', () => { + const { html } = processSteps('<ol><li>Step one</li></ol>'); + expect(html).toMatchInlineSnapshot(`"<ol role="list" class="sl-steps"><li>Step one</li></ol>"`); +}); + +test('does not interfere with other attributes on the child list', () => { + const { html } = processSteps('<ol start="5"><li>Step one</li></ol>'); + expect(html).toMatchInlineSnapshot( + `"<ol start="5" role="list" class="sl-steps" style="--sl-steps-start: 4"><li>Step one</li></ol>"` + ); +}); + +test('applies `class="sl-list"` to child list', () => { + const { html } = processSteps('<ol><li>Step one</li></ol>'); + expect(html).toContain('class="sl-steps"'); +}); + +test('applies class name and preserves existing classes on a child list', () => { + const testClass = 'test class-concat'; + const { html } = processSteps(`<ol class="${testClass}"><li>Step one</li></ol>`); + expect(html).toContain(`class="${testClass} sl-steps"`); + expect(html).toMatchInlineSnapshot( + `"<ol class="test class-concat sl-steps" role="list"><li>Step one</li></ol>"` + ); +}); + +test('applies custom property if start attribute is used', () => { + const start = 10; + const { html } = processSteps(`<ol start="${start}"><li>Step one</li></ol>`); + expect(html).toContain(`style="--sl-steps-start: ${start - 1}"`); +}); + +test('custom property for start count does not interfere with custom styles', () => { + const { html } = processSteps(`<ol start="20" style="color: red"><li>Step one</li></ol>`); + expect(html).toMatchInlineSnapshot( + `"<ol start="20" style="--sl-steps-start: 19;color: red" role="list" class="sl-steps"><li>Step one</li></ol>"` + ); +}); diff --git a/packages/starlight/__tests__/remark-rehype/rehype-tabs.test.ts b/packages/starlight/__tests__/remark-rehype/rehype-tabs.test.ts new file mode 100644 index 00000000000..5280febd311 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/rehype-tabs.test.ts @@ -0,0 +1,114 @@ +import { expect, test } from 'vitest'; +import { fromHtml } from 'hast-util-from-html'; +import { selectAll } from 'hast-util-select'; +import { rehype } from 'rehype'; +import { processPanels, TabItemTagname } from '../../user-components/rehype-tabs'; + +const processor = rehype().data('settings', { fragment: true }); + +const TabItem = ({ label, slot, icon }: { label: string; slot: string; icon?: string }) => { + const iconAttr = icon ? ` data-icon="${icon}"` : ''; + return `<${TabItemTagname} data-label="${label}"${iconAttr}>${slot}</${TabItemTagname}>`; +}; + +/** Get an array of HTML strings, one for each `<div role="tabpanel">` created by rehype-tabs for each tab item. */ +const extractTabPanels = (html: string) => { + const tree = fromHtml(html, { fragment: true }); + const tabPanels = selectAll('div[role="tabpanel"]', tree); + return tabPanels.map((tabPanel) => processor.stringify({ type: 'root', children: [tabPanel] })); +}; + +test('empty component returns no html or panels', () => { + const { panels, html } = processPanels(''); + expect(html).toEqual(''); + expect(panels).toEqual([]); +}); + +test('non-tab-item content is passed unchanged', () => { + const input = '<p>Random paragraph</p>'; + const { panels, html } = processPanels(input); + expect(html).toEqual(input); + expect(panels).toEqual([]); +}); + +test('tab items are processed', () => { + const label = 'Test'; + const slot = '<p>Random paragraph</p>'; + const input = TabItem({ label, slot }); + const { panels, html } = processPanels(input); + + expect(html).toMatchInlineSnapshot( + `"<div id="tab-panel-0" aria-labelledby="tab-0" role="tabpanel" tabindex="0"><p>Random paragraph</p></div>"` + ); + expect(panels).toHaveLength(1); + expect(panels?.[0]?.label).toBe(label); + expect(panels?.[0]?.panelId).toMatchInlineSnapshot('"tab-panel-0"'); + expect(panels?.[0]?.tabId).toMatchInlineSnapshot('"tab-0"'); + expect(panels?.[0]?.icon).not.toBeDefined(); +}); + +test('only first item is not hidden', () => { + const labels = ['One', 'Two', 'Three']; + const input = labels.map((label) => TabItem({ label, slot: `<div>${label}</div>` })).join(''); + const { panels, html } = processPanels(input); + + expect(panels).toHaveLength(3); + expect(html).toMatchInlineSnapshot( + `"<div id="tab-panel-1" aria-labelledby="tab-1" role="tabpanel" tabindex="0"><div>One</div></div><div id="tab-panel-2" aria-labelledby="tab-2" role="tabpanel" tabindex="0" hidden><div>Two</div></div><div id="tab-panel-3" aria-labelledby="tab-3" role="tabpanel" tabindex="0" hidden><div>Three</div></div>"` + ); + const tabPanels = extractTabPanels(html); + expect(tabPanels).toMatchInlineSnapshot(` + [ + "<div id="tab-panel-1" aria-labelledby="tab-1" role="tabpanel" tabindex="0"><div>One</div></div>", + "<div id="tab-panel-2" aria-labelledby="tab-2" role="tabpanel" tabindex="0" hidden><div>Two</div></div>", + "<div id="tab-panel-3" aria-labelledby="tab-3" role="tabpanel" tabindex="0" hidden><div>Three</div></div>", + ] + `); + expect(tabPanels.map((tabPanel) => tabPanel.includes('hidden'))).toEqual([false, true, true]); +}); + +test('applies incrementing ID and aria-labelledby to each tab item', () => { + const labels = ['One', 'Two', 'Three']; + const input = labels.map((label) => TabItem({ label, slot: `<div>${label}</div>` })).join(''); + const { panels, html } = processPanels(input); + + // IDs are incremented globally to ensure they are unique, so we need to extract from the panel data. + const firstTabIdMatches = panels?.[0]?.tabId.match(/^tab-(\d)+$/); + const firstTabId = parseInt(firstTabIdMatches![1]!, 10); + + extractTabPanels(html).forEach((tabPanel, index) => { + expect(tabPanel).includes(`id="tab-panel-${firstTabId + index}"`); + expect(tabPanel).includes(`aria-labelledby="tab-${firstTabId + index}"`); + }); +}); + +test('applies tabindex="0" to tab items without focusable content', () => { + const input = [ + TabItem({ label: 'Focusable', slot: `<div><a href="/home/">Home</a></div>` }), + TabItem({ label: 'Not Focusable', slot: `<div>Plain text</div>` }), + TabItem({ + label: 'Focusable Nested', + slot: `<div><p><span><input type="text"></span></p></div>`, + }), + ].join(''); + const { html } = processPanels(input); + expect(html).toMatchInlineSnapshot( + `"<div id="tab-panel-7" aria-labelledby="tab-7" role="tabpanel"><div><a href="/home/">Home</a></div></div><div id="tab-panel-8" aria-labelledby="tab-8" role="tabpanel" tabindex="0" hidden><div>Plain text</div></div><div id="tab-panel-9" aria-labelledby="tab-9" role="tabpanel" hidden><div><p><span><input type="text"></span></p></div></div>"` + ); + const tabPanels = extractTabPanels(html); + expect(tabPanels[0]).not.includes('tabindex="0"'); + expect(tabPanels[1]).includes('tabindex="0"'); + expect(tabPanels[2]).not.includes('tabindex="0"'); +}); + +test('processes a tab item icon', () => { + const icon = 'star'; + const input = TabItem({ label: 'Test', slot: '<p>Random paragraph</p>', icon }); + const { panels, html } = processPanels(input); + + expect(html).toMatchInlineSnapshot( + `"<div id="tab-panel-10" aria-labelledby="tab-10" role="tabpanel" tabindex="0"><p>Random paragraph</p></div>"` + ); + expect(panels).toHaveLength(1); + expect(panels?.[0]?.icon).toBe(icon); +}); diff --git a/packages/starlight/__tests__/remark-rehype/remark-rehype.test.ts b/packages/starlight/__tests__/remark-rehype/remark-rehype.test.ts new file mode 100644 index 00000000000..116138eae24 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/remark-rehype.test.ts @@ -0,0 +1,47 @@ +import { createMarkdownProcessor } from '@astrojs/markdown-remark'; +import { expect, test } from 'vitest'; +import { starlightRehypePlugins, starlightRemarkPlugins } from '../../integrations/remark-rehype'; +import { createRemarkRehypePluginTestOptions } from './utils'; + +test('does not run Starlight remark plugins on documents without a file path', async () => { + const processor = await createMarkdownProcessor({ + remarkPlugins: [...starlightRemarkPlugins(await createRemarkRehypePluginTestOptions())], + }); + + const res = await processor.render( + ` +:::note +Some text +::: +`, + // Rendering Markdown content using the content loader `renderMarkdown()` API does not provide + // a `fileURL` option. + {} + ); + + // Asides directives should not be processed. + expect(res.code).not.includes(`aside`); + expect(res.code).not.includes(`</svg>Note</p>`); +}); + +test('does not run Starlight rehype plugins on documents without a file path', async () => { + const processor = await createMarkdownProcessor({ + rehypePlugins: [...starlightRehypePlugins(await createRemarkRehypePluginTestOptions())], + }); + + const res = await processor.render( + ` +## Some heading + +And \`some\` inline code. +`, + // Rendering Markdown content using the content loader `renderMarkdown()` API does not provide + // a `fileURL` option. + {} + ); + + // Heading anchor links should not be added. + expect(res.code).not.includes('Section titled'); + // Code elements should not be processed for RTL support. + expect(res.code).not.includes('<code dir="auto">'); +}); diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/file-tree-basic.html b/packages/starlight/__tests__/remark-rehype/snapshots/file-tree-basic.html new file mode 100644 index 00000000000..a034dd3b847 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/file-tree-basic.html @@ -0,0 +1,7 @@ +<ul> + <li class="file"><span class="tree-entry"><span class=""><span><svg></svg></span>root_file</span></span></li> + <li class="directory"><details open><summary><span class="tree-entry"><span class=""><span><span class="sr-only">Directory</span><svg></svg></span>root_directory/ +</span></span></summary><ul> + <li class="file"><span class="tree-entry"><span class=""><span><svg></svg></span>nested_file</span></span></li> + </ul> + </details></li><li class="file"><span class="tree-entry"><span class=""><span><svg></svg></span></span></span></li></ul> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/file-tree-comment-nodes.html b/packages/starlight/__tests__/remark-rehype/snapshots/file-tree-comment-nodes.html new file mode 100644 index 00000000000..68b6db2ee4d --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/file-tree-comment-nodes.html @@ -0,0 +1 @@ +<ul><li class="file"><span class="tree-entry"><span class=""><span><svg></svg></span>file</span> <span class="comment">this is an <strong>important</strong> comment</span></span></li></ul> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/file-tree-comment-text.html b/packages/starlight/__tests__/remark-rehype/snapshots/file-tree-comment-text.html new file mode 100644 index 00000000000..cac6abac711 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/file-tree-comment-text.html @@ -0,0 +1 @@ +<ul><li class="file"><span class="tree-entry"><span class=""><span><svg></svg></span>file</span> <span class="comment">this is a comment</span></span></li></ul> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-anchor-link-markup.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-anchor-link-markup.html new file mode 100644 index 00000000000..81a205f73f4 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-anchor-link-markup.html @@ -0,0 +1 @@ +<div class="sl-heading-wrapper level-h2"><h2 id="some-text">Some text</h2><a class="sl-anchor-link" href="#some-text"><span aria-hidden="true" class="sl-anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentcolor" d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 0 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 1 0-1.42-1.42Zm8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 0 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 1 0 1.42 1.42l3.88-3.89a4.49 4.49 0 0 0 0-6.33ZM8.83 15.17a1 1 0 0 0 1.1.22 1 1 0 0 0 .32-.22l4.92-4.92a1 1 0 0 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42Z"></path></svg></span><span class="sr-only" data-pagefind-ignore="">Section titled “Some text”</span></a></div> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-caution-custom-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-caution-custom-icon.html new file mode 100644 index 00000000000..564ad6cd0b4 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-caution-custom-icon.html @@ -0,0 +1 @@ +<aside aria-label="Caution" class="starlight-aside starlight-aside--caution"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Caution</p><div class="starlight-aside__content"><p>Some text</p></div></aside> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-caution-custom-label-and-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-caution-custom-label-and-icon.html new file mode 100644 index 00000000000..c60755356c2 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-caution-custom-label-and-icon.html @@ -0,0 +1 @@ +<aside aria-label="Custom Label" class="starlight-aside starlight-aside--caution"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Custom Label</p><div class="starlight-aside__content"><p>Some text</p></div></aside> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-danger-custom-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-danger-custom-icon.html new file mode 100644 index 00000000000..c276e3797d8 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-danger-custom-icon.html @@ -0,0 +1 @@ +<aside aria-label="Danger" class="starlight-aside starlight-aside--danger"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Danger</p><div class="starlight-aside__content"><p>Some text</p></div></aside> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-danger-custom-label-and-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-danger-custom-label-and-icon.html new file mode 100644 index 00000000000..fc8c46aeacf --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-danger-custom-label-and-icon.html @@ -0,0 +1 @@ +<aside aria-label="Custom Label" class="starlight-aside starlight-aside--danger"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Custom Label</p><div class="starlight-aside__content"><p>Some text</p></div></aside> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-custom-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-custom-icon.html new file mode 100644 index 00000000000..5727e7be5d2 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-custom-icon.html @@ -0,0 +1 @@ +<aside aria-label="Note" class="starlight-aside starlight-aside--note"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Note</p><div class="starlight-aside__content"><p>Some text</p></div></aside> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-custom-label-and-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-custom-label-and-icon.html new file mode 100644 index 00000000000..506831fcdb6 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-custom-label-and-icon.html @@ -0,0 +1 @@ +<aside aria-label="Custom Label" class="starlight-aside starlight-aside--note"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Custom Label</p><div class="starlight-aside__content"><p>Some text</p></div></aside> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-multiple-path-custom-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-multiple-path-custom-icon.html new file mode 100644 index 00000000000..35cd1b778a1 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-multiple-path-custom-icon.html @@ -0,0 +1 @@ +<aside aria-label="Note" class="starlight-aside starlight-aside--note"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M19.33 10.18a1 1 0 0 1-.77 0 1 1 0 0 1-.62-.93l.01-1.83-8.2 8.2a1 1 0 0 1-1.41-1.42l8.2-8.2H14.7a1 1 0 0 1 0-2h4.25a1 1 0 0 1 1 1v4.25a1 1 0 0 1-.62.93Z"></path><path d="M11 4a1 1 0 1 1 0 2H7a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1v-4a1 1 0 1 1 2 0v4a3 3 0 0 1-3 3H7a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3h4Z"></path></svg>Note</p><div class="starlight-aside__content"><p>Some text</p></div></aside> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-tip-custom-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-tip-custom-icon.html new file mode 100644 index 00000000000..6f6e1eb9582 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-tip-custom-icon.html @@ -0,0 +1 @@ +<aside aria-label="Tip" class="starlight-aside starlight-aside--tip"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Tip</p><div class="starlight-aside__content"><p>Some text</p></div></aside> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-tip-custom-label-and-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-tip-custom-label-and-icon.html new file mode 100644 index 00000000000..b263140d96d --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-tip-custom-label-and-icon.html @@ -0,0 +1 @@ +<aside aria-label="Custom Label" class="starlight-aside starlight-aside--tip"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Custom Label</p><div class="starlight-aside__content"><p>Some text</p></div></aside> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside.html new file mode 100644 index 00000000000..8a5386481b3 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside.html @@ -0,0 +1 @@ +<aside aria-label="Note" class="starlight-aside starlight-aside--note"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M12 11C11.7348 11 11.4804 11.1054 11.2929 11.2929C11.1054 11.4804 11 11.7348 11 12V16C11 16.2652 11.1054 16.5196 11.2929 16.7071C11.4804 16.8946 11.7348 17 12 17C12.2652 17 12.5196 16.8946 12.7071 16.7071C12.8946 16.5196 13 16.2652 13 16V12C13 11.7348 12.8946 11.4804 12.7071 11.2929C12.5196 11.1054 12.2652 11 12 11ZM12.38 7.08C12.1365 6.97998 11.8635 6.97998 11.62 7.08C11.4973 7.12759 11.3851 7.19896 11.29 7.29C11.2017 7.3872 11.1306 7.49882 11.08 7.62C11.024 7.73868 10.9966 7.86882 11 8C10.9992 8.13161 11.0245 8.26207 11.0742 8.38391C11.124 8.50574 11.1973 8.61656 11.29 8.71C11.3872 8.79833 11.4988 8.86936 11.62 8.92C11.7715 8.98224 11.936 9.00632 12.099 8.99011C12.2619 8.97391 12.4184 8.91792 12.5547 8.82707C12.691 8.73622 12.8029 8.61328 12.8805 8.46907C12.9582 8.32486 12.9992 8.16378 13 8C12.9963 7.73523 12.8927 7.48163 12.71 7.29C12.6149 7.19896 12.5028 7.12759 12.38 7.08ZM12 2C10.0222 2 8.08879 2.58649 6.4443 3.6853C4.79981 4.78412 3.51809 6.3459 2.76121 8.17317C2.00433 10.0004 1.8063 12.0111 2.19215 13.9509C2.578 15.8907 3.53041 17.6725 4.92894 19.0711C6.32746 20.4696 8.10929 21.422 10.0491 21.8079C11.9889 22.1937 13.9996 21.9957 15.8268 21.2388C17.6541 20.4819 19.2159 19.2002 20.3147 17.5557C21.4135 15.9112 22 13.9778 22 12C22 10.6868 21.7413 9.38642 21.2388 8.17317C20.7363 6.95991 19.9997 5.85752 19.0711 4.92893C18.1425 4.00035 17.0401 3.26375 15.8268 2.7612C14.6136 2.25866 13.3132 2 12 2ZM12 20C10.4178 20 8.87104 19.5308 7.55544 18.6518C6.23985 17.7727 5.21447 16.5233 4.60897 15.0615C4.00347 13.5997 3.84504 11.9911 4.15372 10.4393C4.4624 8.88743 5.22433 7.46197 6.34315 6.34315C7.46197 5.22433 8.88743 4.4624 10.4393 4.15372C11.9911 3.84504 13.5997 4.00346 15.0615 4.60896C16.5233 5.21447 17.7727 6.23984 18.6518 7.55544C19.5308 8.87103 20 10.4177 20 12C20 14.1217 19.1572 16.1566 17.6569 17.6569C16.1566 19.1571 14.1217 20 12 20Z"></path></svg>Note</p><div class="starlight-aside__content"><p>Some text</p></div></aside> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/handles-complex-children.html b/packages/starlight/__tests__/remark-rehype/snapshots/handles-complex-children.html new file mode 100644 index 00000000000..6da154c2a81 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/handles-complex-children.html @@ -0,0 +1,2 @@ +<aside aria-label="Note" class="starlight-aside starlight-aside--note"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M12 11C11.7348 11 11.4804 11.1054 11.2929 11.2929C11.1054 11.4804 11 11.7348 11 12V16C11 16.2652 11.1054 16.5196 11.2929 16.7071C11.4804 16.8946 11.7348 17 12 17C12.2652 17 12.5196 16.8946 12.7071 16.7071C12.8946 16.5196 13 16.2652 13 16V12C13 11.7348 12.8946 11.4804 12.7071 11.2929C12.5196 11.1054 12.2652 11 12 11ZM12.38 7.08C12.1365 6.97998 11.8635 6.97998 11.62 7.08C11.4973 7.12759 11.3851 7.19896 11.29 7.29C11.2017 7.3872 11.1306 7.49882 11.08 7.62C11.024 7.73868 10.9966 7.86882 11 8C10.9992 8.13161 11.0245 8.26207 11.0742 8.38391C11.124 8.50574 11.1973 8.61656 11.29 8.71C11.3872 8.79833 11.4988 8.86936 11.62 8.92C11.7715 8.98224 11.936 9.00632 12.099 8.99011C12.2619 8.97391 12.4184 8.91792 12.5547 8.82707C12.691 8.73622 12.8029 8.61328 12.8805 8.46907C12.9582 8.32486 12.9992 8.16378 13 8C12.9963 7.73523 12.8927 7.48163 12.71 7.29C12.6149 7.19896 12.5028 7.12759 12.38 7.08ZM12 2C10.0222 2 8.08879 2.58649 6.4443 3.6853C4.79981 4.78412 3.51809 6.3459 2.76121 8.17317C2.00433 10.0004 1.8063 12.0111 2.19215 13.9509C2.578 15.8907 3.53041 17.6725 4.92894 19.0711C6.32746 20.4696 8.10929 21.422 10.0491 21.8079C11.9889 22.1937 13.9996 21.9957 15.8268 21.2388C17.6541 20.4819 19.2159 19.2002 20.3147 17.5557C21.4135 15.9112 22 13.9778 22 12C22 10.6868 21.7413 9.38642 21.2388 8.17317C20.7363 6.95991 19.9997 5.85752 19.0711 4.92893C18.1425 4.00035 17.0401 3.26375 15.8268 2.7612C14.6136 2.25866 13.3132 2 12 2ZM12 20C10.4178 20 8.87104 19.5308 7.55544 18.6518C6.23985 17.7727 5.21447 16.5233 4.60897 15.0615C4.00347 13.5997 3.84504 11.9911 4.15372 10.4393C4.4624 8.88743 5.22433 7.46197 6.34315 6.34315C7.46197 5.22433 8.88743 4.4624 10.4393 4.15372C11.9911 3.84504 13.5997 4.00346 15.0615 4.60896C16.5233 5.21447 17.7727 6.23984 18.6518 7.55544C19.5308 8.87103 20 10.4177 20 12C20 14.1217 19.1572 16.1566 17.6569 17.6569C16.1566 19.1571 14.1217 20 12 20Z"></path></svg>Note</p><div class="starlight-aside__content"><p>Paragraph <a href="/href/">link</a>.</p><p><img src="/img.jpg" alt="alt"></p><details> +<summary>See more</summary><p>More.</p></details></div></aside> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/nested-asides-custom-titles.html b/packages/starlight/__tests__/remark-rehype/snapshots/nested-asides-custom-titles.html new file mode 100644 index 00000000000..72ea632ea4e --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/nested-asides-custom-titles.html @@ -0,0 +1 @@ +<aside aria-label="Caution with a custom title" class="starlight-aside starlight-aside--caution"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M12 16C11.8022 16 11.6089 16.0587 11.4444 16.1686C11.28 16.2784 11.1518 16.4346 11.0761 16.6173C11.0004 16.8001 10.9806 17.0011 11.0192 17.1951C11.0578 17.3891 11.153 17.5673 11.2929 17.7071C11.4327 17.847 11.6109 17.9422 11.8049 17.9808C11.9989 18.0194 12.2 17.9996 12.3827 17.9239C12.5654 17.8482 12.7216 17.72 12.8315 17.5556C12.9413 17.3911 13 17.1978 13 17C13 16.7348 12.8946 16.4805 12.7071 16.2929C12.5196 16.1054 12.2652 16 12 16ZM22.67 17.47L14.62 3.47003C14.3598 3.00354 13.9798 2.61498 13.5192 2.3445C13.0586 2.07401 12.5341 1.9314 12 1.9314C11.4659 1.9314 10.9414 2.07401 10.4808 2.3445C10.0202 2.61498 9.64019 3.00354 9.38 3.47003L1.38 17.47C1.11079 17.924 0.966141 18.441 0.960643 18.9688C0.955144 19.4966 1.089 20.0166 1.34868 20.4761C1.60837 20.9356 1.9847 21.3185 2.43968 21.5861C2.89466 21.8536 3.41218 21.9964 3.94 22H20.06C20.5921 22.0053 21.1159 21.8689 21.5779 21.6049C22.0399 21.341 22.4234 20.9589 22.689 20.4978C22.9546 20.0368 23.0928 19.5134 23.0895 18.9814C23.0862 18.4493 22.9414 17.9277 22.67 17.47ZM20.94 19.47C20.8523 19.626 20.7245 19.7556 20.5697 19.8453C20.4149 19.935 20.2389 19.9815 20.06 19.98H3.94C3.76111 19.9815 3.5851 19.935 3.43032 19.8453C3.27553 19.7556 3.14765 19.626 3.06 19.47C2.97223 19.318 2.92602 19.1456 2.92602 18.97C2.92602 18.7945 2.97223 18.622 3.06 18.47L11.06 4.47003C11.1439 4.30623 11.2714 4.16876 11.4284 4.07277C11.5855 3.97678 11.766 3.92599 11.95 3.92599C12.134 3.92599 12.3145 3.97678 12.4716 4.07277C12.6286 4.16876 12.7561 4.30623 12.84 4.47003L20.89 18.47C20.9892 18.6199 21.0462 18.7937 21.055 18.9732C21.0638 19.1527 21.0241 19.3312 20.94 19.49V19.47ZM12 8.00003C11.7348 8.00003 11.4804 8.10538 11.2929 8.29292C11.1054 8.48046 11 8.73481 11 9.00003V13C11 13.2652 11.1054 13.5196 11.2929 13.7071C11.4804 13.8947 11.7348 14 12 14C12.2652 14 12.5196 13.8947 12.7071 13.7071C12.8946 13.5196 13 13.2652 13 13V9.00003C13 8.73481 12.8946 8.48046 12.7071 8.29292C12.5196 8.10538 12.2652 8.00003 12 8.00003Z"></path></svg>Caution with a custom title</p><div class="starlight-aside__content"><p>Nested caution.</p><aside aria-label="Note" class="starlight-aside starlight-aside--note"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M12 11C11.7348 11 11.4804 11.1054 11.2929 11.2929C11.1054 11.4804 11 11.7348 11 12V16C11 16.2652 11.1054 16.5196 11.2929 16.7071C11.4804 16.8946 11.7348 17 12 17C12.2652 17 12.5196 16.8946 12.7071 16.7071C12.8946 16.5196 13 16.2652 13 16V12C13 11.7348 12.8946 11.4804 12.7071 11.2929C12.5196 11.1054 12.2652 11 12 11ZM12.38 7.08C12.1365 6.97998 11.8635 6.97998 11.62 7.08C11.4973 7.12759 11.3851 7.19896 11.29 7.29C11.2017 7.3872 11.1306 7.49882 11.08 7.62C11.024 7.73868 10.9966 7.86882 11 8C10.9992 8.13161 11.0245 8.26207 11.0742 8.38391C11.124 8.50574 11.1973 8.61656 11.29 8.71C11.3872 8.79833 11.4988 8.86936 11.62 8.92C11.7715 8.98224 11.936 9.00632 12.099 8.99011C12.2619 8.97391 12.4184 8.91792 12.5547 8.82707C12.691 8.73622 12.8029 8.61328 12.8805 8.46907C12.9582 8.32486 12.9992 8.16378 13 8C12.9963 7.73523 12.8927 7.48163 12.71 7.29C12.6149 7.19896 12.5028 7.12759 12.38 7.08ZM12 2C10.0222 2 8.08879 2.58649 6.4443 3.6853C4.79981 4.78412 3.51809 6.3459 2.76121 8.17317C2.00433 10.0004 1.8063 12.0111 2.19215 13.9509C2.578 15.8907 3.53041 17.6725 4.92894 19.0711C6.32746 20.4696 8.10929 21.422 10.0491 21.8079C11.9889 22.1937 13.9996 21.9957 15.8268 21.2388C17.6541 20.4819 19.2159 19.2002 20.3147 17.5557C21.4135 15.9112 22 13.9778 22 12C22 10.6868 21.7413 9.38642 21.2388 8.17317C20.7363 6.95991 19.9997 5.85752 19.0711 4.92893C18.1425 4.00035 17.0401 3.26375 15.8268 2.7612C14.6136 2.25866 13.3132 2 12 2ZM12 20C10.4178 20 8.87104 19.5308 7.55544 18.6518C6.23985 17.7727 5.21447 16.5233 4.60897 15.0615C4.00347 13.5997 3.84504 11.9911 4.15372 10.4393C4.4624 8.88743 5.22433 7.46197 6.34315 6.34315C7.46197 5.22433 8.88743 4.4624 10.4393 4.15372C11.9911 3.84504 13.5997 4.00346 15.0615 4.60896C16.5233 5.21447 17.7727 6.23984 18.6518 7.55544C19.5308 8.87103 20 10.4177 20 12C20 14.1217 19.1572 16.1566 17.6569 17.6569C16.1566 19.1571 14.1217 20 12 20Z"></path></svg>Note</p><div class="starlight-aside__content"><p>Nested note.</p><aside aria-label="Tip with a custom title" class="starlight-aside starlight-aside--tip"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.43909 8.85483L1.44039 8.85354L4.96668 5.33815C5.30653 4.99386 5.7685 4.79662 6.2524 4.78972L6.26553 4.78963L12.9014 4.78962L13.8479 3.84308C16.9187 0.772319 20.0546 0.770617 21.4678 0.975145C21.8617 1.02914 22.2271 1.21053 22.5083 1.4917C22.7894 1.77284 22.9708 2.13821 23.0248 2.53199C23.2294 3.94517 23.2278 7.08119 20.1569 10.1521L19.2107 11.0983V17.7338L19.2106 17.7469C19.2037 18.2308 19.0067 18.6933 18.6624 19.0331L15.1456 22.5608C14.9095 22.7966 14.6137 22.964 14.29 23.0449C13.9663 23.1259 13.6267 23.1174 13.3074 23.0204C12.9881 22.9235 12.7011 22.7417 12.4771 22.4944C12.2533 22.2473 12.1006 21.9441 12.0355 21.6171L11.1783 17.3417L6.65869 12.822L4.34847 12.3589L2.38351 11.965C2.05664 11.8998 1.75272 11.747 1.50564 11.5232C1.25835 11.2992 1.07653 11.0122 0.979561 10.6929C0.882595 10.3736 0.874125 10.034 0.955057 9.7103C1.03599 9.38659 1.20328 9.09092 1.43909 8.85483ZM6.8186 10.8724L2.94619 10.096L6.32006 6.73268H10.9583L6.8186 10.8724ZM15.2219 5.21703C17.681 2.75787 20.0783 2.75376 21.1124 2.8876C21.2462 3.92172 21.2421 6.31895 18.783 8.77812L12.0728 15.4883L8.51172 11.9272L15.2219 5.21703ZM13.9042 21.0538L13.1279 17.1811L17.2676 13.0414V17.68L13.9042 21.0538Z"></path><path d="M9.31827 18.3446C9.45046 17.8529 9.17864 17.3369 8.68945 17.1724C8.56178 17.1294 8.43145 17.1145 8.30512 17.1243C8.10513 17.1398 7.91519 17.2172 7.76181 17.3434C7.62613 17.455 7.51905 17.6048 7.45893 17.7835C6.97634 19.2186 5.77062 19.9878 4.52406 20.4029C4.08525 20.549 3.6605 20.644 3.29471 20.7053C3.35607 20.3395 3.45098 19.9148 3.59711 19.476C4.01221 18.2294 4.78141 17.0237 6.21648 16.5411C6.39528 16.481 6.54504 16.3739 6.65665 16.2382C6.85126 16.0016 6.92988 15.678 6.84417 15.3647C6.83922 15.3466 6.83373 15.3286 6.82767 15.3106C6.74106 15.053 6.55701 14.8557 6.33037 14.7459C6.10949 14.6389 5.84816 14.615 5.59715 14.6994C5.47743 14.7397 5.36103 14.7831 5.24786 14.8294C3.22626 15.6569 2.2347 17.4173 1.75357 18.8621C1.49662 19.6337 1.36993 20.3554 1.30679 20.8818C1.27505 21.1464 1.25893 21.3654 1.25072 21.5213C1.24662 21.5993 1.24448 21.6618 1.24337 21.7066L1.243 21.7226L1.24235 21.7605L1.2422 21.7771L1.24217 21.7827L1.24217 21.7856C1.24217 22.3221 1.67703 22.7579 2.2137 22.7579L2.2155 22.7579L2.22337 22.7578L2.23956 22.7577C2.25293 22.7575 2.27096 22.7572 2.29338 22.7567C2.33821 22.7555 2.40073 22.7534 2.47876 22.7493C2.63466 22.7411 2.85361 22.725 3.11822 22.6932C3.64462 22.6301 4.36636 22.5034 5.13797 22.2464C6.58274 21.7653 8.3431 20.7738 9.17063 18.7522C9.21696 18.639 9.26037 18.5226 9.30064 18.4029C9.30716 18.3835 9.31304 18.364 9.31827 18.3446Z"></path></svg>Tip with a custom title</p><div class="starlight-aside__content"><p>Nested tip.</p></div></aside></div></aside></div></aside> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/nested-asides.html b/packages/starlight/__tests__/remark-rehype/snapshots/nested-asides.html new file mode 100644 index 00000000000..20d409a9c19 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/nested-asides.html @@ -0,0 +1 @@ +<aside aria-label="Note" class="starlight-aside starlight-aside--note"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M12 11C11.7348 11 11.4804 11.1054 11.2929 11.2929C11.1054 11.4804 11 11.7348 11 12V16C11 16.2652 11.1054 16.5196 11.2929 16.7071C11.4804 16.8946 11.7348 17 12 17C12.2652 17 12.5196 16.8946 12.7071 16.7071C12.8946 16.5196 13 16.2652 13 16V12C13 11.7348 12.8946 11.4804 12.7071 11.2929C12.5196 11.1054 12.2652 11 12 11ZM12.38 7.08C12.1365 6.97998 11.8635 6.97998 11.62 7.08C11.4973 7.12759 11.3851 7.19896 11.29 7.29C11.2017 7.3872 11.1306 7.49882 11.08 7.62C11.024 7.73868 10.9966 7.86882 11 8C10.9992 8.13161 11.0245 8.26207 11.0742 8.38391C11.124 8.50574 11.1973 8.61656 11.29 8.71C11.3872 8.79833 11.4988 8.86936 11.62 8.92C11.7715 8.98224 11.936 9.00632 12.099 8.99011C12.2619 8.97391 12.4184 8.91792 12.5547 8.82707C12.691 8.73622 12.8029 8.61328 12.8805 8.46907C12.9582 8.32486 12.9992 8.16378 13 8C12.9963 7.73523 12.8927 7.48163 12.71 7.29C12.6149 7.19896 12.5028 7.12759 12.38 7.08ZM12 2C10.0222 2 8.08879 2.58649 6.4443 3.6853C4.79981 4.78412 3.51809 6.3459 2.76121 8.17317C2.00433 10.0004 1.8063 12.0111 2.19215 13.9509C2.578 15.8907 3.53041 17.6725 4.92894 19.0711C6.32746 20.4696 8.10929 21.422 10.0491 21.8079C11.9889 22.1937 13.9996 21.9957 15.8268 21.2388C17.6541 20.4819 19.2159 19.2002 20.3147 17.5557C21.4135 15.9112 22 13.9778 22 12C22 10.6868 21.7413 9.38642 21.2388 8.17317C20.7363 6.95991 19.9997 5.85752 19.0711 4.92893C18.1425 4.00035 17.0401 3.26375 15.8268 2.7612C14.6136 2.25866 13.3132 2 12 2ZM12 20C10.4178 20 8.87104 19.5308 7.55544 18.6518C6.23985 17.7727 5.21447 16.5233 4.60897 15.0615C4.00347 13.5997 3.84504 11.9911 4.15372 10.4393C4.4624 8.88743 5.22433 7.46197 6.34315 6.34315C7.46197 5.22433 8.88743 4.4624 10.4393 4.15372C11.9911 3.84504 13.5997 4.00346 15.0615 4.60896C16.5233 5.21447 17.7727 6.23984 18.6518 7.55544C19.5308 8.87103 20 10.4177 20 12C20 14.1217 19.1572 16.1566 17.6569 17.6569C16.1566 19.1571 14.1217 20 12 20Z"></path></svg>Note</p><div class="starlight-aside__content"><p>Note contents.</p><aside aria-label="Tip" class="starlight-aside starlight-aside--tip"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.43909 8.85483L1.44039 8.85354L4.96668 5.33815C5.30653 4.99386 5.7685 4.79662 6.2524 4.78972L6.26553 4.78963L12.9014 4.78962L13.8479 3.84308C16.9187 0.772319 20.0546 0.770617 21.4678 0.975145C21.8617 1.02914 22.2271 1.21053 22.5083 1.4917C22.7894 1.77284 22.9708 2.13821 23.0248 2.53199C23.2294 3.94517 23.2278 7.08119 20.1569 10.1521L19.2107 11.0983V17.7338L19.2106 17.7469C19.2037 18.2308 19.0067 18.6933 18.6624 19.0331L15.1456 22.5608C14.9095 22.7966 14.6137 22.964 14.29 23.0449C13.9663 23.1259 13.6267 23.1174 13.3074 23.0204C12.9881 22.9235 12.7011 22.7417 12.4771 22.4944C12.2533 22.2473 12.1006 21.9441 12.0355 21.6171L11.1783 17.3417L6.65869 12.822L4.34847 12.3589L2.38351 11.965C2.05664 11.8998 1.75272 11.747 1.50564 11.5232C1.25835 11.2992 1.07653 11.0122 0.979561 10.6929C0.882595 10.3736 0.874125 10.034 0.955057 9.7103C1.03599 9.38659 1.20328 9.09092 1.43909 8.85483ZM6.8186 10.8724L2.94619 10.096L6.32006 6.73268H10.9583L6.8186 10.8724ZM15.2219 5.21703C17.681 2.75787 20.0783 2.75376 21.1124 2.8876C21.2462 3.92172 21.2421 6.31895 18.783 8.77812L12.0728 15.4883L8.51172 11.9272L15.2219 5.21703ZM13.9042 21.0538L13.1279 17.1811L17.2676 13.0414V17.68L13.9042 21.0538Z"></path><path d="M9.31827 18.3446C9.45046 17.8529 9.17864 17.3369 8.68945 17.1724C8.56178 17.1294 8.43145 17.1145 8.30512 17.1243C8.10513 17.1398 7.91519 17.2172 7.76181 17.3434C7.62613 17.455 7.51905 17.6048 7.45893 17.7835C6.97634 19.2186 5.77062 19.9878 4.52406 20.4029C4.08525 20.549 3.6605 20.644 3.29471 20.7053C3.35607 20.3395 3.45098 19.9148 3.59711 19.476C4.01221 18.2294 4.78141 17.0237 6.21648 16.5411C6.39528 16.481 6.54504 16.3739 6.65665 16.2382C6.85126 16.0016 6.92988 15.678 6.84417 15.3647C6.83922 15.3466 6.83373 15.3286 6.82767 15.3106C6.74106 15.053 6.55701 14.8557 6.33037 14.7459C6.10949 14.6389 5.84816 14.615 5.59715 14.6994C5.47743 14.7397 5.36103 14.7831 5.24786 14.8294C3.22626 15.6569 2.2347 17.4173 1.75357 18.8621C1.49662 19.6337 1.36993 20.3554 1.30679 20.8818C1.27505 21.1464 1.25893 21.3654 1.25072 21.5213C1.24662 21.5993 1.24448 21.6618 1.24337 21.7066L1.243 21.7226L1.24235 21.7605L1.2422 21.7771L1.24217 21.7827L1.24217 21.7856C1.24217 22.3221 1.67703 22.7579 2.2137 22.7579L2.2155 22.7579L2.22337 22.7578L2.23956 22.7577C2.25293 22.7575 2.27096 22.7572 2.29338 22.7567C2.33821 22.7555 2.40073 22.7534 2.47876 22.7493C2.63466 22.7411 2.85361 22.725 3.11822 22.6932C3.64462 22.6301 4.36636 22.5034 5.13797 22.2464C6.58274 21.7653 8.3431 20.7738 9.17063 18.7522C9.21696 18.639 9.26037 18.5226 9.30064 18.4029C9.30716 18.3835 9.31304 18.364 9.31827 18.3446Z"></path></svg>Tip</p><div class="starlight-aside__content"><p>Nested tip.</p></div></aside></div></aside> \ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/utils.ts b/packages/starlight/__tests__/remark-rehype/utils.ts new file mode 100644 index 00000000000..8cf9f0502b8 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/utils.ts @@ -0,0 +1,36 @@ +import type { StarlightUserConfig } from '../../types'; +import { StarlightConfigSchema } from '../../utils/user-config'; +import type { RemarkRehypePluginOptions } from '../../integrations/remark-rehype'; +import { createTranslationSystemFromFs } from '../../utils/translations-fs'; +import { absolutePathToLang } from '../../integrations/shared/absolutePathToLang'; +import { getCollectionPosixPath } from '../../utils/collection-fs'; + +/** Returns options for the Starlight remark-rehype plugins to be used in tests. */ +export async function createRemarkRehypePluginTestOptions( + starlightUserConfig?: StarlightUserConfig +): Promise<RemarkRehypePluginOptions> { + const starlightConfig = StarlightConfigSchema.parse( + starlightUserConfig ?? { title: 'Remark-Rehype Tests' } + ); + + const astroConfig = { + root: new URL(import.meta.url), + srcDir: new URL('./_src/', import.meta.url), + experimental: { headingIdCompat: false }, + }; + + return { + starlightConfig, + astroConfig, + useTranslations: await createTranslationSystemFromFs( + starlightConfig, + // Using non-existent `_src/` to ignore custom files in test fixtures. + { srcDir: astroConfig.srcDir } + ), + absolutePathToLang: (path: string) => + absolutePathToLang(path, { + docsPath: getCollectionPosixPath('docs', astroConfig.srcDir), + starlightConfig, + }), + }; +} diff --git a/packages/starlight/__tests__/sidebar-slug-error/sidebar-slug-error.test.ts b/packages/starlight/__tests__/sidebar-slug-error/sidebar-slug-error.test.ts new file mode 100644 index 00000000000..72d79291feb --- /dev/null +++ b/packages/starlight/__tests__/sidebar-slug-error/sidebar-slug-error.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, test, vi } from 'vitest'; +import { getSidebar } from '../../utils/navigation'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [['getting-started.mdx', { title: 'Getting Started' }]], + }) +); + +describe('getSidebar', () => { + test('throws an error if slug doesn’t match a content collection entry', () => { + expect(() => getSidebar('/', undefined)).toThrowErrorMatchingInlineSnapshot(` + "[AstroUserError]: + The slug \`"/getting-started/"\` specified in the Starlight sidebar config must not start or end with a slash. + Hint: + Please try updating \`"/getting-started/"\` to \`"getting-started"\`." + `); + }); +}); diff --git a/packages/starlight/__tests__/sidebar-slug-error/vitest.config.ts b/packages/starlight/__tests__/sidebar-slug-error/vitest.config.ts new file mode 100644 index 00000000000..96fc6c74fed --- /dev/null +++ b/packages/starlight/__tests__/sidebar-slug-error/vitest.config.ts @@ -0,0 +1,6 @@ +import { defineVitestConfig } from '../test-config'; + +export default defineVitestConfig({ + title: 'sidebar slug error', + sidebar: ['/getting-started/'], +}); diff --git a/packages/starlight/__tests__/sidebar/navigation-attributes.test.ts b/packages/starlight/__tests__/sidebar/navigation-attributes.test.ts new file mode 100644 index 00000000000..7424e9eb307 --- /dev/null +++ b/packages/starlight/__tests__/sidebar/navigation-attributes.test.ts @@ -0,0 +1,203 @@ +import { describe, expect, test, vi } from 'vitest'; +import { getSidebar } from '../../utils/navigation'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'Home Page' }], + ['environmental-impact.md', { title: 'Eco-friendly docs' }], + ['resources/plugins.mdx', { title: 'Plugins' }], + ['resources/themes.mdx', { title: 'Themes' }], + [ + 'reference/frontmatter.md', + { + title: 'Frontmatter Reference', + sidebar: { attrs: { class: 'advanced', ping: 'https://example.com' } }, + }, + ], + // Links to pages in the `api/v1/` directory have custom attributes, even nested ones. + ['api/v1/users.md', { title: 'Users API' }], + ['api/v1/products/add.md', { title: 'Add Product' }], + [ + 'api/v1/products/remove.md', + // A page in the `api/v1/` directory can specify custom attributes to be merged with the + // default ones. + { + title: 'Remove Product', + sidebar: { attrs: { 'data-experimental': true } }, + }, + ], + ['Deprecated API/users.md', { title: 'Deprecated Users API' }], + ], + }) +); + +describe('getSidebar', () => { + test('passes down custom HTML link attributes', () => { + expect(getSidebar('/', undefined)).toMatchInlineSnapshot(` + [ + { + "attrs": {}, + "badge": undefined, + "href": "/", + "isCurrent": true, + "label": "Home", + "type": "link", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": { + "text": "New", + "variant": "success", + }, + "href": "/intro", + "isCurrent": false, + "label": "Introduction", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Deprecated", + "variant": "default", + }, + "href": "/next-steps", + "isCurrent": false, + "label": "Next Steps", + "type": "link", + }, + { + "attrs": { + "class": "showcase-link", + "target": "_blank", + }, + "badge": undefined, + "href": "/showcase", + "isCurrent": false, + "label": "Showcase", + "type": "link", + }, + ], + "label": "Start Here", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/resources/plugins/", + "isCurrent": false, + "label": "Plugins", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/resources/themes/", + "isCurrent": false, + "label": "Themes", + "type": "link", + }, + ], + "label": "Resources", + "type": "group", + }, + { + "badge": { + "text": "Experimental", + "variant": "default", + }, + "collapsed": false, + "entries": [ + { + "attrs": { + "class": "advanced", + "ping": "https://example.com", + }, + "badge": undefined, + "href": "/reference/frontmatter/", + "isCurrent": false, + "label": "Frontmatter Reference", + "type": "link", + }, + ], + "label": "Reference", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": { + "class": "current", + "data-version": "1", + }, + "badge": undefined, + "href": "/api/v1/products/add/", + "isCurrent": false, + "label": "Add Product", + "type": "link", + }, + { + "attrs": { + "class": "current", + "data-experimental": true, + "data-version": "1", + }, + "badge": undefined, + "href": "/api/v1/products/remove/", + "isCurrent": false, + "label": "Remove Product", + "type": "link", + }, + ], + "label": "products", + "type": "group", + }, + { + "attrs": { + "class": "current", + "data-version": "1", + }, + "badge": undefined, + "href": "/api/v1/users/", + "isCurrent": false, + "label": "Users API", + "type": "link", + }, + ], + "label": "API v1", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/deprecated-api/users/", + "isCurrent": false, + "label": "Deprecated Users API", + "type": "link", + }, + ], + "label": "API (deprecated)", + "type": "group", + }, + ] + `); + }); +}); diff --git a/packages/starlight/__tests__/sidebar/navigation-badges.test.ts b/packages/starlight/__tests__/sidebar/navigation-badges.test.ts index 6c4b1863247..5cc37fd67fe 100644 --- a/packages/starlight/__tests__/sidebar/navigation-badges.test.ts +++ b/packages/starlight/__tests__/sidebar/navigation-badges.test.ts @@ -6,8 +6,10 @@ vi.mock('astro:content', async () => docs: [ ['index.mdx', { title: 'Home Page' }], ['environmental-impact.md', { title: 'Eco-friendly docs' }], + ['resources/plugins.mdx', { title: 'Plugins' }], + ['resources/themes.mdx', { title: 'Themes' }], [ - 'reference/configuration.md', + 'reference/configuration.mdx', { title: 'Config Reference', sidebar: { @@ -19,7 +21,9 @@ vi.mock('astro:content', async () => }, ], ['reference/frontmatter.md', { title: 'Frontmatter Reference', sidebar: { badge: 'New' } }], - ['guides/components.mdx', { title: 'Components' }], + ['api/v1/users.md', { title: 'Users API' }], + ['guides/project-structure.mdx', { title: 'Project Structure' }], + ['Deprecated API/users.md', { title: 'Deprecated Users API' }], ], }) ); @@ -29,6 +33,7 @@ describe('getSidebar', () => { expect(getSidebar('/', undefined)).toMatchInlineSnapshot(` [ { + "attrs": {}, "badge": undefined, "href": "/", "isCurrent": true, @@ -36,36 +41,79 @@ describe('getSidebar', () => { "type": "link", }, { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, "badge": { "text": "New", "variant": "success", }, - "href": "/intro/", + "href": "/intro", "isCurrent": false, "label": "Introduction", "type": "link", }, { + "attrs": {}, "badge": { "text": "Deprecated", "variant": "default", }, - "href": "/next-steps/", + "href": "/next-steps", "isCurrent": false, "label": "Next Steps", "type": "link", }, + { + "attrs": { + "class": "showcase-link", + "target": "_blank", + }, + "badge": undefined, + "href": "/showcase", + "isCurrent": false, + "label": "Showcase", + "type": "link", + }, ], "label": "Start Here", "type": "group", }, { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/resources/plugins/", + "isCurrent": false, + "label": "Plugins", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/resources/themes/", + "isCurrent": false, + "label": "Themes", + "type": "link", + }, + ], + "label": "Resources", + "type": "group", + }, + { + "badge": { + "text": "Experimental", + "variant": "default", + }, "collapsed": false, "entries": [ { + "attrs": {}, "badge": { "text": "Experimental", "variant": "tip", @@ -76,6 +124,7 @@ describe('getSidebar', () => { "type": "link", }, { + "attrs": {}, "badge": { "text": "New", "variant": "default", @@ -89,6 +138,41 @@ describe('getSidebar', () => { "label": "Reference", "type": "group", }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": { + "class": "current", + "data-version": "1", + }, + "badge": undefined, + "href": "/api/v1/users/", + "isCurrent": false, + "label": "Users API", + "type": "link", + }, + ], + "label": "API v1", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/deprecated-api/users/", + "isCurrent": false, + "label": "Deprecated Users API", + "type": "link", + }, + ], + "label": "API (deprecated)", + "type": "group", + }, ] `); }); diff --git a/packages/starlight/__tests__/sidebar/navigation-hidden.test.ts b/packages/starlight/__tests__/sidebar/navigation-hidden.test.ts index df539ef7870..567bccdd58e 100644 --- a/packages/starlight/__tests__/sidebar/navigation-hidden.test.ts +++ b/packages/starlight/__tests__/sidebar/navigation-hidden.test.ts @@ -6,9 +6,13 @@ vi.mock('astro:content', async () => docs: [ ['index.mdx', { title: 'Home Page' }], ['environmental-impact.md', { title: 'Eco-friendly docs' }], - ['reference/configuration.md', { title: 'Config Reference' }], + ['resources/plugins.mdx', { title: 'Plugins' }], + ['resources/themes.mdx', { title: 'Themes' }], + ['reference/configuration.mdx', { title: 'Config Reference' }], ['reference/frontmatter.md', { title: 'Frontmatter Reference', sidebar: { hidden: true } }], - ['guides/components.mdx', { title: 'Components' }], + ['api/v1/users.md', { title: 'Users API' }], + ['guides/project-structure.mdx', { title: 'Project Structure' }], + ['Deprecated API/users.md', { title: 'Deprecated Users API' }], ], }) ); @@ -18,6 +22,7 @@ describe('getSidebar', () => { expect(getSidebar('/', undefined)).toMatchInlineSnapshot(` [ { + "attrs": {}, "badge": undefined, "href": "/", "isCurrent": true, @@ -25,36 +30,79 @@ describe('getSidebar', () => { "type": "link", }, { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, "badge": { "text": "New", "variant": "success", }, - "href": "/intro/", + "href": "/intro", "isCurrent": false, "label": "Introduction", "type": "link", }, { + "attrs": {}, "badge": { "text": "Deprecated", "variant": "default", }, - "href": "/next-steps/", + "href": "/next-steps", "isCurrent": false, "label": "Next Steps", "type": "link", }, + { + "attrs": { + "class": "showcase-link", + "target": "_blank", + }, + "badge": undefined, + "href": "/showcase", + "isCurrent": false, + "label": "Showcase", + "type": "link", + }, ], "label": "Start Here", "type": "group", }, { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, + "badge": undefined, + "href": "/resources/plugins/", + "isCurrent": false, + "label": "Plugins", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/resources/themes/", + "isCurrent": false, + "label": "Themes", + "type": "link", + }, + ], + "label": "Resources", + "type": "group", + }, + { + "badge": { + "text": "Experimental", + "variant": "default", + }, + "collapsed": false, + "entries": [ + { + "attrs": {}, "badge": undefined, "href": "/reference/configuration/", "isCurrent": false, @@ -65,6 +113,41 @@ describe('getSidebar', () => { "label": "Reference", "type": "group", }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": { + "class": "current", + "data-version": "1", + }, + "badge": undefined, + "href": "/api/v1/users/", + "isCurrent": false, + "label": "Users API", + "type": "link", + }, + ], + "label": "API v1", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/deprecated-api/users/", + "isCurrent": false, + "label": "Deprecated Users API", + "type": "link", + }, + ], + "label": "API (deprecated)", + "type": "group", + }, ] `); }); diff --git a/packages/starlight/__tests__/sidebar/navigation-order.test.ts b/packages/starlight/__tests__/sidebar/navigation-order.test.ts index f0257bc5c5e..87b25a569bc 100644 --- a/packages/starlight/__tests__/sidebar/navigation-order.test.ts +++ b/packages/starlight/__tests__/sidebar/navigation-order.test.ts @@ -6,9 +6,13 @@ vi.mock('astro:content', async () => docs: [ ['index.mdx', { title: 'Home Page' }], ['environmental-impact.md', { title: 'Eco-friendly docs' }], - ['reference/configuration.md', { title: 'Config Reference' }], + ['resources/plugins.mdx', { title: 'Plugins' }], + ['resources/themes.mdx', { title: 'Themes' }], + ['reference/configuration.mdx', { title: 'Config Reference' }], ['reference/frontmatter.md', { title: 'Frontmatter Reference', sidebar: { order: 1 } }], - ['guides/components.mdx', { title: 'Components' }], + ['api/v1/users.md', { title: 'Users API' }], + ['guides/project-structure.mdx', { title: 'Project Structure' }], + ['Deprecated API/users.md', { title: 'Deprecated Users API' }], ], }) ); @@ -18,6 +22,7 @@ describe('getSidebar', () => { expect(getSidebar('/', undefined)).toMatchInlineSnapshot(` [ { + "attrs": {}, "badge": undefined, "href": "/", "isCurrent": true, @@ -25,36 +30,79 @@ describe('getSidebar', () => { "type": "link", }, { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, "badge": { "text": "New", "variant": "success", }, - "href": "/intro/", + "href": "/intro", "isCurrent": false, "label": "Introduction", "type": "link", }, { + "attrs": {}, "badge": { "text": "Deprecated", "variant": "default", }, - "href": "/next-steps/", + "href": "/next-steps", "isCurrent": false, "label": "Next Steps", "type": "link", }, + { + "attrs": { + "class": "showcase-link", + "target": "_blank", + }, + "badge": undefined, + "href": "/showcase", + "isCurrent": false, + "label": "Showcase", + "type": "link", + }, ], "label": "Start Here", "type": "group", }, { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, + "badge": undefined, + "href": "/resources/plugins/", + "isCurrent": false, + "label": "Plugins", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/resources/themes/", + "isCurrent": false, + "label": "Themes", + "type": "link", + }, + ], + "label": "Resources", + "type": "group", + }, + { + "badge": { + "text": "Experimental", + "variant": "default", + }, + "collapsed": false, + "entries": [ + { + "attrs": {}, "badge": undefined, "href": "/reference/frontmatter/", "isCurrent": false, @@ -62,6 +110,7 @@ describe('getSidebar', () => { "type": "link", }, { + "attrs": {}, "badge": undefined, "href": "/reference/configuration/", "isCurrent": false, @@ -72,6 +121,41 @@ describe('getSidebar', () => { "label": "Reference", "type": "group", }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": { + "class": "current", + "data-version": "1", + }, + "badge": undefined, + "href": "/api/v1/users/", + "isCurrent": false, + "label": "Users API", + "type": "link", + }, + ], + "label": "API v1", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/deprecated-api/users/", + "isCurrent": false, + "label": "Deprecated Users API", + "type": "link", + }, + ], + "label": "API (deprecated)", + "type": "group", + }, ] `); }); diff --git a/packages/starlight/__tests__/sidebar/navigation-unicode.test.ts b/packages/starlight/__tests__/sidebar/navigation-unicode.test.ts new file mode 100644 index 00000000000..0f59f83fa42 --- /dev/null +++ b/packages/starlight/__tests__/sidebar/navigation-unicode.test.ts @@ -0,0 +1,162 @@ +import { describe, expect, test, vi } from 'vitest'; +import { getSidebar } from '../../utils/navigation'; + +vi.mock('astro:content', async () => + (await import('../test-utils')).mockedAstroContent({ + docs: [ + ['index.mdx', { title: 'Home Page' }], + ['environmental-impact.md', { title: 'Eco-friendly docs' }], + ['resources/plugins.mdx', { title: 'Plugins' }], + ['resources/themes.mdx', { title: 'Themes' }], + ['reference/configuration.mdx', { title: 'Config Reference' }], + ['reference/frontmatter.md', { title: 'Frontmatter Reference' }], + ['api/v1/用户.md', { title: 'Path with non-ASCII characters' }], + ['guides/project-structure.mdx', { title: 'Project Structure' }], + ['Deprecated API/用户.md', { title: 'Another path with non-ASCII characters' }], + ], + }) +); + +describe('getSidebar', () => { + test('matches current page when path contains non-ascii characters', () => { + expect(getSidebar('/api/v1/%E7%94%A8%E6%88%B7', undefined)).toMatchInlineSnapshot(` + [ + { + "attrs": {}, + "badge": undefined, + "href": "/", + "isCurrent": false, + "label": "Home", + "type": "link", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": { + "text": "New", + "variant": "success", + }, + "href": "/intro", + "isCurrent": false, + "label": "Introduction", + "type": "link", + }, + { + "attrs": {}, + "badge": { + "text": "Deprecated", + "variant": "default", + }, + "href": "/next-steps", + "isCurrent": false, + "label": "Next Steps", + "type": "link", + }, + { + "attrs": { + "class": "showcase-link", + "target": "_blank", + }, + "badge": undefined, + "href": "/showcase", + "isCurrent": false, + "label": "Showcase", + "type": "link", + }, + ], + "label": "Start Here", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/resources/plugins/", + "isCurrent": false, + "label": "Plugins", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/resources/themes/", + "isCurrent": false, + "label": "Themes", + "type": "link", + }, + ], + "label": "Resources", + "type": "group", + }, + { + "badge": { + "text": "Experimental", + "variant": "default", + }, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/reference/configuration/", + "isCurrent": false, + "label": "Config Reference", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/reference/frontmatter/", + "isCurrent": false, + "label": "Frontmatter Reference", + "type": "link", + }, + ], + "label": "Reference", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": { + "class": "current", + "data-version": "1", + }, + "badge": undefined, + "href": "/api/v1/用户/", + "isCurrent": true, + "label": "Path with non-ASCII characters", + "type": "link", + }, + ], + "label": "API v1", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/deprecated-api/用户/", + "isCurrent": false, + "label": "Another path with non-ASCII characters", + "type": "link", + }, + ], + "label": "API (deprecated)", + "type": "group", + }, + ] + `); + }); +}); diff --git a/packages/starlight/__tests__/sidebar/navigation.test.ts b/packages/starlight/__tests__/sidebar/navigation.test.ts index dd5807402b2..faa8855e662 100644 --- a/packages/starlight/__tests__/sidebar/navigation.test.ts +++ b/packages/starlight/__tests__/sidebar/navigation.test.ts @@ -1,14 +1,20 @@ import { describe, expect, test, vi } from 'vitest'; import { getSidebar } from '../../utils/navigation'; +import type { SidebarEntry } from '../../utils/routing/types'; vi.mock('astro:content', async () => (await import('../test-utils')).mockedAstroContent({ docs: [ ['index.mdx', { title: 'Home Page' }], ['environmental-impact.md', { title: 'Eco-friendly docs' }], - ['reference/configuration.md', { title: 'Config Reference' }], + ['resources/plugins.mdx', { title: 'Plugins' }], + ['resources/themes.mdx', { title: 'Themes' }], + ['reference/configuration.mdx', { title: 'Config Reference' }], ['reference/frontmatter.md', { title: 'Frontmatter Reference' }], - ['guides/components.mdx', { title: 'Components' }], + ['reference/frontmatter/foo.mdx', { title: 'Foo' }], + ['api/v1/users.md', { title: 'Users API' }], + ['guides/project-structure.mdx', { title: 'Project Structure' }], + ['Deprecated API/users.md', { title: 'Deprecated Users API' }], ], }) ); @@ -18,6 +24,7 @@ describe('getSidebar', () => { expect(getSidebar('/', undefined)).toMatchInlineSnapshot(` [ { + "attrs": {}, "badge": undefined, "href": "/", "isCurrent": true, @@ -25,36 +32,79 @@ describe('getSidebar', () => { "type": "link", }, { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, "badge": { "text": "New", "variant": "success", }, - "href": "/intro/", + "href": "/intro", "isCurrent": false, "label": "Introduction", "type": "link", }, { + "attrs": {}, "badge": { "text": "Deprecated", "variant": "default", }, - "href": "/next-steps/", + "href": "/next-steps", "isCurrent": false, "label": "Next Steps", "type": "link", }, + { + "attrs": { + "class": "showcase-link", + "target": "_blank", + }, + "badge": undefined, + "href": "/showcase", + "isCurrent": false, + "label": "Showcase", + "type": "link", + }, ], "label": "Start Here", "type": "group", }, { + "badge": undefined, "collapsed": false, "entries": [ { + "attrs": {}, + "badge": undefined, + "href": "/resources/plugins/", + "isCurrent": false, + "label": "Plugins", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/resources/themes/", + "isCurrent": false, + "label": "Themes", + "type": "link", + }, + ], + "label": "Resources", + "type": "group", + }, + { + "badge": { + "text": "Experimental", + "variant": "default", + }, + "collapsed": false, + "entries": [ + { + "attrs": {}, "badge": undefined, "href": "/reference/configuration/", "isCurrent": false, @@ -63,16 +113,85 @@ describe('getSidebar', () => { }, { "badge": undefined, - "href": "/reference/frontmatter/", + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/reference/frontmatter/", + "isCurrent": false, + "label": "Frontmatter Reference", + "type": "link", + }, + { + "attrs": {}, + "badge": undefined, + "href": "/reference/frontmatter/foo/", + "isCurrent": false, + "label": "Foo", + "type": "link", + }, + ], + "label": "frontmatter", + "type": "group", + }, + ], + "label": "Reference", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": { + "class": "current", + "data-version": "1", + }, + "badge": undefined, + "href": "/api/v1/users/", "isCurrent": false, - "label": "Frontmatter Reference", + "label": "Users API", "type": "link", }, ], - "label": "Reference", + "label": "API v1", + "type": "group", + }, + { + "badge": undefined, + "collapsed": false, + "entries": [ + { + "attrs": {}, + "badge": undefined, + "href": "/deprecated-api/users/", + "isCurrent": false, + "label": "Deprecated Users API", + "type": "link", + }, + ], + "label": "API (deprecated)", "type": "group", }, ] `); }); + + test("ensures trailing slash consistency between internal and auto-generated sidebar links when using `trailingSlash: 'ignore'`", () => { + const sidebar = getSidebar('/', undefined); + const internalLinksGroup = sidebar.at(2); + const autoGeneratedLinksGroup = sidebar.at(3); + + function includesOnlyLinksWithTrailingSlash(entry: SidebarEntry | undefined): boolean { + return ( + entry !== undefined && + ((entry.type === 'link' && entry.href.endsWith('/')) || + (entry.type === 'group' && entry.entries.every(includesOnlyLinksWithTrailingSlash))) + ); + } + + expect(includesOnlyLinksWithTrailingSlash(internalLinksGroup)).toBe(true); + expect(includesOnlyLinksWithTrailingSlash(autoGeneratedLinksGroup)).toBe(true); + }); }); diff --git a/packages/starlight/__tests__/sidebar/vitest.config.ts b/packages/starlight/__tests__/sidebar/vitest.config.ts index 31860caebba..0528a3b14a7 100644 --- a/packages/starlight/__tests__/sidebar/vitest.config.ts +++ b/packages/starlight/__tests__/sidebar/vitest.config.ts @@ -18,12 +18,33 @@ export default defineVitestConfig({ }, }, { label: 'Next Steps', link: '/next-steps', badge: 'Deprecated' }, + { + label: 'Showcase', + link: '/showcase', + attrs: { class: 'showcase-link', target: '_blank' }, + }, ], }, - // A group linking to all pages in the reference directory. + // A group containing internal links using the `slug` property or its shorthand string syntax. + { + label: 'Resources', + items: ['resources/plugins', { slug: 'resources/themes' }], + }, + // A group linking to all pages in the `reference` directory. { label: 'Reference', + badge: 'Experimental', autogenerate: { directory: 'reference' }, }, + // A group linking to all pages in the `api/v1` directory. + { + label: 'API v1', + autogenerate: { directory: '/api/v1/', attrs: { class: 'current', 'data-version': '1' } }, + }, + // A group linking to all pages in the `Deprecated API/` directory. + { + label: 'API (deprecated)', + autogenerate: { directory: '/Deprecated API/' }, + }, ], }); diff --git a/packages/starlight/__tests__/snapshot-serializer-astro-error.ts b/packages/starlight/__tests__/snapshot-serializer-astro-error.ts new file mode 100644 index 00000000000..a9c64264ce8 --- /dev/null +++ b/packages/starlight/__tests__/snapshot-serializer-astro-error.ts @@ -0,0 +1,22 @@ +import { AstroError } from 'astro/errors'; +import type { SnapshotSerializer } from 'vitest'; + +export default { + /** Check if a value should be handled by this serializer, i.e. if it is an `AstroError`. */ + test(val) { + return !!val && AstroError.is(val); + }, + /** Customize serialization of Astro errors to include the `hint`. Vitest only uses `message` by default. */ + serialize({ name, message, hint }: AstroError, config, indentation, depth, refs, printer) { + const prettyError = `[${name}]:\n${indent(message)}\nHint:\n${indent(hint)}`; + return printer(prettyError, config, indentation, depth, refs); + }, +} satisfies SnapshotSerializer; + +/** Indent each line in `string` with a given character. */ +function indent(string = '', indentation = '\t') { + return string + .split('\n') + .map((line) => indentation + line) + .join('\n'); +} diff --git a/packages/starlight/__tests__/test-config.ts b/packages/starlight/__tests__/test-config.ts index 9d06a693120..8c04c39499c 100644 --- a/packages/starlight/__tests__/test-config.ts +++ b/packages/starlight/__tests__/test-config.ts @@ -1,16 +1,51 @@ /// <reference types="vitest" /> +import type { AstroConfig } from 'astro'; import { getViteConfig } from 'astro/config'; -import type { z } from 'astro/zod'; import { vitePluginStarlightUserConfig } from '../integrations/virtual-user-config'; -import { StarlightConfigSchema } from '../utils/user-config'; +import { runPlugins, type StarlightUserConfigWithPlugins } from '../utils/plugins'; +import { createTestPluginContext } from './test-plugin-utils'; +import { vitePluginStarlightCssLayerOrder } from '../integrations/vite-layer-order'; -export function defineVitestConfig(config: z.input<typeof StarlightConfigSchema>) { +const testLegacyCollections = process.env.LEGACY_COLLECTIONS === 'true'; + +export async function defineVitestConfig( + { plugins, ...config }: StarlightUserConfigWithPlugins, + opts?: { + build?: Pick<AstroConfig['build'], 'format'>; + trailingSlash?: AstroConfig['trailingSlash']; + command?: 'dev' | 'build' | 'preview'; + } +) { + const root = new URL('./', import.meta.url); + const srcDir = new URL('./src/', root); + const build = opts?.build ?? { format: 'directory' }; + const trailingSlash = opts?.trailingSlash ?? 'ignore'; + const command = opts?.command ?? 'dev'; + + const { starlightConfig, pluginTranslations } = await runPlugins( + config, + plugins, + createTestPluginContext() + ); return getViteConfig({ plugins: [ - vitePluginStarlightUserConfig(StarlightConfigSchema.parse(config), { - root: new URL(import.meta.url), - }), + vitePluginStarlightCssLayerOrder(), + vitePluginStarlightUserConfig( + command, + starlightConfig, + { + root, + srcDir, + build, + trailingSlash, + legacy: { collections: testLegacyCollections }, + }, + pluginTranslations + ), ], + test: { + snapshotSerializers: ['./snapshot-serializer-astro-error.ts'], + }, }); } diff --git a/packages/starlight/__tests__/test-plugin-utils.ts b/packages/starlight/__tests__/test-plugin-utils.ts new file mode 100644 index 00000000000..0a2f2cb3671 --- /dev/null +++ b/packages/starlight/__tests__/test-plugin-utils.ts @@ -0,0 +1,23 @@ +import type { AstroIntegrationLogger } from 'astro'; +import { type StarlightPluginContext } from '../utils/plugins'; + +export function createTestPluginContext(): StarlightPluginContext { + return { + command: 'dev', + // @ts-expect-error - we don't provide a full Astro config but only what is needed for the + // plugins to run. + config: { srcDir: new URL('./src/', import.meta.url), integrations: [] }, + isRestart: false, + logger: new TestAstroIntegrationLogger(), + }; +} + +export class TestAstroIntegrationLogger { + options = {} as AstroIntegrationLogger['options']; + constructor(public label = 'test-integration-logger') {} + fork = (label: string) => new TestAstroIntegrationLogger(label); + info = () => undefined; + warn = () => undefined; + error = () => undefined; + debug = () => undefined; +} diff --git a/packages/starlight/__tests__/test-utils.ts b/packages/starlight/__tests__/test-utils.ts index b9b0e8991af..df114789ecb 100644 --- a/packages/starlight/__tests__/test-utils.ts +++ b/packages/starlight/__tests__/test-utils.ts @@ -1,6 +1,8 @@ import { z } from 'astro/zod'; +import project from 'virtual:starlight/project-context'; import { docsSchema, i18nSchema } from '../schema'; -import type { StarlightDocsEntry } from '../utils/routing'; +import type { StarlightDocsCollectionEntry } from '../utils/routing/types'; +import type { RouteDataContext } from '../utils/routing/data'; import { vi } from 'vitest'; const frontmatterSchema = docsSchema()({ @@ -17,27 +19,44 @@ const frontmatterSchema = docsSchema()({ z.literal('webp'), z.literal('gif'), z.literal('svg'), + z.literal('avif'), ]), }), }); function mockDoc( - id: StarlightDocsEntry['id'], + docsFilePath: string, data: z.input<typeof frontmatterSchema>, body = '' -): StarlightDocsEntry { - return { - id, - slug: id.replace(/\.[^\.]+$/, '').replace(/\/index$/, ''), +): StarlightDocsCollectionEntry { + const slug = docsFilePath + .replace(/\.[^.]+$/, '') + .replace(/\s/, '-') + .replace(/\/index$/, '') + .toLowerCase(); + + const doc: StarlightDocsCollectionEntry = { + id: project.legacyCollections ? docsFilePath : slug, body, collection: 'docs', data: frontmatterSchema.parse(data), - render: (() => {}) as StarlightDocsEntry['render'], }; + + if (project.legacyCollections) { + doc.slug = slug; + } else { + doc.filePath = `src/content/docs/${docsFilePath}`; + } + + return doc; } function mockDict(id: string, data: z.input<ReturnType<typeof i18nSchema>>) { - return { id, data: i18nSchema().parse(data) }; + return { + id: project.legacyCollections ? id : id.toLocaleLowerCase(), + data: i18nSchema().parse(data), + filePath: project.legacyCollections ? undefined : `src/content/i18n/${id}.yml`, + }; } export async function mockedAstroContent({ @@ -52,6 +71,59 @@ export async function mockedAstroContent({ const mockDicts = i18n.map((dict) => mockDict(...dict)); return { ...mod, - getCollection: (collection: 'docs' | 'i18n') => (collection === 'i18n' ? mockDicts : mockDocs), + getCollection: ( + collection: 'docs' | 'i18n', + filter?: (entry: ReturnType<typeof mockDoc> | ReturnType<typeof mockDict>) => unknown + ) => { + const entries = collection === 'i18n' ? mockDicts : mockDocs; + return filter ? entries.filter(filter) : entries; + }, + }; +} + +export async function mockedCollectionConfig(docsUserSchema?: Parameters<typeof docsSchema>[0]) { + const content = await vi.importActual<typeof import('astro:content')>('astro:content'); + const schemas = await vi.importActual<typeof import('../schema')>('../schema'); + const loaders = await vi.importActual<typeof import('../loaders')>('../loaders'); + + return { + collections: { + docs: content.defineCollection( + project.legacyCollections + ? { schema: schemas.docsSchema(docsUserSchema) } + : { loader: loaders.docsLoader(), schema: schemas.docsSchema(docsUserSchema) } + ), + i18n: content.defineCollection( + project.legacyCollections + ? { type: 'data', schema: schemas.i18nSchema() } + : { loader: loaders.i18nLoader(), schema: schemas.i18nSchema() } + ), + }, + }; +} + +type RouteDataTestContextOptions = { + /** + * The pathname to get route data context for, e.g. `"/getting-started/"`. + * @default "/" + */ + pathname?: string; + /** + * Whether or not the context should include a value for `site`. Set to `false` to test without a `site` value. + * @default true + */ + setSite?: boolean; +}; + +export function getRouteDataTestContext({ + pathname, + setSite = true, +}: RouteDataTestContextOptions = {}): RouteDataContext { + const site = new URL('https://example.com'); + + return { + generator: 'Astro', + url: pathname ? new URL(pathname, site) : site, + site: setSite ? site : undefined, }; } diff --git a/packages/starlight/components.ts b/packages/starlight/components.ts index ac1c0f7bd25..67bf6b474e8 100644 --- a/packages/starlight/components.ts +++ b/packages/starlight/components.ts @@ -1,6 +1,12 @@ +export { default as Aside } from './user-components/Aside.astro'; +export { default as Badge } from './user-components/Badge.astro'; export { default as Card } from './user-components/Card.astro'; export { default as CardGrid } from './user-components/CardGrid.astro'; export { default as Icon } from './user-components/Icon.astro'; export { default as Tabs } from './user-components/Tabs.astro'; export { default as TabItem } from './user-components/TabItem.astro'; export { default as LinkCard } from './user-components/LinkCard.astro'; +export { default as Steps } from './user-components/Steps.astro'; +export { default as FileTree } from './user-components/FileTree.astro'; +export { default as LinkButton } from './user-components/LinkButton.astro'; +export { Code } from 'astro-expressive-code/components'; diff --git a/packages/starlight/components/AnchorHeading.astro b/packages/starlight/components/AnchorHeading.astro new file mode 100644 index 00000000000..8ad4af89bfa --- /dev/null +++ b/packages/starlight/components/AnchorHeading.astro @@ -0,0 +1,53 @@ +--- +import type { HTMLAttributes } from 'astro/types'; +import { transform } from 'ultrahtml'; +import sanitize from 'ultrahtml/transformers/sanitize'; +// These styles are included globally by default, but can be removed when `markdown.headingLinks` is +// set to `false`. We import them here to ensure they are included if the component is used with the +// global Markdown option disabled. +import '../style/anchor-links.css'; +import { AstroError } from 'astro/errors'; + +const headingLevels = [1, 2, 3, 4, 5, 6, '1', '2', '3', '4', '5', '6'] as const; +interface Props extends HTMLAttributes<'h1'> { + level: 1 | 2 | 3 | 4 | 5 | 6 | `${1 | 2 | 3 | 4 | 5 | 6}`; + id: string; +} + +const { level, id, ...attrs } = Astro.props; + +if (!id) { + throw new AstroError( + 'Missing `id` attribute passed to `<AnchorHeading>` component', + `The \`<AnchorHeading>\` component requires an \`id\` attribute, but received \`${typeof id === 'string' ? '""' : id}\`.` + ); +} +if (!headingLevels.includes(level)) { + throw new AstroError( + 'Invalid `level` attribute passed to `<AnchorHeading>` component', + `The \`<AnchorHeading>\` component expects a \`level\` attribute of \`1 | 2 | 3 | 4 | 5 | 6\`, but received \`${level}\`.` + ); +} + +const HeadingElement = `h${level}` as const; +const headingHTML = await Astro.slots.render('default'); +const headingString = await transform(headingHTML, [sanitize({ unblockElements: [] })]); +const accessibleLabel = Astro.locals.t('heading.anchorLabel', { + title: headingString, + interpolation: { escapeValue: false }, +}) +--- + +{/* The spacing in this component is a little awkward to ensure whitespace matches what the rehype plugin produces. */} +<div class={`sl-heading-wrapper level-h${level}`} + ><HeadingElement {id} {...attrs} set:html={headingHTML} /><a class="sl-anchor-link" href={`#${id}`} + ><span aria-hidden="true" class="sl-anchor-icon" + ><svg width="16" height="16" viewBox="0 0 24 24" + ><path + fill="currentcolor" + d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 0 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 1 0-1.42-1.42Zm8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 0 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 1 0 1.42 1.42l3.88-3.89a4.49 4.49 0 0 0 0-6.33ZM8.83 15.17a1 1 0 0 0 1.1.22 1 1 0 0 0 .32-.22l4.92-4.92a1 1 0 0 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42Z" + ></path></svg + ></span + ><span class="sr-only" data-pagefind-ignore="" set:text={accessibleLabel} /></a + ></div +> diff --git a/packages/starlight/components/Badge.astro b/packages/starlight/components/Badge.astro deleted file mode 100644 index dcfe7046566..00000000000 --- a/packages/starlight/components/Badge.astro +++ /dev/null @@ -1,86 +0,0 @@ ---- -import type { Badge } from '../schemas/badge'; - -interface Props { - variant?: Badge['variant'] | 'outline'; - text?: string; -} -const { variant = 'default', text } = Astro.props; ---- - -<span class:list={['sl-badge', variant]} set:html={text} /> - -<style> - .sl-badge { - display: inline-block; - border: 1px solid var(--sl-color-border-badge); - border-radius: 0.25rem; - font-family: var(--sl-font-system-mono); - font-size: var(--sl-text-xs); - font-weight: 400; - padding: 0.125rem 0.375rem; - line-height: 1; - color: #fff; - background-color: var(--sl-color-bg-badge); - } - - .outline { - --sl-color-bg-badge: transparent; - --sl-color-border-badge: currentColor; - color: inherit; - } - - .default { - --sl-color-bg-badge: var(--sl-color-accent-low); - --sl-color-border-badge: var(--sl-color-accent); - } - - .note { - --sl-color-bg-badge: var(--sl-color-blue-low); - --sl-color-border-badge: var(--sl-color-blue); - } - - .danger { - --sl-color-bg-badge: var(--sl-color-red-low); - --sl-color-border-badge: var(--sl-color-red); - } - - .success { - --sl-color-bg-badge: var(--sl-color-green-low); - --sl-color-border-badge: var(--sl-color-green); - } - - .caution { - --sl-color-bg-badge: var(--sl-color-orange-low); - --sl-color-border-badge: var(--sl-color-orange); - } - - .tip { - --sl-color-bg-badge: var(--sl-color-purple-low); - --sl-color-border-badge: var(--sl-color-purple); - } - - :global([data-theme='light']) .default { - --sl-color-bg-badge: var(--sl-color-accent-high); - } - - :global([data-theme='light']) .note { - --sl-color-bg-badge: var(--sl-color-blue-high); - } - - :global([data-theme='light']) .danger { - --sl-color-bg-badge: var(--sl-color-red-high); - } - - :global([data-theme='light']) .success { - --sl-color-bg-badge: var(--sl-color-green-high); - } - - :global([data-theme='light']) .caution { - --sl-color-bg-badge: var(--sl-color-orange-high); - } - - :global([data-theme='light']) .tip { - --sl-color-bg-badge: var(--sl-color-purple-high); - } -</style> diff --git a/packages/starlight/components/Banner.astro b/packages/starlight/components/Banner.astro index e6307bec18d..bc1bf0635d6 100644 --- a/packages/starlight/components/Banner.astro +++ b/packages/starlight/components/Banner.astro @@ -1,23 +1,23 @@ --- -interface Props { - content: string; -} +const { banner } = Astro.locals.starlightRoute.entry.data; --- -<div class="sl-banner" set:html={Astro.props.content} /> +{banner && <div class="sl-banner" data-pagefind-ignore set:html={banner.content} />} <style> - .sl-banner { - --__sl-banner-text: var(--sl-color-banner-text, var(--sl-color-text-invert)); - padding: var(--sl-nav-pad-y) var(--sl-nav-pad-x); - background-color: var(--sl-color-banner-bg, var(--sl-color-bg-accent)); - color: var(--__sl-banner-text); - line-height: var(--sl-line-height-headings); - text-align: center; - text-wrap: balance; - box-shadow: var(--sl-shadow-sm); - } - .sl-banner :global(a) { - color: var(--__sl-banner-text); + @layer starlight.core { + .sl-banner { + --__sl-banner-text: var(--sl-color-banner-text, var(--sl-color-text-invert)); + padding: var(--sl-nav-pad-y) var(--sl-nav-pad-x); + background-color: var(--sl-color-banner-bg, var(--sl-color-bg-accent)); + color: var(--__sl-banner-text); + line-height: var(--sl-line-height-headings); + text-align: center; + text-wrap: balance; + box-shadow: var(--sl-shadow-sm); + } + .sl-banner :global(a) { + color: var(--__sl-banner-text); + } } </style> diff --git a/packages/starlight/components/CallToAction.astro b/packages/starlight/components/CallToAction.astro deleted file mode 100644 index 44ef78de44a..00000000000 --- a/packages/starlight/components/CallToAction.astro +++ /dev/null @@ -1,48 +0,0 @@ ---- -import Icon from '../user-components/Icon.astro'; -import type { Icons } from './Icons'; - -interface Props { - variant: 'primary' | 'secondary' | 'minimal'; - link: string; - icon?: undefined | { type: 'icon'; name: keyof typeof Icons } | { type: 'raw'; html: string }; -} - -const { link, variant, icon } = Astro.props; ---- - -<a class:list={['sl-flex action', variant]} href={link}> - <slot /> - {icon?.type === 'icon' && <Icon name={icon.name} size="1.5rem" />} - {icon?.type === 'raw' && <Fragment set:html={icon.html} />} -</a> - -<style> - .action { - gap: 0.5em; - align-items: center; - border-radius: 999rem; - padding: 0.5rem 1.125rem; - color: var(--sl-color-white); - line-height: 1.1875; - text-decoration: none; - font-size: var(--sl-text-sm); - } - .action.primary { - background: var(--sl-color-text-accent); - color: var(--sl-color-black); - } - .action.secondary { - border: 1px solid; - } - .action.minimal { - padding-inline: 0; - } - - @media (min-width: 50rem) { - .action { - font-size: var(--sl-text-base); - padding: 1rem 1.25rem; - } - } -</style> diff --git a/packages/starlight/components/ContentNotice.astro b/packages/starlight/components/ContentNotice.astro new file mode 100644 index 00000000000..28858f97810 --- /dev/null +++ b/packages/starlight/components/ContentNotice.astro @@ -0,0 +1,33 @@ +--- +import type { StarlightIcon } from '../components/Icons'; +import Icon from '../user-components/Icon.astro'; + +interface Props { + icon: StarlightIcon; + label: string; +} + +const { icon, label } = Astro.props; +--- + +<p class="sl-flex"> + <Icon name={icon} size="1.5em" color="var(--sl-color-orange-high)" /> + <span>{label}</span> +</p> + +<style> + @layer starlight.core { + p { + border: 1px solid var(--sl-color-orange); + padding: 0.75em 1em; + background-color: var(--sl-color-orange-low); + color: var(--sl-color-orange-high); + width: max-content; + max-width: 100%; + align-items: center; + gap: 0.75em; + font-size: var(--sl-text-body-sm); + line-height: var(--sl-line-height-headings); + } + } +</style> diff --git a/packages/starlight/components/ContentPanel.astro b/packages/starlight/components/ContentPanel.astro index d4089408f55..08f44fed314 100644 --- a/packages/starlight/components/ContentPanel.astro +++ b/packages/starlight/components/ContentPanel.astro @@ -3,23 +3,25 @@ </div> <style> - .content-panel { - padding: 1.5rem var(--sl-content-pad-x); - } - .content-panel + .content-panel { - border-top: 1px solid var(--sl-color-hairline); - } - .sl-container { - max-width: var(--sl-content-width); - } + @layer starlight.core { + .content-panel { + padding: 1.5rem var(--sl-content-pad-x); + } + .content-panel + .content-panel { + border-top: 1px solid var(--sl-color-hairline); + } + .sl-container { + max-width: var(--sl-content-width); + } - .sl-container > :global(* + *) { - margin-top: 1.5rem; - } + .sl-container > :global(* + *) { + margin-top: 1.5rem; + } - @media (min-width: 72rem) { - .sl-container { - margin-inline: var(--sl-content-margin-inline, auto); + @media (min-width: 72rem) { + .sl-container { + margin-inline: var(--sl-content-margin-inline, auto); + } } } </style> diff --git a/packages/starlight/components/DraftContentNotice.astro b/packages/starlight/components/DraftContentNotice.astro new file mode 100644 index 00000000000..8c3651534af --- /dev/null +++ b/packages/starlight/components/DraftContentNotice.astro @@ -0,0 +1,5 @@ +--- +import ContentNotice from './ContentNotice.astro'; +--- + +<ContentNotice icon="warning" label={Astro.locals.t('page.draft')} /> diff --git a/packages/starlight/components/EditLink.astro b/packages/starlight/components/EditLink.astro index 4de013482fc..7e30606e0ef 100644 --- a/packages/starlight/components/EditLink.astro +++ b/packages/starlight/components/EditLink.astro @@ -1,48 +1,28 @@ --- -import type { CollectionEntry } from 'astro:content'; -import config from 'virtual:starlight/user-config'; -import project from 'virtual:starlight/project-context'; -import { useTranslations } from '../utils/translations'; import Icon from '../user-components/Icon.astro'; -interface Props { - data: CollectionEntry<'docs'>['data']; - id: CollectionEntry<'docs'>['id']; - locale: string | undefined; -} - -const t = useTranslations(Astro.props.locale); -const { editUrl } = Astro.props.data; -const srcPath = project.srcDir.replace(project.root, ''); - -let { baseUrl } = config.editLink; -if (baseUrl && baseUrl.at(-1) !== '/') baseUrl += '/'; - -const url = - typeof editUrl === 'string' - ? editUrl - : baseUrl - ? baseUrl + srcPath + 'content/docs/' + Astro.props.id - : undefined; +const { editUrl } = Astro.locals.starlightRoute; --- { - editUrl !== false && url && ( - <a href={url} class="sl-flex"> + editUrl && ( + <a href={editUrl} class="sl-flex print:hidden"> <Icon name="pencil" size="1.2em" /> - {t('page.editLink')} + {Astro.locals.t('page.editLink')} </a> ) } <style> - a { - gap: 0.5rem; - align-items: center; - text-decoration: none; - color: var(--sl-color-gray-3); - } - a:hover { - color: var(--sl-color-white); + @layer starlight.core { + a { + gap: 0.5rem; + align-items: center; + text-decoration: none; + color: var(--sl-color-gray-3); + } + a:hover { + color: var(--sl-color-white); + } } </style> diff --git a/packages/starlight/components/FallbackContentNotice.astro b/packages/starlight/components/FallbackContentNotice.astro index 9b7ca623d56..efed300fb78 100644 --- a/packages/starlight/components/FallbackContentNotice.astro +++ b/packages/starlight/components/FallbackContentNotice.astro @@ -1,31 +1,5 @@ --- -import { useTranslations } from '../utils/translations'; -import Icon from '../user-components/Icon.astro'; - -interface Props { - locale: string | undefined; -} - -const t = useTranslations(Astro.props.locale); +import ContentNotice from './ContentNotice.astro'; --- -<p class="sl-flex"> - <Icon name={'warning'} size="1.5em" color="var(--sl-color-orange-high)" /><span - >{t('i18n.untranslatedContent')}</span - > -</p> - -<style> - p { - border: 1px solid var(--sl-color-orange); - padding: 0.75em 1em; - background-color: var(--sl-color-orange-low); - color: var(--sl-color-orange-high); - width: max-content; - max-width: 100%; - align-items: center; - gap: 0.75em; - font-size: var(--sl-text-body-sm); - line-height: var(--sl-line-height-headings); - } -</style> +<ContentNotice icon="warning" label={Astro.locals.t('i18n.untranslatedContent')} /> diff --git a/packages/starlight/components/Footer.astro b/packages/starlight/components/Footer.astro index 2d14dee73e3..070530aa5f4 100644 --- a/packages/starlight/components/Footer.astro +++ b/packages/starlight/components/Footer.astro @@ -1,54 +1,61 @@ --- +import EditLink from 'virtual:starlight/components/EditLink'; +import LastUpdated from 'virtual:starlight/components/LastUpdated'; +import Pagination from 'virtual:starlight/components/Pagination'; import config from 'virtual:starlight/user-config'; -import { type SidebarEntry, getPrevNextLinks } from '../utils/navigation'; -import type { StarlightDocsEntry } from '../utils/routing'; -import type { LocaleData } from '../utils/slugs'; - -import LastUpdated from '../components/LastUpdated.astro'; -import PrevNextLinks from '../components/PrevNextLinks.astro'; -import EditLink from './EditLink.astro'; - -interface Props extends LocaleData { - entry: StarlightDocsEntry; - sidebar: SidebarEntry[]; -} - -const { entry, dir, lang, locale, sidebar } = Astro.props; -const prevNextLinks = getPrevNextLinks(sidebar, config.pagination, { - prev: entry.data.prev, - next: entry.data.next, -}); +import { Icon } from '../components'; --- -<footer> +<footer class="sl-flex"> <div class="meta sl-flex"> - {config.editLink.baseUrl && <EditLink data={entry.data} id={entry.id} {locale} />} - { - (entry.data.lastUpdated ?? config.lastUpdated) && ( - <LastUpdated - id={entry.id} - {lang} - lastUpdated={ - typeof entry.data.lastUpdated !== 'boolean' ? entry.data.lastUpdated : undefined - } - {locale} - /> - ) - } + <EditLink /> + <LastUpdated /> </div> - <PrevNextLinks {...prevNextLinks} {dir} {locale} /> + <Pagination /> + + { + config.credits && ( + <a class="kudos sl-flex" href="https://starlight.astro.build"> + <Icon name={'starlight'} /> {Astro.locals.t('builtWithStarlight.label')} + </a> + ) + } </footer> <style> - .meta { - gap: 0.75rem 3rem; - justify-content: space-between; - flex-wrap: wrap; - margin-block: 3rem 1.5rem; - font-size: var(--sl-text-sm); - color: var(--sl-color-gray-3); + @layer starlight.core { + footer { + flex-direction: column; + gap: 1.5rem; + } + .meta { + gap: 0.75rem 3rem; + justify-content: space-between; + flex-wrap: wrap; + margin-top: 3rem; + font-size: var(--sl-text-sm); + color: var(--sl-color-gray-3); + } + .meta > :global(p:only-child) { + margin-inline-start: auto; + } + + .kudos { + align-items: center; + gap: 0.5em; + margin: 1.5rem auto; + font-size: var(--sl-text-xs); + text-decoration: none; + color: var(--sl-color-gray-3); + } + .kudos:hover { + color: var(--sl-color-white); + } } - .meta > :global(p:only-child) { - margin-inline-start: auto; + + @layer starlight.components { + .kudos :global(svg) { + color: var(--sl-color-orange); + } } </style> diff --git a/packages/starlight/components/Head.astro b/packages/starlight/components/Head.astro new file mode 100644 index 00000000000..eeccf17932e --- /dev/null +++ b/packages/starlight/components/Head.astro @@ -0,0 +1,5 @@ +--- +const { head } = Astro.locals.starlightRoute; +--- + +{head.map(({ tag: Tag, attrs, content }) => <Tag {...attrs} set:html={content} />)} diff --git a/packages/starlight/components/HeadSEO.astro b/packages/starlight/components/HeadSEO.astro deleted file mode 100644 index d187bd98241..00000000000 --- a/packages/starlight/components/HeadSEO.astro +++ /dev/null @@ -1,106 +0,0 @@ ---- -import type { CollectionEntry, z } from 'astro:content'; -import config from 'virtual:starlight/user-config'; -import type { HeadConfigSchema } from '../schemas/head'; -import { createHead } from '../utils/head'; -import { localizedUrl } from '../utils/localizedUrl'; -import { fileWithBase } from '../utils/base'; -import { version } from '../package.json'; - -interface Props { - data: CollectionEntry<'docs'>['data']; - lang: string; -} - -const { data, lang } = Astro.props; - -const canonical = Astro.site ? new URL(Astro.url.pathname, Astro.site) : undefined; -const title = data.title || config.title; -const description = data.description || config.description; - -const headDefaults: z.input<ReturnType<typeof HeadConfigSchema>> = [ - { tag: 'meta', attrs: { charset: 'utf-8' } }, - { - tag: 'meta', - attrs: { name: 'viewport', content: 'width=device-width, initial-scale=1' }, - }, - { tag: 'title', content: title }, - { tag: 'link', attrs: { rel: 'canonical', href: canonical?.href } }, - { tag: 'meta', attrs: { name: 'generator', content: Astro.generator } }, - { - tag: 'meta', - attrs: { name: 'generator', content: `Starlight v${version}` }, - }, - // Favicon - { - tag: 'link', - attrs: { - rel: 'shortcut icon', - href: fileWithBase(config.favicon.href), - type: config.favicon.type, - }, - }, - // OpenGraph Tags - { tag: 'meta', attrs: { property: 'og:title', content: title } }, - { tag: 'meta', attrs: { property: 'og:type', content: 'article' } }, - { tag: 'meta', attrs: { property: 'og:url', content: canonical?.href } }, - { tag: 'meta', attrs: { property: 'og:locale', content: lang } }, - { tag: 'meta', attrs: { property: 'og:description', content: description } }, - { tag: 'meta', attrs: { property: 'og:site_name', content: config.title } }, - // Twitter Tags - { - tag: 'meta', - attrs: { name: 'twitter:card', content: 'summary_large_image' }, - }, - { tag: 'meta', attrs: { name: 'twitter:title', content: title } }, - { tag: 'meta', attrs: { name: 'twitter:description', content: description } }, -]; - -if (description) - headDefaults.push({ - tag: 'meta', - attrs: { name: 'description', content: description }, - }); - -// Link to language alternates. -if (canonical && config.isMultilingual) { - for (const locale in config.locales) { - const localeOpts = config.locales[locale]; - if (!localeOpts) continue; - headDefaults.push({ - tag: 'link', - attrs: { - rel: 'alternate', - hreflang: localeOpts.lang, - href: localizedUrl(canonical, locale).href, - }, - }); - } -} - -// Link to sitemap, but only when `site` is set. -if (Astro.site) { - headDefaults.push({ - tag: 'link', - attrs: { - rel: 'sitemap', - href: fileWithBase('/sitemap-index.xml'), - }, - }); -} - -// Link to Twitter account if set in Starlight config. -if (config.social?.twitter) { - headDefaults.push({ - tag: 'meta', - attrs: { - name: 'twitter:site', - content: new URL(config.social.twitter).pathname, - }, - }); -} - -const head = createHead(headDefaults, config.head, data.head); ---- - -{head.map(({ tag: Tag, attrs, content }) => <Tag {...attrs} set:html={content} />)} diff --git a/packages/starlight/components/Header.astro b/packages/starlight/components/Header.astro index 6ed8aa1c20b..2a05b737636 100644 --- a/packages/starlight/components/Header.astro +++ b/packages/starlight/components/Header.astro @@ -1,68 +1,94 @@ --- -import LanguageSelect from './LanguageSelect.astro'; -import Search from './Search.astro'; -import SiteTitle from './SiteTitle.astro'; -import SocialIcons from './SocialIcons.astro'; -import ThemeSelect from './ThemeSelect.astro'; +import config from 'virtual:starlight/user-config'; -interface Props { - locale: string | undefined; -} +import LanguageSelect from 'virtual:starlight/components/LanguageSelect'; +import Search from 'virtual:starlight/components/Search'; +import SiteTitle from 'virtual:starlight/components/SiteTitle'; +import SocialIcons from 'virtual:starlight/components/SocialIcons'; +import ThemeSelect from 'virtual:starlight/components/ThemeSelect'; -const { locale } = Astro.props; +/** + * Render the `Search` component if Pagefind is enabled or the default search component has been overridden. + */ +const shouldRenderSearch = + config.pagefind || config.components.Search !== '@astrojs/starlight/components/Search.astro'; --- -<div class="header sl-flex"> - <SiteTitle {locale} /> - <Search {locale} /> - <div class="sl-hidden md:sl-flex right-group"> - <SocialIcons /> - <ThemeSelect {locale} /> - <LanguageSelect {locale} /> +<div class="header"> + <div class="title-wrapper sl-flex"> + <SiteTitle /> + </div> + <div class="sl-flex print:hidden"> + {shouldRenderSearch && <Search />} + </div> + <div class="sl-hidden md:sl-flex print:hidden right-group"> + <div class="sl-flex social-icons"> + <SocialIcons /> + </div> + <ThemeSelect /> + <LanguageSelect /> </div> </div> <style> - .header { - gap: var(--sl-nav-gap); - justify-content: space-between; - align-items: center; - height: 100%; - } + @layer starlight.core { + .header { + display: flex; + gap: var(--sl-nav-gap); + justify-content: space-between; + align-items: center; + height: 100%; + } - .right-group { - gap: 1rem; - align-items: center; - } + .title-wrapper { + /* Prevent long titles overflowing and covering the search and menu buttons on narrow viewports. */ + overflow: clip; + /* Avoid clipping focus ring around link inside title wrapper. */ + padding: 0.25rem; + margin: -0.25rem; + min-width: 0; + } - @media (min-width: 50rem) { - :global(:root[data-has-sidebar]) { - --__sidebar-pad: calc(2 * var(--sl-nav-pad-x)); + .right-group, + .social-icons { + gap: 1rem; + align-items: center; } - :global(:root:not([data-has-toc])) { - --__toc-width: 0rem; + .social-icons::after { + content: ''; + height: 2rem; + border-inline-end: 1px solid var(--sl-color-gray-5); } - .header { - --__sidebar-width: max(0rem, var(--sl-content-inline-start, 0rem) - var(--sl-nav-pad-x)); - --__main-column-fr: calc( - ( - 100% + var(--__sidebar-pad, 0rem) - var(--__toc-width, var(--sl-sidebar-width)) - - (2 * var(--__toc-width, var(--sl-nav-pad-x))) - var(--sl-content-inline-start, 0rem) - - var(--sl-content-width) - ) / 2 - ); - display: grid; - grid-template-columns: + + @media (min-width: 50rem) { + :global(:root[data-has-sidebar]) { + --__sidebar-pad: calc(2 * var(--sl-nav-pad-x)); + } + :global(:root:not([data-has-toc])) { + --__toc-width: 0rem; + } + .header { + --__sidebar-width: max(0rem, var(--sl-content-inline-start, 0rem) - var(--sl-nav-pad-x)); + --__main-column-fr: calc( + ( + 100% + var(--__sidebar-pad, 0rem) - var(--__toc-width, var(--sl-sidebar-width)) - + (2 * var(--__toc-width, var(--sl-nav-pad-x))) - var(--sl-content-inline-start, 0rem) - + var(--sl-content-width) + ) / 2 + ); + display: grid; + grid-template-columns: /* 1 (site title): runs up until the main content column’s left edge or the width of the title, whichever is the largest */ - minmax( - calc(var(--__sidebar-width) + max(0rem, var(--__main-column-fr) - var(--sl-nav-gap))), - auto - ) - /* 2 (search box): all free space that is available. */ - 1fr - /* 3 (right items): use the space that these need. */ - auto; - align-content: center; + minmax( + calc(var(--__sidebar-width) + max(0rem, var(--__main-column-fr) - var(--sl-nav-gap))), + auto + ) + /* 2 (search box): all free space that is available. */ + 1fr + /* 3 (right items): use the space that these need. */ + auto; + align-content: center; + } } } </style> diff --git a/packages/starlight/components/Hero.astro b/packages/starlight/components/Hero.astro index fbc3692c945..e537a592777 100644 --- a/packages/starlight/components/Hero.astro +++ b/packages/starlight/components/Hero.astro @@ -1,47 +1,62 @@ --- -import type { CollectionEntry } from 'astro:content'; import { Image } from 'astro:assets'; -import CallToAction from './CallToAction.astro'; +import { PAGE_TITLE_ID } from '../constants'; +import LinkButton from '../user-components/LinkButton.astro'; -interface Props { - fallbackTitle: string; - hero: NonNullable<CollectionEntry<'docs'>['data']['hero']>; -} - -const { title = Astro.props.fallbackTitle, tagline, image, actions } = Astro.props.hero; +const { data } = Astro.locals.starlightRoute.entry; +const { title = data.title, tagline, image, actions = [] } = data.hero || {}; const imageAttrs = { loading: 'eager' as const, decoding: 'async' as const, width: 400, height: 400, - alt: image?.alt, + alt: image?.alt || '', }; + +let darkImage: ImageMetadata | undefined; +let lightImage: ImageMetadata | undefined; +let rawHtml: string | undefined; +if (image) { + if ('file' in image) { + darkImage = image.file; + } else if ('dark' in image) { + darkImage = image.dark; + lightImage = image.light; + } else { + rawHtml = image.html; + } +} --- <div class="hero"> { - image?.file ? ( - image.file.format === 'svg' ? ( - <img src={image.file.src} {...imageAttrs} /> - ) : ( - <Image src={image.file} {...imageAttrs} /> - ) - ) : ( - image?.html && <div class="hero-html sl-flex" set:html={image.html} /> + darkImage && ( + <Image + src={darkImage} + {...imageAttrs} + class:list={{ 'light:sl-hidden': Boolean(lightImage) }} + /> ) } + {lightImage && <Image src={lightImage} {...imageAttrs} class="dark:sl-hidden" />} + {rawHtml && <div class="hero-html sl-flex" set:html={rawHtml} />} <div class="sl-flex stack"> <div class="sl-flex copy"> - <h1 id="_top" data-page-title set:html={title} /> + <h1 id={PAGE_TITLE_ID} data-page-title set:html={title} /> {tagline && <div class="tagline" set:html={tagline} />} </div> { actions.length > 0 && ( <div class="sl-flex actions"> - {actions.map(({ text, ...attrs }) => ( - <CallToAction {...attrs} set:html={text} /> - ))} + {actions.map( + ({ attrs: { class: className, ...attrs } = {}, icon, link: href, text, variant }) => ( + <LinkButton {href} {variant} icon={icon?.name} class:list={[className]} {...attrs}> + {text} + {icon?.html && <Fragment set:html={icon.html} />} + </LinkButton> + ) + )} </div> ) } @@ -49,78 +64,80 @@ const imageAttrs = { </div> <style> - .hero { - display: grid; - align-items: center; - gap: 1rem; - padding-bottom: 1rem; - } - - .hero > img, - .hero > .hero-html { - object-fit: contain; - width: min(70%, 20rem); - height: auto; - margin-inline: auto; - } - - .stack { - flex-direction: column; - gap: clamp(1.5rem, calc(1.5rem + 1vw), 2rem); - text-align: center; - } - - .copy { - flex-direction: column; - gap: 1rem; - align-items: center; - } - - .copy > * { - max-width: 50ch; - } - - h1 { - font-size: clamp(var(--sl-text-3xl), calc(0.25rem + 5vw), var(--sl-text-6xl)); - line-height: var(--sl-line-height-headings); - font-weight: 600; - color: var(--sl-color-white); - } - - .tagline { - font-size: clamp(var(--sl-text-base), calc(0.0625rem + 2vw), var(--sl-text-xl)); - color: var(--sl-color-gray-2); - } - - .actions { - gap: 1rem 2rem; - flex-wrap: wrap; - justify-content: center; - } - - @media (min-width: 50rem) { + @layer starlight.core { .hero { - grid-template-columns: 7fr 4fr; - gap: 3%; - padding-block: clamp(2.5rem, calc(1rem + 10vmin), 10rem); + display: grid; + align-items: center; + gap: 1rem; + padding-bottom: 1rem; } .hero > img, .hero > .hero-html { - order: 2; - width: min(100%, 25rem); + object-fit: contain; + width: min(70%, 20rem); + height: auto; + margin-inline: auto; } .stack { - text-align: start; + flex-direction: column; + gap: clamp(1.5rem, calc(1.5rem + 1vw), 2rem); + text-align: center; } .copy { - align-items: flex-start; + flex-direction: column; + gap: 1rem; + align-items: center; + } + + .copy > * { + max-width: 50ch; + } + + h1 { + font-size: clamp(var(--sl-text-3xl), calc(0.25rem + 5vw), var(--sl-text-6xl)); + line-height: var(--sl-line-height-headings); + font-weight: 600; + color: var(--sl-color-white); + } + + .tagline { + font-size: clamp(var(--sl-text-base), calc(0.0625rem + 2vw), var(--sl-text-xl)); + color: var(--sl-color-gray-2); } .actions { - justify-content: flex-start; + gap: 1rem 2rem; + flex-wrap: wrap; + justify-content: center; + } + + @media (min-width: 50rem) { + .hero { + grid-template-columns: 7fr 4fr; + gap: 3%; + padding-block: clamp(2.5rem, calc(1rem + 10vmin), 10rem); + } + + .hero > img, + .hero > .hero-html { + order: 2; + width: min(100%, 25rem); + } + + .stack { + text-align: start; + } + + .copy { + align-items: flex-start; + } + + .actions { + justify-content: flex-start; + } } } </style> diff --git a/packages/starlight/components/Icons.ts b/packages/starlight/components/Icons.ts index 68f1632fa4a..e0cde48b409 100644 --- a/packages/starlight/components/Icons.ts +++ b/packages/starlight/components/Icons.ts @@ -1,17 +1,25 @@ -export const Icons = { +import { FileIcons } from '../user-components/file-tree-icons'; + +export const BuiltInIcons = { 'up-caret': - '<path d="M16.9999 13.41L12.7099 9.17C12.617 9.07628 12.5064 9.00188 12.3845 8.95111C12.2627 8.90035 12.132 8.87421 11.9999 8.87421C11.8679 8.87421 11.7372 8.90035 11.6154 8.95111C11.4935 9.00188 11.3829 9.07628 11.2899 9.17L7.04995 13.41C6.95622 13.503 6.88183 13.6136 6.83106 13.7354C6.78029 13.8573 6.75415 13.988 6.75415 14.12C6.75415 14.252 6.78029 14.3827 6.83106 14.5046C6.88183 14.6264 6.95622 14.737 7.04995 14.83C7.23731 15.0163 7.49076 15.1208 7.75495 15.1208C8.01913 15.1208 8.27259 15.0163 8.45995 14.83L11.9999 11.29L15.5399 14.83C15.7262 15.0147 15.9776 15.1189 16.2399 15.12C16.3716 15.1208 16.502 15.0955 16.6239 15.0458C16.7457 14.996 16.8565 14.9227 16.9499 14.83C17.047 14.7404 17.1254 14.6324 17.1805 14.5123C17.2356 14.3923 17.2664 14.2625 17.271 14.1304C17.2757 13.9984 17.2541 13.8667 17.2076 13.7431C17.161 13.6194 17.0905 13.5062 16.9999 13.41Z"></path>', + '<path d="m17 13.41-4.29-4.24a.999.999 0 0 0-1.42 0l-4.24 4.24a1 1 0 1 0 1.41 1.42L12 11.29l3.54 3.54a1 1 0 0 0 1.41 0 1 1 0 0 0 .05-1.42Z"/>', 'down-caret': - '<path d="M17 9.17C16.8126 8.98375 16.5592 8.87921 16.295 8.87921C16.0308 8.87921 15.7774 8.98375 15.59 9.17L12 12.71L8.46001 9.17C8.27265 8.98375 8.0192 8.87921 7.75501 8.87921C7.49082 8.87921 7.23737 8.98375 7.05001 9.17C6.95628 9.26297 6.88189 9.37357 6.83112 9.49543C6.78035 9.61729 6.75421 9.74799 6.75421 9.88C6.75421 10.012 6.78035 10.1427 6.83112 10.2646C6.88189 10.3864 6.95628 10.497 7.05001 10.59L11.29 14.83C11.383 14.9237 11.4936 14.9981 11.6154 15.0489C11.7373 15.0997 11.868 15.1258 12 15.1258C12.132 15.1258 12.2627 15.0997 12.3846 15.0489C12.5064 14.9981 12.617 14.9237 12.71 14.83L17 10.59C17.0937 10.497 17.1681 10.3864 17.2189 10.2646C17.2697 10.1427 17.2958 10.012 17.2958 9.88C17.2958 9.74799 17.2697 9.61729 17.2189 9.49543C17.1681 9.37357 17.0937 9.26297 17 9.17Z"></path>', + '<path d="M17 9.17a1 1 0 0 0-1.41 0L12 12.71 8.46 9.17a1 1 0 1 0-1.41 1.42l4.24 4.24a1.002 1.002 0 0 0 1.42 0L17 10.59a1.002 1.002 0 0 0 0-1.42Z"/>', 'right-caret': - '<path d="M14.83 11.29L10.59 7.05001C10.497 6.95628 10.3864 6.88189 10.2646 6.83112C10.1427 6.78035 10.012 6.75421 9.88 6.75421C9.74799 6.75421 9.61729 6.78035 9.49543 6.83112C9.37357 6.88189 9.26297 6.95628 9.17 7.05001C8.98375 7.23737 8.87921 7.49082 8.87921 7.75501C8.87921 8.0192 8.98375 8.27265 9.17 8.46001L12.71 12L9.17 15.54C8.98375 15.7274 8.87921 15.9808 8.87921 16.245C8.87921 16.5092 8.98375 16.7626 9.17 16.95C9.26344 17.0427 9.37426 17.116 9.4961 17.1658C9.61794 17.2155 9.7484 17.2408 9.88 17.24C10.0116 17.2408 10.1421 17.2155 10.2639 17.1658C10.3857 17.116 10.4966 17.0427 10.59 16.95L14.83 12.71C14.9237 12.617 14.9981 12.5064 15.0489 12.3846C15.0997 12.2627 15.1258 12.132 15.1258 12C15.1258 11.868 15.0997 11.7373 15.0489 11.6154C14.9981 11.4936 14.9237 11.383 14.83 11.29Z"></path>', + '<path d="m14.83 11.29-4.24-4.24a1 1 0 1 0-1.42 1.41L12.71 12l-3.54 3.54a1 1 0 0 0 0 1.41 1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.24-4.24a1.002 1.002 0 0 0 0-1.42Z"/>', + 'left-caret': + '<path d="m11.29 12 3.54-3.54a1 1 0 0 0 0-1.41 1 1 0 0 0-1.42 0l-4.24 4.24a1 1 0 0 0 0 1.42L13.41 17a1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29 1 1 0 0 0 0-1.41Z"/>', + 'up-arrow': + '<path d="m17.71 11.29-5-5a1 1 0 0 0-.33-.21 1 1 0 0 0-.76 0 1 1 0 0 0-.33.21l-5 5a1 1 0 0 0 1.42 1.42L11 9.41V17a1 1 0 0 0 2 0V9.41l3.29 3.3a1 1 0 0 0 1.42 0 1 1 0 0 0 0-1.42Z"/>', + 'down-arrow': + '<path d="M17.71 11.29a1 1 0 0 0-1.42 0L13 14.59V7a1 1 0 0 0-2 0v7.59l-3.29-3.3a1 1 0 0 0-1.42 1.42l5 5a1 1 0 0 0 .33.21.94.94 0 0 0 .76 0 1 1 0 0 0 .33-.21l5-5a1 1 0 0 0 0-1.42Z"/>', 'right-arrow': - '<path d="M17.92 11.62C17.8724 11.4973 17.801 11.3851 17.71 11.29L12.71 6.29C12.6168 6.19676 12.5061 6.1228 12.3842 6.07234C12.2624 6.02188 12.1319 5.99591 12 5.99591C11.7337 5.99591 11.4783 6.1017 11.29 6.29C11.1968 6.38324 11.1228 6.49393 11.0723 6.61575C11.0219 6.73758 10.9959 6.86814 10.9959 7C10.9959 7.2663 11.1017 7.5217 11.29 7.71L14.59 11H7C6.73478 11 6.48043 11.1054 6.29289 11.2929C6.10536 11.4804 6 11.7348 6 12C6 12.2652 6.10536 12.5196 6.29289 12.7071C6.48043 12.8946 6.73478 13 7 13H14.59L11.29 16.29C11.1963 16.383 11.1219 16.4936 11.0711 16.6154C11.0203 16.7373 10.9942 16.868 10.9942 17C10.9942 17.132 11.0203 17.2627 11.0711 17.3846C11.1219 17.5064 11.1963 17.617 11.29 17.71C11.383 17.8037 11.4936 17.8781 11.6154 17.9289C11.7373 17.9797 11.868 18.0058 12 18.0058C12.132 18.0058 12.2627 17.9797 12.3846 17.9289C12.5064 17.8781 12.617 17.8037 12.71 17.71L17.71 12.71C17.801 12.6149 17.8724 12.5028 17.92 12.38C18.02 12.1365 18.02 11.8635 17.92 11.62Z" />', + '<path d="M17.92 11.62a1.001 1.001 0 0 0-.21-.33l-5-5a1.003 1.003 0 1 0-1.42 1.42l3.3 3.29H7a1 1 0 0 0 0 2h7.59l-3.3 3.29a1.002 1.002 0 0 0 .325 1.639 1 1 0 0 0 1.095-.219l5-5a1 1 0 0 0 .21-.33 1 1 0 0 0 0-.76Z"/>', 'left-arrow': - '<path d="M17 11H9.41002L12.71 7.71C12.8983 7.5217 13.0041 7.2663 13.0041 7C13.0041 6.7337 12.8983 6.47831 12.71 6.29C12.5217 6.1017 12.2663 5.99591 12 5.99591C11.7337 5.99591 11.4783 6.1017 11.29 6.29L6.29002 11.29C6.19898 11.3851 6.12761 11.4973 6.08002 11.62C5.98 11.8635 5.98 12.1365 6.08002 12.38C6.12761 12.5028 6.19898 12.6149 6.29002 12.71L11.29 17.71C11.383 17.8037 11.4936 17.8781 11.6154 17.9289C11.7373 17.9797 11.868 18.0058 12 18.0058C12.132 18.0058 12.2627 17.9797 12.3846 17.9289C12.5065 17.8781 12.6171 17.8037 12.71 17.71C12.8037 17.617 12.8781 17.5064 12.9289 17.3846C12.9797 17.2627 13.0058 17.132 13.0058 17C13.0058 16.868 12.9797 16.7373 12.9289 16.6154C12.8781 16.4936 12.8037 16.383 12.71 16.29L9.41002 13H17C17.2652 13 17.5196 12.8946 17.7071 12.7071C17.8947 12.5196 18 12.2652 18 12C18 11.7348 17.8947 11.4804 17.7071 11.2929C17.5196 11.1054 17.2652 11 17 11Z"/>', - bars: '<path d="M3 8H21C21.2652 8 21.5196 7.89464 21.7071 7.70711C21.8946 7.51957 22 7.26522 22 7C22 6.73478 21.8946 6.48043 21.7071 6.29289C21.5196 6.10536 21.2652 6 21 6H3C2.73478 6 2.48043 6.10536 2.29289 6.29289C2.10536 6.48043 2 6.73478 2 7C2 7.26522 2.10536 7.51957 2.29289 7.70711C2.48043 7.89464 2.73478 8 3 8ZM21 16H3C2.73478 16 2.48043 16.1054 2.29289 16.2929C2.10536 16.4804 2 16.7348 2 17C2 17.2652 2.10536 17.5196 2.29289 17.7071C2.48043 17.8946 2.73478 18 3 18H21C21.2652 18 21.5196 17.8946 21.7071 17.7071C21.8946 17.5196 22 17.2652 22 17C22 16.7348 21.8946 16.4804 21.7071 16.2929C21.5196 16.1054 21.2652 16 21 16ZM21 11H3C2.73478 11 2.48043 11.1054 2.29289 11.2929C2.10536 11.4804 2 11.7348 2 12C2 12.2652 2.10536 12.5196 2.29289 12.7071C2.48043 12.8946 2.73478 13 3 13H21C21.2652 13 21.5196 12.8946 21.7071 12.7071C21.8946 12.5196 22 12.2652 22 12C22 11.7348 21.8946 11.4804 21.7071 11.2929C21.5196 11.1054 21.2652 11 21 11Z" />', + '<path d="M17 11H9.41l3.3-3.29a1.004 1.004 0 1 0-1.42-1.42l-5 5a1 1 0 0 0-.21.33 1 1 0 0 0 0 .76 1 1 0 0 0 .21.33l5 5a1.002 1.002 0 0 0 1.639-.325 1 1 0 0 0-.219-1.095L9.41 13H17a1 1 0 0 0 0-2Z"/>', + bars: '<path d="M3 8h18a1 1 0 1 0 0-2H3a1 1 0 0 0 0 2Zm18 8H3a1 1 0 0 0 0 2h18a1 1 0 0 0 0-2Zm0-5H3a1 1 0 0 0 0 2h18a1 1 0 0 0 0-2Z"/>', translate: - '<path fill-rule="evenodd" clip-rule="evenodd" d="M8.51562 3C7.99605 3 7.57486 3.42119 7.57486 3.94076V5.09057H2.94076C2.42119 5.09057 2 5.51176 2 6.03133C2 6.5509 2.42119 6.97209 2.94076 6.97209H10.3025C10.1154 8.43628 9.49493 9.81581 8.51605 10.9298C7.89546 10.2235 7.41119 9.40161 7.09425 8.50519C6.92107 8.01534 6.38356 7.75864 5.89371 7.93183C5.40386 8.10501 5.14715 8.64252 5.32034 9.13237C5.71804 10.2572 6.32594 11.2885 7.10503 12.1745C5.88484 13.0016 4.43607 13.4529 2.94076 13.4529C2.42119 13.4529 2 13.8741 2 14.3936C2 14.9132 2.42119 15.3344 2.94076 15.3344C4.96251 15.3344 6.91641 14.6763 8.51606 13.4787C8.58325 13.529 8.65118 13.5784 8.71984 13.627C9.88827 14.4533 11.2259 14.995 12.6263 15.2183L11.8634 16.7441C11.8576 16.7552 11.8519 16.7665 11.8465 16.7779L10.4616 19.5478C10.2292 20.0125 10.4176 20.5776 10.8823 20.8099C11.347 21.0423 11.9121 20.8539 12.1445 20.3892L13.2782 18.1218H19.0839L20.2176 20.3892C20.45 20.8539 21.015 21.0423 21.4798 20.8099C21.9445 20.5776 22.1328 20.0125 21.9005 19.5478L20.5162 16.7792C20.5104 16.7669 20.5043 16.7548 20.498 16.7428L17.0225 9.79176C16.8631 9.47304 16.5374 9.27172 16.181 9.27172C15.8247 9.27172 15.4989 9.47304 15.3396 9.79176L13.52 13.4309C12.236 13.3317 10.9971 12.8998 9.92708 12.1745C11.2086 10.7172 12.0005 8.89713 12.1961 6.97209H14.0905C14.61 6.97209 15.0312 6.5509 15.0312 6.03133C15.0312 5.51176 14.61 5.09057 14.0905 5.09057H9.45638V3.94076C9.45638 3.42119 9.03519 3 8.51562 3ZM14.9419 14.7944C14.9357 14.8074 14.9293 14.8203 14.9226 14.833L14.2189 16.2403H18.1431L16.181 12.3161L14.9419 14.7944Z"></path>', + '<path fill-rule="evenodd" d="M8.516 3a.94.94 0 0 0-.941.94v1.15H2.94a.94.94 0 1 0 0 1.882h7.362a7.422 7.422 0 0 1-1.787 3.958 7.42 7.42 0 0 1-1.422-2.425.94.94 0 1 0-1.774.627 9.303 9.303 0 0 0 1.785 3.043 7.422 7.422 0 0 1-4.164 1.278.94.94 0 1 0 0 1.881 9.303 9.303 0 0 0 5.575-1.855 9.303 9.303 0 0 0 4.11 1.74l-.763 1.525a.968.968 0 0 0-.016.034l-1.385 2.77a.94.94 0 1 0 1.683.841l1.133-2.267h5.806l1.134 2.267a.94.94 0 0 0 1.683-.841l-1.385-2.769a.95.95 0 0 0-.018-.036l-3.476-6.951a.94.94 0 0 0-1.682 0l-1.82 3.639a7.423 7.423 0 0 1-3.593-1.256 9.303 9.303 0 0 0 2.27-5.203h1.894a.94.94 0 0 0 0-1.881H9.456V3.94A.94.94 0 0 0 8.516 3Zm6.426 11.794a1.068 1.068 0 0 1-.02.039l-.703 1.407h3.924l-1.962-3.924-1.24 2.478Z" clip-rule="evenodd"/>', pencil: '<path d="M22 7.24a1 1 0 0 0-.29-.71l-4.24-4.24a1 1 0 0 0-1.1-.22 1 1 0 0 0-.32.22l-2.83 2.83L2.29 16.05a1 1 0 0 0-.29.71V21a1 1 0 0 0 1 1h4.24a1 1 0 0 0 .76-.29l10.87-10.93L21.71 8c.1-.1.17-.2.22-.33a1 1 0 0 0 0-.24v-.14l.07-.05ZM6.83 20H4v-2.83l9.93-9.93 2.83 2.83L6.83 20ZM18.17 8.66l-2.83-2.83 1.42-1.41 2.82 2.82-1.41 1.42Z"/>', pen: '<path d="M21 12a1 1 0 0 0-1 1v6a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h6a1 1 0 1 0 0-2H5a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h14a3 3 0 0 0 3-3v-6a1 1 0 0 0-1-1Zm-15 .76V17a1 1 0 0 0 1 1h4.24a1 1 0 0 0 .71-.29l6.92-6.93L21.71 8a1 1 0 0 0 0-1.42l-4.24-4.29a1 1 0 0 0-1.42 0l-2.82 2.83-6.94 6.93a1 1 0 0 0-.29.71Zm10.76-8.35 2.83 2.83-1.42 1.42-2.83-2.83 1.42-1.42ZM8 13.17l5.93-5.93 2.83 2.83L10.83 16H8v-2.83Z"/>', @@ -23,37 +31,47 @@ export const Icons = { '<path d="m21.32 9.55-1.89-.63.89-1.78A1 1 0 0 0 20.13 6L18 3.87a1 1 0 0 0-1.15-.19l-1.78.89-.63-1.89A1 1 0 0 0 13.5 2h-3a1 1 0 0 0-.95.68l-.63 1.89-1.78-.89A1 1 0 0 0 6 3.87L3.87 6a1 1 0 0 0-.19 1.15l.89 1.78-1.89.63a1 1 0 0 0-.68.94v3a1 1 0 0 0 .68.95l1.89.63-.89 1.78A1 1 0 0 0 3.87 18L6 20.13a1 1 0 0 0 1.15.19l1.78-.89.63 1.89a1 1 0 0 0 .95.68h3a1 1 0 0 0 .95-.68l.63-1.89 1.78.89a1 1 0 0 0 1.13-.19L20.13 18a1 1 0 0 0 .19-1.15l-.89-1.78 1.89-.63a1 1 0 0 0 .68-.94v-3a1 1 0 0 0-.68-.95ZM20 12.78l-1.2.4A2 2 0 0 0 17.64 16l.57 1.14-1.1 1.1-1.11-.6a2 2 0 0 0-2.79 1.16l-.4 1.2h-1.59l-.4-1.2A2 2 0 0 0 8 17.64l-1.14.57-1.1-1.1.6-1.11a2 2 0 0 0-1.16-2.82l-1.2-.4v-1.56l1.2-.4A2 2 0 0 0 6.36 8l-.57-1.11 1.1-1.1L8 6.36a2 2 0 0 0 2.82-1.16l.4-1.2h1.56l.4 1.2A2 2 0 0 0 16 6.36l1.14-.57 1.1 1.1-.6 1.11a2 2 0 0 0 1.16 2.79l1.2.4v1.59ZM12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8Zm0 6a2 2 0 1 1 0-4 2 2 0 0 1 0 4Z"/>', external: '<path d="M19.33 10.18a1 1 0 0 1-.77 0 1 1 0 0 1-.62-.93l.01-1.83-8.2 8.2a1 1 0 0 1-1.41-1.42l8.2-8.2H14.7a1 1 0 0 1 0-2h4.25a1 1 0 0 1 1 1v4.25a1 1 0 0 1-.62.93Z"/><path d="M11 4a1 1 0 1 1 0 2H7a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1v-4a1 1 0 1 1 2 0v4a3 3 0 0 1-3 3H7a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3h4Z"/>', - moon: '<path d="M21.64 13C21.4957 12.8807 21.3207 12.8043 21.1351 12.7796C20.9494 12.7548 20.7606 12.7827 20.59 12.86C19.5326 13.3439 18.3829 13.593 17.22 13.59C15.0689 13.5874 13.006 12.7345 11.4812 11.2171C9.95632 9.69979 9.09321 7.64114 9.08001 5.49003C9.08457 4.81586 9.16848 4.14458 9.33001 3.49003C9.36429 3.31557 9.35143 3.13512 9.29277 2.96728C9.2341 2.79944 9.13175 2.65028 8.99626 2.53516C8.86076 2.42004 8.69702 2.34313 8.52191 2.31234C8.3468 2.28156 8.16665 2.29802 8.00001 2.36003C6.43234 3.06494 5.06958 4.15679 4.03977 5.53301C3.00996 6.90924 2.34689 8.52465 2.11286 10.2275C1.87883 11.9304 2.08152 13.6648 2.70188 15.2678C3.32225 16.8708 4.33993 18.2898 5.65931 19.3915C6.9787 20.4932 8.55649 21.2414 10.2445 21.5658C11.9324 21.8903 13.6752 21.7803 15.309 21.2463C16.9428 20.7122 18.414 19.7716 19.5844 18.5128C20.7548 17.254 21.5861 15.7183 22 14.05C22.0504 13.859 22.0431 13.6574 21.9791 13.4705C21.915 13.2836 21.797 13.1199 21.64 13ZM12.14 19.69C10.4618 19.6782 8.82821 19.1479 7.46301 18.1718C6.0978 17.1956 5.06768 15.8214 4.5137 14.2372C3.95971 12.6529 3.90895 10.9362 4.36835 9.32203C4.82776 7.70785 5.77487 6.27513 7.08001 5.22003V5.49003C7.08266 8.17851 8.15183 10.7561 10.0529 12.6572C11.9539 14.5582 14.5315 15.6274 17.22 15.63C17.9259 15.6326 18.63 15.5589 19.32 15.41C18.6299 16.7155 17.5965 17.8079 16.3312 18.5692C15.0659 19.3305 13.6167 19.7319 12.14 19.73V19.69Z"></path>', - sun: '<path d="M5 12C5 11.7348 4.89464 11.4804 4.70711 11.2929C4.51957 11.1054 4.26522 11 4 11H3C2.73478 11 2.48043 11.1054 2.29289 11.2929C2.10536 11.4804 2 11.7348 2 12C2 12.2652 2.10536 12.5196 2.29289 12.7071C2.48043 12.8946 2.73478 13 3 13H4C4.26522 13 4.51957 12.8946 4.70711 12.7071C4.89464 12.5196 5 12.2652 5 12ZM5.64 17L4.93 17.71C4.74375 17.8974 4.63921 18.1508 4.63921 18.415C4.63921 18.6792 4.74375 18.9326 4.93 19.12C5.11736 19.3063 5.37081 19.4108 5.635 19.4108C5.89919 19.4108 6.15264 19.3063 6.34 19.12L7.05 18.41C7.21383 18.2187 7.29943 17.9726 7.28971 17.7209C7.27999 17.4693 7.17566 17.2305 6.99756 17.0524C6.81947 16.8743 6.58073 16.77 6.32905 16.7603C6.07738 16.7506 5.8313 16.8362 5.64 17ZM12 5C12.2652 5 12.5196 4.89464 12.7071 4.70711C12.8946 4.51957 13 4.26522 13 4V3C13 2.73478 12.8946 2.48043 12.7071 2.29289C12.5196 2.10536 12.2652 2 12 2C11.7348 2 11.4804 2.10536 11.2929 2.29289C11.1054 2.48043 11 2.73478 11 3V4C11 4.26522 11.1054 4.51957 11.2929 4.70711C11.4804 4.89464 11.7348 5 12 5ZM17.66 7.34C17.9223 7.3389 18.1737 7.23474 18.36 7.05L19.07 6.34C19.1747 6.25035 19.2597 6.14004 19.3197 6.01597C19.3797 5.89191 19.4135 5.75677 19.4188 5.61905C19.4241 5.48133 19.4009 5.344 19.3506 5.21568C19.3004 5.08735 19.2241 4.9708 19.1266 4.87335C19.0292 4.77589 18.9126 4.69964 18.7843 4.64936C18.656 4.59909 18.5187 4.57588 18.3809 4.5812C18.2432 4.58652 18.1081 4.62025 17.984 4.68027C17.86 4.7403 17.7496 4.82532 17.66 4.93L17 5.64C16.8137 5.82736 16.7092 6.08081 16.7092 6.345C16.7092 6.60919 16.8137 6.86264 17 7.05C17.1763 7.22536 17.4116 7.32875 17.66 7.34ZM5.66 7.05C5.84626 7.23474 6.09766 7.3389 6.36 7.34C6.49161 7.34076 6.62207 7.31554 6.74391 7.26577C6.86574 7.21601 6.97656 7.14268 7.07 7.05C7.25625 6.86264 7.36079 6.60919 7.36079 6.345C7.36079 6.08081 7.25625 5.82736 7.07 5.64L6.36 4.93C6.26742 4.8361 6.15725 4.76136 6.03578 4.71005C5.91432 4.65873 5.78393 4.63184 5.65207 4.63091C5.52021 4.62998 5.38946 4.65503 5.26728 4.70463C5.14511 4.75424 5.0339 4.82742 4.94 4.92C4.8461 5.01258 4.77136 5.12275 4.72005 5.24422C4.66873 5.36568 4.64184 5.49607 4.64091 5.62793C4.63903 5.89423 4.74302 6.15037 4.93 6.34L5.66 7.05ZM21 11H20C19.7348 11 19.4804 11.1054 19.2929 11.2929C19.1054 11.4804 19 11.7348 19 12C19 12.2652 19.1054 12.5196 19.2929 12.7071C19.4804 12.8946 19.7348 13 20 13H21C21.2652 13 21.5196 12.8946 21.7071 12.7071C21.8946 12.5196 22 12.2652 22 12C22 11.7348 21.8946 11.4804 21.7071 11.2929C21.5196 11.1054 21.2652 11 21 11ZM18.36 17C18.17 16.8943 17.9508 16.8534 17.7355 16.8835C17.5202 16.9136 17.3205 17.0131 17.1668 17.1668C17.0131 17.3205 16.9136 17.5202 16.8835 17.7355C16.8534 17.9508 16.8943 18.17 17 18.36L17.71 19.07C17.8974 19.2563 18.1508 19.3608 18.415 19.3608C18.6792 19.3608 18.9326 19.2563 19.12 19.07C19.3063 18.8826 19.4108 18.6292 19.4108 18.365C19.4108 18.1008 19.3063 17.8474 19.12 17.66L18.36 17ZM12 6.5C10.9122 6.5 9.84883 6.82257 8.94436 7.42692C8.03989 8.03126 7.33494 8.89025 6.91866 9.89524C6.50238 10.9002 6.39346 12.0061 6.60568 13.073C6.8179 14.1399 7.34172 15.1199 8.11091 15.8891C8.8801 16.6583 9.86011 17.1821 10.927 17.3943C11.9939 17.6065 13.0998 17.4976 14.1048 17.0813C15.1098 16.6651 15.9687 15.9601 16.5731 15.0556C17.1774 14.1512 17.5 13.0878 17.5 12C17.4974 10.5421 16.917 9.14471 15.8862 8.11383C14.8553 7.08295 13.4579 6.50264 12 6.5ZM12 15.5C11.3078 15.5 10.6311 15.2947 10.0555 14.9101C9.47993 14.5256 9.03133 13.9789 8.76642 13.3394C8.50151 12.6999 8.4322 11.9961 8.56725 11.3172C8.7023 10.6383 9.03564 10.0146 9.52513 9.52513C10.0146 9.03564 10.6383 8.7023 11.3172 8.56725C11.9961 8.4322 12.6999 8.50151 13.3394 8.76642C13.9789 9.03133 14.5256 9.47993 14.9101 10.0555C15.2947 10.6311 15.5 11.3078 15.5 12C15.5 12.9283 15.1313 13.8185 14.4749 14.4749C13.8185 15.1313 12.9283 15.5 12 15.5ZM12 19C11.7348 19 11.4804 19.1054 11.2929 19.2929C11.1054 19.4804 11 19.7348 11 20V21C11 21.2652 11.1054 21.5196 11.2929 21.7071C11.4804 21.8946 11.7348 22 12 22C12.2652 22 12.5196 21.8946 12.7071 21.7071C12.8946 21.5196 13 21.2652 13 21V20C13 19.7348 12.8946 19.4804 12.7071 19.2929C12.5196 19.1054 12.2652 19 12 19Z"></path>', + download: + '<path d="M8.29 13.29a1 1 0 0 0 0 1.42l3 3a1 1 0 0 0 1.42 0l3-3a1 1 0 0 0-1.42-1.42L13 14.59V3a1 1 0 0 0-2 0v11.59l-1.29-1.3a1 1 0 0 0-1.42 0ZM18 9h-2a1 1 0 0 0 0 2h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-7a1 1 0 0 1 1-1h2a1 1 0 0 0 0-2H6a3 3 0 0 0-3 3v7a3 3 0 0 0 3 3h12a3 3 0 0 0 3-3v-7a3 3 0 0 0-3-3Z"/>', + 'cloud-download': + '<path d="M14.29 17.29 13 18.59V13a1 1 0 0 0-2 0v5.59l-1.29-1.3a1 1 0 0 0-1.42 1.42l3 3a1 1 0 0 0 .33.21.94.94 0 0 0 .76 0 1 1 0 0 0 .33-.21l3-3a1 1 0 0 0-1.42-1.42Zm4.13-11.07A7 7 0 0 0 5.06 8.11 4 4 0 0 0 6 16a1 1 0 0 0 0-2 2 2 0 0 1 0-4 1 1 0 0 0 1-1 5 5 0 0 1 9.73-1.61 1 1 0 0 0 .78.67 3 3 0 0 1 .24 5.84 1 1 0 1 0 .5 1.94 5 5 0 0 0 .17-9.62Z"/>', + moon: '<path d="M21.64 13a1 1 0 0 0-1.05-.14 8.049 8.049 0 0 1-3.37.73 8.15 8.15 0 0 1-8.14-8.1 8.59 8.59 0 0 1 .25-2A1 1 0 0 0 8 2.36a10.14 10.14 0 1 0 14 11.69 1 1 0 0 0-.36-1.05Zm-9.5 6.69A8.14 8.14 0 0 1 7.08 5.22v.27a10.15 10.15 0 0 0 10.14 10.14 9.784 9.784 0 0 0 2.1-.22 8.11 8.11 0 0 1-7.18 4.32v-.04Z"/>', + sun: '<path d="M5 12a1 1 0 0 0-1-1H3a1 1 0 0 0 0 2h1a1 1 0 0 0 1-1Zm.64 5-.71.71a1 1 0 0 0 0 1.41 1 1 0 0 0 1.41 0l.71-.71A1 1 0 0 0 5.64 17ZM12 5a1 1 0 0 0 1-1V3a1 1 0 0 0-2 0v1a1 1 0 0 0 1 1Zm5.66 2.34a1 1 0 0 0 .7-.29l.71-.71a1 1 0 1 0-1.41-1.41l-.66.71a1 1 0 0 0 0 1.41 1 1 0 0 0 .66.29Zm-12-.29a1 1 0 0 0 1.41 0 1 1 0 0 0 0-1.41l-.71-.71a1.004 1.004 0 1 0-1.43 1.41l.73.71ZM21 11h-1a1 1 0 0 0 0 2h1a1 1 0 0 0 0-2Zm-2.64 6A1 1 0 0 0 17 18.36l.71.71a1 1 0 0 0 1.41 0 1 1 0 0 0 0-1.41l-.76-.66ZM12 6.5a5.5 5.5 0 1 0 5.5 5.5A5.51 5.51 0 0 0 12 6.5Zm0 9a3.5 3.5 0 1 1 0-7 3.5 3.5 0 0 1 0 7Zm0 3.5a1 1 0 0 0-1 1v1a1 1 0 0 0 2 0v-1a1 1 0 0 0-1-1Z"/>', laptop: - '<path d="M21 14H20V7C20 6.20435 19.6839 5.44129 19.1213 4.87868C18.5587 4.31607 17.7956 4 17 4H7C6.20435 4 5.44129 4.31607 4.87868 4.87868C4.31607 5.44129 4 6.20435 4 7V14H3C2.73478 14 2.48043 14.1054 2.29289 14.2929C2.10536 14.4804 2 14.7348 2 15V17C2 17.7956 2.31607 18.5587 2.87868 19.1213C3.44129 19.6839 4.20435 20 5 20H19C19.7956 20 20.5587 19.6839 21.1213 19.1213C21.6839 18.5587 22 17.7956 22 17V15C22 14.7348 21.8946 14.4804 21.7071 14.2929C21.5196 14.1054 21.2652 14 21 14ZM6 7C6 6.73478 6.10536 6.48043 6.29289 6.29289C6.48043 6.10536 6.73478 6 7 6H17C17.2652 6 17.5196 6.10536 17.7071 6.29289C17.8946 6.48043 18 6.73478 18 7V14H6V7ZM20 17C20 17.2652 19.8946 17.5196 19.7071 17.7071C19.5196 17.8946 19.2652 18 19 18H5C4.73478 18 4.48043 17.8946 4.29289 17.7071C4.10536 17.5196 4 17.2652 4 17V16H20V17Z"></path>', + '<path d="M21 14h-1V7a3 3 0 0 0-3-3H7a3 3 0 0 0-3 3v7H3a1 1 0 0 0-1 1v2a3 3 0 0 0 3 3h14a3 3 0 0 0 3-3v-2a1 1 0 0 0-1-1ZM6 7a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v7H6V7Zm14 10a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-1h16v1Z"/>', 'open-book': - '<path d="M21.17 2.06C20.4532 1.93653 19.7274 1.87298 19 1.87C16.5184 1.86796 14.0885 2.57957 12 3.92C9.90617 2.59717 7.47667 1.90303 5.00002 1.92C4.27267 1.92298 3.54683 1.98653 2.83002 2.11C2.59523 2.15048 2.3826 2.27346 2.23044 2.45679C2.07827 2.64013 1.99656 2.87177 2.00002 3.11V15.11C1.99788 15.2569 2.02815 15.4025 2.08867 15.5364C2.1492 15.6703 2.23849 15.7893 2.3502 15.8847C2.4619 15.9802 2.59328 16.0499 2.73498 16.0888C2.87668 16.1278 3.02522 16.135 3.17002 16.11C4.60304 15.8619 6.07123 15.9031 7.48809 16.2311C8.90495 16.5591 10.2418 17.1674 11.42 18.02L11.54 18.09H11.65C11.7609 18.1362 11.8799 18.16 12 18.16C12.1202 18.16 12.2391 18.1362 12.35 18.09H12.46L12.58 18.02C13.75 17.1483 15.083 16.5203 16.5002 16.1734C17.9173 15.8264 19.3897 15.7674 20.83 16C20.9748 16.025 21.1234 16.0178 21.2651 15.9788C21.4068 15.9399 21.5381 15.8702 21.6498 15.7747C21.7616 15.6793 21.8508 15.5603 21.9114 15.4264C21.9719 15.2925 22.0022 15.1469 22 15V3C21.9896 2.77215 21.9016 2.55471 21.7507 2.38374C21.5997 2.21276 21.3948 2.09854 21.17 2.06ZM11 15.35C9.14991 14.3767 7.09054 13.8687 5.00002 13.87C4.67002 13.87 4.34002 13.87 4.00002 13.87V3.87C4.33308 3.8508 4.66697 3.8508 5.00002 3.87C7.13341 3.86764 9.22024 4.49369 11 5.67V15.35ZM20 13.91C19.66 13.91 19.33 13.91 19 13.91C16.9095 13.9087 14.8501 14.4167 13 15.39V5.67C14.7798 4.49369 16.8666 3.86764 19 3.87C19.3331 3.8508 19.667 3.8508 20 3.87V13.91ZM21.17 18.06C20.4532 17.9365 19.7274 17.873 19 17.87C16.5184 17.868 14.0885 18.5796 12 19.92C9.91154 18.5796 7.48166 17.868 5.00002 17.87C4.27267 17.873 3.54683 17.9365 2.83002 18.06C2.69985 18.0807 2.57505 18.1268 2.46279 18.1959C2.35053 18.265 2.25302 18.3555 2.17589 18.4624C2.09876 18.5693 2.04351 18.6903 2.01333 18.8186C1.98315 18.9469 1.97862 19.0799 2.00002 19.21C2.05084 19.4697 2.20251 19.6986 2.42181 19.8467C2.64111 19.9948 2.91016 20.0499 3.17002 20C4.60304 19.7519 6.07123 19.7931 7.48809 20.1211C8.90495 20.4491 10.2418 21.0574 11.42 21.91C11.5894 22.0306 11.7921 22.0954 12 22.0954C12.2079 22.0954 12.4107 22.0306 12.58 21.91C13.7582 21.0574 15.0951 20.4491 16.512 20.1211C17.9288 19.7931 19.397 19.7519 20.83 20C21.0899 20.0499 21.3589 19.9948 21.5782 19.8467C21.7975 19.6986 21.9492 19.4697 22 19.21C22.0214 19.0799 22.0169 18.9469 21.9867 18.8186C21.9565 18.6903 21.9013 18.5693 21.8242 18.4624C21.747 18.3555 21.6495 18.265 21.5373 18.1959C21.425 18.1268 21.3002 18.0807 21.17 18.06Z"></path>', + '<path d="M21.17 2.06A13.1 13.1 0 0 0 19 1.87a12.94 12.94 0 0 0-7 2.05 12.94 12.94 0 0 0-7-2 13.1 13.1 0 0 0-2.17.19 1 1 0 0 0-.83 1v12a1 1 0 0 0 1.17 1 10.9 10.9 0 0 1 8.25 1.91l.12.07h.11a.91.91 0 0 0 .7 0h.11l.12-.07A10.899 10.899 0 0 1 20.83 16 1 1 0 0 0 22 15V3a1 1 0 0 0-.83-.94ZM11 15.35a12.87 12.87 0 0 0-6-1.48H4v-10c.333-.02.667-.02 1 0a10.86 10.86 0 0 1 6 1.8v9.68Zm9-1.44h-1a12.87 12.87 0 0 0-6 1.48V5.67a10.86 10.86 0 0 1 6-1.8c.333-.02.667-.02 1 0v10.04Zm1.17 4.15a13.098 13.098 0 0 0-2.17-.19 12.94 12.94 0 0 0-7 2.05 12.94 12.94 0 0 0-7-2.05c-.727.003-1.453.066-2.17.19A1 1 0 0 0 2 19.21a1 1 0 0 0 1.17.79 10.9 10.9 0 0 1 8.25 1.91 1 1 0 0 0 1.16 0A10.9 10.9 0 0 1 20.83 20a1 1 0 0 0 1.17-.79 1 1 0 0 0-.83-1.15Z"/>', information: - '<path d="M12 11C11.7348 11 11.4804 11.1054 11.2929 11.2929C11.1054 11.4804 11 11.7348 11 12V16C11 16.2652 11.1054 16.5196 11.2929 16.7071C11.4804 16.8946 11.7348 17 12 17C12.2652 17 12.5196 16.8946 12.7071 16.7071C12.8946 16.5196 13 16.2652 13 16V12C13 11.7348 12.8946 11.4804 12.7071 11.2929C12.5196 11.1054 12.2652 11 12 11ZM12.38 7.08C12.1365 6.97998 11.8635 6.97998 11.62 7.08C11.4973 7.12759 11.3851 7.19896 11.29 7.29C11.2017 7.3872 11.1306 7.49882 11.08 7.62C11.024 7.73868 10.9966 7.86882 11 8C10.9992 8.13161 11.0245 8.26207 11.0742 8.38391C11.124 8.50574 11.1973 8.61656 11.29 8.71C11.3872 8.79833 11.4988 8.86936 11.62 8.92C11.7715 8.98224 11.936 9.00632 12.099 8.99011C12.2619 8.97391 12.4184 8.91792 12.5547 8.82707C12.691 8.73622 12.8029 8.61328 12.8805 8.46907C12.9582 8.32486 12.9992 8.16378 13 8C12.9963 7.73523 12.8927 7.48163 12.71 7.29C12.6149 7.19896 12.5028 7.12759 12.38 7.08ZM12 2C10.0222 2 8.08879 2.58649 6.4443 3.6853C4.79981 4.78412 3.51809 6.3459 2.76121 8.17317C2.00433 10.0004 1.8063 12.0111 2.19215 13.9509C2.578 15.8907 3.53041 17.6725 4.92894 19.0711C6.32746 20.4696 8.10929 21.422 10.0491 21.8079C11.9889 22.1937 13.9996 21.9957 15.8268 21.2388C17.6541 20.4819 19.2159 19.2002 20.3147 17.5557C21.4135 15.9112 22 13.9778 22 12C22 10.6868 21.7413 9.38642 21.2388 8.17317C20.7363 6.95991 19.9997 5.85752 19.0711 4.92893C18.1425 4.00035 17.0401 3.26375 15.8268 2.7612C14.6136 2.25866 13.3132 2 12 2ZM12 20C10.4178 20 8.87104 19.5308 7.55544 18.6518C6.23985 17.7727 5.21447 16.5233 4.60897 15.0615C4.00347 13.5997 3.84504 11.9911 4.15372 10.4393C4.4624 8.88743 5.22433 7.46197 6.34315 6.34315C7.46197 5.22433 8.88743 4.4624 10.4393 4.15372C11.9911 3.84504 13.5997 4.00346 15.0615 4.60896C16.5233 5.21447 17.7727 6.23984 18.6518 7.55544C19.5308 8.87103 20 10.4177 20 12C20 14.1217 19.1572 16.1566 17.6569 17.6569C16.1566 19.1571 14.1217 20 12 20Z"></path>', + '<path d="M12 11a1 1 0 0 0-1 1v4a1 1 0 0 0 2 0v-4a1 1 0 0 0-1-1Zm.38-3.92a1 1 0 0 0-.76 0 1 1 0 0 0-.33.21 1.15 1.15 0 0 0-.21.33 1 1 0 0 0 .21 1.09c.097.088.209.16.33.21A1 1 0 0 0 13 8a1.05 1.05 0 0 0-.29-.71 1 1 0 0 0-.33-.21ZM12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm0 18a8 8 0 1 1 0-16.001A8 8 0 0 1 12 20Z"/>', magnifier: - '<path d="M21.71 20.29L18 16.61C19.4401 14.8144 20.1375 12.5353 19.9488 10.2413C19.7601 7.94733 18.6997 5.81281 16.9855 4.27667C15.2714 2.74053 13.0338 1.91954 10.7329 1.9825C8.43203 2.04546 6.24272 2.98759 4.61514 4.61517C2.98756 6.24275 2.04543 8.43207 1.98247 10.7329C1.91951 13.0338 2.7405 15.2714 4.27664 16.9855C5.81278 18.6997 7.9473 19.7601 10.2413 19.9488C12.5353 20.1375 14.8144 19.4401 16.61 18L20.29 21.68C20.383 21.7738 20.4936 21.8482 20.6154 21.8989C20.7373 21.9497 20.868 21.9758 21 21.9758C21.132 21.9758 21.2627 21.9497 21.3846 21.8989C21.5064 21.8482 21.617 21.7738 21.71 21.68C21.8902 21.4936 21.991 21.2444 21.991 20.985C21.991 20.7257 21.8902 20.4765 21.71 20.29ZM11 18C9.61553 18 8.26215 17.5895 7.111 16.8203C5.95986 16.0511 5.06265 14.9579 4.53284 13.6788C4.00303 12.3997 3.8644 10.9923 4.1345 9.63439C4.4046 8.27653 5.07128 7.02925 6.05025 6.05028C7.02922 5.07131 8.2765 4.40463 9.63436 4.13453C10.9922 3.86443 12.3997 4.00306 13.6788 4.53287C14.9579 5.06268 16.0511 5.95989 16.8203 7.11103C17.5895 8.26218 18 9.61556 18 11C18 12.8565 17.2625 14.637 15.9497 15.9498C14.637 17.2625 12.8565 18 11 18Z"></path>', + '<path d="M21.71 20.29 18 16.61A9 9 0 1 0 16.61 18l3.68 3.68a.999.999 0 0 0 1.42 0 1 1 0 0 0 0-1.39ZM11 18a7 7 0 1 1 0-14 7 7 0 0 1 0 14Z"/>', 'forward-slash': - '<path d="M17 2H7C5.67392 2 4.40215 2.52678 3.46447 3.46447C2.52678 4.40215 2 5.67392 2 7V17C2 18.3261 2.52678 19.5979 3.46447 20.5355C4.40215 21.4732 5.67392 22 7 22H17C18.3261 22 19.5979 21.4732 20.5355 20.5355C21.4732 19.5979 22 18.3261 22 17V7C22 5.67392 21.4732 4.40215 20.5355 3.46447C19.5979 2.52678 18.3261 2 17 2ZM20 17C20 17.7956 19.6839 18.5587 19.1213 19.1213C18.5587 19.6839 17.7956 20 17 20H7C6.20435 20 5.44129 19.6839 4.87868 19.1213C4.31607 18.5587 4 17.7956 4 17V7C4 6.20435 4.31607 5.44129 4.87868 4.87868C5.44129 4.31607 6.20435 4 7 4H17C17.7956 4 18.5587 4.31607 19.1213 4.87868C19.6839 5.44129 20 6.20435 20 7V17Z" /><path d="M15.2929 6.70711C15.6834 6.31658 16.3166 6.31658 16.7071 6.70711C17.0976 7.09763 17.0976 7.7308 16.7071 8.12132L8.22183 16.6066C7.8313 16.9971 7.19814 16.9971 6.80761 16.6066C6.41709 16.2161 6.41709 15.5829 6.80761 15.1924L15.2929 6.70711Z" />', + '<path d="M17 2H7a5 5 0 0 0-5 5v10a5 5 0 0 0 5 5h10a5 5 0 0 0 5-5V7a5 5 0 0 0-5-5Zm3 15a3 3 0 0 1-3 3H7a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v10Z"/><path d="M15.293 6.707a1 1 0 1 1 1.414 1.414l-8.485 8.486a1 1 0 0 1-1.414-1.415l8.485-8.485Z"/>', close: - '<path d="M13.41 11.9999L19.71 5.70994C19.8983 5.52164 20.0041 5.26624 20.0041 4.99994C20.0041 4.73364 19.8983 4.47825 19.71 4.28994C19.5217 4.10164 19.2663 3.99585 19 3.99585C18.7337 3.99585 18.4783 4.10164 18.29 4.28994L12 10.5899L5.71 4.28994C5.5217 4.10164 5.2663 3.99585 5 3.99585C4.7337 3.99585 4.4783 4.10164 4.29 4.28994C4.1017 4.47825 3.99591 4.73364 3.99591 4.99994C3.99591 5.26624 4.1017 5.52164 4.29 5.70994L10.59 11.9999L4.29 18.2899C4.19627 18.3829 4.12188 18.4935 4.07111 18.6154C4.02034 18.7372 3.9942 18.8679 3.9942 18.9999C3.9942 19.132 4.02034 19.2627 4.07111 19.3845C4.12188 19.5064 4.19627 19.617 4.29 19.7099C4.38296 19.8037 4.49356 19.8781 4.61542 19.9288C4.73728 19.9796 4.86799 20.0057 5 20.0057C5.13201 20.0057 5.26272 19.9796 5.38458 19.9288C5.50644 19.8781 5.61704 19.8037 5.71 19.7099L12 13.4099L18.29 19.7099C18.383 19.8037 18.4936 19.8781 18.6154 19.9288C18.7373 19.9796 18.868 20.0057 19 20.0057C19.132 20.0057 19.2627 19.9796 19.3846 19.9288C19.5064 19.8781 19.617 19.8037 19.71 19.7099C19.8037 19.617 19.8781 19.5064 19.9289 19.3845C19.9797 19.2627 20.0058 19.132 20.0058 18.9999C20.0058 18.8679 19.9797 18.7372 19.9289 18.6154C19.8781 18.4935 19.8037 18.3829 19.71 18.2899L13.41 11.9999Z" />', + '<path d="m13.41 12 6.3-6.29a1.004 1.004 0 1 0-1.42-1.42L12 10.59l-6.29-6.3a1.004 1.004 0 0 0-1.42 1.42l6.3 6.29-6.3 6.29a1 1 0 0 0 0 1.42.998.998 0 0 0 1.42 0l6.29-6.3 6.29 6.3a.999.999 0 0 0 1.42 0 1 1 0 0 0 0-1.42L13.41 12Z"/>', error: - '<path d="M12 7C11.7348 7 11.4804 7.10536 11.2929 7.29289C11.1054 7.48043 11 7.73478 11 8V12C11 12.2652 11.1054 12.5196 11.2929 12.7071C11.4804 12.8946 11.7348 13 12 13C12.2652 13 12.5196 12.8946 12.7071 12.7071C12.8946 12.5196 13 12.2652 13 12V8C13 7.73478 12.8946 7.48043 12.7071 7.29289C12.5196 7.10536 12.2652 7 12 7ZM12 15C11.8022 15 11.6089 15.0586 11.4444 15.1685C11.28 15.2784 11.1518 15.4346 11.0761 15.6173C11.0004 15.8 10.9806 16.0011 11.0192 16.1951C11.0578 16.3891 11.153 16.5673 11.2929 16.7071C11.4327 16.847 11.6109 16.9422 11.8049 16.9808C11.9989 17.0194 12.2 16.9996 12.3827 16.9239C12.5654 16.8482 12.7216 16.72 12.8315 16.5556C12.9414 16.3911 13 16.1978 13 16C13 15.7348 12.8946 15.4804 12.7071 15.2929C12.5196 15.1054 12.2652 15 12 15ZM21.71 7.56L16.44 2.29C16.2484 2.10727 15.9948 2.00368 15.73 2H8.27C8.00523 2.00368 7.75163 2.10727 7.56 2.29L2.29 7.56C2.10727 7.75163 2.00368 8.00523 2 8.27V15.73C2.00368 15.9948 2.10727 16.2484 2.29 16.44L7.56 21.71C7.75163 21.8927 8.00523 21.9963 8.27 22H15.73C15.9948 21.9963 16.2484 21.8927 16.44 21.71L21.71 16.44C21.8927 16.2484 21.9963 15.9948 22 15.73V8.27C21.9963 8.00523 21.8927 7.75163 21.71 7.56ZM20 15.31L15.31 20H8.69L4 15.31V8.69L8.69 4H15.31L20 8.69V15.31Z"></path>', + '<path d="M12 7a1 1 0 0 0-1 1v4a1 1 0 0 0 2 0V8a1 1 0 0 0-1-1Zm0 8a1 1 0 1 0 0 2 1 1 0 0 0 0-2Zm9.71-7.44-5.27-5.27a1.05 1.05 0 0 0-.71-.29H8.27a1.05 1.05 0 0 0-.71.29L2.29 7.56a1.05 1.05 0 0 0-.29.71v7.46c.004.265.107.518.29.71l5.27 5.27c.192.183.445.286.71.29h7.46a1.05 1.05 0 0 0 .71-.29l5.27-5.27a1.05 1.05 0 0 0 .29-.71V8.27a1.05 1.05 0 0 0-.29-.71ZM20 15.31 15.31 20H8.69L4 15.31V8.69L8.69 4h6.62L20 8.69v6.62Z"/>', warning: - '<path d="M12 16C11.8022 16 11.6089 16.0587 11.4444 16.1686C11.28 16.2784 11.1518 16.4346 11.0761 16.6173C11.0004 16.8001 10.9806 17.0011 11.0192 17.1951C11.0578 17.3891 11.153 17.5673 11.2929 17.7071C11.4327 17.847 11.6109 17.9422 11.8049 17.9808C11.9989 18.0194 12.2 17.9996 12.3827 17.9239C12.5654 17.8482 12.7216 17.72 12.8315 17.5556C12.9413 17.3911 13 17.1978 13 17C13 16.7348 12.8946 16.4805 12.7071 16.2929C12.5196 16.1054 12.2652 16 12 16ZM22.67 17.47L14.62 3.47003C14.3598 3.00354 13.9798 2.61498 13.5192 2.3445C13.0586 2.07401 12.5341 1.9314 12 1.9314C11.4659 1.9314 10.9414 2.07401 10.4808 2.3445C10.0202 2.61498 9.64019 3.00354 9.38 3.47003L1.38 17.47C1.11079 17.924 0.966141 18.441 0.960643 18.9688C0.955144 19.4966 1.089 20.0166 1.34868 20.4761C1.60837 20.9356 1.9847 21.3185 2.43968 21.5861C2.89466 21.8536 3.41218 21.9964 3.94 22H20.06C20.5921 22.0053 21.1159 21.8689 21.5779 21.6049C22.0399 21.341 22.4234 20.9589 22.689 20.4978C22.9546 20.0368 23.0928 19.5134 23.0895 18.9814C23.0862 18.4493 22.9414 17.9277 22.67 17.47ZM20.94 19.47C20.8523 19.626 20.7245 19.7556 20.5697 19.8453C20.4149 19.935 20.2389 19.9815 20.06 19.98H3.94C3.76111 19.9815 3.5851 19.935 3.43032 19.8453C3.27553 19.7556 3.14765 19.626 3.06 19.47C2.97223 19.318 2.92602 19.1456 2.92602 18.97C2.92602 18.7945 2.97223 18.622 3.06 18.47L11.06 4.47003C11.1439 4.30623 11.2714 4.16876 11.4284 4.07277C11.5855 3.97678 11.766 3.92599 11.95 3.92599C12.134 3.92599 12.3145 3.97678 12.4716 4.07277C12.6286 4.16876 12.7561 4.30623 12.84 4.47003L20.89 18.47C20.9892 18.6199 21.0462 18.7937 21.055 18.9732C21.0638 19.1527 21.0241 19.3312 20.94 19.49V19.47ZM12 8.00003C11.7348 8.00003 11.4804 8.10538 11.2929 8.29292C11.1054 8.48046 11 8.73481 11 9.00003V13C11 13.2652 11.1054 13.5196 11.2929 13.7071C11.4804 13.8947 11.7348 14 12 14C12.2652 14 12.5196 13.8947 12.7071 13.7071C12.8946 13.5196 13 13.2652 13 13V9.00003C13 8.73481 12.8946 8.48046 12.7071 8.29292C12.5196 8.10538 12.2652 8.00003 12 8.00003Z"></path>', + '<path d="M12 16a1 1 0 1 0 0 2 1 1 0 0 0 0-2Zm10.67 1.47-8.05-14a3 3 0 0 0-5.24 0l-8 14A3 3 0 0 0 3.94 22h16.12a3 3 0 0 0 2.61-4.53Zm-1.73 2a1 1 0 0 1-.88.51H3.94a1 1 0 0 1-.88-.51 1 1 0 0 1 0-1l8-14a1 1 0 0 1 1.78 0l8.05 14a1 1 0 0 1 .05 1.02v-.02ZM12 8a1 1 0 0 0-1 1v4a1 1 0 0 0 2 0V9a1 1 0 0 0-1-1Z"/>', 'approve-check-circle': - '<path d="M14.72 8.79L10.43 13.09L8.78 11.44C8.69036 11.3353 8.58004 11.2503 8.45597 11.1903C8.33191 11.1303 8.19678 11.0965 8.05906 11.0912C7.92134 11.0859 7.78401 11.1091 7.65568 11.1594C7.52736 11.2096 7.41081 11.2859 7.31335 11.3833C7.2159 11.4808 7.13964 11.5974 7.08937 11.7257C7.03909 11.854 7.01589 11.9913 7.02121 12.1291C7.02653 12.2668 7.06026 12.4019 7.12028 12.526C7.1803 12.65 7.26532 12.7604 7.37 12.85L9.72 15.21C9.81344 15.3027 9.92426 15.376 10.0461 15.4258C10.1679 15.4755 10.2984 15.5008 10.43 15.5C10.6923 15.4989 10.9437 15.3947 11.13 15.21L16.13 10.21C16.2237 10.117 16.2981 10.0064 16.3489 9.88458C16.3997 9.76272 16.4258 9.63201 16.4258 9.5C16.4258 9.36799 16.3997 9.23728 16.3489 9.11542C16.2981 8.99356 16.2237 8.88296 16.13 8.79C15.9426 8.60375 15.6892 8.49921 15.425 8.49921C15.1608 8.49921 14.9074 8.60375 14.72 8.79ZM12 2C10.0222 2 8.08879 2.58649 6.4443 3.6853C4.79981 4.78412 3.51809 6.3459 2.76121 8.17317C2.00433 10.0004 1.8063 12.0111 2.19215 13.9509C2.578 15.8907 3.53041 17.6725 4.92894 19.0711C6.32746 20.4696 8.10929 21.422 10.0491 21.8079C11.9889 22.1937 13.9996 21.9957 15.8268 21.2388C17.6541 20.4819 19.2159 19.2002 20.3147 17.5557C21.4135 15.9112 22 13.9778 22 12C22 10.6868 21.7413 9.38642 21.2388 8.17317C20.7363 6.95991 19.9997 5.85752 19.0711 4.92893C18.1425 4.00035 17.0401 3.26375 15.8268 2.7612C14.6136 2.25866 13.3132 2 12 2V2ZM12 20C10.4178 20 8.87104 19.5308 7.55544 18.6518C6.23985 17.7727 5.21447 16.5233 4.60897 15.0615C4.00347 13.5997 3.84504 11.9911 4.15372 10.4393C4.4624 8.88743 5.22433 7.46197 6.34315 6.34315C7.46197 5.22433 8.88743 4.4624 10.4393 4.15372C11.9911 3.84504 13.5997 4.00346 15.0615 4.60896C16.5233 5.21447 17.7727 6.23984 18.6518 7.55544C19.5308 8.87103 20 10.4177 20 12C20 14.1217 19.1572 16.1566 17.6569 17.6569C16.1566 19.1571 14.1217 20 12 20V20Z"></path>', + '<path d="m14.72 8.79-4.29 4.3-1.65-1.65a1 1 0 1 0-1.41 1.41l2.35 2.36a1 1 0 0 0 1.41 0l5-5a1.002 1.002 0 1 0-1.41-1.42ZM12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm0 18a8 8 0 1 1 0-16.001A8 8 0 0 1 12 20Z"/>', 'approve-check': - '<path d="M18.71 7.20998C18.617 7.11625 18.5064 7.04186 18.3846 6.99109C18.2627 6.94032 18.132 6.91418 18 6.91418C17.868 6.91418 17.7373 6.94032 17.6154 6.99109C17.4936 7.04186 17.383 7.11625 17.29 7.20998L9.84001 14.67L6.71001 11.53C6.61349 11.4367 6.49955 11.3634 6.37469 11.3142C6.24984 11.265 6.11651 11.2409 5.98233 11.2432C5.84815 11.2455 5.71574 11.2743 5.59266 11.3278C5.46959 11.3812 5.35825 11.4585 5.26501 11.555C5.17177 11.6515 5.09846 11.7654 5.04925 11.8903C5.00005 12.0152 4.97592 12.1485 4.97824 12.2827C4.98056 12.4168 5.00929 12.5493 5.06278 12.6723C5.11628 12.7954 5.19349 12.9067 5.29001 13L9.13001 16.84C9.22297 16.9337 9.33358 17.0081 9.45543 17.0589C9.57729 17.1096 9.708 17.1358 9.84001 17.1358C9.97202 17.1358 10.1027 17.1096 10.2246 17.0589C10.3464 17.0081 10.457 16.9337 10.55 16.84L18.71 8.67998C18.8115 8.58634 18.8925 8.47269 18.9479 8.34619C19.0033 8.21969 19.0319 8.08308 19.0319 7.94498C19.0319 7.80688 19.0033 7.67028 18.9479 7.54378C18.8925 7.41728 18.8115 7.30363 18.71 7.20998Z"></path>', + '<path d="M18.71 7.21a1 1 0 0 0-1.42 0l-7.45 7.46-3.13-3.14A1.02 1.02 0 1 0 5.29 13l3.84 3.84a1.001 1.001 0 0 0 1.42 0l8.16-8.16a1 1 0 0 0 0-1.47Z"/>', rocket: - '<path fill-rule="evenodd" clip-rule="evenodd" d="M1.43909 8.85483L1.44039 8.85354L4.96668 5.33815C5.30653 4.99386 5.7685 4.79662 6.2524 4.78972L6.26553 4.78963L12.9014 4.78962L13.8479 3.84308C16.9187 0.772319 20.0546 0.770617 21.4678 0.975145C21.8617 1.02914 22.2271 1.21053 22.5083 1.4917C22.7894 1.77284 22.9708 2.13821 23.0248 2.53199C23.2294 3.94517 23.2278 7.08119 20.1569 10.1521L19.2107 11.0983V17.7338L19.2106 17.7469C19.2037 18.2308 19.0067 18.6933 18.6624 19.0331L15.1456 22.5608C14.9095 22.7966 14.6137 22.964 14.29 23.0449C13.9663 23.1259 13.6267 23.1174 13.3074 23.0204C12.9881 22.9235 12.7011 22.7417 12.4771 22.4944C12.2533 22.2473 12.1006 21.9441 12.0355 21.6171L11.1783 17.3417L6.65869 12.822L4.34847 12.3589L2.38351 11.965C2.05664 11.8998 1.75272 11.747 1.50564 11.5232C1.25835 11.2992 1.07653 11.0122 0.979561 10.6929C0.882595 10.3736 0.874125 10.034 0.955057 9.7103C1.03599 9.38659 1.20328 9.09092 1.43909 8.85483ZM6.8186 10.8724L2.94619 10.096L6.32006 6.73268H10.9583L6.8186 10.8724ZM15.2219 5.21703C17.681 2.75787 20.0783 2.75376 21.1124 2.8876C21.2462 3.92172 21.2421 6.31895 18.783 8.77812L12.0728 15.4883L8.51172 11.9272L15.2219 5.21703ZM13.9042 21.0538L13.1279 17.1811L17.2676 13.0414V17.68L13.9042 21.0538Z"></path><path d="M9.31827 18.3446C9.45046 17.8529 9.17864 17.3369 8.68945 17.1724C8.56178 17.1294 8.43145 17.1145 8.30512 17.1243C8.10513 17.1398 7.91519 17.2172 7.76181 17.3434C7.62613 17.455 7.51905 17.6048 7.45893 17.7835C6.97634 19.2186 5.77062 19.9878 4.52406 20.4029C4.08525 20.549 3.6605 20.644 3.29471 20.7053C3.35607 20.3395 3.45098 19.9148 3.59711 19.476C4.01221 18.2294 4.78141 17.0237 6.21648 16.5411C6.39528 16.481 6.54504 16.3739 6.65665 16.2382C6.85126 16.0016 6.92988 15.678 6.84417 15.3647C6.83922 15.3466 6.83373 15.3286 6.82767 15.3106C6.74106 15.053 6.55701 14.8557 6.33037 14.7459C6.10949 14.6389 5.84816 14.615 5.59715 14.6994C5.47743 14.7397 5.36103 14.7831 5.24786 14.8294C3.22626 15.6569 2.2347 17.4173 1.75357 18.8621C1.49662 19.6337 1.36993 20.3554 1.30679 20.8818C1.27505 21.1464 1.25893 21.3654 1.25072 21.5213C1.24662 21.5993 1.24448 21.6618 1.24337 21.7066L1.243 21.7226L1.24235 21.7605L1.2422 21.7771L1.24217 21.7827L1.24217 21.7856C1.24217 22.3221 1.67703 22.7579 2.2137 22.7579L2.2155 22.7579L2.22337 22.7578L2.23956 22.7577C2.25293 22.7575 2.27096 22.7572 2.29338 22.7567C2.33821 22.7555 2.40073 22.7534 2.47876 22.7493C2.63466 22.7411 2.85361 22.725 3.11822 22.6932C3.64462 22.6301 4.36636 22.5034 5.13797 22.2464C6.58274 21.7653 8.3431 20.7738 9.17063 18.7522C9.21696 18.639 9.26037 18.5226 9.30064 18.4029C9.30716 18.3835 9.31304 18.364 9.31827 18.3446Z"></path>', + '<path fill-rule="evenodd" d="M1.44 8.855v-.001l3.527-3.516c.34-.344.802-.541 1.285-.548h6.649l.947-.947c3.07-3.07 6.207-3.072 7.62-2.868a1.821 1.821 0 0 1 1.557 1.557c.204 1.413.203 4.55-2.868 7.62l-.946.946v6.649a1.845 1.845 0 0 1-.549 1.286l-3.516 3.528a1.844 1.844 0 0 1-3.11-.944l-.858-4.275-4.52-4.52-2.31-.463-1.964-.394A1.847 1.847 0 0 1 .98 10.693a1.843 1.843 0 0 1 .46-1.838Zm5.379 2.017-3.873-.776L6.32 6.733h4.638l-4.14 4.14Zm8.403-5.655c2.459-2.46 4.856-2.463 5.89-2.33.134 1.035.13 3.432-2.329 5.891l-6.71 6.71-3.561-3.56 6.71-6.711Zm-1.318 15.837-.776-3.873 4.14-4.14v4.639l-3.364 3.374Z" clip-rule="evenodd"/><path d="M9.318 18.345a.972.972 0 0 0-1.86-.561c-.482 1.435-1.687 2.204-2.934 2.619a8.22 8.22 0 0 1-1.23.302c.062-.365.157-.79.303-1.229.415-1.247 1.184-2.452 2.62-2.935a.971.971 0 1 0-.62-1.842c-.12.04-.236.084-.35.13-2.02.828-3.012 2.588-3.493 4.033a10.383 10.383 0 0 0-.51 2.845l-.001.016v.063c0 .536.434.972.97.972H2.24a7.21 7.21 0 0 0 .878-.065c.527-.063 1.248-.19 2.02-.447 1.445-.48 3.205-1.472 4.033-3.494a5.828 5.828 0 0 0 .147-.407Z"/>', star: '<path d="M22 9.67a1 1 0 0 0-.86-.67l-5.69-.83L12.9 3a1 1 0 0 0-1.8 0L8.55 8.16 2.86 9a1 1 0 0 0-.81.68 1 1 0 0 0 .25 1l4.13 4-1 5.68a1 1 0 0 0 1.45 1.07L12 18.76l5.1 2.68c.14.08.3.12.46.12a1 1 0 0 0 .99-1.19l-1-5.68 4.13-4A1 1 0 0 0 22 9.67Zm-6.15 4a1 1 0 0 0-.29.89l.72 4.19-3.76-2a1 1 0 0 0-.94 0l-3.76 2 .72-4.19a1 1 0 0 0-.29-.89l-3-3 4.21-.61a1 1 0 0 0 .76-.55L12 5.7l1.88 3.82a1 1 0 0 0 .76.55l4.21.61-3 2.99Z"/>', puzzle: '<path d="M17 22H5a3 3 0 0 1-3-3V9a3 3 0 0 1 3-3h1a4 4 0 0 1 7.3-2.18c.448.64.692 1.4.7 2.18h3a1 1 0 0 1 1 1v3a4 4 0 0 1 2.18 7.3A3.86 3.86 0 0 1 18 18v3a1 1 0 0 1-1 1ZM5 8a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h11v-3.18a1 1 0 0 1 1.33-.95 1.77 1.77 0 0 0 1.74-.23 2 2 0 0 0 .93-1.37 2 2 0 0 0-.48-1.59 1.89 1.89 0 0 0-2.17-.55 1 1 0 0 1-1.33-.95V8h-3.2a1 1 0 0 1-1-1.33 1.77 1.77 0 0 0-.23-1.74 1.939 1.939 0 0 0-3-.43A2 2 0 0 0 8 6c.002.23.046.456.13.67A1 1 0 0 1 7.18 8H5Z"/>', 'list-format': - '<path d="M3.71 16.29C3.6149 16.199 3.50276 16.1276 3.38 16.08C3.13654 15.98 2.86346 15.98 2.62 16.08C2.49725 16.1276 2.38511 16.199 2.29 16.29C2.19896 16.3851 2.1276 16.4972 2.08 16.62C2.00342 16.8021 1.9825 17.0028 2.01988 17.1968C2.05725 17.3908 2.15125 17.5694 2.29 17.71C2.3872 17.7983 2.49882 17.8694 2.62 17.92C2.7397 17.9729 2.86913 18.0002 3 18.0002C3.13087 18.0002 3.2603 17.9729 3.38 17.92C3.50119 17.8694 3.6128 17.7983 3.71 17.71C3.84876 17.5694 3.94276 17.3908 3.98013 17.1968C4.01751 17.0028 3.99658 16.8021 3.92 16.62C3.87241 16.4972 3.80104 16.3851 3.71 16.29ZM7 8H21C21.2652 8 21.5196 7.89464 21.7071 7.70711C21.8946 7.51957 22 7.26522 22 7C22 6.73478 21.8946 6.48043 21.7071 6.29289C21.5196 6.10536 21.2652 6 21 6H7C6.73479 6 6.48043 6.10536 6.2929 6.29289C6.10536 6.48043 6 6.73478 6 7C6 7.26522 6.10536 7.51957 6.2929 7.70711C6.48043 7.89464 6.73479 8 7 8ZM3.71 11.29C3.56938 11.1512 3.39081 11.0572 3.19682 11.0199C3.00283 10.9825 2.80211 11.0034 2.62 11.08C2.49882 11.1306 2.3872 11.2017 2.29 11.29C2.19896 11.3851 2.1276 11.4972 2.08 11.62C2.0271 11.7397 1.99977 11.8691 1.99977 12C1.99977 12.1309 2.0271 12.2603 2.08 12.38C2.13065 12.5012 2.20167 12.6128 2.29 12.71C2.3872 12.7983 2.49882 12.8694 2.62 12.92C2.7397 12.9729 2.86913 13.0002 3 13.0002C3.13087 13.0002 3.2603 12.9729 3.38 12.92C3.50119 12.8694 3.6128 12.7983 3.71 12.71C3.79833 12.6128 3.86936 12.5012 3.92 12.38C3.97291 12.2603 4.00024 12.1309 4.00024 12C4.00024 11.8691 3.97291 11.7397 3.92 11.62C3.87241 11.4972 3.80104 11.3851 3.71 11.29ZM21 11H7C6.73479 11 6.48043 11.1054 6.2929 11.2929C6.10536 11.4804 6 11.7348 6 12C6 12.2652 6.10536 12.5196 6.2929 12.7071C6.48043 12.8946 6.73479 13 7 13H21C21.2652 13 21.5196 12.8946 21.7071 12.7071C21.8946 12.5196 22 12.2652 22 12C22 11.7348 21.8946 11.4804 21.7071 11.2929C21.5196 11.1054 21.2652 11 21 11ZM3.71 6.29C3.6149 6.19896 3.50276 6.12759 3.38 6.08C3.19789 6.00342 2.99718 5.9825 2.80319 6.01987C2.6092 6.05725 2.43063 6.15124 2.29 6.29C2.20167 6.3872 2.13065 6.49882 2.08 6.62C2.0271 6.7397 1.99977 6.86913 1.99977 7C1.99977 7.13087 2.0271 7.2603 2.08 7.38C2.13065 7.50119 2.20167 7.6128 2.29 7.71C2.3872 7.79833 2.49882 7.86936 2.62 7.92C2.80211 7.99658 3.00283 8.0175 3.19682 7.98013C3.39081 7.94275 3.56938 7.84876 3.71 7.71C3.79833 7.6128 3.86936 7.50119 3.92 7.38C3.97291 7.2603 4.00024 7.13087 4.00024 7C4.00024 6.86913 3.97291 6.7397 3.92 6.62C3.86936 6.49882 3.79833 6.3872 3.71 6.29ZM21 16H7C6.73479 16 6.48043 16.1054 6.2929 16.2929C6.10536 16.4804 6 16.7348 6 17C6 17.2652 6.10536 17.5196 6.2929 17.7071C6.48043 17.8946 6.73479 18 7 18H21C21.2652 18 21.5196 17.8946 21.7071 17.7071C21.8946 17.5196 22 17.2652 22 17C22 16.7348 21.8946 16.4804 21.7071 16.2929C21.5196 16.1054 21.2652 16 21 16Z"></path>', + '<path d="M3.71 16.29a1 1 0 0 0-.33-.21 1 1 0 0 0-.76 0 1 1 0 0 0-.33.21 1 1 0 0 0-.21.33 1 1 0 0 0 .21 1.09c.097.088.209.16.33.21a.94.94 0 0 0 .76 0 1.15 1.15 0 0 0 .33-.21 1 1 0 0 0 .21-1.09 1 1 0 0 0-.21-.33ZM7 8h14a1 1 0 1 0 0-2H7a1 1 0 0 0 0 2Zm-3.29 3.29a1 1 0 0 0-1.09-.21 1.15 1.15 0 0 0-.33.21 1 1 0 0 0-.21.33.94.94 0 0 0 0 .76c.05.121.122.233.21.33.097.088.209.16.33.21a.94.94 0 0 0 .76 0 1.15 1.15 0 0 0 .33-.21 1.15 1.15 0 0 0 .21-.33.94.94 0 0 0 0-.76 1 1 0 0 0-.21-.33ZM21 11H7a1 1 0 0 0 0 2h14a1 1 0 0 0 0-2ZM3.71 6.29a1 1 0 0 0-.33-.21 1 1 0 0 0-1.09.21 1.15 1.15 0 0 0-.21.33.94.94 0 0 0 0 .76c.05.121.122.233.21.33.097.088.209.16.33.21a1 1 0 0 0 1.09-.21 1.15 1.15 0 0 0 .21-.33.94.94 0 0 0 0-.76 1.15 1.15 0 0 0-.21-.33ZM21 16H7a1 1 0 0 0 0 2h14a1 1 0 0 0 0-2Z"/>', random: '<path d="M8.7 10a1 1 0 0 0 1.41 0 1 1 0 0 0 0-1.41l-6.27-6.3a1 1 0 0 0-1.42 1.42ZM21 14a1 1 0 0 0-1 1v3.59L15.44 14A1 1 0 0 0 14 15.44L18.59 20H15a1 1 0 0 0 0 2h6a1 1 0 0 0 .38-.08 1 1 0 0 0 .54-.54A1 1 0 0 0 22 21v-6a1 1 0 0 0-1-1Zm.92-11.38a1 1 0 0 0-.54-.54A1 1 0 0 0 21 2h-6a1 1 0 0 0 0 2h3.59L2.29 20.29a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0L20 5.41V9a1 1 0 0 0 2 0V3a1 1 0 0 0-.08-.38Z"/>', + comment: + '<path d="M12 2A10 10 0 0 0 2 12a9.9 9.9 0 0 0 2.3 6.3l-2 2a1 1 0 0 0-.3 1.1 1 1 0 0 0 1 .6h9a10 10 0 0 0 0-20m0 18H5.4l1-1a1 1 0 0 0 0-1.3A8 8 0 1 1 12 20"/>', + 'comment-alt': + '<path d="M19 2H5a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h11.6l3.7 3.7a1 1 0 0 0 .7.3.8.8 0 0 0 .4 0 1 1 0 0 0 .6-1V5a3 3 0 0 0-3-3m1 16.6-2.3-2.3a1 1 0 0 0-.7-.3H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1Z"/>', + heart: + '<path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"/>', github: '<path d="M12 .3a12 12 0 0 0-3.8 23.38c.6.12.83-.26.83-.57L9 21.07c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.08-.74.09-.73.09-.73 1.2.09 1.83 1.24 1.83 1.24 1.08 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.64 1.66.24 2.88.12 3.18a4.65 4.65 0 0 1 1.23 3.22c0 4.61-2.8 5.63-5.48 5.92.42.36.81 1.1.81 2.22l-.01 3.29c0 .31.2.69.82.57A12 12 0 0 0 12 .3Z"/>', gitlab: @@ -62,12 +80,16 @@ export const Icons = { '<path d="M1 1.5a.8.8 0 0 0-.7.9l3.2 19.3c0 .5.5.8 1 .8h15.2c.4 0 .7-.2.8-.6l3.2-19.5a.7.7 0 0 0-.8-.9H1zm13.4 14H9.6l-1.3-7h7.3l-1.2 7z"/>', codePen: '<path d="M23.5 7.5 12.5.2a1 1 0 0 0-1 0L.4 7.5a1 1 0 0 0-.5.8v7.4c0 .3.2.6.5.8l11 7.3c.3.3.7.3 1 0l11-7.3c.3-.2.5-.5.5-.8V8.3a1 1 0 0 0-.5-.8zM13 3l8.1 5.3-3.6 2.5-4.5-3V3zm-2 0v4.8l-4.5 3-3.6-2.5 8-5.3zm-9 7.3L4.7 12l-2.5 1.7v-3.4zM11 21l-8.1-5.3 3.6-2.5 4.5 3V21zm1-6.6L8.4 12 12 9.6l3.6 2.4-3.6 2.4zm1 6.6v-4.8l4.5-3 3.6 2.5-8 5.3zm9-7.3L19.3 12l2.5-1.7v3.4z"/>', + farcaster: + '<path d="M 4.572 1.25 h 14.59 v 20.746 h -2.142 v -9.503 h -0.021 a 5.154 5.154 0 0 0 -10.264 0 h -0.021 v 9.503 H 4.571 z"/><path d="m 0.69 4.195 0.87 2.945 h 0.737 v 11.912 a 0.669 0.669 0 0 0 -0.669 0.669 v 0.803 h -0.134 a 0.669 0.669 0 0 0 -0.669 0.669 v 0.803 h 7.495 v -0.803 a 0.669 0.669 0 0 0 -0.669 -0.669 h -0.134 v -0.803 A 0.669 0.669 0 0 0 6.847 19.052 h -0.803 V 4.195 z M 17.153 19.052 a 0.669 0.669 0 0 0 -0.669 0.669 v 0.803 h -0.134 a 0.669 0.669 0 0 0 -0.669 0.669 v 0.803 h 7.495 v -0.803 a 0.669 0.669 0 0 0 -0.669 -0.669 h -0.134 v -0.803 a 0.669 0.669 0 0 0 -0.669 -0.669 V 7.14 h 0.737 l 0.87 -2.945 h -5.354 v 14.857 z"/>', discord: '<path d="M20.32 4.37a19.8 19.8 0 0 0-4.93-1.51 13.78 13.78 0 0 0-.64 1.28 18.27 18.27 0 0 0-5.5 0 12.64 12.64 0 0 0-.64-1.28h-.05A19.74 19.74 0 0 0 3.64 4.4 20.26 20.26 0 0 0 .11 18.09l.02.02a19.9 19.9 0 0 0 6.04 3.03l.04-.02a14.24 14.24 0 0 0 1.23-2.03.08.08 0 0 0-.05-.07 13.1 13.1 0 0 1-1.9-.92.08.08 0 0 1 .02-.1 10.2 10.2 0 0 0 .41-.31h.04a14.2 14.2 0 0 0 12.1 0l.04.01a9.63 9.63 0 0 0 .4.32.08.08 0 0 1-.03.1 12.29 12.29 0 0 1-1.9.91.08.08 0 0 0-.02.1 15.97 15.97 0 0 0 1.27 2.01h.04a19.84 19.84 0 0 0 6.03-3.05v-.03a20.12 20.12 0 0 0-3.57-13.69ZM8.02 15.33c-1.18 0-2.16-1.08-2.16-2.42 0-1.33.96-2.42 2.16-2.42 1.21 0 2.18 1.1 2.16 2.42 0 1.34-.96 2.42-2.16 2.42Zm7.97 0c-1.18 0-2.15-1.08-2.15-2.42 0-1.33.95-2.42 2.15-2.42 1.22 0 2.18 1.1 2.16 2.42 0 1.34-.94 2.42-2.16 2.42Z"/>', gitter: '<path d="M6.11 15.12H3.75V0h2.36v15.12zm4.71-11.55H8.46V24h2.36V3.57zm4.72 0h-2.36V24h2.36V3.57zm4.71 0h-2.36v11.57h2.36V3.56z"/>', twitter: '<path d="M24 4.4a10 10 0 0 1-2.83.78 5.05 5.05 0 0 0 2.17-2.79 9.7 9.7 0 0 1-3.13 1.23 4.89 4.89 0 0 0-5.94-1.03 5 5 0 0 0-2.17 2.38 5.15 5.15 0 0 0-.3 3.25c-1.95-.1-3.86-.63-5.61-1.53a14.04 14.04 0 0 1-4.52-3.74 5.2 5.2 0 0 0-.09 4.91c.39.74.94 1.35 1.61 1.82a4.77 4.77 0 0 1-2.23-.63v.06c0 1.16.4 2.29 1.12 3.18a4.9 4.9 0 0 0 2.84 1.74c-.73.22-1.5.26-2.24.12a4.89 4.89 0 0 0 4.59 3.49A9.78 9.78 0 0 1 0 19.73 13.65 13.65 0 0 0 7.55 22a13.63 13.63 0 0 0 9.96-4.16A14.26 14.26 0 0 0 21.6 7.65V7c.94-.72 1.75-1.6 2.4-2.6Z"/>', + 'x.com': + '<path d="M 18.242188 2.25 L 21.554688 2.25 L 14.324219 10.507812 L 22.828125 21.75 L 16.171875 21.75 L 10.953125 14.933594 L 4.992188 21.75 L 1.679688 21.75 L 9.40625 12.914062 L 1.257812 2.25 L 8.082031 2.25 L 12.792969 8.480469 Z M 17.082031 19.773438 L 18.914062 19.773438 L 7.082031 4.125 L 5.113281 4.125 Z M 17.082031 19.773438 "/>', mastodon: '<path d="M16.45 17.77c2.77-.33 5.18-2.03 5.49-3.58.47-2.45.44-5.97.44-5.97 0-4.77-3.15-6.17-3.15-6.17-1.58-.72-4.3-1.03-7.13-1.05h-.07c-2.83.02-5.55.33-7.13 1.05 0 0-3.14 1.4-3.14 6.17v.91c-.01.88-.02 1.86 0 2.88.12 4.67.87 9.27 5.2 10.4 2 .53 3.72.64 5.1.57 2.51-.14 3.92-.9 3.92-.9l-.08-1.8s-1.8.56-3.8.5c-2-.08-4.1-.22-4.43-2.66a4.97 4.97 0 0 1-.04-.68s1.96.48 4.44.59c1.51.07 2.94-.09 4.38-.26Zm2.22-3.4h-2.3v-5.6c0-1.19-.5-1.79-1.5-1.79-1.1 0-1.66.71-1.66 2.12v3.07h-2.3V9.1c0-1.4-.55-2.12-1.65-2.12-1 0-1.5.6-1.5 1.78v5.61h-2.3V8.6c0-1.18.3-2.12.9-2.81a3.17 3.17 0 0 1 2.47-1.05c1.18 0 2.07.45 2.66 1.35l.57.96.58-.96a2.97 2.97 0 0 1 2.66-1.35c1.01 0 1.83.36 2.46 1.05.6.7.9 1.63.9 2.81v5.78Z"/>', codeberg: @@ -80,10 +102,109 @@ export const Icons = { '<path d="M20.47 2H3.53a1.45 1.45 0 0 0-1.47 1.43v17.14A1.45 1.45 0 0 0 3.53 22h16.94a1.45 1.45 0 0 0 1.47-1.43V3.43A1.45 1.45 0 0 0 20.47 2ZM8.09 18.74h-3v-9h3v9ZM6.59 8.48a1.56 1.56 0 0 1 0-3.12 1.57 1.57 0 1 1 0 3.12Zm12.32 10.26h-3v-4.83c0-1.21-.43-2-1.52-2A1.65 1.65 0 0 0 12.85 13a2 2 0 0 0-.1.73v5h-3v-9h3V11a3 3 0 0 1 2.71-1.5c2 0 3.45 1.29 3.45 4.06v5.18Z"/>', twitch: '<path d="M2.5 1 1 4.8v15.4h5.5V23h3.1l3-2.8H17l6-5.7V1H2.6ZM21 13.5l-3.4 3.3H12l-3 2.8v-2.8H4.5V3H21v10.5Zm-3.4-6.8v5.8h-2V6.7h2Zm-5.5 0v5.8h-2V6.7h2Z"/>', + azureDevOps: + '<path d="M17,4v9.74l-4,3.28-6.2-2.26V17L3.29,12.41l10.23.8V4.44Zm-3.41.49L7.85,1V3.29L2.58,4.84,1,6.87v4.61l2.26,1V6.57Z"/>', microsoftTeams: '<path d="M13.78 7.2a3.63 3.63 0 1 0-4.3-3.68h1.78a2.52 2.52 0 0 1 2.52 2.53V7.2zM7.34 18.8h3.92a2.52 2.52 0 0 0 2.52-2.52V8.37h4.17c.58.01 1.04.5 1.03 1.07v6.45a6.3 6.3 0 0 1-6.14 6.43 6.3 6.3 0 0 1-5.5-3.52zm16.1-14.06a2.51 2.51 0 1 1-5.02 0 2.51 2.51 0 0 1 5.02 0zm-3.36 14.24h-.17c.4-1 .59-2.05.57-3.11V9.46c0-.38-.07-.75-.23-1.09h2.69c.58 0 1.06.48 1.06 1.06v5.65a3.9 3.9 0 0 1-3.9 3.9h-.02z"/><path d="M1.02 5.02h10.24c.56 0 1.02.46 1.02 1.03v10.23a1.02 1.02 0 0 1-1.02 1.02H1.02A1.02 1.02 0 0 1 0 16.28V6.04c0-.56.46-1.02 1.02-1.02zm7.81 3.9V7.84H3.45v1.08h2.03v5.57h1.3V8.92h2.05z"/>', instagram: '<path d="M17.3 5.5a1.2 1.2 0 1 0 1.2 1.2 1.2 1.2 0 0 0-1.2-1.2ZM22 7.9a7.6 7.6 0 0 0-.4-2.5 5 5 0 0 0-1.2-1.7 4.7 4.7 0 0 0-1.8-1.2 7.3 7.3 0 0 0-2.4-.4L12 2H7.9a7.3 7.3 0 0 0-2.5.5 4.8 4.8 0 0 0-1.7 1.2 4.7 4.7 0 0 0-1.2 1.8 7.3 7.3 0 0 0-.4 2.4L2 12v4.1a7.3 7.3 0 0 0 .5 2.4 4.7 4.7 0 0 0 1.2 1.8 4.8 4.8 0 0 0 1.8 1.2 7.3 7.3 0 0 0 2.4.4l4.1.1h4.1a7.3 7.3 0 0 0 2.4-.5 4.7 4.7 0 0 0 1.8-1.2 4.8 4.8 0 0 0 1.2-1.7 7.6 7.6 0 0 0 .4-2.5L22 12V7.9ZM20.1 16a5.6 5.6 0 0 1-.3 1.9A3 3 0 0 1 19 19a3.2 3.2 0 0 1-1.1.8 5.6 5.6 0 0 1-1.9.3H8a5.7 5.7 0 0 1-1.9-.3A3.3 3.3 0 0 1 5 19a3 3 0 0 1-.7-1.1 5.5 5.5 0 0 1-.4-1.9l-.1-4V8a5.5 5.5 0 0 1 .4-1.9A3 3 0 0 1 5 5a3.1 3.1 0 0 1 1.1-.8A5.7 5.7 0 0 1 8 3.9l4-.1h4a5.6 5.6 0 0 1 1.9.4A3 3 0 0 1 19 5a3 3 0 0 1 .7 1.1A5.6 5.6 0 0 1 20 8l.1 4v4ZM12 6.9a5.1 5.1 0 1 0 5.1 5.1A5.1 5.1 0 0 0 12 6.9Zm0 8.4a3.3 3.3 0 1 1 3.3-3.3 3.3 3.3 0 0 1-3.3 3.3Z"/>', stackOverflow: '<path d="M15.72 0 14 1.28l6.4 8.58 1.7-1.26L15.73 0zm-3.94 3.42-1.36 1.64 8.22 6.85 1.37-1.64-8.23-6.85zM8.64 7.88l-.91 1.94 9.7 4.52.9-1.94-9.7-4.52zm-1.86 4.86-.44 2.1 10.48 2.2.44-2.1-10.47-2.2zM1.9 15.47V24h19.19v-8.53h-2.13v6.4H4.02v-6.4H1.9zm4.26 2.13v2.13h10.66V17.6H6.15Z"/>', + telegram: + '<path d="M22.265 2.428a2.048 2.048 0 0 0-2.078-.324L2.266 9.339a2.043 2.043 0 0 0 .104 3.818l3.625 1.261 2.02 6.682a.998.998 0 0 0 .119.252c.008.012.019.02.027.033a.988.988 0 0 0 .211.215.972.972 0 0 0 .07.05.986.986 0 0 0 .31.136l.013.001.006.003a1.022 1.022 0 0 0 .203.02l.018-.003a.993.993 0 0 0 .301-.052c.023-.008.042-.02.064-.03a.993.993 0 0 0 .205-.114 250.76 250.76 0 0 1 .152-.129l2.702-2.983 4.03 3.122a2.023 2.023 0 0 0 1.241.427 2.054 2.054 0 0 0 2.008-1.633l3.263-16.017a2.03 2.03 0 0 0-.693-1.97ZM9.37 14.736a.994.994 0 0 0-.272.506l-.31 1.504-.784-2.593 4.065-2.117Zm8.302 5.304-4.763-3.69a1.001 1.001 0 0 0-1.353.12l-.866.955.306-1.487 7.083-7.083a1 1 0 0 0-1.169-1.593L6.745 12.554 3.02 11.191 20.999 4Z"/>', + rss: '<path d="M2.88 16.88a3 3 0 0 0 0 4.24 3 3 0 0 0 4.24 0 3 3 0 0 0-4.24-4.24Zm2.83 2.83a1 1 0 0 1-1.42-1.42 1 1 0 0 1 1.42 0 1 1 0 0 1 0 1.42ZM5 12a1 1 0 0 0 0 2 5 5 0 0 1 5 5 1 1 0 0 0 2 0 7 7 0 0 0-7-7Zm0-4a1 1 0 0 0 0 2 9 9 0 0 1 9 9 1 1 0 0 0 2 0 11.08 11.08 0 0 0-3.22-7.78A11.08 11.08 0 0 0 5 8Zm10.61.39A15.11 15.11 0 0 0 5 4a1 1 0 0 0 0 2 13 13 0 0 1 13 13 1 1 0 0 0 2 0 15.11 15.11 0 0 0-4.39-10.61Z"/>', + facebook: + '<path d="M20.9 2H3.1A1.1 1.1 0 0 0 2 3.1v17.8A1.1 1.1 0 0 0 3.1 22h9.58v-7.75h-2.6v-3h2.6V9a3.64 3.64 0 0 1 3.88-4 20.26 20.26 0 0 1 2.33.12v2.7H17.3c-1.26 0-1.5.6-1.5 1.47v1.93h3l-.39 3H15.8V22h5.1a1.1 1.1 0 0 0 1.1-1.1V3.1A1.1 1.1 0 0 0 20.9 2Z"/>', + email: + '<path d="M19 4H5a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h14a3 3 0 0 0 3-3V7a3 3 0 0 0-3-3Zm-.41 2-5.88 5.88a1 1 0 0 1-1.42 0L5.41 6ZM20 17a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7.41l5.88 5.88a3 3 0 0 0 4.24 0L20 7.41Z"/>', + phone: + '<path d="M19.44 13c-.22 0-.45-.07-.67-.12a9.44 9.44 0 0 1-1.31-.39 2 2 0 0 0-2.48 1l-.22.45a12.18 12.18 0 0 1-2.66-2 12.18 12.18 0 0 1-2-2.66l.42-.28a2 2 0 0 0 1-2.48 10.33 10.33 0 0 1-.39-1.31c-.05-.22-.09-.45-.12-.68a3 3 0 0 0-3-2.49h-3a3 3 0 0 0-3 3.41 19 19 0 0 0 16.52 16.46h.38a3 3 0 0 0 2-.76 3 3 0 0 0 1-2.25v-3a3 3 0 0 0-2.47-2.9Zm.5 6a1 1 0 0 1-.34.75 1.05 1.05 0 0 1-.82.25A17 17 0 0 1 4.07 5.22a1.09 1.09 0 0 1 .25-.82 1 1 0 0 1 .75-.34h3a1 1 0 0 1 1 .79q.06.41.15.81a11.12 11.12 0 0 0 .46 1.55l-1.4.65a1 1 0 0 0-.49 1.33 14.49 14.49 0 0 0 7 7 1 1 0 0 0 .76 0 1 1 0 0 0 .57-.52l.62-1.4a13.69 13.69 0 0 0 1.58.46q.4.09.81.15a1 1 0 0 1 .79 1Z"/>', + reddit: + '<path d="M14.41 16.87a3.38 3.38 0 0 1-2.37.63 3.37 3.37 0 0 1-2.36-.63 1 1 0 0 0-1.42 1.41 5.11 5.11 0 0 0 3.78 1.22 5.12 5.12 0 0 0 3.78-1.22 1 1 0 1 0-1.41-1.41ZM9.2 15a1 1 0 1 0-1-1 1 1 0 0 0 1 1Zm6-2a1 1 0 1 0 1 1 1 1 0 0 0-1-1Zm7.8-1.22a3.77 3.77 0 0 0-6.8-2.26 16.5 16.5 0 0 0-3.04-.48l.85-5.7 2.09.7a3 3 0 0 0 6-.06v-.02a3.03 3.03 0 0 0-3-2.96 2.98 2.98 0 0 0-2.34 1.16l-3.24-1.1a1 1 0 0 0-1.3.8l-1.09 7.17a16.66 16.66 0 0 0-3.34.49 3.77 3.77 0 0 0-6.22 4.23A4.86 4.86 0 0 0 1 16c0 3.92 4.83 7 11 7s11-3.08 11-7a4.86 4.86 0 0 0-.57-2.25 3.78 3.78 0 0 0 .57-1.97ZM19.1 3a1 1 0 1 1-1 1 1.02 1.02 0 0 1 1-1ZM4.77 10a1.76 1.76 0 0 1 .88.25A9.98 9.98 0 0 0 3 11.92v-.14A1.78 1.78 0 0 1 4.78 10ZM12 21c-4.88 0-9-2.29-9-5s4.12-5 9-5 9 2.29 9 5-4.12 5-9 5Zm8.99-9.08a9.98 9.98 0 0 0-2.65-1.67 1.76 1.76 0 0 1 .88-.25A1.78 1.78 0 0 1 21 11.78l-.01.14Z"/>', + patreon: + '<path d="M22.04 7.6c0-2.8-2.19-5.1-4.75-5.93a15.19 15.19 0 0 0-10.44.55C3.16 3.96 2 7.78 1.95 11.58c-.02 3.12.3 11.36 4.94 11.42 3.45.04 3.97-4.4 5.56-6.55 1.14-1.52 2.6-1.95 4.4-2.4 3.1-.76 5.2-3.2 5.2-6.44Z"/>', + signal: + '<path d="m9.12.35.27 1.09a10.9 10.9 0 0 0-3.015 1.248l-.578-.964A12 12 0 0 1 9.12.35m5.76 0-.27 1.09a10.9 10.9 0 0 1 3.015 1.248l.581-.964A12 12 0 0 0 14.88.35M1.725 5.797A12 12 0 0 0 .351 9.119l1.09.27A10.9 10.9 0 0 1 2.69 6.374zm-.6 6.202a11 11 0 0 1 .122-1.63l-1.112-.168a12 12 0 0 0 0 3.596l1.112-.169A11 11 0 0 1 1.125 12zm17.078 10.275-.578-.964a10.9 10.9 0 0 1-3.011 1.247l.27 1.091a12 12 0 0 0 3.319-1.374M22.875 12a11 11 0 0 1-.122 1.63l1.112.168a12 12 0 0 0 0-3.596l-1.112.169a11 11 0 0 1 .122 1.63zm.774 2.88-1.09-.27a10.9 10.9 0 0 1-1.248 3.015l.964.581a12 12 0 0 0 1.374-3.326m-10.02 7.875a11 11 0 0 1-3.258 0l-.17 1.112a12 12 0 0 0 3.597 0zm7.125-4.303a11 11 0 0 1-2.304 2.302l.668.906a12 12 0 0 0 2.542-2.535zM18.45 3.245a11 11 0 0 1 2.304 2.304l.906-.675a12 12 0 0 0-2.535-2.535zM3.246 5.549A11 11 0 0 1 5.55 3.245l-.675-.906A12 12 0 0 0 2.34 4.874zm19.029.248-.964.577a10.9 10.9 0 0 1 1.247 3.011l1.091-.27a12 12 0 0 0-1.374-3.318M10.371 1.246a11 11 0 0 1 3.258 0L13.8.134a12 12 0 0 0-3.597 0zM3.823 21.957 1.5 22.5l.542-2.323-1.095-.257-.542 2.323a1.125 1.125 0 0 0 1.352 1.352l2.321-.532zm-2.642-3.041 1.095.255.375-1.61a10.8 10.8 0 0 1-1.21-2.952l-1.09.27a12 12 0 0 0 1.106 2.852zm5.25 2.437-1.61.375.255 1.095 1.185-.275a12 12 0 0 0 2.851 1.106l.27-1.091a10.8 10.8 0 0 1-2.943-1.217zM12 2.25a9.75 9.75 0 0 0-8.25 14.938l-.938 4 4-.938A9.75 9.75 0 1 0 12 2.25"/>', + slack: + '<path d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52Zm1.271 0a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313ZM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834Zm0 1.271a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312Zm10.122 2.521a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834Zm-1.268 0a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312Zm-2.523 10.122a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52Zm0-1.268a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313Z"/>', + matrix: + '<path d="M22.5 1.5v21h-2.25V24H24V0h-3.75v1.5h2.25ZM7.46 7.95V9.1h.04a3.02 3.02 0 0 1 2.61-1.39c.54 0 1.03.1 1.48.32.44.2.78.58 1.01 1.1.26-.37.6-.7 1.03-.99.44-.28.95-.43 1.55-.43.45 0 .87.06 1.26.17.38.11.71.29.99.53.27.24.49.56.64.95.15.4.23.86.23 1.42v5.72h-2.34v-4.85c0-.29-.01-.56-.04-.8a1.73 1.73 0 0 0-.18-.67 1.1 1.1 0 0 0-.44-.45 1.6 1.6 0 0 0-.78-.16c-.33 0-.6.06-.8.19-.2.12-.37.29-.48.5a2 2 0 0 0-.23.69c-.04.26-.06.52-.06.78v4.77H10.6v-4.8l-.01-.75a2.29 2.29 0 0 0-.14-.69c-.08-.2-.23-.38-.42-.5a1.5 1.5 0 0 0-.85-.2c-.15.01-.3.04-.44.08-.19.06-.37.15-.52.28-.18.14-.32.34-.44.6-.12.26-.18.6-.18 1.02v4.96H5.25V7.94h2.21ZM1.5 1.5v21h2.25V24H0V0h3.75v1.5H1.5Z"/>', + hackerOne: + '<path d="M7.2 0Q6.5 0 6 .3a1 1 0 0 0-.4.8v21.8q0 .4.4.7.5.4 1.2.4t1.2-.3q.5-.4.5-.8V1c0-.3-.2-.6-.5-.8Q7.9 0 7.2 0m9.5 8.7q-.7 0-1.1.3L11 11.7c-.2.2-.3.5-.2.9q0 .6.5 1c.3.4.7.7 1 .7q.7.2 1-.1l1.7-1v9.7q0 .4.5.7c.3.3.7.4 1.1.4q.7 0 1.2-.3c.4-.3.5-.5.5-.8V9.7q0-.4-.5-.7-.4-.3-1.2-.3"/>', + openCollective: + '<path d="M21.86 5.17a11.94 11.94 0 0 1 0 13.66l-3.1-3.1a7.68 7.68 0 0 0 0-7.46l3.1-3.1Zm-3.03-3.03-3.1 3.1a7.71 7.71 0 1 0 0 13.51l3.1 3.11a12 12 0 1 1 0-19.73Z"/><path d="M21.86 5.17a11.94 11.94 0 0 1 0 13.66l-3.1-3.1a7.68 7.68 0 0 0 0-7.46l3.1-3.1Z"/>', + blueSky: + '<path d="M12 10.8c-1-2.1-4-6-6.8-8C2.6 1 1.6 1.3.9 1.6.1 1.9 0 3 0 3.8c0 .7.4 5.6.6 6.4C1.4 13 4.3 14 7 13.6h.4H7c-4 .6-7.4 2-2.8 7 5 5.3 6.8-1 7.8-4.2 1 3.2 2 9.3 7.7 4.3 4.3-4.3 1.2-6.5-2.7-7a9 9 0 0 1-.4-.1h.4c2.7.3 5.6-.6 6.4-3.4.2-.8.6-5.7.6-6.4 0-.7-.1-1.9-.9-2.2-.7-.3-1.7-.7-4.3 1.2-2.8 2-5.7 5.9-6.8 8"/>', + discourse: + '<path d="M12.102 0h-.081C5.462 0 .13 5.252.001 11.779v.012L.007 24l12.097-.01c6.582-.055 11.897-5.404 11.897-11.995S18.686.056 12.109 0h-.005zM12 18.857h-.015a6.778 6.778 0 0 1-2.94-.666l.041.018-4.345 1.077 1.227-4.018a6.78 6.78 0 0 1-.83-3.27A6.86 6.86 0 1 1 12 18.857z"/>', + zulip: + '<path d="M21 19c0 1.7-1.2 3-2.7 3H5.7C4.2 22 3 20.7 3 19a3 3 0 0 1 1.2-2.4l6.7-6c0-.1.3 0 .2.2l-2.5 5s0 .2.2.2h9.5c1.5 0 2.7 1.4 2.7 3Zm0-14a3 3 0 0 1-1.2 2.4l-6.7 6c0 .1-.2 0-.2-.2l2.5-5s0-.2-.2-.2H5.7C4.2 8 3 6.6 3 5c0-1.7 1.2-3 2.7-3h12.6C19.8 2 21 3.3 21 5Z"/>', + pinterest: + '<path d="M12 0a12 12 0 0 0-4.4 23.1c0-.9-.2-2.4 0-3.4l1.5-6s-.4-.7-.4-1.7c0-1.7 1-3 2.2-3 1 0 1.5.8 1.5 1.7 0 1-.6 2.6-1 4-.3 1.2.6 2.2 1.8 2.2 2.1 0 3.8-2.2 3.8-5.5 0-2.8-2-4.9-5-4.9a5.2 5.2 0 0 0-5.4 5.2c0 1 .3 2.2.8 2.8.1.1.2.2.1.3l-.3 1.4c0 .2-.2.3-.4.2-1.5-.7-2.4-3-2.4-4.7C4.4 8 7 4.5 12.3 4.5c4.1 0 7.4 3 7.4 6.9 0 4.1-2.6 7.4-6.3 7.4-1.2 0-2.3-.6-2.7-1.3l-.8 2.8c-.2 1-1 2.4-1.5 3.2A12 12 0 1 0 12 0z"/>', + tiktok: + '<path d="M12.525.02c1.31-.02 2.61-.01 3.91-.02.08 1.53.63 3.09 1.75 4.17 1.12 1.11 2.7 1.62 4.24 1.79v4.03c-1.44-.05-2.89-.35-4.2-.97-.57-.26-1.1-.59-1.62-.93-.01 2.92.01 5.84-.02 8.75-.08 1.4-.54 2.79-1.35 3.94-1.31 1.92-3.58 3.17-5.91 3.21-1.43.08-2.86-.31-4.08-1.03-2.02-1.19-3.44-3.37-3.65-5.71-.02-.5-.03-1-.01-1.49.18-1.9 1.12-3.72 2.58-4.96 1.66-1.44 3.98-2.13 6.15-1.72.02 1.48-.04 2.96-.04 4.44-.99-.32-2.15-.23-3.02.37-.63.41-1.11 1.04-1.36 1.75-.21.51-.15 1.07-.14 1.61.24 1.64 1.82 3.02 3.5 2.87 1.12-.01 2.19-.66 2.77-1.61.19-.33.4-.67.41-1.06.1-1.79.06-3.57.07-5.36.01-4.03-.01-8.05.02-12.07z"/>', + astro: + '<path d="M7.233 15.856c-.456 1.5-.132 3.586.948 4.57v-.036l.036-.096c.132-.636.648-1.032 1.309-1.008.612.012.96.336 1.044 1.044.036.264.036.528.048.803v.084c0 .6.168 1.176.504 1.68.3.48.72.851 1.284 1.103l-.024-.048-.024-.096c-.42-1.26-.12-2.135.984-2.879l.336-.227.745-.492a3.647 3.647 0 0 0 1.536-2.603c.06-.456 0-.9-.132-1.331l-.18.12c-1.668.887-3.577 1.2-5.425.84-1.117-.169-2.197-.48-3-1.416l.011-.012ZM2 15.592s3.205-1.559 6.421-1.559l2.437-7.508c.084-.36.348-.6.648-.6.3 0 .552.24.648.612l2.425 7.496c3.816 0 6.421 1.56 6.421 1.56L15.539.72c-.144-.444-.42-.72-.768-.72H8.24c-.348 0-.6.276-.768.72L2 15.592Z"/>', + alpine: '<path d="m18.7 6 5.3 5.3-5.3 5.3-5.4-5.3L18.7 6zM5.3 6l11 11H5.8L0 11.2 5.3 6z"/>', + pnpm: '<path d="M0 0v7.5h7.5V0H0Zm8.25 0v7.5h7.498V0H8.25Zm8.25 0v7.5H24V0h-7.5ZM8.25 8.25v7.5h7.498v-7.5H8.25Zm8.25 0v7.5H24v-7.5h-7.5ZM0 16.5V24h7.5v-7.5H0Zm8.25 0V24h7.498v-7.5H8.25Zm8.25 0V24H24v-7.5h-7.5Z"/>', + biome: + '<path d="m12 2-5.346 9.259a12.065 12.065 0 0 1 6.326-.22l1.807.427-1.7 7.208-1.81-.427c-2.223-.524-4.36.644-5.263 2.507l-1.672-.809c1.276-2.636 4.284-4.232 7.363-3.505l.848-3.593A10.213 10.213 0 0 0 0 22.785h24L12 2Z"/>', + bun: '<path d="M11.966 22.132c6.609 0 11.966-4.326 11.966-9.661 0-3.308-2.051-6.23-5.204-7.963-1.283-.713-2.291-1.353-3.13-1.885C14.018 1.619 13.043 1 11.966 1c-1.094 0-2.327.783-3.955 1.816a49.78 49.78 0 0 1-2.808 1.692C2.051 6.241 0 9.163 0 12.471c0 5.335 5.357 9.661 11.966 9.661Zm-1.397-17.83a5.885 5.885 0 0 0 .497-2.403c0-.144.201-.186.229-.028.656 2.775-.9 4.15-2.051 4.61-.124.048-.199-.12-.103-.208a5.747 5.747 0 0 0 1.428-1.971Zm2.052-.102a5.795 5.795 0 0 0-.78-2.3v-.015c-.068-.123.086-.263.185-.172 1.956 2.105 1.303 4.055.554 5.037-.082.102-.229-.003-.188-.126a5.837 5.837 0 0 0 .229-2.424Zm1.771-.559a5.709 5.709 0 0 0-1.607-1.801v-.014c-.112-.085-.024-.274.113-.218 2.588 1.084 2.766 3.171 2.452 4.395a.116.116 0 0 1-.13.09.11.11 0 0 1-.071-.045.118.118 0 0 1-.022-.083 5.863 5.863 0 0 0-.735-2.324ZM9.32 4.2c-.616.544-1.279.758-2.058.997-.116 0-.194-.078-.155-.18 1.747-.907 2.369-1.645 2.99-2.771 0 0 .155-.117.188.085 0 .303-.348 1.325-.965 1.869Zm4.931 11.205a2.95 2.95 0 0 1-.935 1.549 2.16 2.16 0 0 1-1.282.618 2.167 2.167 0 0 1-1.323-.618 2.95 2.95 0 0 1-.923-1.549.243.243 0 0 1 .064-.197.23.23 0 0 1 .192-.069h3.954a.227.227 0 0 1 .244.16c.01.035.014.07.009.106Zm-5.443-2.17a1.85 1.85 0 0 1-2.377-.244 1.969 1.969 0 0 1-.233-2.44c.207-.318.502-.565.846-.711a1.84 1.84 0 0 1 2.053.42c.264.27.443.616.515.99a1.98 1.98 0 0 1-.108 1.118c-.142.35-.384.653-.696.867Zm8.471.005a1.85 1.85 0 0 1-2.374-.252 1.956 1.956 0 0 1-.546-1.362c0-.383.11-.758.319-1.076.207-.318.502-.566.847-.711a1.84 1.84 0 0 1 1.09-.108c.366.076.702.261.965.533s.44.617.512.993a1.98 1.98 0 0 1-.113 1.118 1.922 1.922 0 0 1-.7.865Z"/>', + mdx: '<path d="m15.494 12.406-3.169 3.169-3.25-3.169.894-.894 1.706 1.707V8.588h1.219V13.3l1.706-1.706.894.812Zm-13.65-.65 2.193 2.194 2.276-2.194v3.575H7.53v-6.58l-3.494 3.493L.625 8.75v6.581h1.219v-3.575ZM22.4 15.25l-2.519-2.519-2.518 2.519-.813-.894 2.519-2.518-2.6-2.6.893-.813 2.52 2.6 2.6-2.6.893.813-2.6 2.6 2.519 2.518-.894.894Z"/>', + apple: + '<path d="M14.94 5.19A4.38 4.38 0 0 0 16 2a4.44 4.44 0 0 0-3 1.52 4.17 4.17 0 0 0-1 3.09 3.69 3.69 0 0 0 2.94-1.42Zm2.52 7.44a4.51 4.51 0 0 1 2.16-3.81 4.66 4.66 0 0 0-3.66-2c-1.56-.16-3 .91-3.83.91s-2-.89-3.3-.87a4.92 4.92 0 0 0-4.14 2.53C2.93 12.45 4.24 17 6 19.47c.8 1.21 1.8 2.58 3.12 2.53s1.75-.82 3.28-.82 2 .82 3.3.79 2.22-1.24 3.06-2.45a11 11 0 0 0 1.38-2.85 4.41 4.41 0 0 1-2.68-4.04Z"/>', + linux: + '<path d="M19.7 17.6c-.1-.2-.2-.4-.2-.6 0-.4-.2-.7-.5-1-.1-.1-.3-.2-.4-.2.6-1.8-.3-3.6-1.3-4.9-.8-1.2-2-2.1-1.9-3.7 0-1.9.2-5.4-3.3-5.1-3.6.2-2.6 3.9-2.7 5.2 0 1.1-.5 2.2-1.3 3.1-.2.2-.4.5-.5.7-1 1.2-1.5 2.8-1.5 4.3-.2.2-.4.4-.5.6-.1.1-.2.2-.2.3-.1.1-.3.2-.5.3-.4.1-.7.3-.9.7-.1.3-.2.7-.1 1.1.1.2.1.4 0 .7-.2.4-.2.9 0 1.4.3.4.8.5 1.5.6.5 0 1.1.2 1.6.4.5.3 1.1.5 1.7.5.3 0 .7-.1 1-.2.3-.2.5-.4.6-.7.4 0 1-.2 1.7-.2.6 0 1.2.2 2 .1 0 .1 0 .2.1.3.2.5.7.9 1.3 1h.2c.8-.1 1.6-.5 2.1-1.1.4-.4.9-.7 1.4-.9.6-.3 1-.5 1.1-1 .1-.7-.1-1.1-.5-1.7zM12.8 4.8c.6.1 1.1.6 1 1.2 0 .3-.1.6-.3.9h-.1c-.2-.1-.3-.1-.4-.2.1-.1.1-.3.2-.5 0-.4-.2-.7-.4-.7-.3 0-.5.3-.5.7v.1c-.1-.1-.3-.1-.4-.2V6c-.1-.5.3-1.1.9-1.2zm-.3 2c.1.1.3.2.4.2.1 0 .3.1.4.2.2.1.4.2.4.5s-.3.6-.9.8c-.2.1-.3.1-.4.2-.3.2-.6.3-1 .3-.3 0-.6-.2-.8-.4-.1-.1-.2-.2-.4-.3-.1-.1-.3-.3-.4-.6 0-.1.1-.2.2-.3.3-.2.4-.3.5-.4l.1-.1c.2-.3.6-.5 1-.5.3.1.6.2.9.4zM10.4 5c.4 0 .7.4.8 1.1v.2c-.1 0-.3.1-.4.2v-.2c0-.3-.2-.6-.4-.5-.2 0-.3.3-.3.6 0 .2.1.3.2.4 0 0-.1.1-.2.1-.2-.2-.4-.5-.4-.8 0-.6.3-1.1.7-1.1zm-1 16.1c-.7.3-1.6.2-2.2-.2-.6-.3-1.1-.4-1.8-.4-.5-.1-1-.1-1.1-.3-.1-.2-.1-.5.1-1 .1-.3.1-.6 0-.9-.1-.3-.1-.5 0-.8.1-.3.3-.4.6-.5.3-.1.5-.2.7-.4.1-.1.2-.2.3-.4.3-.4.5-.6.8-.6.6.1 1.1 1 1.5 1.9.2.3.4.7.7 1 .4.5.9 1.2.9 1.6 0 .5-.2.8-.5 1zm4.9-2.2c0 .1 0 .1-.1.2-1.2.9-2.8 1-4.1.3l-.6-.9c.9-.1.7-1.3-1.2-2.5-2-1.3-.6-3.7.1-4.8.1-.1.1 0-.3.8-.3.6-.9 2.1-.1 3.2 0-.8.2-1.6.5-2.4.7-1.3 1.2-2.8 1.5-4.3.1.1.1.1.2.1.1.1.2.2.3.2.2.3.6.4.9.4h.1c.4 0 .8-.1 1.1-.4.1-.1.2-.2.4-.2.3-.1.6-.3.9-.6.4 1.3.8 2.5 1.4 3.6.4.8.7 1.6.9 2.5.3 0 .7.1 1 .3.8.4 1.1.7 1 1.2H18c0-.3-.2-.6-.9-.9-.7-.3-1.3-.3-1.5.4-.1 0-.2.1-.3.1-.8.4-.8 1.5-.9 2.6.1.4 0 .7-.1 1.1zm4.6.6c-.6.2-1.1.6-1.5 1.1-.4.6-1.1 1-1.9.9-.4 0-.8-.3-.9-.7-.1-.6-.1-1.2.2-1.8.1-.4.2-.7.3-1.1.1-1.2.1-1.9.6-2.2 0 .5.3.8.7 1 .5 0 1-.1 1.4-.5h.2c.3 0 .5 0 .7.2.2.2.3.5.3.7 0 .3.2.6.3.9.5.5.5.8.5.9-.1.2-.5.4-.9.6zm-9-12c-.1 0-.1 0-.1.1 0 0 0 .1.1.1s.1.1.1.1c.3.4.8.6 1.4.7.5-.1 1-.2 1.5-.6l.6-.3c.1 0 .1-.1.1-.1 0-.1 0-.1-.1-.1-.2.1-.5.2-.7.3-.4.3-.9.5-1.4.5-.5 0-.9-.3-1.2-.6-.1 0-.2-.1-.3-.1z"/>', + homebrew: + '<path d="M7.94 0a.21.21 0 0 0-.2.16c-.32 1.1.17 2.15.83 2.93.15.18.31.35.48.5a2.04 2.04 0 0 0-.67.02c-1.18.24-2.2.99-2.74 2.53a3.9 3.9 0 0 0-.2 1.47 1.56 1.56 0 0 0-1.16 1.5 1.59 1.59 0 0 0 1.23 1.55l.03 12.04c0 .2.1.38.26.48a.21.21 0 0 0 .01 0c.54.32 2.05.82 5.21.82 3.24 0 4.7-.68 5.18-1.04a.57.57 0 0 0 .22-.45v-1.6a.14.14 0 0 1 .14-.14h1.32a1.83 1.83 0 0 0 1.83-1.82v-5.8a1.83 1.83 0 0 0-1.82-1.83h-1.33a.14.14 0 0 1-.14-.15v-.57a1.57 1.57 0 0 0 1.36-1.56c0-.81-.63-1.49-1.42-1.56a4.34 4.34 0 0 0-.74-2.58 3.1 3.1 0 0 0-2.28-1.32c-.5-.02-.84.12-1.13.25-.21.1-.42.18-.67.22 0-1.28.95-1.98.95-1.98a.21.21 0 0 0 .05-.3s-.09-.12-.21-.26c-.12-.13-.27-.3-.47-.38a.21.21 0 0 0-.08-.01.21.21 0 0 0-.14.05 4.3 4.3 0 0 0-.88 1.1 3.42 3.42 0 0 0-.13.28 3.5 3.5 0 0 0-.38-.85A4.44 4.44 0 0 0 8.02.02.21.21 0 0 0 7.94 0zm.15.52c.85.38 1.43.83 1.8 1.4.27.45.42.97.48 1.6a3.07 3.07 0 0 0-.01.45 6.9 6.9 0 0 1-.17-.05 5.49 5.49 0 0 1-1.3-1.1c-.54-.66-.93-1.46-.8-2.3m3.71 1.1c.07.05.14.1.21.18l.06.07a2.97 2.97 0 0 0-.95 2.45.21.21 0 0 0 .22.2c.47-.02.78-.17 1.06-.3.27-.13.5-.23.93-.21.87.02 1.64.71 1.94 1.13.3.45.65 1 .66 2.36a1.66 1.66 0 0 0-.41.14 1.94 1.94 0 0 0-1.77-1.16 1.94 1.94 0 0 0-1.87 1.45 1.78 1.78 0 0 0-1.36-.64c-.48 0-.9.2-1.23.52a1.87 1.87 0 0 0-1.85-1.63c-.65 0-1.22.34-1.55.84a3.1 3.1 0 0 1 .16-.73c.5-1.44 1.35-2.05 2.42-2.26.36-.07.66 0 .99.1.32.1.67.26 1.09.34a.21.21 0 0 0 .25-.25c-.11-.67.07-1.26.34-1.74a3.71 3.71 0 0 1 .66-.86m-4.36 5A1.44 1.44 0 0 1 8.8 8.53a.21.21 0 0 0 .17.28.21.21 0 0 0 .24-.15 1.37 1.37 0 0 1 2.62 0 .21.21 0 0 0 .41-.1 1.5 1.5 0 0 1 1.5-1.66c.69 0 1.26.44 1.45 1.05a.21.21 0 0 0 .26.15l.15-.04a.21.21 0 0 0 .05-.02 1.14 1.14 0 0 1 1.7 1 1.14 1.14 0 0 1-.98 1.12 2.21 2.21 0 0 0-.49.13 10.65 10.65 0 0 1-1.18.36.21.21 0 0 0-.16.2 1.28 1.28 0 0 1-.14.47 2.07 2.07 0 0 0-.24 1.11v.15a.44.44 0 0 1-.16.36.67.67 0 0 1-.43.14.59.59 0 0 1-.59-.59.8.8 0 0 0-.38-.68 1.28 1.28 0 0 1-.53-.64.21.21 0 0 0-.21-.14 19.47 19.47 0 0 1-5.37-.6 9 9 0 0 0-.84-.2 1.16 1.16 0 0 1-.94-1.13c0-.62.5-1.11 1.1-1.14a.21.21 0 0 0 .21-.17A1.44 1.44 0 0 1 7.44 6.6m8.55 4.1v.46c0 .32.26.57.57.57h1.33a1.4 1.4 0 0 1 1.4 1.4v5.8a1.4 1.4 0 0 1-1.4 1.4h-1.32a.57.57 0 0 0-.58.57v1.6c0 .05-.02.08-.05.11-.35.26-1.75.95-4.92.95-3.1 0-4.59-.52-4.99-.75a.14.14 0 0 1-.06-.12l-.03-11.95.43.1.39.1v10.37c0 .13.07.25.18.31.45.22 1.77.74 4.07.74 2.32 0 3.6-.63 4.02-.89a.36.36 0 0 0 .17-.3v-10.2l.79-.26m-8 .9a.5.5 0 0 1 .5.48v8.58a.5.5 0 0 1-.49.5.5.5 0 0 1-.5-.5V12.1a.5.5 0 0 1 .5-.49zm8.66 1.13a.66.66 0 0 0-.66.66v5.21a.66.66 0 0 0 .66.66h1.14a.66.66 0 0 0 .66-.66v-5.2a.66.66 0 0 0-.66-.67zm0 .43h1.14a.23.23 0 0 1 .23.23v5.21a.23.23 0 0 1-.23.23h-1.14a.23.23 0 0 1-.23-.23v-5.2a.23.23 0 0 1 .23-.24"/>', + nix: '<path d="M7.4 1.6H6l-.7 1.1L7 5.5H3.7L2.4 7.8h11.7l-1.3-2.3H9.6l-2.2-4zm6.1 0h-2.7l5.9 10.1L18 9.4l-1.6-2.8 2.3-3.8-.7-1.2h-1.3L15 4.3l-1.6-2.7zm7 4.2-6 10.1h2.8l1.6-2.8h4.4L24 12l-.7-1.2h-3.1l1.6-2.7-1.4-2.3zM9.4 8H6.6L5 10.8H.7L0 12l.7 1.2h3.1l-1.6 2.7 1.4 2.3zm-2.2 4.2L6 14.6l1.6 2.8-2.3 3.8.7 1.2h1.3L9 19.7l1.6 2.7h2.7zm2.6 3.9 1.3 2.3h3.2l2.2 3.9H18l.7-1.2-1.6-2.7h3.2l1.3-2.3z"/>', + starlight: + '<path fill-rule="evenodd" d="M15.19 6.75 12 0 8.81 6.75l-.19.38-1.68-1.88a1.2 1.2 0 1 0-1.69 1.69L7.13 8.8h-.38L0 12l6.75 3.19h.38l-1.88 1.87a1.2 1.2 0 1 0 1.69 1.69l1.68-1.88.2.38L12 24l3.19-6.75v-.38l1.69 1.88a1.2 1.2 0 1 0 1.68-1.69l-1.68-1.68.37-.2L24 12l-6.75-3.19-.38-.19 1.7-1.68a1.2 1.2 0 1 0-1.7-1.69L15.2 7.13v-.38ZM12 7.13l-.38.93a8.18 8.18 0 0 1-3.56 3.56l-.94.38.94.38a8.18 8.18 0 0 1 3.56 3.56l.38.94.38-.94a8.18 8.18 0 0 1 3.56-3.56l.94-.38-.94-.38a8.18 8.18 0 0 1-3.56-3.56L12 7.12Z"/><path d="M22.12 3.56a1.2 1.2 0 1 0-1.68-1.69l-.57.57a1.2 1.2 0 0 0 1.7 1.68l.55-.56Zm-18 .75c-.37.38-1.12.38-1.68 0l-.57-.56a1.2 1.2 0 0 1 1.7-1.69l.55.56c.57.38.57 1.13 0 1.7Zm0 15.38c-.37-.38-1.12-.38-1.68 0l-.57.56a1.2 1.2 0 1 0 1.7 1.69l.55-.57c.57-.37.57-1.12 0-1.68Zm18 .75a1.2 1.2 0 1 1-1.68 1.68l-.57-.56a1.2 1.2 0 0 1 1.7-1.69l.55.57Z"/>', + pkl: '<path fill-rule="evenodd" d="M18.7 1.8 18 5a9 9 0 0 1 2 2.4l3.2.2c.4 1 .6 2 .7 3.1L21 12.2a9 9 0 0 1-.7 3l1.9 2.7c-.6 1-1.2 1.7-2 2.5l-3-1.3c-.9.6-1.9 1-2.9 1.4l-.9 3c-1 .2-2.1.2-3.2 0l-.8-3c-1-.4-2-.8-2.9-1.5l-3 1.3a12 12 0 0 1-2-2.5l2-2.6a9 9 0 0 1-.8-3L0 10.5c.1-1.1.3-2.1.7-3.1L4 7.3A9 9 0 0 1 6 5l-.6-3.2c1-.6 2-1 3-1.3l2 2.4c1.1-.2 2.2-.2 3.2 0L15.8.4c1 .3 2 .8 2.9 1.4Zm1 9.8c0 4.2-3.3 7.5-7.5 7.5a7.5 7.5 0 0 1-7.6-7.5c0-4.1 3.4-7.5 7.6-7.5 4.2 0 7.6 3.4 7.6 7.5Z"></path><path fill-opacity=".5" d="M11.4 10.8c-6.6-2.7-3.6-5.5.4-5.5 4.3 0 7.8 2.5 1.2 5.5a2 2 0 0 1-1.6 0Zm.4 1.9c1 7-3 5.8-5 2.5-2.1-3.7-1.7-8 4.2-3.9a2 2 0 0 1 .8 1.4Zm6.2 1.7c2-3.3 1-7.3-4.7-3a2 2 0 0 0-.8 1.4c-.7 7.1 3.3 5.4 5.5 1.7Z"/>', + node: '<path d="M12 23.96c-.34 0-.66-.1-.96-.25l-3.03-1.73c-.45-.25-.22-.33-.09-.38.62-.2.73-.24 1.37-.6.07-.04.16-.02.23.03l2.32 1.34c.1.05.2.05.27 0l9.1-5.08a.27.27 0 0 0 .13-.24V6.9c0-.11-.05-.2-.14-.24L12.11 1.6c-.09-.05-.2-.05-.27 0L2.75 6.66c-.09.04-.13.15-.13.24v10.14c0 .1.04.2.13.25l2.49 1.38c1.34.66 2.18-.1 2.18-.88V7.78c0-.13.12-.26.28-.26h1.16c.13 0 .27.1.27.26v10.01c0 1.74-.98 2.75-2.69 2.75-.52 0-.93 0-2.1-.55l-2.38-1.32a1.85 1.85 0 0 1-.96-1.6V6.92c0-.66.36-1.28.96-1.6l9.08-5.1a2.1 2.1 0 0 1 1.92 0l9.08 5.08c.6.33.96.95.96 1.61v10.15c0 .66-.36 1.27-.96 1.6l-9.08 5.09a2.4 2.4 0 0 1-.96.2m2.8-6.98c-3.98 0-4.8-1.76-4.8-3.26 0-.13.11-.26.27-.26h1.18c.14 0 .25.08.25.22.19 1.16.71 1.73 3.12 1.73 1.92 0 2.74-.41 2.74-1.4 0-.58-.23-1-3.21-1.28-2.49-.24-4.04-.77-4.04-2.68 0-1.79 1.55-2.84 4.15-2.84 2.91 0 4.35.96 4.53 3.08a.35.35 0 0 1-.07.2.27.27 0 0 1-.18.08h-1.18a.27.27 0 0 1-.25-.2c-.28-1.2-.98-1.6-2.85-1.6-2.1 0-2.35.7-2.35 1.23 0 .64.3.84 3.12 1.19 2.8.35 4.13.86 4.13 2.75-.03 1.94-1.67 3.04-4.56 3.04"/>', + cloudflare: + '<path d="M16.5 16.84c.16-.5.1-.97-.15-1.3-.22-.33-.6-.5-1.06-.53l-8.66-.11a.15.15 0 0 1-.13-.08.21.21 0 0 1-.02-.15.25.25 0 0 1 .2-.15l8.74-.12a3.13 3.13 0 0 0 2.55-1.91l.5-1.3a.25.25 0 0 0 .01-.17 5.68 5.68 0 0 0-10.93-.59 2.58 2.58 0 0 0-3.35.24 2.55 2.55 0 0 0-.67 2.44 3.64 3.64 0 0 0-3.5 4.17.18.18 0 0 0 .17.15h15.98a.22.22 0 0 0 .21-.16l.12-.43Zm2.77-5.56-.24.01c-.06 0-.1.05-.13.1l-.34 1.18c-.15.5-.1.97.16 1.31.22.32.6.5 1.06.52l1.84.12c.06 0 .1.02.14.07.02.04.03.1.02.15a.23.23 0 0 1-.2.15l-1.93.12a3.11 3.11 0 0 0-2.55 1.91l-.14.36c-.03.07.02.14.1.14h6.6a.18.18 0 0 0 .16-.12 4.74 4.74 0 0 0-4.56-6v-.02Z"/>', + vercel: '<path d="m12 1l12 21H0z"/>', + netlify: + '<path d="M6.49 19.04h-.23L5.13 17.9v-.23l1.73-1.71h1.2l.15.15v1.2L6.5 19.04ZM5.13 6.31V6.1l1.13-1.13h.23L8.2 6.68v1.2l-.15.15h-1.2zm9.96 9.09h-1.65l-.14-.13v-3.83c0-.68-.27-1.2-1.1-1.23c-.42 0-.9 0-1.43.02l-.07.08v4.96l-.14.14H8.9l-.13-.14V8.73l.13-.14h3.7a2.6 2.6 0 0 1 2.61 2.6v4.08l-.13.14Zm-8.37-2.44H.14L0 12.82v-1.64l.14-.14h6.58l.14.14v1.64zm17.14 0h-6.58l-.14-.14v-1.64l.14-.14h6.58l.14.14v1.64zM11.05 6.55V1.64l.14-.14h1.65l.14.14v4.9l-.14.14h-1.65zm0 15.81v-4.9l.14-.14h1.65l.14.13v4.91l-.14.14h-1.65z"/>', + deno: '<path d="M12 0a12 12 0 1 1 0 24 12 12 0 0 1 0-24m-.47 6.8c-3.49 0-6.2 2.19-6.2 4.92 0 2.58 2.5 4.23 6.37 4.15h.12l.42-.02-.1.28v.03l.09.22v.03l.02.04.02.07.02.04.01.05.02.05.02.07.02.08.02.06.02.08.02.09.02.09.03.1.01.06.03.1.02.1.03.15.02.07.02.11.03.12.02.12.04.17.02.15.04.2.02.1.03.15.03.15.04.22.04.23.04.23.04.24.04.24.04.26.04.26.04.2.05.34.02.14.06.36.04.3.04.22.04.31.03.16a10.76 10.76 0 0 0 6.53-3.41l.05-.06-.24-.89-.64-2.37-.39-1.47-.35-1.3-.21-.78-.14-.5-.08-.3-.07-.26-.03-.11-.02-.07-.01-.03v-.03a6.04 6.04 0 0 0-2.05-2.97 6.75 6.75 0 0 0-4.25-1.35M8.47 19.3a.59.59 0 0 0-.72.4v.01l-.53 1.96q.5.24 1.01.43l.08.03.57-2.11V20a.59.59 0 0 0-.41-.7m3.26-1.43a.59.59 0 0 0-.71.4v.01l-.8 2.96v.01a.59.59 0 0 0 1.12.3l.8-2.96v-.02l.02-.06v-.02l-.02-.1-.02-.14-.02-.08a.58.58 0 0 0-.37-.3Zm-5.55-3.04a1 1 0 0 0-.04.09v.02l-.8 2.95v.02a.59.59 0 0 0 1.13.3v-.01l.72-2.68a5.3 5.3 0 0 1-1.01-.7Zm-1.9-3.4a.59.59 0 0 0-.72.4v.02l-.8 2.95v.01a.59.59 0 0 0 1.13.3l.8-2.96v-.01a.59.59 0 0 0-.41-.7m17.87-.68a.59.59 0 0 0-.72.4v.02l-.8 2.95v.01a.59.59 0 0 0 1.13.3l.8-2.96v-.01a.59.59 0 0 0-.41-.7M2.55 6.81a10.7 10.7 0 0 0-1.26 3.93.59.59 0 0 0 1-.22v-.02l.8-2.95v-.01a.59.59 0 0 0-.55-.73m17.59.02a.59.59 0 0 0-.72.4v.01l-.8 2.96v.01a.59.59 0 0 0 1.13.3l.8-2.96v-.01a.59.59 0 0 0-.41-.7Zm-7.85 1.93a.75.75 0 1 1 0 1.5.75.75 0 0 1 0-1.5M6.01 4.03a.59.59 0 0 0-.71.4v.02L4.5 7.4v.01a.59.59 0 0 0 1.12.3l.8-2.96v-.01a.59.59 0 0 0-.41-.7Zm10.24.56a.59.59 0 0 0-.71.4V5L15 7q.52.26.99.6l.05.04.62-2.32V5.3a.59.59 0 0 0-.41-.7m-5.21-3.34a11 11 0 0 0-1.12.16l-.07.01L9.1 4.2v.01a.59.59 0 0 0 1.13.3l.8-2.96v-.01a.6.6 0 0 0 0-.27m7.34 2.04-.16.58v.02a.59.59 0 0 0 1.13.3V4.2l.02-.07a11 11 0 0 0-.92-.77zm-4.64-1.94-.28 1.05a.59.59 0 0 0 1.13.31v-.01l.3-1.1q-.52-.15-1.06-.24z"/>', + jsr: '<path d="M3.7 5.54v3.7H0v7.38h7.38v1.84h12.93v-3.7H24V7.39h-7.38V5.54Zm1.84 1.85h1.85v7.38H1.84v-3.7h1.84v1.85h1.85zm3.7 0h5.53v1.84h-3.7v1.85h3.7v5.53H9.23v-1.84h3.7v-1.85h-3.7Zm7.38 1.84h5.53v3.7h-1.84v-1.85h-1.85v5.54h-1.84z"/>', + nostr: + '<path d="M21.6 10.6v9.7a.7.7 0 0 1-.6.6h-8a.7.7 0 0 1-.6-.6v-1.8c0-2.2.3-4.4.8-5.3a2 2 0 0 1 1.3-1c1-.4 2.9-.2 3.7-.2 0 0 2.3 0 2.3-1.3 0-1-1-1-1-1-1.2 0-2 0-2.6-.2-1-.4-1-1.1-1-1.3 0-2.7-4-3-7.5-2.4-3.9.7 0 6.2 0 13.5v1a.7.7 0 0 1-.7.6H3.8a.7.7 0 0 1-.6-.6V3.5a.7.7 0 0 1 .6-.6h3.7a.7.7 0 0 1 .7.6c0 .6.6.9 1 .6 1.3-1 3-1.5 5-1.5 4.2 0 7.4 2.5 7.4 8zm-7-2a1.4 1.4 0 1 0-2.9 0 1.4 1.4 0 0 0 2.9 0z"/>', + backstage: + '<path d="M18.4 9.3a4.4 4.4 0 0 0 .7-.5l.1-.1a4.5 4.5 0 0 0 .8-1.1l.3-1c0-1-.6-2-2-3L12.7.4 6 6.6l-4.3 4 6 3.7a6.1 6.1 0 0 0 3 .9c1.5 0 2.8-.5 3.7-1.4 1-1 1.4-2.3.8-3.4a2.8 2.8 0 0 0-.4-.5l1 .1a4.6 4.6 0 0 0 1.8-.3 4.5 4.5 0 0 0 .7-.3zm-5.5 3.3c-1 1-2.8 1.2-4.2.4l-4.1-2.5 3.7-3.6 4.2 2.6c1.5.9 1.4 2.1.4 3.1zm.5-4.5-4-2.3L13 2.4l3.8 2.3c1.4.9 1.6 2 .6 3a3.3 3.3 0 0 1-4 .4zM15 18.5c-1 1-2.5 1.6-4.1 1.6a6.8 6.8 0 0 1-3.5-1l-5.6-3.4v1.4l6 3.6a6.1 6.1 0 0 0 3 .9c1.5 0 2.8-.5 3.7-1.4.7-.7 1.1-1.5 1.1-2.3l-.6.6zm0-2.1c-1 1-2.5 1.6-4.1 1.6a6.8 6.8 0 0 1-3.5-1l-5.6-3.4V15l6 3.6a6.1 6.1 0 0 0 3 .9c1.5 0 2.8-.5 3.7-1.4.7-.7 1.1-1.5 1.1-2.3v-.1l-.6.7zm0-2.1c-1 1-2.5 1.6-4.1 1.6a6.8 6.8 0 0 1-3.5-1l-5.6-3.4v1.3l6 3.6a6.1 6.1 0 0 0 3 1c1.5 0 2.8-.6 3.7-1.5.7-.7 1.1-1.5 1.1-2.3l-.6.7zm4.6 1.4a5.2 5.2 0 0 1-3.3 1.4v1.5a4.5 4.5 0 0 0 2.8-1.3c.8-.7 1.2-1.5 1.2-2.3v-.1l-.7.8zm-4.6 5c-1 1-2.5 1.6-4.1 1.6a6.8 6.8 0 0 1-3.5-1l-5.6-3.4v1.3l6 3.6a6.1 6.1 0 0 0 3 1c1.5 0 2.8-.5 3.7-1.5.7-.6 1.1-1.5 1.1-2.2V20l-.6.7zM19.7 9l-.1.2-1.2.8a5.2 5.2 0 0 1-1.5.5 5.2 5.2 0 0 1-.8 0l.1.4V12a4.6 4.6 0 0 0 1.5-.3A4.4 4.4 0 0 0 19 11l.1-.1a4.5 4.5 0 0 0 .8-1.1 2.6 2.6 0 0 0 .3-1.1v-.1l-.2.1-.4.6zm0 4.3a6 6 0 0 1-.1.1 5.2 5.2 0 0 1-3.3 1.5v1.4a4.5 4.5 0 0 0 2.8-1.2l1-1.2.2-1v-.1l-.2.2a4.8 4.8 0 0 1-.4.5zm0-2.1-.1.1a4.8 4.8 0 0 1-.6.5 5.2 5.2 0 0 1-2.7 1v1.4A4.5 4.5 0 0 0 19 13h.1a4.2 4.2 0 0 0 .8-1.2l.3-.9v-.3a4 4 0 0 1-.2.2l-.4.5z"/>', + confluence: + '<path d="M.85 18.07.1 19.32a.76.76 0 0 0-.1.28.76.76 0 0 0 .02.28.75.75 0 0 0 .33.46l4.97 3.07a.76.76 0 0 0 .86-.03.75.75 0 0 0 .2-.23l.73-1.23c1.97-3.23 3.97-2.83 7.54-1.14l4.93 2.34a.76.76 0 0 0 .6.03.76.76 0 0 0 .43-.4l2.36-5.35a.75.75 0 0 0 .02-.57.77.77 0 0 0-.38-.43c-1.04-.49-3.1-1.45-4.96-2.36C10.9 10.8 5.2 11 .85 18.07Z"/><path d="m23.15 5.94.75-1.25a.77.77 0 0 0 .08-.57.76.76 0 0 0-.13-.27.76.76 0 0 0-.22-.2L18.67.6a.76.76 0 0 0-.29-.1.77.77 0 0 0-.57.13.77.77 0 0 0-.2.23l-.73 1.22c-1.98 3.25-3.96 2.86-7.53 1.16L4.42.89a.78.78 0 0 0-.59-.03.76.76 0 0 0-.26.15.76.76 0 0 0-.18.24L1.02 6.61a.77.77 0 0 0-.02.57c.04.1.09.18.15.25a.76.76 0 0 0 .24.18c1.04.5 3.11 1.45 4.96 2.36 6.73 3.26 12.44 3.04 16.8-4.03z"/>', + jira: '<path d="M7.75 16.3H5.62C2.4 16.3.09 14.31.09 11.43h11.47c.6 0 .98.42.98 1.02V24c-2.87 0-4.79-2.32-4.79-5.56Zm5.67-5.74h-2.14c-3.21 0-5.52-1.94-5.52-4.82h11.47c.6 0 1.01.38 1.01.98v11.54c-2.87 0-4.82-2.32-4.82-5.56zm5.7-5.7h-2.14c-3.21 0-5.52-1.97-5.52-4.86h11.47c.6 0 .98.42.98.99v11.54c-2.87 0-4.8-2.32-4.8-5.56z"/>', + storybook: + '<path d="m20.35 0-1.32.08.1 2.78a.18.18 0 0 1-.3.14l-.9-.7-1.05.8a.18.18 0 0 1-.25-.03.18.18 0 0 1-.04-.12l.12-2.72-13.21.82A1.2 1.2 0 0 0 2.37 2.3l.74 19.82a1.2 1.2 0 0 0 1.15 1.16l16.11.72h.06c.66 0 1.2-.54 1.2-1.2V1.12A1.2 1.2 0 0 0 20.35 0zm-7.99 4.08c3.14 0 4.86 1.68 4.86 4.88-.42.33-3.59.56-3.59.09.07-1.8-.73-1.87-1.18-1.87-.42 0-1.13.12-1.13 1.08 0 2.37 6.1 2.24 6.1 7.02 0 2.69-2.18 4.17-4.97 4.17-2.87 0-5.38-1.16-5.1-5.2.11-.47 3.77-.35 3.77 0-.05 1.67.33 2.16 1.29 2.16.73 0 1.07-.4 1.07-1.09 0-2.43-6.02-2.51-6.02-6.97 0-2.56 1.76-4.27 4.9-4.27z"/>', + vscode: + '<path d="M23.15 2.59 18.2.2a1.5 1.5 0 0 0-1.7.29L7.04 9.13 2.93 6a1 1 0 0 0-1.28.06L.33 7.26a1 1 0 0 0 0 1.48L3.9 12 .32 15.26a1 1 0 0 0 0 1.48l1.33 1.2a1 1 0 0 0 1.28.06l4.12-3.13 9.46 8.63c.44.45 1.13.57 1.7.29l4.94-2.38c.52-.25.85-.77.85-1.35V3.94c0-.58-.33-1.1-.85-1.36ZM18 17.45 10.82 12 18 6.55v10.9Z"/>', + jetbrains: + '<path fill-rule="evenodd" d="M2.05 24h9.33c1.17 0 2.28-.52 3.11-1.47l5.22-5.97A5.45 5.45 0 0 0 21 13.01V2.34C21 1.05 20.08 0 18.95 0H9.62C8.45 0 7.34.52 6.5 1.47L1.29 7.43A5.45 5.45 0 0 0 0 11v10.66C0 22.95.92 24 2.05 24ZM3.47 6.5l3.72-4.25A3.2 3.2 0 0 1 9.62 1.1h9.33c.6 0 1.08.56 1.08 1.23V13a4.3 4.3 0 0 1-1 2.77l-3.73 4.25V6.51H3.47Zm-.17.2v13.52h11.83l-1.32 1.51a3.22 3.22 0 0 1-2.43 1.15H2.05c-.6 0-1.08-.56-1.08-1.24V11a4.3 4.3 0 0 1 1-2.77L3.3 6.71Zm6.6 10.43H4.8v1.37h5.1v-1.37Z"/>', + zed: '<path d="M2.25 1.5a.75.75 0 0 0-.75.75v16.5H0V2.25C0 1.01 1 0 2.25 0h20.1c1 0 1.5 1.21.79 1.92L10.76 14.3h3.49v-1.55h1.5v1.92c0 .62-.5 1.13-1.13 1.13H9.27L6.7 18.37h11.69V9h1.5v9.38c0 .82-.68 1.5-1.5 1.5H5.18L2.57 22.5h19.19c.41 0 .75-.34.75-.75V5.25H24v16.5c0 1.24-1 2.25-2.25 2.25H1.65c-1 0-1.5-1.21-.79-1.92L13.19 9.75H9.75v1.5h-1.5V9.37c0-.62.5-1.12 1.12-1.12h5.32l2.62-2.62H5.63V15h-1.5V5.63c0-.83.67-1.5 1.5-1.5H18.8l2.63-2.63H2.25Z"/>', + vim: '<path d="m19.83 16.57.45-.49h1.25l.29.4-1.19 3.84h.46l-.07.2h-1.67l1.05-3.34h-1.89l-1 3.18h.4l-.08.16h-1.5l1.04-3.33H15.4l-1 3.13h.41l-.06.2h-1.56l1.42-4.18h-.55l.09-.26h1.54l.49.5h.85l.46-.51h1l.45.5h.9ZM6 20.27H4.4l-.25-.14V3.65H2.98l-.1-.1v-1.1l.14-.14h6.91l.2.2v1.04L10 3.7H8.99v8.14l8.25-8.14H15.3l-.17-.18V2.44l.12-.1h7.02l.12.13v1l-9.46 9.7H12.5a.24.24 0 0 0-.11.06l-.32.28a.25.25 0 0 0-.07.1l-.28.78-5.74 5.88Zm7.45-6.75.14.14-.26.87-.2.2h-.91l-.17-.16.29-.82.27-.23h.84Zm-3.47 7.04 1.48-4.22h-.47l.28-.29h1.56l-1.47 4.27h.59l-.08.24H9.97ZM23.25 12h-.03l-4.05-4.05 4.04-4.14V2.12l-.61-.6H14.9l-.61.56v.98L12 .78V.75L12 .77l-.01-.02v.03l-1.21 1.2-.5-.5H2.65l-.6.65V3.9l.58.58h.67v4.97L.78 12H.75l.02.01-.02.01h.03l2.53 2.54v6.06l.85.5h2.18l1.74-1.8 3.9 3.91v.03l.02-.02.01.02v-.03l2.35-2.35h.46c.1 0 .2-.07.23-.17l.14-.4.01-.07c0-.06-.01-.11-.04-.15l1.37-1.37-.58 1.84v.07c0 .11.06.2.17.24l.07.01h1.7c.11 0 .2-.06.24-.15l.15-.37a.25.25 0 0 0 0-.2.25.25 0 0 0-.23-.15h-.07l.79-2.47h1.15l-.95 3.02-.01.07c0 .11.07.2.17.24l.08.01h1.88c.1 0 .2-.07.23-.16l.15-.4a.25.25 0 0 0-.15-.32.24.24 0 0 0-.08-.02h-.14l1.06-3.44.02-.08c0-.05-.02-.1-.05-.14l-.36-.48a.25.25 0 0 0-.2-.1h-1.34a.25.25 0 0 0-.18.08l-.37.41h-.59l-.04-.04 4.17-4.17h.03-.02l.02-.02Z"/>', + figma: + '<path d="M5.77 8.28A4.44 4.44 0 0 1 8.19.1h7.6a4.44 4.44 0 0 1 2.43 8.17 4.44 4.44 0 0 1-2.42 8.16h-.08a4.42 4.42 0 0 1-3-1.17v4.14a4.5 4.5 0 0 1-4.51 4.48 4.46 4.46 0 0 1-2.44-8.17 4.44 4.44 0 0 1 0-7.44ZM12.7 12a3 3 0 0 0 3 3h.09a3 3 0 1 0 0-6h-.08a3 3 0 0 0-3 3Zm-1.43-3H8.19a3 3 0 0 0-.01 6h3.1V9Zm-3.09 7.44h-.01a3 3 0 1 0 .03 6.01 3.06 3.06 0 0 0 3.07-3.04v-2.97H8.19Zm3.09-8.88V1.55H8.19a3 3 0 1 0 0 6.01h3.09Zm4.52 0a3 3 0 1 0 0-6.01H12.7v6.01h3.09Z"/>', + sketch: + '<path d="m.29 8.99 4.8-6.53a.6.6 0 0 1 .42-.24l6.42-.71a.6.6 0 0 1 .14 0l6.42.71a.6.6 0 0 1 .42.24L23.7 9a.6.6 0 0 1-.02.75L12.34 22.86a.45.45 0 0 1-.68 0L.31 9.74a.6.6 0 0 1-.02-.75Zm13.36-5.55a.15.15 0 0 0-.21.2l3.04 3.75a.3.3 0 0 1-.23.49h-8.5a.3.3 0 0 1-.23-.5l3.05-3.74a.15.15 0 0 0-.22-.2L5.8 7.72a.3.3 0 0 1-.5-.24l.21-3.04a.15.15 0 0 0-.3-.05l-.99 3.48a.75.75 0 0 1-.48.5l-2.19.71a.15.15 0 0 0 .05.3h2.1a.75.75 0 0 1 .64.34l5.56 8.74a.23.23 0 0 0 .39-.22L6.3 10.02a.45.45 0 0 1 .4-.64h10.57a.45.45 0 0 1 .4.64l-3.98 8.22a.22.22 0 0 0 .4.22l5.55-8.74a.75.75 0 0 1 .64-.34h2.04a.15.15 0 0 0 .04-.3l-2.12-.7a.75.75 0 0 1-.48-.51l-1-3.48a.15.15 0 0 0-.17-.1.15.15 0 0 0-.12.15l.22 3.04a.3.3 0 0 1-.51.24l-4.54-4.28Z"/>', + npm: '<path d="M1.76 0h20.48a1.76 1.76 0 0 1 1.76 1.76v20.48a1.76 1.76 0 0 1-1.76 1.76H1.76A1.76 1.76 0 0 1 0 22.24V1.76A1.76 1.76 0 0 1 1.76 0zM5.11 19.16h6.93V8.8h3.47v10.36h3.47V5.34H5.13v13.82z"></path>', + sourcehut: + '<path d="M12 20a8 8 0 0 1-8-8 8 8 0 0 1 8-8 8 8 0 0 1 8 8 8 8 0 0 1-8 8m0-18A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2"/>', + substack: + '<path d="M22.5 8.2h-21V5.4h21v2.8zm-21 2.6V24L12 18.1 22.5 24V10.8h-21zM22.5 0h-21v2.8h21V0z"/>', + chrome: + '<path d="M9.83 21.76A10 10 0 0 1 3.33 7l4.3 7.42a5 5 0 0 0 4.97 2.55zM12 22l4.29-7.42A5 5 0 0 0 17 12a5 5 0 0 0-1-3h5.54a10 10 0 0 1 .46 3 10 10 0 0 1-10 10m2.57-8.45a3 3 0 0 1-5.17-.05l-.03-.05a3 3 0 1 1 5.23.05zM4.63 5.24A10 10 0 0 1 12 2a10 10 0 0 1 8.66 5H12a5 5 0 0 0-4.6 3.03z"/>', + edge: '<path d="M10.86 15.37a5 5 0 0 1-1.31-2.72q-.46.69-.73 1.5a5.97 5.97 0 0 0 3.4 7.18c2.34.78 4.97-.61 6.7-2.13.26-.35 2.31-2.16 1.29-2.36-3.02 1.55-7.02 1.11-9.35-1.47m.6-5.81c1.04-.01.04-.43-.39-.75a7 7 0 0 0-3.44-.85C3.78 8 1 10.41 2.3 14.4c.94 3.88 4.31 7 8.29 7.5a7.3 7.3 0 0 1-3.29-6.12c.08-2.53 1.64-5.5 4.16-6.22M2.78 8.24C5.82 6 10.66 6.18 13.28 9c1.02 1.11 1.72 3 .79 4.37-1.74 1.88 3.08 2.13 4.11 1.85 3.74-.72 4.73-5.07 2.95-8.07-1.7-3.4-5.47-5.18-9.17-5.15a9.8 9.8 0 0 0-9.18 6.24"/>', + firefox: + '<path d="M6.85 6.74q.02 0 0 0M21.28 8.6a5.6 5.6 0 0 0-2.01-2.54c.56 1.11.89 2.22 1.02 3.04v.02c-1.13-2.82-3.05-3.96-4.62-6.44q-.13-.18-.24-.38l-.11-.21a2 2 0 0 1-.15-.4l-.02-.02h-.03a7.3 7.3 0 0 0-3.38 5.04q-1.05.06-1.99.51c-.12.05-.17.19-.13.31.05.14.21.21.34.15a5 5 0 0 1 1.74-.45h.05l.25-.01q.74-.01 1.44.2l.06.02.25.06.16.08.14.06.2.09.09.05.2.11.12.07a5 5 0 0 1 1.75 1.81A3.5 3.5 0 0 0 14 9.19c3.6 1.81 2.63 8-2.36 7.76a4 4 0 0 1-1.76-.45 4.3 4.3 0 0 1-2.38-3.27s.5-1.73 3.33-1.73c.31 0 1.17-.86 1.2-1.1 0-.09-1.74-.78-2.42-1.45l-.69-.66-.26-.19a4.6 4.6 0 0 1-.03-2.45A8 8 0 0 0 6.22 7.5c-.4-.5-.37-2.15-.35-2.5l-.33.18q-.53.38-.98.82-.52.55-.94 1.14a9 9 0 0 0-1.34 3.04c0 .01-.1.41-.17.92l-.03.23-.08.58v.41A10.02 10.02 0 0 0 21.88 14l.05-.37c.2-1.72-.02-3.52-.65-5.03"/>', + safari: + '<path d="M5.4 13.2H3.6V12h1.8zm1.944-5.868-.852.852L5.22 6.912l.852-.852zM12 5.4h-1.2V3.6H12zm6.6 5.4h1.8V12h-1.8zm-1.944 5.868.852-.852 1.272 1.272-.852.852zM12 18.6h1.2v1.8H12zm.924-5.676-1.848-1.848L9.24 14.76zM12 21.6a9.6 9.6 0 0 0 9.6-9.6c0-2.508-.96-4.8-2.532-6.492l-4.524 9.036-9.036 4.524A9.6 9.6 0 0 0 12 21.6m0-19.2A9.6 9.6 0 0 0 2.4 12c0 2.508.96 4.8 2.532 6.492l4.524-9.036 9.036-4.524A9.6 9.6 0 0 0 12 2.4M12 0c6.627 0 12 5.373 12 12s-5.373 12-12 12S0 18.627 0 12 5.373 0 12 0"/>', +}; + +export const Icons = { + ...BuiltInIcons, + ...FileIcons, }; + +export type StarlightIcon = keyof typeof Icons; diff --git a/packages/starlight/components/LanguageSelect.astro b/packages/starlight/components/LanguageSelect.astro index d59df1c18b2..8bb4e1f0f04 100644 --- a/packages/starlight/components/LanguageSelect.astro +++ b/packages/starlight/components/LanguageSelect.astro @@ -1,21 +1,15 @@ --- +import context from 'virtual:starlight/project-context'; import config from 'virtual:starlight/user-config'; import { localizedUrl } from '../utils/localizedUrl'; -import { useTranslations } from '../utils/translations'; import Select from './Select.astro'; -interface Props { - locale: string | undefined; -} - /** * Get the equivalent of the current page path for the passed locale. */ function localizedPathname(locale: string | undefined): string { - return localizedUrl(Astro.url, locale).pathname; + return localizedUrl(Astro.url, locale, context.trailingSlash).pathname; } - -const t = useTranslations(Astro.props.locale); --- { @@ -23,11 +17,10 @@ const t = useTranslations(Astro.props.locale); <starlight-lang-select> <Select icon="translate" - label={t('languageSelect.accessibleLabel')} - value={localizedPathname(Astro.props.locale)} + label={Astro.locals.t('languageSelect.accessibleLabel')} options={Object.entries(config.locales).map(([code, locale]) => ({ value: localizedPathname(code), - selected: code === Astro.props.locale, + selected: code === Astro.locals.starlightRoute.locale, label: locale!.label, }))} width="7em" @@ -47,6 +40,16 @@ const t = useTranslations(Astro.props.locale); window.location.pathname = e.currentTarget.value; } }); + window.addEventListener('pageshow', (event) => { + if (!event.persisted) return; + // If the page was loaded from a cache, the language select selected index might not be + // in sync with the current page. + const markupSelectedIndex = + select.querySelector<HTMLOptionElement>('option[selected]')?.index; + if (markupSelectedIndex !== select.selectedIndex) { + select.selectedIndex = markupSelectedIndex ?? 0; + } + }); } } } diff --git a/packages/starlight/components/LastUpdated.astro b/packages/starlight/components/LastUpdated.astro index 278057e905b..9a29831af5f 100644 --- a/packages/starlight/components/LastUpdated.astro +++ b/packages/starlight/components/LastUpdated.astro @@ -1,36 +1,13 @@ --- -import type { CollectionEntry } from 'astro:content'; -import { fileURLToPath } from 'node:url'; -import project from 'virtual:starlight/project-context'; -import { getFileCommitDate } from '../utils/git'; -import { useTranslations } from '../utils/translations'; - -interface Props { - id: CollectionEntry<'docs'>['id']; - lang: string; - lastUpdated: Date | undefined; - locale: string | undefined; -} - -const { id, lang, lastUpdated, locale } = Astro.props; -const t = useTranslations(locale); - -const currentFilePath = fileURLToPath(new URL('src/content/docs/' + id, project.root)); - -let date = lastUpdated; -try { - if (!date) { - ({ date } = getFileCommitDate(currentFilePath, 'newest')); - } -} catch {} +const { lang, lastUpdated } = Astro.locals.starlightRoute; --- { - date && ( + lastUpdated && ( <p> - {t('page.lastUpdated')}{' '} - <time datetime={date.toISOString()}> - {date.toLocaleDateString(lang, { dateStyle: 'medium' })} + {Astro.locals.t('page.lastUpdated')}{' '} + <time datetime={lastUpdated.toISOString()}> + {lastUpdated.toLocaleDateString(lang, { dateStyle: 'medium', timeZone: 'UTC' })} </time> </p> ) diff --git a/packages/starlight/components/MarkdownContent.astro b/packages/starlight/components/MarkdownContent.astro index ea44bd6c185..90fe3d884d3 100644 --- a/packages/starlight/components/MarkdownContent.astro +++ b/packages/starlight/components/MarkdownContent.astro @@ -1,123 +1,5 @@ -<div class="content"><slot /></div> +--- +import '../style/markdown.css'; +--- -<style> - .content - :global( - :not(a, strong, em, del, span, input) - + :not(a, strong, em, del, span, input, :where(.not-content *)) - ) { - margin-top: 1.5rem; - } - - /* Headings after non-headings have more spacing. */ - .content - :global( - :not(h1, h2, h3, h4, h5, h6) + :is(h1, h2, h3, h4, h5, h6):not(:where(.not-content *)) - ) { - margin-top: 2.5rem; - } - - .content :global(li + li:not(:where(.not-content *))), - .content :global(dt + dt:not(:where(.not-content *))), - .content :global(dt + dd:not(:where(.not-content *))), - .content :global(dd + dd:not(:where(.not-content *))) { - margin-top: 0.25rem; - } - - .content - :global( - li > :last-child:not(li, ul, ol):not(a, strong, em, del, span, input, :where(.not-content *)) - ) { - margin-bottom: 1.25rem; - } - - .content :global(dt:not(:where(.not-content *))) { - font-weight: 700; - } - .content :global(dd:not(:where(.not-content *))) { - padding-inline-start: 1rem; - } - - .content :global(:is(h1, h2, h3, h4, h5, h6):not(:where(.not-content *))) { - color: var(--sl-color-white); - line-height: var(--sl-line-height-headings); - font-weight: 600; - } - - .content :global(:is(img, picture, video, canvas, svg, iframe):not(:where(.not-content *))) { - display: block; - max-width: 100%; - height: auto; - } - - .content :global(h1:not(:where(.not-content *))) { - font-size: var(--sl-text-h1); - } - .content :global(h2:not(:where(.not-content *))) { - font-size: var(--sl-text-h2); - } - .content :global(h3:not(:where(.not-content *))) { - font-size: var(--sl-text-h3); - } - .content :global(h4:not(:where(.not-content *))) { - font-size: var(--sl-text-h4); - } - .content :global(h5:not(:where(.not-content *))) { - font-size: var(--sl-text-h5); - } - .content :global(h6:not(:where(.not-content *))) { - font-size: var(--sl-text-h6); - } - - .content :global(a:not(:where(.not-content *))) { - color: var(--sl-color-text-accent); - } - .content :global(a:hover:not(:where(.not-content *))) { - color: var(--sl-color-white); - } - - .content :global(code:not(:where(.not-content *))) { - background-color: var(--sl-color-bg-inline-code); - margin-block: -0.125rem; - padding: 0.125rem 0.375rem; - font-size: var(--sl-text-code-sm); - } - .content :global(:is(h1, h2, h3, h4, h5, h6) code) { - font-size: inherit; - } - - .content :global(pre:not(:where(.not-content *))) { - border: 1px solid var(--sl-color-gray-5); - padding: 0.75rem 1rem; - font-size: var(--sl-text-code); - tab-size: 2; - } - - .content :global(pre code:not(:where(.not-content *))) { - all: unset; - font-family: var(--__sl-font-mono); - } - - .content :global(blockquote:not(:where(.not-content *))) { - border-inline-start: 1px solid var(--sl-color-gray-5); - padding-inline-start: 1rem; - } - - .content :global(table:not(:where(.not-content *))) { - display: block; - overflow: auto; - border-collapse: collapse; - } - .content :global(tr:nth-child(2n):not(:where(.not-content *))) { - background-color: var(--sl-color-gray-7, var(--sl-color-gray-6)); - } - .content :global(:is(th, td):not(:where(.not-content *))) { - border: 1px solid var(--sl-color-hairline-light); - padding: 0.375rem 0.8125rem; - } - - .content :global(hr:not(:where(.not-content *))) { - border: 0; - border-bottom: 1px solid var(--sl-color-hairline); - } -</style> +<div class="sl-markdown-content"><slot /></div> diff --git a/packages/starlight/components/MobileMenuFooter.astro b/packages/starlight/components/MobileMenuFooter.astro new file mode 100644 index 00000000000..095d3328255 --- /dev/null +++ b/packages/starlight/components/MobileMenuFooter.astro @@ -0,0 +1,35 @@ +--- +import LanguageSelect from 'virtual:starlight/components/LanguageSelect'; +import SocialIcons from 'virtual:starlight/components/SocialIcons'; +import ThemeSelect from 'virtual:starlight/components/ThemeSelect'; +--- + +<div class="mobile-preferences sl-flex"> + <div class="social-icons"> + <SocialIcons /> + </div> + <ThemeSelect /> + <LanguageSelect /> +</div> + +<style> + @layer starlight.core { + .social-icons { + display: flex; + margin-inline-end: auto; + gap: 1rem; + align-items: center; + padding-block: 1rem; + } + .social-icons:empty { + display: none; + } + .mobile-preferences { + justify-content: space-between; + flex-wrap: wrap; + border-top: 1px solid var(--sl-color-gray-6); + column-gap: 1rem; + padding: 0.5rem 0; + } + } +</style> diff --git a/packages/starlight/components/MobileMenuToggle.astro b/packages/starlight/components/MobileMenuToggle.astro index a6e620b05df..0f078d36a50 100644 --- a/packages/starlight/components/MobileMenuToggle.astro +++ b/packages/starlight/components/MobileMenuToggle.astro @@ -1,22 +1,16 @@ --- import Icon from '../user-components/Icon.astro'; -import { useTranslations } from '../utils/translations'; - -interface Props { - locale: string | undefined; -} - -const t = useTranslations(Astro.props.locale); --- -<starlight-menu-button> +<starlight-menu-button class="print:hidden"> <button aria-expanded="false" - aria-label={t('menuButton.accessibleLabel')} + aria-label={Astro.locals.t('menuButton.accessibleLabel')} aria-controls="starlight__sidebar" class="sl-flex md:sl-hidden" > - <Icon name="bars" /> + <Icon name="bars" class="open-menu" /> + <Icon name="close" class="close-menu" /> </button> </starlight-menu-button> @@ -57,45 +51,57 @@ const t = useTranslations(Astro.props.locale); </script> <style> - button { - position: fixed; - top: calc((var(--sl-nav-height) - var(--sl-menu-button-size)) / 2); - inset-inline-end: var(--sl-nav-pad-x); - z-index: var(--sl-z-index-navbar); - border: 0; - border-radius: 50%; - width: var(--sl-menu-button-size); - height: var(--sl-menu-button-size); - padding: 0.5rem; - background-color: var(--sl-color-white); - color: var(--sl-color-black); - box-shadow: var(--sl-shadow-md); - cursor: pointer; - } + @layer starlight.core { + button { + position: fixed; + top: calc((var(--sl-nav-height) - var(--sl-menu-button-size)) / 2); + inset-inline-end: var(--sl-nav-pad-x); + z-index: var(--sl-z-index-navbar); + border: 0; + border-radius: 50%; + width: var(--sl-menu-button-size); + height: var(--sl-menu-button-size); + padding: 0.5rem; + background-color: var(--sl-color-white); + color: var(--sl-color-black); + box-shadow: var(--sl-shadow-md); + cursor: pointer; + } - [aria-expanded='true'] button { - background-color: var(--sl-color-gray-2); - box-shadow: none; - } + [aria-expanded='true'] button { + background-color: var(--sl-color-gray-2); + box-shadow: none; + } - :global([data-theme='light']) button { - background-color: var(--sl-color-black); - color: var(--sl-color-white); - } + [aria-expanded='true'] button .open-menu { + display: none; + } + + :not([aria-expanded='true']) button .close-menu { + display: none; + } + + :global([data-theme='light']) button { + background-color: var(--sl-color-black); + color: var(--sl-color-white); + } - :global([data-theme='light']) [aria-expanded='true'] button { - background-color: var(--sl-color-gray-5); + :global([data-theme='light']) [aria-expanded='true'] button { + background-color: var(--sl-color-gray-5); + } } </style> <style is:global> - [data-mobile-menu-expanded] { - overflow: hidden; - } - - @media (min-width: 50rem) { + @layer starlight.core { [data-mobile-menu-expanded] { - overflow: auto; + overflow: hidden; + } + + @media (min-width: 50rem) { + [data-mobile-menu-expanded] { + overflow: auto; + } } } </style> diff --git a/packages/starlight/components/MobileTableOfContents.astro b/packages/starlight/components/MobileTableOfContents.astro new file mode 100644 index 00000000000..13c4f8657b0 --- /dev/null +++ b/packages/starlight/components/MobileTableOfContents.astro @@ -0,0 +1,151 @@ +--- +import Icon from '../user-components/Icon.astro'; +import TableOfContentsList from './TableOfContents/TableOfContentsList.astro'; + +const { toc } = Astro.locals.starlightRoute; +--- + +{ + toc && ( + <mobile-starlight-toc data-min-h={toc.minHeadingLevel} data-max-h={toc.maxHeadingLevel}> + <nav aria-labelledby="starlight__on-this-page--mobile"> + <details id="starlight__mobile-toc"> + <summary id="starlight__on-this-page--mobile" class="sl-flex"> + <span class="toggle sl-flex"> + {Astro.locals.t('tableOfContents.onThisPage')} + <Icon name={'right-caret'} class="caret" size="1rem" /> + </span> + <span class="display-current" /> + </summary> + <div class="dropdown"> + <TableOfContentsList toc={toc.items} isMobile /> + </div> + </details> + </nav> + </mobile-starlight-toc> + ) +} + +<style> + @layer starlight.core { + nav { + position: fixed; + z-index: var(--sl-z-index-toc); + top: calc(var(--sl-nav-height) - 1px); + inset-inline: 0; + border-top: 1px solid var(--sl-color-gray-5); + background-color: var(--sl-color-bg-nav); + } + @media (min-width: 50rem) { + nav { + inset-inline-start: var(--sl-content-inline-start, 0); + } + } + + summary { + gap: 0.5rem; + align-items: center; + height: var(--sl-mobile-toc-height); + border-bottom: 1px solid var(--sl-color-hairline-shade); + padding: 0.5rem 1rem; + font-size: var(--sl-text-xs); + outline-offset: var(--sl-outline-offset-inside); + } + summary::marker, + summary::-webkit-details-marker { + display: none; + } + + .toggle { + flex-shrink: 0; + gap: 1rem; + align-items: center; + justify-content: space-between; + border: 1px solid var(--sl-color-gray-5); + border-radius: 0.5rem; + padding-block: 0.5rem; + padding-inline-start: 0.75rem; + padding-inline-end: 0.5rem; + line-height: 1; + background-color: var(--sl-color-black); + user-select: none; + cursor: pointer; + } + details[open] .toggle { + color: var(--sl-color-white); + border-color: var(--sl-color-accent); + } + details .toggle:hover { + color: var(--sl-color-white); + border-color: var(--sl-color-gray-2); + } + + :global([dir='rtl']) .caret { + transform: rotateZ(180deg); + } + details[open] .caret { + transform: rotateZ(90deg); + } + + .display-current { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + color: var(--sl-color-white); + } + + .dropdown { + --border-top: 1px; + margin-top: calc(-1 * var(--border-top)); + border: var(--border-top) solid var(--sl-color-gray-6); + border-top-color: var(--sl-color-hairline-shade); + max-height: calc(85vh - var(--sl-nav-height) - var(--sl-mobile-toc-height)); + overflow-y: auto; + background-color: var(--sl-color-black); + box-shadow: var(--sl-shadow-md); + overscroll-behavior: contain; + } + } +</style> + +<script> + import { StarlightTOC } from './TableOfContents/starlight-toc'; + + class MobileStarlightTOC extends StarlightTOC { + override set current(link: HTMLAnchorElement) { + super.current = link; + const display = this.querySelector('.display-current') as HTMLSpanElement; + if (display) display.textContent = link.textContent; + } + + constructor() { + super(); + const details = this.querySelector('details'); + if (!details) return; + const closeToC = () => { + details.open = false; + }; + // Close the table of contents whenever a link is clicked. + details.querySelectorAll('a').forEach((a) => { + a.addEventListener('click', closeToC); + }); + // Close the table of contents when a user clicks outside of it. + window.addEventListener('click', (e) => { + if (!details.contains(e.target as Node)) closeToC(); + }); + // Or when they press the escape key. + window.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && details.open) { + const hasFocus = details.contains(document.activeElement); + closeToC(); + if (hasFocus) { + const summary = details.querySelector('summary'); + if (summary) summary.focus(); + } + } + }); + } + } + + customElements.define('mobile-starlight-toc', MobileStarlightTOC); +</script> diff --git a/packages/starlight/components/Page.astro b/packages/starlight/components/Page.astro new file mode 100644 index 00000000000..ac8ffbeb171 --- /dev/null +++ b/packages/starlight/components/Page.astro @@ -0,0 +1,126 @@ +--- +// Important that this is the first import so it can override cascade layers order. +import 'virtual:starlight/user-css'; + +// Starlight nested cascade layers definitions which specify the default order of internal layers. +import '../style/layers.css'; + +// Built-in CSS styles. +import '../style/props.css'; +import '../style/reset.css'; +import '../style/asides.css'; +import '../style/util.css'; +import 'virtual:starlight/optional-css'; + +import Banner from 'virtual:starlight/components/Banner'; +import ContentPanel from 'virtual:starlight/components/ContentPanel'; +import FallbackContentNotice from 'virtual:starlight/components/FallbackContentNotice'; +import DraftContentNotice from 'virtual:starlight/components/DraftContentNotice'; +import Footer from 'virtual:starlight/components/Footer'; +import Head from 'virtual:starlight/components/Head'; +import Header from 'virtual:starlight/components/Header'; +import Hero from 'virtual:starlight/components/Hero'; +import MarkdownContent from 'virtual:starlight/components/MarkdownContent'; +import PageFrame from 'virtual:starlight/components/PageFrame'; +import PageSidebar from 'virtual:starlight/components/PageSidebar'; +import PageTitle from 'virtual:starlight/components/PageTitle'; +import Sidebar from 'virtual:starlight/components/Sidebar'; +import SkipLink from 'virtual:starlight/components/SkipLink'; +import ThemeProvider from 'virtual:starlight/components/ThemeProvider'; +import TwoColumnContent from 'virtual:starlight/components/TwoColumnContent'; + +import printHref from '../style/print.css?url&no-inline'; + +const { starlightRoute } = Astro.locals; + +const pagefindEnabled = + starlightRoute.entry.slug !== '404' && + !starlightRoute.entry.slug.endsWith('/404') && + starlightRoute.entry.data.pagefind !== false; + +const htmlDataAttributes: DOMStringMap = { 'data-theme': 'dark' }; +if (Boolean(starlightRoute.toc)) htmlDataAttributes['data-has-toc'] = ''; +if (starlightRoute.hasSidebar) htmlDataAttributes['data-has-sidebar'] = ''; +if (Boolean(starlightRoute.entry.data.hero)) htmlDataAttributes['data-has-hero'] = ''; + +const mainDataAttributes: DOMStringMap = {}; +if (pagefindEnabled) mainDataAttributes['data-pagefind-body'] = ''; +--- + +<html lang={starlightRoute.lang} dir={starlightRoute.dir} {...htmlDataAttributes}> + <head> + <Head /> + <style> + html:not([data-has-toc]) { + --sl-mobile-toc-height: 0rem; + } + html:not([data-has-sidebar]) { + --sl-content-width: 67.5rem; + } + /* Add scroll padding to ensure anchor headings aren't obscured by nav */ + html { + /* Additional padding is needed to account for the mobile TOC */ + scroll-padding-top: calc(1.5rem + var(--sl-nav-height) + var(--sl-mobile-toc-height)); + } + main { + padding: var(--sl-main-pad); + } + @media (min-width: 50em) { + [data-has-sidebar] { + --sl-content-inline-start: var(--sl-sidebar-width); + } + } + @media (min-width: 72em) { + html { + scroll-padding-top: calc(1.5rem + var(--sl-nav-height)); + } + } + </style> + <ThemeProvider /> + <link rel="stylesheet" href={printHref} media="print" /> + </head> + <body> + <SkipLink /> + <PageFrame> + <Header slot="header" /> + {starlightRoute.hasSidebar && <Sidebar slot="sidebar" />} + <script src="./SidebarPersistState"></script> + <TwoColumnContent> + <PageSidebar slot="right-sidebar" /> + <main + {...mainDataAttributes} + lang={starlightRoute.entryMeta.lang} + dir={starlightRoute.entryMeta.dir} + > + {/* TODO: Revisit how this logic flows. */} + <Banner /> + { + starlightRoute.entry.data.hero ? ( + <ContentPanel> + <Hero /> + <MarkdownContent> + <slot /> + </MarkdownContent> + <Footer /> + </ContentPanel> + ) : ( + <> + <ContentPanel> + <PageTitle /> + {starlightRoute.entry.data.draft && <DraftContentNotice />} + {starlightRoute.isFallback && <FallbackContentNotice />} + </ContentPanel> + <ContentPanel> + <MarkdownContent> + <slot /> + </MarkdownContent> + <Footer /> + </ContentPanel> + </> + ) + } + </main> + </TwoColumnContent> + </PageFrame> + </body> +</html> diff --git a/packages/starlight/components/PageFrame.astro b/packages/starlight/components/PageFrame.astro new file mode 100644 index 00000000000..5cfb1162049 --- /dev/null +++ b/packages/starlight/components/PageFrame.astro @@ -0,0 +1,97 @@ +--- +import MobileMenuToggle from 'virtual:starlight/components/MobileMenuToggle'; + +const { hasSidebar } = Astro.locals.starlightRoute; +--- + +<div class="page sl-flex"> + <header class="header"><slot name="header" /></header> + { + hasSidebar && ( + <nav class="sidebar print:hidden" aria-label={Astro.locals.t('sidebarNav.accessibleLabel')}> + <MobileMenuToggle /> + <div id="starlight__sidebar" class="sidebar-pane"> + <div class="sidebar-content sl-flex"> + <slot name="sidebar" /> + </div> + </div> + </nav> + ) + } + <div class="main-frame"><slot /></div> +</div> + +<style> + @layer starlight.core { + .page { + flex-direction: column; + min-height: 100vh; + } + + .header { + z-index: var(--sl-z-index-navbar); + position: fixed; + inset-inline-start: 0; + inset-block-start: 0; + width: 100%; + height: var(--sl-nav-height); + border-bottom: 1px solid var(--sl-color-hairline-shade); + padding: var(--sl-nav-pad-y) var(--sl-nav-pad-x); + padding-inline-end: var(--sl-nav-pad-x); + background-color: var(--sl-color-bg-nav); + } + + :global([data-has-sidebar]) .header { + padding-inline-end: calc( + var(--sl-nav-gap) + var(--sl-nav-pad-x) + var(--sl-menu-button-size) + ); + } + + .sidebar-pane { + visibility: var(--sl-sidebar-visibility, hidden); + position: fixed; + z-index: var(--sl-z-index-menu); + inset-block: var(--sl-nav-height) 0; + inset-inline-start: 0; + width: 100%; + background-color: var(--sl-color-black); + overflow-y: auto; + } + + :global([aria-expanded='true']) ~ .sidebar-pane { + --sl-sidebar-visibility: visible; + } + + .sidebar-content { + height: 100%; + min-height: max-content; + padding: 1rem var(--sl-sidebar-pad-x) 0; + flex-direction: column; + gap: 1rem; + } + + @media (min-width: 50rem) { + .sidebar-content::after { + content: ''; + padding-bottom: 1px; + } + } + + .main-frame { + padding-top: calc(var(--sl-nav-height) + var(--sl-mobile-toc-height)); + padding-inline-start: var(--sl-content-inline-start); + } + + @media (min-width: 50rem) { + :global([data-has-sidebar]) .header { + padding-inline-end: var(--sl-nav-pad-x); + } + .sidebar-pane { + --sl-sidebar-visibility: visible; + width: var(--sl-sidebar-width); + background-color: var(--sl-color-bg-sidebar); + border-inline-end: 1px solid var(--sl-color-hairline-shade); + } + } + } +</style> diff --git a/packages/starlight/components/PageSidebar.astro b/packages/starlight/components/PageSidebar.astro new file mode 100644 index 00000000000..f334621cfc8 --- /dev/null +++ b/packages/starlight/components/PageSidebar.astro @@ -0,0 +1,59 @@ +--- +import MobileTableOfContents from 'virtual:starlight/components/MobileTableOfContents'; +import TableOfContents from 'virtual:starlight/components/TableOfContents'; +--- + +{ + Astro.locals.starlightRoute.toc && ( + <> + <div class="lg:sl-hidden"> + <MobileTableOfContents /> + </div> + <div class="right-sidebar-panel sl-hidden lg:sl-block"> + <div class="sl-container"> + <TableOfContents /> + </div> + </div> + </> + ) +} + +<style> + @layer starlight.core { + .right-sidebar-panel { + padding: 1rem var(--sl-sidebar-pad-x); + } + .sl-container { + width: calc(var(--sl-sidebar-width) - 2 * var(--sl-sidebar-pad-x)); + } + .right-sidebar-panel :global(h2) { + color: var(--sl-color-white); + font-size: var(--sl-text-h5); + font-weight: 600; + line-height: var(--sl-line-height-headings); + margin-bottom: 0.5rem; + } + .right-sidebar-panel :global(:where(a)) { + display: block; + font-size: var(--sl-text-xs); + text-decoration: none; + color: var(--sl-color-gray-3); + overflow-wrap: anywhere; + } + .right-sidebar-panel :global(:where(a):hover) { + color: var(--sl-color-white); + } + @media (min-width: 72rem) { + .sl-container { + max-width: calc( + ( + ( + 100vw - var(--sl-sidebar-width) - 2 * var(--sl-content-pad-x) - 2 * + var(--sl-sidebar-pad-x) + ) * 0.25 /* MAGIC NUMBER 🥲 */ + ) + ); + } + } + } +</style> diff --git a/packages/starlight/components/PageTitle.astro b/packages/starlight/components/PageTitle.astro new file mode 100644 index 00000000000..f8ede6e4484 --- /dev/null +++ b/packages/starlight/components/PageTitle.astro @@ -0,0 +1,17 @@ +--- +import { PAGE_TITLE_ID } from '../constants'; +--- + +<h1 id={PAGE_TITLE_ID}>{Astro.locals.starlightRoute.entry.data.title}</h1> + +<style> + @layer starlight.core { + h1 { + margin-top: 1rem; + font-size: var(--sl-text-h1); + line-height: var(--sl-line-height-headings); + font-weight: 600; + color: var(--sl-color-white); + } + } +</style> diff --git a/packages/starlight/components/Pagination.astro b/packages/starlight/components/Pagination.astro new file mode 100644 index 00000000000..16cddfbf864 --- /dev/null +++ b/packages/starlight/components/Pagination.astro @@ -0,0 +1,79 @@ +--- +import Icon from '../user-components/Icon.astro'; + +const { dir, pagination } = Astro.locals.starlightRoute; +const { prev, next } = pagination; +const isRtl = dir === 'rtl'; +--- + +<div class="pagination-links print:hidden" dir={dir}> + { + prev && ( + <a href={prev.href} rel="prev"> + <Icon name={isRtl ? 'right-arrow' : 'left-arrow'} size="1.5rem" /> + <span> + {Astro.locals.t('page.previousLink')} + <br /> + <span class="link-title">{prev.label}</span> + </span> + </a> + ) + } + { + next && ( + <a href={next.href} rel="next"> + <Icon name={isRtl ? 'left-arrow' : 'right-arrow'} size="1.5rem" /> + <span> + {Astro.locals.t('page.nextLink')} + <br /> + <span class="link-title">{next.label}</span> + </span> + </a> + ) + } +</div> + +<style> + @layer starlight.core { + .pagination-links { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr)); + gap: 1rem; + } + + a { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 0.5rem; + width: 100%; + flex-basis: calc(50% - 0.5rem); + flex-grow: 1; + border: 1px solid var(--sl-color-gray-5); + border-radius: 0.5rem; + padding: 1rem; + text-decoration: none; + color: var(--sl-color-gray-2); + box-shadow: var(--sl-shadow-md); + overflow-wrap: anywhere; + } + [rel='next'] { + justify-content: end; + text-align: end; + flex-direction: row-reverse; + } + a:hover { + border-color: var(--sl-color-gray-2); + } + + .link-title { + color: var(--sl-color-white); + font-size: var(--sl-text-2xl); + line-height: var(--sl-line-height-headings); + } + + svg { + flex-shrink: 0; + } + } +</style> diff --git a/packages/starlight/components/PrevNextLinks.astro b/packages/starlight/components/PrevNextLinks.astro deleted file mode 100644 index d18f1557f07..00000000000 --- a/packages/starlight/components/PrevNextLinks.astro +++ /dev/null @@ -1,80 +0,0 @@ ---- -import type { Link } from '../utils/navigation'; -import { useTranslations } from '../utils/translations'; -import Icon from '../user-components/Icon.astro'; - -interface Props { - prev: Link | undefined; - next: Link | undefined; - dir: 'ltr' | 'rtl'; - locale: string | undefined; -} - -const { prev, next, dir, locale } = Astro.props; -const isRtl = dir === 'rtl'; -const t = useTranslations(locale); ---- - -<div class="pagination-links sl-flex" dir={dir}> - { - prev && ( - <a href={prev.href} rel="prev"> - <Icon name={isRtl ? 'right-arrow' : 'left-arrow'} size="1.5rem" /> - <span> - {t('page.previousLink')} - <br /> - <span class="link-title">{prev.label}</span> - </span> - </a> - ) - } - { - next && ( - <a href={next.href} rel="next"> - <Icon name={isRtl ? 'left-arrow' : 'right-arrow'} size="1.5rem" /> - <span> - {t('page.nextLink')} - <br /> - <span class="link-title">{next.label}</span> - </span> - </a> - ) - } -</div> - -<style> - .pagination-links { - flex-wrap: wrap; - gap: 1rem; - } - - a { - display: flex; - align-items: center; - justify-content: flex-start; - gap: 0.5rem; - width: 100%; - flex-basis: calc(50% - 0.5rem); - flex-grow: 1; - border: 1px solid var(--sl-color-gray-5); - border-radius: 0.5rem; - padding: 1rem; - text-decoration: none; - color: var(--sl-color-gray-2); - box-shadow: var(--sl-shadow-md); - } - [rel='next'] { - justify-content: end; - text-align: end; - flex-direction: row-reverse; - } - a:hover { - border-color: var(--sl-color-gray-2); - } - - .link-title { - color: var(--sl-color-white); - font-size: var(--sl-text-2xl); - line-height: var(--sl-line-height-headings); - } -</style> diff --git a/packages/starlight/components/RightSidebar.astro b/packages/starlight/components/RightSidebar.astro deleted file mode 100644 index 142a7f0f511..00000000000 --- a/packages/starlight/components/RightSidebar.astro +++ /dev/null @@ -1,36 +0,0 @@ ---- -import type { MarkdownHeading } from 'astro'; -import RightSidebarPanel from './RightSidebarPanel.astro'; -import MobileTableOfContents from './TableOfContents/MobileTableOfContents.astro'; -import TableOfContents from './TableOfContents.astro'; -import { generateToC } from './TableOfContents/generateToC'; -import { useTranslations } from '../utils/translations'; - -interface Props { - headings: MarkdownHeading[]; - locale: string | undefined; - tocConfig: { maxHeadingLevel: number; minHeadingLevel: number } | false; -} - -const { headings, locale, tocConfig } = Astro.props; -const t = useTranslations(locale); -const tocProps = tocConfig && { - ...tocConfig, - locale, - toc: generateToC(headings, { - ...tocConfig, - title: t('tableOfContents.overview'), - }), -}; ---- - -{ - tocProps && ( - <> - <MobileTableOfContents {...tocProps} /> - <RightSidebarPanel> - <TableOfContents {...tocProps} /> - </RightSidebarPanel> - </> - ) -} diff --git a/packages/starlight/components/RightSidebarPanel.astro b/packages/starlight/components/RightSidebarPanel.astro deleted file mode 100644 index 8c79694ffd3..00000000000 --- a/packages/starlight/components/RightSidebarPanel.astro +++ /dev/null @@ -1,46 +0,0 @@ -<div class="right-sidebar-panel sl-hidden lg:sl-block"> - <div class="sl-container"> - <slot /> - </div> -</div> - -<style> - .right-sidebar-panel { - padding: 1rem var(--sl-sidebar-pad-x); - } - .right-sidebar-panel + .right-sidebar-panel { - border-top: 1px solid var(--sl-color-hairline); - } - .sl-container { - width: calc(var(--sl-sidebar-width) - 2 * var(--sl-sidebar-pad-x)); - } - .right-sidebar-panel :global(h2) { - color: var(--sl-color-white); - font-size: var(--sl-text-h5); - font-weight: 600; - line-height: var(--sl-line-height-headings); - margin-bottom: 0.5rem; - } - .right-sidebar-panel :global(a) { - display: block; - font-size: var(--sl-text-xs); - text-decoration: none; - color: var(--sl-color-gray-3); - word-break: break-word; - } - .right-sidebar-panel :global(a:hover) { - color: var(--sl-color-white); - } - @media (min-width: 72rem) { - .sl-container { - max-width: calc( - ( - ( - 100vw - var(--sl-sidebar-width) - 2 * var(--sl-content-pad-x) - 2 * - var(--sl-sidebar-pad-x) - ) * 0.25 /* MAGIC NUMBER 🥲 */ - ) - ); - } - } -</style> diff --git a/packages/starlight/components/Search.astro b/packages/starlight/components/Search.astro index 89c2bed0e9b..d8c80d82699 100644 --- a/packages/starlight/components/Search.astro +++ b/packages/starlight/components/Search.astro @@ -1,43 +1,46 @@ --- -import '@pagefind/default-ui/css/ui.css'; -import { useTranslations } from '../utils/translations'; import Icon from '../user-components/Icon.astro'; +import project from 'virtual:starlight/project-context'; -interface Props { - locale: string | undefined; -} - -const t = useTranslations(Astro.props.locale); const pagefindTranslations = { - placeholder: t('search.label'), + placeholder: Astro.locals.t('search.label'), ...Object.fromEntries( - Object.entries(t.pick('pagefind.')).map(([key, value]) => [key.replace('pagefind.', ''), value]) + Object.entries(Astro.locals.t.all()) + .filter(([key]) => key.startsWith('pagefind.')) + .map(([key, value]) => [key.replace('pagefind.', ''), value]) ), }; + +const dataAttributes: DOMStringMap = { 'data-translations': JSON.stringify(pagefindTranslations) }; +if (project.trailingSlash === 'never') dataAttributes['data-strip-trailing-slash'] = ''; --- -<site-search data-translations={JSON.stringify(pagefindTranslations)}> - <button data-open-modal disabled> - { - /* The span is `aria-hidden` because it is not shown on small screens. Instead, the icon label is used for accessibility purposes. */ - } - <Icon name="magnifier" label={t('search.label')} /> - <span class="sl-hidden md:sl-block" aria-hidden="true">{t('search.label')}</span> - <Icon name="forward-slash" class="sl-hidden md:sl-block" label={t('search.shortcutLabel')} /> +<site-search class={Astro.props.class} {...dataAttributes}> + <button + data-open-modal + disabled + aria-label={Astro.locals.t('search.label')} + aria-keyshortcuts="Control+K" + > + <Icon name="magnifier" /> + <span class="sl-hidden md:sl-block" aria-hidden="true">{Astro.locals.t('search.label')}</span> + <kbd class="sl-hidden md:sl-flex" style="display: none;"> + <kbd>{Astro.locals.t('search.ctrlKey')}</kbd><kbd>K</kbd> + </kbd> </button> - <dialog style="padding:0" aria-label={t('search.label')}> + <dialog style="padding:0" aria-label={Astro.locals.t('search.label')}> <div class="dialog-frame sl-flex"> { /* TODO: Make the layout of this button flexible to accommodate different word lengths. Currently hard-coded for English: “Cancel” */ } <button data-close-modal class="sl-flex md:sl-hidden"> - {t('search.cancelLabel')} + {Astro.locals.t('search.cancelLabel')} </button> { import.meta.env.DEV ? ( <div style="margin: auto; text-align: center; white-space: pre-line;" dir="ltr"> - <p>{t('search.devWarning')}</p> + <p>{Astro.locals.t('search.devWarning')}</p> </div> ) : ( <div class="search-container"> @@ -49,7 +52,30 @@ const pagefindTranslations = { </dialog> </site-search> +{ + /** + * This is intentionally inlined to avoid briefly showing an invalid shortcut. + * Purposely using the deprecated `navigator.platform` property to detect Apple devices, as the + * user agent is spoofed by some browsers when opening the devtools. + */ +} +<script is:inline> + (() => { + const openBtn = document.querySelector('button[data-open-modal]'); + const shortcut = openBtn?.querySelector('kbd'); + if (!openBtn || !(shortcut instanceof HTMLElement)) return; + const platformKey = shortcut.querySelector('kbd'); + if (platformKey && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)) { + platformKey.textContent = '⌘'; + openBtn.setAttribute('aria-keyshortcuts', 'Meta+K'); + } + shortcut.style.display = ''; + })(); +</script> + <script> + import { pagefindUserConfig } from 'virtual:starlight/pagefind-config'; + class SiteSearch extends HTMLElement { constructor() { super(); @@ -89,17 +115,11 @@ const pagefindTranslations = { window.removeEventListener('click', onClick); }); - // Listen for `/` and `cmd + k` keyboard shortcuts. + // Listen for `ctrl + k` and `cmd + k` keyboard shortcuts. window.addEventListener('keydown', (e) => { - const isInput = - document.activeElement && - ['input', 'select', 'textarea'].includes(document.activeElement.tagName.toLowerCase()); - if (e.metaKey === true && e.key === 'k') { + if ((e.metaKey === true || e.ctrlKey === true) && e.key === 'k') { dialog.open ? closeModal() : openModal(); e.preventDefault(); - } else if (e.key === '/' && !dialog.open && !isInput) { - openModal(); - e.preventDefault(); } }); @@ -108,18 +128,31 @@ const pagefindTranslations = { translations = JSON.parse(this.dataset.translations || '{}'); } catch {} + const shouldStrip = this.dataset.stripTrailingSlash !== undefined; + const stripTrailingSlash = (path: string) => path.replace(/(.)\/(#.*)?$/, '$1$2'); + const formatURL = shouldStrip ? stripTrailingSlash : (path: string) => path; + window.addEventListener('DOMContentLoaded', () => { if (import.meta.env.DEV) return; const onIdle = window.requestIdleCallback || ((cb) => setTimeout(cb, 1)); onIdle(async () => { + // @ts-expect-error — Missing types for @pagefind/default-ui package. const { PagefindUI } = await import('@pagefind/default-ui'); new PagefindUI({ + ...pagefindUserConfig, element: '#starlight__search', baseUrl: import.meta.env.BASE_URL, bundlePath: import.meta.env.BASE_URL.replace(/\/$/, '') + '/pagefind/', showImages: false, translations, showSubResults: true, + processResult: (result: { url: string; sub_results: Array<{ url: string }> }) => { + result.url = formatURL(result.url); + result.sub_results = result.sub_results.map((sub_result) => { + sub_result.url = formatURL(sub_result.url); + return sub_result; + }); + }, }); }); }); @@ -129,288 +162,327 @@ const pagefindTranslations = { </script> <style> - button[data-open-modal] { - display: flex; - align-items: center; - gap: 0.5rem; - border: 0; - background-color: transparent; - color: var(--sl-color-gray-1); - cursor: pointer; - height: 2.5rem; - font-size: var(--sl-text-xl); - } - - @media (min-width: 50rem) { + @layer starlight.core { + site-search { + display: contents; + } button[data-open-modal] { - border: 1px solid var(--sl-color-gray-5); - border-radius: 0.5rem; - padding-inline-start: 0.75rem; - padding-inline-end: 1rem; - background-color: var(--sl-color-black); - color: var(--sl-color-gray-2); - font-size: var(--sl-text-sm); - width: 100%; - max-width: 22rem; + display: flex; + align-items: center; + gap: 0.5rem; + border: 0; + background-color: transparent; + color: var(--sl-color-gray-1); + cursor: pointer; + height: 2.5rem; + font-size: var(--sl-text-xl); } - button[data-open-modal]:hover { - border-color: var(--sl-color-gray-2); - color: var(--sl-color-white); + + @media (min-width: 50rem) { + button[data-open-modal] { + border: 1px solid var(--sl-color-gray-5); + border-radius: 0.5rem; + padding-inline-start: 0.75rem; + padding-inline-end: 0.5rem; + background-color: var(--sl-color-black); + color: var(--sl-color-gray-2); + font-size: var(--sl-text-sm); + width: 100%; + max-width: 22rem; + } + button[data-open-modal]:hover { + border-color: var(--sl-color-gray-2); + color: var(--sl-color-white); + } + + button[data-open-modal] > :last-child { + margin-inline-start: auto; + } } - button[data-open-modal] > :last-child { - margin-inline-start: auto; + button > kbd { + border-radius: 0.25rem; + font-size: var(--sl-text-2xs); + gap: 0.25em; + padding-inline: 0.375rem; + background-color: var(--sl-color-gray-6); } - } - dialog { - margin: 0; - background-color: var(--sl-color-gray-6); - border: 1px solid var(--sl-color-gray-5); - width: 100%; - max-width: 100%; - height: 100%; - max-height: 100%; - box-shadow: var(--sl-shadow-lg); - } - dialog[open] { - display: grid; - } + kbd { + font-family: var(--__sl-font); + } - dialog::backdrop { - background-color: var(--sl-color-backdrop-overlay); - -webkit-backdrop-filter: blur(0.25rem); - backdrop-filter: blur(0.25rem); - } + dialog { + margin: 0; + background-color: var(--sl-color-gray-6); + border: 1px solid var(--sl-color-gray-5); + width: 100%; + max-width: 100%; + height: 100%; + max-height: 100%; + box-shadow: var(--sl-shadow-lg); + } + dialog[open] { + display: flex; + } - .dialog-frame { - flex-direction: column; - gap: 1rem; - padding: 1rem; - } + dialog::backdrop { + background-color: var(--sl-color-backdrop-overlay); + -webkit-backdrop-filter: blur(0.25rem); + backdrop-filter: blur(0.25rem); + } - button[data-close-modal] { - position: absolute; - z-index: 1; - align-items: center; - align-self: flex-end; - height: calc(64px * var(--pagefind-ui-scale)); - padding: 0.25rem; - border: 0; - background: transparent; - cursor: pointer; - color: var(--sl-color-text-accent); - } + .dialog-frame { + position: relative; + overflow: auto; + flex-direction: column; + flex-grow: 1; + gap: 1rem; + padding: 1rem; + } - #starlight__search { - --pagefind-ui-primary: var(--sl-color-accent-light); - --pagefind-ui-text: var(--sl-color-gray-2); - --pagefind-ui-font: var(--__sl-font); - --pagefind-ui-background: var(--sl-color-black); - --pagefind-ui-border: var(--sl-color-gray-5); - --pagefind-ui-border-width: 1px; - --sl-search-cancel-space: 5rem; - } + button[data-close-modal] { + position: absolute; + z-index: 1; + align-items: center; + align-self: flex-end; + height: calc(64px * var(--pagefind-ui-scale)); + padding: 0.25rem; + border: 0; + background: transparent; + cursor: pointer; + color: var(--sl-color-text-accent); + } - @media (min-width: 50rem) { #starlight__search { - --sl-search-cancel-space: 0px; + --pagefind-ui-primary: var(--sl-color-text); + --pagefind-ui-text: var(--sl-color-gray-2); + --pagefind-ui-font: var(--__sl-font); + --pagefind-ui-background: var(--sl-color-black); + --pagefind-ui-border: var(--sl-color-gray-5); + --pagefind-ui-border-width: 1px; + --pagefind-ui-tag: var(--sl-color-gray-5); + --sl-search-cancel-space: 5rem; } - dialog { - margin: 4rem auto auto; - border-radius: 0.5rem; - width: 90%; - max-width: 40rem; - height: max-content; - min-height: 15rem; - max-height: calc(100% - 8rem); + :root[data-theme='light'] #starlight__search { + --pagefind-ui-tag: var(--sl-color-gray-6); } - .dialog-frame { - padding: 1.5rem; + @media (min-width: 50rem) { + #starlight__search { + --sl-search-cancel-space: 0px; + } + + dialog { + margin: 4rem auto auto; + border-radius: 0.5rem; + width: 90%; + max-width: 40rem; + height: max-content; + min-height: 15rem; + max-height: calc(100% - 8rem); + } + + .dialog-frame { + padding: 1.5rem; + } } } </style> <style is:global> - [data-search-modal-open] { - overflow: hidden; - } + @import url('@pagefind/default-ui/css/ui.css') layer(starlight.core); - #starlight__search { - --sl-search-result-spacing: calc(1.25rem * var(--pagefind-ui-scale)); - --sl-search-result-pad-inline-start: calc(3.75rem * var(--pagefind-ui-scale)); - --sl-search-result-pad-inline-end: calc(1.25rem * var(--pagefind-ui-scale)); - --sl-search-result-pad-block: calc(0.9375rem * var(--pagefind-ui-scale)); - --sl-search-result-nested-pad-block: calc(0.625rem * var(--pagefind-ui-scale)); - --sl-search-corners: calc(0.3125rem * var(--pagefind-ui-scale)); - --sl-search-page-icon-size: calc(1.875rem * var(--pagefind-ui-scale)); - --sl-search-page-icon-inline-start: calc( - (var(--sl-search-result-pad-inline-start) - var(--sl-search-page-icon-size)) / 2 - ); - --sl-search-tree-diagram-size: calc(2.5rem * var(--pagefind-ui-scale)); - --sl-search-tree-diagram-inline-start: calc( - (var(--sl-search-result-pad-inline-start) - var(--sl-search-tree-diagram-size)) / 2 - ); - } + @layer starlight.core { + [data-search-modal-open] { + overflow: hidden; + } - #starlight__search .pagefind-ui__form::before { - --pagefind-ui-text: var(--sl-color-gray-1); - opacity: 1; - } + #starlight__search { + --sl-search-result-spacing: calc(1.25rem * var(--pagefind-ui-scale)); + --sl-search-result-pad-inline-start: calc(3.75rem * var(--pagefind-ui-scale)); + --sl-search-result-pad-inline-end: calc(1.25rem * var(--pagefind-ui-scale)); + --sl-search-result-pad-block: calc(0.9375rem * var(--pagefind-ui-scale)); + --sl-search-result-nested-pad-block: calc(0.625rem * var(--pagefind-ui-scale)); + --sl-search-corners: calc(0.3125rem * var(--pagefind-ui-scale)); + --sl-search-page-icon-size: calc(1.875rem * var(--pagefind-ui-scale)); + --sl-search-page-icon-inline-start: calc( + (var(--sl-search-result-pad-inline-start) - var(--sl-search-page-icon-size)) / 2 + ); + --sl-search-tree-diagram-size: calc(2.5rem * var(--pagefind-ui-scale)); + --sl-search-tree-diagram-inline-start: calc( + (var(--sl-search-result-pad-inline-start) - var(--sl-search-tree-diagram-size)) / 2 + ); + } - #starlight__search .pagefind-ui__search-input { - color: var(--sl-color-white); - font-weight: 400; - width: calc(100% - var(--sl-search-cancel-space)); - } + #starlight__search .pagefind-ui__form::before { + --pagefind-ui-text: var(--sl-color-gray-1); + opacity: 1; + } - #starlight__search input:focus { - --pagefind-ui-border: var(--sl-color-accent); - } + #starlight__search .pagefind-ui__search-input { + color: var(--sl-color-white); + font-weight: 400; + width: calc(100% - var(--sl-search-cancel-space)); + } - #starlight__search .pagefind-ui__search-clear { - inset-inline-end: var(--sl-search-cancel-space); - width: calc(60px * var(--pagefind-ui-scale)); - padding: 0; - background-color: transparent; - overflow: hidden; - } - #starlight__search .pagefind-ui__search-clear:focus { - outline: 1px solid var(--sl-color-accent); - } - #starlight__search .pagefind-ui__search-clear::before { - content: ''; - -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m13.41 12 6.3-6.29a1 1 0 1 0-1.42-1.42L12 10.59l-6.29-6.3a1 1 0 0 0-1.42 1.42l6.3 6.29-6.3 6.29a1 1 0 0 0 .33 1.64 1 1 0 0 0 1.09-.22l6.29-6.3 6.29 6.3a1 1 0 0 0 1.64-.33 1 1 0 0 0-.22-1.09L13.41 12Z'/%3E%3C/svg%3E") - center / 50% no-repeat; - mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m13.41 12 6.3-6.29a1 1 0 1 0-1.42-1.42L12 10.59l-6.29-6.3a1 1 0 0 0-1.42 1.42l6.3 6.29-6.3 6.29a1 1 0 0 0 .33 1.64 1 1 0 0 0 1.09-.22l6.29-6.3 6.29 6.3a1 1 0 0 0 1.64-.33 1 1 0 0 0-.22-1.09L13.41 12Z'/%3E%3C/svg%3E") - center / 50% no-repeat; - background-color: var(--sl-color-text-accent); - display: block; - width: 100%; - height: 100%; - } + #starlight__search input:focus { + --pagefind-ui-border: var(--sl-color-accent); + } - #starlight__search .pagefind-ui__results > * + * { - margin-top: var(--sl-search-result-spacing); - } - #starlight__search .pagefind-ui__result { - border: 0; - padding: 0; - } + #starlight__search .pagefind-ui__search-clear { + inset-inline-end: var(--sl-search-cancel-space); + width: calc(60px * var(--pagefind-ui-scale)); + padding: 0; + background-color: transparent; + overflow: hidden; + } + #starlight__search .pagefind-ui__search-clear:focus { + outline: 1px solid var(--sl-color-accent); + } + #starlight__search .pagefind-ui__search-clear::before { + content: ''; + -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m13.41 12 6.3-6.29a1 1 0 1 0-1.42-1.42L12 10.59l-6.29-6.3a1 1 0 0 0-1.42 1.42l6.3 6.29-6.3 6.29a1 1 0 0 0 .33 1.64 1 1 0 0 0 1.09-.22l6.29-6.3 6.29 6.3a1 1 0 0 0 1.64-.33 1 1 0 0 0-.22-1.09L13.41 12Z'/%3E%3C/svg%3E") + center / 50% no-repeat; + mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m13.41 12 6.3-6.29a1 1 0 1 0-1.42-1.42L12 10.59l-6.29-6.3a1 1 0 0 0-1.42 1.42l6.3 6.29-6.3 6.29a1 1 0 0 0 .33 1.64 1 1 0 0 0 1.09-.22l6.29-6.3 6.29 6.3a1 1 0 0 0 1.64-.33 1 1 0 0 0-.22-1.09L13.41 12Z'/%3E%3C/svg%3E") + center / 50% no-repeat; + background-color: var(--sl-color-text-accent); + display: block; + width: 100%; + height: 100%; + } - #starlight__search .pagefind-ui__result-nested { - position: relative; - padding: var(--sl-search-result-nested-pad-block) var(--sl-search-result-pad-inline-end); - padding-inline-start: var(--sl-search-result-pad-inline-start); - } + #starlight__search .pagefind-ui__results > * + * { + margin-top: var(--sl-search-result-spacing); + } + #starlight__search .pagefind-ui__result { + border: 0; + padding: 0; + } - #starlight__search .pagefind-ui__result-title:not(:where(.pagefind-ui__result-nested *)), - #starlight__search .pagefind-ui__result-nested { - position: relative; - background-color: var(--sl-color-black); - } + #starlight__search .pagefind-ui__result-nested { + position: relative; + padding: var(--sl-search-result-nested-pad-block) var(--sl-search-result-pad-inline-end); + padding-inline-start: var(--sl-search-result-pad-inline-start); + } - #starlight__search .pagefind-ui__result-title:not(:where(.pagefind-ui__result-nested *)):hover, - #starlight__search - .pagefind-ui__result-title:not(:where(.pagefind-ui__result-nested *)):focus-within, - #starlight__search .pagefind-ui__result-nested:hover, - #starlight__search .pagefind-ui__result-nested:focus-within { - outline: 1px solid var(--sl-color-accent-high); - } + #starlight__search .pagefind-ui__result-title:not(:where(.pagefind-ui__result-nested *)), + #starlight__search .pagefind-ui__result-nested { + position: relative; + background-color: var(--sl-color-black); + } - #starlight__search - .pagefind-ui__result-title:not(:where(.pagefind-ui__result-nested *)):focus-within, - #starlight__search .pagefind-ui__result-nested:focus-within { - background-color: var(--sl-color-accent-low); - } + #starlight__search .pagefind-ui__result-title:not(:where(.pagefind-ui__result-nested *)):hover, + #starlight__search + .pagefind-ui__result-title:not(:where(.pagefind-ui__result-nested *)):focus-within, + #starlight__search .pagefind-ui__result-nested:hover, + #starlight__search .pagefind-ui__result-nested:focus-within { + outline: 1px solid var(--sl-color-accent-high); + } - #starlight__search .pagefind-ui__result-thumb, - #starlight__search .pagefind-ui__result-inner { - margin-top: 0; - } + #starlight__search + .pagefind-ui__result-title:not(:where(.pagefind-ui__result-nested *)):focus-within, + #starlight__search .pagefind-ui__result-nested:focus-within { + background-color: var(--sl-color-accent-low); + } - #starlight__search .pagefind-ui__result-inner > :first-child { - border-radius: var(--sl-search-corners) var(--sl-search-corners) 0 0; - } - #starlight__search .pagefind-ui__result-inner > :last-child { - border-radius: 0 0 var(--sl-search-corners) var(--sl-search-corners); - } + #starlight__search .pagefind-ui__result-thumb, + #starlight__search .pagefind-ui__result-inner { + margin-top: 0; + } - #starlight__search .pagefind-ui__result-inner > .pagefind-ui__result-title { - padding: var(--sl-search-result-pad-block) var(--sl-search-result-pad-inline-end); - padding-inline-start: var(--sl-search-result-pad-inline-start); - } - #starlight__search .pagefind-ui__result-inner > .pagefind-ui__result-title::before { - content: ''; - position: absolute; - inset-block: 0; - inset-inline-start: var(--sl-search-page-icon-inline-start); - width: var(--sl-search-page-icon-size); - background: var(--sl-color-gray-3); - -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") - center no-repeat; - 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") - center no-repeat; - } + #starlight__search .pagefind-ui__result-inner > :first-child { + border-radius: var(--sl-search-corners) var(--sl-search-corners) 0 0; + } + #starlight__search .pagefind-ui__result-inner > :last-child { + border-radius: 0 0 var(--sl-search-corners) var(--sl-search-corners); + } - #starlight__search .pagefind-ui__result-inner { - align-items: stretch; - gap: 1px; - } + #starlight__search .pagefind-ui__result-inner > .pagefind-ui__result-title { + padding: var(--sl-search-result-pad-block) var(--sl-search-result-pad-inline-end); + padding-inline-start: var(--sl-search-result-pad-inline-start); + } + #starlight__search .pagefind-ui__result-inner > .pagefind-ui__result-title::before { + content: ''; + position: absolute; + inset-block: 0; + inset-inline-start: var(--sl-search-page-icon-inline-start); + width: var(--sl-search-page-icon-size); + background: var(--sl-color-gray-3); + -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") + center no-repeat; + 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") + center no-repeat; + } - #starlight__search .pagefind-ui__result-link { - position: unset; - --pagefind-ui-text: var(--sl-color-white); - font-weight: 600; - } + #starlight__search .pagefind-ui__result-inner { + align-items: stretch; + gap: 1px; + } - #starlight__search .pagefind-ui__result-link:hover { - text-decoration: none; - } + #starlight__search .pagefind-ui__result-link { + position: unset; + --pagefind-ui-text: var(--sl-color-white); + font-weight: 600; + } - #starlight__search .pagefind-ui__result-nested .pagefind-ui__result-link::before { - content: unset; - } + #starlight__search .pagefind-ui__result-link:hover { + text-decoration: none; + } - #starlight__search .pagefind-ui__result-nested::before { - content: ''; - position: absolute; - inset-block: 0; - inset-inline-start: var(--sl-search-tree-diagram-inline-start); - width: var(--sl-search-tree-diagram-size); - background: var(--sl-color-gray-4); - -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") - 0% 0% / 100% no-repeat; - 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") - 0% 0% / 100% no-repeat; - } - #starlight__search .pagefind-ui__result-nested:last-child::before { - -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"); - 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"); - } + #starlight__search .pagefind-ui__result-nested .pagefind-ui__result-link::before { + content: unset; + } - /* Flip page and tree icons around the vertical axis when in an RTL layout. */ - [dir='rtl'] .pagefind-ui__result-title::before, - [dir='rtl'] .pagefind-ui__result-nested::before { - transform: matrix(-1, 0, 0, 1, 0, 0); - } + #starlight__search .pagefind-ui__result-nested::before { + content: ''; + position: absolute; + inset-block: 0; + inset-inline-start: var(--sl-search-tree-diagram-inline-start); + width: var(--sl-search-tree-diagram-size); + background: var(--sl-color-gray-4); + -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") + 0% 0% / 100% no-repeat; + 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") + 0% 0% / 100% no-repeat; + } + #starlight__search .pagefind-ui__result-nested:last-of-type::before { + -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"); + 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"); + } - #starlight__search .pagefind-ui__result-link::after { - content: ''; - position: absolute; - inset: 0; - } + /* Flip page and tree icons around the vertical axis when in an RTL layout. */ + [dir='rtl'] .pagefind-ui__result-title::before, + [dir='rtl'] .pagefind-ui__result-nested::before { + transform: matrix(-1, 0, 0, 1, 0, 0); + } - #starlight__search .pagefind-ui__result-excerpt { - font-size: calc(1rem * var(--pagefind-ui-scale)); - word-break: break-word; - } + #starlight__search .pagefind-ui__result-link::after { + content: ''; + position: absolute; + inset: 0; + } + + #starlight__search .pagefind-ui__result-excerpt { + font-size: calc(1rem * var(--pagefind-ui-scale)); + overflow-wrap: anywhere; + } - #starlight__search mark { - color: var(--sl-color-gray-2); - background-color: transparent; - font-weight: 600; + #starlight__search mark { + color: var(--sl-color-gray-2); + background-color: transparent; + font-weight: 600; + } + + #starlight__search .pagefind-ui__filter-value::before { + border-color: var(--sl-color-text-invert); + } + + #starlight__search .pagefind-ui__result-tags { + background-color: var(--sl-color-black); + margin-top: 0; + padding: var(--sl-search-result-nested-pad-block) var(--sl-search-result-pad-inline-end); + } } </style> diff --git a/packages/starlight/components/Select.astro b/packages/starlight/components/Select.astro index 0975a678939..a77cb295a07 100644 --- a/packages/starlight/components/Select.astro +++ b/packages/starlight/components/Select.astro @@ -3,7 +3,6 @@ import Icon from '../user-components/Icon.astro'; interface Props { label: string; - value: string; icon: Parameters<typeof Icon>[0]['name']; width?: string; options: Array<{ @@ -12,12 +11,21 @@ interface Props { selected: boolean; }>; } + +/** + * The `autocomplete="off"` attribute is used to prevent the browser from automatically selecting a + * value for this input, e.g. based on the user's previous selections, as this could lead to + * incorrect values being selected for example when the user switches between languages and uses + * the back button. + * Note that this attribute is only useful when a value is not restored at a later stage, e.g. the + * bfcache that ignores this attribute when restoring the value. + */ --- <label style={`--sl-select-width: ${Astro.props.width}`}> <span class="sr-only">{Astro.props.label}</span> <Icon name={Astro.props.icon} class="icon label-icon" /> - <select value={Astro.props.value}> + <select autocomplete="off"> { Astro.props.options.map(({ value, selected, label }) => ( <option value={value} selected={selected} set:html={label} /> @@ -28,57 +36,64 @@ interface Props { </label> <style> - label { - --sl-label-icon-size: 0.875rem; - --sl-caret-size: 1.25rem; - position: relative; - display: flex; - align-items: center; - gap: 0.25rem; - color: var(--sl-color-gray-1); - } + @layer starlight.core { + label { + --sl-label-icon-size: 0.875rem; + --sl-caret-size: 1.25rem; + --sl-inline-padding: 0.5rem; + position: relative; + display: flex; + align-items: center; + gap: 0.25rem; + color: var(--sl-color-gray-1); + } - label:hover { - color: var(--sl-color-gray-2); - } + label:hover { + color: var(--sl-color-gray-2); + } - .icon { - position: absolute; - top: 50%; - transform: translateY(-50%); - pointer-events: none; - } + .icon { + position: absolute; + top: 50%; + transform: translateY(-50%); + pointer-events: none; + } - .label-icon { - font-size: var(--sl-label-icon-size); - inset-inline-start: 0; - } + select { + border: 0; + padding-block: 0.625rem; + padding-inline: calc(var(--sl-label-icon-size) + var(--sl-inline-padding) + 0.25rem) + calc(var(--sl-caret-size) + var(--sl-inline-padding) + 0.25rem); + margin-inline: calc(var(--sl-inline-padding) * -1); + width: calc(var(--sl-select-width) + var(--sl-inline-padding) * 2); + background-color: transparent; + text-overflow: ellipsis; + color: inherit; + cursor: pointer; + appearance: none; + } - .caret { - font-size: var(--sl-caret-size); - inset-inline-end: 0; - } + option { + background-color: var(--sl-color-bg-nav); + color: var(--sl-color-gray-1); + } - select { - border: 0; - padding-block: 0.625rem; - padding-inline: calc(var(--sl-label-icon-size) + 0.25rem) calc(var(--sl-caret-size) + 0.25rem); - width: var(--sl-select-width); - background-color: transparent; - text-overflow: ellipsis; - color: inherit; - cursor: pointer; - appearance: none; + @media (min-width: 50rem) { + select { + font-size: var(--sl-text-sm); + } + } } - option { - background-color: var(--sl-color-bg-nav); - color: var(--sl-color-gray-1); - } + @layer starlight.components { + .label-icon { + font-size: var(--sl-label-icon-size); + inset-inline-start: 0; + } - @media (min-width: 50rem) { - select { - font-size: var(--sl-text-sm); + .caret { + font-size: var(--sl-caret-size); + inset-inline-end: 0; } } </style> diff --git a/packages/starlight/components/Sidebar.astro b/packages/starlight/components/Sidebar.astro index 7b898e91f18..570c5827897 100644 --- a/packages/starlight/components/Sidebar.astro +++ b/packages/starlight/components/Sidebar.astro @@ -1,42 +1,15 @@ --- -import type { getSidebar } from '../utils/navigation'; -import LanguageSelect from './LanguageSelect.astro'; +import MobileMenuFooter from 'virtual:starlight/components/MobileMenuFooter'; +import SidebarPersister from './SidebarPersister.astro'; import SidebarSublist from './SidebarSublist.astro'; -import ThemeSelect from './ThemeSelect.astro'; -interface Props { - sidebar: ReturnType<typeof getSidebar>; - locale: string | undefined; -} - -const { sidebar, locale } = Astro.props; +const { sidebar } = Astro.locals.starlightRoute; --- -<div class="sidebar sl-flex"> +<SidebarPersister> <SidebarSublist sublist={sidebar} /> - <div class="mobile-preferences sl-flex md:sl-hidden"> - <ThemeSelect {locale} /> - <LanguageSelect {locale} /> - </div> -</div> - -<style> - .sidebar { - height: 100%; - padding: 1rem var(--sl-sidebar-pad-x); - flex-direction: column; - gap: 1rem; - } +</SidebarPersister> - .mobile-preferences { - justify-content: space-between; - border-top: 1px solid var(--sl-color-gray-6); - padding: 0.5rem 0; - } - - @media (min-width: 50rem) { - .sidebar > :global(:nth-last-child(2)) { - padding-bottom: 1rem; - } - } -</style> +<div class="md:sl-hidden"> + <MobileMenuFooter /> +</div> diff --git a/packages/starlight/components/SidebarPersistState.ts b/packages/starlight/components/SidebarPersistState.ts new file mode 100644 index 00000000000..9ab665bf2c6 --- /dev/null +++ b/packages/starlight/components/SidebarPersistState.ts @@ -0,0 +1,72 @@ +// Collect required elements from the DOM. +const scroller = document.getElementById('starlight__sidebar'); +const target = scroller?.querySelector<HTMLElement>('sl-sidebar-state-persist'); + +/** Starlight uses this key to store sidebar state in `sessionStorage`. */ +const storageKey = 'sl-sidebar-state'; + +/** The shape used to persist sidebar state across a user’s session. */ +interface SidebarState { + hash: string; + open: Array<boolean | null>; + scroll: number; +} + +/** + * Get the current sidebar state. + * + * The `open` state is loaded from session storage when the sidebar hashes match, while `scroll` + * and `hash` are read from the current page. + */ +const getState = (): SidebarState => { + let open: SidebarState['open'] = []; + const hash = target?.dataset.hash || ''; + try { + const rawStoredState = sessionStorage.getItem(storageKey); + const storedState = JSON.parse(rawStoredState || '{}') as SidebarState; + if (Array.isArray(storedState.open) && storedState.hash === hash) open = storedState.open; + } catch {} + return { + hash, + open, + scroll: scroller?.scrollTop || 0, + }; +}; + +/** Store the passed sidebar state in session storage. */ +const storeState = (state: SidebarState): void => { + try { + sessionStorage.setItem(storageKey, JSON.stringify(state)); + } catch {} +}; + +/** Updates sidebar state in session storage without modifying `open` state. */ +const updateState = (): void => storeState(getState()); + +/** Updates sidebar state in session storage to include a new value for a specific `<details>` element. */ +const setToggleState = (open: boolean, detailsIndex: number): void => { + const state = getState(); + state.open[detailsIndex] = open; + storeState(state); +}; + +// Store the current `open` state whenever a user interacts with one of the `<details>` groups. +target?.addEventListener('click', (event) => { + if (!(event.target instanceof Element)) return; + // Query for the nearest `<summary>` and then its parent `<details>`. + // This excludes clicks outside of the `<summary>`, which don’t trigger toggles. + const toggledDetails = event.target.closest('summary')?.closest('details'); + if (!toggledDetails) return; + const restoreElement = toggledDetails.querySelector<HTMLElement>('sl-sidebar-restore'); + const index = parseInt(restoreElement?.dataset.index || ''); + if (isNaN(index)) return; + setToggleState(!toggledDetails.open, index); +}); + +// Store sidebar state before navigating. These will also store it on tab blur etc., +// but avoid using the `beforeunload` event, which can cause issues with back/forward cache +// on some browsers. +addEventListener('visibilitychange', () => { + if (document.visibilityState === 'hidden') updateState(); +}); +addEventListener('pageHide', updateState); diff --git a/packages/starlight/components/SidebarPersister.astro b/packages/starlight/components/SidebarPersister.astro new file mode 100644 index 00000000000..ee1c838a4a1 --- /dev/null +++ b/packages/starlight/components/SidebarPersister.astro @@ -0,0 +1,78 @@ +--- +/* + This component is designed to wrap the tree of `<SidebarSublist>` components in the sidebar. + + It does the following: + - Wraps the tree in an `<sl-sidebar-state-persist>` custom element + - Before the tree renders, adds an inline script which loads state and defines + the behaviour for the `<sl-sidebar-restore>` custom element. + - After the tree renders, adds an inline script which restores the sidebar scroll state. + + Notes: + - On smaller viewports, restoring state is skipped as the sidebar is collapsed inside a menu. + - The state is parsed from session storage and restored. + - This is a progressive enhancement, so any errors are swallowed silently. + + The `aria-hidden` attribute on script tags is used to prevent a Safari/VoiceOver bug where the + script is read out loud due to them being inside a container with `display: contents`. + @see https://bugs.webkit.org/show_bug.cgi?id=283645 + @see https://github.com/withastro/starlight/pull/2633 +*/ + +import { getSidebarHash } from '../utils/navigation'; + +const hash = getSidebarHash(Astro.locals.starlightRoute.sidebar); + +declare global { + interface Window { + /** Restored scroll position. Briefly stored on the `window` global to pass between inline scripts. */ + _starlightScrollRestore?: number; + } +} +--- + +<sl-sidebar-state-persist data-hash={hash}> + <script is:inline aria-hidden="true"> + (() => { + try { + if (!matchMedia('(min-width: 50em)').matches) return; + /** @type {HTMLElement | null} */ + const target = document.querySelector('sl-sidebar-state-persist'); + const state = JSON.parse(sessionStorage.getItem('sl-sidebar-state') || '0'); + if (!target || !state || target.dataset.hash !== state.hash) return; + window._starlightScrollRestore = state.scroll; + customElements.define( + 'sl-sidebar-restore', + class SidebarRestore extends HTMLElement { + connectedCallback() { + try { + const idx = parseInt(this.dataset.index || ''); + const details = this.closest('details'); + if (details && typeof state.open[idx] === 'boolean') details.open = state.open[idx]; + } catch {} + } + } + ); + } catch {} + })(); + </script> + + <slot /> + + <script is:inline aria-hidden="true"> + (() => { + const scroller = document.getElementById('starlight__sidebar'); + if (!window._starlightScrollRestore || !scroller) return; + scroller.scrollTop = window._starlightScrollRestore; + delete window._starlightScrollRestore; + })(); + </script> +</sl-sidebar-state-persist> + +<style> + @layer starlight.core { + sl-sidebar-state-persist { + display: contents; + } + } +</style> diff --git a/packages/starlight/components/SidebarRestorePoint.astro b/packages/starlight/components/SidebarRestorePoint.astro new file mode 100644 index 00000000000..5da9b8b202d --- /dev/null +++ b/packages/starlight/components/SidebarRestorePoint.astro @@ -0,0 +1,12 @@ +--- +/** Unique symbol for storing a running index in `locals`. */ +const currentGroupIndexSymbol = Symbol.for('starlight-sidebar-group-index'); +const locals = Astro.locals as App.Locals & { [currentGroupIndexSymbol]: number }; + +/** The current sidebar group’s index retrieved from `locals` if set, starting at `0`. */ +const index = locals[currentGroupIndexSymbol] || 0; +// Increment the index for the next instance. +locals[currentGroupIndexSymbol] = index + 1; +--- + +<sl-sidebar-restore data-index={index}></sl-sidebar-restore> diff --git a/packages/starlight/components/SidebarSublist.astro b/packages/starlight/components/SidebarSublist.astro index c1049febb6c..457ab20fd35 100644 --- a/packages/starlight/components/SidebarSublist.astro +++ b/packages/starlight/components/SidebarSublist.astro @@ -1,33 +1,36 @@ --- -import { flattenSidebar, type SidebarEntry } from '../utils/navigation'; +import { flattenSidebar } from '../utils/navigation'; +import type { SidebarEntry } from '../utils/routing/types'; import Icon from '../user-components/Icon.astro'; -import Badge from './Badge.astro'; +import Badge from '../user-components/Badge.astro'; +import SidebarRestorePoint from './SidebarRestorePoint.astro'; interface Props { sublist: SidebarEntry[]; nested?: boolean; } + +const { sublist, nested } = Astro.props; --- -<ul class:list={{ 'top-level': !Astro.props.nested }}> +<ul class:list={{ 'top-level': !nested }}> { - Astro.props.sublist.map((entry) => ( + sublist.map((entry) => ( <li> {entry.type === 'link' ? ( <a href={entry.href} - aria-current={entry.isCurrent && 'page'} - class:list={{ large: !Astro.props.nested }} + aria-current={entry.isCurrent ? 'page' : undefined} + class:list={[{ large: !nested }, entry.attrs.class]} + {...entry.attrs} > <span>{entry.label}</span> {entry.badge && ( - <> - {' '} - <Badge - text={entry.badge.text} - variant={entry.isCurrent ? 'outline' : entry.badge.variant} - /> - </> + <Badge + variant={entry.badge.variant} + class={entry.badge.class} + text={entry.badge.text} + /> )} </a> ) : ( @@ -35,9 +38,19 @@ interface Props { open={flattenSidebar(entry.entries).some((i) => i.isCurrent) || !entry.collapsed} > <summary> - <h2 class="large">{entry.label}</h2> + <span class="group-label"> + <span class="large">{entry.label}</span> + {entry.badge && ( + <Badge + variant={entry.badge.variant} + class={entry.badge.class} + text={entry.badge.text} + /> + )} + </span> <Icon name="right-caret" class="caret" size="1.25rem" /> </summary> + <SidebarRestorePoint /> <Astro.self sublist={entry.entries} nested /> </details> )} @@ -47,86 +60,95 @@ interface Props { </ul> <style> - ul { - --sl-sidebar-item-padding-inline: 0.5rem; - list-style: none; - padding: 0; - } - - ul ul li { - margin-inline-start: var(--sl-sidebar-item-padding-inline); - border-inline-start: 1px solid var(--sl-color-hairline-light); - padding-inline-start: var(--sl-sidebar-item-padding-inline); - } + @layer starlight.core { + ul { + --sl-sidebar-item-padding-inline: 0.5rem; + list-style: none; + padding: 0; + } - .large { - font-size: var(--sl-text-lg); - font-weight: 600; - color: var(--sl-color-white); - } + li { + overflow-wrap: anywhere; + } - .top-level > li + li { - margin-top: 0.75rem; - } + ul ul li { + margin-inline-start: var(--sl-sidebar-item-padding-inline); + border-inline-start: 1px solid var(--sl-color-hairline-light); + padding-inline-start: var(--sl-sidebar-item-padding-inline); + } - summary { - display: flex; - align-items: center; - justify-content: space-between; - padding-inline: var(--sl-sidebar-item-padding-inline); - cursor: pointer; - user-select: none; - } - summary::marker, - summary::-webkit-details-marker { - display: none; - } + .large { + font-size: var(--sl-text-lg); + font-weight: 600; + color: var(--sl-color-white); + } - .caret { - transition: transform 0.2s ease-in-out; - } - :global([dir='rtl']) .caret { - transform: rotateZ(180deg); - } - [open] > summary .caret { - transform: rotateZ(90deg); - } + .top-level > li + li { + margin-top: 0.75rem; + } - a { - display: block; - border-radius: 0.25rem; - text-decoration: none; - color: var(--sl-color-gray-2); - padding: 0.3em var(--sl-sidebar-item-padding-inline); - line-height: 1.4; - } + summary { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.2em var(--sl-sidebar-item-padding-inline); + line-height: 1.4; + cursor: pointer; + user-select: none; + } + summary::marker, + summary::-webkit-details-marker { + display: none; + } - a:hover, - a:focus { - color: var(--sl-color-white); - } + .caret { + transition: transform 0.2s ease-in-out; + flex-shrink: 0; + } + :global([dir='rtl']) .caret { + transform: rotateZ(180deg); + } + [open] > summary .caret { + transform: rotateZ(90deg); + } - [aria-current='page'], - [aria-current='page']:hover, - [aria-current='page']:focus { - font-weight: 600; - color: var(--sl-color-text-invert); - background-color: var(--sl-color-text-accent); - } + a { + display: block; + border-radius: 0.25rem; + text-decoration: none; + color: var(--sl-color-gray-2); + padding: 0.3em var(--sl-sidebar-item-padding-inline); + line-height: 1.4; + } - a > *:not(:last-child) { - margin-inline-end: 0.25em; - } + a:hover, + a:focus { + color: var(--sl-color-white); + } - @media (min-width: 50rem) { - .top-level > li + li { - margin-top: 0.5rem; + [aria-current='page'], + [aria-current='page']:hover, + [aria-current='page']:focus { + font-weight: 600; + color: var(--sl-color-text-invert); + background-color: var(--sl-color-text-accent); } - .large { - font-size: var(--sl-text-base); + + a > *:not(:last-child), + .group-label > *:not(:last-child) { + margin-inline-end: 0.25em; } - a { - font-size: var(--sl-text-sm); + + @media (min-width: 50rem) { + .top-level > li + li { + margin-top: 0.5rem; + } + .large { + font-size: var(--sl-text-base); + } + a { + font-size: var(--sl-text-sm); + } } } </style> diff --git a/packages/starlight/components/SiteTitle.astro b/packages/starlight/components/SiteTitle.astro index b4cf4c9064d..6f1405cb143 100644 --- a/packages/starlight/components/SiteTitle.astro +++ b/packages/starlight/components/SiteTitle.astro @@ -1,37 +1,15 @@ --- import { logos } from 'virtual:starlight/user-images'; import config from 'virtual:starlight/user-config'; -import { pathWithBase } from '../utils/base'; - -interface Props { - locale: string | undefined; -} - -if (config.logo) { - let err: string | undefined; - if ('src' in config.logo) { - if (!logos.dark || !logos.light) { - err = `Could not resolve logo import for "${config.logo.src}" (logo.src)`; - } - } else { - if (!logos.dark) { - err = `Could not resolve logo import for "${config.logo.dark}" (logo.dark)`; - } else if (!logos.light) { - err = `Could not resolve logo import for "${config.logo.light}" (logo.light)`; - } - } - if (err) throw new Error(err); -} - -const href = pathWithBase(Astro.props.locale || '/'); +const { siteTitle, siteTitleHref } = Astro.locals.starlightRoute; --- -<a {href} class="site-title sl-flex"> +<a href={siteTitleHref} class="site-title sl-flex"> { config.logo && logos.dark && ( <> <img - class:list={{ 'dark-only': !('src' in config.logo) }} + class:list={{ 'light:sl-hidden print:hidden': !('src' in config.logo) }} alt={config.logo.alt} src={logos.dark.src} width={logos.dark.width} @@ -40,7 +18,7 @@ const href = pathWithBase(Astro.props.locale || '/'); {/* Show light alternate if a user configure both light and dark logos. */} {!('src' in config.logo) && ( <img - class="light-only" + class="dark:sl-hidden print:block" alt={config.logo.alt} src={logos.light?.src} width={logos.light?.width} @@ -50,35 +28,32 @@ const href = pathWithBase(Astro.props.locale || '/'); </> ) } - <span class:list={{ 'sr-only': config.logo?.replacesTitle }}> - {config.title} + <span class:list={{ 'sr-only': config.logo?.replacesTitle }} translate="no"> + {siteTitle} </span> </a> <style> - .site-title { - justify-self: flex-start; - max-width: 100%; - overflow: hidden; - align-items: center; - gap: var(--sl-nav-gap); - font-size: var(--sl-text-h4); - font-weight: 600; - color: var(--sl-color-text-accent); - text-decoration: none; - white-space: nowrap; - } - img { - height: calc(var(--sl-nav-height) - 2 * var(--sl-nav-pad-y)); - width: auto; - max-width: 100%; - object-fit: contain; - object-position: 0 50%; - } - :global([data-theme='light']) .dark-only { - display: none; - } - :global([data-theme='dark']) .light-only { - display: none; + @layer starlight.core { + .site-title { + align-items: center; + gap: var(--sl-nav-gap); + font-size: var(--sl-text-h4); + font-weight: 600; + color: var(--sl-color-text-accent); + text-decoration: none; + white-space: nowrap; + min-width: 0; + } + span { + overflow: hidden; + } + img { + height: calc(var(--sl-nav-height) - 2 * var(--sl-nav-pad-y)); + width: auto; + max-width: 100%; + object-fit: contain; + object-position: 0 50%; + } } </style> diff --git a/packages/starlight/components/SkipLink.astro b/packages/starlight/components/SkipLink.astro index 3363dbe894f..9bbd9af33f5 100644 --- a/packages/starlight/components/SkipLink.astro +++ b/packages/starlight/components/SkipLink.astro @@ -1,30 +1,26 @@ --- -import { useTranslations } from '../utils/translations'; - -interface Props { - locale: string | undefined; -} - -const t = useTranslations(Astro.props.locale); +import { PAGE_TITLE_ID } from '../constants'; --- -<a href="#_top">{t('skipLink.label')}</a> +<a href={`#${PAGE_TITLE_ID}`}>{Astro.locals.t('skipLink.label')}</a> <style> - a { - clip: rect(0, 0, 0, 0); - position: fixed; - top: 0.75rem; - inset-inline-start: 0.75rem; - } - a:focus { - clip: unset; - z-index: var(--sl-z-index-skiplink); - display: block; - padding: 0.5rem 1rem; - text-decoration: none; - color: var(--sl-color-text-invert); - background-color: var(--sl-color-text-accent); - box-shadow: var(--sl-shadow-lg); + @layer starlight.core { + a { + clip: rect(0, 0, 0, 0); + position: fixed; + top: 0.75rem; + inset-inline-start: 0.75rem; + } + a:focus { + clip: unset; + z-index: var(--sl-z-index-skiplink); + display: block; + padding: 0.5rem 1rem; + text-decoration: none; + color: var(--sl-color-text-invert); + background-color: var(--sl-color-text-accent); + box-shadow: var(--sl-shadow-lg); + } } </style> diff --git a/packages/starlight/components/SocialIcons.astro b/packages/starlight/components/SocialIcons.astro index 2a42e71f797..77e9fad7b3d 100644 --- a/packages/starlight/components/SocialIcons.astro +++ b/packages/starlight/components/SocialIcons.astro @@ -2,56 +2,31 @@ import config from 'virtual:starlight/user-config'; import Icon from '../user-components/Icon.astro'; -type Platform = keyof NonNullable<typeof config.social>; - -const labels: Record<Platform, string> = { - github: 'GitHub', - gitlab: 'GitLab', - bitbucket: 'Bitbucket', - discord: 'Discord', - gitter: 'Gitter', - twitter: 'Twitter', - mastodon: 'Mastodon', - codeberg: 'Codeberg', - codePen: 'CodePen', - youtube: 'YouTube', - threads: 'Threads', - linkedin: 'LinkedIn', - twitch: 'Twitch', - microsoftTeams: 'Microsoft Teams', - instagram: 'Instagram', - stackOverflow: 'Stack Overflow', -}; - -const links = Object.entries(config.social || {}).filter(([, url]) => Boolean(url)) as [ - platform: Platform, - url: string, -][]; +const links = config.social || []; --- { links.length > 0 && ( <> - {links.map(([platform, url]) => ( - <a href={url} rel="me" class="sl-flex"> - <span class="sr-only">{labels[platform]}</span> - <Icon name={platform} /> + {links.map(({ label, href, icon }) => ( + <a {href} rel="me" class="sl-flex"> + <span class="sr-only">{label}</span> + <Icon name={icon} /> </a> ))} - <div class="divider" /> </> ) } <style> - a { - color: var(--sl-color-text-accent); - } - a:hover { - opacity: 0.66; - } - .divider { - height: 2rem; - border-inline-end: 1px solid var(--sl-color-gray-5); + @layer starlight.core { + a { + color: var(--sl-color-text-accent); + padding: 0.5em; + margin: -0.5em; + } + a:hover { + opacity: 0.66; + } } </style> diff --git a/packages/starlight/components/StarlightPage.astro b/packages/starlight/components/StarlightPage.astro new file mode 100644 index 00000000000..e92408fb0ab --- /dev/null +++ b/packages/starlight/components/StarlightPage.astro @@ -0,0 +1,17 @@ +--- +import { attachRouteDataAndRunMiddleware } from '../utils/routing/middleware'; +import { + generateStarlightPageRouteData, + type StarlightPageProps as Props, +} from '../utils/starlight-page'; +import Page from './Page.astro'; + +export type StarlightPageProps = Props; + +await attachRouteDataAndRunMiddleware( + Astro, + await generateStarlightPageRouteData({ props: Astro.props, context: Astro }) +); +--- + +<Page><slot /></Page> diff --git a/packages/starlight/components/TableOfContents.astro b/packages/starlight/components/TableOfContents.astro index 570305af936..0d507a70d40 100644 --- a/packages/starlight/components/TableOfContents.astro +++ b/packages/starlight/components/TableOfContents.astro @@ -1,24 +1,18 @@ --- -import { useTranslations } from '../utils/translations'; import TableOfContentsList from './TableOfContents/TableOfContentsList.astro'; -import type { TocItem } from './TableOfContents/generateToC'; -interface Props { - toc: TocItem[]; - locale: string | undefined; - maxHeadingLevel: number; - minHeadingLevel: number; -} - -const { locale, toc, maxHeadingLevel, minHeadingLevel } = Astro.props; -const t = useTranslations(locale); +const { toc } = Astro.locals.starlightRoute; --- -<starlight-toc data-min-h={minHeadingLevel} data-max-h={maxHeadingLevel}> - <nav aria-labelledby="starlight__on-this-page"> - <h2 id="starlight__on-this-page">{t('tableOfContents.onThisPage')}</h2> - <TableOfContentsList {toc} /> - </nav> -</starlight-toc> +{ + toc && ( + <starlight-toc data-min-h={toc.minHeadingLevel} data-max-h={toc.maxHeadingLevel}> + <nav aria-labelledby="starlight__on-this-page"> + <h2 id="starlight__on-this-page">{Astro.locals.t('tableOfContents.onThisPage')}</h2> + <TableOfContentsList toc={toc.items} /> + </nav> + </starlight-toc> + ) +} <script src="./TableOfContents/starlight-toc"></script> diff --git a/packages/starlight/components/TableOfContents/MobileTableOfContents.astro b/packages/starlight/components/TableOfContents/MobileTableOfContents.astro deleted file mode 100644 index 34fe1d5e19a..00000000000 --- a/packages/starlight/components/TableOfContents/MobileTableOfContents.astro +++ /dev/null @@ -1,154 +0,0 @@ ---- -import { useTranslations } from '../../utils/translations'; -import Icon from '../../user-components/Icon.astro'; -import TableOfContentsList from './TableOfContentsList.astro'; -import type { TocItem } from './generateToC'; - -interface Props { - toc: TocItem[]; - locale: string | undefined; - maxHeadingLevel: number; - minHeadingLevel: number; -} - -const { locale, toc, maxHeadingLevel, minHeadingLevel } = Astro.props; -const t = useTranslations(locale); ---- - -<mobile-starlight-toc data-min-h={minHeadingLevel} data-max-h={maxHeadingLevel}> - <nav aria-labelledby="starlight__on-this-page--mobile" class="lg:sl-hidden"> - <details id="starlight__mobile-toc"> - <summary id="starlight__on-this-page--mobile" class="sl-flex"> - <div class="toggle sl-flex"> - {t('tableOfContents.onThisPage')} - <Icon name={'right-caret'} class="caret" size="1rem" /> - </div> - <span class="display-current">{toc[0]?.text}</span> - </summary> - <div class="dropdown"> - <TableOfContentsList toc={toc} isMobile /> - </div> - </details> - </nav> -</mobile-starlight-toc> - -<style> - nav { - position: fixed; - z-index: var(--sl-z-index-toc); - top: calc(var(--sl-nav-height) - 1px); - inset-inline: 0; - border-top: 1px solid var(--sl-color-gray-5); - background-color: var(--sl-color-bg-nav); - } - @media (min-width: 50rem) { - nav { - inset-inline-start: var(--sl-content-inline-start, 0); - } - } - - summary { - gap: 0.5rem; - align-items: center; - height: var(--sl-mobile-toc-height); - border-bottom: 1px solid var(--sl-color-hairline-shade); - padding: 0.5rem 1rem; - font-size: var(--sl-text-xs); - outline-offset: var(--sl-outline-offset-inside); - } - summary::marker, - summary::-webkit-details-marker { - display: none; - } - - .toggle { - flex-shrink: 0; - gap: 1rem; - align-items: center; - justify-content: space-between; - border: 1px solid var(--sl-color-gray-5); - border-radius: 0.5rem; - padding-block: 0.5rem; - padding-inline-start: 0.75rem; - padding-inline-end: 0.5rem; - line-height: 1; - background-color: var(--sl-color-black); - user-select: none; - cursor: pointer; - } - details[open] .toggle { - color: var(--sl-color-white); - border-color: var(--sl-color-accent); - } - details .toggle:hover { - color: var(--sl-color-white); - border-color: var(--sl-color-gray-2); - } - - :global([dir='rtl']) .caret { - transform: rotateZ(180deg); - } - details[open] .caret { - transform: rotateZ(90deg); - } - - .display-current { - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - color: var(--sl-color-white); - } - - .dropdown { - --border-top: 1px; - margin-top: calc(-1 * var(--border-top)); - border: var(--border-top) solid var(--sl-color-gray-6); - border-top-color: var(--sl-color-hairline-shade); - max-height: calc(85vh - var(--sl-nav-height) - var(--sl-mobile-toc-height)); - overflow-y: auto; - background-color: var(--sl-color-black); - box-shadow: var(--sl-shadow-md); - } -</style> - -<script> - import { StarlightTOC } from './starlight-toc'; - - class MobileStarlightTOC extends StarlightTOC { - override set current(link: HTMLAnchorElement) { - super.current = link; - const display = this.querySelector('.display-current') as HTMLSpanElement; - if (display) display.textContent = link.textContent; - } - - constructor() { - super(); - const details = this.querySelector('details'); - if (!details) return; - const closeToC = () => { - details.open = false; - }; - // Close the table of contents whenever a link is clicked. - details.querySelectorAll('a').forEach((a) => { - a.addEventListener('click', closeToC); - }); - // Close the table of contents when a user clicks outside of it. - window.addEventListener('click', (e) => { - if (!details.contains(e.target as Node)) closeToC(); - }); - // Or when they press the escape key. - window.addEventListener('keydown', (e) => { - if (e.key === 'Escape' && details.open) { - const hasFocus = details.contains(document.activeElement); - closeToC(); - if (hasFocus) { - const summary = details.querySelector('summary'); - if (summary) summary.focus(); - } - } - }); - } - } - - customElements.define('mobile-starlight-toc', MobileStarlightTOC); -</script> diff --git a/packages/starlight/components/TableOfContents/TableOfContentsList.astro b/packages/starlight/components/TableOfContents/TableOfContentsList.astro index 7c290a1ef23..8cac910ce1b 100644 --- a/packages/starlight/components/TableOfContents/TableOfContentsList.astro +++ b/packages/starlight/components/TableOfContents/TableOfContentsList.astro @@ -1,5 +1,5 @@ --- -import type { TocItem } from './generateToC'; +import type { TocItem } from '../../utils/generateToC'; interface Props { toc: TocItem[]; @@ -26,56 +26,54 @@ const { toc, isMobile = false, depth = 0 } = Astro.props; </ul> <style define:vars={{ depth }}> - ul { - padding: 0; - list-style: none; - } - a { - --pad-inline: 0.5rem; - display: block; - border-radius: 0.25rem; - padding-block: 0.25rem; - padding-inline: calc(1rem * var(--depth) + var(--pad-inline)) var(--pad-inline); - line-height: 1.25; - } - a[aria-current='true'], - a[aria-current='true']:hover, - a[aria-current='true']:focus { - font-weight: 600; - color: var(--sl-color-text-invert); - background-color: var(--sl-color-text-accent); - } - .isMobile a { - --pad-inline: 1rem; - display: flex; - justify-content: space-between; - gap: var(--pad-inline); - border-top: 1px solid var(--sl-color-gray-6); - border-radius: 0; - padding-block: 0.5rem; - color: var(--sl-color-text); - font-size: var(--sl-text-sm); - text-decoration: none; - outline-offset: var(--sl-outline-offset-inside); - } - .isMobile:first-child > li:first-child > a { - border-top: 0; - } - .isMobile a[aria-current='true'], - .isMobile a[aria-current='true']:hover, - .isMobile a[aria-current='true']:focus { - color: var(--sl-color-white); - background-color: unset; - } - .isMobile a[aria-current='true']::after { - content: ''; - width: 1rem; - background-color: var(--sl-color-text-accent); - /* Check mark SVG icon */ - -webkit-mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCAxNCAxNCc+PHBhdGggZD0nTTEwLjkxNCA0LjIwNmEuNTgzLjU4MyAwIDAgMC0uODI4IDBMNS43NCA4LjU1NyAzLjkxNCA2LjcyNmEuNTk2LjU5NiAwIDAgMC0uODI4Ljg1N2wyLjI0IDIuMjRhLjU4My41ODMgMCAwIDAgLjgyOCAwbDQuNzYtNC43NmEuNTgzLjU4MyAwIDAgMCAwLS44NTdaJy8+PC9zdmc+Cg=='); - mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCAxNCAxNCc+PHBhdGggZD0nTTEwLjkxNCA0LjIwNmEuNTgzLjU4MyAwIDAgMC0uODI4IDBMNS43NCA4LjU1NyAzLjkxNCA2LjcyNmEuNTk2LjU5NiAwIDAgMC0uODI4Ljg1N2wyLjI0IDIuMjRhLjU4My41ODMgMCAwIDAgLjgyOCAwbDQuNzYtNC43NmEuNTgzLjU4MyAwIDAgMCAwLS44NTdaJy8+PC9zdmc+Cg=='); - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - flex-shrink: 0; + @layer starlight.core { + ul { + padding: 0; + list-style: none; + } + a { + --pad-inline: 0.5rem; + display: block; + border-radius: 0.25rem; + padding-block: 0.25rem; + padding-inline: calc(1rem * var(--depth) + var(--pad-inline)) var(--pad-inline); + line-height: 1.25; + } + a[aria-current='true'] { + color: var(--sl-color-text-accent); + } + .isMobile a { + --pad-inline: 1rem; + display: flex; + justify-content: space-between; + gap: var(--pad-inline); + border-top: 1px solid var(--sl-color-gray-6); + border-radius: 0; + padding-block: 0.5rem; + color: var(--sl-color-text); + font-size: var(--sl-text-sm); + text-decoration: none; + outline-offset: var(--sl-outline-offset-inside); + } + .isMobile:first-child > li:first-child > a { + border-top: 0; + } + .isMobile a[aria-current='true'], + .isMobile a[aria-current='true']:hover, + .isMobile a[aria-current='true']:focus { + color: var(--sl-color-white); + background-color: unset; + } + .isMobile a[aria-current='true']::after { + content: ''; + width: 1rem; + background-color: var(--sl-color-text-accent); + /* Check mark SVG icon */ + -webkit-mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCAxNCAxNCc+PHBhdGggZD0nTTEwLjkxNCA0LjIwNmEuNTgzLjU4MyAwIDAgMC0uODI4IDBMNS43NCA4LjU1NyAzLjkxNCA2LjcyNmEuNTk2LjU5NiAwIDAgMC0uODI4Ljg1N2wyLjI0IDIuMjRhLjU4My41ODMgMCAwIDAgLjgyOCAwbDQuNzYtNC43NmEuNTgzLjU4MyAwIDAgMCAwLS44NTdaJy8+PC9zdmc+Cg=='); + mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCAxNCAxNCc+PHBhdGggZD0nTTEwLjkxNCA0LjIwNmEuNTgzLjU4MyAwIDAgMC0uODI4IDBMNS43NCA4LjU1NyAzLjkxNCA2LjcyNmEuNTk2LjU5NiAwIDAgMC0uODI4Ljg1N2wyLjI0IDIuMjRhLjU4My41ODMgMCAwIDAgLjgyOCAwbDQuNzYtNC43NmEuNTgzLjU4MyAwIDAgMCAwLS44NTdaJy8+PC9zdmc+Cg=='); + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + flex-shrink: 0; + } } </style> diff --git a/packages/starlight/components/TableOfContents/starlight-toc.ts b/packages/starlight/components/TableOfContents/starlight-toc.ts index 4283f36168d..415c5cf93a2 100644 --- a/packages/starlight/components/TableOfContents/starlight-toc.ts +++ b/packages/starlight/components/TableOfContents/starlight-toc.ts @@ -1,8 +1,18 @@ +import { PAGE_TITLE_ID } from '../../constants'; + export class StarlightTOC extends HTMLElement { - private _current = this.querySelector('a[aria-current="true"]') as HTMLAnchorElement | null; + private _current = this.querySelector<HTMLAnchorElement>('a[aria-current="true"]'); private minH = parseInt(this.dataset.minH || '2', 10); private maxH = parseInt(this.dataset.maxH || '3', 10); + /** + * CSS selector string that matches only headings that can appear in the table of contents. + * Generates a selector like `h1#_top,:where(h2,h3)[id]`. + */ + private tocHeadingSelector = + `h1#${PAGE_TITLE_ID},` + + `:where(${[...Array.from({ length: 1 + this.maxH - this.minH }).map((_, index) => `h${this.minH + index}`)].join()})[id]`; + protected set current(link: HTMLAnchorElement) { if (link === this._current) return; if (this._current) this._current.removeAttribute('aria-current'); @@ -10,33 +20,35 @@ export class StarlightTOC extends HTMLElement { this._current = link; } + private onIdle = (cb: IdleRequestCallback) => + (window.requestIdleCallback || ((cb) => setTimeout(cb, 1)))(cb); + constructor() { super(); + this.onIdle(() => this.init()); + } + private init = (): void => { /** All the links in the table of contents. */ const links = [...this.querySelectorAll('a')]; /** Test if an element is a table-of-contents heading. */ - const isHeading = (el: Element): el is HTMLHeadingElement => { - if (el instanceof HTMLHeadingElement) { - // Special case for page title h1 - if ('pageTitle' in el.dataset) return true; - // Check the heading level is within the user-configured limits for the ToC - const level = el.tagName[1]; - if (level) { - const int = parseInt(level, 10); - if (int >= this.minH && int <= this.maxH) return true; - } - } - return false; - }; + const isHeading = (el: Element): el is HTMLHeadingElement => + el.matches(this.tocHeadingSelector); /** Walk up the DOM to find the nearest heading. */ const getElementHeading = (el: Element | null): HTMLHeadingElement | null => { if (!el) return null; const origin = el; while (el) { + // Short circuit if we reach the top-level content container or one of the other containers in main. + if (el.matches('.sl-markdown-content, main > *')) { + return document.getElementById(PAGE_TITLE_ID) as HTMLHeadingElement; + } if (isHeading(el)) return el; + // Find the first heading that is a child of this element, and return it if there is one. + const childHeading = el.querySelector<HTMLHeadingElement>(this.tocHeadingSelector); + if (childHeading) return childHeading; // Assign the previous sibling’s last, most deeply nested child to el. el = el.previousElementSibling; while (el?.lastElementChild) { @@ -64,28 +76,40 @@ export class StarlightTOC extends HTMLElement { } }; - // Observe elements with an `id` (most likely headings) and their siblings. - // Also observe direct children of `.content` to include elements before - // the first heading. - const toObserve = document.querySelectorAll('main [id], main [id] ~ *, main .content > *'); + // Observe the following elements: + // - headings that appear in the table of contents + // - siblings of those headings or of the `.sl-heading-wrapper` added by Starlight’s anchor links feature + // - direct children of `.sl-markdown-content` to include elements before the first subheading + // - direct children of `main` that don’t include headings (mainly to target Starlight’s banner) + // Ignore any elements that themselves contain a table-of-contents heading, as we are already observing those children. + const toObserve = document.querySelectorAll( + [ + `main :where(${this.tocHeadingSelector})`, + `main :where(${this.tocHeadingSelector}, .sl-heading-wrapper) ~ *:not(:has(${this.tocHeadingSelector}))`, + `main .sl-markdown-content > *:not(:has(${this.tocHeadingSelector}))`, + `main > *:not(:has(${this.tocHeadingSelector}))`, + ].join() + ); let observer: IntersectionObserver | undefined; const observe = () => { - if (observer) observer.disconnect(); + if (observer) return; observer = new IntersectionObserver(setCurrent, { rootMargin: this.getRootMargin() }); toObserve.forEach((h) => observer!.observe(h)); }; observe(); - const onIdle = window.requestIdleCallback || ((cb) => setTimeout(cb, 1)); let timeout: NodeJS.Timeout; window.addEventListener('resize', () => { // Disable intersection observer while window is resizing. - if (observer) observer.disconnect(); + if (observer) { + observer.disconnect(); + observer = undefined; + } clearTimeout(timeout); - timeout = setTimeout(() => onIdle(observe), 200); + timeout = setTimeout(() => this.onIdle(observe), 200); }); - } + }; private getRootMargin(): `-${number}px 0% ${number}px` { const navBarHeight = document.querySelector('header')?.getBoundingClientRect().height || 0; @@ -93,8 +117,8 @@ export class StarlightTOC extends HTMLElement { const mobileTocHeight = this.querySelector('summary')?.getBoundingClientRect().height || 0; /** Start intersections at nav height + 2rem padding. */ const top = navBarHeight + mobileTocHeight + 32; - /** End intersections 1.5rem later. */ - const bottom = top + 24; + /** End intersections `53px` later. This is slightly more than the maximum `margin-top` in Markdown content. */ + const bottom = top + 53; const height = document.documentElement.clientHeight; return `-${top}px 0% ${bottom - height}px`; } diff --git a/packages/starlight/components/ThemeSelect.astro b/packages/starlight/components/ThemeSelect.astro index 0146e09e8a3..a7cd175a1ca 100644 --- a/packages/starlight/components/ThemeSelect.astro +++ b/packages/starlight/components/ThemeSelect.astro @@ -1,24 +1,16 @@ --- -import { useTranslations } from '../utils/translations'; import Select from './Select.astro'; - -interface Props { - locale: string | undefined; -} - -const t = useTranslations(Astro.props.locale); --- <starlight-theme-select> {/* TODO: Can we give this select a width that works well for each language’s strings? */} <Select icon="laptop" - label={t('themeSelect.accessibleLabel')} - value="auto" + label={Astro.locals.t('themeSelect.accessibleLabel')} options={[ - { label: t('themeSelect.dark'), selected: false, value: 'dark' }, - { label: t('themeSelect.light'), selected: false, value: 'light' }, - { label: t('themeSelect.auto'), selected: true, value: 'auto' }, + { label: Astro.locals.t('themeSelect.dark'), selected: false, value: 'dark' }, + { label: Astro.locals.t('themeSelect.light'), selected: false, value: 'light' }, + { label: Astro.locals.t('themeSelect.auto'), selected: true, value: 'auto' }, ]} width="6.25em" /> @@ -32,62 +24,50 @@ const t = useTranslations(Astro.props.locale); <script> type Theme = 'auto' | 'dark' | 'light'; - class StarlightThemeSelect extends HTMLElement { - /** Key in `localStorage` to store color theme preference at. */ - #key = 'starlight-theme'; + /** Key in `localStorage` to store color theme preference at. */ + const storageKey = 'starlight-theme'; - constructor() { - super(); - this.#onThemeChange(this.#loadTheme()); - const select = this.querySelector('select'); - if (select) { - select.addEventListener('change', (e) => { - if (e.currentTarget instanceof HTMLSelectElement) { - this.#onThemeChange(this.#parseTheme(e.currentTarget.value)); - } - }); - } - } + /** Get a typesafe theme string from any JS value (unknown values are coerced to `'auto'`). */ + const parseTheme = (theme: unknown): Theme => + theme === 'auto' || theme === 'dark' || theme === 'light' ? theme : 'auto'; - /** Get a typesafe theme string from any JS value (unknown values are coerced to `'auto'`). */ - #parseTheme(theme: unknown): Theme { - if (theme === 'auto' || theme === 'dark' || theme === 'light') { - return theme; - } else { - return 'auto'; - } - } + /** Load the user’s preference from `localStorage`. */ + const loadTheme = (): Theme => + parseTheme(typeof localStorage !== 'undefined' && localStorage.getItem(storageKey)); - /** Get the preferred system color scheme. */ - #getPreferredColorScheme(): Theme { - return matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'; + /** Store the user’s preference in `localStorage`. */ + function storeTheme(theme: Theme): void { + if (typeof localStorage !== 'undefined') { + localStorage.setItem(storageKey, theme === 'light' || theme === 'dark' ? theme : ''); } + } - /** Update select menu UI, document theme, and local storage state. */ - #onThemeChange(theme: Theme): void { - StarlightThemeProvider.updatePickers(theme); - document.documentElement.dataset.theme = - theme === 'auto' ? this.#getPreferredColorScheme() : theme; - this.#storeTheme(theme); - } + /** Get the preferred system color scheme. */ + const getPreferredColorScheme = (): Theme => + matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'; - /** Store the user’s preference in `localStorage`. */ - #storeTheme(theme: Theme): void { - if (typeof localStorage !== 'undefined') { - if (theme === 'light' || theme === 'dark') { - localStorage.setItem(this.#key, theme); - } else { - localStorage.removeItem(this.#key); - } - } - } + /** Update select menu UI, document theme, and local storage state. */ + function onThemeChange(theme: Theme): void { + StarlightThemeProvider.updatePickers(theme); + document.documentElement.dataset.theme = theme === 'auto' ? getPreferredColorScheme() : theme; + storeTheme(theme); + } - /** Load the user’s preference from `localStorage`. */ - #loadTheme(): Theme { - const theme = typeof localStorage !== 'undefined' && localStorage.getItem(this.#key); - return this.#parseTheme(theme); + // React to changes in system color scheme. + matchMedia(`(prefers-color-scheme: light)`).addEventListener('change', () => { + if (loadTheme() === 'auto') onThemeChange('auto'); + }); + + class StarlightThemeSelect extends HTMLElement { + constructor() { + super(); + onThemeChange(loadTheme()); + this.querySelector('select')?.addEventListener('change', (e) => { + if (e.currentTarget instanceof HTMLSelectElement) { + onThemeChange(parseTheme(e.currentTarget.value)); + } + }); } } - customElements.define('starlight-theme-select', StarlightThemeSelect); </script> diff --git a/packages/starlight/components/TwoColumnContent.astro b/packages/starlight/components/TwoColumnContent.astro new file mode 100644 index 00000000000..3cfea5c607c --- /dev/null +++ b/packages/starlight/components/TwoColumnContent.astro @@ -0,0 +1,54 @@ +<div class="lg:sl-flex"> + { + Astro.locals.starlightRoute.toc && ( + <aside class="right-sidebar-container print:hidden"> + <div class="right-sidebar"> + <slot name="right-sidebar" /> + </div> + </aside> + ) + } + <div class="main-pane"><slot /></div> +</div> + +<style> + @layer starlight.core { + .main-pane { + isolation: isolate; + } + + @media (min-width: 72rem) { + .right-sidebar-container { + order: 2; + position: relative; + width: calc( + var(--sl-sidebar-width) + (100% - var(--sl-content-width) - var(--sl-sidebar-width)) / 2 + ); + } + + .right-sidebar { + position: fixed; + top: 0; + border-inline-start: 1px solid var(--sl-color-hairline); + padding-top: var(--sl-nav-height); + width: 100%; + height: 100vh; + overflow-y: auto; + scrollbar-width: none; + } + + .main-pane { + width: 100%; + } + + :global([data-has-sidebar][data-has-toc]) .main-pane { + --sl-content-margin-inline: auto 0; + + order: 1; + width: calc( + var(--sl-content-width) + (100% - var(--sl-content-width) - var(--sl-sidebar-width)) / 2 + ); + } + } + } +</style> diff --git a/packages/starlight/constants.ts b/packages/starlight/constants.ts new file mode 100644 index 00000000000..f679b6ae66b --- /dev/null +++ b/packages/starlight/constants.ts @@ -0,0 +1,4 @@ +// N.B. THIS FILE IS IMPORTED IN BOTH SERVER- AND CLIENT-SIDE CODE. +// THINK TWICE BEFORE ADDING STUFF AS IT WILL GET SHIPPED TO THE CLIENT. + +export const PAGE_TITLE_ID = '_top'; diff --git a/packages/starlight/expressive-code.d.ts b/packages/starlight/expressive-code.d.ts new file mode 100644 index 00000000000..d03f5cc66a7 --- /dev/null +++ b/packages/starlight/expressive-code.d.ts @@ -0,0 +1,37 @@ +/** + * @file This file provides the types for Starlight's `@astrojs/starlight/expressive-code` export. + */ + +export * from 'astro-expressive-code'; + +import type { StarlightExpressiveCodeOptions } from './integrations/expressive-code'; + +export type { StarlightExpressiveCodeOptions }; + +/** + * A utility function that helps you define an Expressive Code configuration object. It is meant + * to be used inside the optional config file `ec.config.mjs` located in the root directory + * of your Starlight project, and its return value to be exported as the default export. + * + * Expressive Code will automatically detect this file and use the exported configuration object + * to override its own default settings. + * + * Using this function is recommended, but not required. It just passes through the given object, + * but it also provides type information for your editor's auto-completion and type checking. + * + * @example + * ```js + * // ec.config.mjs + * import { defineEcConfig } from '@astrojs/starlight/expressive-code' + * + * export default defineEcConfig({ + * themes: ['starlight-dark', 'github-light'], + * styleOverrides: { + * borderRadius: '0.5rem', + * }, + * }) + * ``` + */ +export function defineEcConfig( + config: StarlightExpressiveCodeOptions +): StarlightExpressiveCodeOptions; diff --git a/packages/starlight/expressive-code.mjs b/packages/starlight/expressive-code.mjs new file mode 100644 index 00000000000..1bfc6523a25 --- /dev/null +++ b/packages/starlight/expressive-code.mjs @@ -0,0 +1,23 @@ +/** + * @file This file is exported by Starlight as `@astrojs/starlight/expressive-code`. + * + * It is required by the `<Code>` component to access the same configuration preprocessor + * function as the one used by the integration. + * + * It also provides access to all of the Expressive Code classes and functions without having + * to install `astro-expressive-code` as an additional dependency into a user's project + * (and thereby risiking version conflicts). + * + * Note: This file is intentionally not a TypeScript module to allow access to all exported + * functionality even if TypeScript is not available, e.g. from the `ec.config.mjs` file + * that does not get processed by Vite. + */ + +export * from 'astro-expressive-code'; + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore - Types are provided by the separate `expressive-code.d.ts` file and this may not be +// a type error for some users running `tsc --noEmit` depending on their `tsconfig.json` settings. +export function defineEcConfig(config) { + return config; +} diff --git a/packages/starlight/global.d.ts b/packages/starlight/global.d.ts index 6b31ebeac65..13121ecaffa 100644 --- a/packages/starlight/global.d.ts +++ b/packages/starlight/global.d.ts @@ -1,4 +1,4 @@ -declare global { +export declare global { var StarlightThemeProvider: { updatePickers(theme?: string): void; }; diff --git a/packages/starlight/i18n.d.ts b/packages/starlight/i18n.d.ts new file mode 100644 index 00000000000..8cb82217cd7 --- /dev/null +++ b/packages/starlight/i18n.d.ts @@ -0,0 +1,18 @@ +/* + * This file imports the original `i18next` types and extends them to configure the + * Starlight namespace. + * + * Note that the top-level `import` makes this module non-ambient, so can’t be + * combined with other `.d.ts` files such as `locals.d.ts`. + */ + +import 'i18next'; + +declare module 'i18next' { + interface CustomTypeOptions { + defaultNS: typeof import('./utils/createTranslationSystem').I18nextNamespace; + resources: { + starlight: Record<import('./utils/createTranslationSystem').I18nKeys, string>; + }; + } +} diff --git a/packages/starlight/index.astro b/packages/starlight/index.astro deleted file mode 100644 index d480f420698..00000000000 --- a/packages/starlight/index.astro +++ /dev/null @@ -1,15 +0,0 @@ ---- -import type { InferGetStaticPropsType } from 'astro'; -import { paths } from './utils/routing'; - -import Page from './layout/Page.astro'; - -export async function getStaticPaths() { - return paths; -} - -type Props = InferGetStaticPropsType<typeof getStaticPaths>; -const { Content, headings } = await Astro.props.entry.render(); ---- - -<Page {...Astro.props} {headings}><Content /></Page> diff --git a/packages/starlight/index.ts b/packages/starlight/index.ts index 50e37d046c0..4af0f925548 100644 --- a/packages/starlight/index.ts +++ b/packages/starlight/index.ts @@ -1,82 +1,155 @@ +/** + * These triple-slash directives defines dependencies to various declaration files that will be + * loaded when a user imports the Starlight integration in their Astro configuration file. These + * directives must be first at the top of the file and can only be preceded by this comment. + */ +/// <reference path="./locals.d.ts" /> +/// <reference path="./i18n.d.ts" /> +/// <reference path="./virtual.d.ts" /> + import mdx from '@astrojs/mdx'; -import type { AstroIntegration, AstroUserConfig } from 'astro'; -import { spawn } from 'node:child_process'; -import { dirname, relative } from 'node:path'; -import { fileURLToPath } from 'node:url'; -import { starlightAsides } from './integrations/asides'; +import type { AstroIntegration } from 'astro'; +import { AstroError } from 'astro/errors'; +import { + starlightRehypePlugins, + starlightRemarkPlugins, + type RemarkRehypePluginOptions, +} from './integrations/remark-rehype'; +import { starlightDirectivesRestorationIntegration } from './integrations/asides'; +import { starlightExpressiveCode } from './integrations/expressive-code/index'; +import { starlightPagefind } from './integrations/pagefind'; import { starlightSitemap } from './integrations/sitemap'; +import { vitePluginStarlightCssLayerOrder } from './integrations/vite-layer-order'; import { vitePluginStarlightUserConfig } from './integrations/virtual-user-config'; -import { errorMap } from './utils/error-map'; -import { StarlightConfigSchema, type StarlightUserConfig } from './utils/user-config'; -import { rehypeRtlCodeSupport } from './integrations/code-rtl-support'; - -export default function StarlightIntegration(opts: StarlightUserConfig): AstroIntegration[] { - const parsedConfig = StarlightConfigSchema.safeParse(opts, { errorMap }); +import { + injectPluginTranslationsTypes, + runPlugins, + type PluginTranslations, + type StarlightUserConfigWithPlugins, +} from './utils/plugins'; +import { processI18nConfig } from './utils/i18n'; +import type { StarlightConfig } from './types'; - if (!parsedConfig.success) { - throw new Error( - 'Invalid config passed to starlight integration\n' + - parsedConfig.error.issues.map((i) => i.message).join('\n') +export default function StarlightIntegration( + userOpts: StarlightUserConfigWithPlugins +): AstroIntegration { + if (typeof userOpts !== 'object' || userOpts === null || Array.isArray(userOpts)) + throw new AstroError( + 'Invalid config passed to starlight integration', + `The Starlight integration expects a configuration object with at least a \`title\` property.\n\n` + + `See more details in the [Starlight configuration reference](https://starlight.astro.build/reference/configuration/)\n` ); - } - - const userConfig = parsedConfig.data; - - const Starlight: AstroIntegration = { + const { plugins, ...opts } = userOpts; + let userConfig: StarlightConfig; + let pluginTranslations: PluginTranslations = {}; + return { name: '@astrojs/starlight', hooks: { - 'astro:config:setup': ({ config, injectRoute, updateConfig }) => { - injectRoute({ - pattern: '404', - entryPoint: '@astrojs/starlight/404.astro', + 'astro:config:setup': async ({ + addMiddleware, + command, + config, + injectRoute, + isRestart, + logger, + updateConfig, + }) => { + // Run plugins to get the updated configuration and any extra Astro integrations to load. + const pluginResult = await runPlugins(opts, plugins, { + command, + config, + isRestart, + logger, }); + // Process the Astro and Starlight configurations for i18n and translations. + const { astroI18nConfig, starlightConfig } = processI18nConfig( + pluginResult.starlightConfig, + config.i18n + ); + + const { integrations, useTranslations, absolutePathToLang } = pluginResult; + pluginTranslations = pluginResult.pluginTranslations; + userConfig = starlightConfig; + + addMiddleware({ entrypoint: '@astrojs/starlight/locals', order: 'pre' }); + + if (!starlightConfig.disable404Route) { + injectRoute({ + pattern: '404', + entrypoint: starlightConfig.prerender + ? '@astrojs/starlight/routes/static/404.astro' + : '@astrojs/starlight/routes/ssr/404.astro', + prerender: starlightConfig.prerender, + }); + } injectRoute({ pattern: '[...slug]', - entryPoint: '@astrojs/starlight/index.astro', + entrypoint: starlightConfig.prerender + ? '@astrojs/starlight/routes/static/index.astro' + : '@astrojs/starlight/routes/ssr/index.astro', + prerender: starlightConfig.prerender, }); - const newConfig: AstroUserConfig = { + + // Add built-in integrations only if they are not already added by the user through the + // config or by a plugin. + const allIntegrations = [...config.integrations, ...integrations]; + if (!allIntegrations.find(({ name }) => name === 'astro-expressive-code')) { + integrations.push( + ...starlightExpressiveCode({ astroConfig: config, starlightConfig, useTranslations }) + ); + } + if (!allIntegrations.find(({ name }) => name === '@astrojs/sitemap')) { + integrations.push(starlightSitemap(starlightConfig)); + } + if (!allIntegrations.find(({ name }) => name === '@astrojs/mdx')) { + integrations.push(mdx({ optimize: true })); + } + + // Add Starlight directives restoration integration at the end of the list so that remark + // plugins injected by Starlight plugins through Astro integrations can handle text and + // leaf directives before they are transformed back to their original form. + integrations.push(starlightDirectivesRestorationIntegration()); + + // Add integrations immediately after Starlight in the config array. + // e.g. if a user has `integrations: [starlight(), tailwind()]`, then the order will be + // `[starlight(), expressiveCode(), sitemap(), mdx(), tailwind()]`. + // This ensures users can add integrations before/after Starlight and we respect that order. + const selfIndex = config.integrations.findIndex((i) => i.name === '@astrojs/starlight'); + config.integrations.splice(selfIndex + 1, 0, ...integrations); + + const remarkRehypeOptions: RemarkRehypePluginOptions = { + starlightConfig, + astroConfig: config, + useTranslations, + absolutePathToLang, + }; + + updateConfig({ vite: { - plugins: [vitePluginStarlightUserConfig(userConfig, config)], + plugins: [ + vitePluginStarlightCssLayerOrder(), + vitePluginStarlightUserConfig(command, starlightConfig, config, pluginTranslations), + ], }, markdown: { - remarkPlugins: [...starlightAsides()], - rehypePlugins: [rehypeRtlCodeSupport()], - shikiConfig: - // Configure Shiki theme if the user is using the default github-dark theme. - config.markdown.shikiConfig.theme !== 'github-dark' ? {} : { theme: 'css-variables' }, + remarkPlugins: [...starlightRemarkPlugins(remarkRehypeOptions)], + rehypePlugins: [...starlightRehypePlugins(remarkRehypeOptions)], }, scopedStyleStrategy: 'where', - }; - updateConfig(newConfig); + // If not already configured, default to prefetching all links on hover. + prefetch: config.prefetch ?? { prefetchAll: true }, + i18n: astroI18nConfig, + }); }, - 'astro:config:done': ({ config }) => { - const integrations = config.integrations.map(({ name }) => name); - for (const builtin of ['@astrojs/mdx', '@astrojs/sitemap']) { - if (integrations.filter((name) => name === builtin).length > 1) { - throw new Error( - `Found more than one instance of ${builtin}.\n` + - `Starlight includes ${builtin} by default.\n` + - 'Please remove it from your integrations array in astro.config.mjs' - ); - } - } + 'astro:config:done': ({ injectTypes }) => { + injectPluginTranslationsTypes(pluginTranslations, injectTypes); }, - 'astro:build:done': ({ dir }) => { - const targetDir = fileURLToPath(dir); - const cwd = dirname(fileURLToPath(import.meta.url)); - const relativeDir = relative(cwd, targetDir); - return new Promise<void>((resolve) => { - spawn('npx', ['-y', 'pagefind', '--site', relativeDir], { - stdio: 'inherit', - shell: true, - cwd, - }).on('close', () => resolve()); - }); + 'astro:build:done': async (options) => { + if (!userConfig.pagefind) return; + return starlightPagefind(options); }, }, }; - - return [starlightSitemap(userConfig), Starlight, mdx()]; } diff --git a/packages/starlight/integrations/asides-error.ts b/packages/starlight/integrations/asides-error.ts new file mode 100644 index 00000000000..076e77288cf --- /dev/null +++ b/packages/starlight/integrations/asides-error.ts @@ -0,0 +1,9 @@ +import { AstroError } from 'astro/errors'; + +export function throwInvalidAsideIconError(icon: string) { + throw new AstroError( + 'Invalid aside icon', + `An aside custom icon must be set to the name of one of Starlight’s built-in icons, but received \`${icon}\`.\n\n` + + 'See https://starlight.astro.build/reference/icons/#all-icons for a list of available icons.' + ); +} diff --git a/packages/starlight/integrations/asides.ts b/packages/starlight/integrations/asides.ts index 5d2107ad79e..d534d382618 100644 --- a/packages/starlight/integrations/asides.ts +++ b/packages/starlight/integrations/asides.ts @@ -1,31 +1,105 @@ -import type { AstroUserConfig } from 'astro'; -import { h as _h, s as _s, type Properties } from 'hastscript'; -import type { Paragraph as P, Root } from 'mdast'; -import remarkDirective from 'remark-directive'; +/// <reference types="mdast-util-directive" /> + +import type { AstroIntegration } from 'astro'; +import { h as _h, s as _s, type Properties, type Result } from 'hastscript'; +import type { Node, Paragraph as P, Parent, PhrasingContent, Root } from 'mdast'; +import { + type Directives, + directiveToMarkdown, + type TextDirective, + type LeafDirective, +} from 'mdast-util-directive'; +import { toMarkdown } from 'mdast-util-to-markdown'; +import { toString } from 'mdast-util-to-string'; import type { Plugin, Transformer } from 'unified'; -import { remove } from 'unist-util-remove'; import { visit } from 'unist-util-visit'; +import type { RemarkRehypePluginOptions } from './remark-rehype'; +import type { StarlightIcon } from '../types'; +import { Icons } from '../components/Icons'; +import { fromHtml } from 'hast-util-from-html'; +import type { Element } from 'hast'; +import { throwInvalidAsideIconError } from './asides-error'; /** Hacky function that generates an mdast HTML tree ready for conversion to HTML by rehype. */ -function h(el: string, attrs: Properties = {}, children: any[] = []): P { +function h(el: string, attrs: Properties = {}, children: unknown[] = []): P { const { tagName, properties } = _h(el, attrs); return { type: 'paragraph', data: { hName: tagName, hProperties: properties }, - children, + children: children as P['children'], }; } /** Hacky function that generates an mdast SVG tree ready for conversion to HTML by rehype. */ -function s(el: string, attrs: Properties = {}, children: any[] = []): P { +function s(el: string, attrs: Properties = {}, children: unknown[] = []): P { const { tagName, properties } = _s(el, attrs); return { type: 'paragraph', data: { hName: tagName, hProperties: properties }, - children, + children: children as P['children'], }; } +/** Checks if a node is a directive. */ +function isNodeDirective(node: Node): node is Directives { + return ( + node.type === 'textDirective' || + node.type === 'leafDirective' || + node.type === 'containerDirective' + ); +} + +/** + * Transforms back directives not handled by Starlight to avoid breaking user content. + * For example, a user might write `x:y` in the middle of a sentence, where `:y` would be + * identified as a text directive, which are not used by Starlight, and we definitely want that + * text to be rendered verbatim in the output. + */ +function transformUnhandledDirective( + node: TextDirective | LeafDirective, + index: number, + parent: Parent +) { + let markdown = toMarkdown(node, { extensions: [directiveToMarkdown()] }); + /** + * `mdast-util-to-markdown` assumes that the tree represents a complete document (as it's an AST + * and not a CST) and to follow the POSIX definition of a line (a sequence of zero or more + * non- <newline> characters plus a terminating <newline> character), a newline is automatically + * added at the end of the output so that the output is a valid file. + * In this specific case, we can safely remove the newline character at the end of the output + * before replacing the directive with its value. + * + * @see https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206 + * @see https://github.com/syntax-tree/mdast-util-to-markdown/blob/fd6a508cc619b862f75b762dcf876c6b8315d330/lib/index.js#L79-L85 + */ + if (markdown.at(-1) === '\n') markdown = markdown.slice(0, -1); + const textNode = { type: 'text', value: markdown } as const; + if (node.type === 'textDirective') { + parent.children[index] = textNode; + } else { + parent.children[index] = { + type: 'paragraph', + children: [textNode], + }; + } +} + +/** Hacky function that generates the children of an mdast SVG tree. */ +function makeSvgChildNodes(children: Result['children']): P[] { + const nodes: P[] = []; + for (const child of children) { + if (child.type !== 'element') continue; + nodes.push({ + type: 'paragraph', + data: { hName: child.tagName, hProperties: child.properties }, + // We are explicitly casting to the expected type here due to the hacky nature of this + // function which only works with SVG elements. + children: makeSvgChildNodes(child.children) as unknown as P['children'], + }); + } + return nodes; +} + /** * remark plugin that converts blocks delimited with `:::` into styled * asides (a.k.a. “callouts”, “admonitions”, etc.). Depends on the @@ -44,25 +118,17 @@ function s(el: string, attrs: Properties = {}, children: any[] = []): P { * ```astro * <aside class="starlight-aside starlight-aside--tip" aria-label="Did you know?"> * <p class="starlight-aside__title" aria-hidden="true">Did you know?</p> - * <section class="starlight-aside__content"> + * <div class="starlight-aside__content"> * <p>Astro helps you build faster websites with “Islands Architecture”.</p> - * </section> - * </Aside> + * </div> + * </aside> * ``` */ -function remarkAsides(): Plugin<[], Root> { +export function remarkAsides(options: RemarkRehypePluginOptions): Plugin<[], Root> { type Variant = 'note' | 'tip' | 'caution' | 'danger'; const variants = new Set(['note', 'tip', 'caution', 'danger']); const isAsideVariant = (s: string): s is Variant => variants.has(s); - // TODO: hook these up for i18n once the design for translating strings is ready - const defaultTitles = { - note: 'Note', - tip: 'Tip', - caution: 'Caution', - danger: 'Danger', - }; - const iconPaths = { // Information icon note: [ @@ -95,31 +161,51 @@ function remarkAsides(): Plugin<[], Root> { ], }; - const transformer: Transformer<Root> = (tree) => { + const transformer: Transformer<Root> = (tree, file) => { + const lang = options.absolutePathToLang(file.path); + const t = options.useTranslations(lang); visit(tree, (node, index, parent) => { - if (!parent || index === null || node.type !== 'containerDirective') { + if (!parent || index === undefined || !isNodeDirective(node)) { + return; + } + if (node.type === 'textDirective' || node.type === 'leafDirective') { return; } const variant = node.name; + const attributes = node.attributes; if (!isAsideVariant(variant)) return; - // remark-directive converts a container’s “label” to a paragraph in - // its children, but we want to pass it as the title prop to <Aside>, so - // we iterate over the children, find a directive label, store it for the - // title prop, and remove the paragraph from children. - let title = defaultTitles[variant]; - remove(node, (child): boolean | void => { - if (child.data?.directiveLabel) { - if ( - 'children' in child && - Array.isArray(child.children) && - 'value' in child.children[0] - ) { - title = child.children[0].value; - } - return true; - } - }); + // remark-directive converts a container’s “label” to a paragraph added as the head of its + // children with the `directiveLabel` property set to true. We want to pass it as the title + // prop to <Aside>, so when we find a directive label, we store it for the title prop and + // remove the paragraph from the container’s children. + let title: string = t(`aside.${variant}`); + let titleNode: PhrasingContent[] = [{ type: 'text', value: title }]; + const firstChild = node.children[0]; + if ( + firstChild?.type === 'paragraph' && + firstChild.data && + 'directiveLabel' in firstChild.data && + firstChild.children.length > 0 + ) { + titleNode = firstChild.children; + title = toString(firstChild.children); + // The first paragraph contains a directive label, we can safely remove it. + node.children.splice(0, 1); + } + + let iconPath = iconPaths[variant]; + + if (attributes?.['icon']) { + const iconName = attributes['icon'] as StarlightIcon; + const icon = Icons[iconName]; + if (!icon) throwInvalidAsideIconError(iconName); + // Omit the root node and return only the first child which is the SVG element. + const iconHastTree = fromHtml(`<svg>${icon}</svg>`, { fragment: true, space: 'svg' }) + .children[0] as Element; + // Render all SVG child nodes. + iconPath = makeSvgChildNodes(iconHastTree.children); + } const aside = h( 'aside', @@ -138,11 +224,11 @@ function remarkAsides(): Plugin<[], Root> { fill: 'currentColor', class: 'starlight-aside__icon', }, - iconPaths[variant] + iconPath ), - { type: 'text', value: title }, + ...titleNode, ]), - h('section', { class: 'starlight-aside__content' }, node.children), + h('div', { class: 'starlight-aside__content' }, node.children), ] ); @@ -155,8 +241,43 @@ function remarkAsides(): Plugin<[], Root> { }; } -type RemarkPlugins = NonNullable<NonNullable<AstroUserConfig['markdown']>['remarkPlugins']>; +export function remarkDirectivesRestoration() { + return function transformer(tree: Root) { + visit(tree, (node, index, parent) => { + if ( + index !== undefined && + parent && + (node.type === 'textDirective' || node.type === 'leafDirective') && + node.data === undefined + ) { + transformUnhandledDirective(node, index, parent); + return; + } + }); + }; +} -export function starlightAsides(): RemarkPlugins { - return [remarkDirective, remarkAsides()]; +/** + * Directives not handled by Starlight are transformed back to their original form to avoid + * breaking user content. + * To allow remark plugins injected by Starlight plugins through Astro integrations to handle + * such directives, we need to restore unhandled text and leaf directives back to their original + * form only after all these other plugins have run. + * To do so, we run a remark plugin restoring these directives back to their original form from + * another Astro integration that runs after all the ones that may have been injected by Starlight + * plugins. + */ +export function starlightDirectivesRestorationIntegration(): AstroIntegration { + return { + name: 'starlight-directives-restoration', + hooks: { + 'astro:config:setup': ({ updateConfig }) => { + updateConfig({ + markdown: { + remarkPlugins: [remarkDirectivesRestoration], + }, + }); + }, + }, + }; } diff --git a/packages/starlight/integrations/code-rtl-support.ts b/packages/starlight/integrations/code-rtl-support.ts index b8f7c3a6660..fd66fb11afb 100644 --- a/packages/starlight/integrations/code-rtl-support.ts +++ b/packages/starlight/integrations/code-rtl-support.ts @@ -1,5 +1,7 @@ -import type { Root } from 'hastscript/lib/core'; +import type { Root } from 'hast'; import { CONTINUE, SKIP, visit } from 'unist-util-visit'; +import type { Transformer } from 'unified'; +import type { RemarkRehypePluginOptions } from './remark-rehype'; /** * rehype plugin that adds `dir` attributes to `<code>` and `<pre>` @@ -15,9 +17,9 @@ import { CONTINUE, SKIP, visit } from 'unist-util-visit'; * - `<code>` is often LTR, but could also be RTL. `dir="auto"` ensures the bidirectional * algorithm treats the contents of `<code>` in isolation and gives its best guess. */ -export function rehypeRtlCodeSupport() { - return () => (root: Root) => { - visit(root, 'element', (el) => { +export function rehypeRtlCodeSupport(_options: RemarkRehypePluginOptions) { + const transformer: Transformer<Root> = (tree) => { + visit(tree, 'element', (el) => { if (el.tagName === 'pre' || el.tagName === 'code') { el.properties ||= {}; if (!('dir' in el.properties)) { @@ -28,4 +30,8 @@ export function rehypeRtlCodeSupport() { return CONTINUE; }); }; + + return function attacher() { + return transformer; + }; } diff --git a/packages/starlight/integrations/expressive-code/hast.d.ts b/packages/starlight/integrations/expressive-code/hast.d.ts new file mode 100644 index 00000000000..e2d67796b77 --- /dev/null +++ b/packages/starlight/integrations/expressive-code/hast.d.ts @@ -0,0 +1,5 @@ +/** + * @file This file provides the types for Starlight's `@astrojs/starlight/expressive-code/hast` export. + */ + +export * from 'astro-expressive-code/hast'; diff --git a/packages/starlight/integrations/expressive-code/hast.mjs b/packages/starlight/integrations/expressive-code/hast.mjs new file mode 100644 index 00000000000..3b6549fe47b --- /dev/null +++ b/packages/starlight/integrations/expressive-code/hast.mjs @@ -0,0 +1,9 @@ +/** + * @file This file is exported by Starlight as `@astrojs/starlight/expressive-code/hast`. + * + * Note: This file is intentionally not a TypeScript module to allow access to all exported + * functionality even if TypeScript is not available, e.g. from the `ec.config.mjs` file + * that does not get processed by Vite. + */ + +export * from 'astro-expressive-code/hast'; diff --git a/packages/starlight/integrations/expressive-code/index.ts b/packages/starlight/integrations/expressive-code/index.ts new file mode 100644 index 00000000000..4564230c5ec --- /dev/null +++ b/packages/starlight/integrations/expressive-code/index.ts @@ -0,0 +1,125 @@ +import { astroExpressiveCode, type AstroExpressiveCodeOptions } from 'astro-expressive-code'; +import type { AstroConfig, AstroIntegration } from 'astro'; +import type { HookParameters, StarlightConfig } from '../../types'; +import { getStarlightEcConfigPreprocessor } from './preprocessor'; +import { type ThemeObjectOrBundledThemeName } from './theming'; +import { getCollectionPosixPath } from '../../utils/collection-fs'; + +export type StarlightExpressiveCodeOptions = Omit<AstroExpressiveCodeOptions, 'themes'> & { + /** + * Set the themes used to style code blocks. + * + * See the [Expressive Code `themes` documentation](https://expressive-code.com/guides/themes/) + * for details of the supported theme formats. + * + * Starlight uses the dark and light variants of Sarah Drasner’s + * [Night Owl theme](https://github.com/sdras/night-owl-vscode-theme) by default. + * + * If you provide at least one dark and one light theme, Starlight will automatically keep + * the active code block theme in sync with the current site theme. Configure this behavior + * with the [`useStarlightDarkModeSwitch`](#usestarlightdarkmodeswitch) option. + * + * Defaults to `['starlight-dark', 'starlight-light']`. + */ + themes?: ThemeObjectOrBundledThemeName[] | undefined; + /** + * When `true`, code blocks automatically switch between light and dark themes when the + * site theme changes. + * + * When `false`, you must manually add CSS to handle switching between multiple themes. + * + * **Note**: When setting `themes`, you must provide at least one dark and one light theme + * for the Starlight dark mode switch to work. + * + * Defaults to `true`. + */ + useStarlightDarkModeSwitch?: boolean | undefined; + /** + * When `true`, Starlight's CSS variables are used for the colors of code block UI elements + * (backgrounds, buttons, shadows etc.), matching the + * [site color theme](/guides/css-and-tailwind/#theming). + * + * When `false`, the colors provided by the active syntax highlighting theme are used for + * these elements. + * + * Defaults to `true` if the `themes` option is not set (= you are using Starlight's + * default themes), and `false` otherwise. + * + * **Note**: When manually setting this to `true` with your custom set of `themes`, you must + * provide at least one dark and one light theme to ensure proper color contrast. + */ + useStarlightUiThemeColors?: boolean | undefined; +}; + +type StarlightEcIntegrationOptions = { + astroConfig: AstroConfig; + starlightConfig: StarlightConfig; + useTranslations: HookParameters<'config:setup'>['useTranslations']; +}; + +export const starlightExpressiveCode = ({ + astroConfig, + starlightConfig, + useTranslations, +}: StarlightEcIntegrationOptions): AstroIntegration[] => { + // If Expressive Code is disabled, add a shim to prevent build errors and provide + // a helpful error message in case the user tries to use the `<Code>` component + if (starlightConfig.expressiveCode === false) { + const modules: Record<string, string> = { + 'virtual:astro-expressive-code/api': 'export default {}', + 'virtual:astro-expressive-code/config': 'export default {}', + 'virtual:astro-expressive-code/preprocess-config': `throw new Error("Starlight's + Code component requires Expressive Code, which is disabled in your Starlight config. + Please remove \`expressiveCode: false\` from your config or import Astro's built-in + Code component from 'astro:components' instead.")`.replace(/\s+/g, ' '), + }; + + return [ + { + name: 'astro-expressive-code-shim', + hooks: { + 'astro:config:setup': ({ updateConfig }) => { + updateConfig({ + vite: { + plugins: [ + { + name: 'vite-plugin-astro-expressive-code-shim', + enforce: 'post', + resolveId: (id) => (id in modules ? `\0${id}` : undefined), + load: (id) => (id?.[0] === '\0' ? modules[id.slice(1)] : undefined), + }, + ], + }, + }); + }, + }, + }, + ]; + } + + const configArgs = + typeof starlightConfig.expressiveCode === 'object' + ? (starlightConfig.expressiveCode as AstroExpressiveCodeOptions) + : {}; + + const docsPath = getCollectionPosixPath('docs', astroConfig.srcDir); + + return [ + astroExpressiveCode({ + ...configArgs, + customConfigPreprocessors: { + preprocessAstroIntegrationConfig: getStarlightEcConfigPreprocessor({ + docsPath, + starlightConfig, + useTranslations, + }), + preprocessComponentConfig: ` + import starlightConfig from 'virtual:starlight/user-config' + import { useTranslations, getStarlightEcConfigPreprocessor } from '@astrojs/starlight/internal' + + export default getStarlightEcConfigPreprocessor({ docsPath: ${JSON.stringify(docsPath)}, starlightConfig, useTranslations }) + `, + }, + }), + ]; +}; diff --git a/packages/starlight/integrations/expressive-code/preprocessor.ts b/packages/starlight/integrations/expressive-code/preprocessor.ts new file mode 100644 index 00000000000..70c9ba93826 --- /dev/null +++ b/packages/starlight/integrations/expressive-code/preprocessor.ts @@ -0,0 +1,121 @@ +import { + type AstroExpressiveCodeOptions, + type CustomConfigPreprocessors, +} from 'astro-expressive-code'; +import { addClassName } from 'astro-expressive-code/hast'; +import type { StarlightExpressiveCodeOptions } from './index'; +import type { HookParameters, StarlightConfig } from '../../types'; +import { applyStarlightUiThemeColors, preprocessThemes } from './theming'; +import { addTranslations } from './translations'; +import { slugToLocale } from '../shared/slugToLocale'; +import { localeToLang } from '../shared/localeToLang'; +import { absolutePathToLang } from '../shared/absolutePathToLang'; + +type StarlightEcConfigPreprocessorOptions = { + docsPath: string; + starlightConfig: StarlightConfig; + useTranslations: HookParameters<'config:setup'>['useTranslations']; +}; + +/** + * Create an Expressive Code configuration preprocessor based on Starlight config. + * Used internally to set up Expressive Code and by the `<Code>` component. + */ +export function getStarlightEcConfigPreprocessor({ + docsPath, + starlightConfig, + useTranslations, +}: StarlightEcConfigPreprocessorOptions): CustomConfigPreprocessors['preprocessAstroIntegrationConfig'] { + return (input): AstroExpressiveCodeOptions => { + const ecConfig = input.ecConfig as StarlightExpressiveCodeOptions; + + const { + themes: themesInput, + cascadeLayer, + customizeTheme, + styleOverrides: { textMarkers: textMarkersStyleOverrides, ...otherStyleOverrides } = {}, + useStarlightDarkModeSwitch, + useStarlightUiThemeColors = ecConfig.themes === undefined, + plugins = [], + ...rest + } = ecConfig; + + // Handle the `themes` option + const themes = preprocessThemes(themesInput); + if (useStarlightUiThemeColors === true && themes.length < 2) { + console.warn( + `*** Warning: Using the config option "useStarlightUiThemeColors: true" ` + + `with a single theme is not recommended. For better color contrast, ` + + `please provide at least one dark and one light theme.\n` + ); + } + + // Add the `not-content` class to all rendered blocks to prevent them from being affected + // by Starlight's default content styles + plugins.push({ + name: 'Starlight Plugin', + hooks: { + postprocessRenderedBlock: ({ renderData }) => { + addClassName(renderData.blockAst, 'not-content'); + }, + }, + }); + + // Add Expressive Code UI translations for all defined locales + addTranslations(starlightConfig, useTranslations); + + return { + themes, + customizeTheme: (theme) => { + if (useStarlightUiThemeColors) { + applyStarlightUiThemeColors(theme); + } + if (customizeTheme) { + theme = customizeTheme(theme) ?? theme; + } + return theme; + }, + defaultLocale: starlightConfig.defaultLocale?.lang ?? starlightConfig.defaultLocale?.locale, + themeCssSelector: (theme, { styleVariants }) => { + // If one dark and one light theme are available, and the user has not disabled it, + // generate theme CSS selectors compatible with Starlight's dark mode switch + if (useStarlightDarkModeSwitch !== false && styleVariants.length >= 2) { + const baseTheme = styleVariants[0]?.theme; + const altTheme = styleVariants.find((v) => v.theme.type !== baseTheme?.type)?.theme; + if (theme === baseTheme || theme === altTheme) return `[data-theme='${theme.type}']`; + } + // Return the default selector + return `[data-theme='${theme.name}']`; + }, + cascadeLayer: cascadeLayer ?? 'starlight.components', + styleOverrides: { + borderRadius: '0px', + borderWidth: '1px', + codePaddingBlock: '0.75rem', + codePaddingInline: '1rem', + codeFontFamily: 'var(--__sl-font-mono)', + codeFontSize: 'var(--sl-text-code)', + codeLineHeight: 'var(--sl-line-height)', + uiFontFamily: 'var(--__sl-font)', + textMarkers: { + lineDiffIndicatorMarginLeft: '0.25rem', + defaultChroma: '45', + backgroundOpacity: '60%', + ...textMarkersStyleOverrides, + }, + ...otherStyleOverrides, + }, + getBlockLocale: ({ file }) => { + if (file.url) { + const locale = slugToLocale(file.url.pathname.slice(1), starlightConfig); + return localeToLang(starlightConfig, locale); + } + // Note that EC cannot use the `absolutePathToLang` helper passed down to plugins as this callback + // is also called in the context of the `<Code>` component. + return absolutePathToLang(file.path, { docsPath, starlightConfig }); + }, + plugins, + ...rest, + }; + }; +} diff --git a/packages/starlight/integrations/expressive-code/themes/night-owl-dark.jsonc b/packages/starlight/integrations/expressive-code/themes/night-owl-dark.jsonc new file mode 100644 index 00000000000..81fd0b76ef4 --- /dev/null +++ b/packages/starlight/integrations/expressive-code/themes/night-owl-dark.jsonc @@ -0,0 +1,1796 @@ +/** + * Night Owl VS Code Theme - https://github.com/sdras/night-owl-vscode-theme + * + * MIT License + * + * Copyright (c) 2018 Sarah Drasner + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +{ + "name": "Night Owl No Italics", + "type": "dark", + "semanticHighlighting": false, + "colors": { + "contrastBorder": "#122d42", + "focusBorder": "#122d42", + "foreground": "#d6deeb", + "widget.shadow": "#011627", + "selection.background": "#4373c2", + "errorForeground": "#EF5350", + "button.background": "#7e57c2cc", + "button.foreground": "#ffffffcc", + "button.hoverBackground": "#7e57c2", + "dropdown.background": "#011627", + "dropdown.border": "#5f7e97", + "dropdown.foreground": "#ffffffcc", + "input.background": "#0b253a", + "input.border": "#5f7e97", + "input.foreground": "#ffffffcc", + "input.placeholderForeground": "#5f7e97", + "inputOption.activeBorder": "#ffffffcc", + "punctuation.definition.generic.begin.html": "#ef5350f2", + "inputValidation.errorBackground": "#AB0300F2", + "inputValidation.errorBorder": "#EF5350", + "inputValidation.infoBackground": "#00589EF2", + "inputValidation.infoBorder": "#64B5F6", + "inputValidation.warningBackground": "#675700F2", + "inputValidation.warningBorder": "#FFCA28", + "scrollbar.shadow": "#010b14", + "scrollbarSlider.activeBackground": "#084d8180", + "scrollbarSlider.background": "#084d8180", + "scrollbarSlider.hoverBackground": "#084d8180", + "badge.background": "#5f7e97", + "badge.foreground": "#ffffff", + "progress.background": "#7e57c2", + "breadcrumb.foreground": "#A599E9", + "breadcrumb.focusForeground": "#ffffff", + "breadcrumb.activeSelectionForeground": "#FFFFFF", + "breadcrumbPicker.background": "#001122", + "list.activeSelectionBackground": "#234d708c", + "list.activeSelectionForeground": "#ffffff", + "list.invalidItemForeground": "#975f94", + "list.dropBackground": "#011627", + "list.focusBackground": "#010d18", + "list.focusForeground": "#ffffff", + "list.highlightForeground": "#ffffff", + "list.hoverBackground": "#011627", + "list.hoverForeground": "#ffffff", + "list.inactiveSelectionBackground": "#0e293f", + "list.inactiveSelectionForeground": "#5f7e97", + "activityBar.background": "#011627", + "activityBar.dropBackground": "#5f7e97", + "activityBar.foreground": "#5f7e97", + "activityBar.border": "#011627", + "activityBarBadge.background": "#44596b", + "activityBarBadge.foreground": "#ffffff", + "sideBar.background": "#011627", + "sideBar.foreground": "#89a4bb", + "sideBar.border": "#011627", + "sideBarTitle.foreground": "#5f7e97", + "sideBarSectionHeader.background": "#011627", + "sideBarSectionHeader.foreground": "#5f7e97", + "editorGroup.emptyBackground": "#011627", + "editorGroup.border": "#011627", + "editorGroup.dropBackground": "#7e57c273", + "editorGroupHeader.noTabsBackground": "#011627", + "editorGroupHeader.tabsBackground": "#011627", + "editorGroupHeader.tabsBorder": "#262A39", + "tab.activeBackground": "#0b2942", + "tab.activeForeground": "#d2dee7", + "tab.border": "#272B3B", + "tab.activeBorder": "#262A39", + "tab.unfocusedActiveBorder": "#262A39", + "tab.inactiveBackground": "#01111d", + "tab.inactiveForeground": "#5f7e97", + "tab.unfocusedActiveForeground": "#5f7e97", + "tab.unfocusedInactiveForeground": "#5f7e97", + "editor.background": "#011627", + "editor.foreground": "#d6deeb", + "editorLineNumber.foreground": "#4b6479", + "editorLineNumber.activeForeground": "#C5E4FD", + "editorCursor.foreground": "#80a4c2", + "editor.selectionBackground": "#1d3b53", + "editor.selectionHighlightBackground": "#5f7e9779", + "editor.inactiveSelectionBackground": "#7e57c25a", + "editor.wordHighlightBackground": "#f6bbe533", + "editor.wordHighlightStrongBackground": "#e2a2f433", + "editor.findMatchBackground": "#5f7e9779", + "editor.findMatchHighlightBackground": "#1085bb5d", + "editor.findRangeHighlightBackground": null, + "editor.hoverHighlightBackground": "#7e57c25a", + "editor.lineHighlightBackground": "#0003", + "editor.lineHighlightBorder": null, + "editorLink.activeForeground": null, + "editor.rangeHighlightBackground": "#7e57c25a", + "editorWhitespace.foreground": null, + "editorIndentGuide.background": "#5e81ce52", + "editorIndentGuide.activeBackground": "#7E97AC", + "editorRuler.foreground": "#5e81ce52", + "editorCodeLens.foreground": "#5e82ceb4", + "editorBracketMatch.background": "#5f7e974d", + "editorBracketMatch.border": null, + "editorOverviewRuler.currentContentForeground": "#7e57c2", + "editorOverviewRuler.incomingContentForeground": "#7e57c2", + "editorOverviewRuler.commonContentForeground": "#7e57c2", + "editorError.foreground": "#EF5350", + "editorError.border": null, + "editorWarning.foreground": "#b39554", + "editorWarning.border": null, + "editorGutter.background": "#011627", + "editorGutter.modifiedBackground": "#e2b93d", + "editorGutter.addedBackground": "#9CCC65", + "editorGutter.deletedBackground": "#EF5350", + "diffEditor.insertedTextBackground": "#99b76d23", + "diffEditor.insertedTextBorder": "#c5e47833", + "diffEditor.removedTextBackground": "#ef535033", + "diffEditor.removedTextBorder": "#ef53504d", + "editorWidget.background": "#021320", + "editorWidget.border": "#5f7e97", + "editorSuggestWidget.background": "#2C3043", + "editorSuggestWidget.border": "#2B2F40", + "editorSuggestWidget.foreground": "#d6deeb", + "editorSuggestWidget.highlightForeground": "#ffffff", + "editorSuggestWidget.selectedBackground": "#5f7e97", + "editorHoverWidget.background": "#011627", + "editorHoverWidget.border": "#5f7e97", + "debugExceptionWidget.background": "#011627", + "debugExceptionWidget.border": "#5f7e97", + "editorMarkerNavigation.background": "#0b2942", + "editorMarkerNavigationError.background": "#EF5350", + "editorMarkerNavigationWarning.background": "#FFCA28", + "peekView.border": "#5f7e97", + "peekViewEditor.background": "#011627", + "peekViewEditor.matchHighlightBackground": "#7e57c25a", + "peekViewResult.background": "#011627", + "peekViewResult.fileForeground": "#5f7e97", + "peekViewResult.lineForeground": "#5f7e97", + "peekViewResult.matchHighlightBackground": "#ffffffcc", + "peekViewResult.selectionBackground": "#2E3250", + "peekViewResult.selectionForeground": "#5f7e97", + "peekViewTitle.background": "#011627", + "peekViewTitleDescription.foreground": "#697098", + "peekViewTitleLabel.foreground": "#5f7e97", + "merge.currentHeaderBackground": "#5f7e97", + "merge.currentContentBackground": null, + "merge.incomingHeaderBackground": "#7e57c25a", + "merge.incomingContentBackground": null, + "merge.border": null, + "panel.background": "#011627", + "panel.border": "#5f7e97", + "panelTitle.activeBorder": "#5f7e97", + "panelTitle.activeForeground": "#ffffffcc", + "panelTitle.inactiveForeground": "#d6deeb80", + "statusBar.background": "#011627", + "statusBar.foreground": "#5f7e97", + "statusBar.border": "#262A39", + "statusBar.debuggingBackground": "#202431", + "statusBar.debuggingForeground": null, + "statusBar.debuggingBorder": "#1F2330", + "statusBar.noFolderForeground": null, + "statusBar.noFolderBackground": "#011627", + "statusBar.noFolderBorder": "#25293A", + "statusBarItem.activeBackground": "#202431", + "statusBarItem.hoverBackground": "#202431", + "statusBarItem.prominentBackground": "#202431", + "statusBarItem.prominentHoverBackground": "#202431", + "titleBar.activeBackground": "#011627", + "titleBar.activeForeground": "#eeefff", + "titleBar.inactiveBackground": "#010e1a", + "titleBar.inactiveForeground": null, + "notifications.background": "#01111d", + "notifications.border": "#262a39", + "notificationCenter.border": "#262a39", + "notificationToast.border": "#262a39", + "notifications.foreground": "#ffffffcc", + "notificationLink.foreground": "#80CBC4", + "extensionButton.prominentForeground": "#ffffffcc", + "extensionButton.prominentBackground": "#7e57c2cc", + "extensionButton.prominentHoverBackground": "#7e57c2", + "pickerGroup.foreground": "#d1aaff", + "pickerGroup.border": "#011627", + "terminal.ansiWhite": "#ffffff", + "terminal.ansiBlack": "#011627", + "terminal.ansiBlue": "#82AAFF", + "terminal.ansiCyan": "#21c7a8", + "terminal.ansiGreen": "#22da6e", + "terminal.ansiMagenta": "#C792EA", + "terminal.ansiRed": "#EF5350", + "terminal.ansiYellow": "#c5e478", + "terminal.ansiBrightWhite": "#ffffff", + "terminal.ansiBrightBlack": "#575656", + "terminal.ansiBrightBlue": "#82AAFF", + "terminal.ansiBrightCyan": "#7fdbca", + "terminal.ansiBrightGreen": "#22da6e", + "terminal.ansiBrightMagenta": "#C792EA", + "terminal.ansiBrightRed": "#EF5350", + "terminal.ansiBrightYellow": "#ffeb95", + "terminal.selectionBackground": "#1b90dd4d", + "terminalCursor.background": "#234d70", + "textCodeBlock.background": "#4f4f4f", + "debugToolBar.background": "#011627", + "welcomePage.buttonBackground": "#011627", + "welcomePage.buttonHoverBackground": "#011627", + "walkThrough.embeddedEditorBackground": "#011627", + "gitDecoration.modifiedResourceForeground": "#a2bffc", + "gitDecoration.deletedResourceForeground": "#EF535090", + "gitDecoration.untrackedResourceForeground": "#c5e478ff", + "gitDecoration.ignoredResourceForeground": "#395a75", + "gitDecoration.conflictingResourceForeground": "#ffeb95cc", + "source.elm": "#5f7e97", + "string.quoted.single.js": "#ffffff", + "meta.objectliteral.js": "#82AAFF", + }, + "tokenColors": [ + { + "name": "Changed", + "scope": [ + "markup.changed", + "meta.diff.header.git", + "meta.diff.header.from-file", + "meta.diff.header.to-file", + ], + "settings": { + "foreground": "#a2bffc", + }, + }, + { + "name": "Deleted", + "scope": "markup.deleted.diff", + "settings": { + "foreground": "#EF535090", + }, + }, + { + "name": "Inserted", + "scope": "markup.inserted.diff", + "settings": { + "foreground": "#c5e478ff", + }, + }, + { + "name": "Global settings", + "settings": { + "background": "#011627", + "foreground": "#d6deeb", + }, + }, + { + "name": "Comment", + "scope": "comment", + "settings": { + "foreground": "#637777", + "fontStyle": "", + }, + }, + { + "name": "String", + "scope": "string", + "settings": { + "foreground": "#ecc48d", + }, + }, + { + "name": "String Quoted", + "scope": ["string.quoted", "variable.other.readwrite.js"], + "settings": { + "foreground": "#ecc48d", + }, + }, + { + "name": "Support Constant Math", + "scope": "support.constant.math", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Number", + "scope": ["constant.numeric", "constant.character.numeric"], + "settings": { + "foreground": "#F78C6C", + "fontStyle": "", + }, + }, + { + "name": "Built-in constant", + "scope": ["constant.language", "punctuation.definition.constant", "variable.other.constant"], + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "User-defined constant", + "scope": ["constant.character", "constant.other"], + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "Constant Character Escape", + "scope": "constant.character.escape", + "settings": { + "foreground": "#F78C6C", + }, + }, + { + "name": "RegExp String", + "scope": ["string.regexp", "string.regexp keyword.other"], + "settings": { + "foreground": "#5ca7e4", + }, + }, + { + "name": "Comma in functions", + "scope": "meta.function punctuation.separator.comma", + "settings": { + "foreground": "#5f7e97", + }, + }, + { + "name": "Variable", + "scope": "variable", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Keyword", + "scope": ["punctuation.accessor", "keyword"], + "settings": { + "foreground": "#c792ea", + "fontStyle": "", + }, + }, + { + "name": "Storage", + "scope": [ + "storage", + "meta.var.expr", + "meta.class meta.method.declaration meta.var.expr storage.type.js", + "storage.type.property.js", + "storage.type.property.ts", + "storage.type.property.tsx", + ], + "settings": { + "foreground": "#c792ea", + "fontStyle": "", + }, + }, + { + "name": "Storage type", + "scope": "storage.type", + "settings": { + "foreground": "#c792ea", + }, + }, + { + "name": "Storage type", + "scope": "storage.type.function.arrow.js", + "settings": { + "fontStyle": "", + }, + }, + { + "name": "Class name", + "scope": ["entity.name.class", "meta.class entity.name.type.class"], + "settings": { + "foreground": "#ffcb8b", + }, + }, + { + "name": "Inherited class", + "scope": "entity.other.inherited-class", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Function name", + "scope": "entity.name.function", + "settings": { + "foreground": "#c792ea", + "fontStyle": "", + }, + }, + { + "name": "Meta Tag", + "scope": ["punctuation.definition.tag", "meta.tag"], + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "HTML Tag names", + "scope": [ + "entity.name.tag", + "meta.tag.other.html", + "meta.tag.other.js", + "meta.tag.other.tsx", + "entity.name.tag.tsx", + "entity.name.tag.js", + "entity.name.tag", + "meta.tag.js", + "meta.tag.tsx", + "meta.tag.html", + ], + "settings": { + "foreground": "#caece6", + "fontStyle": "", + }, + }, + { + "name": "Tag attribute", + "scope": "entity.other.attribute-name", + "settings": { + "fontStyle": "", + "foreground": "#c5e478", + }, + }, + { + "name": "Entity Name Tag Custom", + "scope": "entity.name.tag.custom", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Library (function & constant)", + "scope": ["support.function", "support.constant"], + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "Support Constant Property Value meta", + "scope": "support.constant.meta.property-value", + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "Library class/type", + "scope": ["support.type", "support.class"], + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Support Variable DOM", + "scope": "support.variable.dom", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Invalid", + "scope": "invalid", + "settings": { + "background": "#ff2c83", + "foreground": "#ffffff", + }, + }, + { + "name": "Invalid deprecated", + "scope": "invalid.deprecated", + "settings": { + "foreground": "#ffffff", + "background": "#d3423e", + }, + }, + { + "name": "Keyword Operator", + "scope": "keyword.operator", + "settings": { + "foreground": "#7fdbca", + "fontStyle": "", + }, + }, + { + "name": "Keyword Operator Relational", + "scope": "keyword.operator.relational", + "settings": { + "foreground": "#c792ea", + "fontStyle": "", + }, + }, + { + "name": "Keyword Operator Assignment", + "scope": "keyword.operator.assignment", + "settings": { + "foreground": "#c792ea", + }, + }, + { + "name": "Keyword Operator Arithmetic", + "scope": "keyword.operator.arithmetic", + "settings": { + "foreground": "#c792ea", + }, + }, + { + "name": "Keyword Operator Bitwise", + "scope": "keyword.operator.bitwise", + "settings": { + "foreground": "#c792ea", + }, + }, + { + "name": "Keyword Operator Increment", + "scope": "keyword.operator.increment", + "settings": { + "foreground": "#c792ea", + }, + }, + { + "name": "Keyword Operator Ternary", + "scope": "keyword.operator.ternary", + "settings": { + "foreground": "#c792ea", + }, + }, + { + "name": "Double-Slashed Comment", + "scope": "comment.line.double-slash", + "settings": { + "foreground": "#637777", + }, + }, + { + "name": "Object", + "scope": "object", + "settings": { + "foreground": "#cdebf7", + }, + }, + { + "name": "Null", + "scope": "constant.language.null", + "settings": { + "foreground": "#ff5874", + }, + }, + { + "name": "Meta Brace", + "scope": "meta.brace", + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "Meta Delimiter Period", + "scope": "meta.delimiter.period", + "settings": { + "foreground": "#c792ea", + "fontStyle": "", + }, + }, + { + "name": "Punctuation Definition String", + "scope": "punctuation.definition.string", + "settings": { + "foreground": "#d9f5dd", + }, + }, + { + "name": "Punctuation Definition String Markdown", + "scope": "punctuation.definition.string.begin.markdown", + "settings": { + "foreground": "#ff5874", + }, + }, + { + "name": "Boolean", + "scope": "constant.language.boolean", + "settings": { + "foreground": "#ff5874", + }, + }, + { + "name": "Object Comma", + "scope": "object.comma", + "settings": { + "foreground": "#ffffff", + }, + }, + { + "name": "Variable Parameter Function", + "scope": "variable.parameter.function", + "settings": { + "foreground": "#7fdbca", + "fontStyle": "", + }, + }, + { + "name": "Support Type Property Name & entity name tags", + "scope": [ + "support.type.vendor.property-name", + "support.constant.vendor.property-value", + "support.type.property-name", + "meta.property-list entity.name.tag", + ], + "settings": { + "foreground": "#80CBC4", + "fontStyle": "", + }, + }, + { + "name": "Entity Name tag reference in stylesheets", + "scope": "meta.property-list entity.name.tag.reference", + "settings": { + "foreground": "#57eaf1", + }, + }, + { + "name": "Constant Other Color RGB Value Punctuation Definition Constant", + "scope": "constant.other.color.rgb-value punctuation.definition.constant", + "settings": { + "foreground": "#F78C6C", + }, + }, + { + "name": "Constant Other Color", + "scope": "constant.other.color", + "settings": { + "foreground": "#FFEB95", + }, + }, + { + "name": "Keyword Other Unit", + "scope": "keyword.other.unit", + "settings": { + "foreground": "#FFEB95", + }, + }, + { + "name": "Meta Selector", + "scope": "meta.selector", + "settings": { + "foreground": "#c792ea", + "fontStyle": "", + }, + }, + { + "name": "Entity Other Attribute Name Id", + "scope": "entity.other.attribute-name.id", + "settings": { + "foreground": "#FAD430", + }, + }, + { + "name": "Meta Property Name", + "scope": "meta.property-name", + "settings": { + "foreground": "#80CBC4", + }, + }, + { + "name": "Doctypes", + "scope": ["entity.name.tag.doctype", "meta.tag.sgml.doctype"], + "settings": { + "foreground": "#c792ea", + "fontStyle": "", + }, + }, + { + "name": "Punctuation Definition Parameters", + "scope": "punctuation.definition.parameters", + "settings": { + "foreground": "#d9f5dd", + }, + }, + { + "name": "Keyword Control Operator", + "scope": "keyword.control.operator", + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "Keyword Operator Logical", + "scope": "keyword.operator.logical", + "settings": { + "foreground": "#c792ea", + "fontStyle": "", + }, + }, + { + "name": "Variable Instances", + "scope": [ + "variable.instance", + "variable.other.instance", + "variable.readwrite.instance", + "variable.other.readwrite.instance", + "variable.other.property", + ], + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "Variable Property Other object property", + "scope": ["variable.other.object.property"], + "settings": { + "foreground": "#faf39f", + "fontStyle": "", + }, + }, + { + "name": "Variable Property Other object", + "scope": ["variable.other.object.js"], + "settings": { + "fontStyle": "", + }, + }, + { + "name": "Entity Name Function", + "scope": ["entity.name.function"], + "settings": { + "foreground": "#82AAFF", + "fontStyle": "", + }, + }, + { + "name": "Keyword Operator Comparison, returns, imports, and Keyword Operator Ruby", + "scope": [ + "keyword.control.conditional.js", + "keyword.operator.comparison", + "keyword.control.flow.js", + "keyword.control.flow.ts", + "keyword.control.flow.tsx", + "keyword.control.ruby", + "keyword.control.def.ruby", + "keyword.control.loop.js", + "keyword.control.loop.ts", + "keyword.control.import.js", + "keyword.control.import.ts", + "keyword.control.import.tsx", + "keyword.control.from.js", + "keyword.control.from.ts", + "keyword.control.from.tsx", + "keyword.control.conditional.js", + "keyword.control.conditional.ts", + "keyword.control.switch.js", + "keyword.control.switch.ts", + "keyword.operator.instanceof.js", + "keyword.operator.expression.instanceof.ts", + "keyword.operator.expression.instanceof.tsx", + ], + "settings": { + "foreground": "#c792ea", + "fontStyle": "", + }, + }, + { + "name": "Support Constant, `new` keyword, Special Method Keyword, `debugger`, other keywords", + "scope": [ + "support.constant", + "keyword.other.special-method", + "keyword.other.new", + "keyword.other.debugger", + "keyword.control", + ], + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "Support Function", + "scope": "support.function", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Invalid Broken", + "scope": "invalid.broken", + "settings": { + "foreground": "#020e14", + "background": "#F78C6C", + }, + }, + { + "name": "Invalid Unimplemented", + "scope": "invalid.unimplemented", + "settings": { + "background": "#8BD649", + "foreground": "#ffffff", + }, + }, + { + "name": "Invalid Illegal", + "scope": "invalid.illegal", + "settings": { + "foreground": "#ffffff", + "background": "#ec5f67", + }, + }, + { + "name": "Language Variable", + "scope": "variable.language", + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "Support Variable Property", + "scope": "support.variable.property", + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "Variable Function", + "scope": "variable.function", + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "Variable Interpolation", + "scope": "variable.interpolation", + "settings": { + "foreground": "#ec5f67", + }, + }, + { + "name": "Meta Function Call", + "scope": "meta.function-call", + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "Punctuation Section Embedded", + "scope": "punctuation.section.embedded", + "settings": { + "foreground": "#d3423e", + }, + }, + { + "name": "Punctuation Tweaks", + "scope": [ + "punctuation.terminator.expression", + "punctuation.definition.arguments", + "punctuation.definition.array", + "punctuation.section.array", + "meta.array", + ], + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "More Punctuation Tweaks", + "scope": [ + "punctuation.definition.list.begin", + "punctuation.definition.list.end", + "punctuation.separator.arguments", + "punctuation.definition.list", + ], + "settings": { + "foreground": "#d9f5dd", + }, + }, + { + "name": "Template Strings", + "scope": "string.template meta.template.expression", + "settings": { + "foreground": "#d3423e", + }, + }, + { + "name": "Backticks(``) in Template Strings", + "scope": "string.template punctuation.definition.string", + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "Italics", + "scope": "italic", + "settings": { + "foreground": "#c792ea", + "fontStyle": "italic", + }, + }, + { + "name": "Bold", + "scope": "bold", + "settings": { + "foreground": "#c5e478", + "fontStyle": "bold", + }, + }, + { + "name": "Quote", + "scope": "quote", + "settings": { + "foreground": "#697098", + "fontStyle": "", + }, + }, + { + "name": "Raw Code", + "scope": "raw", + "settings": { + "foreground": "#80CBC4", + }, + }, + { + "name": "CoffeeScript Variable Assignment", + "scope": "variable.assignment.coffee", + "settings": { + "foreground": "#31e1eb", + }, + }, + { + "name": "CoffeeScript Parameter Function", + "scope": "variable.parameter.function.coffee", + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "CoffeeScript Assignments", + "scope": "variable.assignment.coffee", + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "C# Readwrite Variables", + "scope": "variable.other.readwrite.cs", + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "C# Classes & Storage types", + "scope": ["entity.name.type.class.cs", "storage.type.cs"], + "settings": { + "foreground": "#ffcb8b", + }, + }, + { + "name": "C# Namespaces", + "scope": "entity.name.type.namespace.cs", + "settings": { + "foreground": "#B2CCD6", + }, + }, + { + "name": "C# Unquoted String Zone", + "scope": "string.unquoted.preprocessor.message.cs", + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "C# Region", + "scope": [ + "punctuation.separator.hash.cs", + "keyword.preprocessor.region.cs", + "keyword.preprocessor.endregion.cs", + ], + "settings": { + "foreground": "#ffcb8b", + "fontStyle": "bold", + }, + }, + { + "name": "C# Other Variables", + "scope": "variable.other.object.cs", + "settings": { + "foreground": "#B2CCD6", + }, + }, + { + "name": "C# Enum", + "scope": "entity.name.type.enum.cs", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Dart String", + "scope": ["string.interpolated.single.dart", "string.interpolated.double.dart"], + "settings": { + "foreground": "#FFCB8B", + }, + }, + { + "name": "Dart Class", + "scope": "support.class.dart", + "settings": { + "foreground": "#FFCB8B", + }, + }, + { + "name": "Tag names in Stylesheets", + "scope": [ + "entity.name.tag.css", + "entity.name.tag.less", + "entity.name.tag.custom.css", + "support.constant.property-value.css", + ], + "settings": { + "foreground": "#ff6363", + "fontStyle": "", + }, + }, + { + "name": "Wildcard(*) selector in Stylesheets", + "scope": [ + "entity.name.tag.wildcard.css", + "entity.name.tag.wildcard.less", + "entity.name.tag.wildcard.scss", + "entity.name.tag.wildcard.sass", + ], + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "CSS Keyword Other Unit", + "scope": "keyword.other.unit.css", + "settings": { + "foreground": "#FFEB95", + }, + }, + { + "name": "Attribute Name for CSS", + "scope": [ + "meta.attribute-selector.css entity.other.attribute-name.attribute", + "variable.other.readwrite.js", + ], + "settings": { + "foreground": "#F78C6C", + }, + }, + { + "name": "Elixir Classes", + "scope": [ + "source.elixir support.type.elixir", + "source.elixir meta.module.elixir entity.name.class.elixir", + ], + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "Elixir Functions", + "scope": "source.elixir entity.name.function", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Elixir Constants", + "scope": [ + "source.elixir constant.other.symbol.elixir", + "source.elixir constant.other.keywords.elixir", + ], + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "Elixir String Punctuations", + "scope": "source.elixir punctuation.definition.string", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Elixir", + "scope": [ + "source.elixir variable.other.readwrite.module.elixir", + "source.elixir variable.other.readwrite.module.elixir punctuation.definition.variable.elixir", + ], + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Elixir Binary Punctuations", + "scope": "source.elixir .punctuation.binary.elixir", + "settings": { + "foreground": "#c792ea", + "fontStyle": "", + }, + }, + { + "name": "Closure Constant Keyword", + "scope": "constant.keyword.clojure", + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "Go Function Calls", + "scope": "source.go meta.function-call.go", + "settings": { + "foreground": "#DDDDDD", + }, + }, + { + "name": "Go Keywords", + "scope": [ + "source.go keyword.package.go", + "source.go keyword.import.go", + "source.go keyword.function.go", + "source.go keyword.type.go", + "source.go keyword.struct.go", + "source.go keyword.interface.go", + "source.go keyword.const.go", + "source.go keyword.var.go", + "source.go keyword.map.go", + "source.go keyword.channel.go", + "source.go keyword.control.go", + ], + "settings": { + "foreground": "#c792ea", + }, + }, + { + "name": "Go Constants e.g. nil, string format (%s, %d, etc.)", + "scope": ["source.go constant.language.go", "source.go constant.other.placeholder.go"], + "settings": { + "foreground": "#ff5874", + }, + }, + { + "name": "C++ Functions", + "scope": ["entity.name.function.preprocessor.cpp", "entity.scope.name.cpp"], + "settings": { + "foreground": "#7fdbcaff", + }, + }, + { + "name": "C++ Meta Namespace", + "scope": ["meta.namespace-block.cpp"], + "settings": { + "foreground": "#e0dec6", + }, + }, + { + "name": "C++ Language Primitive Storage", + "scope": ["storage.type.language.primitive.cpp"], + "settings": { + "foreground": "#ff5874", + }, + }, + { + "name": "C++ Preprocessor Macro", + "scope": ["meta.preprocessor.macro.cpp"], + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "C++ Variable Parameter", + "scope": ["variable.parameter"], + "settings": { + "foreground": "#ffcb8b", + }, + }, + { + "name": "Powershell Variables", + "scope": ["variable.other.readwrite.powershell"], + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "Powershell Function", + "scope": ["support.function.powershell"], + "settings": { + "foreground": "#7fdbcaff", + }, + }, + { + "name": "ID Attribute Name in HTML", + "scope": "entity.other.attribute-name.id.html", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "HTML Punctuation Definition Tag", + "scope": "punctuation.definition.tag.html", + "settings": { + "foreground": "#6ae9f0", + }, + }, + { + "name": "HTML Doctype", + "scope": "meta.tag.sgml.doctype.html", + "settings": { + "foreground": "#c792ea", + "fontStyle": "", + }, + }, + { + "name": "JavaScript Classes", + "scope": "meta.class entity.name.type.class.js", + "settings": { + "foreground": "#ffcb8b", + }, + }, + { + "name": "JavaScript Method Declaration e.g. `constructor`", + "scope": "meta.method.declaration storage.type.js", + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "JavaScript Terminator", + "scope": "terminator.js", + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "JavaScript Meta Punctuation Definition", + "scope": "meta.js punctuation.definition.js", + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "Entity Names in Code Documentations", + "scope": ["entity.name.type.instance.jsdoc", "entity.name.type.instance.phpdoc"], + "settings": { + "foreground": "#5f7e97", + }, + }, + { + "name": "Other Variables in Code Documentations", + "scope": ["variable.other.jsdoc", "variable.other.phpdoc"], + "settings": { + "foreground": "#78ccf0", + }, + }, + { + "name": "JavaScript module imports and exports", + "scope": [ + "variable.other.meta.import.js", + "meta.import.js variable.other", + "variable.other.meta.export.js", + "meta.export.js variable.other", + ], + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "JavaScript Variable Parameter Function", + "scope": "variable.parameter.function.js", + "settings": { + "foreground": "#7986E7", + }, + }, + { + "name": "JavaScript[React] Variable Other Object", + "scope": [ + "variable.other.object.js", + "variable.other.object.jsx", + "variable.object.property.js", + "variable.object.property.jsx", + ], + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "JavaScript Variables", + "scope": ["variable.js", "variable.other.js"], + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "JavaScript Entity Name Type", + "scope": ["entity.name.type.js", "entity.name.type.module.js"], + "settings": { + "foreground": "#ffcb8b", + "fontStyle": "", + }, + }, + { + "name": "JavaScript Support Classes", + "scope": "support.class.js", + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "JSON Property Names", + "scope": "support.type.property-name.json", + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "JSON Support Constants", + "scope": "support.constant.json", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "JSON Property values (string)", + "scope": "meta.structure.dictionary.value.json string.quoted.double", + "settings": { + "foreground": "#c789d6", + }, + }, + { + "name": "Strings in JSON values", + "scope": "string.quoted.double.json punctuation.definition.string.json", + "settings": { + "foreground": "#80CBC4", + }, + }, + { + "name": "Specific JSON Property values like null", + "scope": "meta.structure.dictionary.json meta.structure.dictionary.value constant.language", + "settings": { + "foreground": "#ff5874", + }, + }, + { + "name": "JavaScript Other Variable", + "scope": "variable.other.object.js", + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "Ruby Variables", + "scope": ["variable.other.ruby"], + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "Ruby Class", + "scope": ["entity.name.type.class.ruby"], + "settings": { + "foreground": "#ecc48d", + }, + }, + { + "name": "Ruby Hashkeys", + "scope": "constant.language.symbol.hashkey.ruby", + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "LESS Tag names", + "scope": "entity.name.tag.less", + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "LESS Keyword Other Unit", + "scope": "keyword.other.unit.css", + "settings": { + "foreground": "#FFEB95", + }, + }, + { + "name": "Attribute Name for LESS", + "scope": "meta.attribute-selector.less entity.other.attribute-name.attribute", + "settings": { + "foreground": "#F78C6C", + }, + }, + { + "name": "Markdown Headings", + "scope": [ + "markup.heading.markdown", + "markup.heading.setext.1.markdown", + "markup.heading.setext.2.markdown", + ], + "settings": { + "foreground": "#82b1ff", + }, + }, + { + "name": "Markdown Italics", + "scope": "markup.italic.markdown", + "settings": { + "foreground": "#c792ea", + "fontStyle": "italic", + }, + }, + { + "name": "Markdown Bold", + "scope": "markup.bold.markdown", + "settings": { + "foreground": "#c5e478", + "fontStyle": "bold", + }, + }, + { + "name": "Markdown Quote + others", + "scope": "markup.quote.markdown", + "settings": { + "foreground": "#697098", + "fontStyle": "", + }, + }, + { + "name": "Markdown Raw Code + others", + "scope": "markup.inline.raw.markdown", + "settings": { + "foreground": "#80CBC4", + }, + }, + { + "name": "Markdown Links", + "scope": ["markup.underline.link.markdown", "markup.underline.link.image.markdown"], + "settings": { + "foreground": "#ff869a", + }, + }, + { + "name": "Markdown Link Title and Description", + "scope": ["string.other.link.title.markdown", "string.other.link.description.markdown"], + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "Markdown Punctuation", + "scope": [ + "punctuation.definition.string.markdown", + "punctuation.definition.string.begin.markdown", + "punctuation.definition.string.end.markdown", + "meta.link.inline.markdown punctuation.definition.string", + ], + "settings": { + "foreground": "#82b1ff", + }, + }, + { + "name": "Markdown MetaData Punctuation", + "scope": ["punctuation.definition.metadata.markdown"], + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "Markdown List Punctuation", + "scope": ["beginning.punctuation.definition.list.markdown"], + "settings": { + "foreground": "#82b1ff", + }, + }, + { + "name": "Markdown Inline Raw String", + "scope": "markup.inline.raw.string.markdown", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "PHP Variables", + "scope": "variable.other.php", + "settings": { + "foreground": "#bec5d4", + }, + }, + { + "name": "Support Classes in PHP", + "scope": "support.class.php", + "settings": { + "foreground": "#ffcb8b", + }, + }, + { + "name": "Punctuations in PHP function calls", + "scope": "meta.function-call.php punctuation", + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "PHP Global Variables", + "scope": "variable.other.global.php", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Declaration Punctuation in PHP Global Variables", + "scope": "variable.other.global.php punctuation.definition.variable", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Language Constants in Python", + "scope": "constant.language.python", + "settings": { + "foreground": "#ff5874", + }, + }, + { + "name": "Python Function Parameter and Arguments", + "scope": ["variable.parameter.function.python", "meta.function-call.arguments.python"], + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "Python Function Call", + "scope": ["meta.function-call.python", "meta.function-call.generic.python"], + "settings": { + "foreground": "#B2CCD6", + }, + }, + { + "name": "Punctuations in Python", + "scope": "punctuation.python", + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "Decorator Functions in Python", + "scope": "entity.name.function.decorator.python", + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Python Language Variable", + "scope": "source.python variable.language.special", + "settings": { + "foreground": "#8EACE3", + }, + }, + { + "name": "Python import control keyword", + "scope": "keyword.control", + "settings": { + "foreground": "#c792ea", + }, + }, + { + "name": "SCSS Variable", + "scope": [ + "variable.scss", + "variable.sass", + "variable.parameter.url.scss", + "variable.parameter.url.sass", + ], + "settings": { + "foreground": "#c5e478", + }, + }, + { + "name": "Variables in SASS At-Rules", + "scope": ["source.css.scss meta.at-rule variable", "source.css.sass meta.at-rule variable"], + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "Variables in SASS At-Rules", + "scope": ["source.css.scss meta.at-rule variable", "source.css.sass meta.at-rule variable"], + "settings": { + "foreground": "#bec5d4", + }, + }, + { + "name": "Attribute Name for SASS", + "scope": [ + "meta.attribute-selector.scss entity.other.attribute-name.attribute", + "meta.attribute-selector.sass entity.other.attribute-name.attribute", + ], + "settings": { + "foreground": "#F78C6C", + }, + }, + { + "name": "Tag names in SASS", + "scope": ["entity.name.tag.scss", "entity.name.tag.sass"], + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "SASS Keyword Other Unit", + "scope": ["keyword.other.unit.scss", "keyword.other.unit.sass"], + "settings": { + "foreground": "#FFEB95", + }, + }, + { + "name": "TypeScript[React] Variables and Object Properties", + "scope": [ + "variable.other.readwrite.alias.ts", + "variable.other.readwrite.alias.tsx", + "variable.other.readwrite.ts", + "variable.other.readwrite.tsx", + "variable.other.object.ts", + "variable.other.object.tsx", + "variable.object.property.ts", + "variable.object.property.tsx", + "variable.other.ts", + "variable.other.tsx", + "variable.tsx", + "variable.ts", + ], + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "TypeScript[React] Entity Name Types", + "scope": ["entity.name.type.ts", "entity.name.type.tsx"], + "settings": { + "foreground": "#ffcb8b", + }, + }, + { + "name": "TypeScript[React] Node Classes", + "scope": ["support.class.node.ts", "support.class.node.tsx"], + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "TypeScript[React] Entity Name Types as Parameters", + "scope": [ + "meta.type.parameters.ts entity.name.type", + "meta.type.parameters.tsx entity.name.type", + ], + "settings": { + "foreground": "#5f7e97", + }, + }, + { + "name": "TypeScript[React] Import/Export Punctuations", + "scope": [ + "meta.import.ts punctuation.definition.block", + "meta.import.tsx punctuation.definition.block", + "meta.export.ts punctuation.definition.block", + "meta.export.tsx punctuation.definition.block", + ], + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "TypeScript[React] Punctuation Decorators", + "scope": [ + "meta.decorator punctuation.decorator.ts", + "meta.decorator punctuation.decorator.tsx", + ], + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "TypeScript[React] Punctuation Decorators", + "scope": "meta.tag.js meta.jsx.children.tsx", + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "YAML Entity Name Tags", + "scope": "entity.name.tag.yaml", + "settings": { + "foreground": "#7fdbca", + }, + }, + { + "name": "JavaScript Variable Other ReadWrite", + "scope": ["variable.other.readwrite.js", "variable.parameter"], + "settings": { + "foreground": "#d7dbe0", + }, + }, + { + "name": "Support Class Component", + "scope": ["support.class.component.js", "support.class.component.tsx"], + "settings": { + "foreground": "#f78c6c", + "fontStyle": "", + }, + }, + { + "name": "Text nested in React tags", + "scope": ["meta.jsx.children", "meta.jsx.children.js", "meta.jsx.children.tsx"], + "settings": { + "foreground": "#d6deeb", + }, + }, + { + "name": "TypeScript Classes", + "scope": "meta.class entity.name.type.class.tsx", + "settings": { + "foreground": "#ffcb8b", + }, + }, + { + "name": "TypeScript Entity Name Type", + "scope": ["entity.name.type.tsx", "entity.name.type.module.tsx"], + "settings": { + "foreground": "#ffcb8b", + }, + }, + { + "name": "TypeScript Class Variable Keyword", + "scope": [ + "meta.class.ts meta.var.expr.ts storage.type.ts", + "meta.class.tsx meta.var.expr.tsx storage.type.tsx", + ], + "settings": { + "foreground": "#C792EA", + }, + }, + { + "name": "TypeScript Method Declaration e.g. `constructor`", + "scope": [ + "meta.method.declaration storage.type.ts", + "meta.method.declaration storage.type.tsx", + ], + "settings": { + "foreground": "#82AAFF", + }, + }, + { + "name": "normalize font style of certain components", + "scope": [ + "meta.property-list.css meta.property-value.css variable.other.less", + "meta.property-list.scss variable.scss", + "meta.property-list.sass variable.sass", + "meta.brace", + "keyword.operator.operator", + "keyword.operator.or.regexp", + "keyword.operator.expression.in", + "keyword.operator.relational", + "keyword.operator.assignment", + "keyword.operator.comparison", + "keyword.operator.type", + "keyword.operator", + "keyword", + "punctuation.definition.string", + "punctuation", + "variable.other.readwrite.js", + "storage.type", + "source.css", + "string.quoted", + ], + "settings": { + "fontStyle": "", + }, + }, + ], +} diff --git a/packages/starlight/integrations/expressive-code/themes/night-owl-light.jsonc b/packages/starlight/integrations/expressive-code/themes/night-owl-light.jsonc new file mode 100644 index 00000000000..f48d6b8481a --- /dev/null +++ b/packages/starlight/integrations/expressive-code/themes/night-owl-light.jsonc @@ -0,0 +1,1695 @@ +/** + * Night Owl VS Code Theme - https://github.com/sdras/night-owl-vscode-theme + * + * MIT License + * + * Copyright (c) 2018 Sarah Drasner + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +{ + "name": "Night Owl Light", + "type": "light", + "semanticHighlighting": false, + "colors": { + "foreground": "#403f53", + "focusBorder": "#93A1A1", + "errorForeground": "#403f53", + "selection.background": "#7a8181ad", + "descriptionForeground": "#403f53", + "widget.shadow": "#d9d9d9", + "titleBar.activeBackground": "#F0F0F0", + "notifications.background": "#F0F0F0", + "notifications.foreground": "#403f53", + "notificationLink.foreground": "#994cc3", + "notifications.border": "#CCCCCC", + "notificationCenter.border": "#CCCCCC", + "notificationToast.border": "#CCCCCC", + "notificationCenterHeader.foreground": "#403f53", + "notificationCenterHeader.background": "#F0F0F0", + "button.background": "#2AA298", + "button.foreground": "#F0F0F0", + "dropdown.background": "#F0F0F0", + "dropdown.foreground": "#403f53", + "dropdown.border": "#d9d9d9", + "input.background": "#F0F0F0", + "input.foreground": "#403f53", + "input.border": "#d9d9d9", + "input.placeholderForeground": "#93A1A1", + "inputOption.activeBorder": "#2AA298", + "inputValidation.infoBorder": "#D0D0D0", + "inputValidation.infoBackground": "#F0F0F0", + "inputValidation.warningBackground": "#daaa01", + "inputValidation.warningBorder": "#E0AF02", + "inputValidation.errorBackground": "#f76e6e", + "inputValidation.errorBorder": "#de3d3b", + "badge.background": "#2AA298", + "badge.foreground": "#F0F0F0", + "progressBar.background": "#2AA298", + "list.activeSelectionBackground": "#d3e8f8", + "list.activeSelectionForeground": "#403f53", + "list.inactiveSelectionBackground": "#E0E7EA", + "list.inactiveSelectionForeground": "#403f53", + "list.focusBackground": "#d3e8f8", + "list.hoverBackground": "#d3e8f8", + "list.focusForeground": "#403f53", + "list.hoverForeground": "#403f53", + "list.highlightForeground": "#403f53", + "list.errorForeground": "#E64D49", + "list.warningForeground": "#daaa01", + "activityBar.background": "#F0F0F0", + "activityBar.foreground": "#403f53", + "activityBar.dropBackground": "#D0D0D0", + "activityBarBadge.background": "#403f53", + "activityBarBadge.foreground": "#F0F0F0", + "activityBar.border": "#F0F0F0", + "sideBar.background": "#F0F0F0", + "sideBar.foreground": "#403f53", + "sideBarTitle.foreground": "#403f53", + "sideBar.border": "#F0F0F0", + "scrollbar.shadow": "#CCCCCC", + "tab.border": "#F0F0F0", + "tab.activeBackground": "#F6F6F6", + "tab.activeForeground": "#403f53", + "tab.inactiveForeground": "#403f53", + "tab.inactiveBackground": "#F0F0F0", + "editorGroup.border": "#F0F0F0", + "editorGroup.background": "#F6F6F6", + "editorGroupHeader.tabsBackground": "#F0F0F0", + "editorGroupHeader.tabsBorder": "#F0F0F0", + "editorGroupHeader.noTabsBackground": "#F0F0F0", + "tab.activeModifiedBorder": "#2AA298", + "tab.inactiveModifiedBorder": "#93A1A1", + "tab.unfocusedActiveModifiedBorder": "#93A1A1", + "tab.unfocusedInactiveModifiedBorder": "#93A1A1", + "editor.background": "#FBFBFB", + "editor.foreground": "#403f53", + "editorCursor.foreground": "#90A7B2", + "editorLineNumber.foreground": "#90A7B2", + "editorLineNumber.activeForeground": "#403f53", + "editor.selectionBackground": "#E0E0E0", + "editor.selectionHighlightBackground": "#339cec33", + "editor.wordHighlightBackground": "#339cec33", + "editor.wordHighlightStrongBackground": "#007dd659", + "editor.findMatchBackground": "#93A1A16c", + "editor.findMatchHighlightBackground": "#93a1a16c", + "editor.findRangeHighlightBackground": "#7497a633", + "editor.hoverHighlightBackground": "#339cec33", + "editor.lineHighlightBackground": "#F0F0F0", + "editor.rangeHighlightBackground": "#7497a633", + "editorWhitespace.foreground": "#d9d9d9", + "editorIndentGuide.background": "#d9d9d9", + "editorCodeLens.foreground": "#403f53", + "editorBracketMatch.background": "#d3e8f8", + "editorBracketMatch.border": "#2AA298", + "editorError.foreground": "#E64D49", + "editorError.border": "#FBFBFB", + "editorWarning.foreground": "#daaa01", + "editorWarning.border": "#daaa01", + "editorGutter.addedBackground": "#49d0c5", + "editorGutter.modifiedBackground": "#6fbef6", + "editorGutter.deletedBackground": "#f76e6e", + "editorRuler.foreground": "#d9d9d9", + "editorOverviewRuler.errorForeground": "#E64D49", + "editorOverviewRuler.warningForeground": "#daaa01", + "editorWidget.background": "#F0F0F0", + "editorWidget.border": "#d9d9d9", + "editorSuggestWidget.background": "#F0F0F0", + "editorSuggestWidget.foreground": "#403f53", + "editorSuggestWidget.highlightForeground": "#403f53", + "editorSuggestWidget.selectedBackground": "#d3e8f8", + "editorSuggestWidget.border": "#d9d9d9", + "editorHoverWidget.background": "#F0F0F0", + "editorHoverWidget.border": "#d9d9d9", + "debugExceptionWidget.background": "#F0F0F0", + "debugExceptionWidget.border": "#d9d9d9", + "editorMarkerNavigation.background": "#D0D0D0", + "editorMarkerNavigationError.background": "#f76e6e", + "editorMarkerNavigationWarning.background": "#daaa01", + "debugToolBar.background": "#F0F0F0", + "pickerGroup.border": "#d9d9d9", + "pickerGroup.foreground": "#403f53", + "extensionButton.prominentBackground": "#2AA298", + "extensionButton.prominentForeground": "#F0F0F0", + "statusBar.background": "#F0F0F0", + "statusBar.border": "#F0F0F0", + "statusBar.debuggingBackground": "#F0F0F0", + "statusBar.debuggingForeground": "#403f53", + "statusBar.foreground": "#403f53", + "statusBar.noFolderBackground": "#F0F0F0", + "statusBar.noFolderForeground": "#403f53", + "panel.background": "#F0F0F0", + "panel.border": "#d9d9d9", + "peekView.border": "#d9d9d9", + "peekViewEditor.background": "#F6F6F6", + "peekViewEditorGutter.background": "#F6F6F6", + "peekViewEditor.matchHighlightBackground": "#49d0c5", + "peekViewResult.background": "#F0F0F0", + "peekViewResult.fileForeground": "#403f53", + "peekViewResult.lineForeground": "#403f53", + "peekViewResult.matchHighlightBackground": "#49d0c5", + "peekViewResult.selectionBackground": "#E0E7EA", + "peekViewResult.selectionForeground": "#403f53", + "peekViewTitle.background": "#F0F0F0", + "peekViewTitleLabel.foreground": "#403f53", + "peekViewTitleDescription.foreground": "#403f53", + "terminal.ansiBrightBlack": "#403f53", + "terminal.ansiBlack": "#403f53", + "terminal.ansiBrightBlue": "#288ed7", + "terminal.ansiBlue": "#288ed7", + "terminal.ansiBrightCyan": "#2AA298", + "terminal.ansiCyan": "#2AA298", + "terminal.ansiBrightGreen": "#08916a", + "terminal.ansiGreen": "#08916a", + "terminal.ansiBrightMagenta": "#d6438a", + "terminal.ansiMagenta": "#d6438a", + "terminal.ansiBrightRed": "#de3d3b", + "terminal.ansiRed": "#de3d3b", + "terminal.ansiBrightWhite": "#F0F0F0", + "terminal.ansiWhite": "#F0F0F0", + "terminal.ansiBrightYellow": "#daaa01", + "terminal.ansiYellow": "#E0AF02", + "terminal.background": "#F6F6F6", + "terminal.foreground": "#403f53", + }, + "tokenColors": [ + { + "name": "Changed", + "scope": [ + "markup.changed", + "meta.diff.header.git", + "meta.diff.header.from-file", + "meta.diff.header.to-file", + ], + "settings": { + "foreground": "#a2bffc", + }, + }, + { + "name": "Deleted", + "scope": "markup.deleted.diff", + "settings": { + "foreground": "#EF535090", + }, + }, + { + "name": "Inserted", + "scope": "markup.inserted.diff", + "settings": { + "foreground": "#4876d6ff", + }, + }, + { + "name": "Global settings", + "settings": { + "background": "#011627", + "foreground": "#403f53", + }, + }, + { + "name": "Comment", + "scope": "comment", + "settings": { + "foreground": "#989fb1", + }, + }, + { + "name": "String", + "scope": "string", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "String Quoted", + "scope": ["string.quoted", "variable.other.readwrite.js"], + "settings": { + "foreground": "#c96765", + }, + }, + { + "name": "Support Constant Math", + "scope": "support.constant.math", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Number", + "scope": ["constant.numeric", "constant.character.numeric"], + "settings": { + "foreground": "#aa0982", + "fontStyle": "", + }, + }, + { + "name": "Built-in constant", + "scope": ["constant.language", "punctuation.definition.constant", "variable.other.constant"], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "User-defined constant", + "scope": ["constant.character", "constant.other"], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Constant Character Escape", + "scope": "constant.character.escape", + "settings": { + "foreground": "#aa0982", + }, + }, + { + "name": "RegExp String", + "scope": ["string.regexp", "string.regexp keyword.other"], + "settings": { + "foreground": "#5ca7e4", + }, + }, + { + "name": "Comma in functions", + "scope": "meta.function punctuation.separator.comma", + "settings": { + "foreground": "#5f7e97", + }, + }, + { + "name": "Variable", + "scope": "variable", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Keyword", + "scope": ["punctuation.accessor", "keyword"], + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Storage", + "scope": [ + "storage", + "meta.var.expr", + "meta.class meta.method.declaration meta.var.expr storage.type.js", + "storage.type.property.js", + "storage.type.property.ts", + "storage.type.property.tsx", + ], + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Storage type", + "scope": "storage.type", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Storage type", + "scope": "storage.type.function.arrow.js", + "settings": { + "fontStyle": "", + }, + }, + { + "name": "Class name", + "scope": ["entity.name.class", "meta.class entity.name.type.class"], + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "Inherited class", + "scope": "entity.other.inherited-class", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Function name", + "scope": "entity.name.function", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Meta Tag", + "scope": ["punctuation.definition.tag", "meta.tag"], + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "HTML Tag names", + "scope": [ + "entity.name.tag", + "meta.tag.other.html", + "meta.tag.other.js", + "meta.tag.other.tsx", + "entity.name.tag.tsx", + "entity.name.tag.js", + "entity.name.tag", + "meta.tag.js", + "meta.tag.tsx", + "meta.tag.html", + ], + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Tag attribute", + "scope": "entity.other.attribute-name", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Entity Name Tag Custom", + "scope": "entity.name.tag.custom", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Library (function & constant)", + "scope": ["support.function", "support.constant"], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Support Constant Property Value meta", + "scope": "support.constant.meta.property-value", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Library class/type", + "scope": ["support.type", "support.class"], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Support Variable DOM", + "scope": "support.variable.dom", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Invalid", + "scope": "invalid", + "settings": { + "foreground": "#ff2c83", + }, + }, + { + "name": "Invalid deprecated", + "scope": "invalid.deprecated", + "settings": { + "foreground": "#d3423e", + }, + }, + { + "name": "Keyword Operator", + "scope": "keyword.operator", + "settings": { + "foreground": "#0c969b", + "fontStyle": "", + }, + }, + { + "name": "Keyword Operator Relational", + "scope": "keyword.operator.relational", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Keyword Operator Assignment", + "scope": "keyword.operator.assignment", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Keyword Operator Arithmetic", + "scope": "keyword.operator.arithmetic", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Keyword Operator Bitwise", + "scope": "keyword.operator.bitwise", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Keyword Operator Increment", + "scope": "keyword.operator.increment", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Keyword Operator Ternary", + "scope": "keyword.operator.ternary", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Double-Slashed Comment", + "scope": "comment.line.double-slash", + "settings": { + "foreground": "#939dbb", + }, + }, + { + "name": "Object", + "scope": "object", + "settings": { + "foreground": "#cdebf7", + }, + }, + { + "name": "Null", + "scope": "constant.language.null", + "settings": { + "foreground": "#bc5454", + }, + }, + { + "name": "Meta Brace", + "scope": "meta.brace", + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "Meta Delimiter Period", + "scope": "meta.delimiter.period", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Punctuation Definition String", + "scope": "punctuation.definition.string", + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "Punctuation Definition String Markdown", + "scope": "punctuation.definition.string.begin.markdown", + "settings": { + "foreground": "#bc5454", + }, + }, + { + "name": "Boolean", + "scope": "constant.language.boolean", + "settings": { + "foreground": "#bc5454", + }, + }, + { + "name": "Object Comma", + "scope": "object.comma", + "settings": { + "foreground": "#ffffff", + }, + }, + { + "name": "Variable Parameter Function", + "scope": "variable.parameter.function", + "settings": { + "foreground": "#0c969b", + "fontStyle": "", + }, + }, + { + "name": "Support Type Property Name & entity name tags", + "scope": [ + "support.type.vendor.property-name", + "support.constant.vendor.property-value", + "support.type.property-name", + "meta.property-list entity.name.tag", + ], + "settings": { + "foreground": "#0c969b", + "fontStyle": "", + }, + }, + { + "name": "Entity Name tag reference in stylesheets", + "scope": "meta.property-list entity.name.tag.reference", + "settings": { + "foreground": "#57eaf1", + }, + }, + { + "name": "Constant Other Color RGB Value Punctuation Definition Constant", + "scope": "constant.other.color.rgb-value punctuation.definition.constant", + "settings": { + "foreground": "#aa0982", + }, + }, + { + "name": "Constant Other Color", + "scope": "constant.other.color", + "settings": { + "foreground": "#aa0982", + }, + }, + { + "name": "Keyword Other Unit", + "scope": "keyword.other.unit", + "settings": { + "foreground": "#aa0982", + }, + }, + { + "name": "Meta Selector", + "scope": "meta.selector", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Entity Other Attribute Name Id", + "scope": "entity.other.attribute-name.id", + "settings": { + "foreground": "#aa0982", + }, + }, + { + "name": "Meta Property Name", + "scope": "meta.property-name", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Doctypes", + "scope": ["entity.name.tag.doctype", "meta.tag.sgml.doctype"], + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Punctuation Definition Parameters", + "scope": "punctuation.definition.parameters", + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "Keyword Control Operator", + "scope": "keyword.control.operator", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Keyword Operator Logical", + "scope": "keyword.operator.logical", + "settings": { + "foreground": "#994cc3", + "fontStyle": "", + }, + }, + { + "name": "Variable Instances", + "scope": [ + "variable.instance", + "variable.other.instance", + "variable.readwrite.instance", + "variable.other.readwrite.instance", + "variable.other.property", + ], + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Variable Property Other object property", + "scope": ["variable.other.object.property"], + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "Variable Property Other object", + "scope": ["variable.other.object.js"], + "settings": { + "fontStyle": "", + }, + }, + { + "name": "Entity Name Function", + "scope": ["entity.name.function"], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Keyword Operator Comparison, imports, returns and Keyword Operator Ruby", + "scope": [ + "keyword.operator.comparison", + "keyword.control.flow.js", + "keyword.control.flow.ts", + "keyword.control.flow.tsx", + "keyword.control.ruby", + "keyword.control.module.ruby", + "keyword.control.class.ruby", + "keyword.control.def.ruby", + "keyword.control.loop.js", + "keyword.control.loop.ts", + "keyword.control.import.js", + "keyword.control.import.ts", + "keyword.control.import.tsx", + "keyword.control.from.js", + "keyword.control.from.ts", + "keyword.control.from.tsx", + "keyword.operator.instanceof.js", + "keyword.operator.expression.instanceof.ts", + "keyword.operator.expression.instanceof.tsx", + ], + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Keyword Control Conditional", + "scope": [ + "keyword.control.conditional.js", + "keyword.control.conditional.ts", + "keyword.control.switch.js", + "keyword.control.switch.ts", + ], + "settings": { + "foreground": "#994cc3", + "fontStyle": "", + }, + }, + { + "name": "Support Constant, `new` keyword, Special Method Keyword, `debugger`, other keywords", + "scope": [ + "support.constant", + "keyword.other.special-method", + "keyword.other.new", + "keyword.other.debugger", + "keyword.control", + ], + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Support Function", + "scope": "support.function", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Invalid Broken", + "scope": "invalid.broken", + "settings": { + "foreground": "#aa0982", + }, + }, + { + "name": "Invalid Unimplemented", + "scope": "invalid.unimplemented", + "settings": { + "foreground": "#8BD649", + }, + }, + { + "name": "Invalid Illegal", + "scope": "invalid.illegal", + "settings": { + "foreground": "#c96765", + }, + }, + { + "name": "Language Variable", + "scope": "variable.language", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Support Variable Property", + "scope": "support.variable.property", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Variable Function", + "scope": "variable.function", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Variable Interpolation", + "scope": "variable.interpolation", + "settings": { + "foreground": "#ec5f67", + }, + }, + { + "name": "Meta Function Call", + "scope": "meta.function-call", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Punctuation Section Embedded", + "scope": "punctuation.section.embedded", + "settings": { + "foreground": "#d3423e", + }, + }, + { + "name": "Punctuation Tweaks", + "scope": [ + "punctuation.terminator.expression", + "punctuation.definition.arguments", + "punctuation.definition.array", + "punctuation.section.array", + "meta.array", + ], + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "More Punctuation Tweaks", + "scope": [ + "punctuation.definition.list.begin", + "punctuation.definition.list.end", + "punctuation.separator.arguments", + "punctuation.definition.list", + ], + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "Template Strings", + "scope": "string.template meta.template.expression", + "settings": { + "foreground": "#d3423e", + }, + }, + { + "name": "Backticks(``) in Template Strings", + "scope": "string.template punctuation.definition.string", + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "Italics", + "scope": "italic", + "settings": { + "foreground": "#994cc3", + "fontStyle": "italic", + }, + }, + { + "name": "Bold", + "scope": "bold", + "settings": { + "foreground": "#4876d6", + "fontStyle": "bold", + }, + }, + { + "name": "Quote", + "scope": "quote", + "settings": { + "foreground": "#697098", + }, + }, + { + "name": "Raw Code", + "scope": "raw", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "CoffeeScript Variable Assignment", + "scope": "variable.assignment.coffee", + "settings": { + "foreground": "#31e1eb", + }, + }, + { + "name": "CoffeeScript Parameter Function", + "scope": "variable.parameter.function.coffee", + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "CoffeeScript Assignments", + "scope": "variable.assignment.coffee", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "C# Readwrite Variables", + "scope": "variable.other.readwrite.cs", + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "C# Classes & Storage types", + "scope": ["entity.name.type.class.cs", "storage.type.cs"], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "C# Namespaces", + "scope": "entity.name.type.namespace.cs", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Tag names in Stylesheets", + "scope": [ + "entity.name.tag.css", + "entity.name.tag.less", + "entity.name.tag.custom.css", + "support.constant.property-value.css", + ], + "settings": { + "foreground": "#c96765", + "fontStyle": "", + }, + }, + { + "name": "Wildcard(*) selector in Stylesheets", + "scope": [ + "entity.name.tag.wildcard.css", + "entity.name.tag.wildcard.less", + "entity.name.tag.wildcard.scss", + "entity.name.tag.wildcard.sass", + ], + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "CSS Keyword Other Unit", + "scope": "keyword.other.unit.css", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Attribute Name for CSS", + "scope": [ + "meta.attribute-selector.css entity.other.attribute-name.attribute", + "variable.other.readwrite.js", + ], + "settings": { + "foreground": "#aa0982", + }, + }, + { + "name": "Elixir Classes", + "scope": [ + "source.elixir support.type.elixir", + "source.elixir meta.module.elixir entity.name.class.elixir", + ], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Elixir Functions", + "scope": "source.elixir entity.name.function", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Elixir Constants", + "scope": [ + "source.elixir constant.other.symbol.elixir", + "source.elixir constant.other.keywords.elixir", + ], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Elixir String Punctuations", + "scope": "source.elixir punctuation.definition.string", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Elixir", + "scope": [ + "source.elixir variable.other.readwrite.module.elixir", + "source.elixir variable.other.readwrite.module.elixir punctuation.definition.variable.elixir", + ], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Elixir Binary Punctuations", + "scope": "source.elixir .punctuation.binary.elixir", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Closure Constant Keyword", + "scope": "constant.keyword.clojure", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Go Function Calls", + "scope": "source.go meta.function-call.go", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Go Keywords", + "scope": [ + "source.go keyword.package.go", + "source.go keyword.import.go", + "source.go keyword.function.go", + "source.go keyword.type.go", + "source.go keyword.struct.go", + "source.go keyword.interface.go", + "source.go keyword.const.go", + "source.go keyword.var.go", + "source.go keyword.map.go", + "source.go keyword.channel.go", + "source.go keyword.control.go", + ], + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "Go Constants e.g. nil, string format (%s, %d, etc.)", + "scope": ["source.go constant.language.go", "source.go constant.other.placeholder.go"], + "settings": { + "foreground": "#bc5454", + }, + }, + { + "name": "C++ Functions", + "scope": ["entity.name.function.preprocessor.cpp", "entity.scope.name.cpp"], + "settings": { + "foreground": "#0c969bff", + }, + }, + { + "name": "C++ Meta Namespace", + "scope": ["meta.namespace-block.cpp"], + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "C++ Language Primitive Storage", + "scope": ["storage.type.language.primitive.cpp"], + "settings": { + "foreground": "#bc5454", + }, + }, + { + "name": "C++ Preprocessor Macro", + "scope": ["meta.preprocessor.macro.cpp"], + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "C++ Variable Parameter", + "scope": ["variable.parameter"], + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "Powershell Variables", + "scope": ["variable.other.readwrite.powershell"], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Powershell Function", + "scope": ["support.function.powershell"], + "settings": { + "foreground": "#0c969bff", + }, + }, + { + "name": "ID Attribute Name in HTML", + "scope": "entity.other.attribute-name.id.html", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "HTML Punctuation Definition Tag", + "scope": "punctuation.definition.tag.html", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "HTML Doctype", + "scope": "meta.tag.sgml.doctype.html", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "JavaScript Classes", + "scope": "meta.class entity.name.type.class.js", + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "JavaScript Method Declaration e.g. `constructor`", + "scope": "meta.method.declaration storage.type.js", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "JavaScript Terminator", + "scope": "terminator.js", + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "JavaScript Meta Punctuation Definition", + "scope": "meta.js punctuation.definition.js", + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "Entity Names in Code Documentations", + "scope": ["entity.name.type.instance.jsdoc", "entity.name.type.instance.phpdoc"], + "settings": { + "foreground": "#5f7e97", + }, + }, + { + "name": "Other Variables in Code Documentations", + "scope": ["variable.other.jsdoc", "variable.other.phpdoc"], + "settings": { + "foreground": "#78ccf0", + }, + }, + { + "name": "JavaScript module imports and exports", + "scope": [ + "variable.other.meta.import.js", + "meta.import.js variable.other", + "variable.other.meta.export.js", + "meta.export.js variable.other", + ], + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "JavaScript Variable Parameter Function", + "scope": "variable.parameter.function.js", + "settings": { + "foreground": "#7986E7", + }, + }, + { + "name": "JavaScript[React] Variable Other Object", + "scope": [ + "variable.other.object.js", + "variable.other.object.jsx", + "variable.object.property.js", + "variable.object.property.jsx", + ], + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "JavaScript Variables", + "scope": ["variable.js", "variable.other.js"], + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "JavaScript Entity Name Type", + "scope": ["entity.name.type.js", "entity.name.type.module.js"], + "settings": { + "foreground": "#111111", + "fontStyle": "", + }, + }, + { + "name": "JavaScript Support Classes", + "scope": "support.class.js", + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "JSON Property Names", + "scope": "support.type.property-name.json", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "JSON Support Constants", + "scope": "support.constant.json", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "JSON Property values (string)", + "scope": "meta.structure.dictionary.value.json string.quoted.double", + "settings": { + "foreground": "#c789d6", + }, + }, + { + "name": "Strings in JSON values", + "scope": "string.quoted.double.json punctuation.definition.string.json", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Specific JSON Property values like null", + "scope": "meta.structure.dictionary.json meta.structure.dictionary.value constant.language", + "settings": { + "foreground": "#bc5454", + }, + }, + { + "name": "JavaScript Other Variable", + "scope": "variable.other.object.js", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Ruby Variables", + "scope": ["variable.other.ruby"], + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "Ruby Class", + "scope": ["entity.name.type.class.ruby"], + "settings": { + "foreground": "#c96765", + }, + }, + { + "name": "Ruby Hashkeys", + "scope": "constant.language.symbol.hashkey.ruby", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Ruby Symbols", + "scope": "constant.language.symbol.ruby", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "LESS Tag names", + "scope": "entity.name.tag.less", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "LESS Keyword Other Unit", + "scope": "keyword.other.unit.css", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Attribute Name for LESS", + "scope": "meta.attribute-selector.less entity.other.attribute-name.attribute", + "settings": { + "foreground": "#aa0982", + }, + }, + { + "name": "Markdown Headings", + "scope": [ + "markup.heading.markdown", + "markup.heading.setext.1.markdown", + "markup.heading.setext.2.markdown", + ], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Markdown Italics", + "scope": "markup.italic.markdown", + "settings": { + "foreground": "#994cc3", + "fontStyle": "italic", + }, + }, + { + "name": "Markdown Bold", + "scope": "markup.bold.markdown", + "settings": { + "foreground": "#4876d6", + "fontStyle": "bold", + }, + }, + { + "name": "Markdown Quote + others", + "scope": "markup.quote.markdown", + "settings": { + "foreground": "#697098", + }, + }, + { + "name": "Markdown Raw Code + others", + "scope": "markup.inline.raw.markdown", + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Markdown Links", + "scope": ["markup.underline.link.markdown", "markup.underline.link.image.markdown"], + "settings": { + "foreground": "#ff869a", + }, + }, + { + "name": "Markdown Link Title and Description", + "scope": ["string.other.link.title.markdown", "string.other.link.description.markdown"], + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "Markdown Punctuation", + "scope": [ + "punctuation.definition.string.markdown", + "punctuation.definition.string.begin.markdown", + "punctuation.definition.string.end.markdown", + "meta.link.inline.markdown punctuation.definition.string", + ], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Markdown MetaData Punctuation", + "scope": ["punctuation.definition.metadata.markdown"], + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Markdown List Punctuation", + "scope": ["beginning.punctuation.definition.list.markdown"], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Markdown Inline Raw String", + "scope": "markup.inline.raw.string.markdown", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "PHP Variables", + "scope": ["variable.other.php", "variable.other.property.php"], + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "Support Classes in PHP", + "scope": "support.class.php", + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "Punctuations in PHP function calls", + "scope": "meta.function-call.php punctuation", + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "PHP Global Variables", + "scope": "variable.other.global.php", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Declaration Punctuation in PHP Global Variables", + "scope": "variable.other.global.php punctuation.definition.variable", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Language Constants in Python", + "scope": "constant.language.python", + "settings": { + "foreground": "#bc5454", + }, + }, + { + "name": "Python Function Parameter and Arguments", + "scope": ["variable.parameter.function.python", "meta.function-call.arguments.python"], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Python Function Call", + "scope": ["meta.function-call.python", "meta.function-call.generic.python"], + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "Punctuations in Python", + "scope": "punctuation.python", + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "Decorator Functions in Python", + "scope": "entity.name.function.decorator.python", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Python Language Variable", + "scope": "source.python variable.language.special", + "settings": { + "foreground": "#aa0982", + }, + }, + { + "name": "Python import control keyword", + "scope": "keyword.control", + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "SCSS Variable", + "scope": [ + "variable.scss", + "variable.sass", + "variable.parameter.url.scss", + "variable.parameter.url.sass", + ], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Variables in SASS At-Rules", + "scope": ["source.css.scss meta.at-rule variable", "source.css.sass meta.at-rule variable"], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "Variables in SASS At-Rules", + "scope": ["source.css.scss meta.at-rule variable", "source.css.sass meta.at-rule variable"], + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "Attribute Name for SASS", + "scope": [ + "meta.attribute-selector.scss entity.other.attribute-name.attribute", + "meta.attribute-selector.sass entity.other.attribute-name.attribute", + ], + "settings": { + "foreground": "#aa0982", + }, + }, + { + "name": "Tag names in SASS", + "scope": ["entity.name.tag.scss", "entity.name.tag.sass"], + "settings": { + "foreground": "#0c969b", + }, + }, + { + "name": "SASS Keyword Other Unit", + "scope": ["keyword.other.unit.scss", "keyword.other.unit.sass"], + "settings": { + "foreground": "#994cc3", + }, + }, + { + "name": "TypeScript[React] Variables and Object Properties", + "scope": [ + "variable.other.readwrite.alias.ts", + "variable.other.readwrite.alias.tsx", + "variable.other.readwrite.ts", + "variable.other.readwrite.tsx", + "variable.other.object.ts", + "variable.other.object.tsx", + "variable.object.property.ts", + "variable.object.property.tsx", + "variable.other.ts", + "variable.other.tsx", + "variable.tsx", + "variable.ts", + ], + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "TypeScript[React] Entity Name Types", + "scope": ["entity.name.type.ts", "entity.name.type.tsx"], + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "TypeScript[React] Node Classes", + "scope": ["support.class.node.ts", "support.class.node.tsx"], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "TypeScript[React] Entity Name Types as Parameters", + "scope": [ + "meta.type.parameters.ts entity.name.type", + "meta.type.parameters.tsx entity.name.type", + ], + "settings": { + "foreground": "#5f7e97", + }, + }, + { + "name": "TypeScript[React] Import/Export Punctuations", + "scope": [ + "meta.import.ts punctuation.definition.block", + "meta.import.tsx punctuation.definition.block", + "meta.export.ts punctuation.definition.block", + "meta.export.tsx punctuation.definition.block", + ], + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "TypeScript[React] Punctuation Decorators", + "scope": [ + "meta.decorator punctuation.decorator.ts", + "meta.decorator punctuation.decorator.tsx", + ], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "TypeScript[React] Punctuation Decorators", + "scope": "meta.tag.js meta.jsx.children.tsx", + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "YAML Entity Name Tags", + "scope": "entity.name.tag.yaml", + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "JavaScript Variable Other ReadWrite", + "scope": ["variable.other.readwrite.js", "variable.parameter"], + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "Support Class Component", + "scope": ["support.class.component.js", "support.class.component.tsx"], + "settings": { + "foreground": "#aa0982", + "fontStyle": "", + }, + }, + { + "name": "Text nested in React tags", + "scope": ["meta.jsx.children", "meta.jsx.children.js", "meta.jsx.children.tsx"], + "settings": { + "foreground": "#403f53", + }, + }, + { + "name": "TypeScript Classes", + "scope": "meta.class entity.name.type.class.tsx", + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "TypeScript Entity Name Type", + "scope": ["entity.name.type.tsx", "entity.name.type.module.tsx"], + "settings": { + "foreground": "#111111", + }, + }, + { + "name": "TypeScript Class Variable Keyword", + "scope": [ + "meta.class.ts meta.var.expr.ts storage.type.ts", + "meta.class.tsx meta.var.expr.tsx storage.type.tsx", + ], + "settings": { + "foreground": "#C792EA", + }, + }, + { + "name": "TypeScript Method Declaration e.g. `constructor`", + "scope": [ + "meta.method.declaration storage.type.ts", + "meta.method.declaration storage.type.tsx", + ], + "settings": { + "foreground": "#4876d6", + }, + }, + { + "name": "normalize font style of certain components", + "scope": [ + "meta.property-list.css meta.property-value.css variable.other.less", + "meta.property-list.scss variable.scss", + "meta.property-list.sass variable.sass", + "meta.brace", + "keyword.operator.operator", + "keyword.operator.or.regexp", + "keyword.operator.expression.in", + "keyword.operator.relational", + "keyword.operator.assignment", + "keyword.operator.comparison", + "keyword.operator.type", + "keyword.operator", + "keyword", + "punctuation.definition.string", + "punctuation", + "variable.other.readwrite.js", + "storage.type", + "source.css", + "string.quoted", + ], + "settings": { + "fontStyle": "", + }, + }, + ], +} diff --git a/packages/starlight/integrations/expressive-code/theming.ts b/packages/starlight/integrations/expressive-code/theming.ts new file mode 100644 index 00000000000..e207aac3895 --- /dev/null +++ b/packages/starlight/integrations/expressive-code/theming.ts @@ -0,0 +1,105 @@ +import { ExpressiveCodeTheme, type ThemeObjectOrShikiThemeName } from 'astro-expressive-code'; +import nightOwlDark from './themes/night-owl-dark.jsonc?raw'; +import nightOwlLight from './themes/night-owl-light.jsonc?raw'; + +export type BundledThemeName = 'starlight-dark' | 'starlight-light'; + +export type ThemeObjectOrBundledThemeName = ThemeObjectOrShikiThemeName | BundledThemeName; + +/** + * Converts the Starlight `themes` config option into a format understood by Expressive Code, + * loading any bundled themes and using the Starlight defaults if no themes were provided. + */ +export function preprocessThemes( + themes: ThemeObjectOrBundledThemeName[] | undefined +): ThemeObjectOrShikiThemeName[] { + // Try to gracefully handle cases where the user forgot to use an array in the config + themes = themes && !Array.isArray(themes) ? [themes] : themes; + // If no themes were provided, use our bundled default themes + if (!themes || !themes.length) themes = ['starlight-dark', 'starlight-light']; + + return themes.map((theme) => { + // If the current entry is the name of a bundled theme, load it + if (theme === 'starlight-dark' || theme === 'starlight-light') { + const bundledTheme = theme === 'starlight-dark' ? nightOwlDark : nightOwlLight; + return customizeBundledTheme(ExpressiveCodeTheme.fromJSONString(bundledTheme)); + } + // Otherwise, just pass it through + return theme; + }); +} + +/** + * Customizes some settings of the bundled theme to make it fit better with Starlight. + */ +function customizeBundledTheme(theme: ExpressiveCodeTheme) { + theme.colors['titleBar.border'] = theme.colors['tab.activeBackground']; + theme.colors['editorGroupHeader.tabsBorder'] = theme.colors['tab.activeBackground']; + + // Add underline font style to link syntax highlighting tokens + // to match the new GitHub theme link style + theme.settings.forEach((s) => { + if (s.name?.includes('Link')) s.settings.fontStyle = 'underline'; + }); + + return theme; +} + +/** + * Modifies the given theme by applying Starlight's CSS variables to the colors of UI elements + * (backgrounds, buttons, shadows etc.). This ensures that code blocks match the site's theme. + */ +export function applyStarlightUiThemeColors(theme: ExpressiveCodeTheme) { + const isDark = theme.type === 'dark'; + const neutralMinimal = isDark ? '#ffffff17' : '#0000001a'; + const neutralDimmed = isDark ? '#ffffff40' : '#00000055'; + + // Make borders slightly transparent + const borderColor = 'color-mix(in srgb, var(--sl-color-gray-5), transparent 25%)'; + theme.colors['titleBar.border'] = borderColor; + theme.colors['editorGroupHeader.tabsBorder'] = borderColor; + + // Use the same color for terminal title bar background and editor tab bar background + const backgroundColor = isDark ? 'var(--sl-color-black)' : 'var(--sl-color-gray-6)'; + theme.colors['titleBar.activeBackground'] = backgroundColor; + theme.colors['editorGroupHeader.tabsBackground'] = backgroundColor; + + // Use the same color for terminal titles and tab titles + theme.colors['titleBar.activeForeground'] = 'var(--sl-color-text)'; + theme.colors['tab.activeForeground'] = 'var(--sl-color-text)'; + + // Set tab border colors + const activeBorderColor = isDark ? 'var(--sl-color-accent-high)' : 'var(--sl-color-accent)'; + theme.colors['tab.activeBorder'] = 'transparent'; + theme.colors['tab.activeBorderTop'] = activeBorderColor; + + // Use neutral colors for scrollbars + theme.colors['scrollbarSlider.background'] = neutralMinimal; + theme.colors['scrollbarSlider.hoverBackground'] = neutralDimmed; + + // Set theme `bg` color property for contrast calculations + theme.bg = isDark ? '#23262f' : '#f6f7f9'; + theme.colors['editor.background'] = theme.bg; + // Set actual background color to the appropriate Starlight CSS variable + const editorBackgroundColor = isDark ? 'var(--sl-color-gray-6)' : 'var(--sl-color-gray-7)'; + + theme.styleOverrides.frames = { + // Use the same color for editor background, terminal background and active tab background + editorBackground: editorBackgroundColor, + terminalBackground: editorBackgroundColor, + editorActiveTabBackground: editorBackgroundColor, + terminalTitlebarDotsForeground: borderColor, + terminalTitlebarDotsOpacity: '0.75', + inlineButtonForeground: 'var(--sl-color-text)', + frameBoxShadowCssValue: 'none', + }; + + // Use neutral, semi-transparent colors for default text markers + // to avoid conflicts with the user's chosen background color + theme.styleOverrides.textMarkers = { + markBackground: neutralMinimal, + markBorderColor: neutralDimmed, + }; + + return theme; +} diff --git a/packages/starlight/integrations/expressive-code/translations.ts b/packages/starlight/integrations/expressive-code/translations.ts new file mode 100644 index 00000000000..a6802132ca5 --- /dev/null +++ b/packages/starlight/integrations/expressive-code/translations.ts @@ -0,0 +1,36 @@ +import { pluginFramesTexts } from 'astro-expressive-code'; +import type { StarlightConfig } from '../../types'; +import type { createTranslationSystemFromFs } from '../../utils/translations-fs'; +import { localeToLang } from '../shared/localeToLang'; + +export function addTranslations(config: StarlightConfig, useTranslations: UseTranslations) { + addTranslationsForLocale(config.defaultLocale.locale, config, useTranslations); + if (config.isMultilingual) { + for (const locale in config.locales) { + if (locale === config.defaultLocale.locale || locale === 'root') continue; + addTranslationsForLocale(locale, config, useTranslations); + } + } +} + +function addTranslationsForLocale( + locale: string | undefined, + config: StarlightConfig, + useTranslations: UseTranslations +) { + const lang = localeToLang(config, locale); + const t = useTranslations(lang); + const translationKeys = [ + 'expressiveCode.copyButtonCopied', + 'expressiveCode.copyButtonTooltip', + 'expressiveCode.terminalWindowFallbackTitle', + ] as const; + translationKeys.forEach((key) => { + const translation = t.exists(key) ? t(key) : undefined; + if (!translation) return; + const ecId = key.replace(/^expressiveCode\./, ''); + pluginFramesTexts.overrideTexts(lang, { [ecId]: translation }); + }); +} + +type UseTranslations = Awaited<ReturnType<typeof createTranslationSystemFromFs>>; diff --git a/packages/starlight/integrations/heading-links.ts b/packages/starlight/integrations/heading-links.ts new file mode 100644 index 00000000000..6d053c79470 --- /dev/null +++ b/packages/starlight/integrations/heading-links.ts @@ -0,0 +1,81 @@ +import type { Nodes, Root } from 'hast'; +import { toString } from 'hast-util-to-string'; +import { h } from 'hastscript'; +import type { Transformer } from 'unified'; +import { SKIP, visit } from 'unist-util-visit'; +import type { RemarkRehypePluginOptions } from './remark-rehype'; + +const AnchorLinkIcon = h( + 'span', + { ariaHidden: 'true', class: 'sl-anchor-icon' }, + h( + 'svg', + { width: 16, height: 16, viewBox: '0 0 24 24' }, + h('path', { + fill: 'currentcolor', + d: 'm12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 0 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 1 0-1.42-1.42Zm8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 0 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 1 0 1.42 1.42l3.88-3.89a4.49 4.49 0 0 0 0-6.33ZM8.83 15.17a1 1 0 0 0 1.1.22 1 1 0 0 0 .32-.22l4.92-4.92a1 1 0 0 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42Z', + }) + ) +); + +/** + * Add anchor links to headings. + */ +export default function rehypeAutolinkHeadings({ + absolutePathToLang, + useTranslations, +}: RemarkRehypePluginOptions) { + const transformer: Transformer<Root> = (tree, file) => { + const pageLang = absolutePathToLang(file.path); + const t = useTranslations(pageLang); + + visit(tree, 'element', function (node, index, parent) { + if (!headingRank(node) || !node.properties.id || typeof index !== 'number' || !parent) { + return; + } + + const accessibleLabel = t('heading.anchorLabel', { + title: toString(node), + interpolation: { escapeValue: false }, + }); + + // Wrap the heading in a div and append the anchor link. + parent.children[index] = h( + 'div', + { class: `sl-heading-wrapper level-${node.tagName}` }, + // Heading + node, + // Anchor link + { + type: 'element', + tagName: 'a', + properties: { class: 'sl-anchor-link', href: '#' + String(node.properties.id) }, + children: [ + AnchorLinkIcon, + h('span', { class: 'sr-only', 'data-pagefind-ignore': true }, accessibleLabel), + ], + } + ); + + return SKIP; + }); + }; + + return function attacher() { + return transformer; + }; +} + +// This utility is inlined from https://github.com/syntax-tree/hast-util-heading-rank +// Copyright (c) 2020 Titus Wormer <tituswormer@gmail.com> +// MIT License: https://github.com/syntax-tree/hast-util-heading-rank/blob/main/license +/** + * Get the rank (`1` to `6`) of headings (`h1` to `h6`). + * @param node Node to check. + * @returns Rank of the heading or `undefined` if not a heading. + */ +function headingRank(node: Nodes): number | undefined { + const name = node.type === 'element' ? node.tagName.toLowerCase() : ''; + const code = name.length === 2 && name.charCodeAt(0) === 104 /* `h` */ ? name.charCodeAt(1) : 0; + return code > 48 /* `0` */ && code < 55 /* `7` */ ? code - 48 /* `0` */ : undefined; +} diff --git a/packages/starlight/integrations/pagefind.ts b/packages/starlight/integrations/pagefind.ts new file mode 100644 index 00000000000..ca271bb2f54 --- /dev/null +++ b/packages/starlight/integrations/pagefind.ts @@ -0,0 +1,60 @@ +import type { HookParameters } from 'astro'; +import { fileURLToPath } from 'node:url'; +import * as pagefind from 'pagefind'; + +/** Run Pagefind to generate search index files based on the build output directory. */ +export async function starlightPagefind({ + dir, + logger: starlightLogger, +}: PagefindIntegrationOptions) { + const logger = starlightLogger.fork('starlight:pagefind'); + const options = { dir, logger }; + + try { + const now = performance.now(); + logger.info('Building search index with Pagefind...'); + + const newIndexResponse = await pagefind.createIndex(); + + const { index } = assertPagefindResponse<pagefind.NewIndexResponse>(newIndexResponse, options); + + const indexingResponse = await index.addDirectory({ path: fileURLToPath(dir) }); + const { page_count } = assertPagefindResponse<pagefind.IndexingResponse>( + indexingResponse, + options + ); + + logger.info(`Found ${page_count} HTML files.`); + + const writeFilesResponse = await index.writeFiles({ + outputPath: fileURLToPath(new URL('./pagefind/', dir)), + }); + assertPagefindResponse<pagefind.WriteFilesResponse>(writeFilesResponse, options); + + const pagefindTime = performance.now() - now; + logger.info( + `Finished building search index in ${pagefindTime < 750 ? `${Math.round(pagefindTime)}ms` : `${(pagefindTime / 1000).toFixed(2)}s`}.` + ); + } catch (cause) { + throw new Error('Failed to run Pagefind.', { cause }); + } finally { + await pagefind.close(); + } +} + +function assertPagefindResponse<T extends PagefindBaseResponse>( + response: T, + { logger }: PagefindIntegrationOptions +) { + if (response.errors.length > 0) { + for (const error of response.errors) logger.error(`Pagefind error: ${error}`); + throw new Error('Pagefind response contained errors.'); + } + return response as Required<T>; +} + +interface PagefindBaseResponse { + errors: string[]; +} + +type PagefindIntegrationOptions = Pick<HookParameters<'astro:build:done'>, 'dir' | 'logger'>; diff --git a/packages/starlight/integrations/remark-rehype.ts b/packages/starlight/integrations/remark-rehype.ts new file mode 100644 index 00000000000..ebfa4865cc4 --- /dev/null +++ b/packages/starlight/integrations/remark-rehype.ts @@ -0,0 +1,126 @@ +import { resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import type { AstroConfig } from 'astro'; +import { rehypeHeadingIds } from '@astrojs/markdown-remark'; +import type { Root as RehypeRoot } from 'hast'; +import type { Root as RemarkRoot } from 'mdast'; +import remarkDirective from 'remark-directive'; +import type { Plugin } from 'unified'; +import type { VFile } from 'vfile'; +import { resolveCollectionPath } from '../utils/collection-fs'; +import type { HookParameters, StarlightConfig } from '../types'; +import { remarkAsides } from './asides'; +import { rehypeRtlCodeSupport } from './code-rtl-support'; +import rehypeAutolinkHeadings from './heading-links'; + +/** List of remark plugins to apply. */ +export function starlightRemarkPlugins(options: RemarkRehypePluginOptions): RemarkPlugin[] { + return [remarkDirective, remarkPlugins(options)]; +} + +/** List of rehype plugins to apply. */ +export function starlightRehypePlugins(options: RemarkRehypePluginOptions): RehypePlugin[] { + return [ + ...(options.starlightConfig.markdown.headingLinks + ? [ + [ + rehypeHeadingIds, + { experimentalHeadingIdCompat: options.astroConfig.experimental?.headingIdCompat }, + ], + ] + : []), + rehypePlugins(options), + ] as RehypePlugin[]; +} + +/** Remark plugin applying other Starlight remark plugins if necessary. */ +function remarkPlugins(options: RemarkRehypePluginOptions): RemarkPlugin { + const remarkRehypePaths = getRemarkRehypePaths(options); + + return function attacher(this) { + const remarkAsidesTransformer = remarkAsides(options).call(this)!; + + return async function transformer(...args) { + const [, file] = args; + + if (!shouldTransformFile(file, remarkRehypePaths)) return; + + await remarkAsidesTransformer(...args); + }; + }; +} + +/** Rehype plugin applying other Starlight rehype plugins if necessary. */ +function rehypePlugins(options: RemarkRehypePluginOptions): RehypePlugin { + const remarkRehypePaths = getRemarkRehypePaths(options); + + return function attacher(this) { + const rehypeRtlCodeSupportTransformer = rehypeRtlCodeSupport(options).call(this); + const rehypeAutolinkHeadingsTransformer = rehypeAutolinkHeadings(options).call(this); + + return async function transformer(...args) { + const [, file] = args; + + if (!shouldTransformFile(file, remarkRehypePaths)) return; + + await rehypeRtlCodeSupportTransformer(...args); + + if (options.starlightConfig.markdown.headingLinks) { + await rehypeAutolinkHeadingsTransformer(...args); + } + }; + }; +} + +/** + * Returns the paths to the Starlight docs collection and any additional paths defined in the + * `starlightConfig.markdown.processedDirs` option that can be used with the + * `shouldTransformFile()` utility to determine if a file should be transformed by a plugin or not. + */ +function getRemarkRehypePaths(options: RemarkRehypePluginOptions): string[] { + const paths = [normalizePath(resolveCollectionPath('docs', options.astroConfig.srcDir))]; + + for (const processedDir of options.starlightConfig.markdown.processedDirs) { + paths.push(normalizePath(resolve(fileURLToPath(options.astroConfig.root), processedDir))); + } + + return paths; +} + +/** + * Determines if a file should be transformed by a remark/rehype plugin, e.g. files without a known + * path or files that are not part of the allowed remark/rehype paths are skipped. + */ +function shouldTransformFile(file: VFile, remarkRehypePaths: string[]) { + // If the content is rendered using the content loader `renderMarkdown()` API, a file path + // is not provided. + // In that case, we skip the file. + if (!file?.path) return false; + + const normalizedPath = normalizePath(file.path); + + // If the document is not part of the allowed remark/rehype paths, skip it. + return remarkRehypePaths.some((path) => normalizedPath.startsWith(path)); +} + +/** + * File path separators seems to be inconsistent on Windows between remark/rehype plugins used on + * Markdown vs MDX files. + * For the time being, we normalize all paths to unix style paths. + */ +const backSlashRegex = /\\/g; +function normalizePath(path: string) { + return path.replace(backSlashRegex, '/'); +} + +export interface RemarkRehypePluginOptions { + starlightConfig: Pick<StarlightConfig, 'defaultLocale' | 'locales' | 'markdown'>; + astroConfig: Pick<AstroConfig, 'root' | 'srcDir'> & { + experimental: Pick<AstroConfig['experimental'], 'headingIdCompat'>; + }; + useTranslations: HookParameters<'config:setup'>['useTranslations']; + absolutePathToLang: HookParameters<'config:setup'>['absolutePathToLang']; +} + +type RemarkPlugin = Plugin<[], RemarkRoot>; +type RehypePlugin = Plugin<[], RehypeRoot>; diff --git a/packages/starlight/integrations/shared/absolutePathToLang.ts b/packages/starlight/integrations/shared/absolutePathToLang.ts new file mode 100644 index 00000000000..74a58da4960 --- /dev/null +++ b/packages/starlight/integrations/shared/absolutePathToLang.ts @@ -0,0 +1,26 @@ +import type { StarlightConfig } from '../../types'; +import { localeToLang } from './localeToLang'; +import { slugToLocale } from './slugToLocale'; + +/** Get current language from an absolute file path. */ +export function absolutePathToLang( + path: string, + { + docsPath, + starlightConfig, + }: { + docsPath: string; + starlightConfig: Pick<StarlightConfig, 'defaultLocale' | 'locales'>; + } +): string { + // Format path to unix style path. + path = path?.replace(/\\/g, '/'); + // Ensure that the page path starts with a slash if the docs directory also does, + // which makes stripping the docs path in the next step work on Windows, too. + if (path && !path.startsWith('/') && docsPath.startsWith('/')) path = '/' + path; + // Strip docs path leaving only content collection file ID. + // Example: /Users/houston/repo/src/content/docs/en/guide.md => en/guide.md + const slug = path?.replace(docsPath, ''); + const locale = slugToLocale(slug, starlightConfig); + return localeToLang(starlightConfig, locale); +} diff --git a/packages/starlight/integrations/shared/localeToLang.ts b/packages/starlight/integrations/shared/localeToLang.ts new file mode 100644 index 00000000000..6319c6e7c43 --- /dev/null +++ b/packages/starlight/integrations/shared/localeToLang.ts @@ -0,0 +1,15 @@ +import type { StarlightConfig } from '../../types'; +import { BuiltInDefaultLocale } from '../../utils/i18n'; + +/** + * Get the BCP-47 language tag for the given locale. + * @param locale Locale string or `undefined` for the root locale. + */ +export function localeToLang( + config: Pick<StarlightConfig, 'defaultLocale' | 'locales'>, + locale: string | undefined +): string { + const lang = locale ? config.locales?.[locale]?.lang : config.locales?.root?.lang; + const defaultLang = config.defaultLocale?.lang || config.defaultLocale?.locale; + return lang || defaultLang || BuiltInDefaultLocale.lang; +} diff --git a/packages/starlight/integrations/shared/slugToLocale.ts b/packages/starlight/integrations/shared/slugToLocale.ts new file mode 100644 index 00000000000..69e1f3bc0b2 --- /dev/null +++ b/packages/starlight/integrations/shared/slugToLocale.ts @@ -0,0 +1,18 @@ +import type { StarlightConfig } from '../../types'; + +/** + * Get the “locale” of a slug. This is the base path at which a language is served. + * For example, if French docs are in `src/content/docs/french/`, the locale is `french`. + * Root locale slugs will return `undefined`. + * @param slug A collection entry slug + */ +export function slugToLocale( + slug: string | undefined, + config: Pick<StarlightConfig, 'defaultLocale' | 'locales'> +): string | undefined { + const localesConfig = config.locales ?? {}; + const baseSegment = slug?.split('/')[0]; + if (baseSegment && localesConfig[baseSegment]) return baseSegment; + if (!localesConfig.root) return config.defaultLocale.locale; + return undefined; +} diff --git a/packages/starlight/integrations/sitemap.ts b/packages/starlight/integrations/sitemap.ts index ba18af034f1..996536cebbe 100644 --- a/packages/starlight/integrations/sitemap.ts +++ b/packages/starlight/integrations/sitemap.ts @@ -1,19 +1,23 @@ import sitemap, { type SitemapOptions } from '@astrojs/sitemap'; import type { StarlightConfig } from '../types'; -/** - * A wrapped version of the `@astrojs/sitemap` integration configured based - * on Starlight i18n config. - */ -export function starlightSitemap(opts: StarlightConfig) { +export function getSitemapConfig(opts: StarlightConfig): SitemapOptions { const sitemapConfig: SitemapOptions = {}; if (opts.isMultilingual) { sitemapConfig.i18n = { - defaultLocale: opts.defaultLocale.locale! || 'root', + defaultLocale: opts.defaultLocale.locale || 'root', locales: Object.fromEntries( - Object.entries(opts.locales).map(([locale, config]) => [locale, config?.lang!]) + Object.entries(opts.locales).map(([locale, config]) => [locale, config!.lang!]) ), }; } - return sitemap(sitemapConfig); + return sitemapConfig; +} + +/** + * A wrapped version of the `@astrojs/sitemap` integration configured based + * on Starlight i18n config. + */ +export function starlightSitemap(opts: StarlightConfig) { + return sitemap(getSitemapConfig(opts)); } diff --git a/packages/starlight/integrations/virtual-user-config.ts b/packages/starlight/integrations/virtual-user-config.ts index 86c2b2a4b96..893af513df6 100644 --- a/packages/starlight/integrations/virtual-user-config.ts +++ b/packages/starlight/integrations/virtual-user-config.ts @@ -1,7 +1,11 @@ -import type { AstroConfig, ViteUserConfig } from 'astro'; +import type { AstroConfig, HookParameters, ViteUserConfig } from 'astro'; +import { existsSync } from 'node:fs'; import { resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; +import { resolveCollectionPath } from '../utils/collection-fs'; import type { StarlightConfig } from '../utils/user-config'; +import { getAllNewestCommitDate } from '../utils/git'; +import type { PluginTranslations } from '../utils/plugins'; function resolveVirtualModuleId<T extends string>(id: T): `\0${T}` { return `\0${id}`; @@ -9,26 +13,131 @@ function resolveVirtualModuleId<T extends string>(id: T): `\0${T}` { /** Vite plugin that exposes Starlight user config and project context via virtual modules. */ export function vitePluginStarlightUserConfig( + command: HookParameters<'astro:config:setup'>['command'], opts: StarlightConfig, - { root, srcDir }: Pick<AstroConfig, 'root' | 'srcDir'> + { + build, + legacy, + root, + srcDir, + trailingSlash, + }: Pick<AstroConfig, 'root' | 'srcDir' | 'trailingSlash'> & { + build: Pick<AstroConfig['build'], 'format'>; + legacy: Pick<AstroConfig['legacy'], 'collections'>; + }, + pluginTranslations: PluginTranslations ): NonNullable<ViteUserConfig['plugins']>[number] { - const resolveId = (id: string) => - JSON.stringify(id.startsWith('.') ? resolve(fileURLToPath(root), id) : id); + /** + * Resolves module IDs to a usable format: + * - Relative paths (e.g. `'./module.js'`) are resolved against `base` and formatted as an absolute path. + * - Package identifiers (e.g. `'module'`) are returned unchanged. + * + * By default, `base` is the project root directory. + */ + const resolveId = (id: string, base = root) => + JSON.stringify(id.startsWith('.') ? resolve(fileURLToPath(base), id) : id); + + /** + * Resolves a path to a Starlight file relative to this file. + * @example + * resolveLocalPath('../utils/git.ts'); + * // => '"/users/houston/docs/node_modules/@astrojs/starlight/utils/git.ts"' + */ + const resolveLocalPath = (path: string) => + JSON.stringify(fileURLToPath(new URL(path, import.meta.url))); + + const rootPath = fileURLToPath(root); + const docsPath = resolveCollectionPath('docs', srcDir); + + let collectionConfigImportPath = resolve( + fileURLToPath(srcDir), + legacy.collections ? './content/config.ts' : './content.config.ts' + ); + // If not using legacy collections and the config doesn't exist, fallback to the legacy location. + // We need to test this ahead of time as we cannot `try/catch` a failing import in the virtual + // module as this would fail at build time when Rollup tries to resolve a non-existent path. + if (!legacy.collections && !existsSync(collectionConfigImportPath)) { + collectionConfigImportPath = resolve(fileURLToPath(srcDir), './content/config.ts'); + } + + const virtualComponentModules = Object.fromEntries( + Object.entries(opts.components).map(([name, path]) => [ + `virtual:starlight/components/${name}`, + `export { default } from ${resolveId(path)};`, + ]) + ); /** Map of virtual module names to their code contents as strings. */ const modules = { 'virtual:starlight/user-config': `export default ${JSON.stringify(opts)}`, - 'virtual:starlight/project-context': `export default ${JSON.stringify({ root, srcDir })}`, + 'virtual:starlight/project-context': `export default ${JSON.stringify({ + build: { format: build.format }, + legacyCollections: legacy.collections, + root, + srcDir, + trailingSlash, + })}`, + 'virtual:starlight/git-info': + (command !== 'build' + ? `import { makeAPI } from ${resolveLocalPath('../utils/git.ts')};` + + `const api = makeAPI(${JSON.stringify(rootPath)});` + : `import { makeAPI } from ${resolveLocalPath('../utils/gitInlined.ts')};` + + `const api = makeAPI(${JSON.stringify(getAllNewestCommitDate(rootPath, docsPath))});`) + + 'export const getNewestCommitDate = api.getNewestCommitDate;', + /** + * Module containing styles for features that can be toggled on or off such as heading anchor links. + */ + 'virtual:starlight/optional-css': opts.markdown.headingLinks + ? `import ${resolveLocalPath('../style/anchor-links.css')};` + : '', + /** + * Module containing imports of user-specified custom CSS files. + */ 'virtual:starlight/user-css': opts.customCss.map((id) => `import ${resolveId(id)};`).join(''), 'virtual:starlight/user-images': opts.logo ? 'src' in opts.logo ? `import src from ${resolveId( opts.logo.src - )}; export const logos = { dark: src, light: src };` + )}; export const logos = { dark: src, light: src };` : `import dark from ${resolveId(opts.logo.dark)}; import light from ${resolveId( opts.logo.light - )}; export const logos = { dark, light };` + )}; export const logos = { dark, light };` : 'export const logos = {};', + 'virtual:starlight/collection-config': `let userCollections; + try { + userCollections = (await import(${JSON.stringify(collectionConfigImportPath)})).collections; + } catch {} + export const collections = userCollections;`, + 'virtual:starlight/plugin-translations': `export default ${JSON.stringify(pluginTranslations)}`, + /** + * Exports an array of route middleware functions. + * For example, might generate a module that looks like: + * + * ```js + * import { onRequest as routeMiddleware0 } from "/users/houston/docs/src/middleware"; + * import { onRequest as routeMiddleware1 } from "@houston-inc/plugin/middleware"; + * + * export const routeMiddleware = [ + * routeMiddleware0, + * routeMiddleware1, + * ]; + * ``` + */ + 'virtual:starlight/route-middleware': + opts.routeMiddleware + .reduce( + ([imports, entries], id, index) => { + const importName = `routeMiddleware${index}`; + imports += `import { onRequest as ${importName} } from ${resolveId(id)};\n`; + entries += `\t${importName},\n`; + return [imports, entries] as [string, string]; + }, + ['', 'export const routeMiddleware = [\n'] as [string, string] + ) + .join('\n') + '];', + /** Map of modules exporting Starlight’s templating components. */ + 'virtual:starlight/pagefind-config': `export const pagefindUserConfig = ${JSON.stringify(opts.pagefind || {})}`, + ...virtualComponentModules, } satisfies Record<string, string>; /** Mapping names prefixed with `\0` to their original form. */ diff --git a/packages/starlight/integrations/vite-layer-order.ts b/packages/starlight/integrations/vite-layer-order.ts new file mode 100644 index 00000000000..41277e49c4f --- /dev/null +++ b/packages/starlight/integrations/vite-layer-order.ts @@ -0,0 +1,66 @@ +import type { ViteUserConfig } from 'astro'; +import MagicString from 'magic-string'; + +const starlightPageImportSource = '@astrojs/starlight/components/StarlightPage.astro'; + +/** + * Vite plugin that ensures the StarlightPage component is always imported first when imported in + * an Astro file. + * + * This is necessary to ensure a predictable CSS layer order which is defined by the `<Page />` + * imported by the `<StarlightPage />` component. If a user imports any other component using + * cascade layers before the `<StarlightPage />` component, it will result in undesired layers + * being created before we explicitly set the expected layer order. + */ +export function vitePluginStarlightCssLayerOrder(): VitePlugin { + return { + name: 'vite-plugin-starlight-css-layer-order', + enforce: 'pre', + transform(code, id) { + if ( + !id.endsWith('.astro') || + id.endsWith(starlightPageImportSource) || + code.indexOf('StarlightPage.astro') === -1 + ) { + return; + } + + let ast: ReturnType<typeof this.parse>; + + try { + ast = this.parse(code); + } catch { + return; + } + + let hasStarlightPageImport = false; + + for (const node of ast.body) { + if (node.type !== 'ImportDeclaration') continue; + if (node.source.value !== starlightPageImportSource) continue; + + const importDefaultSpecifier = node.specifiers.find( + (specifier) => specifier.type === 'ImportDefaultSpecifier' + ); + if (!importDefaultSpecifier) continue; + + hasStarlightPageImport = true; + break; + } + + if (!hasStarlightPageImport) return; + + // Format path to unix style path. + const filename = id.replace(/\\/g, '/'); + const ms = new MagicString(code, { filename }); + ms.prepend(`import "${starlightPageImportSource}";\n`); + + return { + code: ms.toString(), + map: ms.generateMap({ hires: 'boundary' }), + }; + }, + }; +} + +type VitePlugin = NonNullable<ViteUserConfig['plugins']>[number]; diff --git a/packages/starlight/internal.ts b/packages/starlight/internal.ts new file mode 100644 index 00000000000..f7de032db0e --- /dev/null +++ b/packages/starlight/internal.ts @@ -0,0 +1,6 @@ +/** + * @file This file contains utility functions imported by the `<Code>` component. + */ + +export { useTranslations } from './utils/translations'; +export { getStarlightEcConfigPreprocessor } from './integrations/expressive-code/preprocessor'; diff --git a/packages/starlight/layout/Page.astro b/packages/starlight/layout/Page.astro deleted file mode 100644 index 0999122dffc..00000000000 --- a/packages/starlight/layout/Page.astro +++ /dev/null @@ -1,132 +0,0 @@ ---- -import config from 'virtual:starlight/user-config'; -import type { MarkdownHeading } from 'astro'; -import { getSidebar } from '../utils/navigation'; -import type { Route } from '../utils/routing'; - -// Built-in CSS styles. -import '../style/props.css'; -import '../style/reset.css'; -import '../style/shiki.css'; -import '../style/util.css'; - -// Components — can override built-in CSS, but not user CSS. -import ContentPanel from '../components/ContentPanel.astro'; -import FallbackContentNotice from '../components/FallbackContentNotice.astro'; -import Footer from '../components/Footer.astro'; -import HeadSEO from '../components/HeadSEO.astro'; -import Header from '../components/Header.astro'; -import Hero from '../components/Hero.astro'; -import MarkdownContent from '../components/MarkdownContent.astro'; -import RightSidebar from '../components/RightSidebar.astro'; -import Sidebar from '../components/Sidebar.astro'; -import SkipLink from '../components/SkipLink.astro'; -import ThemeProvider from '../components/ThemeProvider.astro'; -import PageFrame from '../layout/PageFrame.astro'; -import TwoColumnContent from '../layout/TwoColumnContent.astro'; -import Banner from '../components/Banner.astro'; - -// Remark component CSS (needs to override `MarkdownContent.astro`) -import '../style/asides.css'; - -// Important that this is the last import so it can override built-in styles. -import 'virtual:starlight/user-css'; - -type Props = Route & { headings: MarkdownHeading[] }; - -const { dir, entry, entryMeta, headings, isFallback, lang, locale } = Astro.props; -const sidebar = getSidebar(Astro.url.pathname, locale); - -const hasSidebar = entry.data.template !== 'splash'; -const tocConfig = !hasSidebar - ? false - : entry.data.tableOfContents !== undefined - ? entry.data.tableOfContents - : config.tableOfContents; -const hasToC = Boolean(tocConfig); -const hasHero = Boolean(entry.data.hero); -const pagefindEnabled = - entry.slug !== '404' && !entry.slug.endsWith('/404') && entry.data.pagefind !== false; ---- - -<html - lang={lang} - dir={dir} - data-has-toc={hasToC} - data-has-sidebar={hasSidebar} - data-has-hero={hasHero} -> - <head> - <HeadSEO data={entry.data} lang={lang} /> - <style> - html:not([data-has-toc]) { - --sl-mobile-toc-height: 0rem; - } - html:not([data-has-sidebar]) { - --sl-content-width: 67.5rem; - } - /* Add scroll padding to ensure anchor headings aren't obscured by nav */ - html { - /* Additional padding is needed to account for the mobile TOC */ - scroll-padding-top: calc(1.5rem + var(--sl-nav-height) + var(--sl-mobile-toc-height)); - } - main { - padding-bottom: 3vh; - } - @media (min-width: 50em) { - [data-has-sidebar] { - --sl-content-inline-start: var(--sl-sidebar-width); - } - } - @media (min-width: 72em) { - html { - scroll-padding-top: calc(1.5rem + var(--sl-nav-height)); - } - } - </style> - </head> - <body> - <ThemeProvider /> - <SkipLink {locale} /> - <PageFrame {locale} {hasSidebar}> - <Header slot="header" {locale} /> - {hasSidebar && <Sidebar slot="sidebar" {sidebar} {locale} />} - <TwoColumnContent {hasToC}> - <RightSidebar slot="right-sidebar" {headings} {locale} {tocConfig} /> - <main data-pagefind-body={pagefindEnabled} lang={entryMeta.lang} dir={entryMeta.dir}> - {/* TODO: Revisit how this logic flows. */} - {entry.data.banner && <Banner {...entry.data.banner} />} - { - entry.data.hero ? ( - <ContentPanel> - <Hero hero={entry.data.hero} fallbackTitle={entry.data.title} /> - <MarkdownContent> - <slot /> - </MarkdownContent> - </ContentPanel> - ) : ( - <> - <ContentPanel> - <h1 - id="_top" - data-page-title - style="font-size: var(--sl-text-h1); line-height: var(--sl-line-height-headings); font-weight: 600; color: var(--sl-color-white); margin-top: 1rem;" - > - {entry.data.title} - </h1> - {isFallback && <FallbackContentNotice {locale} />} - </ContentPanel> - <ContentPanel> - <MarkdownContent> - <slot /> - </MarkdownContent> - <Footer {...{ entry, dir, lang, locale, sidebar }} /> - </ContentPanel> - </> - ) - } - </main> - </TwoColumnContent> - </PageFrame> - </body> -</html> diff --git a/packages/starlight/layout/PageFrame.astro b/packages/starlight/layout/PageFrame.astro deleted file mode 100644 index f0f1f7c9d90..00000000000 --- a/packages/starlight/layout/PageFrame.astro +++ /dev/null @@ -1,90 +0,0 @@ ---- -import MobileMenuToggle from '../components/MobileMenuToggle.astro'; -import { useTranslations } from '../utils/translations'; - -interface Props { - hasSidebar: boolean; - locale: string | undefined; -} - -const { hasSidebar, locale } = Astro.props; -const t = useTranslations(locale); ---- - -<div class="page sl-flex"> - <header class="header"><slot name="header" /></header> - { - hasSidebar && ( - <nav class="sidebar" aria-label={t('sidebarNav.accessibleLabel')}> - <MobileMenuToggle {locale} /> - <div id="starlight__sidebar" class="sidebar-pane"> - <div class="sidebar-content"> - <slot name="sidebar" /> - </div> - </div> - </nav> - ) - } - <div class="main-frame"><slot /></div> -</div> - -<style> - .page { - flex-direction: column; - min-height: 100vh; - } - - .header { - z-index: var(--sl-z-index-navbar); - position: fixed; - inset-inline-start: 0; - inset-block-start: 0; - width: 100%; - height: var(--sl-nav-height); - border-bottom: 1px solid var(--sl-color-hairline-shade); - padding: var(--sl-nav-pad-y) var(--sl-nav-pad-x); - padding-inline-end: var(--sl-nav-pad-x); - background-color: var(--sl-color-bg-nav); - } - - :global([data-has-sidebar]) .header { - padding-inline-end: calc(var(--sl-nav-gap) + var(--sl-nav-pad-x) + var(--sl-menu-button-size)); - } - - .sidebar-pane { - visibility: var(--sl-sidebar-visibility, hidden); - position: fixed; - z-index: var(--sl-z-index-menu); - inset-block: 0; - inset-inline-start: 0; - padding-top: var(--sl-nav-height); - width: 100%; - background-color: var(--sl-color-black); - } - - :global([aria-expanded='true']) ~ .sidebar-pane { - --sl-sidebar-visibility: visible; - } - - .sidebar-content { - height: 100%; - overflow-y: auto; - } - - .main-frame { - padding-top: calc(var(--sl-nav-height) + var(--sl-mobile-toc-height)); - padding-inline-start: var(--sl-content-inline-start); - } - - @media (min-width: 50rem) { - :global([data-has-sidebar]) .header { - padding-inline-end: var(--sl-nav-pad-x); - } - .sidebar-pane { - --sl-sidebar-visibility: visible; - width: var(--sl-sidebar-width); - background-color: var(--sl-color-bg-sidebar); - border-inline-end: 1px solid var(--sl-color-hairline-shade); - } - } -</style> diff --git a/packages/starlight/layout/TwoColumnContent.astro b/packages/starlight/layout/TwoColumnContent.astro deleted file mode 100644 index 381632fb85e..00000000000 --- a/packages/starlight/layout/TwoColumnContent.astro +++ /dev/null @@ -1,58 +0,0 @@ ---- -interface Props { - hasToC: boolean; -} ---- - -<div class="lg:sl-flex"> - { - Astro.props.hasToC && ( - <aside class="right-sidebar-container"> - <div class="right-sidebar"> - <slot name="right-sidebar" /> - </div> - </aside> - ) - } - <div class="main-pane"><slot /></div> -</div> - -<style> - .main-pane { - isolation: isolate; - } - - @media (min-width: 72rem) { - .right-sidebar-container { - order: 2; - position: relative; - width: calc( - var(--sl-sidebar-width) + (100% - var(--sl-content-width) - var(--sl-sidebar-width)) / 2 - ); - } - - .right-sidebar { - position: fixed; - top: 0; - border-inline-start: 1px solid var(--sl-color-gray-6); - padding-top: var(--sl-nav-height); - width: 100%; - height: 100vh; - overflow-y: auto; - scrollbar-width: none; - } - - .main-pane { - width: 100%; - } - - :global([data-has-sidebar][data-has-toc]) .main-pane { - --sl-content-margin-inline: auto 0; - - order: 1; - width: calc( - var(--sl-content-width) + (100% - var(--sl-content-width) - var(--sl-sidebar-width)) / 2 - ); - } - } -</style> diff --git a/packages/starlight/loaders.ts b/packages/starlight/loaders.ts new file mode 100644 index 00000000000..ef2d6766de3 --- /dev/null +++ b/packages/starlight/loaders.ts @@ -0,0 +1,63 @@ +import { glob, type Loader, type LoaderContext } from 'astro/loaders'; +import { getCollectionPathFromRoot, type StarlightCollection } from './utils/collection'; + +// https://github.com/withastro/astro/blob/main/packages/astro/src/core/constants.ts#L87 +// https://github.com/withastro/astro/blob/main/packages/integrations/mdx/src/index.ts#L59 +const docsExtensions = ['markdown', 'mdown', 'mkdn', 'mkd', 'mdwn', 'md', 'mdx']; +const i18nExtensions = ['json', 'yml', 'yaml']; + +type GlobOptions = Parameters<typeof glob>[0]; +type GenerateIdFunction = NonNullable<GlobOptions['generateId']>; + +/** + * Loads content files from the `src/content/docs/` directory, ignoring filenames starting with `_`. + */ +export function docsLoader({ + generateId, +}: { + /** + * Function that generates an ID for an entry. Default implementation generates a slug from the entry path. + * @returns The ID of the entry. Must be unique per collection. + **/ + generateId?: GenerateIdFunction; +} = {}): Loader { + return { + name: 'starlight-docs-loader', + load: createGlobLoadFn('docs', generateId), + }; +} + +/** + * Loads data files from the `src/content/i18n/` directory, ignoring filenames starting with `_`. + */ +export function i18nLoader(): Loader { + return { + name: 'starlight-i18n-loader', + load: createGlobLoadFn('i18n'), + }; +} + +function createGlobLoadFn( + collection: StarlightCollection, + generateId?: GenerateIdFunction +): Loader['load'] { + return (context: LoaderContext) => { + const extensions = collection === 'docs' ? docsExtensions : i18nExtensions; + + if ( + collection === 'docs' && + context.config.integrations.find(({ name }) => name === '@astrojs/markdoc') + ) { + // https://github.com/withastro/astro/blob/main/packages/integrations/markdoc/src/content-entry-type.ts#L28 + extensions.push('mdoc'); + } + + const options: GlobOptions = { + base: getCollectionPathFromRoot(collection, context.config), + pattern: `**/[^_]*.{${extensions.join(',')}}`, + }; + if (generateId) options.generateId = generateId; + + return glob(options).load(context); + }; +} diff --git a/packages/starlight/locals.d.ts b/packages/starlight/locals.d.ts new file mode 100644 index 00000000000..12ae5fad26d --- /dev/null +++ b/packages/starlight/locals.d.ts @@ -0,0 +1,43 @@ +/** + * This namespace is reserved for Starlight (only used for i18n at the moment). + * It can be extended by plugins using module augmentation and interface merging. + * For an example, see: https://starlight.astro.build/reference/plugins/#injecttranslations + */ +declare namespace StarlightApp { + interface I18n {} +} + +/** + * Extending Astro’s `App.Locals` interface registers types for the middleware added by Starlight. + */ +declare namespace App { + interface Locals { + /** + * Starlight’s localization API, powered by i18next. + * + * @see https://starlight.astro.build/guides/i18n/#using-ui-translations + * + * @example + * // Render a UI string for the current locale. + * <p>{Astro.locals.t('404.text')}</p> + */ + t: import('./utils/createTranslationSystem').I18nT; + + /** + * Starlight’s data for the current route. + * + * @see https://starlight.astro.build/guides/route-data/ + * + * @throws Will throw an error if accessed on non-Starlight routes. + * + * @example + * // Render the title for the current page + * <h1>{Astro.locals.starlightRoute.entry.data.title}</h1> + * + * @example + * // Check if the current page should render the sidebar + * const { hasSidebar } = Astro.locals.starlightRoute; + */ + starlightRoute: import('./utils/routing/types').StarlightRouteData; + } +} diff --git a/packages/starlight/locals.ts b/packages/starlight/locals.ts new file mode 100644 index 00000000000..29088d26783 --- /dev/null +++ b/packages/starlight/locals.ts @@ -0,0 +1,43 @@ +import type { APIContext } from 'astro'; +import { AstroError } from 'astro/errors'; +import { defineMiddleware } from 'astro:middleware'; +import type { StarlightRouteData } from './route-data'; +import { useTranslations } from './utils/translations'; + +export const onRequest = defineMiddleware(async (context, next) => { + context.locals.t = useTranslations(context.currentLocale); + initializeStarlightRoute(context); + return next(); +}); + +/** + * Sets up a `starlightRoute` property on locals. Initially, this will throw an error if accessed. + * When rendering, Starlight’s routes set `starlightRoute` with the resolved route data object for + * the current page. + * + * This ensures Starlight components can easily access `starlightRoute` without needing type guards, + * we can throw a helpful message if `starlightRoute` is accessed on non-Starlight pages, and we + * avoid generating route data in this middleware which also runs for non-Starlight route. + */ +export function initializeStarlightRoute(context: APIContext) { + if ('starlightRoute' in context.locals) return; + const state: { routeData: StarlightRouteData | undefined } = { routeData: undefined }; + Object.defineProperty(context.locals, 'starlightRoute', { + get() { + if (!state.routeData) { + throw new AstroError( + '`locals.starlightRoute` is not defined', + 'This usually means a component that accesses `locals.starlightRoute` is being rendered outside of a Starlight page, which is not supported.\n\n' + + 'If this is a component you authored, you can do one of the following:\n\n' + + '1. Avoid using this component in non-Starlight pages.\n' + + '2. Wrap the code that reads `locals.starlightRoute` in a `try/catch` block and handle the cases where `starlightRoute` is not available.\n\n' + + 'If this is a Starlight built-in or third-party component, you may need to report a bug or avoid this use of the component.' + ); + } + return state.routeData; + }, + set(routeData: StarlightRouteData) { + state.routeData = routeData; + }, + }); +} diff --git a/packages/starlight/package.json b/packages/starlight/package.json index dc1bcbe3910..4e94889d685 100644 --- a/packages/starlight/package.json +++ b/packages/starlight/package.json @@ -1,10 +1,14 @@ { "name": "@astrojs/starlight", - "version": "0.10.3", + "version": "0.37.6", "description": "Build beautiful, high-performance documentation websites with Astro", "scripts": { "test": "vitest", - "test:coverage": "vitest run --coverage" + "test:legacy": "LEGACY_COLLECTIONS=true vitest", + "test:coverage": "vitest run --coverage", + "test:e2e": "pnpm test:e2e:chrome", + "test:e2e:chrome": "playwright install --with-deps chromium && playwright test --project chrome", + "test:e2e:firefox": "playwright install --with-deps firefox && playwright test --project firefox" }, "keywords": [ "docs", @@ -25,36 +29,203 @@ "type": "module", "exports": { ".": "./index.ts", + "./locals": "./locals.ts", "./components": "./components.ts", + "./components/LanguageSelect.astro": { + "types": "./components/LanguageSelect.astro.tsx", + "import": "./components/LanguageSelect.astro" + }, + "./components/Select.astro": { + "types": "./components/Select.astro.tsx", + "import": "./components/Select.astro" + }, + "./components/Banner.astro": { + "types": "./components/Banner.astro.tsx", + "import": "./components/Banner.astro" + }, + "./components/LastUpdated.astro": { + "types": "./components/LastUpdated.astro.tsx", + "import": "./components/LastUpdated.astro" + }, + "./components/Sidebar.astro": { + "types": "./components/Sidebar.astro.tsx", + "import": "./components/Sidebar.astro" + }, + "./components/MarkdownContent.astro": { + "types": "./components/MarkdownContent.astro.tsx", + "import": "./components/MarkdownContent.astro" + }, + "./components/SidebarPersister.astro": { + "types": "./components/SidebarPersister.astro.tsx", + "import": "./components/SidebarPersister.astro" + }, + "./components/SidebarSublist.astro": { + "types": "./components/SidebarSublist.astro.tsx", + "import": "./components/SidebarSublist.astro" + }, + "./components/ContentPanel.astro": { + "types": "./components/ContentPanel.astro.tsx", + "import": "./components/ContentPanel.astro" + }, + "./components/MobileMenuFooter.astro": { + "types": "./components/MobileMenuFooter.astro.tsx", + "import": "./components/MobileMenuFooter.astro" + }, + "./components/SiteTitle.astro": { + "types": "./components/SiteTitle.astro.tsx", + "import": "./components/SiteTitle.astro" + }, + "./components/EditLink.astro": { + "types": "./components/EditLink.astro.tsx", + "import": "./components/EditLink.astro" + }, + "./components/MobileMenuToggle.astro": { + "types": "./components/MobileMenuToggle.astro.tsx", + "import": "./components/MobileMenuToggle.astro" + }, + "./components/SkipLink.astro": { + "types": "./components/SkipLink.astro.tsx", + "import": "./components/SkipLink.astro" + }, + "./components/MobileTableOfContents.astro": { + "types": "./components/MobileTableOfContents.astro.tsx", + "import": "./components/MobileTableOfContents.astro" + }, + "./components/SocialIcons.astro": { + "types": "./components/SocialIcons.astro.tsx", + "import": "./components/SocialIcons.astro" + }, + "./components/FallbackContentNotice.astro": { + "types": "./components/FallbackContentNotice.astro.tsx", + "import": "./components/FallbackContentNotice.astro" + }, + "./components/DraftContentNotice.astro": { + "types": "./components/DraftContentNotice.astro.tsx", + "import": "./components/DraftContentNotice.astro" + }, + "./components/Page.astro": { + "types": "./components/Page.astro.tsx", + "import": "./components/Page.astro" + }, + "./components/StarlightPage.astro": { + "types": "./components/StarlightPage.astro.tsx", + "import": "./components/StarlightPage.astro" + }, + "./components/AnchorHeading.astro": { + "types": "./components/AnchorHeading.astro.tsx", + "import": "./components/AnchorHeading.astro" + }, + "./components/Footer.astro": { + "types": "./components/Footer.astro.tsx", + "import": "./components/Footer.astro" + }, + "./components/PageFrame.astro": { + "types": "./components/PageFrame.astro.tsx", + "import": "./components/PageFrame.astro" + }, + "./components/TableOfContents.astro": { + "types": "./components/TableOfContents.astro.tsx", + "import": "./components/TableOfContents.astro" + }, + "./components/Head.astro": { + "types": "./components/Head.astro.tsx", + "import": "./components/Head.astro" + }, + "./components/PageSidebar.astro": { + "types": "./components/PageSidebar.astro.tsx", + "import": "./components/PageSidebar.astro" + }, + "./components/ThemeProvider.astro": { + "types": "./components/ThemeProvider.astro.tsx", + "import": "./components/ThemeProvider.astro" + }, + "./components/Header.astro": { + "types": "./components/Header.astro.tsx", + "import": "./components/Header.astro" + }, + "./components/PageTitle.astro": { + "types": "./components/PageTitle.astro.tsx", + "import": "./components/PageTitle.astro" + }, + "./components/ThemeSelect.astro": { + "types": "./components/ThemeSelect.astro.tsx", + "import": "./components/ThemeSelect.astro" + }, + "./components/Hero.astro": { + "types": "./components/Hero.astro.tsx", + "import": "./components/Hero.astro" + }, + "./components/Pagination.astro": { + "types": "./components/Pagination.astro.tsx", + "import": "./components/Pagination.astro" + }, + "./components/TwoColumnContent.astro": { + "types": "./components/TwoColumnContent.astro.tsx", + "import": "./components/TwoColumnContent.astro" + }, + "./components/Search.astro": { + "types": "./components/Search.astro.tsx", + "import": "./components/Search.astro" + }, + "./internal": "./internal.ts", + "./props": "./props.ts", "./schema": "./schema.ts", + "./loaders": "./loaders.ts", + "./route-data": "./route-data.ts", "./types": "./types.ts", - "./index.astro": "./index.astro", - "./404.astro": "./404.astro" + "./expressive-code": { + "types": "./expressive-code.d.ts", + "default": "./expressive-code.mjs" + }, + "./expressive-code/hast": { + "types": "./integrations/expressive-code/hast.d.ts", + "default": "./integrations/expressive-code/hast.mjs" + }, + "./routes/*": "./routes/*", + "./style/markdown.css": "./style/markdown.css" }, "peerDependencies": { - "astro": "^3.0.0" + "astro": "^5.5.0" }, "devDependencies": { + "@playwright/test": "^1.45.0", "@types/node": "^18.16.19", - "@vitest/coverage-v8": "^0.33.0", - "astro": "^3.2.1", - "vitest": "^0.33.0" + "@vitest/coverage-v8": "^3.0.5", + "astro": "^5.6.1", + "linkedom": "^0.18.4", + "vitest": "^3.0.5" }, "dependencies": { - "@astrojs/mdx": "^1.1.0", - "@astrojs/sitemap": "^3.0.0", - "@pagefind/default-ui": "^1.0.3", - "@types/mdast": "^3.0.11", + "@astrojs/markdown-remark": "^6.3.1", + "@astrojs/mdx": "^4.2.3", + "@astrojs/sitemap": "^3.3.0", + "@pagefind/default-ui": "^1.3.0", + "@types/hast": "^3.0.4", + "@types/js-yaml": "^4.0.9", + "@types/mdast": "^4.0.4", + "astro-expressive-code": "^0.41.1", "bcp-47": "^2.1.0", - "execa": "^7.1.1", - "hast-util-select": "^5.0.5", - "hastscript": "^7.2.0", - "pagefind": "^1.0.3", - "rehype": "^12.0.1", - "remark-directive": "^2.0.1", - "unified": "^10.1.2", - "unist-util-remove": "^3.1.1", - "unist-util-visit": "^4.1.2", - "vfile": "^5.3.7" + "hast-util-from-html": "^2.0.1", + "hast-util-select": "^6.0.2", + "hast-util-to-string": "^3.0.0", + "hastscript": "^9.0.0", + "i18next": "^23.11.5", + "js-yaml": "^4.1.0", + "klona": "^2.0.6", + "magic-string": "^0.30.17", + "mdast-util-directive": "^3.0.0", + "mdast-util-to-markdown": "^2.1.0", + "mdast-util-to-string": "^4.0.0", + "pagefind": "^1.3.0", + "rehype": "^13.0.1", + "rehype-format": "^5.0.0", + "remark-directive": "^3.0.0", + "ultrahtml": "^1.6.0", + "unified": "^11.0.5", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.2" + }, + "publishConfig": { + "provenance": true } } diff --git a/packages/starlight/playwright.config.ts b/packages/starlight/playwright.config.ts new file mode 100644 index 00000000000..cf14dd6d4ac --- /dev/null +++ b/packages/starlight/playwright.config.ts @@ -0,0 +1,27 @@ +import { defineConfig, devices } from '@playwright/test'; + +// Toggle headless mode on/off. +const headless = true; + +export default defineConfig({ + forbidOnly: !!process.env['CI'], + projects: [ + { + name: 'chrome', + use: { + ...devices['Desktop Chrome'], + headless, + }, + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'], + headless, + }, + }, + ], + testMatch: '__e2e__/*.test.ts', + timeout: 40 * 1_000, + workers: 1, +}); diff --git a/packages/starlight/props.ts b/packages/starlight/props.ts new file mode 100644 index 00000000000..c94d5080946 --- /dev/null +++ b/packages/starlight/props.ts @@ -0,0 +1,14 @@ +import type { StarlightRouteData } from './utils/routing/types'; +export type { StarlightPageProps } from './utils/starlight-page'; + +/** + * @deprecated The `Props` type is deprecated. If updating an override to use + * `Astro.locals.starlightRoute` instead of `Astro.props`, import the new `StarlightRouteData` + * type instead: + * ```astro + * --- + * import type { StarlightRouteData } from '@astrojs/starlight/route-data'; + * --- + * ``` + */ +export type Props = StarlightRouteData; diff --git a/packages/starlight/route-data.ts b/packages/starlight/route-data.ts new file mode 100644 index 00000000000..b54bbd84d2c --- /dev/null +++ b/packages/starlight/route-data.ts @@ -0,0 +1,11 @@ +import type { APIContext } from 'astro'; +export type { StarlightRouteData } from './utils/routing/types'; + +export type RouteMiddlewareHandler = ( + context: APIContext, + next: () => Promise<void> +) => void | Promise<void>; + +export function defineRouteMiddleware(fn: RouteMiddlewareHandler) { + return fn; +} diff --git a/packages/starlight/routes/common.astro b/packages/starlight/routes/common.astro new file mode 100644 index 00000000000..8c4bfae2ef8 --- /dev/null +++ b/packages/starlight/routes/common.astro @@ -0,0 +1,23 @@ +--- +import { render } from 'astro:content'; +import Page from '../components/Page.astro'; +import { getRoute, useRouteData } from '../utils/routing/data'; +import { attachRouteDataAndRunMiddleware } from '../utils/routing/middleware'; + +const route = await getRoute(Astro); +/** + * The call to `render` from `astro:content` is purposely made in this file to work around a + * development mode head propagation issue which is heavily tied to `astro:content` imports. Even + * though we have a test for this, refactoring and moving this code to a different file should be + * avoided for now until the linked issue which also contains more details is resolved. + * + * @see https://github.com/withastro/astro/issues/13724 + */ +const renderResult = await render(route.entry); + +await attachRouteDataAndRunMiddleware(Astro, useRouteData(Astro, route, renderResult)); + +const { Content, entry } = Astro.locals.starlightRoute; +--- + +<Page>{Content && <Content frontmatter={entry.data} />}</Page> diff --git a/packages/starlight/routes/ssr/404.astro b/packages/starlight/routes/ssr/404.astro new file mode 100644 index 00000000000..9376b3105b3 --- /dev/null +++ b/packages/starlight/routes/ssr/404.astro @@ -0,0 +1,7 @@ +--- +import FourOhFour from '../static/404.astro'; + +export const prerender = false; +--- + +<FourOhFour /> diff --git a/packages/starlight/routes/ssr/index.astro b/packages/starlight/routes/ssr/index.astro new file mode 100644 index 00000000000..8698373fd4e --- /dev/null +++ b/packages/starlight/routes/ssr/index.astro @@ -0,0 +1,14 @@ +--- +import { getRouteBySlugParam } from '../../utils/routing'; +import CommonPage from '../common.astro'; + +export const prerender = false; + +const route = getRouteBySlugParam(Astro.params.slug); + +if (route === undefined) { + return new Response(null, { status: 404 }); +} +--- + +<CommonPage /> diff --git a/packages/starlight/routes/static/404.astro b/packages/starlight/routes/static/404.astro new file mode 100644 index 00000000000..aa90d9cbcd7 --- /dev/null +++ b/packages/starlight/routes/static/404.astro @@ -0,0 +1,7 @@ +--- +import CommonPage from '../common.astro'; + +export const prerender = true; +--- + +<CommonPage /> diff --git a/packages/starlight/routes/static/index.astro b/packages/starlight/routes/static/index.astro new file mode 100644 index 00000000000..559645c5046 --- /dev/null +++ b/packages/starlight/routes/static/index.astro @@ -0,0 +1,12 @@ +--- +import { paths } from '../../utils/routing'; +import CommonPage from '../common.astro'; + +export const prerender = true; + +export async function getStaticPaths() { + return paths; +} +--- + +<CommonPage /> diff --git a/packages/starlight/schema.ts b/packages/starlight/schema.ts index 89fc47e2811..905258e45c2 100644 --- a/packages/starlight/schema.ts +++ b/packages/starlight/schema.ts @@ -3,154 +3,171 @@ import type { SchemaContext } from 'astro:content'; import { HeadConfigSchema } from './schemas/head'; import { PrevNextLinkConfigSchema } from './schemas/prevNextLink'; import { TableOfContentsSchema } from './schemas/tableOfContents'; -import { Icons } from './components/Icons'; import { BadgeConfigSchema } from './schemas/badge'; +import { HeroSchema } from './schemas/hero'; +import { SidebarLinkItemHTMLAttributesSchema } from './schemas/sidebar'; export { i18nSchema } from './schemas/i18n'; -type IconName = keyof typeof Icons; -const iconNames = Object.keys(Icons) as [IconName, ...IconName[]]; - -export function docsSchema() { - return ({ image }: SchemaContext) => - z.object({ - /** The title of the current page. Required. */ - title: z.string(), - - /** - * A short description of the current page’s content. Optional, but recommended. - * A good description is 150–160 characters long and outlines the key content - * of the page in a clear and engaging way. - */ - description: z.string().optional(), - - /** - * Custom URL where a reader can edit this page. - * Overrides the `editLink.baseUrl` global config if set. - * - * Can also be set to `false` to disable showing an edit link on this page. - */ - editUrl: z.union([z.string().url(), z.boolean()]).optional().default(true), - - /** Set custom `<head>` tags just for this page. */ - head: HeadConfigSchema(), - - /** Override global table of contents configuration for this page. */ - tableOfContents: TableOfContentsSchema().optional(), - - /** - * Set the layout style for this page. - * Can be `'doc'` (the default) or `'splash'` for a wider layout without any sidebars. - */ - template: z.enum(['doc', 'splash']).default('doc'), - - /** Display a hero section on this page. */ - hero: z - .object({ - /** - * The large title text to show. If not provided, will default to the top-level `title`. - * Can include HTML. - */ - title: z.string().optional(), - /** - * A short bit of text about your project. - * Will be displayed in a smaller size below the title. - */ - tagline: z.string().optional(), - /** The image to use in the hero. You can provide either a relative `file` path or raw `html`. */ - image: z - .object({ - /** Alt text for screenreaders and other assistive technologies describing your hero image. */ - alt: z.string().default(''), - /** Relative path to an image file in your repo, e.g. `../../assets/hero.png`. */ - file: image().optional(), - /** Raw HTML string instead of an image file. Useful for inline SVGs or more complex hero content. */ - html: z.string().optional(), - }) - .optional(), - /** An array of call-to-action links displayed at the bottom of the hero. */ - actions: z - .object({ - /** Text label displayed in the link. */ - text: z.string(), - /** Value for the link’s `href` attribute, e.g. `/page` or `https://mysite.com`. */ - link: z.string(), - /** Button style to use. One of `primary`, `secondary`, or `minimal` (the default). */ - variant: z.enum(['primary', 'secondary', 'minimal']).default('minimal'), - /** - * An optional icon to display alongside the link text. - * Can be an inline `<svg>` or the name of one of Starlight’s built-in icons. - */ - icon: z - .union([z.enum(iconNames), z.string().startsWith('<svg')]) - .transform((icon) => { - const parsedIcon = z.enum(iconNames).safeParse(icon); - return parsedIcon.success - ? ({ type: 'icon', name: parsedIcon.data } as const) - : ({ type: 'raw', html: icon } as const); - }) - .optional(), - }) - .array() - .default([]), - }) - .optional(), - - /** - * The last update date of the current page. - * Overrides the `lastUpdated` global config or the date generated from the Git history. - */ - lastUpdated: z.union([z.date(), z.boolean()]).optional(), - - /** - * The previous navigation link configuration. - * Overrides the `pagination` global config or the link text and/or URL. - */ - prev: PrevNextLinkConfigSchema(), - /** - * The next navigation link configuration. - * Overrides the `pagination` global config or the link text and/or URL. - */ - next: PrevNextLinkConfigSchema(), - - sidebar: z - .object({ - /** - * The order of this page in the navigation. - * Pages are sorted by this value in ascending order. Then by slug. - * If not provided, pages will be sorted alphabetically by slug. - * If two pages have the same order value, they will be sorted alphabetically by slug. - */ - order: z.number().optional(), - - /** - * The label for this page in the navigation. - * Defaults to the page `title` if not set. - */ - label: z.string().optional(), - - /** - * Prevents this page from being included in autogenerated sidebar groups. - */ - hidden: z.boolean().default(false), - /** - * Adds a badge to the sidebar link. - * Can be a string or an object with a variant and text. - * Variants include 'note', 'tip', 'caution', 'danger', 'success', and 'default'. - * Passing only a string defaults to the 'default' variant which uses the site accent color. - */ - badge: BadgeConfigSchema(), - }) - .default({}), - - /** Display an announcement banner at the top of this page. */ - banner: z - .object({ - /** The content of the banner. Supports HTML syntax. */ - content: z.string(), - }) - .optional(), - - /** Pagefind indexing for this page - set to false to disable. */ - pagefind: z.boolean().default(true), - }); +/** Default content collection schema for Starlight’s `docs` collection. */ +const StarlightFrontmatterSchema = (context: SchemaContext) => + z.object({ + /** The title of the current page. Required. */ + title: z.string(), + + /** + * A short description of the current page’s content. Optional, but recommended. + * A good description is 150–160 characters long and outlines the key content + * of the page in a clear and engaging way. + */ + description: z.string().optional(), + + /** + * Custom URL where a reader can edit this page. + * Overrides the `editLink.baseUrl` global config if set. + * + * Can also be set to `false` to disable showing an edit link on this page. + */ + editUrl: z.union([z.string().url(), z.boolean()]).optional().default(true), + + /** Set custom `<head>` tags just for this page. */ + head: HeadConfigSchema({ source: 'content' }), + + /** Override global table of contents configuration for this page. */ + tableOfContents: TableOfContentsSchema().optional(), + + /** + * Set the layout style for this page. + * Can be `'doc'` (the default) or `'splash'` for a wider layout without any sidebars. + */ + template: z.enum(['doc', 'splash']).default('doc'), + + /** Display a hero section on this page. */ + hero: HeroSchema(context).optional(), + + /** + * The last update date of the current page. + * Overrides the `lastUpdated` global config or the date generated from the Git history. + */ + lastUpdated: z.union([z.date(), z.boolean()]).optional(), + + /** + * The previous navigation link configuration. + * Overrides the `pagination` global config or the link text and/or URL. + */ + prev: PrevNextLinkConfigSchema(), + /** + * The next navigation link configuration. + * Overrides the `pagination` global config or the link text and/or URL. + */ + next: PrevNextLinkConfigSchema(), + + sidebar: z + .object({ + /** + * The order of this page in the navigation. + * Pages are sorted by this value in ascending order. Then by slug. + * If not provided, pages will be sorted alphabetically by slug. + * If two pages have the same order value, they will be sorted alphabetically by slug. + */ + order: z.number().optional(), + + /** + * The label for this page in the navigation. + * Defaults to the page `title` if not set. + */ + label: z.string().optional(), + + /** + * Prevents this page from being included in autogenerated sidebar groups. + */ + hidden: z.boolean().default(false), + /** + * Adds a badge to the sidebar link. + * Can be a string or an object with a variant and text. + * Variants include 'note', 'tip', 'caution', 'danger', 'success', and 'default'. + * Passing only a string defaults to the 'default' variant which uses the site accent color. + */ + badge: BadgeConfigSchema(), + /** HTML attributes to add to the sidebar link. */ + attrs: SidebarLinkItemHTMLAttributesSchema(), + }) + .default({}), + + /** Display an announcement banner at the top of this page. */ + banner: z + .object({ + /** The content of the banner. Supports HTML syntax. */ + content: z.string(), + }) + .optional(), + + /** Pagefind indexing for this page - set to false to disable. */ + pagefind: z.boolean().default(true), + + /** + * Indicates that this page is a draft and will not be included in production builds. + * Note that the page will still be available when running Astro in development mode. + */ + draft: z.boolean().default(false), + }); +/** Type of Starlight’s default frontmatter schema. */ +type DefaultSchema = ReturnType<typeof StarlightFrontmatterSchema>; + +/** Plain object, union, and intersection Zod types. */ +type BaseSchemaWithoutEffects = + | z.AnyZodObject + | z.ZodUnion<[BaseSchemaWithoutEffects, ...BaseSchemaWithoutEffects[]]> + | z.ZodDiscriminatedUnion<string, z.AnyZodObject[]> + | z.ZodIntersection<BaseSchemaWithoutEffects, BaseSchemaWithoutEffects>; +/** Base subset of Zod types that we support passing to the `extend` option. */ +type BaseSchema = BaseSchemaWithoutEffects | z.ZodEffects<BaseSchemaWithoutEffects>; + +/** Type that extends Starlight’s default schema with an optional, user-defined schema. */ +type ExtendedSchema<T extends BaseSchema = never> = [T] extends [never] + ? DefaultSchema + : T extends BaseSchema + ? z.ZodIntersection<DefaultSchema, T> + : DefaultSchema; + +interface DocsSchemaOpts<T extends BaseSchema> { + /** + * Extend Starlight’s schema with additional fields. + * + * @example + * // Extend the built-in schema with a Zod schema. + * docsSchema({ + * extend: z.object({ + * // Add a new field to the schema. + * category: z.enum(['tutorial', 'guide', 'reference']).optional(), + * }), + * }) + * + * // Use the Astro image helper. + * docsSchema({ + * extend: ({ image }) => { + * return z.object({ + * cover: image(), + * }); + * }, + * }) + */ + extend?: T | ((context: SchemaContext) => T); +} + +/** Content collection schema for Starlight’s `docs` collection. */ +export function docsSchema<T extends BaseSchema = never>( + ...args: [DocsSchemaOpts<T>?] +): (context: SchemaContext) => ExtendedSchema<T> { + const [options = {}] = args; + const { extend } = options; + + return (context: SchemaContext) => { + const UserSchema = typeof extend === 'function' ? extend(context) : extend; + + return ( + UserSchema + ? StarlightFrontmatterSchema(context).and(UserSchema) + : StarlightFrontmatterSchema(context) + ) as ExtendedSchema<T>; + }; } diff --git a/packages/starlight/schemas/badge.ts b/packages/starlight/schemas/badge.ts index dc6fdb67a16..f3f1f738f68 100644 --- a/packages/starlight/schemas/badge.ts +++ b/packages/starlight/schemas/badge.ts @@ -1,14 +1,29 @@ import { z } from 'astro/zod'; -const badgeSchema = () => - z.object({ - variant: z.enum(['note', 'danger', 'success', 'caution', 'tip', 'default']).default('default'), - text: z.string(), - }); +const badgeBaseSchema = z.object({ + variant: z.enum(['note', 'danger', 'success', 'caution', 'tip', 'default']).default('default'), + class: z.string().optional(), +}); + +const badgeSchema = badgeBaseSchema.extend({ + text: z.string(), +}); + +const i18nBadgeSchema = badgeBaseSchema.extend({ + text: z.union([z.string(), z.record(z.string())]), +}); + +export const BadgeComponentSchema = badgeSchema + .extend({ + size: z.enum(['small', 'medium', 'large']).default('small'), + }) + .passthrough(); + +export type BadgeComponentProps = z.input<typeof BadgeComponentSchema>; export const BadgeConfigSchema = () => z - .union([z.string(), badgeSchema()]) + .union([z.string(), badgeSchema]) .transform((badge) => { if (typeof badge === 'string') { return { variant: 'default' as const, text: badge }; @@ -17,4 +32,8 @@ export const BadgeConfigSchema = () => }) .optional(); -export type Badge = z.output<ReturnType<typeof badgeSchema>>; +export const I18nBadgeConfigSchema = () => z.union([z.string(), i18nBadgeSchema]).optional(); + +export type Badge = z.output<typeof badgeSchema>; +export type I18nBadge = z.output<typeof i18nBadgeSchema>; +export type I18nBadgeConfig = z.output<ReturnType<typeof I18nBadgeConfigSchema>>; diff --git a/packages/starlight/schemas/components.ts b/packages/starlight/schemas/components.ts new file mode 100644 index 00000000000..3ae79ec65cf --- /dev/null +++ b/packages/starlight/schemas/components.ts @@ -0,0 +1,265 @@ +import { z } from 'astro/zod'; + +export function ComponentConfigSchema() { + return z + .object({ + /* + HEAD ---------------------------------------------------------------------------------------- + */ + + /** + * Component rendered inside each page’s `<head>`. + * Includes important tags including `<title>`, and `<meta charset="utf-8">`. + * + * Override this component as a last resort. Prefer the `head` option Starlight config if possible. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/Head.astro `Head` default implementation} + */ + Head: z.string().default('@astrojs/starlight/components/Head.astro'), + + /** + * Component rendered inside `<head>` that sets up dark/light theme support. + * The default implementation includes an inline script and a `<template>` used by the + * script in `ThemeSelect.astro`. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeProvider.astro `ThemeProvider` default implementation} + */ + ThemeProvider: z.string().default('@astrojs/starlight/components/ThemeProvider.astro'), + + /* + BODY ---------------------------------------------------------------------------------------- + */ + + /** + * Component rendered as the first element inside `<body>` which links to the main page + * content for accessibility. The default implementation is hidden until a user focuses it + * by tabbing with their keyboard. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/SkipLink.astro `SkipLink` default implementation} + */ + SkipLink: z.string().default('@astrojs/starlight/components/SkipLink.astro'), + + /* + LAYOUT -------------------------------------------------------------------------------------- + */ + + /** + * Layout component wrapped around most of the page content. + * The default implementation sets up the header–sidebar–main layout and includes + * `header` and `sidebar` named slots along with a default slot for the main content. + * It also renders `<MobileMenuToggle />` to support toggling the sidebar navigation + * on small (mobile) viewports. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageFrame.astro `PageFrame` default implementation} + */ + PageFrame: z.string().default('@astrojs/starlight/components/PageFrame.astro'), + /** + * Component rendered inside `<PageFrame>` that is responsible for toggling the + * sidebar navigation on small (mobile) viewports. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuToggle.astro `MobileMenuToggle` default implementation} + */ + MobileMenuToggle: z.string().default('@astrojs/starlight/components/MobileMenuToggle.astro'), + + /** + * Layout component wrapped around the main content column and right sidebar (table of contents). + * The default implementation handles the switch between a single-column, small-viewport layout + * and a two-column, larger-viewport layout. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/TwoColumnContent.astro `TwoColumnContent` default implementation} + */ + TwoColumnContent: z.string().default('@astrojs/starlight/components/TwoColumnContent.astro'), + + /* + HEADER -------------------------------------------------------------------------------------- + */ + + /** + * Header component displayed at the top of every page. + * The default implementation displays `<SiteTitle />`, `<Search />`, `<SocialIcons />`, + * `<ThemeSelect />`, and `<LanguageSelect />`. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/Header.astro `Header` default implementation} + */ + Header: z.string().default('@astrojs/starlight/components/Header.astro'), + /** + * Component rendered at the start of the site header to render the site title. + * The default implementation includes logic for rendering logos defined in Starlight config. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/SiteTitle.astro `SiteTitle` default implementation} + */ + SiteTitle: z.string().default('@astrojs/starlight/components/SiteTitle.astro'), + /** + * Component used to render Starlight’s search UI. The default implementation includes the + * button in the header and the code for displaying a search modal when it is clicked. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/Search.astro `Search` default implementation} + */ + Search: z.string().default('@astrojs/starlight/components/Search.astro'), + /** + * Component rendered in the site header including social icon links. The default + * implementation uses the `social` option in Starlight config to render icons and links. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/SocialIcons.astro `SocialIcons` default implementation} + */ + SocialIcons: z.string().default('@astrojs/starlight/components/SocialIcons.astro'), + /** + * Component rendered in the site header that allows users to select their preferred color scheme. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/ThemeSelect.astro `ThemeSelect` default implementation} + */ + ThemeSelect: z.string().default('@astrojs/starlight/components/ThemeSelect.astro'), + /** + * Component rendered in the site header that allows users to switch to a different language. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/LanguageSelect.astro `LanguageSelect` default implementation} + */ + LanguageSelect: z.string().default('@astrojs/starlight/components/LanguageSelect.astro'), + + /* + SIDEBAR ------------------------------------------------------------------------------------- + */ + + /** + * Component rendered before page content that contains global navigation. + * The default implementation displays as a sidebar on wide enough viewports and inside a + * drop-down menu on small (mobile) viewports. It also renders `<MobileMenuFooter />` to + * show additional items inside the mobile menu. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/Sidebar.astro `Sidebar` default implementation} + */ + Sidebar: z.string().default('@astrojs/starlight/components/Sidebar.astro'), + /** + * Component rendered at the bottom of the mobile drop-down menu. + * The default implementation renders `<ThemeSelect />` and `<LanguageSelect />`. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuFooter.astro `MobileMenuFooter` default implementation} + */ + MobileMenuFooter: z.string().default('@astrojs/starlight/components/MobileMenuFooter.astro'), + + /* + TOC ----------------------------------------------------------------------------------------- + */ + + /** + * Component rendered before the main page’s content to display a table of contents. + * The default implementation renders `<TableOfContents />` and `<MobileTableOfContents />`. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageSidebar.astro `PageSidebar` default implementation} + */ + PageSidebar: z.string().default('@astrojs/starlight/components/PageSidebar.astro'), + /** + * Component that renders the current page’s table of contents on wider viewports. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/TableOfContents.astro `TableOfContents` default implementation} + */ + TableOfContents: z.string().default('@astrojs/starlight/components/TableOfContents.astro'), + /** + * Component that renders the current page’s table of contents on small (mobile) viewports. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileTableOfContents.astro `MobileTableOfContents` default implementation} + */ + MobileTableOfContents: z + .string() + .default('@astrojs/starlight/components/MobileTableOfContents.astro'), + + /* + CONTENT HEADER ------------------------------------------------------------------------------ + */ + + /** + * Banner component rendered at the top of each page. The default implementation uses the + * page’s `banner` frontmatter value to decide whether or not to render. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/Banner.astro `Banner` default implementation} + */ + Banner: z.string().default('@astrojs/starlight/components/Banner.astro'), + + /** + * Layout component used to wrap sections of the main content column. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/ContentPanel.astro `ContentPanel` default implementation} + */ + ContentPanel: z.string().default('@astrojs/starlight/components/ContentPanel.astro'), + + /** + * Component containing the `<h1>` element for the current page. + * + * Implementations should ensure they set `id="_top"` on the `<h1>` element as in the default + * implementation. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageTitle.astro `PageTitle` default implementation} + */ + PageTitle: z.string().default('@astrojs/starlight/components/PageTitle.astro'), + + /** + * Notice displayed to users on pages where a translation for the current language is not + * available. Only used on multilingual sites. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/FallbackContentNotice.astro `FallbackContentNotice` default implementation} + */ + FallbackContentNotice: z + .string() + .default('@astrojs/starlight/components/FallbackContentNotice.astro'), + + /** + * Notice displayed to users on draft pages. Only used in development mode. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/DraftContentNotice.astro `DraftContentNotice` default implementation} + */ + DraftContentNotice: z + .string() + .default('@astrojs/starlight/components/DraftContentNotice.astro'), + + /** + * Component rendered at the top of the page when `hero` is set in frontmatter. The default + * implementation shows a large title, tagline, and call-to-action links alongside an optional image. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/Hero.astro `Hero` default implementation} + */ + Hero: z.string().default('@astrojs/starlight/components/Hero.astro'), + + /* + CONTENT ------------------------------------------------------------------------------------- + */ + + /** + * Component rendered around each page’s main content. + * The default implementation sets up basic styles to apply to Markdown content. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/MarkdownContent.astro `MarkdownContent` default implementation} + */ + MarkdownContent: z.string().default('@astrojs/starlight/components/MarkdownContent.astro'), + + /* + CONTENT FOOTER ------------------------------------------------------------------------------ + */ + + /** + * Footer component displayed at the bottom of each documentation page. + * The default implementation displays `<LastUpdated />`, `<Pagination />`, and `<EditLink />`. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/Footer.astro `Footer` default implementation} + */ + Footer: z.string().default('@astrojs/starlight/components/Footer.astro'), + /** + * Component rendered in the page footer to display the last-updated date. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/LastUpdated.astro `LastUpdated` default implementation} + */ + LastUpdated: z.string().default('@astrojs/starlight/components/LastUpdated.astro'), + /** + * Component rendered in the page footer to display navigation arrows between previous/next pages. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/Pagination.astro `Pagination` default implementation} + */ + Pagination: z.string().default('@astrojs/starlight/components/Pagination.astro'), + /** + * Component rendered in the page footer to display a link to where the page can be edited. + * + * @see {@link https://github.com/withastro/starlight/blob/main/packages/starlight/components/EditLink.astro `EditLink` default implementation} + */ + EditLink: z.string().default('@astrojs/starlight/components/EditLink.astro'), + }) + .default({}); +} diff --git a/packages/starlight/schemas/expressiveCode.ts b/packages/starlight/schemas/expressiveCode.ts new file mode 100644 index 00000000000..97420ab4ca2 --- /dev/null +++ b/packages/starlight/schemas/expressiveCode.ts @@ -0,0 +1,15 @@ +import { z } from 'astro/zod'; +import type { StarlightExpressiveCodeOptions } from '../integrations/expressive-code'; + +export const ExpressiveCodeSchema = () => + z + .union([ + z.custom<StarlightExpressiveCodeOptions>( + (value) => typeof value === 'object' && (value as StarlightExpressiveCodeOptions) + ), + z.boolean(), + ]) + .describe( + 'Define how code blocks are rendered by passing options to Expressive Code, or disable the integration by passing `false`.' + ) + .optional(); diff --git a/packages/starlight/schemas/favicon.ts b/packages/starlight/schemas/favicon.ts index 7f599099d2f..b3b6a570096 100644 --- a/packages/starlight/schemas/favicon.ts +++ b/packages/starlight/schemas/favicon.ts @@ -15,7 +15,9 @@ export const FaviconSchema = () => .string() .default('/favicon.svg') .transform((favicon, ctx) => { - const ext = extname(favicon).toLowerCase(); + // favicon can be absolute or relative url + const { pathname } = new URL(favicon, 'https://example.com'); + const ext = extname(pathname).toLowerCase(); if (!isFaviconExt(ext)) { ctx.addIssue({ diff --git a/packages/starlight/schemas/head.ts b/packages/starlight/schemas/head.ts index d942c57b7e4..367480b2917 100644 --- a/packages/starlight/schemas/head.ts +++ b/packages/starlight/schemas/head.ts @@ -1,16 +1,47 @@ import { z } from 'astro/zod'; +import yaml from 'js-yaml'; -export const HeadConfigSchema = () => +export const HeadConfigSchema = ({ + source, +}: { + /** + * Depending on the content being validated, either a user's config or a page's frontmatter, + * different error messages will be shown. + */ + source: 'config' | 'content'; +}) => z .array( - z.object({ - /** Name of the HTML tag to add to `<head>`, e.g. `'meta'`, `'link'`, or `'script'`. */ - tag: z.enum(['title', 'base', 'link', 'style', 'meta', 'script', 'noscript', 'template']), - /** Attributes to set on the tag, e.g. `{ rel: 'stylesheet', href: '/custom.css' }`. */ - attrs: z.record(z.union([z.string(), z.boolean(), z.undefined()])).default({}), - /** Content to place inside the tag (optional). */ - content: z.string().default(''), - }) + z + .object({ + /** Name of the HTML tag to add to `<head>`, e.g. `'meta'`, `'link'`, or `'script'`. */ + tag: z.enum(['title', 'base', 'link', 'style', 'meta', 'script', 'noscript', 'template']), + /** Attributes to set on the tag, e.g. `{ rel: 'stylesheet', href: '/custom.css' }`. */ + attrs: z.record(z.union([z.string(), z.boolean(), z.undefined()])).optional(), + /** Content to place inside the tag (optional). */ + content: z.string().optional(), + }) + .superRefine((config, ctx) => { + if (config.tag !== 'meta' || config.content === undefined) return; + const { content, ...rest } = config; + const correctTag = { + ...rest, + attrs: { ...(config.attrs ?? { name: 'identifier' }), content: config.content }, + }; + const code = + source === 'config' ? JSON.stringify(correctTag, null, 2) : yaml.dump([correctTag]); + ctx.addIssue({ + code: 'custom', + message: + `The \`head\` configuration includes a \`meta\` tag with \`content\` which is invalid HTML.\n` + + `You should instead use a \`content\` attribute ` + + (Object.keys(rest.attrs ?? {}).length === 0 + ? 'with an additional attribute such as `name`, `property`, or `http-equiv` to identify the kind of metadata it represents ' + : '') + + `in the \`attrs\` object:\n\n` + + code, + }); + }) ) .default([]); diff --git a/packages/starlight/schemas/hero.ts b/packages/starlight/schemas/hero.ts new file mode 100644 index 00000000000..e1af1f90676 --- /dev/null +++ b/packages/starlight/schemas/hero.ts @@ -0,0 +1,69 @@ +import { z } from 'astro/zod'; +import type { SchemaContext } from 'astro:content'; +import { IconSchema } from './icon'; + +export const HeroSchema = ({ image }: SchemaContext) => + z.object({ + /** + * The large title text to show. If not provided, will default to the top-level `title`. + * Can include HTML. + */ + title: z.string().optional(), + /** + * A short bit of text about your project. + * Will be displayed in a smaller size below the title. + */ + tagline: z.string().optional(), + /** The image to use in the hero. You can provide either a relative `file` path or raw `html`. */ + image: z + .union([ + z.object({ + /** Alt text for screenreaders and other assistive technologies describing your hero image. */ + alt: z.string().default(''), + /** Relative path to an image file in your repo, e.g. `../../assets/hero.png`. */ + file: image(), + }), + z.object({ + /** Alt text for screenreaders and other assistive technologies describing your hero image. */ + alt: z.string().default(''), + /** Relative path to an image file in your repo to use in dark mode, e.g. `../../assets/hero-dark.png`. */ + dark: image(), + /** Relative path to an image file in your repo to use in light mode, e.g. `../../assets/hero-light.png`. */ + light: image(), + }), + z + .object({ + /** Raw HTML string instead of an image file. Useful for inline SVGs or more complex hero content. */ + html: z.string(), + }) + .transform(({ html }) => ({ html, alt: '' })), + ]) + .optional(), + /** An array of call-to-action links displayed at the bottom of the hero. */ + actions: z + .object({ + /** Text label displayed in the link. */ + text: z.string(), + /** Value for the link’s `href` attribute, e.g. `/page` or `https://mysite.com`. */ + link: z.string(), + /** Button style to use. One of `primary` (the default), `secondary`, or `minimal`. */ + variant: z.enum(['primary', 'secondary', 'minimal']).default('primary'), + /** + * An optional icon to display alongside the link text. + * Can be an inline `<svg>` or the name of one of Starlight’s built-in icons. + */ + icon: z + .union([IconSchema(), z.string().startsWith('<svg')]) + .transform((icon) => { + const parsedIcon = IconSchema().safeParse(icon); + return parsedIcon.success + ? ({ type: 'icon', name: parsedIcon.data } as const) + : ({ type: 'raw', html: icon } as const); + }) + .optional(), + /** HTML attributes to add to the link */ + attrs: z.record(z.union([z.string(), z.number(), z.boolean()])).optional(), + }) + .array() + .default([]), + }); diff --git a/packages/starlight/schemas/i18n.ts b/packages/starlight/schemas/i18n.ts index 070034128c3..11e5ae02c1d 100644 --- a/packages/starlight/schemas/i18n.ts +++ b/packages/starlight/schemas/i18n.ts @@ -1,11 +1,59 @@ import { z } from 'astro/zod'; -export function i18nSchema() { - return starlightI18nSchema().merge(pagefindI18nSchema()); +interface i18nSchemaOpts<T extends z.AnyZodObject = z.SomeZodObject> { + /** + * Extend Starlight’s i18n schema with additional fields. + * + * @example + * // Add two optional fields to the default schema. + * i18nSchema({ + * extend: z + * .object({ + * 'customUi.heading': z.string(), + * 'customUi.text': z.string(), + * }) + * .partial(), + * }) + */ + extend?: T; } +const defaultI18nSchema = () => + starlightI18nSchema().merge(pagefindI18nSchema()).merge(expressiveCodeI18nSchema()); +/** Type of Starlight’s default i18n schema, including extensions from Pagefind and Expressive Code. */ +type DefaultI18nSchema = ReturnType<typeof defaultI18nSchema>; + +/** + * Based on the the return type of Zod’s `merge()` method. Merges the type of two `z.object()` schemas. + * Also sets them as “passthrough” schemas as that’s how we use them. In practice whether or not the types + * are passthrough or not doesn’t matter too much. + * + * @see https://github.com/colinhacks/zod/blob/3032e240a0c227692bb96eedf240ed493c53f54c/src/types.ts#L2656-L2660 + */ +type MergeSchemas<A extends z.AnyZodObject, B extends z.AnyZodObject> = z.ZodObject< + z.objectUtil.extendShape<A['shape'], B['shape']>, + 'passthrough', + B['_def']['catchall'] +>; +/** Type that extends Starlight’s default i18n schema with an optional, user-defined schema. */ +type ExtendedSchema<T extends z.AnyZodObject> = T extends z.AnyZodObject + ? MergeSchemas<DefaultI18nSchema, T> + : DefaultI18nSchema; + +/** Content collection schema for Starlight’s optional `i18n` collection. */ +export function i18nSchema<T extends z.AnyZodObject = z.SomeZodObject>({ + extend = z.object({}) as T, +}: i18nSchemaOpts<T> = {}): ExtendedSchema<T> { + return defaultI18nSchema().merge(extend).passthrough() as ExtendedSchema<T>; +} +export type i18nSchemaOutput = z.output<ReturnType<typeof i18nSchema>>; + export function builtinI18nSchema() { - return starlightI18nSchema().required().strict().merge(pagefindI18nSchema()); + return starlightI18nSchema() + .required() + .strict() + .merge(pagefindI18nSchema()) + .merge(expressiveCodeI18nSchema()); } function starlightI18nSchema() { @@ -19,9 +67,11 @@ function starlightI18nSchema() { 'search.label': z.string().describe('Text displayed in the search bar.'), - 'search.shortcutLabel': z + 'search.ctrlKey': z .string() - .describe('Accessible label for the shortcut key to open the search modal.'), + .describe( + 'Visible representation of the Control key potentially used in the shortcut key to open the search modal.' + ), 'search.cancelLabel': z .string() @@ -49,12 +99,12 @@ function starlightI18nSchema() { 'menuButton.accessibleLabel': z .string() - .describe('Accessible label for he mobile menu button.'), + .describe('Accessible label for the mobile menu button.'), 'sidebarNav.accessibleLabel': z .string() .describe( - 'Accessible label for the main sidebar `<nav>` element to distinguish it fom other `<nav>` landmarks on the page.' + 'Accessible label for the main sidebar `<nav>` element to distinguish it from other `<nav>` landmarks on the page.' ), 'tableOfContents.onThisPage': z @@ -87,7 +137,29 @@ function starlightI18nSchema() { .string() .describe('Label shown on the “next page” pagination arrow in the page footer.'), + 'page.draft': z + .string() + .describe( + 'Development-only notice informing users they are on a page that is a draft which will not be included in production builds.' + ), + '404.text': z.string().describe('Text shown on Starlight’s default 404 page'), + 'aside.tip': z.string().describe('Text shown on the tip aside variant'), + 'aside.note': z.string().describe('Text shown on the note aside variant'), + 'aside.caution': z.string().describe('Text shown on the warning aside variant'), + 'aside.danger': z.string().describe('Text shown on the danger aside variant'), + + 'fileTree.directory': z + .string() + .describe('Label for the directory icon in the file tree component.'), + + 'builtWithStarlight.label': z + .string() + .describe( + 'Label for the “Built with Starlight” badge optionally displayed in the site footer.' + ), + + 'heading.anchorLabel': z.string().describe('Label for anchor links in Markdown content.'), }) .partial(); } @@ -157,3 +229,21 @@ function pagefindI18nSchema() { }) .partial(); } + +function expressiveCodeI18nSchema() { + return z + .object({ + 'expressiveCode.copyButtonCopied': z + .string() + .describe('Expressive Code UI translation. English default value: `"Copied!"`'), + + 'expressiveCode.copyButtonTooltip': z + .string() + .describe('Expressive Code UI translation. English default value: `"Copy to clipboard"`'), + + 'expressiveCode.terminalWindowFallbackTitle': z + .string() + .describe('Expressive Code UI translation. English default value: `"Terminal window"`'), + }) + .partial(); +} diff --git a/packages/starlight/schemas/icon.ts b/packages/starlight/schemas/icon.ts new file mode 100644 index 00000000000..49462371fe0 --- /dev/null +++ b/packages/starlight/schemas/icon.ts @@ -0,0 +1,7 @@ +import { z } from 'astro/zod'; +import { Icons, type StarlightIcon } from '../components/Icons'; + +const iconNames = Object.keys(Icons) as [StarlightIcon, ...StarlightIcon[]]; + +/** String that matches the name of one of Starlight’s built-in icons. */ +export const IconSchema = () => z.enum(iconNames); diff --git a/packages/starlight/schemas/pagefind.ts b/packages/starlight/schemas/pagefind.ts new file mode 100644 index 00000000000..2f3e1fc2442 --- /dev/null +++ b/packages/starlight/schemas/pagefind.ts @@ -0,0 +1,109 @@ +import { z } from 'astro/zod'; + +const indexWeightSchema = z.number().nonnegative().optional(); +const pagefindRankingWeightsSchema = z.object({ + /** + * Set Pagefind’s `pageLength` ranking option. + * + * The default value is `0.1` and values must be in the range `0` to `1`. + * + * @see https://pagefind.app/docs/ranking/#configuring-page-length + */ + pageLength: z.number().min(0).max(1).default(0.1), + /** + * Set Pagefind’s `termFrequency` ranking option. + * + * The default value is `0.1` and values must be in the range `0` to `1`. + * + * @see https://pagefind.app/docs/ranking/#configuring-term-frequency + */ + termFrequency: z.number().min(0).max(1).default(0.1), + /** + * Set Pagefind’s `termSaturation` ranking option. + * + * The default value is `2` and values must be in the range `0` to `2`. + * + * @see https://pagefind.app/docs/ranking/#configuring-term-saturation + */ + termSaturation: z.number().min(0).max(2).default(2), + /** + * Set Pagefind’s `termSimilarity` ranking option. + * + * The default value is `9` and values must be greater than or equal to `0`. + * + * @see https://pagefind.app/docs/ranking/#configuring-term-similarity + */ + termSimilarity: z.number().min(0).default(9), +}); +const pagefindIndexOptionsSchema = z.object({ + /** + * Overrides the URL path that Pagefind uses to load its search bundle + */ + basePath: z.string().optional(), + /** + * Appends the given baseURL to all search results. May be a path, or a full domain + */ + baseUrl: z.string().optional(), + /** + * Multiply all rankings for this index by the given weight. + * + * @see https://pagefind.app/docs/multisite/#changing-the-weighting-of-individual-indexes + */ + indexWeight: indexWeightSchema, + /** + * Apply this filter configuration to all search results from this index. + * + * Only applies in multisite setups. + * + * @see https://pagefind.app/docs/multisite/#filtering-results-by-index + */ + mergeFilter: z.record(z.string(), z.string().or(z.array(z.string()).nonempty())).optional(), + /** + * Language of this index. + * + * @see https://pagefind.app/docs/multisite/#merging-a-specific-language-index + */ + language: z.string().optional(), + /** + * Configure how search result rankings are calculated by Pagefind. + */ + // We apply a default value to merged indexes in order to share the same ranking for them and the current site when not set explicitly. + ranking: pagefindRankingWeightsSchema.default({}), +}); + +const pagefindSchema = z.object({ + /** + * Configure how search results from the current website are weighted by Pagefind + * compared to results from other sites when using the `mergeIndex` option. + * + * @see https://pagefind.app/docs/multisite/#changing-the-weighting-of-individual-indexes + */ + indexWeight: indexWeightSchema, + /** Configure how search result rankings are calculated by Pagefind. */ + ranking: pagefindRankingWeightsSchema.default({}), + /** + * Configure how search indexes from different sites are merged by Pagefind. + * + * @see https://pagefind.app/docs/multisite/#searching-additional-sites-from-pagefind-ui + */ + mergeIndex: z + .array( + /** + * Each entry of this array represents a `PagefindIndexOptions` from pagefind. + * + * @see https://github.com/CloudCannon/pagefind/blob/v1.3.0/pagefind_web_js/lib/coupled_search.ts#L549 + */ + pagefindIndexOptionsSchema.extend({ + /** + * Set Pagefind’s `bundlePath` mergeIndex option. + * + * @see https://pagefind.app/docs/multisite/#searching-additional-sites-from-pagefind-ui + */ + bundlePath: z.string(), + }) + ) + .optional(), +}); + +export const PagefindConfigSchema = () => pagefindSchema; +export const PagefindConfigDefaults = () => pagefindSchema.parse({}); diff --git a/packages/starlight/schemas/sidebar.ts b/packages/starlight/schemas/sidebar.ts new file mode 100644 index 00000000000..b76bc80e961 --- /dev/null +++ b/packages/starlight/schemas/sidebar.ts @@ -0,0 +1,125 @@ +import type { AstroBuiltinAttributes } from 'astro'; +import type { HTMLAttributes } from 'astro/types'; +import { z } from 'astro/zod'; +import { I18nBadgeConfigSchema } from './badge'; +import { stripLeadingAndTrailingSlashes } from '../utils/path'; + +const SidebarBaseSchema = z.object({ + /** The visible label for this item in the sidebar. */ + label: z.string(), + /** Translations of the `label` for each supported language. */ + translations: z.record(z.string()).default({}), + /** Adds a badge to the item */ + badge: I18nBadgeConfigSchema(), +}); + +const SidebarGroupSchema = SidebarBaseSchema.extend({ + /** + * Explicitly prevent custom attributes on groups as the final type for supported sidebar item + * is a non-discriminated union where TypeScript will not perform excess property checks. + * This means that a user could define a sidebar group with custom attributes, not getting a + * TypeScript error, and only have it fail at runtime. + * @see https://github.com/microsoft/TypeScript/issues/20863 + */ + attrs: z.never().optional(), + /** Whether this item should be collapsed by default. */ + collapsed: z.boolean().default(false), +}); + +// HTML attributes that can be added to an anchor element, validated as +// `Record<string, string | number | boolean | undefined>` but typed as `HTMLAttributes<'a'>` +// for user convenience. +const linkHTMLAttributesSchema = z.record( + z.union([z.string(), z.number(), z.boolean(), z.undefined(), z.null()]) +) as z.Schema<Omit<HTMLAttributes<'a'>, keyof AstroBuiltinAttributes | 'children'>>; +export type LinkHTMLAttributes = z.infer<typeof linkHTMLAttributesSchema>; + +export const SidebarLinkItemHTMLAttributesSchema = () => linkHTMLAttributesSchema.default({}); + +const SidebarLinkItemSchema = SidebarBaseSchema.extend({ + /** The link to this item’s content. Can be a relative link to local files or the full URL of an external page. */ + link: z.string(), + /** HTML attributes to add to the link item. */ + attrs: SidebarLinkItemHTMLAttributesSchema(), +}).strict(); +export type SidebarLinkItem = z.infer<typeof SidebarLinkItemSchema>; + +const AutoSidebarGroupSchema = SidebarGroupSchema.extend({ + /** Enable autogenerating a sidebar category from a specific docs directory. */ + autogenerate: z.object({ + /** The directory to generate sidebar items for. */ + directory: z.string().transform(stripLeadingAndTrailingSlashes), + /** + * Whether the autogenerated subgroups should be collapsed by default. + * Defaults to the `AutoSidebarGroup` `collapsed` value. + */ + collapsed: z.boolean().optional(), + /** HTML attributes to add to the autogenerated link items. */ + attrs: SidebarLinkItemHTMLAttributesSchema(), + // TODO: not supported by Docusaurus but would be good to have + /** How many directories deep to include from this directory in the sidebar. Default: `Infinity`. */ + // depth: z.number().optional(), + }), +}).strict(); +export type AutoSidebarGroup = z.infer<typeof AutoSidebarGroupSchema>; + +type ManualSidebarGroupInput = z.input<typeof SidebarGroupSchema> & { + /** Array of links and subcategories to display in this category. */ + items: Array< + | z.input<typeof SidebarLinkItemSchema> + | z.input<typeof AutoSidebarGroupSchema> + | z.input<typeof InternalSidebarLinkItemSchema> + | z.input<typeof InternalSidebarLinkItemShorthandSchema> + | ManualSidebarGroupInput + >; +}; + +type ManualSidebarGroupOutput = z.output<typeof SidebarGroupSchema> & { + /** Array of links and subcategories to display in this category. */ + items: Array< + | z.output<typeof SidebarLinkItemSchema> + | z.output<typeof AutoSidebarGroupSchema> + | z.output<typeof InternalSidebarLinkItemSchema> + | z.output<typeof InternalSidebarLinkItemShorthandSchema> + | ManualSidebarGroupOutput + >; +}; + +const ManualSidebarGroupSchema: z.ZodType< + ManualSidebarGroupOutput, + z.ZodTypeDef, + ManualSidebarGroupInput +> = SidebarGroupSchema.extend({ + /** Array of links and subcategories to display in this category. */ + items: z.lazy(() => + z + .union([ + SidebarLinkItemSchema, + ManualSidebarGroupSchema, + AutoSidebarGroupSchema, + InternalSidebarLinkItemSchema, + InternalSidebarLinkItemShorthandSchema, + ]) + .array() + ), +}).strict(); + +const InternalSidebarLinkItemSchema = SidebarBaseSchema.partial({ label: true }).extend({ + /** The link to this item’s content. Must be a slug of a Content Collection entry. */ + slug: z.string(), + /** HTML attributes to add to the link item. */ + attrs: SidebarLinkItemHTMLAttributesSchema(), +}); +const InternalSidebarLinkItemShorthandSchema = z + .string() + .transform((slug) => InternalSidebarLinkItemSchema.parse({ slug })); +export type InternalSidebarLinkItem = z.output<typeof InternalSidebarLinkItemSchema>; + +export const SidebarItemSchema = z.union([ + SidebarLinkItemSchema, + ManualSidebarGroupSchema, + AutoSidebarGroupSchema, + InternalSidebarLinkItemSchema, + InternalSidebarLinkItemShorthandSchema, +]); +export type SidebarItem = z.infer<typeof SidebarItemSchema>; diff --git a/packages/starlight/schemas/site-title.ts b/packages/starlight/schemas/site-title.ts new file mode 100644 index 00000000000..ad5e62b6472 --- /dev/null +++ b/packages/starlight/schemas/site-title.ts @@ -0,0 +1,22 @@ +import { z } from 'astro/zod'; + +export const TitleConfigSchema = () => + z + .union([z.string(), z.record(z.string())]) + .describe('Title for your website. Will be used in metadata and as browser tab title.'); + +// transform the title for runtime use +export const TitleTransformConfigSchema = (defaultLang: string) => + TitleConfigSchema().transform((title, ctx) => { + if (typeof title === 'string') { + return { [defaultLang]: title }; + } + if (!title[defaultLang] && title[defaultLang] !== '') { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Title must have a key for the default language "${defaultLang}"`, + }); + return z.NEVER; + } + return title; + }); diff --git a/packages/starlight/schemas/social.ts b/packages/starlight/schemas/social.ts new file mode 100644 index 00000000000..f2129fe5672 --- /dev/null +++ b/packages/starlight/schemas/social.ts @@ -0,0 +1,22 @@ +import { z } from 'astro/zod'; +import { IconSchema } from './icon'; + +const LinksSchema = z + .object({ icon: IconSchema(), label: z.string().min(1), href: z.string() }) + .array() + .optional(); + +export const SocialLinksSchema = () => + // Add a more specific error message to help people migrate from the old object syntax. + // TODO: remove once most people have updated to v0.33 or higher (e.g. when releasing Starlight v1) + z.preprocess((value, ctx) => { + if (value && typeof value === 'object' && !Array.isArray(value)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + 'Starlight v0.33.0 changed the `social` configuration syntax. Please specify an array of link items instead of an object.\n' + + 'See the Starlight changelog for details: https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md#0330\n', + }); + } + return value; + }, LinksSchema) as unknown as typeof LinksSchema; diff --git a/packages/starlight/style/anchor-links.css b/packages/starlight/style/anchor-links.css new file mode 100644 index 00000000000..193d3f717e0 --- /dev/null +++ b/packages/starlight/style/anchor-links.css @@ -0,0 +1,131 @@ +/* +How does anchor link placement work? + +Because anchor links need to placed inline at the end of a heading, but are not children of the +heading element itself, positioning them to behave in a desirable way is a tiny bit tricky. Here’s +how we do it. + +1. We wrap the heading and anchor link in a div and make the heading element inline: + <div class="sl-heading-wrapper"> + <h2>...</h2><a class="sl-anchor-link">...</a> + </a> + +2. We need to avoid the anchor link wrapping onto a new line by itself like this because it looks + broken: + + Some heading text + ⛓ + +3. To achieve this we add an area of padding to the end of the heading and move the link over this + padding using negative margin: + + padding-inline-end creates space at the end of the line + ↓ + Some heading text[ ]⛓ + + margin-inline-start then pulls the anchor link into that space + ↓ + Some heading text[ ⛓ ] + + This ensures that when the anchor link wraps, the final word in the heading will wrap with it. + +*/ +@layer starlight.content { + /* ====================================================== + WRAPPER + ====================================================== */ + .sl-markdown-content .sl-heading-wrapper { + /* The size of the SVG icon. */ + --sl-anchor-icon-size: 0.8275em; + /* The horizontal space between the SVG icon and the end of the heading text. */ + --sl-anchor-icon-gap: 0.25em; + /* The end of line space required to accommodate the anchor link. */ + --sl-anchor-icon-space: calc(var(--sl-anchor-icon-size) + var(--sl-anchor-icon-gap)); + + line-height: var(--sl-line-height-headings); + } + + /* We need to apply the same rule we use for heading spacing to the parent wrapper. */ + .sl-markdown-content + :not(h1, h2, h3, h4, h5, h6, .sl-heading-wrapper) + + :is(.sl-heading-wrapper) { + margin-top: 1.5em; + } + + /* These font sizes are set in `markdown.css` for heading elements, but we need them one level higher on the wrapper. */ + .sl-markdown-content .sl-heading-wrapper.level-h1 { + font-size: var(--sl-text-h1); + } + .sl-markdown-content .sl-heading-wrapper.level-h2 { + font-size: var(--sl-text-h2); + } + .sl-markdown-content .sl-heading-wrapper.level-h3 { + font-size: var(--sl-text-h3); + } + .sl-markdown-content .sl-heading-wrapper.level-h4 { + font-size: var(--sl-text-h4); + } + .sl-markdown-content .sl-heading-wrapper.level-h5 { + font-size: var(--sl-text-h5); + } + .sl-markdown-content .sl-heading-wrapper.level-h6 { + font-size: var(--sl-text-h6); + } + + /* ====================================================== + HEADING + ====================================================== */ + .sl-markdown-content .sl-heading-wrapper > :first-child { + display: inline; + /* Apply end-of-line padding to the heading element. */ + padding-inline-end: var(--sl-anchor-icon-space); + } + + /* ====================================================== + LINK + ====================================================== */ + .sl-markdown-content .sl-anchor-link { + position: relative; + /* Move the anchor link over the heading element’s end-of-line padding. */ + margin-inline-start: calc(-1 * var(--sl-anchor-icon-size)); + /* Prevent double or triple clicks from potentially selecting the anchor link a11y text. */ + -webkit-user-select: none; + user-select: none; + /* Prevent double clicks on the last word (or single word) of a heading to include an extra new + line in Chrome and Safari. */ + display: inline-flex; + } + + /* Increase clickable area for anchor links with a pseudo element that doesn’t impact layout. */ + .sl-markdown-content .sl-anchor-link::after { + content: ''; + position: absolute; + /* While most icon spacing is done with `em` to be relative to the heading font-size, increasing + the touch area is most important for smaller headings like h5/h6, so we use absolute units, + which have a diminishing impact at larger font-sizes. */ + inset: -0.25rem -0.5rem; + } + + /* Size and position the SVG icon inside the link. */ + .sl-markdown-content .sl-anchor-icon > svg { + display: inline; + width: var(--sl-anchor-icon-size); + /* Center the link icon SVG vertically in the line. */ + vertical-align: top; + transform: translateY( + calc((var(--sl-line-height-headings) * 1em - var(--sl-anchor-icon-size)) / 2) + ); + } + + /* On devices with hover capability, hide the anchor link icons and show only show them when focused + or when the heading is hovered. */ + @media (hover: hover) { + .sl-markdown-content .sl-anchor-link { + opacity: 0; + } + .sl-markdown-content .sl-anchor-link:focus, + .sl-markdown-content .sl-heading-wrapper:hover .sl-anchor-link { + opacity: 1; + } + } +} diff --git a/packages/starlight/style/asides.css b/packages/starlight/style/asides.css index 026544d4909..5bcdcd1690c 100644 --- a/packages/starlight/style/asides.css +++ b/packages/starlight/style/asides.css @@ -1,49 +1,51 @@ -.starlight-aside { - padding: 1rem; - border-inline-start: 0.25rem solid; - color: var(--sl-color-white); -} -.starlight-aside--note { - --sl-color-asides-text-accent: var(--sl-color-blue-high); - border-color: var(--sl-color-blue); - background-color: var(--sl-color-blue-low); -} -.starlight-aside--tip { - --sl-color-asides-text-accent: var(--sl-color-purple-high); - border-color: var(--sl-color-purple); - background-color: var(--sl-color-purple-low); -} -.starlight-aside--caution { - --sl-color-asides-text-accent: var(--sl-color-orange-high); - border-color: var(--sl-color-orange); - background-color: var(--sl-color-orange-low); -} -.starlight-aside--danger { - --sl-color-asides-text-accent: var(--sl-color-red-high); - border-color: var(--sl-color-red); - background-color: var(--sl-color-red-low); -} +@layer starlight.components { + .starlight-aside { + padding: 1rem; + border-inline-start: 0.25rem solid var(--sl-color-asides-border); + color: var(--sl-color-white); + } + .starlight-aside--note { + --sl-color-asides-text-accent: var(--sl-color-blue-high); + --sl-color-asides-border: var(--sl-color-blue); + background-color: var(--sl-color-blue-low); + } + .starlight-aside--tip { + --sl-color-asides-text-accent: var(--sl-color-purple-high); + --sl-color-asides-border: var(--sl-color-purple); + background-color: var(--sl-color-purple-low); + } + .starlight-aside--caution { + --sl-color-asides-text-accent: var(--sl-color-orange-high); + --sl-color-asides-border: var(--sl-color-orange); + background-color: var(--sl-color-orange-low); + } + .starlight-aside--danger { + --sl-color-asides-text-accent: var(--sl-color-red-high); + --sl-color-asides-border: var(--sl-color-red); + background-color: var(--sl-color-red-low); + } -.starlight-aside__title { - display: flex; - gap: 0.5rem; - align-items: center; - font-size: var(--sl-text-h5); - font-weight: 600; - line-height: var(--sl-line-height-headings); - color: var(--sl-color-asides-text-accent); -} + .starlight-aside__title { + display: flex; + gap: 0.5rem; + align-items: center; + font-size: var(--sl-text-h5); + font-weight: 600; + line-height: var(--sl-line-height-headings); + color: var(--sl-color-asides-text-accent); + } -.starlight-aside__icon { - font-size: 1.333em; - width: 1em; - height: 1em; -} + .starlight-aside__icon { + font-size: 1.333em; + width: 1em; + height: 1em; + } -.starlight-aside__title + .starlight-aside__content { - margin-top: 0.5rem; -} + .starlight-aside__title + .starlight-aside__content { + margin-top: 0.5rem; + } -.starlight-aside__content a { - color: var(--sl-color-asides-text-accent); + .starlight-aside__content a { + color: var(--sl-color-asides-text-accent); + } } diff --git a/packages/starlight/style/layers.css b/packages/starlight/style/layers.css new file mode 100644 index 00000000000..0ecdb8d0b44 --- /dev/null +++ b/packages/starlight/style/layers.css @@ -0,0 +1 @@ +@layer starlight.base, starlight.reset, starlight.core, starlight.content, starlight.components, starlight.utils; diff --git a/packages/starlight/style/markdown.css b/packages/starlight/style/markdown.css new file mode 100644 index 00000000000..72831da1ee7 --- /dev/null +++ b/packages/starlight/style/markdown.css @@ -0,0 +1,253 @@ +@layer starlight.content { + .sl-markdown-content + :not(a, strong, em, del, span, input, code, br) + + :not(a, strong, em, del, span, input, code, br, :where(.not-content *)) { + margin-top: var(--sl-content-gap-y); + } + + /* Vertical spacing between Markdown content blocks and UI Framework components using client directives. */ + .sl-markdown-content + :not(a, strong, em, del, span, input, code, br) + + :is(astro-island, astro-slot) + > :not(a, strong, em, del, span, input, code, br, :where(.not-content *)):first-child { + margin-top: var(--sl-content-gap-y); + } + + /* Headings after non-headings have more spacing. */ + .sl-markdown-content + :not(h1, h2, h3, h4, h5, h6) + + :is(h1, h2, h3, h4, h5, h6):not(:where(.not-content *)) { + margin-top: 1.5em; + } + + .sl-markdown-content li + li:not(:where(.not-content *)), + .sl-markdown-content dt + dt:not(:where(.not-content *)), + .sl-markdown-content dt + dd:not(:where(.not-content *)), + .sl-markdown-content dd + dd:not(:where(.not-content *)) { + margin-top: 0.25rem; + } + + .sl-markdown-content li:not(:where(.not-content *)) { + overflow-wrap: anywhere; + } + + .sl-markdown-content + li + > :is( + :last-child:not( + li, + ul, + ol, + a, + strong, + em, + del, + span, + input, + code, + br, + script, + :where(.not-content *) + ), + /** + * For list items ending with 1 or multiple script elements (`:has(~ script:last-child)`), we + * need to style the last non-script element (`:not(script)`) that doesn't have a subsequent + * sibling that is not a script (`:not(:has(~ :not(script)))`). + */ + :not(script):has(~ script:last-child):not(:has(~ :not(script))) + ) { + margin-bottom: 1.25rem; + } + + .sl-markdown-content dt:not(:where(.not-content *)) { + font-weight: 700; + } + .sl-markdown-content dd:not(:where(.not-content *)) { + padding-inline-start: 1rem; + } + + .sl-markdown-content :is(h1, h2, h3, h4, h5, h6):not(:where(.not-content *)) { + color: var(--sl-color-white); + line-height: var(--sl-line-height-headings); + font-weight: 600; + } + + .sl-markdown-content :is(img, picture, video, canvas, svg, iframe):not(:where(.not-content *)) { + display: block; + max-width: 100%; + height: auto; + } + + .sl-markdown-content h1:not(:where(.not-content *)) { + font-size: var(--sl-text-h1); + } + .sl-markdown-content h2:not(:where(.not-content *)) { + font-size: var(--sl-text-h2); + } + .sl-markdown-content h3:not(:where(.not-content *)) { + font-size: var(--sl-text-h3); + } + .sl-markdown-content h4:not(:where(.not-content *)) { + font-size: var(--sl-text-h4); + } + .sl-markdown-content h5:not(:where(.not-content *)) { + font-size: var(--sl-text-h5); + } + .sl-markdown-content h6:not(:where(.not-content *)) { + font-size: var(--sl-text-h6); + } + + .sl-markdown-content a:not(:where(.not-content *)) { + color: var(--sl-color-text-accent); + } + .sl-markdown-content a:hover:not(:where(.not-content *)) { + color: var(--sl-color-white); + } + + .sl-markdown-content code:not(:where(.not-content *)) { + background-color: var(--sl-color-bg-inline-code); + margin-block: -0.125rem; + padding: 0.125rem 0.375rem; + font-size: var(--sl-text-code-sm); + } + .sl-markdown-content :is(h1, h2, h3, h4, h5, h6) code { + font-size: inherit; + } + + .sl-markdown-content pre:not(:where(.not-content *)) { + border: 1px solid var(--sl-color-gray-5); + padding: 0.75rem 1rem; + font-size: var(--sl-text-code); + tab-size: 2; + } + + .sl-markdown-content pre code:not(:where(.not-content *)) { + all: unset; + font-family: var(--__sl-font-mono); + } + + .sl-markdown-content blockquote:not(:where(.not-content *)) { + border-inline-start: 1px solid var(--sl-color-gray-5); + padding-inline-start: 1rem; + } + + /* Table styling */ + .sl-markdown-content table:not(:where(.not-content *)) { + display: block; + overflow: auto; + border-spacing: 0; + } + .sl-markdown-content :is(th, td):not(:where(.not-content *)) { + border-bottom: 1px solid var(--sl-color-gray-5); + padding: 0.5rem 1rem; + /* Align text to the top of the row in multiline tables. */ + vertical-align: baseline; + } + .sl-markdown-content :is(th:first-child, td:first-child):not(:where(.not-content *)) { + padding-inline-start: 0; + } + .sl-markdown-content :is(th:last-child, td:last-child):not(:where(.not-content *)) { + padding-inline-end: 0; + } + .sl-markdown-content th:not(:where(.not-content *)) { + color: var(--sl-color-white); + font-weight: 600; + } + /* Align headings to the start of the line unless set by the `align` attribute. */ + .sl-markdown-content th:not([align]):not(:where(.not-content *)) { + text-align: start; + } + /* <table>s, <hr>s, and <blockquote>s inside asides */ + .sl-markdown-content .starlight-aside :is(th, td, hr, blockquote):not(:where(.not-content *)) { + border-color: var(--sl-color-gray-4); + } + @supports ( + border-color: color-mix(in srgb, var(--sl-color-asides-text-accent) 30%, transparent) + ) { + .sl-markdown-content .starlight-aside :is(th, td, hr, blockquote):not(:where(.not-content *)) { + border-color: color-mix(in srgb, var(--sl-color-asides-text-accent) 30%, transparent); + } + } + + /* <code> inside asides */ + @supports ( + border-color: color-mix(in srgb, var(--sl-color-asides-text-accent) 12%, transparent) + ) { + .sl-markdown-content .starlight-aside code:not(:where(.not-content *)) { + background-color: color-mix(in srgb, var(--sl-color-asides-text-accent) 12%, transparent); + } + } + + .sl-markdown-content hr:not(:where(.not-content *)) { + border: 0; + border-bottom: 1px solid var(--sl-color-hairline); + } + + /* <details> and <summary> styles */ + .sl-markdown-content details:not(:where(.not-content *)) { + --sl-details-border-color: var(--sl-color-gray-5); + --sl-details-border-color--hover: var(--sl-color-text-accent); + + border-inline-start: 2px solid var(--sl-details-border-color); + padding-inline-start: 1rem; + } + .sl-markdown-content details:not([open]):hover:not(:where(.not-content *)), + .sl-markdown-content details:has(> summary:hover):not(:where(.not-content *)) { + border-color: var(--sl-details-border-color--hover); + } + .sl-markdown-content summary:not(:where(.not-content *)) { + color: var(--sl-color-white); + cursor: pointer; + display: block; /* Needed to hide the default marker in some browsers. */ + font-weight: 600; + /* Expand the outline so that the marker cannot distort it. */ + margin-inline-start: -0.5rem; + padding-inline-start: 0.5rem; + } + .sl-markdown-content details[open] > summary:not(:where(.not-content *)) { + margin-bottom: 1rem; + } + + /* <summary> marker styles */ + .sl-markdown-content summary:not(:where(.not-content *))::marker, + .sl-markdown-content summary:not(:where(.not-content *))::-webkit-details-marker { + display: none; + } + .sl-markdown-content summary:not(:where(.not-content *))::before { + --sl-details-marker-size: 1.25rem; + + background-color: currentColor; + content: ''; + display: inline-block; + height: var(--sl-details-marker-size); + width: var(--sl-details-marker-size); + margin-inline: calc((var(--sl-details-marker-size) / 4) * -1) 0.25rem; + vertical-align: middle; + -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M14.8 11.3 10.6 7a1 1 0 1 0-1.4 1.5l3.5 3.5-3.5 3.5a1 1 0 0 0 0 1.4 1 1 0 0 0 .7.3 1 1 0 0 0 .7-.3l4.2-4.2a1 1 0 0 0 0-1.4Z'/%3E%3C/svg%3E%0A"); + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M14.8 11.3 10.6 7a1 1 0 1 0-1.4 1.5l3.5 3.5-3.5 3.5a1 1 0 0 0 0 1.4 1 1 0 0 0 .7.3 1 1 0 0 0 .7-.3l4.2-4.2a1 1 0 0 0 0-1.4Z'/%3E%3C/svg%3E%0A"); + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + } + @media (prefers-reduced-motion: no-preference) { + .sl-markdown-content summary:not(:where(.not-content *))::before { + transition: transform 0.2s ease-in-out; + } + } + .sl-markdown-content details[open] > summary:not(:where(.not-content *))::before { + transform: rotateZ(90deg); + } + [dir='rtl'] .sl-markdown-content summary:not(:where(.not-content *))::before, + .sl-markdown-content [dir='rtl'] summary:not(:where(.not-content *))::before { + transform: rotateZ(180deg); + } + /* <summary> with only a paragraph automatically added when using MDX */ + .sl-markdown-content summary:not(:where(.not-content *)) p:only-child { + display: inline; + } + + /* <details> styles inside asides */ + .sl-markdown-content .starlight-aside details:not(:where(.not-content *)) { + --sl-details-border-color: var(--sl-color-asides-border); + --sl-details-border-color--hover: var(--sl-color-asides-text-accent); + } +} diff --git a/packages/starlight/style/print.css b/packages/starlight/style/print.css new file mode 100644 index 00000000000..6a3ce488865 --- /dev/null +++ b/packages/starlight/style/print.css @@ -0,0 +1,175 @@ +@media print { + :root { + /* Colours — force light mode when printing */ + --sl-color-white: hsl(224, 10%, 10%); + --sl-color-gray-1: hsl(224, 14%, 16%); + --sl-color-gray-2: hsl(224, 10%, 23%); + --sl-color-gray-3: hsl(224, 7%, 36%); + --sl-color-gray-4: hsl(224, 6%, 56%); + --sl-color-gray-5: hsl(224, 6%, 77%); + --sl-color-gray-6: hsl(224, 20%, 94%); + --sl-color-gray-7: hsl(224, 19%, 97%); + --sl-color-black: hsl(0, 0%, 100%); + + --sl-color-orange-high: hsl(var(--sl-hue-orange), 80%, 25%); + --sl-color-orange: hsl(var(--sl-hue-orange), 90%, 60%); + --sl-color-orange-low: hsl(var(--sl-hue-orange), 90%, 88%); + --sl-color-green-high: hsl(var(--sl-hue-green), 80%, 22%); + --sl-color-green: hsl(var(--sl-hue-green), 90%, 46%); + --sl-color-green-low: hsl(var(--sl-hue-green), 85%, 90%); + --sl-color-blue-high: hsl(var(--sl-hue-blue), 80%, 30%); + --sl-color-blue: hsl(var(--sl-hue-blue), 90%, 60%); + --sl-color-blue-low: hsl(var(--sl-hue-blue), 88%, 90%); + --sl-color-purple-high: hsl(var(--sl-hue-purple), 90%, 30%); + --sl-color-purple: hsl(var(--sl-hue-purple), 90%, 60%); + --sl-color-purple-low: hsl(var(--sl-hue-purple), 80%, 90%); + --sl-color-red-high: hsl(var(--sl-hue-red), 80%, 30%); + --sl-color-red: hsl(var(--sl-hue-red), 90%, 60%); + --sl-color-red-low: hsl(var(--sl-hue-red), 80%, 90%); + + --sl-color-accent-high: hsl(234, 80%, 30%); + --sl-color-accent: hsl(234, 90%, 60%); + --sl-color-accent-low: hsl(234, 88%, 90%); + + --sl-color-text-accent: var(--sl-color-accent); + --sl-color-text-invert: var(--sl-color-black); + --sl-color-bg-nav: var(--sl-color-gray-7); + --sl-color-bg-sidebar: var(--sl-color-bg); + --sl-color-bg-inline-code: var(--sl-color-gray-6); + --sl-color-bg-accent: var(--sl-color-accent); + --sl-color-hairline-light: var(--sl-color-gray-6); + --sl-color-hairline-shade: var(--sl-color-gray-6); + + --sl-color-backdrop-overlay: hsla(225, 9%, 36%, 0.66); + + /* Disable shadows when printing. */ + --sl-shadow-sm: none; + --sl-shadow-md: none; + --sl-shadow-lg: none; + } + + /* Utility classes for controlling element visibility when printing. */ + .print\:hidden { + display: none; + } + .print\:flex { + display: flex; + } + .print\:block { + display: block; + } + + /* Page layout tweaks. */ + main { + padding-bottom: 0; + } + main > .content-panel { + padding-block-start: 0; + } + .content-panel + .content-panel { + border: 0; + } + /* components/PageFrame.astro */ + .page > header { + position: relative; + } + .page > .main-frame { + padding-top: 0; + padding-inline-start: 0; + } + /* components/TwoColumnContent.astro */ + .main-pane { + --sl-sidebar-width: 0px; + --sl-content-width: 100%; + } + /* components/Banner.astro */ + .sl-banner { + --sl-color-banner-text: var(--sl-color-white); + background-color: transparent; + } + + /* components/MarkdownContent.astro */ + .sl-markdown-content :is(h1, h2, h3, h4, h5, h6) { + break-after: avoid; + } + .sl-markdown-content :is(p, li) { + orphans: 2; + widows: 2; + } + .sl-markdown-content pre { + overflow-x: hidden; + white-space: pre-wrap; + } + .sl-markdown-content .expressive-code, + .sl-markdown-content figure, + .sl-markdown-content pre { + break-inside: avoid; + } + .expressive-code .frame.is-terminal .header::before { + /* Ensure terminal frame dots are visible even if backgrounds are disabled. */ + box-shadow: inset 99rem 99rem var(--sl-color-gray-5); + } + .expressive-code .frame.has-title:not(.is-terminal) .header { + /* Divide title bar and code without relying on background colors. */ + background: transparent; + border-bottom: 1px solid var(--sl-color-gray-6); + } + .expressive-code .frame.has-title:not(.is-terminal) .title { + /* Hide title tab background color. */ + background: transparent; + } + .expressive-code .frame.has-title:not(.is-terminal) .title::after { + /* Remove title tab highlight. */ + border-top: 0; + } + .expressive-code .copy { + /* Ensure Expressive Code copy button is hidden when printing from touch devices. */ + display: none; + } + /* Inline code */ + .sl-markdown-content code:not(:where(.not-content *)) { + background-color: transparent; + padding: 0; + margin-block: unset; + font-size: 0.9375em; + } + + /* user-components/Badge.astro */ + .sl-badge { + background: transparent; + color: var(--sl-color-white); + } + + /* user-components/FileTree.astro */ + starlight-file-tree { + break-inside: avoid; + } + starlight-file-tree .highlight { + outline: 3px solid var(--sl-color-accent-low); + color: var(--sl-color-text); + background-color: transparent; + } + + /* user-components/Aside.astro */ + .starlight-aside { + break-inside: avoid; + } + + /* user-components/LinkButton.astro */ + .sl-link-button.primary { + background: transparent; + border-color: var(--sl-color-white); + color: var(--sl-color-white); + } + + /* user-components/Tabs.astro */ + starlight-tabs { + break-inside: avoid; + } + + /* user-components/Steps.astro */ + .sl-steps > li::after { + /* Ensure steps guidelines are visible when background colors are disabled. */ + box-shadow: inset 99rem 99rem var(--sl-color-hairline-light); + } +} diff --git a/packages/starlight/style/props.css b/packages/starlight/style/props.css index 421abc17364..7e412686aa1 100644 --- a/packages/starlight/style/props.css +++ b/packages/starlight/style/props.css @@ -1,183 +1,188 @@ -:root, -::backdrop { - /* Colors (dark mode) */ - --sl-color-white: hsl(0, 0%, 100%); /* “white” */ - --sl-color-gray-1: hsl(224, 20%, 94%); - --sl-color-gray-2: hsl(224, 6%, 77%); - --sl-color-gray-3: hsl(224, 6%, 56%); - --sl-color-gray-4: hsl(224, 7%, 36%); - --sl-color-gray-5: hsl(224, 10%, 23%); - --sl-color-gray-6: hsl(224, 14%, 16%); - --sl-color-black: hsl(224, 10%, 10%); - - --sl-hue-orange: 41; - --sl-color-orange-low: hsl(var(--sl-hue-orange), 39%, 22%); - --sl-color-orange: hsl(var(--sl-hue-orange), 82%, 63%); - --sl-color-orange-high: hsl(var(--sl-hue-orange), 82%, 87%); - --sl-hue-green: 101; - --sl-color-green-low: hsl(var(--sl-hue-green), 39%, 22%); - --sl-color-green: hsl(var(--sl-hue-green), 82%, 63%); - --sl-color-green-high: hsl(var(--sl-hue-green), 82%, 80%); - --sl-hue-blue: 234; - --sl-color-blue-low: hsl(var(--sl-hue-blue), 54%, 20%); - --sl-color-blue: hsl(var(--sl-hue-blue), 100%, 60%); - --sl-color-blue-high: hsl(var(--sl-hue-blue), 100%, 87%); - --sl-hue-purple: 281; - --sl-color-purple-low: hsl(var(--sl-hue-purple), 39%, 22%); - --sl-color-purple: hsl(var(--sl-hue-purple), 82%, 63%); - --sl-color-purple-high: hsl(var(--sl-hue-purple), 82%, 89%); - --sl-hue-red: 339; - --sl-color-red-low: hsl(var(--sl-hue-red), 39%, 22%); - --sl-color-red: hsl(var(--sl-hue-red), 82%, 63%); - --sl-color-red-high: hsl(var(--sl-hue-red), 82%, 87%); - - --sl-color-accent-low: hsl(224, 54%, 20%); - --sl-color-accent: hsl(224, 100%, 60%); - --sl-color-accent-high: hsl(224, 100%, 85%); - - --sl-color-text: var(--sl-color-gray-2); - --sl-color-text-accent: var(--sl-color-accent-high); - --sl-color-text-invert: var(--sl-color-accent-low); - --sl-color-bg: var(--sl-color-black); - --sl-color-bg-nav: var(--sl-color-gray-6); - --sl-color-bg-sidebar: var(--sl-color-gray-6); - --sl-color-bg-inline-code: var(--sl-color-gray-5); - --sl-color-bg-accent: var(--sl-color-accent-high); - --sl-color-hairline-light: var(--sl-color-gray-5); - --sl-color-hairline: var(--sl-color-gray-6); - --sl-color-hairline-shade: var(--sl-color-black); - - --sl-color-backdrop-overlay: hsla(223, 13%, 10%, 0.66); - - /* Shadows (dark mode) */ - --sl-shadow-sm: 0px 1px 1px hsla(0, 0%, 0%, 0.12), 0px 2px 1px hsla(0, 0%, 0%, 0.24); - --sl-shadow-md: 0px 8px 4px hsla(0, 0%, 0%, 0.08), 0px 5px 2px hsla(0, 0%, 0%, 0.08), - 0px 3px 2px hsla(0, 0%, 0%, 0.12), 0px 1px 1px hsla(0, 0%, 0%, 0.15); - --sl-shadow-lg: 0px 25px 7px hsla(0, 0%, 0%, 0.03), 0px 16px 6px hsla(0, 0%, 0%, 0.1), - 0px 9px 5px hsla(223, 13%, 10%, 0.33), 0px 4px 4px hsla(0, 0%, 0%, 0.75), - 0px 4px 2px hsla(0, 0%, 0%, 0.25); - - /* Text size and line height */ - --sl-text-xs: 0.8125rem; /* 13px */ - --sl-text-sm: 0.875rem; /* 14px */ - --sl-text-base: 1rem; /* 16px */ - --sl-text-lg: 1.125rem; /* 18px */ - --sl-text-xl: 1.25rem; /* 20px */ - --sl-text-2xl: 1.5rem; /* 24px */ - --sl-text-3xl: 1.8125rem; /* 29px */ - --sl-text-4xl: 2.1875rem; /* 35px */ - --sl-text-5xl: 2.625rem; /* 42px */ - --sl-text-6xl: 4rem; /* 64px */ - - --sl-text-body: var(--sl-text-base); - --sl-text-body-sm: var(--sl-text-xs); - --sl-text-code: var(--sl-text-sm); - --sl-text-code-sm: var(--sl-text-xs); - --sl-text-h1: var(--sl-text-4xl); - --sl-text-h2: var(--sl-text-3xl); - --sl-text-h3: var(--sl-text-2xl); - --sl-text-h4: var(--sl-text-xl); - --sl-text-h5: var(--sl-text-lg); - - --sl-line-height: 1.8; - --sl-line-height-headings: 1.2; - - --sl-font-system: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, - 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', - 'Segoe UI Symbol', 'Noto Color Emoji'; - --sl-font-system-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', - 'Courier New', monospace; - --__sl-font: var(--sl-font, ''), var(--sl-font-system); - --__sl-font-mono: var(--sl-font-mono, ''), var(--sl-font-system-mono); - - /** Key layout values */ - --sl-nav-height: 3.5rem; - --sl-nav-pad-x: 1rem; - --sl-nav-pad-y: 0.75rem; - --sl-mobile-toc-height: 3rem; - --sl-sidebar-width: 18.75rem; - --sl-sidebar-pad-x: 1rem; - --sl-content-width: 45rem; - --sl-content-pad-x: 1rem; - --sl-menu-button-size: 2rem; - --sl-nav-gap: var(--sl-content-pad-x); - /* Offset required to show outline inside an element instead of round the outside */ - --sl-outline-offset-inside: -0.1875rem; - - /* Global z-index values */ - --sl-z-index-toc: 4; - --sl-z-index-menu: 5; - --sl-z-index-navbar: 10; - --sl-z-index-skiplink: 20; -} +@layer starlight.base { + :root, + ::backdrop { + /* Colors (dark mode) */ + --sl-color-white: hsl(0, 0%, 100%); /* “white” */ + --sl-color-gray-1: hsl(224, 20%, 94%); + --sl-color-gray-2: hsl(224, 6%, 77%); + --sl-color-gray-3: hsl(224, 6%, 56%); + --sl-color-gray-4: hsl(224, 7%, 36%); + --sl-color-gray-5: hsl(224, 10%, 23%); + --sl-color-gray-6: hsl(224, 14%, 16%); + --sl-color-black: hsl(224, 10%, 10%); + + --sl-hue-orange: 41; + --sl-color-orange-low: hsl(var(--sl-hue-orange), 39%, 22%); + --sl-color-orange: hsl(var(--sl-hue-orange), 82%, 63%); + --sl-color-orange-high: hsl(var(--sl-hue-orange), 82%, 87%); + --sl-hue-green: 101; + --sl-color-green-low: hsl(var(--sl-hue-green), 39%, 22%); + --sl-color-green: hsl(var(--sl-hue-green), 82%, 63%); + --sl-color-green-high: hsl(var(--sl-hue-green), 82%, 80%); + --sl-hue-blue: 234; + --sl-color-blue-low: hsl(var(--sl-hue-blue), 54%, 20%); + --sl-color-blue: hsl(var(--sl-hue-blue), 100%, 60%); + --sl-color-blue-high: hsl(var(--sl-hue-blue), 100%, 87%); + --sl-hue-purple: 281; + --sl-color-purple-low: hsl(var(--sl-hue-purple), 39%, 22%); + --sl-color-purple: hsl(var(--sl-hue-purple), 82%, 63%); + --sl-color-purple-high: hsl(var(--sl-hue-purple), 82%, 89%); + --sl-hue-red: 339; + --sl-color-red-low: hsl(var(--sl-hue-red), 39%, 22%); + --sl-color-red: hsl(var(--sl-hue-red), 82%, 63%); + --sl-color-red-high: hsl(var(--sl-hue-red), 82%, 87%); + + --sl-color-accent-low: hsl(224, 54%, 20%); + --sl-color-accent: hsl(224, 100%, 60%); + --sl-color-accent-high: hsl(224, 100%, 85%); + + --sl-color-text: var(--sl-color-gray-2); + --sl-color-text-accent: var(--sl-color-accent-high); + --sl-color-text-invert: var(--sl-color-accent-low); + --sl-color-bg: var(--sl-color-black); + --sl-color-bg-nav: var(--sl-color-gray-6); + --sl-color-bg-sidebar: var(--sl-color-gray-6); + --sl-color-bg-inline-code: var(--sl-color-gray-5); + --sl-color-bg-accent: var(--sl-color-accent-high); + --sl-color-hairline-light: var(--sl-color-gray-5); + --sl-color-hairline: var(--sl-color-gray-6); + --sl-color-hairline-shade: var(--sl-color-black); + + --sl-color-backdrop-overlay: hsla(223, 13%, 10%, 0.66); + + /* Shadows (dark mode) */ + --sl-shadow-sm: 0px 1px 1px hsla(0, 0%, 0%, 0.12), 0px 2px 1px hsla(0, 0%, 0%, 0.24); + --sl-shadow-md: 0px 8px 4px hsla(0, 0%, 0%, 0.08), 0px 5px 2px hsla(0, 0%, 0%, 0.08), + 0px 3px 2px hsla(0, 0%, 0%, 0.12), 0px 1px 1px hsla(0, 0%, 0%, 0.15); + --sl-shadow-lg: 0px 25px 7px hsla(0, 0%, 0%, 0.03), 0px 16px 6px hsla(0, 0%, 0%, 0.1), + 0px 9px 5px hsla(223, 13%, 10%, 0.33), 0px 4px 4px hsla(0, 0%, 0%, 0.75), + 0px 4px 2px hsla(0, 0%, 0%, 0.25); + + /* Text size and line height */ + --sl-text-2xs: 0.75rem; /* 12px */ + --sl-text-xs: 0.8125rem; /* 13px */ + --sl-text-sm: 0.875rem; /* 14px */ + --sl-text-base: 1rem; /* 16px */ + --sl-text-lg: 1.125rem; /* 18px */ + --sl-text-xl: 1.25rem; /* 20px */ + --sl-text-2xl: 1.5rem; /* 24px */ + --sl-text-3xl: 1.8125rem; /* 29px */ + --sl-text-4xl: 2.1875rem; /* 35px */ + --sl-text-5xl: 2.625rem; /* 42px */ + --sl-text-6xl: 4rem; /* 64px */ + + --sl-text-body: var(--sl-text-base); + --sl-text-body-sm: var(--sl-text-xs); + --sl-text-code: var(--sl-text-sm); + --sl-text-code-sm: var(--sl-text-xs); + --sl-text-h1: var(--sl-text-4xl); + --sl-text-h2: var(--sl-text-3xl); + --sl-text-h3: var(--sl-text-2xl); + --sl-text-h4: var(--sl-text-xl); + --sl-text-h5: var(--sl-text-lg); + + --sl-line-height: 1.75; + --sl-line-height-headings: 1.2; + + --sl-font-system: ui-sans-serif, system-ui, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, + 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', + 'Noto Color Emoji'; + --sl-font-system-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', + 'Courier New', monospace; + --__sl-font: var(--sl-font, var(--sl-font-system)), var(--sl-font-system); + --__sl-font-mono: var(--sl-font-mono, var(--sl-font-system-mono)), var(--sl-font-system-mono); + + /** Key layout values */ + --sl-nav-height: 3.5rem; + --sl-nav-pad-x: 1rem; + --sl-nav-pad-y: 0.75rem; + --sl-mobile-toc-height: 3rem; + --sl-sidebar-width: 18.75rem; + --sl-sidebar-pad-x: 1rem; + --sl-content-width: 45rem; + --sl-content-pad-x: 1rem; + --sl-content-gap-y: 1rem; + --sl-main-pad: 0 0 3vh 0; + --sl-menu-button-size: 2rem; + --sl-nav-gap: var(--sl-content-pad-x); + /* Offset required to show outline inside an element instead of round the outside */ + --sl-outline-offset-inside: -0.1875rem; + + /* Global z-index values */ + --sl-z-index-toc: 4; + --sl-z-index-menu: 5; + --sl-z-index-navbar: 10; + --sl-z-index-skiplink: 20; + } -:root[data-theme='light'], -[data-theme='light'] ::backdrop { - /* Colours (light mode) */ - --sl-color-white: hsl(224, 10%, 10%); - --sl-color-gray-1: hsl(224, 14%, 16%); - --sl-color-gray-2: hsl(224, 10%, 23%); - --sl-color-gray-3: hsl(224, 7%, 36%); - --sl-color-gray-4: hsl(224, 6%, 56%); - --sl-color-gray-5: hsl(224, 6%, 77%); - --sl-color-gray-6: hsl(224, 20%, 94%); - --sl-color-gray-7: hsl(224, 19%, 97%); - --sl-color-black: hsl(0, 0%, 100%); - - --sl-color-orange-high: hsl(var(--sl-hue-orange), 80%, 25%); - --sl-color-orange: hsl(var(--sl-hue-orange), 90%, 60%); - --sl-color-orange-low: hsl(var(--sl-hue-orange), 90%, 88%); - --sl-color-green-high: hsl(var(--sl-hue-green), 80%, 22%); - --sl-color-green: hsl(var(--sl-hue-green), 90%, 46%); - --sl-color-green-low: hsl(var(--sl-hue-green), 85%, 90%); - --sl-color-blue-high: hsl(var(--sl-hue-blue), 80%, 30%); - --sl-color-blue: hsl(var(--sl-hue-blue), 90%, 60%); - --sl-color-blue-low: hsl(var(--sl-hue-blue), 88%, 90%); - --sl-color-purple-high: hsl(var(--sl-hue-purple), 90%, 30%); - --sl-color-purple: hsl(var(--sl-hue-purple), 90%, 60%); - --sl-color-purple-low: hsl(var(--sl-hue-purple), 80%, 90%); - --sl-color-red-high: hsl(var(--sl-hue-red), 80%, 30%); - --sl-color-red: hsl(var(--sl-hue-red), 90%, 60%); - --sl-color-red-low: hsl(var(--sl-hue-red), 80%, 90%); - - --sl-color-accent-high: hsl(234, 80%, 30%); - --sl-color-accent: hsl(234, 90%, 60%); - --sl-color-accent-low: hsl(234, 88%, 90%); - - --sl-color-text-accent: var(--sl-color-accent); - --sl-color-text-invert: var(--sl-color-black); - --sl-color-bg-nav: var(--sl-color-gray-7); - --sl-color-bg-sidebar: var(--sl-color-bg); - --sl-color-bg-inline-code: var(--sl-color-gray-6); - --sl-color-bg-accent: var(--sl-color-accent); - --sl-color-hairline-light: var(--sl-color-gray-6); - --sl-color-hairline-shade: var(--sl-color-gray-6); - - --sl-color-backdrop-overlay: hsla(225, 9%, 36%, 0.66); - - /* Shadows (light mode) */ - --sl-shadow-sm: 0px 1px 1px hsla(0, 0%, 0%, 0.06), 0px 2px 1px hsla(0, 0%, 0%, 0.06); - --sl-shadow-md: 0px 8px 4px hsla(0, 0%, 0%, 0.03), 0px 5px 2px hsla(0, 0%, 0%, 0.03), - 0px 3px 2px hsla(0, 0%, 0%, 0.06), 0px 1px 1px hsla(0, 0%, 0%, 0.06); - --sl-shadow-lg: 0px 25px 7px rgba(0, 0, 0, 0.01), 0px 16px 6px hsla(0, 0%, 0%, 0.03), - 0px 9px 5px hsla(223, 13%, 10%, 0.08), 0px 4px 4px hsla(0, 0%, 0%, 0.16), - 0px 4px 2px hsla(0, 0%, 0%, 0.04); -} + :root[data-theme='light'], + [data-theme='light'] ::backdrop { + /* Colours (light mode) */ + --sl-color-white: hsl(224, 10%, 10%); + --sl-color-gray-1: hsl(224, 14%, 16%); + --sl-color-gray-2: hsl(224, 10%, 23%); + --sl-color-gray-3: hsl(224, 7%, 36%); + --sl-color-gray-4: hsl(224, 6%, 56%); + --sl-color-gray-5: hsl(224, 6%, 77%); + --sl-color-gray-6: hsl(224, 20%, 94%); + --sl-color-gray-7: hsl(224, 19%, 97%); + --sl-color-black: hsl(0, 0%, 100%); + + --sl-color-orange-high: hsl(var(--sl-hue-orange), 80%, 25%); + --sl-color-orange: hsl(var(--sl-hue-orange), 90%, 60%); + --sl-color-orange-low: hsl(var(--sl-hue-orange), 90%, 88%); + --sl-color-green-high: hsl(var(--sl-hue-green), 80%, 22%); + --sl-color-green: hsl(var(--sl-hue-green), 90%, 46%); + --sl-color-green-low: hsl(var(--sl-hue-green), 85%, 90%); + --sl-color-blue-high: hsl(var(--sl-hue-blue), 80%, 30%); + --sl-color-blue: hsl(var(--sl-hue-blue), 90%, 60%); + --sl-color-blue-low: hsl(var(--sl-hue-blue), 88%, 90%); + --sl-color-purple-high: hsl(var(--sl-hue-purple), 90%, 30%); + --sl-color-purple: hsl(var(--sl-hue-purple), 90%, 60%); + --sl-color-purple-low: hsl(var(--sl-hue-purple), 80%, 90%); + --sl-color-red-high: hsl(var(--sl-hue-red), 80%, 30%); + --sl-color-red: hsl(var(--sl-hue-red), 90%, 60%); + --sl-color-red-low: hsl(var(--sl-hue-red), 80%, 90%); + + --sl-color-accent-high: hsl(234, 80%, 30%); + --sl-color-accent: hsl(234, 90%, 60%); + --sl-color-accent-low: hsl(234, 88%, 90%); + + --sl-color-text-accent: var(--sl-color-accent); + --sl-color-text-invert: var(--sl-color-black); + --sl-color-bg-nav: var(--sl-color-gray-7); + --sl-color-bg-sidebar: var(--sl-color-bg); + --sl-color-bg-inline-code: var(--sl-color-gray-6); + --sl-color-bg-accent: var(--sl-color-accent); + --sl-color-hairline-light: var(--sl-color-gray-6); + --sl-color-hairline-shade: var(--sl-color-gray-6); + + --sl-color-backdrop-overlay: hsla(225, 9%, 36%, 0.66); + + /* Shadows (light mode) */ + --sl-shadow-sm: 0px 1px 1px hsla(0, 0%, 0%, 0.06), 0px 2px 1px hsla(0, 0%, 0%, 0.06); + --sl-shadow-md: 0px 8px 4px hsla(0, 0%, 0%, 0.03), 0px 5px 2px hsla(0, 0%, 0%, 0.03), + 0px 3px 2px hsla(0, 0%, 0%, 0.06), 0px 1px 1px hsla(0, 0%, 0%, 0.06); + --sl-shadow-lg: 0px 25px 7px rgba(0, 0, 0, 0.01), 0px 16px 6px hsla(0, 0%, 0%, 0.03), + 0px 9px 5px hsla(223, 13%, 10%, 0.08), 0px 4px 4px hsla(0, 0%, 0%, 0.16), + 0px 4px 2px hsla(0, 0%, 0%, 0.04); + } -@media (min-width: 50em) { - :root { - --sl-nav-height: 4rem; - --sl-nav-pad-x: 1.5rem; - --sl-text-h1: var(--sl-text-5xl); - --sl-text-h2: var(--sl-text-4xl); - --sl-text-h3: var(--sl-text-3xl); - --sl-text-h4: var(--sl-text-2xl); + @media (min-width: 50em) { + :root { + --sl-nav-height: 4rem; + --sl-nav-pad-x: 1.5rem; + --sl-text-h1: var(--sl-text-5xl); + --sl-text-h2: var(--sl-text-4xl); + --sl-text-h3: var(--sl-text-3xl); + --sl-text-h4: var(--sl-text-2xl); + } } -} -@media (min-width: 72rem) { - :root { - --sl-content-pad-x: 1.5rem; - --sl-mobile-toc-height: 0rem; + @media (min-width: 72rem) { + :root { + --sl-content-pad-x: 1.5rem; + --sl-mobile-toc-height: 0rem; + } } } diff --git a/packages/starlight/style/reset.css b/packages/starlight/style/reset.css index 6a0a3c55763..e9bc9c83b51 100644 --- a/packages/starlight/style/reset.css +++ b/packages/starlight/style/reset.css @@ -1,48 +1,52 @@ -*, -*::before, -*::after { - box-sizing: border-box; -} +@layer starlight.reset { + *, + *::before, + *::after { + box-sizing: border-box; + } -* { - margin: 0; -} + * { + margin: 0; + } -html { - color-scheme: dark; - accent-color: var(--sl-color-accent); -} + html { + color-scheme: dark; + accent-color: var(--sl-color-accent); + -webkit-text-size-adjust: 100%; + text-size-adjust: 100%; + } -html[data-theme='light'] { - color-scheme: light; -} + html[data-theme='light'] { + color-scheme: light; + } -body { - font-family: var(--__sl-font); - line-height: var(--sl-line-height); - -webkit-font-smoothing: antialiased; - color: var(--sl-color-text); - background-color: var(--sl-color-bg); -} + body { + font-family: var(--__sl-font); + line-height: var(--sl-line-height); + -webkit-font-smoothing: antialiased; + color: var(--sl-color-text); + background-color: var(--sl-color-bg); + } -input, -button, -textarea, -select { - font: inherit; -} + input, + button, + textarea, + select { + font: inherit; + } -p, -h1, -h2, -h3, -h4, -h5, -h6, -code { - overflow-wrap: break-word; -} + p, + h1, + h2, + h3, + h4, + h5, + h6, + code { + overflow-wrap: break-word; + } -code { - font-family: var(--__sl-font-mono); + code { + font-family: var(--__sl-font-mono); + } } diff --git a/packages/starlight/style/shiki.css b/packages/starlight/style/shiki.css deleted file mode 100644 index b35288bdf8c..00000000000 --- a/packages/starlight/style/shiki.css +++ /dev/null @@ -1,13 +0,0 @@ -:root { - --astro-code-color-text: var(--sl-color-white); - --astro-code-color-background: var(--sl-color-gray-6); - --astro-code-token-constant: var(--sl-color-blue-high); - --astro-code-token-string: var(--sl-color-green-high); - --astro-code-token-comment: var(--sl-color-gray-2); - --astro-code-token-keyword: var(--sl-color-purple-high); - --astro-code-token-parameter: var(--sl-color-red-high); - --astro-code-token-function: var(--sl-color-red-high); - --astro-code-token-string-expression: var(--sl-color-green-high); - --astro-code-token-punctuation: var(--sl-color-gray-2); - --astro-code-token-link: var(--sl-color-blue-high); -} diff --git a/packages/starlight/style/util.css b/packages/starlight/style/util.css index b041a9c2f39..bb839538b33 100644 --- a/packages/starlight/style/util.css +++ b/packages/starlight/style/util.css @@ -1,55 +1,63 @@ -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; -} +@layer starlight.utils { + .sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; + } -.sl-hidden { - display: none; -} -.sl-flex { - display: flex; -} -.sl-block { - display: block; -} -@media (min-width: 50rem) { - .md\:sl-hidden { + .sl-hidden { display: none; } - .md\:sl-flex { + .sl-flex { display: flex; } - .md\:sl-block { + .sl-block { display: block; } -} -@media (min-width: 72rem) { - .lg\:sl-hidden { - display: none; + @media (min-width: 50rem) { + .md\:sl-hidden { + display: none; + } + .md\:sl-flex { + display: flex; + } + .md\:sl-block { + display: block; + } } - .lg\:sl-flex { - display: flex; + @media (min-width: 72rem) { + .lg\:sl-hidden { + display: none; + } + .lg\:sl-flex { + display: flex; + } + .lg\:sl-block { + display: block; + } } - .lg\:sl-block { - display: block; + [data-theme='light'] .light\:sl-hidden { + display: none; + } + [data-theme='dark'] .dark\:sl-hidden { + display: none; } -} - -/* -Flip an element around the y-axis when in an RTL context. -Primarily useful for things where we can’t rely on writing direction like icons. - -<Icon name="right-arrow" class="rtl:flip" /> -In a LTR context: → In a RTL context: ← -*/ -[dir='rtl'] .rtl\:flip:not(:where([dir='rtl'] [dir='ltr'] *)) { - transform: matrix(-1, 0, 0, 1, 0, 0); + /** + * Flip an element around the y-axis when in an RTL context. + * Primarily useful for things where we can’t rely on writing direction like icons. + * + * <Icon name="right-arrow" class="rtl:flip" /> + * + * In a LTR context: → In a RTL context: ← + */ + [dir='rtl'] .rtl\:flip:not(:where([dir='rtl'] [dir='ltr'] *)) { + transform: matrix(-1, 0, 0, 1, 0, 0); + } } diff --git a/packages/starlight/translations/ar.json b/packages/starlight/translations/ar.json index 15600f0dfdd..5d02881748b 100644 --- a/packages/starlight/translations/ar.json +++ b/packages/starlight/translations/ar.json @@ -1,7 +1,7 @@ { "skipLink.label": "تخطَّ إلى المحتوى", "search.label": "ابحث", - "search.shortcutLabel": "(إضغط / للبحث)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "إلغاء", "search.devWarning": "البحث متوفر فقط في بنيات اﻹنتاج. \n جرب بناء المشروع ومعاينته على جهازك", "themeSelect.accessibleLabel": "اختر سمة", @@ -13,10 +13,18 @@ "sidebarNav.accessibleLabel": "الرئيسية", "tableOfContents.onThisPage": "على هذه الصفحة", "tableOfContents.overview": "نظرة عامة", - "i18n.untranslatedContent": "هذا المحتوى لا يتوفر بلغتك بعد.", + "i18n.untranslatedContent": "هذا المحتوى غير متوفر بلغتك بعد.", "page.editLink": "عدل الصفحة", - "page.lastUpdated": "اخر تحديث:", + "page.lastUpdated": "آخر تحديث:", "page.previousLink": "السابق", "page.nextLink": "التالي", - "404.text": "الصفحة غير موجودة. تأكد من الرابط أو ابحث بإستعمال شريط البحث." + "page.draft": "هذا المحتوى مجرد مسودة ولن يظهر في بنيات الإنتاج", + "404.text": "الصفحة غير موجودة. تأكد من الرابط أو ابحث بإستعمال شريط البحث.", + "aside.note": "ملاحظة", + "aside.tip": "نصيحة", + "aside.caution": "تنبيه", + "aside.danger": "تحذير", + "fileTree.directory": "Directory", + "builtWithStarlight.label": "طوِّر بواسطة Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" } diff --git a/packages/starlight/translations/ca.json b/packages/starlight/translations/ca.json new file mode 100644 index 00000000000..ebd3f2dae10 --- /dev/null +++ b/packages/starlight/translations/ca.json @@ -0,0 +1,43 @@ +{ + "skipLink.label": "Saltar al contingut", + "search.label": "Cercar", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "Cancel·lar", + "search.devWarning": "La cerca només està disponible a les versions de producció. \nProva de construir i previsualitzar el lloc per provar-ho localment.", + "themeSelect.accessibleLabel": "Seleccionar tema", + "themeSelect.dark": "Fosc", + "themeSelect.light": "Clar", + "themeSelect.auto": "Automàtic", + "languageSelect.accessibleLabel": "Seleccionar idioma", + "menuButton.accessibleLabel": "Menú", + "sidebarNav.accessibleLabel": "Primari", + "tableOfContents.onThisPage": "En aquesta pàgina", + "tableOfContents.overview": "Sinopsi", + "i18n.untranslatedContent": "Aquesta pàgina encara no està disponible en el teu idioma.", + "page.editLink": "Edita aquesta pàgina", + "page.lastUpdated": "Última actualització:", + "page.previousLink": "Pàgina anterior", + "page.nextLink": "Pàgina següent", + "page.draft": "Aquest contingut és un esborrany i no s'inclourà en les versions de producció.", + "404.text": "Pàgina no trobada. Comprova la URL o intenta utilitzar la barra de cerca.", + "aside.note": "Nota", + "aside.tip": "Consell", + "aside.caution": "Precaució", + "aside.danger": "Perill", + "expressiveCode.copyButtonCopied": "Copiat!", + "expressiveCode.copyButtonTooltip": "Copiar al porta-retalls", + "expressiveCode.terminalWindowFallbackTitle": "Finestra del terminal", + "fileTree.directory": "Directori", + "builtWithStarlight.label": "Fet amb Starlight", + "pagefind.clear_search": "Netejar", + "pagefind.load_more": "Carregar més resultats", + "pagefind.search_label": "Cercar pàgina", + "pagefind.filters_label": "Filtres", + "pagefind.zero_results": "Cap resultat per a: [SEARCH_TERM]", + "pagefind.many_results": "[COUNT] resultats per a: [SEARCH_TERM]", + "pagefind.one_result": "[COUNT] resultat per a: [SEARCH_TERM]", + "pagefind.alt_search": "Cap resultat per a [SEARCH_TERM]. Mostrant resultats per a: [DIFFERENT_TERM]", + "pagefind.search_suggestion": "Cap resultat per a [SEARCH_TERM]. Prova alguna d’aquestes cerques:", + "pagefind.searching": "Cercant [SEARCH_TERM]...", + "heading.anchorLabel": "Section titled “{{title}}”" +} diff --git a/packages/starlight/translations/cs.json b/packages/starlight/translations/cs.json index d90eeda5fc1..8b2e321051e 100644 --- a/packages/starlight/translations/cs.json +++ b/packages/starlight/translations/cs.json @@ -1,7 +1,7 @@ { "skipLink.label": "Přeskočit na obsah", "search.label": "Hledat", - "search.shortcutLabel": "(Vyhledejte stisknutím /)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "Zrušit", "search.devWarning": "Vyhledávání je dostupné pouze v produkčních sestaveních. \nZkuste sestavit a zobrazit náhled webu a otestovat jej lokálně.", "themeSelect.accessibleLabel": "Vyberte motiv", @@ -18,5 +18,26 @@ "page.lastUpdated": "Poslední aktualizace:", "page.previousLink": "Předchozí", "page.nextLink": "Další", - "404.text": "Stránka nenalezena. Zkontrolujte adresu URL nebo zkuste použít vyhledávací pole." + "page.draft": "Tento obsah je koncept a nebude zahrnutý v produkčním sestavení.", + "404.text": "Stránka nenalezena. Zkontrolujte adresu nebo zkuste použít vyhledávač", + "aside.note": "Poznámka", + "aside.tip": "Tip", + "aside.caution": "Upozornění", + "aside.danger": "Nebezpečí", + "fileTree.directory": "Adresář", + "builtWithStarlight.label": "Postavené s Starlight", + "expressiveCode.copyButtonCopied": "Zkopírováno!", + "expressiveCode.copyButtonTooltip": "Kopíruj do schránky", + "expressiveCode.terminalWindowFallbackTitle": "Terminál", + "pagefind.clear_search": "Vyčistit", + "pagefind.load_more": "Načíst další výsledky", + "pagefind.search_label": "Vyhledat stránku", + "pagefind.filters_label": "Filtry", + "pagefind.zero_results": "Žádný výsledek pro: [SEARCH_TERM]", + "pagefind.many_results": "počet výsledků: [COUNT] pro: [SEARCH_TERM]", + "pagefind.one_result": "[COUNT] výsledek pro: [SEARCH_TERM]", + "pagefind.alt_search": "Žádné výsledky pro [SEARCH_TERM]. Namísto toho zobrazuji výsledky pro: [DIFFERENT_TERM]", + "pagefind.search_suggestion": "Žádný výsledek pro [SEARCH_TERM]. Zkus nějaké z těchto hledání:", + "pagefind.searching": "Hledám [SEARCH_TERM]...", + "heading.anchorLabel": "Section titled “{{title}}”" } diff --git a/packages/starlight/translations/da.json b/packages/starlight/translations/da.json index 14903f0a746..307a5f4fdb5 100644 --- a/packages/starlight/translations/da.json +++ b/packages/starlight/translations/da.json @@ -1,7 +1,7 @@ { "skipLink.label": "Gå til indhold", "search.label": "Søg", - "search.shortcutLabel": "(Tryk / for at søge)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "Annuller", "search.devWarning": "Søgning er kun tilgængeligt i produktions versioner. \nPrøv at bygge siden og forhåndsvis den for at teste det lokalt.", "themeSelect.accessibleLabel": "Vælg tema", @@ -18,5 +18,13 @@ "page.lastUpdated": "Sidst opdateret:", "page.previousLink": "Forrige", "page.nextLink": "Næste", - "404.text": "Siden er ikke fundet. Tjek din URL eller prøv søgelinjen." + "page.draft": "Indholdet er en kladde og vil ikke blive inkluderet i produktions versioner.", + "404.text": "Siden er ikke fundet. Tjek din URL eller prøv søgelinjen.", + "aside.note": "Note", + "aside.tip": "Tip", + "aside.caution": "Bemærk", + "aside.danger": "Advarsel", + "fileTree.directory": "Mappe", + "builtWithStarlight.label": "Bygget med Starlight", + "heading.anchorLabel": "Sektion kaldt “{{title}}”" } diff --git a/packages/starlight/translations/de.json b/packages/starlight/translations/de.json index da82f791541..c9cf8856158 100644 --- a/packages/starlight/translations/de.json +++ b/packages/starlight/translations/de.json @@ -1,9 +1,9 @@ { "skipLink.label": "Zum Inhalt springen", "search.label": "Suchen", - "search.shortcutLabel": "(Drücke / zum Suchen)", + "search.ctrlKey": "Strg", "search.cancelLabel": "Abbrechen", - "search.devWarning": "Search is only available in production builds. \nTry building and previewing the site to test it out locally.", + "search.devWarning": "Die Suche ist nur in Produktions-Builds verfügbar. \nVersuche, die Website zu bauen und in der Vorschau anzusehen, um sie lokal zu testen.", "themeSelect.accessibleLabel": "Farbschema wählen", "themeSelect.dark": "Dunkel", "themeSelect.light": "Hell", @@ -15,8 +15,16 @@ "tableOfContents.overview": "Überblick", "i18n.untranslatedContent": "Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.", "page.editLink": "Seite bearbeiten", - "page.lastUpdated": "Zuletzt bearbeitet:", + "page.lastUpdated": "Zuletzt aktualisiert:", "page.previousLink": "Vorherige Seite", "page.nextLink": "Nächste Seite", - "404.text": "Seite nicht gefunden. Überprüfe die URL oder nutze die Suchleiste." + "page.draft": "Dieser Inhalt ist ein Entwurf und wird nicht in den Produktions-Builds enthalten sein.", + "404.text": "Seite nicht gefunden. Überprüfe die URL oder nutze die Suchleiste.", + "aside.note": "Hinweis", + "aside.tip": "Tipp", + "aside.caution": "Achtung", + "aside.danger": "Gefahr", + "fileTree.directory": "Ordner", + "builtWithStarlight.label": "Erstellt mit Starlight", + "heading.anchorLabel": "Abschnitt betitelt „{{title}}“" } diff --git a/packages/starlight/translations/el.json b/packages/starlight/translations/el.json new file mode 100644 index 00000000000..930e8647740 --- /dev/null +++ b/packages/starlight/translations/el.json @@ -0,0 +1,30 @@ +{ + "skipLink.label": "Μετάβαση στο περιεχόμενο", + "search.label": "Αναζήτηση", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "Ακύρωση", + "search.devWarning": "Η αναζήτηση είναι διαθέσιμη μόνο σε builds παραγωγής.\nΔοκίμασε να κάνεις build τον ιστότοπο και να τον προεπισκοπήσεις για να τον ελέγξεις τοπικά.", + "themeSelect.accessibleLabel": "Επιλογή χρωματικού θέματος", + "themeSelect.dark": "Σκοτεινό", + "themeSelect.light": "Φωτεινό", + "themeSelect.auto": "Σύστημα", + "languageSelect.accessibleLabel": "Επιλογή γλώσσας", + "menuButton.accessibleLabel": "Μενού", + "sidebarNav.accessibleLabel": "Κύρια πλοήγηση", + "tableOfContents.onThisPage": "Σε αυτή τη σελίδα", + "tableOfContents.overview": "Επισκόπηση", + "i18n.untranslatedContent": "Αυτό το περιεχόμενο δεν είναι ακόμη διαθέσιμο στη γλώσσα σου.", + "page.editLink": "Επεξεργασία σελίδας", + "page.lastUpdated": "Τελευταία ενημέρωση:", + "page.previousLink": "Προηγούμενη σελίδα", + "page.nextLink": "Επόμενη σελίδα", + "page.draft": "Αυτό το περιεχόμενο είναι πρόχειρο και δεν θα περιλαμβάνεται στα builds παραγωγής.", + "404.text": "Η σελίδα δεν βρέθηκε. Έλεγξε το URL ή χρησιμοποίησε τη γραμμή αναζήτησης.", + "aside.note": "Σημείωση", + "aside.tip": "Συμβουλή", + "aside.caution": "Προσοχή", + "aside.danger": "Κίνδυνος", + "fileTree.directory": "Φάκελος", + "builtWithStarlight.label": "Δημιουργήθηκε με το Starlight", + "heading.anchorLabel": "Ενότητα με τίτλο «{{title}}»" +} diff --git a/packages/starlight/translations/en.json b/packages/starlight/translations/en.json index 5bc396b2c87..5e968f8ce3c 100644 --- a/packages/starlight/translations/en.json +++ b/packages/starlight/translations/en.json @@ -1,7 +1,7 @@ { "skipLink.label": "Skip to content", "search.label": "Search", - "search.shortcutLabel": "(Press / to Search)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "Cancel", "search.devWarning": "Search is only available in production builds. \nTry building and previewing the site to test it out locally.", "themeSelect.accessibleLabel": "Select theme", @@ -18,5 +18,13 @@ "page.lastUpdated": "Last updated:", "page.previousLink": "Previous", "page.nextLink": "Next", - "404.text": "Page not found. Check the URL or try using the search bar." + "page.draft": "This content is a draft and will not be included in production builds.", + "404.text": "Page not found. Check the URL or try using the search bar.", + "aside.note": "Note", + "aside.tip": "Tip", + "aside.caution": "Caution", + "aside.danger": "Danger", + "fileTree.directory": "Directory", + "builtWithStarlight.label": "Built with Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" } diff --git a/packages/starlight/translations/es.json b/packages/starlight/translations/es.json index 5cf3200abf7..e2653ca5b9f 100644 --- a/packages/starlight/translations/es.json +++ b/packages/starlight/translations/es.json @@ -1,8 +1,8 @@ { - "skipLink.label": "Saltearse al contenido", + "skipLink.label": "Ir al contenido", "search.label": "Buscar", - "search.shortcutLabel": "(Presiona / para buscar)", - "search.cancelLabel": "Interrumpir", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "Cancelar", "search.devWarning": "La búsqueda solo está disponible en las versiones de producción. \nIntenta construir y previsualizar el sitio para probarlo localmente.", "themeSelect.accessibleLabel": "Seleccionar tema", "themeSelect.dark": "Oscuro", @@ -18,5 +18,26 @@ "page.lastUpdated": "Última actualización:", "page.previousLink": "Página anterior", "page.nextLink": "Siguiente página", - "404.text": "Página no encontrada. Verifica la URL o intenta usar la barra de búsqueda." + "page.draft": "Este contenido es un borrador y no se incluirá en las versiones de producción.", + "404.text": "Página no encontrada. Verifica la URL o intenta usar la barra de búsqueda.", + "aside.note": "Nota", + "aside.tip": "Consejo", + "aside.caution": "Precaución", + "aside.danger": "Peligro", + "expressiveCode.copyButtonCopied": "¡Copiado!", + "expressiveCode.copyButtonTooltip": "Copiar al portapapeles", + "expressiveCode.terminalWindowFallbackTitle": "Ventana de terminal", + "fileTree.directory": "Directorio", + "builtWithStarlight.label": "Hecho con Starlight", + "pagefind.clear_search": "Limpiar", + "pagefind.load_more": "Cargar más resultados", + "pagefind.search_label": "Buscar página", + "pagefind.filters_label": "Filtros", + "pagefind.zero_results": "Ningún resultado para: [SEARCH_TERM]", + "pagefind.many_results": "[COUNT] resultados para: [SEARCH_TERM]", + "pagefind.one_result": "[COUNT] resultado para: [SEARCH_TERM]", + "pagefind.alt_search": "Ningún resultado para [SEARCH_TERM]. Mostrando resultados para: [DIFFERENT_TERM]", + "pagefind.search_suggestion": "Ningún resultado para [SEARCH_TERM]. Prueba alguna de estas búsquedas:", + "pagefind.searching": "Buscando [SEARCH_TERM]...", + "heading.anchorLabel": "Sección titulada «{{title}}»" } diff --git a/packages/starlight/translations/fa.json b/packages/starlight/translations/fa.json index 1e83fed9833..22db252ddf4 100644 --- a/packages/starlight/translations/fa.json +++ b/packages/starlight/translations/fa.json @@ -1,7 +1,7 @@ { "skipLink.label": "رفتن به محتوا", "search.label": "جستجو", - "search.shortcutLabel": "(برای جستجو / را فشار دهید)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "لغو", "search.devWarning": "جستجو تنها در نسخه‌های تولیدی در دسترس است. \nسعی کنید سایت را بسازید و پیش‌نمایش آن را به صورت محلی آزمایش کنید.", "themeSelect.accessibleLabel": "انتخاب پوسته", @@ -12,11 +12,19 @@ "menuButton.accessibleLabel": "منو", "sidebarNav.accessibleLabel": "اصلی", "tableOfContents.onThisPage": "در این صفحه", - "tableOfContents.overview": "بررسی اجمالی", + "tableOfContents.overview": "نگاه کلی", "i18n.untranslatedContent": "این محتوا هنوز به زبان شما در دسترس نیست.", "page.editLink": "ویرایش صفحه", - "page.lastUpdated": "آخرین به روز رسانی:", + "page.lastUpdated": "آخرین به‌روزرسانی:", "page.previousLink": "قبلی", "page.nextLink": "بعدی", - "404.text": "صفحه یافت نشد. لطفاً URL را بررسی کنید یا از جستجو استفاده نمایید." + "page.draft": "This content is a draft and will not be included in production builds.", + "404.text": "صفحه یافت نشد. لطفاً URL را بررسی کنید یا از جستجو استفاده نمایید.", + "aside.note": "یادداشت", + "aside.tip": "نکته", + "aside.caution": "احتیاط", + "aside.danger": "خطر", + "fileTree.directory": "فهرست", + "builtWithStarlight.label": "Built with Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" } diff --git a/packages/starlight/translations/fi.json b/packages/starlight/translations/fi.json new file mode 100644 index 00000000000..520ff408eb8 --- /dev/null +++ b/packages/starlight/translations/fi.json @@ -0,0 +1,30 @@ +{ + "skipLink.label": "Siirry sisältöön", + "search.label": "Haku", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "Peruuta", + "search.devWarning": "Haku on käytettävissä vain tuotantoversioissa.\nKokeile kääntää ja esikatsella sivustoa paikallisesti testataksesi sitä.", + "themeSelect.accessibleLabel": "Valitse teema", + "themeSelect.dark": "Tumma", + "themeSelect.light": "Vaalea", + "themeSelect.auto": "Automaattinen", + "languageSelect.accessibleLabel": "Valitse kieli", + "menuButton.accessibleLabel": "Valikko", + "sidebarNav.accessibleLabel": "Päävalikko", + "tableOfContents.onThisPage": "Tällä sivulla", + "tableOfContents.overview": "Yleiskatsaus", + "i18n.untranslatedContent": "Tämä sisältö ei ole vielä saatavilla valitsemallasi kielellä.", + "page.editLink": "Muokkaa sivua", + "page.lastUpdated": "Viimeksi päivitetty:", + "page.previousLink": "Edellinen", + "page.nextLink": "Seuraava", + "page.draft": "Tämä sisältö on luonnos eikä sitä sisällytetä tuotantoversioon.", + "404.text": "Sivua ei löytynyt. Tarkista URL-osoite tai käytä hakupalkkia.", + "aside.note": "Huomio", + "aside.tip": "Vinkki", + "aside.caution": "Varoitus", + "aside.danger": "Vaara", + "fileTree.directory": "Hakemisto", + "builtWithStarlight.label": "Rakennettu Starlightilla", + "heading.anchorLabel": "Osio nimeltä “{{title}}”" +} diff --git a/packages/starlight/translations/fr.json b/packages/starlight/translations/fr.json index bc947080e02..25e6cea8108 100644 --- a/packages/starlight/translations/fr.json +++ b/packages/starlight/translations/fr.json @@ -1,7 +1,7 @@ { "skipLink.label": "Aller au contenu", "search.label": "Rechercher", - "search.shortcutLabel": "(Presser / pour rechercher)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "Annuler", "search.devWarning": "La recherche est disponible uniquement en mode production. \nEssayez de construire puis de prévisualiser votre site pour tester la recherche localement.", "themeSelect.accessibleLabel": "Selectionner le thème", @@ -18,5 +18,16 @@ "page.lastUpdated": "Dernière mise à jour :", "page.previousLink": "Précédent", "page.nextLink": "Suivant", - "404.text": "Page non trouvée. Vérifiez l’URL ou essayez d’utiliser la barre de recherche." + "page.draft": "Ce contenu est une ébauche et ne sera pas inclus dans la version de production.", + "404.text": "Page non trouvée. Vérifiez l’URL ou essayez d’utiliser la barre de recherche.", + "aside.note": "Note", + "aside.tip": "Astuce", + "aside.caution": "Attention", + "aside.danger": "Danger", + "expressiveCode.copyButtonCopied": "Copié !", + "expressiveCode.copyButtonTooltip": "Copier dans le presse-papiers", + "expressiveCode.terminalWindowFallbackTitle": "Fenêtre de terminal", + "fileTree.directory": "Répertoire", + "builtWithStarlight.label": "Créé avec Starlight", + "heading.anchorLabel": "Section intitulée « {{title}} »" } diff --git a/packages/starlight/translations/gl.json b/packages/starlight/translations/gl.json new file mode 100644 index 00000000000..71656223045 --- /dev/null +++ b/packages/starlight/translations/gl.json @@ -0,0 +1,43 @@ +{ + "skipLink.label": "Ir ao contido", + "search.label": "Busca", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "Deixar", + "search.devWarning": "A busca só está dispoñible nas versións de producción. \nTrata de construir e ollear o sitio para probalo localmente.", + "themeSelect.accessibleLabel": "Selecciona tema", + "themeSelect.dark": "Escuro", + "themeSelect.light": "Claro", + "themeSelect.auto": "Auto", + "languageSelect.accessibleLabel": "Seleciona linguaxe", + "menuButton.accessibleLabel": "Menú", + "sidebarNav.accessibleLabel": "Principal", + "tableOfContents.onThisPage": "Nesta páxina", + "tableOfContents.overview": "Sinopse", + "i18n.untranslatedContent": "Este contido aínda non está dispoñible no teu idioma.", + "page.editLink": "Editar páxina", + "page.lastUpdated": "Última actualización:", + "page.previousLink": "Anterior", + "page.nextLink": "Seguinte", + "page.draft": "Este contido é un borrador e non se incluirá nas versións de producción.", + "404.text": "Páxina non atopada. Comproba a URL ou intenta usar a barra de busca.", + "aside.note": "Nota", + "aside.tip": "Consello", + "aside.caution": "Precaución", + "aside.danger": "Perigo", + "expressiveCode.copyButtonCopied": "¡Copiado!", + "expressiveCode.copyButtonTooltip": "Copiar ao portapapeis", + "expressiveCode.terminalWindowFallbackTitle": "Fiestra do terminal", + "fileTree.directory": "Directorio", + "builtWithStarlight.label": "Feito con Starlight", + "pagefind.clear_search": "Limpar", + "pagefind.load_more": "Cargar máis resultados", + "pagefind.search_label": "Buscar páxina", + "pagefind.filters_label": "Filtros", + "pagefind.zero_results": "Ningún resultado para: [SEARCH_TERM]", + "pagefind.many_results": "[COUNT] resultados para: [SEARCH_TERM]", + "pagefind.one_result": "[COUNT] resultado para: [SEARCH_TERM]", + "pagefind.alt_search": "Ningún resultado para [SEARCH_TERM]. Amósanse resultados para: [DIFFERENT_TERM]", + "pagefind.search_suggestion": "Ningún resultado para [SEARCH_TERM]. Proba algunha destas buscas:", + "pagefind.searching": "Buscando [SEARCH_TERM]...", + "heading.anchorLabel": "Sección titulada «{{title}}»" +} diff --git a/packages/starlight/translations/he.json b/packages/starlight/translations/he.json index e09ccec2ec6..0728103410d 100644 --- a/packages/starlight/translations/he.json +++ b/packages/starlight/translations/he.json @@ -1,7 +1,7 @@ { "skipLink.label": "דלגו לתוכן", "search.label": "חיפוש", - "search.shortcutLabel": "(לחצו / כדי לחפש)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "ביטול", "search.devWarning": "החיפוש זמין רק בסביבת ייצור. \nנסו לבנות ולהציג תצוגה מקדימה של האתר כדי לבדוק אותו באופן מקומי.", "themeSelect.accessibleLabel": "בחרו פרופיל צבע", @@ -18,5 +18,13 @@ "page.lastUpdated": "עדכון אחרון:", "page.previousLink": "הקודם", "page.nextLink": "הבא", - "404.text": "הדף לא נמצא. אנא בדקו את כתובת האתר או נסו להשתמש בסרגל החיפוש." + "page.draft": "This content is a draft and will not be included in production builds.", + "404.text": "הדף לא נמצא. אנא בדקו את כתובת האתר או נסו להשתמש בסרגל החיפוש.", + "aside.note": "Note", + "aside.tip": "Tip", + "aside.caution": "Caution", + "aside.danger": "Danger", + "fileTree.directory": "Directory", + "builtWithStarlight.label": "Built with Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" } diff --git a/packages/starlight/translations/hi.json b/packages/starlight/translations/hi.json new file mode 100644 index 00000000000..6cd11a0ca76 --- /dev/null +++ b/packages/starlight/translations/hi.json @@ -0,0 +1,30 @@ +{ + "skipLink.label": "इसे छोड़कर कंटेंट पर जाएं", + "search.label": "खोजें", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "रद्द करे", + "search.devWarning": "खोज केवल उत्पादन बिल्ड में उपलब्ध है। \nस्थानीय स्तर पर परीक्षण करने के लिए साइट बनाए और उसका पूर्वावलोकन करने का प्रयास करें।", + "themeSelect.accessibleLabel": "थीम चुनें", + "themeSelect.dark": "अँधेरा", + "themeSelect.light": "रोशनी", + "themeSelect.auto": "स्वत", + "languageSelect.accessibleLabel": "भाषा चुने", + "menuButton.accessibleLabel": "मेन्यू", + "sidebarNav.accessibleLabel": "मुख्य", + "tableOfContents.onThisPage": "इस पृष्ठ पर", + "tableOfContents.overview": "अवलोकन", + "i18n.untranslatedContent": "यह कंटेंट अभी तक आपकी भाषा में उपलब्ध नहीं है।", + "page.editLink": "पृष्ठ संपादित करें", + "page.lastUpdated": "आखिरी अद्यतन:", + "page.previousLink": "पिछला", + "page.nextLink": "अगला", + "page.draft": "This content is a draft and will not be included in production builds.", + "404.text": "यह पृष्ठ नहीं मिला। URL जांचें या खोज बार का उपयोग करने का प्रयास करें।", + "aside.note": "टिप्पणी", + "aside.tip": "संकेत", + "aside.caution": "सावधानी", + "aside.danger": "खतरा", + "fileTree.directory": "Directory", + "builtWithStarlight.label": "Starlight द्वारा निर्मित", + "heading.anchorLabel": "Section titled “{{title}}”" +} diff --git a/packages/starlight/translations/hu.json b/packages/starlight/translations/hu.json new file mode 100644 index 00000000000..d94fb7b1430 --- /dev/null +++ b/packages/starlight/translations/hu.json @@ -0,0 +1,43 @@ +{ + "skipLink.label": "Tovább a tartalomhoz", + "search.label": "Keresés", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "Mégsem", + "search.devWarning": "A keresés csak a production build-ekben működik. \nPróbáld meg először buildelni, hogy kipróbálhasd.", + "themeSelect.accessibleLabel": "Téma választás", + "themeSelect.dark": "Sötét", + "themeSelect.light": "Világos", + "themeSelect.auto": "Auto", + "languageSelect.accessibleLabel": "Nyelv választása", + "menuButton.accessibleLabel": "Menü", + "sidebarNav.accessibleLabel": "Fő", + "tableOfContents.onThisPage": "Ezen az oldalon", + "tableOfContents.overview": "Tartalom", + "i18n.untranslatedContent": "Ez a tartalom még nem érhető el a jelenlegi nyelven.", + "page.editLink": "Oldal szerkesztése", + "page.lastUpdated": "Utoljára frissítve:", + "page.previousLink": "Előző", + "page.nextLink": "Következő", + "page.draft": "Ez a tartalom még vázlat, így nem lesz benne a production build-ben.", + "404.text": "Az oldal nem található. Nézd meg az URL-t vagy használd a keresőt.", + "aside.note": "Megjegyzés", + "aside.tip": "Tipp", + "aside.caution": "Figyelem", + "aside.danger": "Veszély", + "fileTree.directory": "Könyvtár", + "builtWithStarlight.label": "Starlight-tal készítve", + "heading.anchorLabel": "Szekció neve “{{title}}”", + "expressiveCode.copyButtonCopied": "Másolva!", + "expressiveCode.copyButtonTooltip": "Másolás", + "expressiveCode.terminalWindowFallbackTitle": "Terminál", + "pagefind.clear_search": "Törlés", + "pagefind.load_more": "Több találat betöltése", + "pagefind.search_label": "Keresés ezen az oldalon", + "pagefind.filters_label": "Szűrők", + "pagefind.zero_results": "Erre a kifejezésre nincs találat: [SEARCH_TERM]", + "pagefind.many_results": "[COUNT] találat erre: [SEARCH_TERM]", + "pagefind.one_result": "[COUNT] találat erre: [SEARCH_TERM]", + "pagefind.alt_search": "Erre a kifejezésre nincs találat: [SEARCH_TERM]. Találatok mutatása erre: [DIFFERENT_TERM]", + "pagefind.search_suggestion": "Erre a kifejezésre nincs találat: [SEARCH_TERM]. Próbáld meg ezek közül az egyiket:", + "pagefind.searching": "Keresés erre: [SEARCH_TERM]..." +} diff --git a/packages/starlight/translations/id.json b/packages/starlight/translations/id.json index efc7cd0d034..b42d3f3b7ad 100644 --- a/packages/starlight/translations/id.json +++ b/packages/starlight/translations/id.json @@ -1,7 +1,7 @@ { "skipLink.label": "Lewati ke konten", "search.label": "Pencarian", - "search.shortcutLabel": "(Tekan / untuk mencari)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "Batal", "search.devWarning": "Pencarian hanya tersedia pada build produksi. \nLakukan proses build dan pratinjau situs Anda sebelum mencoba di lingkungan lokal.", "themeSelect.accessibleLabel": "Pilih tema", @@ -12,11 +12,19 @@ "menuButton.accessibleLabel": "Menu", "sidebarNav.accessibleLabel": "Utama", "tableOfContents.onThisPage": "Di halaman ini", - "tableOfContents.overview": "Selayang Pandang", + "tableOfContents.overview": "Ringkasan", "i18n.untranslatedContent": "Konten ini belum tersedia dalam bahasa Anda.", "page.editLink": "Edit halaman", "page.lastUpdated": "Terakhir diperbaharui:", "page.previousLink": "Sebelumnya", "page.nextLink": "Selanjutnya", - "404.text": "Halaman tidak ditemukan. Cek kembali kolom URL atau gunakan fitur pencarian." + "page.draft": "This content is a draft and will not be included in production builds.", + "404.text": "Halaman tidak ditemukan. Cek kembali kolom URL atau gunakan fitur pencarian.", + "aside.note": "Catatan", + "aside.tip": "Tips", + "aside.caution": "Perhatian", + "aside.danger": "Bahaya", + "fileTree.directory": "Directory", + "builtWithStarlight.label": "Built with Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" } diff --git a/packages/starlight/translations/index.ts b/packages/starlight/translations/index.ts index 1f4fdf7b5a1..7cbf2c40d42 100644 --- a/packages/starlight/translations/index.ts +++ b/packages/starlight/translations/index.ts @@ -2,23 +2,37 @@ import { builtinI18nSchema } from '../schemas/i18n'; import cs from './cs.json'; import en from './en.json'; import es from './es.json'; +import ca from './ca.json'; import de from './de.json'; import ja from './ja.json'; import pt from './pt.json'; import fa from './fa.json'; +import fi from './fi.json'; import fr from './fr.json'; +import gl from './gl.json'; import he from './he.json'; import id from './id.json'; import it from './it.json'; import nl from './nl.json'; import da from './da.json'; +import th from './th.json'; import tr from './tr.json'; import ar from './ar.json'; import nb from './nb.json'; -import zh from './zh.json'; +import zh from './zh-CN.json'; import ko from './ko.json'; import sv from './sv.json'; +import ro from './ro.json'; import ru from './ru.json'; +import vi from './vi.json'; +import uk from './uk.json'; +import hi from './hi.json'; +import zhTW from './zh-TW.json'; +import pl from './pl.json'; +import sk from './sk.json'; +import lv from './lv.json'; +import hu from './hu.json'; +import el from './el.json'; const { parse } = builtinI18nSchema(); @@ -27,22 +41,36 @@ export default Object.fromEntries( cs, en, es, + ca, de, ja, pt, fa, + fi, fr, + gl, he, id, it, nl, da, + th, tr, ar, nb, zh, ko, sv, + ro, ru, + vi, + uk, + hi, + 'zh-TW': zhTW, + pl, + sk, + lv, + hu, + el, }).map(([key, dict]) => [key, parse(dict)]) ); diff --git a/packages/starlight/translations/it.json b/packages/starlight/translations/it.json index f0657e89de1..65c32f15b6f 100644 --- a/packages/starlight/translations/it.json +++ b/packages/starlight/translations/it.json @@ -1,9 +1,9 @@ { "skipLink.label": "Salta ai contenuti", "search.label": "Cerca", - "search.shortcutLabel": "(Usa / per cercare)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "Cancella", - "search.devWarning": "Search is only available in production builds. \nTry building and previewing the site to test it out locally.", + "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.", "themeSelect.accessibleLabel": "Seleziona tema", "themeSelect.dark": "Scuro", "themeSelect.light": "Chiaro", @@ -18,5 +18,13 @@ "page.lastUpdated": "Ultimo aggiornamento:", "page.previousLink": "Indietro", "page.nextLink": "Avanti", - "404.text": "Pagina non trovata. Verifica l'URL o prova a utilizzare la barra di ricerca." + "page.draft": "This content is a draft and will not be included in production builds.", + "404.text": "Pagina non trovata. Verifica l'URL o prova a utilizzare la barra di ricerca.", + "aside.note": "Nota", + "aside.tip": "Consiglio", + "aside.caution": "Attenzione", + "aside.danger": "Pericolo", + "fileTree.directory": "Directory", + "builtWithStarlight.label": "Built with Starlight", + "heading.anchorLabel": "Sezione intitolata “{{title}}”" } diff --git a/packages/starlight/translations/ja.json b/packages/starlight/translations/ja.json index 1f199b482cf..2e1fd806968 100644 --- a/packages/starlight/translations/ja.json +++ b/packages/starlight/translations/ja.json @@ -1,7 +1,7 @@ { "skipLink.label": "コンテンツにスキップ", "search.label": "検索", - "search.shortcutLabel": "(/を押して検索)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "キャンセル", "search.devWarning": "検索はプロダクションビルドでのみ利用可能です。\nローカルでテストするには、サイトをビルドしてプレビューしてください。", "themeSelect.accessibleLabel": "テーマの選択", @@ -18,5 +18,13 @@ "page.lastUpdated": "最終更新日:", "page.previousLink": "前へ", "page.nextLink": "次へ", - "404.text": "ページが見つかりません。 URL を確認するか、検索バーを使用してみてください。" + "page.draft": "このコンテンツは下書きです。プロダクションビルドには含まれません。", + "404.text": "ページが見つかりません。 URL を確認するか、検索バーを使用してみてください。", + "aside.note": "ノート", + "aside.tip": "ヒント", + "aside.caution": "注意", + "aside.danger": "危険", + "fileTree.directory": "ディレクトリ", + "builtWithStarlight.label": "Starlightで作成", + "heading.anchorLabel": "Section titled “{{title}}”" } diff --git a/packages/starlight/translations/ko.json b/packages/starlight/translations/ko.json index 5d4c2b27712..c8db5972fec 100644 --- a/packages/starlight/translations/ko.json +++ b/packages/starlight/translations/ko.json @@ -1,22 +1,30 @@ { - "skipLink.label": "컨텐츠로 이동", + "skipLink.label": "콘텐츠로 이동", "search.label": "검색", - "search.shortcutLabel": "(검색을 위해 / 키를 누르세요)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "취소", - "search.devWarning": "검색 기능은 프로덕션 환경에서만 사용할 수 있습니다.\n사이트를 로컬 환경에서 테스트하기 위해 빌드하고 미리보기(Preview) 하세요.", + "search.devWarning": "검색 기능은 프로덕션 빌드에서만 작동합니다. \n로컬에서 테스트하려면 사이트를 빌드하고 미리 보기를 실행하세요.", "themeSelect.accessibleLabel": "테마 선택", - "themeSelect.dark": "어두움", - "themeSelect.light": "밝음", + "themeSelect.dark": "어두운 테마", + "themeSelect.light": "밝은 테마", "themeSelect.auto": "자동", "languageSelect.accessibleLabel": "언어 선택", "menuButton.accessibleLabel": "메뉴", "sidebarNav.accessibleLabel": "메인", "tableOfContents.onThisPage": "목차", "tableOfContents.overview": "개요", - "i18n.untranslatedContent": "이 컨텐츠는 아직 번역되지 않았습니다.", - "page.editLink": "페이지 수정", - "page.lastUpdated": "최종 수정:", + "i18n.untranslatedContent": "이 콘텐츠는 아직 번역되지 않았습니다.", + "page.editLink": "페이지 편집", + "page.lastUpdated": "마지막 업데이트:", "page.previousLink": "이전 페이지", "page.nextLink": "다음 페이지", - "404.text": "페이지를 찾을 수 없습니다. URL을 확인하거나 검색창을 사용해보세요." + "page.draft": "이 콘텐츠는 아직 초안 상태이며, 최종 빌드에는 포함되지 않습니다.", + "404.text": "페이지를 찾을 수 없습니다. URL을 다시 확인해보거나 검색을 사용해보세요.", + "aside.note": "참고", + "aside.tip": "팁", + "aside.caution": "주의", + "aside.danger": "위험", + "fileTree.directory": "디렉터리", + "builtWithStarlight.label": "이 웹사이트는 Starlight로 제작되었습니다.", + "heading.anchorLabel": "섹션 제목: “{{title}}”" } diff --git a/packages/starlight/translations/lv.json b/packages/starlight/translations/lv.json new file mode 100644 index 00000000000..43190fc987b --- /dev/null +++ b/packages/starlight/translations/lv.json @@ -0,0 +1,30 @@ +{ + "skipLink.label": "Pāriet uz saturu", + "search.label": "Meklēt", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "Atcelt", + "search.devWarning": "Meklēšana ir pieejama tikai ražošanas kompilācijās. \nMēģiniet kompilēt un priekšskatīt vietni, lai to pārbaudītu lokāli.", + "themeSelect.accessibleLabel": "Izvēlieties tēmu", + "themeSelect.dark": "Tumša", + "themeSelect.light": "Gaiša", + "themeSelect.auto": "Automātiska", + "languageSelect.accessibleLabel": "Izvēlieties valodu", + "menuButton.accessibleLabel": "Izvēlne", + "sidebarNav.accessibleLabel": "Galvenā", + "tableOfContents.onThisPage": "Šajā lapā", + "tableOfContents.overview": "Pārskats", + "i18n.untranslatedContent": "Šis saturs vēl nav pieejams jūsu valodā.", + "page.editLink": "Rediģēt lapu", + "page.lastUpdated": "Pēdējoreiz atjaunināts:", + "page.previousLink": "Iepriekšējā", + "page.nextLink": "Nākamā", + "page.draft": "Šis saturs ir melnraksts un netiks iekļauts ražošanas kompilācijās.", + "404.text": "Lapa nav atrasta. Pārbaudiet URL vai mēģiniet izmantot meklēšanas joslu.", + "aside.note": "Piezīme", + "aside.tip": "Padoms", + "aside.caution": "Uzmanību", + "aside.danger": "Bīstamība", + "fileTree.directory": "Direktorija", + "builtWithStarlight.label": "Veidots ar Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" +} diff --git a/packages/starlight/translations/nb.json b/packages/starlight/translations/nb.json index e6abae70ceb..892fc435e2d 100644 --- a/packages/starlight/translations/nb.json +++ b/packages/starlight/translations/nb.json @@ -1,7 +1,7 @@ { "skipLink.label": "Gå til innholdet", "search.label": "Søk", - "search.shortcutLabel": "(Trykk / for å søke)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "Avbryt", "search.devWarning": "Søk er bare tilgjengelig i produksjonsbygg. \nPrøv å bygg siden og forhåndsvis den for å teste det lokalt.", "themeSelect.accessibleLabel": "Velg tema", @@ -18,5 +18,13 @@ "page.lastUpdated": "Sist oppdatert:", "page.previousLink": "Forrige", "page.nextLink": "Neste", - "404.text": "Siden ble ikke funnet. Sjekk URL-en eller prøv å bruke søkefeltet." + "page.draft": "This content is a draft and will not be included in production builds.", + "404.text": "Siden ble ikke funnet. Sjekk URL-en eller prøv å bruke søkefeltet.", + "aside.note": "Merknad", + "aside.tip": "Tips", + "aside.caution": "Advarsel", + "aside.danger": "Fare", + "fileTree.directory": "Mappe", + "builtWithStarlight.label": "Laget med Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" } diff --git a/packages/starlight/translations/nl.json b/packages/starlight/translations/nl.json index 6e485fb6e0d..e2a6cbe7c4f 100644 --- a/packages/starlight/translations/nl.json +++ b/packages/starlight/translations/nl.json @@ -1,7 +1,7 @@ { "skipLink.label": "Ga naar inhoud", "search.label": "Zoeken", - "search.shortcutLabel": "(Druk op / om te zoeken)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "Annuleren", "search.devWarning": "Zoeken is alleen beschikbaar tijdens productie. \nProbeer om de site te builden en er een preview van te bekijken om lokaal te testen.", "themeSelect.accessibleLabel": "Selecteer thema", @@ -18,5 +18,13 @@ "page.lastUpdated": "Laatst bewerkt:", "page.previousLink": "Vorige", "page.nextLink": "Volgende", - "404.text": "Pagina niet gevonden. Controleer de URL of probeer de zoekbalk." + "page.draft": "This content is a draft and will not be included in production builds.", + "404.text": "Pagina niet gevonden. Controleer de URL of probeer de zoekbalk.", + "aside.note": "Opmerking", + "aside.tip": "Tip", + "aside.caution": "Opgepast", + "aside.danger": "Gevaar", + "fileTree.directory": "Directory", + "builtWithStarlight.label": "Built with Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" } diff --git a/packages/starlight/translations/pl.json b/packages/starlight/translations/pl.json new file mode 100644 index 00000000000..8a0c475930d --- /dev/null +++ b/packages/starlight/translations/pl.json @@ -0,0 +1,33 @@ +{ + "skipLink.label": "Przejdź do głównej zawartości", + "search.label": "Szukaj", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "Anuluj", + "search.devWarning": "Wyszukiwanie jest dostępne tylko w buildach produkcyjnych. \nSpróbuj zbudować i uruchomić aplikację, aby przetestować lokalnie.", + "themeSelect.accessibleLabel": "Wybierz motyw", + "themeSelect.dark": "Ciemny", + "themeSelect.light": "Jasny", + "themeSelect.auto": "Auto", + "languageSelect.accessibleLabel": "Wybierz język", + "menuButton.accessibleLabel": "Menu", + "sidebarNav.accessibleLabel": "Główne", + "tableOfContents.onThisPage": "Na tej stronie", + "tableOfContents.overview": "Przegląd", + "i18n.untranslatedContent": "Ta treść nie jest jeszcze dostępna w Twoim języku.", + "page.editLink": "Edytuj stronę", + "page.lastUpdated": "Ostatnia aktualizacja:", + "page.previousLink": "Poprzednia strona", + "page.nextLink": "Następna strona", + "page.draft": "This content is a draft and will not be included in production builds.", + "404.text": "Nie znaleziono. Sprawdź URL lub użyj wyszukiwarki.", + "aside.note": "Notatka", + "aside.tip": "Wskazówka", + "aside.caution": "Uwaga", + "aside.danger": "Ważne", + "fileTree.directory": "Folder", + "expressiveCode.copyButtonCopied": "Skopiowane!", + "expressiveCode.copyButtonTooltip": "Skopiuj do schowka", + "expressiveCode.terminalWindowFallbackTitle": "Okno terminala", + "builtWithStarlight.label": "Built with Starlight", + "heading.anchorLabel": "Dział zatytułowany „{{title}}”" +} diff --git a/packages/starlight/translations/pt.json b/packages/starlight/translations/pt.json index 2b3790351e9..25b57b2fd5b 100644 --- a/packages/starlight/translations/pt.json +++ b/packages/starlight/translations/pt.json @@ -1,7 +1,7 @@ { "skipLink.label": "Pular para o conteúdo", "search.label": "Pesquisar", - "search.shortcutLabel": "(Pressione / para Pesquisar)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "Cancelar", "search.devWarning": "A pesquisa está disponível apenas em builds em produção. \nTente fazer a build e pré-visualize o site para testar localmente.", "themeSelect.accessibleLabel": "Selecionar tema", @@ -18,5 +18,13 @@ "page.lastUpdated": "Última atualização:", "page.previousLink": "Anterior", "page.nextLink": "Próximo", - "404.text": "Página não encontrada. Verifique o URL ou tente usar a barra de pesquisa." + "page.draft": "Esse conteúdo é um rascunho e não será incluído em builds de produção.", + "404.text": "Página não encontrada. Verifique o URL ou tente usar a barra de pesquisa.", + "aside.note": "Nota", + "aside.tip": "Dica", + "aside.caution": "Cuidado", + "aside.danger": "Perigo", + "fileTree.directory": "Directory", + "builtWithStarlight.label": "Feito com Starlight", + "heading.anchorLabel": "Seção intitulada “{{title}}”" } diff --git a/packages/starlight/translations/ro.json b/packages/starlight/translations/ro.json new file mode 100644 index 00000000000..e7083649c86 --- /dev/null +++ b/packages/starlight/translations/ro.json @@ -0,0 +1,30 @@ +{ + "skipLink.label": "Sari la conținut", + "search.label": "Caută", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "Anulează", + "search.devWarning": "Căutarea este disponibilă numai în versiunea de producție. \nÎncercă să construiești și să previzualizezi site-ul pentru a-l testa local.", + "themeSelect.accessibleLabel": "Selectează tema", + "themeSelect.dark": "Întunecată", + "themeSelect.light": "Deschisă", + "themeSelect.auto": "Auto", + "languageSelect.accessibleLabel": "Selectează limba", + "menuButton.accessibleLabel": "Meniu", + "sidebarNav.accessibleLabel": "Principal", + "tableOfContents.onThisPage": "Pe această pagină", + "tableOfContents.overview": "Sinopsis", + "i18n.untranslatedContent": "Acest conținut nu este încă disponibil în limba selectată.", + "page.editLink": "Editează pagina", + "page.lastUpdated": "Ultima actualizare:", + "page.previousLink": "Pagina precendentă", + "page.nextLink": "Pagina următoare", + "page.draft": "This content is a draft and will not be included in production builds.", + "404.text": "Pagina nu a fost găsită. Verifică adresa URL sau încercă să folosești bara de căutare.", + "aside.note": "Mențiune", + "aside.tip": "Sfat", + "aside.caution": "Atenție", + "aside.danger": "Pericol", + "fileTree.directory": "Directory", + "builtWithStarlight.label": "Built with Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" +} diff --git a/packages/starlight/translations/ru.json b/packages/starlight/translations/ru.json index fda513f055c..1d97ae79e44 100644 --- a/packages/starlight/translations/ru.json +++ b/packages/starlight/translations/ru.json @@ -1,22 +1,33 @@ { - "skipLink.label": "Пропустить до содержимого", + "skipLink.label": "Перейти к содержимому", "search.label": "Поиск", - "search.shortcutLabel": "(Нажмите / для Поиска)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "Отменить", - "search.devWarning": "Поиск доступен только в производственных сборках. \nПопробуйте выполнить сборку и просмотреть сайт, чтобы протестировать его локально.", + "search.devWarning": "Поиск доступен только в продакшен-сборках. \nВыполните сборку и запустите превью, чтобы протестировать поиск локально.", "themeSelect.accessibleLabel": "Выберите тему", - "themeSelect.dark": "Темная", + "themeSelect.dark": "Тёмная", "themeSelect.light": "Светлая", "themeSelect.auto": "Авто", "languageSelect.accessibleLabel": "Выберите язык", "menuButton.accessibleLabel": "Меню", "sidebarNav.accessibleLabel": "Основное", - "tableOfContents.onThisPage": "На странице", + "tableOfContents.onThisPage": "На этой странице", "tableOfContents.overview": "Обзор", - "i18n.untranslatedContent": "Этот содержимое пока не доступно на вашем языке.", - "page.editLink": "Редактировать странице", + "i18n.untranslatedContent": "Это содержимое пока не доступно на вашем языке.", + "page.editLink": "Редактировать страницу", "page.lastUpdated": "Последнее обновление:", "page.previousLink": "Предыдущая", "page.nextLink": "Следующая", - "404.text": "Страница не найдена. Проверьтье URL или используйте поиск по сайту" + "page.draft": "Этот контент является черновиком и не будет добавлен в продакшен-сборки.", + "404.text": "Страница не найдена. Проверьте URL или используйте поиск по сайту.", + "aside.note": "Заметка", + "aside.tip": "Совет", + "aside.caution": "Осторожно", + "aside.danger": "Опасно", + "fileTree.directory": "Директория", + "expressiveCode.copyButtonCopied": "Скопировано!", + "expressiveCode.copyButtonTooltip": "Копировать", + "expressiveCode.terminalWindowFallbackTitle": "Окно терминала", + "builtWithStarlight.label": "Сделано с помощью Starlight", + "heading.anchorLabel": "Заголовок раздела «{{title}}»" } diff --git a/packages/starlight/translations/sk.json b/packages/starlight/translations/sk.json new file mode 100644 index 00000000000..a54c83fb9c3 --- /dev/null +++ b/packages/starlight/translations/sk.json @@ -0,0 +1,30 @@ +{ + "skipLink.label": "Preskočiť na obsah", + "search.label": "Hľadať", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "Zrušiť", + "search.devWarning": "Vyhľadávanie je dostupné len v produkčných zostaveniach. \nSkúste vytvoriť a zobraziť náhľad stránky lokálne.", + "themeSelect.accessibleLabel": "Vyberte tému", + "themeSelect.dark": "Tmavý", + "themeSelect.light": "Svetlý", + "themeSelect.auto": "Auto", + "languageSelect.accessibleLabel": "Vyberte jazyk", + "menuButton.accessibleLabel": "Menu", + "sidebarNav.accessibleLabel": "Hlavný", + "tableOfContents.onThisPage": "Na tejto stránke", + "tableOfContents.overview": "Prehľad", + "i18n.untranslatedContent": "Tento obsah zatiaľ nie je dostupný vo vašom jazyku.", + "page.editLink": "Upraviť stránku", + "page.lastUpdated": "Posledná aktualizácia:", + "page.previousLink": "Predchádzajúce", + "page.nextLink": "Nasledujúce", + "page.draft": "Tento obsah je koncept a nebude zahrnutý do produkčných zostavení.", + "404.text": "Stránka nenájdená. Skontrolujte URL alebo skúste použiť vyhľadávacie pole.", + "aside.note": "Poznámka", + "aside.tip": "Tip", + "aside.caution": "Upozornenie", + "aside.danger": "Nebezpečenstvo", + "fileTree.directory": "Adresár", + "builtWithStarlight.label": "Postavené so Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" +} diff --git a/packages/starlight/translations/sv.json b/packages/starlight/translations/sv.json index ef7c2d35b34..a834ea96090 100644 --- a/packages/starlight/translations/sv.json +++ b/packages/starlight/translations/sv.json @@ -1,7 +1,7 @@ { "skipLink.label": "Hoppa till innehåll", "search.label": "Sök", - "search.shortcutLabel": "(Tryck / för att söka)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "Avbryt", "search.devWarning": "Sökfunktionen är endast tillgänglig i produktionsbyggen. \nProva att bygga och förhandsvisa siten för att testa det lokalt.", "themeSelect.accessibleLabel": "Välj tema", @@ -18,5 +18,13 @@ "page.lastUpdated": "Senast uppdaterad:", "page.previousLink": "Föregående", "page.nextLink": "Nästa", - "404.text": "Sidan hittades inte. Kontrollera URL:n eller testa att använda sökfältet." + "page.draft": "This content is a draft and will not be included in production builds.", + "404.text": "Sidan hittades inte. Kontrollera URL:n eller testa att använda sökfältet.", + "aside.note": "Note", + "aside.tip": "Tip", + "aside.caution": "Caution", + "aside.danger": "Danger", + "fileTree.directory": "Directory", + "builtWithStarlight.label": "Built with Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" } diff --git a/packages/starlight/translations/th.json b/packages/starlight/translations/th.json new file mode 100644 index 00000000000..ce2a780658c --- /dev/null +++ b/packages/starlight/translations/th.json @@ -0,0 +1,30 @@ +{ + "skipLink.label": "ข้ามไปยังเนื้อหา", + "search.label": "ค้นหา", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "ยกเลิก", + "search.devWarning": "การค้นหาสามารถใช้งานได้ในเฉพาะเวอร์ชันใช้งานจริงเท่านั้น\nโปรดลองบิลด์และดูตัวอย่างเว็บไซต์เพื่อทดสอบฟังก์ชันบนอุปกรณ์ของคุณ", + "themeSelect.accessibleLabel": "เลือกธีม", + "themeSelect.dark": "มืด", + "themeSelect.light": "สว่าง", + "themeSelect.auto": "อัตโนมัติ", + "languageSelect.accessibleLabel": "เลือกภาษา", + "menuButton.accessibleLabel": "เมนู", + "sidebarNav.accessibleLabel": "หลัก", + "tableOfContents.onThisPage": "ในหน้านี้", + "tableOfContents.overview": "ภาพรวม", + "i18n.untranslatedContent": "เนื้อหานี้ยังไม่มีในภาษาของคุณ", + "page.editLink": "แก้ไขหน้า", + "page.lastUpdated": "อัพเดทล่าสุด:", + "page.previousLink": "ก่อนหน้า", + "page.nextLink": "ถัดไป", + "page.draft": "เนื้อหานี้เป็นแบบร่างและจะไม่ถูกใส่ในเวอร์ชันใช้งานจริง", + "404.text": "ไม่พบหน้า โปรดตรวจสอบ URL หรือลองใช้ฟังก์ชันการค้นหา", + "aside.note": "หมายเหตุ", + "aside.tip": "เคล็ดลับ", + "aside.caution": "คำเตือน", + "aside.danger": "อันตราย", + "fileTree.directory": "โฟลเดอร์", + "builtWithStarlight.label": "ถูกสร้างขึ้นด้วย Starlight", + "heading.anchorLabel": "หัวข้อที่มีชื่อว่า “{{title}}”" +} diff --git a/packages/starlight/translations/tr.json b/packages/starlight/translations/tr.json index d288a163a24..9ea485734ec 100644 --- a/packages/starlight/translations/tr.json +++ b/packages/starlight/translations/tr.json @@ -1,7 +1,7 @@ { "skipLink.label": "İçeriğe geç", "search.label": "Ara", - "search.shortcutLabel": "(Aramak için / bas)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "İptal", "search.devWarning": "Arama yalnızca üretim derlemelerinde kullanılabilir. \nYerel bilgisayarınızda test etmek için siteyi derleyin ve önizleme yapın.", "themeSelect.accessibleLabel": "Tema seç", @@ -18,5 +18,13 @@ "page.lastUpdated": "Son güncelleme:", "page.previousLink": "Önceki", "page.nextLink": "Sonraki", - "404.text": "Sayfa bulunamadı. URL'i kontrol edin ya da arama çubuğunu kullanmayı deneyin." + "page.draft": "Bu içerik taslaktır ve canlı sürümde bulunmayacaktır.", + "404.text": "Sayfa bulunamadı. URL'i kontrol edin ya da arama çubuğunu kullanmayı deneyin.", + "aside.note": "Not", + "aside.tip": "İpucu", + "aside.caution": "Dikkat", + "aside.danger": "Tehlike", + "fileTree.directory": "Dizin", + "builtWithStarlight.label": "Built with Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" } diff --git a/packages/starlight/translations/uk.json b/packages/starlight/translations/uk.json new file mode 100644 index 00000000000..5bcbd924a8b --- /dev/null +++ b/packages/starlight/translations/uk.json @@ -0,0 +1,30 @@ +{ + "skipLink.label": "Перейти до вмісту", + "search.label": "Пошук", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "Скасувати", + "search.devWarning": "Пошук доступний лише у виробничих збірках. \nСпробуйте зібрати та переглянути сайт, щоби протестувати його локально", + "themeSelect.accessibleLabel": "Обрати тему", + "themeSelect.dark": "Темна", + "themeSelect.light": "Світла", + "themeSelect.auto": "Авто", + "languageSelect.accessibleLabel": "Обрати мову", + "menuButton.accessibleLabel": "Меню", + "sidebarNav.accessibleLabel": "Головне", + "tableOfContents.onThisPage": "На цій сторінці", + "tableOfContents.overview": "Огляд", + "i18n.untranslatedContent": "Цей контент ще не доступний вашою мовою.", + "page.editLink": "Редагувати сторінку", + "page.lastUpdated": "Останнє оновлення:", + "page.previousLink": "Назад", + "page.nextLink": "Далі", + "page.draft": "Цей контент є чернеткою і не буде включений до виробничих збірок.", + "404.text": "Сторінку не знайдено. Перевірте URL або спробуйте скористатися пошуком.", + "aside.note": "Заувага", + "aside.tip": "Порада", + "aside.caution": "Обережно", + "aside.danger": "Небезпечно", + "fileTree.directory": "Каталог", + "builtWithStarlight.label": "Створено з Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" +} diff --git a/packages/starlight/translations/vi.json b/packages/starlight/translations/vi.json new file mode 100644 index 00000000000..44e3f10efa7 --- /dev/null +++ b/packages/starlight/translations/vi.json @@ -0,0 +1,30 @@ +{ + "skipLink.label": "Bỏ qua để đến nội dung", + "search.label": "Tìm kiếm", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "Hủy", + "search.devWarning": "Chức năng tìm kiếm chỉ có sẵn trong các phiên bản thật.\nHãy thử xây dựng và xem trước trang web để kiểm tra.", + "themeSelect.accessibleLabel": "Chọn giao diện", + "themeSelect.dark": "Tối", + "themeSelect.light": "Sáng", + "themeSelect.auto": "Tự động", + "languageSelect.accessibleLabel": "Chọn ngôn ngữ", + "menuButton.accessibleLabel": "Menu", + "sidebarNav.accessibleLabel": "Chính", + "tableOfContents.onThisPage": "Trên trang này", + "tableOfContents.overview": "Tổng quan", + "i18n.untranslatedContent": "Nội dung này hiện chưa có sẵn bằng ngôn ngữ của bạn.", + "page.editLink": "Chỉnh sửa trang", + "page.lastUpdated": "Cập nhật lần cuối:", + "page.previousLink": "Trước", + "page.nextLink": "Tiếp", + "page.draft": "Nội dung này là bản nháp và sẽ không được đưa vào các phiên bản thật.", + "404.text": "Không tìm thấy trang. Hãy kiểm tra lại URL hoặc thử dùng thanh tìm kiếm.", + "aside.note": "Ghi chú", + "aside.tip": "Mẹo", + "aside.caution": "Chú ý", + "aside.danger": "Nguy hiểm", + "fileTree.directory": "Thư mục", + "builtWithStarlight.label": "Được xây dựng bằng Starlight", + "heading.anchorLabel": "Phần tiêu đề “{{title}}”" +} diff --git a/packages/starlight/translations/zh.json b/packages/starlight/translations/zh-CN.json similarity index 65% rename from packages/starlight/translations/zh.json rename to packages/starlight/translations/zh-CN.json index 367f63fc6b9..17c0f4e98f3 100644 --- a/packages/starlight/translations/zh.json +++ b/packages/starlight/translations/zh-CN.json @@ -1,7 +1,7 @@ { "skipLink.label": "跳转到内容", "search.label": "搜索", - "search.shortcutLabel": "(按 / 进行搜索)", + "search.ctrlKey": "Ctrl", "search.cancelLabel": "取消", "search.devWarning": "搜索仅适用于生产版本。\n尝试构建并预览网站以在本地测试。", "themeSelect.accessibleLabel": "选择主题", @@ -11,12 +11,20 @@ "languageSelect.accessibleLabel": "选择语言", "menuButton.accessibleLabel": "菜单", "sidebarNav.accessibleLabel": "主要", - "tableOfContents.onThisPage": "本页", + "tableOfContents.onThisPage": "本页内容", "tableOfContents.overview": "概述", "i18n.untranslatedContent": "此内容尚不支持你的语言。", "page.editLink": "编辑此页", "page.lastUpdated": "最近更新:", "page.previousLink": "上一页", "page.nextLink": "下一页", - "404.text": "页面未找到。检查 URL 或尝试使用搜索栏。" + "page.draft": "此内容为草稿,不会包含在生产版本中。", + "404.text": "页面未找到。检查 URL 或尝试使用搜索栏。", + "aside.note": "注意", + "aside.tip": "提示", + "aside.caution": "警告", + "aside.danger": "危险", + "fileTree.directory": "文件夹", + "builtWithStarlight.label": "基于 Starlight 构建", + "heading.anchorLabel": "Section titled “{{title}}”" } diff --git a/packages/starlight/translations/zh-TW.json b/packages/starlight/translations/zh-TW.json new file mode 100644 index 00000000000..001e1d77fe1 --- /dev/null +++ b/packages/starlight/translations/zh-TW.json @@ -0,0 +1,30 @@ +{ + "skipLink.label": "跳到內容", + "search.label": "搜尋", + "search.ctrlKey": "Ctrl", + "search.cancelLabel": "取消", + "search.devWarning": "正式版本才能使用搜尋功能。\n如要在本地測試,請先建置並預覽網站。", + "themeSelect.accessibleLabel": "選擇佈景主題", + "themeSelect.dark": "深色", + "themeSelect.light": "淺色", + "themeSelect.auto": "自動", + "languageSelect.accessibleLabel": "選擇語言", + "menuButton.accessibleLabel": "選單", + "sidebarNav.accessibleLabel": "主要", + "tableOfContents.onThisPage": "本頁內容", + "tableOfContents.overview": "概述", + "i18n.untranslatedContent": "本頁內容尚未翻譯。", + "page.editLink": "編輯頁面", + "page.lastUpdated": "最後更新於:", + "page.previousLink": "前一則", + "page.nextLink": "下一則", + "page.draft": "This content is a draft and will not be included in production builds.", + "404.text": "找不到頁面。請檢查網址或改用搜尋功能。", + "aside.note": "注意", + "aside.tip": "提示", + "aside.caution": "警告", + "aside.danger": "危險", + "fileTree.directory": "目錄", + "builtWithStarlight.label": "Built with Starlight", + "heading.anchorLabel": "Section titled “{{title}}”" +} diff --git a/packages/starlight/types.ts b/packages/starlight/types.ts index 8d99451e515..c549ca8afd9 100644 --- a/packages/starlight/types.ts +++ b/packages/starlight/types.ts @@ -1 +1,7 @@ export type { StarlightConfig } from './utils/user-config'; +export type { + StarlightPlugin, + StarlightUserConfigWithPlugins as StarlightUserConfig, + HookParameters, +} from './utils/plugins'; +export type { StarlightIcon } from './components/Icons'; diff --git a/packages/starlight/user-components/Aside.astro b/packages/starlight/user-components/Aside.astro new file mode 100644 index 00000000000..1c01bca6cd7 --- /dev/null +++ b/packages/starlight/user-components/Aside.astro @@ -0,0 +1,40 @@ +--- +import { AstroError } from 'astro/errors'; +import Icon from './Icon.astro'; +import { Icons, type StarlightIcon } from '../components/Icons'; +import { throwInvalidAsideIconError } from '../integrations/asides-error'; + +const asideVariants = ['note', 'tip', 'caution', 'danger'] as const; +const icons = { note: 'information', tip: 'rocket', caution: 'warning', danger: 'error' } as const; + +interface Props { + type?: (typeof asideVariants)[number]; + title?: string; + icon?: StarlightIcon; +} + +let { type = 'note', title, icon } = Astro.props; + +if (!asideVariants.includes(type)) { + throw new AstroError( + 'Invalid `type` prop passed to the `<Aside>` component.\n', + `Received: ${JSON.stringify(type)}\n` + + `Expected one of ${asideVariants.map((i) => JSON.stringify(i)).join(', ')}` + ); +} + +if (icon && !Icons[icon]) throwInvalidAsideIconError(icon); + +if (!title) { + title = Astro.locals.t(`aside.${type}`); +} +--- + +<aside aria-label={title} class={`starlight-aside starlight-aside--${type}`}> + <p class="starlight-aside__title" aria-hidden="true"> + <Icon name={icon || icons[type]} class="starlight-aside__icon" />{title} + </p> + <div class="starlight-aside__content"> + <slot /> + </div> +</aside> diff --git a/packages/starlight/user-components/Badge.astro b/packages/starlight/user-components/Badge.astro new file mode 100644 index 00000000000..f39080b0b02 --- /dev/null +++ b/packages/starlight/user-components/Badge.astro @@ -0,0 +1,148 @@ +--- +import { BadgeComponentSchema, type BadgeComponentProps } from '../schemas/badge'; +import { parseWithFriendlyErrors } from '../utils/error-map'; +import type { HTMLAttributes } from 'astro/types'; + +type Props = BadgeComponentProps & HTMLAttributes<'span'>; + +const { + text, + variant, + size, + class: customClass, + ...attrs +} = parseWithFriendlyErrors( + BadgeComponentSchema, + Astro.props, + 'Invalid prop passed to the `<Badge/>` component.' +); + +/** + * The fragment around the element is used as a workaround to avoid a trailing whitespace in the output. + * @see https://github.com/withastro/compiler/issues/1003 + */ +--- + +<><span class:list={['sl-badge', variant, size, customClass]} {...attrs}>{text}</span></> + +<style> + @layer starlight.components { + :global(:root) { + --sl-badge-default-border: var(--sl-color-accent); + --sl-badge-default-bg: var(--sl-color-accent-low); + --sl-badge-default-text: #fff; + + --sl-badge-note-border: var(--sl-color-blue); + --sl-badge-note-bg: var(--sl-color-blue-low); + --sl-badge-note-text: #fff; + + --sl-badge-danger-border: var(--sl-color-red); + --sl-badge-danger-bg: var(--sl-color-red-low); + --sl-badge-danger-text: #fff; + + --sl-badge-success-border: var(--sl-color-green); + --sl-badge-success-bg: var(--sl-color-green-low); + --sl-badge-success-text: #fff; + + --sl-badge-caution-border: var(--sl-color-orange); + --sl-badge-caution-bg: var(--sl-color-orange-low); + --sl-badge-caution-text: #fff; + + --sl-badge-tip-border: var(--sl-color-purple); + --sl-badge-tip-bg: var(--sl-color-purple-low); + --sl-badge-tip-text: #fff; + } + + :global([data-theme='light']:root) { + --sl-badge-default-bg: var(--sl-color-accent-high); + --sl-badge-note-bg: var(--sl-color-blue-high); + --sl-badge-danger-bg: var(--sl-color-red-high); + --sl-badge-success-bg: var(--sl-color-green-high); + --sl-badge-caution-bg: var(--sl-color-orange-high); + --sl-badge-tip-bg: var(--sl-color-purple-high); + } + + .sl-badge { + display: inline-block; + border: 1px solid var(--sl-color-border-badge); + border-radius: 0.25rem; + font-family: var(--sl-font-system-mono); + line-height: normal; + color: var(--sl-color-text-badge); + background-color: var(--sl-color-bg-badge); + overflow-wrap: anywhere; + } + + /* Sidebar overrides */ + :global(.sidebar-content) .sl-badge { + line-height: 1; + font-size: var(--sl-text-xs); + padding: 0.125rem 0.375rem; + } + + /* outline variant */ + :global(.sidebar-content a[aria-current='page']) > .sl-badge { + --sl-color-bg-badge: transparent; + --sl-color-border-badge: currentColor; + color: inherit; + } + + /* Color variants */ + .default { + --sl-color-bg-badge: var(--sl-badge-default-bg); + --sl-color-border-badge: var(--sl-badge-default-border); + --sl-color-text-badge: var(--sl-badge-default-text); + } + + .note { + --sl-color-bg-badge: var(--sl-badge-note-bg); + --sl-color-border-badge: var(--sl-badge-note-border); + --sl-color-text-badge: var(--sl-badge-note-text); + } + + .danger { + --sl-color-bg-badge: var(--sl-badge-danger-bg); + --sl-color-border-badge: var(--sl-badge-danger-border); + --sl-color-text-badge: var(--sl-badge-danger-text); + } + + .success { + --sl-color-bg-badge: var(--sl-badge-success-bg); + --sl-color-border-badge: var(--sl-badge-success-border); + --sl-color-text-badge: var(--sl-badge-success-text); + } + + .tip { + --sl-color-bg-badge: var(--sl-badge-tip-bg); + --sl-color-border-badge: var(--sl-badge-tip-border); + --sl-color-text-badge: var(--sl-badge-tip-text); + } + + .caution { + --sl-color-bg-badge: var(--sl-badge-caution-bg); + --sl-color-border-badge: var(--sl-badge-caution-border); + --sl-color-text-badge: var(--sl-badge-caution-text); + } + + /* Size variants */ + .small { + font-size: var(--sl-text-xs); + padding: 0.125rem 0.25rem; + } + + .medium { + font-size: var(--sl-text-sm); + padding: 0.175rem 0.35rem; + } + + .large { + font-size: var(--sl-text-base); + padding: 0.225rem 0.45rem; + } + + /* Badge in headings */ + :global(.sl-markdown-content :is(h1, h2, h3, h4, h5, h6)) .sl-badge { + vertical-align: middle; + } + } +</style> diff --git a/packages/starlight/user-components/Card.astro b/packages/starlight/user-components/Card.astro index 6b95e5bf88d..224db05b960 100644 --- a/packages/starlight/user-components/Card.astro +++ b/packages/starlight/user-components/Card.astro @@ -1,9 +1,9 @@ --- import Icon from './Icon.astro'; -import type { Icons } from '../components/Icons'; +import type { StarlightIcon } from '../components/Icons'; interface Props { - icon?: keyof typeof Icons; + icon?: StarlightIcon; title: string; } @@ -19,47 +19,50 @@ const { icon, title } = Astro.props; </article> <style> - .card { - --sl-card-border: var(--sl-color-purple); - --sl-card-bg: var(--sl-color-purple-low); - border: 1px solid var(--sl-color-gray-5); - background-color: var(--sl-color-black); - padding: clamp(1rem, calc(0.125rem + 3vw), 2.5rem); - flex-direction: column; - gap: clamp(0.5rem, calc(0.125rem + 1vw), 1rem); - } - .card:nth-child(4n + 1) { - --sl-card-border: var(--sl-color-orange); - --sl-card-bg: var(--sl-color-orange-low); - } - .card:nth-child(4n + 3) { - --sl-card-border: var(--sl-color-green); - --sl-card-bg: var(--sl-color-green-low); - } - .card:nth-child(4n + 4) { - --sl-card-border: var(--sl-color-red); - --sl-card-bg: var(--sl-color-red-low); - } - .card:nth-child(4n + 5) { - --sl-card-border: var(--sl-color-blue); - --sl-card-bg: var(--sl-color-blue-low); - } - .title { - font-weight: 600; - font-size: var(--sl-text-h4); - color: var(--sl-color-white); - line-height: var(--sl-line-height-headings); - gap: 1rem; - align-items: center; - } - .card .icon { - border: 1px solid var(--sl-card-border); - background-color: var(--sl-card-bg); - padding: 0.2em; - border-radius: 0.25rem; - } - .card .body { - margin: 0; - font-size: clamp(var(--sl-text-sm), calc(0.5rem + 1vw), var(--sl-text-body)); + @layer starlight.components { + .card { + --sl-card-border: var(--sl-color-purple); + --sl-card-bg: var(--sl-color-purple-low); + border: 1px solid var(--sl-color-gray-5); + background-color: var(--sl-color-black); + padding: clamp(1rem, calc(0.125rem + 3vw), 2.5rem); + flex-direction: column; + gap: clamp(0.5rem, calc(0.125rem + 1vw), 1rem); + } + .card:nth-child(4n + 1) { + --sl-card-border: var(--sl-color-orange); + --sl-card-bg: var(--sl-color-orange-low); + } + .card:nth-child(4n + 3) { + --sl-card-border: var(--sl-color-green); + --sl-card-bg: var(--sl-color-green-low); + } + .card:nth-child(4n + 4) { + --sl-card-border: var(--sl-color-red); + --sl-card-bg: var(--sl-color-red-low); + } + .card:nth-child(4n + 5) { + --sl-card-border: var(--sl-color-blue); + --sl-card-bg: var(--sl-color-blue-low); + } + .title { + font-weight: 600; + font-size: var(--sl-text-h4); + color: var(--sl-color-white); + line-height: var(--sl-line-height-headings); + gap: 1rem; + align-items: center; + } + .card .icon { + border: 1px solid var(--sl-card-border); + background-color: var(--sl-card-bg); + padding: 0.2em; + border-radius: 0.25rem; + flex-shrink: 0; + } + .card .body { + margin: 0; + font-size: clamp(var(--sl-text-sm), calc(0.5rem + 1vw), var(--sl-text-body)); + } } </style> diff --git a/packages/starlight/user-components/CardGrid.astro b/packages/starlight/user-components/CardGrid.astro index df05287e49c..dba872ee43b 100644 --- a/packages/starlight/user-components/CardGrid.astro +++ b/packages/starlight/user-components/CardGrid.astro @@ -9,27 +9,30 @@ const { stagger = false } = Astro.props; <div class:list={['card-grid', { stagger }]}><slot /></div> <style> - .card-grid { - display: grid; - gap: 1rem; - } - - .card-grid > :global(*) { - margin-top: 0 !important; - } - - @media (min-width: 50rem) { + @layer starlight.components { .card-grid { - grid-template-columns: 1fr 1fr; - gap: 1.5rem; + display: grid; + grid-template-columns: 100%; + gap: 1rem; } - .stagger { - --stagger-height: 5rem; - padding-bottom: var(--stagger-height); + + .card-grid > :global(*) { + margin-top: 0 !important; } - .stagger > :global(*):nth-child(2n) { - transform: translateY(var(--stagger-height)); + @media (min-width: 50rem) { + .card-grid { + grid-template-columns: 1fr 1fr; + gap: 1.5rem; + } + .stagger { + --stagger-height: 5rem; + padding-bottom: var(--stagger-height); + } + + .stagger > :global(*):nth-child(2n) { + transform: translateY(var(--stagger-height)); + } } } </style> diff --git a/packages/starlight/user-components/FileTree.astro b/packages/starlight/user-components/FileTree.astro new file mode 100644 index 00000000000..2bd532d66da --- /dev/null +++ b/packages/starlight/user-components/FileTree.astro @@ -0,0 +1,137 @@ +--- +import { processFileTree } from './rehype-file-tree'; + +const fileTreeHtml = await Astro.slots.render('default'); +const html = processFileTree(fileTreeHtml, Astro.locals.t('fileTree.directory')); +--- + +<starlight-file-tree set:html={html} class="not-content" data-pagefind-ignore /> + +<style> + @layer starlight.components { + starlight-file-tree { + --x-space: 1.5rem; + --y-space: 0.125rem; + --y-pad: 0; + + display: block; + border: 1px solid var(--sl-color-gray-5); + padding: 1rem; + background-color: var(--sl-color-gray-6); + font-size: var(--sl-text-xs); + font-family: var(--__sl-font-mono); + overflow-x: auto; + } + + starlight-file-tree :global(.directory > details) { + border: 0; + padding: 0; + padding-inline-start: var(--x-space); + background: transparent; + } + + starlight-file-tree :global(.directory > details > summary) { + margin-inline-start: calc(-1 * var(--x-space)); + border: 0; + padding: var(--y-pad) 0.625rem; + font-weight: normal; + color: var(--sl-color-white); + max-width: 100%; + } + + starlight-file-tree :global(.directory > details > summary::marker), + starlight-file-tree :global(.directory > details > summary::-webkit-details-marker) { + color: var(--sl-color-gray-3); + } + + starlight-file-tree :global(.directory > details > summary:hover), + starlight-file-tree :global(.directory > details > summary:hover .tree-icon) { + cursor: pointer; + color: var(--sl-color-text-accent); + fill: currentColor; + } + + starlight-file-tree :global(.directory > details > summary:hover ~ ul) { + border-color: var(--sl-color-gray-4); + } + + starlight-file-tree :global(.directory > details > summary:hover .highlight .tree-icon) { + color: var(--sl-color-text-invert); + fill: currentColor; + } + + starlight-file-tree :global(ul) { + margin-inline-start: 0.5rem; + border-inline-start: 1px solid var(--sl-color-gray-5); + padding: 0; + padding-inline-start: 0.125rem; + list-style: none; + } + + starlight-file-tree > :global(ul) { + margin: 0; + border: 0; + padding: 0; + } + + starlight-file-tree :global(li) { + margin: var(--y-space) 0; + padding: var(--y-pad) 0; + } + + starlight-file-tree :global(.file) { + margin-inline-start: calc(var(--x-space) - 0.125rem); + color: var(--sl-color-white); + } + + starlight-file-tree :global(.tree-entry) { + display: inline-flex; + align-items: flex-start; + flex-wrap: wrap; + max-width: calc(100% - 1rem); + } + + @media (min-width: 30em) { + starlight-file-tree :global(.tree-entry) { + flex-wrap: nowrap; + } + } + + starlight-file-tree :global(.tree-entry > :first-child) { + flex-shrink: 0; + } + + starlight-file-tree :global(.empty) { + color: var(--sl-color-gray-3); + padding-inline-start: 0.375rem; + } + + starlight-file-tree :global(.comment) { + color: var(--sl-color-gray-3); + padding-inline-start: 1.625rem; + max-width: 24rem; + min-width: 12rem; + } + + starlight-file-tree :global(.highlight) { + display: inline-block; + border-radius: 0.25rem; + padding-inline-end: 0.5rem; + color: var(--sl-color-text-invert); + background-color: var(--sl-color-text-accent); + } + + starlight-file-tree :global(svg) { + display: inline; + fill: var(--sl-color-gray-3); + vertical-align: middle; + margin-inline: 0.25rem 0.375rem; + width: 0.875rem; + height: 0.875rem; + } + + starlight-file-tree :global(.highlight svg.tree-icon) { + fill: currentColor; + } + } +</style> diff --git a/packages/starlight/user-components/Icon.astro b/packages/starlight/user-components/Icon.astro index 7575cc78702..16b24dee591 100644 --- a/packages/starlight/user-components/Icon.astro +++ b/packages/starlight/user-components/Icon.astro @@ -1,8 +1,8 @@ --- -import { Icons } from '../components/Icons'; +import { Icons, type StarlightIcon } from '../components/Icons'; interface Props { - name: keyof typeof Icons; + name: StarlightIcon; label?: string; color?: string; size?: string; @@ -11,23 +11,32 @@ interface Props { const { name, label, size = '1em', color } = Astro.props; const a11yAttrs = label ? ({ 'aria-label': label } as const) : ({ 'aria-hidden': 'true' } as const); + +/** + * The fragment around the element is used as a workaround to avoid a trailing whitespace in the output. + * @see https://github.com/withastro/compiler/issues/1003 + */ --- -<svg - {...a11yAttrs} - class={Astro.props.class} - width="16" - height="16" - viewBox="0 0 24 24" - fill="currentColor" - set:html={Icons[name]} -/> +<> + <svg + {...a11yAttrs} + class={Astro.props.class} + width="16" + height="16" + viewBox="0 0 24 24" + fill="currentColor" + set:html={Icons[name]} + /> +</> <style define:vars={{ 'sl-icon-color': color, 'sl-icon-size': size }}> - svg { - color: var(--sl-icon-color); - font-size: var(--sl-icon-size, 1em); - width: 1em; - height: 1em; + @layer starlight.components { + svg { + color: var(--sl-icon-color); + font-size: var(--sl-icon-size, 1em); + width: 1em; + height: 1em; + } } </style> diff --git a/packages/starlight/user-components/LinkButton.astro b/packages/starlight/user-components/LinkButton.astro new file mode 100644 index 00000000000..6480c92f36c --- /dev/null +++ b/packages/starlight/user-components/LinkButton.astro @@ -0,0 +1,78 @@ +--- +import type { HTMLAttributes } from 'astro/types'; +import type { StarlightIcon } from '../components/Icons'; +import Icon from './Icon.astro'; + +interface Props extends Omit<HTMLAttributes<'a'>, 'href'> { + href: string | URL; + icon?: StarlightIcon | undefined; + iconPlacement?: 'start' | 'end' | undefined; + variant?: 'primary' | 'secondary' | 'minimal'; +} + +const { + class: className, + icon, + iconPlacement = 'end', + variant = 'primary', + ...attrs +} = Astro.props; +--- + +<a class:list={['sl-link-button not-content', variant, className]} {...attrs}> + {icon && iconPlacement === 'start' && <Icon name={icon} size="1.5rem" />} + <slot /> + {icon && iconPlacement === 'end' && <Icon name={icon} size="1.5rem" />} +</a> + +<style> + @layer starlight.components { + .sl-link-button { + align-items: center; + border: 1px solid transparent; + border-radius: 999rem; + display: inline-flex; + font-size: var(--sl-text-sm); + gap: 0.5em; + line-height: 1.1875; + outline-offset: 0.25rem; + padding: 0.4375rem 1.125rem; + text-decoration: none; + } + + .sl-link-button.primary { + background: var(--sl-color-text-accent); + border-color: var(--sl-color-text-accent); + color: var(--sl-color-black); + } + .sl-link-button.primary:hover { + color: var(--sl-color-black); + } + .sl-link-button.secondary { + border-color: inherit; + color: var(--sl-color-white); + } + .sl-link-button.minimal { + color: var(--sl-color-white); + padding-inline: 0; + } + + .sl-link-button :global(svg) { + flex-shrink: 0; + } + + @media (min-width: 50rem) { + .sl-link-button { + font-size: var(--sl-text-base); + padding: 0.9375rem 1.25rem; + } + } + + :global(.sl-markdown-content) .sl-link-button { + margin-inline-end: 1rem; + } + :global(.sl-markdown-content) .sl-link-button:not(:where(p *)) { + margin-block: 1rem; + } + } +</style> diff --git a/packages/starlight/user-components/LinkCard.astro b/packages/starlight/user-components/LinkCard.astro index aecbe572118..b53b9c64a9f 100644 --- a/packages/starlight/user-components/LinkCard.astro +++ b/packages/starlight/user-components/LinkCard.astro @@ -10,7 +10,7 @@ interface Props extends Omit<HTMLAttributes<'a'>, 'title'> { const { title, description, ...attributes } = Astro.props; --- -<div> +<div class="sl-link-card"> <span class="sl-flex stack"> <a {...attributes}> <span class="title" set:html={title} /> @@ -21,56 +21,58 @@ const { title, description, ...attributes } = Astro.props; </div> <style> - div { - display: grid; - grid-template-columns: 1fr auto; - gap: 0.5rem; - border: 1px solid var(--sl-color-gray-5); - border-radius: 0.5rem; - padding: 1rem; - box-shadow: var(--sl-shadow-sm); - position: relative; - } + @layer starlight.components { + .sl-link-card { + display: grid; + grid-template-columns: 1fr auto; + gap: 0.5rem; + border: 1px solid var(--sl-color-gray-5); + border-radius: 0.5rem; + padding: 1rem; + box-shadow: var(--sl-shadow-sm); + position: relative; + } - a { - text-decoration: none; - } + a { + text-decoration: none; + line-height: var(--sl-line-height-headings); + } - /* a11y fix for https://github.com/withastro/starlight/issues/487 */ - a::before { - content: ''; - position: absolute; - inset: 0; - } + /* a11y fix for https://github.com/withastro/starlight/issues/487 */ + a::before { + content: ''; + position: absolute; + inset: 0; + } - .stack { - flex-direction: column; - gap: 0.5rem; - } + .stack { + flex-direction: column; + gap: 0.5rem; + } - .title { - color: var(--sl-color-white); - font-weight: 600; - font-size: var(--sl-text-lg); - line-height: var(--sl-line-height-headings); - } + .title { + color: var(--sl-color-white); + font-weight: 600; + font-size: var(--sl-text-lg); + } - .description { - color: var(--sl-color-gray-3); - line-height: 1.5; - } + .description { + color: var(--sl-color-gray-3); + line-height: 1.5; + } - .icon { - color: var(--sl-color-gray-3); - } + .icon { + color: var(--sl-color-gray-3); + } - /* Hover state */ - div:hover { - background: var(--sl-color-gray-7, var(--sl-color-gray-6)); - border-color: var(--sl-color-gray-2); - } + /* Hover state */ + .sl-link-card:hover { + background: var(--sl-color-gray-7, var(--sl-color-gray-6)); + border-color: var(--sl-color-gray-2); + } - div:hover .icon { - color: var(--sl-color-white); + .sl-link-card:hover .icon { + color: var(--sl-color-white); + } } </style> diff --git a/packages/starlight/user-components/Steps.astro b/packages/starlight/user-components/Steps.astro new file mode 100644 index 00000000000..bd193e73d5f --- /dev/null +++ b/packages/starlight/user-components/Steps.astro @@ -0,0 +1,90 @@ +--- +import { processSteps } from './rehype-steps'; + +const content = await Astro.slots.render('default'); +const { html } = processSteps(content); +--- + +<Fragment set:html={html} /> + +<style is:global> + @layer starlight.components { + .sl-steps { + --bullet-size: calc(var(--sl-line-height) * 1rem); + --bullet-margin: 0.375rem; + + list-style: none; + counter-reset: steps-counter var(--sl-steps-start, 0); + padding-inline-start: 0; + } + + .sl-steps > li { + counter-increment: steps-counter; + position: relative; + padding-inline-start: calc(var(--bullet-size) + 1rem); + /* HACK: Keeps any `margin-bottom` inside the `<li>`’s padding box to avoid gaps in the hairline border. */ + padding-bottom: 1px; + /* Prevent bullets from touching in short list items. */ + min-height: calc(var(--bullet-size) + var(--bullet-margin)); + } + .sl-steps > li + li { + /* Remove margin between steps. */ + margin-top: 0; + } + + /* Custom list marker element. */ + .sl-steps > li::before { + content: counter(steps-counter); + position: absolute; + top: 0; + inset-inline-start: 0; + width: var(--bullet-size); + height: var(--bullet-size); + line-height: var(--bullet-size); + + font-size: var(--sl-text-xs); + font-weight: 600; + text-align: center; + color: var(--sl-color-white); + background-color: var(--sl-color-gray-6); + border-radius: 99rem; + box-shadow: inset 0 0 0 1px var(--sl-color-gray-5); + } + + /* Vertical guideline linking list numbers. */ + .sl-steps > li::after { + --guide-width: 1px; + content: ''; + position: absolute; + top: calc(var(--bullet-size) + var(--bullet-margin)); + bottom: var(--bullet-margin); + inset-inline-start: calc((var(--bullet-size) - var(--guide-width)) / 2); + width: var(--guide-width); + background-color: var(--sl-color-hairline-light); + } + } + + @layer starlight.content { + /* Adjust first item inside a step so that it aligns vertically with the number + even if using a larger font size (e.g. a heading) */ + .sl-steps > li > :first-child { + /* + The `lh` unit is not yet supported by all browsers in our support matrix + — see https://caniuse.com/mdn-css_types_length_lh + In unsupported browsers we approximate this using our known line-heights. + */ + --lh: calc(1em * var(--sl-line-height)); + --shift-y: calc(0.5 * (var(--bullet-size) - var(--lh))); + transform: translateY(var(--shift-y)); + margin-bottom: var(--shift-y); + } + .sl-steps > li > :first-child:where(h1, h2, h3, h4, h5, h6) { + --lh: calc(1em * var(--sl-line-height-headings)); + } + @supports (--prop: 1lh) { + .sl-steps > li > :first-child { + --lh: 1lh; + } + } + } +</style> diff --git a/packages/starlight/user-components/TabItem.astro b/packages/starlight/user-components/TabItem.astro index bc08c86e64d..0bd9fa6df54 100644 --- a/packages/starlight/user-components/TabItem.astro +++ b/packages/starlight/user-components/TabItem.astro @@ -1,17 +1,19 @@ --- import { TabItemTagname } from './rehype-tabs'; +import type { StarlightIcon } from '../components/Icons'; interface Props { + icon?: StarlightIcon; label: string; } -const { label } = Astro.props; +const { icon, label } = Astro.props; if (!label) { throw new Error('Missing prop `label` on `<TabItem>` component.'); } --- -<TabItemTagname data-label={label}> +<TabItemTagname data-label={label} data-icon={icon}> <slot /> </TabItemTagname> diff --git a/packages/starlight/user-components/Tabs.astro b/packages/starlight/user-components/Tabs.astro index 82b3af179dd..66f1b2e9e8d 100644 --- a/packages/starlight/user-components/Tabs.astro +++ b/packages/starlight/user-components/Tabs.astro @@ -1,24 +1,90 @@ --- +import Icon from './Icon.astro'; import { processPanels } from './rehype-tabs'; +interface Props { + syncKey?: string; +} + +const { syncKey } = Astro.props; const panelHtml = await Astro.slots.render('default'); const { html, panels } = processPanels(panelHtml); + +/** + * Synced tabs are persisted across page using `localStorage`. The script used to restore the + * active tab for a given sync key has a few requirements: + * + * - The script should only be included when at least one set of synced tabs is present on the page. + * - The script should be inlined to avoid a flash of invalid active tab. + * - The script should only be included once per page. + * + * To do so, we keep track of whether the script has been rendered using a variable stored using + * `Astro.locals` which will be reset for each new page. The value is tracked using an untyped + * symbol on purpose to avoid Starlight users to get autocomplete for it and avoid potential + * clashes with user-defined variables. + * + * The restore script defines a custom element `starlight-tabs-restore` that will be included in + * each set of synced tabs to restore the active tab based on the persisted value using the + * `connectedCallback` lifecycle method. To ensure this callback can access all tabs and panels for + * the current set of tabs, the script should be rendered before the tabs themselves. + */ +const isSynced = syncKey !== undefined; +const didRenderSyncedTabsRestoreScriptSymbol = Symbol.for('starlight:did-render-synced-tabs-restore-script'); +// @ts-expect-error - See above +const shouldRenderSyncedTabsRestoreScript = isSynced && Astro.locals[didRenderSyncedTabsRestoreScriptSymbol] !== true; + +if (isSynced) { + // @ts-expect-error - See above + Astro.locals[didRenderSyncedTabsRestoreScriptSymbol] = true +} --- -<starlight-tabs> +{/* Inlined to avoid a flash of invalid active tab. */} +{shouldRenderSyncedTabsRestoreScript && <script is:inline> +(() => { + class StarlightTabsRestore extends HTMLElement { + connectedCallback() { + const starlightTabs = this.closest('starlight-tabs'); + if (!(starlightTabs instanceof HTMLElement) || typeof localStorage === 'undefined') return; + const syncKey = starlightTabs.dataset.syncKey; + if (!syncKey) return; + const label = localStorage.getItem(`starlight-synced-tabs__${syncKey}`); + if (!label) return; + const tabs = [...starlightTabs?.querySelectorAll('[role="tab"]')]; + const tabIndexToRestore = tabs.findIndex( + (tab) => tab instanceof HTMLAnchorElement && tab.textContent?.trim() === label + ); + const panels = starlightTabs?.querySelectorAll(':scope > [role="tabpanel"]'); + const newTab = tabs[tabIndexToRestore]; + const newPanel = panels[tabIndexToRestore]; + if (tabIndexToRestore < 1 || !newTab || !newPanel) return; + tabs[0]?.setAttribute('aria-selected', 'false'); + tabs[0]?.setAttribute('tabindex', '-1'); + panels?.[0]?.setAttribute('hidden', 'true'); + newTab.removeAttribute('tabindex'); + newTab.setAttribute('aria-selected', 'true'); + newPanel.removeAttribute('hidden'); + } + } + customElements.define('starlight-tabs-restore', StarlightTabsRestore); +})() +</script>} + +<starlight-tabs data-sync-key={syncKey}> { panels && ( <div class="tablist-wrapper not-content"> <ul role="tablist"> - {panels.map(({ label, panelId, tabId }, idx) => ( + {panels.map(({ icon, label, panelId, tabId }, idx) => ( <li role="presentation" class="tab"> <a role="tab" href={'#' + panelId} id={tabId} - aria-selected={idx === 0 && 'true'} + aria-selected={idx === 0 ? 'true' : 'false'} tabindex={idx !== 0 ? -1 : 0} > + {icon && <Icon name={icon} />} {label} </a> </li> @@ -28,62 +94,83 @@ const { html, panels } = processPanels(panelHtml); ) } <Fragment set:html={html} /> + {isSynced && <starlight-tabs-restore />} </starlight-tabs> <style> - starlight-tabs { - display: block; - } + @layer starlight.components { + starlight-tabs { + display: block; + } - .tablist-wrapper { - overflow-x: auto; - } + .tablist-wrapper { + overflow-x: auto; + } - [role='tablist'] { - display: flex; - list-style: none; - border-bottom: 2px solid var(--sl-color-gray-5); - padding: 0; - } + [role='tablist'] { + display: flex; + list-style: none; + border-bottom: 2px solid var(--sl-color-gray-5); + padding: 0; + } - .tab { - margin-bottom: -2px; - } - .tab > [role='tab'] { - display: block; - padding: 0 1.25rem; - text-decoration: none; - border-bottom: 2px solid var(--sl-color-gray-5); - color: var(--sl-color-gray-3); - outline-offset: var(--sl-outline-offset-inside); - } - .tab [role='tab'][aria-selected] { - color: var(--sl-color-white); - border-color: var(--sl-color-text-accent); - font-weight: 600; - } + .tab { + display: flex; + } + .tab > [role='tab'] { + --sl-tab-color-border: var(--sl-color-gray-5); + display: flex; + align-items: center; + gap: 0.5rem; + line-height: var(--sl-line-height-headings); + padding: 0.275rem 1.25rem; + text-decoration: none; + box-shadow: 0 2px 0 var(--sl-tab-color-border); + color: var(--sl-color-gray-3); + outline-offset: var(--sl-outline-offset-inside); + overflow-wrap: initial; + } + .tab [role='tab'][aria-selected='true'] { + --sl-tab-color-border: var(--sl-color-text-accent); + color: var(--sl-color-white); + font-weight: 600; + } - .tablist-wrapper ~ :global([role='tabpanel']) { - margin-top: 1rem; + .tablist-wrapper ~ :global([role='tabpanel']) { + margin-top: 1rem; + } } </style> <script> class StarlightTabs extends HTMLElement { + // A map of sync keys to all tabs that are synced to that key. + static #syncedTabs = new Map<string, StarlightTabs[]>(); + tabs: HTMLAnchorElement[]; panels: HTMLElement[]; + #syncKey: string | undefined; + // The storage key prefix should be in sync with the one used in the restore script. + #storageKeyPrefix = 'starlight-synced-tabs__'; constructor() { super(); const tablist = this.querySelector<HTMLUListElement>('[role="tablist"]')!; this.tabs = [...tablist.querySelectorAll<HTMLAnchorElement>('[role="tab"]')]; this.panels = [...this.querySelectorAll<HTMLElement>(':scope > [role="tabpanel"]')]; + this.#syncKey = this.dataset.syncKey; + + if (this.#syncKey) { + const syncedTabs = StarlightTabs.#syncedTabs.get(this.#syncKey) ?? []; + syncedTabs.push(this); + StarlightTabs.#syncedTabs.set(this.#syncKey, syncedTabs); + } this.tabs.forEach((tab, i) => { // Handle clicks for mouse users tab.addEventListener('click', (e) => { e.preventDefault(); - const currentTab = tablist.querySelector('[aria-selected]'); + const currentTab = tablist.querySelector('[aria-selected="true"]'); if (e.currentTarget !== currentTab) { this.switchTab(e.currentTarget as HTMLAnchorElement, i); } @@ -98,12 +185,12 @@ const { html, panels } = processPanels(panelHtml); e.key === 'ArrowLeft' ? index - 1 : e.key === 'ArrowRight' - ? index + 1 - : e.key === 'Home' - ? 0 - : e.key === 'End' - ? this.tabs.length - 1 - : null; + ? index + 1 + : e.key === 'Home' + ? 0 + : e.key === 'End' + ? this.tabs.length - 1 + : null; if (nextIndex === null) return; if (this.tabs[nextIndex]) { e.preventDefault(); @@ -113,12 +200,17 @@ const { html, panels } = processPanels(panelHtml); }); } - switchTab(newTab: HTMLAnchorElement | null | undefined, index: number) { + switchTab(newTab: HTMLAnchorElement | null | undefined, index: number, shouldSync = true) { if (!newTab) return; + // If tabs should be synced, we store the current position so we can restore it after + // switching tabs to prevent the page from jumping when the new tab content is of a different + // height than the previous tab. + const previousTabsOffset = shouldSync ? this.getBoundingClientRect().top : 0; + // Mark all tabs as unselected and hide all tab panels. this.tabs.forEach((tab) => { - tab.removeAttribute('aria-selected'); + tab.setAttribute('aria-selected', 'false'); tab.setAttribute('tabindex', '-1'); }); this.panels.forEach((oldPanel) => { @@ -131,7 +223,44 @@ const { html, panels } = processPanels(panelHtml); // Restore active tab to the default tab order. newTab.removeAttribute('tabindex'); newTab.setAttribute('aria-selected', 'true'); - newTab.focus(); + if (shouldSync) { + newTab.focus(); + StarlightTabs.#syncTabs(this, newTab); + window.scrollTo({ + top: window.scrollY + (this.getBoundingClientRect().top - previousTabsOffset), + behavior: 'instant', + }); + } + } + + #persistSyncedTabs(label: string) { + if (!this.#syncKey || typeof localStorage === 'undefined') return; + localStorage.setItem(this.#storageKeyPrefix + this.#syncKey, label); + } + + static #syncTabs(emitter: StarlightTabs, newTab: HTMLAnchorElement) { + const syncKey = emitter.#syncKey; + const label = StarlightTabs.#getTabLabel(newTab); + if (!syncKey || !label) return; + const syncedTabs = StarlightTabs.#syncedTabs.get(syncKey); + if (!syncedTabs) return; + + for (const receiver of syncedTabs) { + if (receiver === emitter) continue; + const labelIndex = receiver.tabs.findIndex((tab) => StarlightTabs.#getTabLabel(tab) === label); + if (labelIndex === -1) continue; + receiver.switchTab(receiver.tabs[labelIndex], labelIndex, false); + } + + emitter.#persistSyncedTabs(label); + } + + static #getTabLabel(tab: HTMLAnchorElement) { + // `textContent` returns the content of all elements. In the case of a tab with an icon, this + // could potentially include extra spaces due to the presence of the SVG icon. + // To sync tabs with the same sync key and label, no matter the presence of an icon, we trim + // these extra spaces. + return tab.textContent?.trim(); } } diff --git a/packages/starlight/user-components/file-tree-icons.ts b/packages/starlight/user-components/file-tree-icons.ts new file mode 100644 index 00000000000..2afc8b6cb7d --- /dev/null +++ b/packages/starlight/user-components/file-tree-icons.ts @@ -0,0 +1,782 @@ +/** + * This file was generated by the `file-icons-generator` package. + * Do not edit this file directly as it will be overwritten. + */ + +import type { Definitions } from './rehype-file-tree.ts'; + +/** + * Based on https://github.com/elviswolcott/seti-icons which + * is derived from https://github.com/jesseweed/seti-ui/ + * + * Copyright (c) 2014 Jesse Weed + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +export const definitions: Definitions = { + files: { + 'astro.config.js': 'astro', + 'astro.config.mjs': 'astro', + 'astro.config.cjs': 'astro', + 'astro.config.ts': 'astro', + 'pnpm-debug.log': 'pnpm', + 'pnpm-lock.yaml': 'pnpm', + 'pnpm-workspace.yaml': 'pnpm', + 'biome.json': 'biome', + 'bun.lockb': 'bun', + COMMIT_EDITMSG: 'seti:git', + MERGE_MSG: 'seti:git', + 'karma.conf.js': 'seti:karma', + 'karma.conf.cjs': 'seti:karma', + 'karma.conf.mjs': 'seti:karma', + 'karma.conf.coffee': 'seti:karma', + 'README.md': 'seti:info', + 'README.txt': 'seti:info', + README: 'seti:info', + 'CHANGELOG.md': 'seti:clock', + 'CHANGELOG.txt': 'seti:clock', + CHANGELOG: 'seti:clock', + 'CHANGES.md': 'seti:clock', + 'CHANGES.txt': 'seti:clock', + CHANGES: 'seti:clock', + 'VERSION.md': 'seti:clock', + 'VERSION.txt': 'seti:clock', + VERSION: 'seti:clock', + mvnw: 'seti:maven', + 'pom.xml': 'seti:maven', + 'tsconfig.json': 'seti:tsconfig', + 'vite.config.js': 'seti:vite', + 'vite.config.ts': 'seti:vite', + 'vite.config.mjs': 'seti:vite', + 'vite.config.mts': 'seti:vite', + 'vite.config.cjs': 'seti:vite', + 'vite.config.cts': 'seti:vite', + 'swagger.json': 'seti:json', + 'swagger.yml': 'seti:json', + 'swagger.yaml': 'seti:json', + 'mime.types': 'seti:config', + Jenkinsfile: 'seti:jenkins', + 'babel.config.js': 'seti:babel', + 'babel.config.json': 'seti:babel', + 'babel.config.cjs': 'seti:babel', + BUILD: 'seti:bazel', + 'BUILD.bazel': 'seti:bazel', + WORKSPACE: 'seti:bazel', + 'WORKSPACE.bazel': 'seti:bazel', + 'bower.json': 'seti:bower', + 'Bower.json': 'seti:bower', + 'eslint.config.js': 'seti:eslint', + 'firebase.json': 'seti:firebase', + geckodriver: 'seti:firefox', + 'Gruntfile.js': 'seti:grunt', + 'gruntfile.babel.js': 'seti:grunt', + 'Gruntfile.babel.js': 'seti:grunt', + 'gruntfile.js': 'seti:grunt', + 'Gruntfile.coffee': 'seti:grunt', + 'gruntfile.coffee': 'seti:grunt', + 'ionic.config.json': 'seti:ionic', + 'Ionic.config.json': 'seti:ionic', + 'ionic.project': 'seti:ionic', + 'Ionic.project': 'seti:ionic', + 'platformio.ini': 'seti:platformio', + 'rollup.config.js': 'seti:rollup', + 'sass-lint.yml': 'seti:sass', + 'stylelint.config.js': 'seti:stylelint', + 'stylelint.config.cjs': 'seti:stylelint', + 'stylelint.config.mjs': 'seti:stylelint', + 'yarn.clean': 'seti:yarn', + 'yarn.lock': 'seti:yarn', + 'webpack.config.js': 'seti:webpack', + 'webpack.config.cjs': 'seti:webpack', + 'webpack.config.mjs': 'seti:webpack', + 'webpack.config.ts': 'seti:webpack', + 'webpack.config.build.js': 'seti:webpack', + 'webpack.config.build.cjs': 'seti:webpack', + 'webpack.config.build.mjs': 'seti:webpack', + 'webpack.config.build.ts': 'seti:webpack', + 'webpack.common.js': 'seti:webpack', + 'webpack.common.cjs': 'seti:webpack', + 'webpack.common.mjs': 'seti:webpack', + 'webpack.common.ts': 'seti:webpack', + 'webpack.dev.js': 'seti:webpack', + 'webpack.dev.cjs': 'seti:webpack', + 'webpack.dev.mjs': 'seti:webpack', + 'webpack.dev.ts': 'seti:webpack', + 'webpack.prod.js': 'seti:webpack', + 'webpack.prod.cjs': 'seti:webpack', + 'webpack.prod.mjs': 'seti:webpack', + 'webpack.prod.ts': 'seti:webpack', + 'npm-debug.log': 'seti:npm_ignored', + }, + extensions: { + '.astro': 'astro', + '.mdx': 'mdx', + '.pkl': 'pkl', + '.bsl': 'seti:bsl', + '.mdo': 'seti:mdo', + '.cls': 'seti:salesforce', + '.apex': 'seti:salesforce', + '.asm': 'seti:asm', + '.s': 'seti:asm', + '.bicep': 'seti:bicep', + '.bzl': 'seti:bazel', + '.bazel': 'seti:bazel', + '.BUILD': 'seti:bazel', + '.WORKSPACE': 'seti:bazel', + '.bazelignore': 'seti:bazel', + '.bazelversion': 'seti:bazel', + '.c': 'seti:c', + '.h': 'seti:c', + '.m': 'seti:c', + '.cs': 'seti:c-sharp', + '.cshtml': 'seti:html', + '.aspx': 'seti:html', + '.ascx': 'seti:html', + '.asax': 'seti:html', + '.master': 'seti:html', + '.cc': 'seti:cpp', + '.cpp': 'seti:cpp', + '.cxx': 'seti:cpp', + '.c++': 'seti:cpp', + '.hh': 'seti:cpp', + '.hpp': 'seti:cpp', + '.hxx': 'seti:cpp', + '.h++': 'seti:cpp', + '.mm': 'seti:cpp', + '.clj': 'seti:clojure', + '.cljs': 'seti:clojure', + '.cljc': 'seti:clojure', + '.edn': 'seti:clojure', + '.cfc': 'seti:coldfusion', + '.cfm': 'seti:coldfusion', + '.coffee': 'seti:cjsx', + '.litcoffee': 'seti:cjsx', + '.config': 'seti:config', + '.cfg': 'seti:config', + '.conf': 'seti:config', + '.cr': 'seti:crystal', + '.ecr': 'seti:crystal_embedded', + '.slang': 'seti:crystal_embedded', + '.cson': 'seti:json', + '.css': 'seti:css', + '.css.map': 'seti:css', + '.sss': 'seti:css', + '.csv': 'seti:csv', + '.xls': 'seti:xls', + '.xlsx': 'seti:xls', + '.cu': 'seti:cu', + '.cuh': 'seti:cu', + '.hu': 'seti:cu', + '.cake': 'seti:cake', + '.ctp': 'seti:cake_php', + '.d': 'seti:d', + '.doc': 'seti:word', + '.docx': 'seti:word', + '.ejs': 'seti:ejs', + '.ex': 'seti:elixir', + '.exs': 'seti:elixir_script', + '.elm': 'seti:elm', + '.ico': 'seti:favicon', + '.fs': 'seti:f-sharp', + '.fsx': 'seti:f-sharp', + '.gitignore': 'seti:git', + '.gitconfig': 'seti:git', + '.gitkeep': 'seti:git', + '.gitattributes': 'seti:git', + '.gitmodules': 'seti:git', + '.go': 'seti:go', + '.slide': 'seti:go', + '.article': 'seti:go', + '.gd': 'seti:godot', + '.godot': 'seti:godot', + '.tres': 'seti:godot', + '.tscn': 'seti:godot', + '.gradle': 'seti:gradle', + '.groovy': 'seti:grails', + '.gsp': 'seti:grails', + '.gql': 'seti:graphql', + '.graphql': 'seti:graphql', + '.graphqls': 'seti:graphql', + '.hack': 'seti:hacklang', + '.haml': 'seti:haml', + '.handlebars': 'seti:mustache', + '.hbs': 'seti:mustache', + '.hjs': 'seti:mustache', + '.hs': 'seti:haskell', + '.lhs': 'seti:haskell', + '.hx': 'seti:haxe', + '.hxs': 'seti:haxe', + '.hxp': 'seti:haxe', + '.hxml': 'seti:haxe', + '.html': 'seti:html', + '.jade': 'seti:jade', + '.java': 'seti:java', + '.class': 'seti:java', + '.classpath': 'seti:java', + '.properties': 'seti:java', + '.js': 'seti:javascript', + '.js.map': 'seti:javascript', + '.cjs': 'seti:javascript', + '.cjs.map': 'seti:javascript', + '.mjs': 'seti:javascript', + '.mjs.map': 'seti:javascript', + '.spec.js': 'seti:javascript', + '.spec.cjs': 'seti:javascript', + '.spec.mjs': 'seti:javascript', + '.test.js': 'seti:javascript', + '.test.cjs': 'seti:javascript', + '.test.mjs': 'seti:javascript', + '.es': 'seti:javascript', + '.es5': 'seti:javascript', + '.es6': 'seti:javascript', + '.es7': 'seti:javascript', + '.jinja': 'seti:jinja', + '.jinja2': 'seti:jinja', + '.json': 'seti:json', + '.jl': 'seti:julia', + '.kt': 'seti:kotlin', + '.kts': 'seti:kotlin', + '.dart': 'seti:dart', + '.less': 'seti:json', + '.liquid': 'seti:liquid', + '.ls': 'seti:livescript', + '.lua': 'seti:lua', + '.markdown': 'seti:markdown', + '.md': 'seti:markdown', + '.argdown': 'seti:argdown', + '.ad': 'seti:argdown', + '.mustache': 'seti:mustache', + '.stache': 'seti:mustache', + '.nim': 'seti:nim', + '.nims': 'seti:nim', + '.github-issues': 'seti:github', + '.ipynb': 'seti:notebook', + '.njk': 'seti:nunjucks', + '.nunjucks': 'seti:nunjucks', + '.nunjs': 'seti:nunjucks', + '.nunj': 'seti:nunjucks', + '.njs': 'seti:nunjucks', + '.nj': 'seti:nunjucks', + '.npm-debug.log': 'seti:npm', + '.npmignore': 'seti:npm', + '.npmrc': 'seti:npm', + '.ml': 'seti:ocaml', + '.mli': 'seti:ocaml', + '.cmx': 'seti:ocaml', + '.cmxa': 'seti:ocaml', + '.odata': 'seti:odata', + '.pl': 'seti:perl', + '.php': 'seti:php', + '.php.inc': 'seti:php', + '.pipeline': 'seti:pipeline', + '.pddl': 'seti:pddl', + '.plan': 'seti:plan', + '.happenings': 'seti:happenings', + '.ps1': 'seti:powershell', + '.psd1': 'seti:powershell', + '.psm1': 'seti:powershell', + '.prisma': 'seti:prisma', + '.pug': 'seti:pug', + '.pp': 'seti:puppet', + '.epp': 'seti:puppet', + '.purs': 'seti:purescript', + '.py': 'seti:python', + '.jsx': 'seti:react', + '.spec.jsx': 'seti:react', + '.test.jsx': 'seti:react', + '.cjsx': 'seti:react', + '.tsx': 'seti:react', + '.spec.tsx': 'seti:react', + '.test.tsx': 'seti:react', + '.res': 'seti:rescript', + '.resi': 'seti:rescript', + '.R': 'seti:R', + '.rmd': 'seti:R', + '.rb': 'seti:ruby', + '.erb': 'seti:html', + '.erb.html': 'seti:html', + '.html.erb': 'seti:html', + '.rs': 'seti:rust', + '.sass': 'seti:sass', + '.scss': 'seti:sass', + '.springBeans': 'seti:spring', + '.slim': 'seti:slim', + '.smarty.tpl': 'seti:smarty', + '.tpl': 'seti:smarty', + '.sbt': 'seti:sbt', + '.scala': 'seti:scala', + '.sol': 'seti:ethereum', + '.styl': 'seti:stylus', + '.svelte': 'seti:svelte', + '.swift': 'seti:swift', + '.sql': 'seti:db', + '.soql': 'seti:db', + '.tf': 'seti:terraform', + '.tf.json': 'seti:terraform', + '.tfvars': 'seti:terraform', + '.tfvars.json': 'seti:terraform', + '.tex': 'seti:tex', + '.sty': 'seti:tex', + '.dtx': 'seti:tex', + '.ins': 'seti:tex', + '.txt': 'seti:default', + '.toml': 'seti:config', + '.twig': 'seti:twig', + '.ts': 'seti:typescript', + '.spec.ts': 'seti:typescript', + '.test.ts': 'seti:typescript', + '.vala': 'seti:vala', + '.vapi': 'seti:vala', + '.component': 'seti:html', + '.vue': 'seti:vue', + '.wasm': 'seti:wasm', + '.wat': 'seti:wat', + '.xml': 'seti:xml', + '.yml': 'seti:yml', + '.yaml': 'seti:yml', + '.pro': 'seti:prolog', + '.zig': 'seti:zig', + '.jar': 'seti:zip', + '.zip': 'seti:zip', + '.wgt': 'seti:wgt', + '.ai': 'seti:illustrator', + '.psd': 'seti:photoshop', + '.pdf': 'seti:pdf', + '.eot': 'seti:font', + '.ttf': 'seti:font', + '.woff': 'seti:font', + '.woff2': 'seti:font', + '.otf': 'seti:font', + '.avif': 'seti:image', + '.gif': 'seti:image', + '.jpg': 'seti:image', + '.jpeg': 'seti:image', + '.png': 'seti:image', + '.pxm': 'seti:image', + '.svg': 'seti:svg', + '.svgx': 'seti:image', + '.tiff': 'seti:image', + '.webp': 'seti:image', + '.sublime-project': 'seti:sublime', + '.sublime-workspace': 'seti:sublime', + '.code-search': 'seti:code-search', + '.sh': 'seti:shell', + '.zsh': 'seti:shell', + '.fish': 'seti:shell', + '.zshrc': 'seti:shell', + '.bashrc': 'seti:shell', + '.mov': 'seti:video', + '.ogv': 'seti:video', + '.webm': 'seti:video', + '.avi': 'seti:video', + '.mpg': 'seti:video', + '.mp4': 'seti:video', + '.mp3': 'seti:audio', + '.ogg': 'seti:audio', + '.wav': 'seti:audio', + '.flac': 'seti:audio', + '.3ds': 'seti:svg', + '.3dm': 'seti:svg', + '.stl': 'seti:svg', + '.obj': 'seti:svg', + '.dae': 'seti:svg', + '.bat': 'seti:windows', + '.cmd': 'seti:windows', + '.babelrc': 'seti:babel', + '.babelrc.js': 'seti:babel', + '.babelrc.cjs': 'seti:babel', + '.bazelrc': 'seti:bazel', + '.bowerrc': 'seti:bower', + '.codeclimate.yml': 'seti:code-climate', + '.eslintrc': 'seti:eslint', + '.eslintrc.js': 'seti:eslint', + '.eslintrc.cjs': 'seti:eslint', + '.eslintrc.yaml': 'seti:eslint', + '.eslintrc.yml': 'seti:eslint', + '.eslintrc.json': 'seti:eslint', + '.eslintignore': 'seti:eslint', + '.firebaserc': 'seti:firebase', + '.gitlab-ci.yml': 'seti:gitlab', + '.jshintrc': 'seti:javascript', + '.jscsrc': 'seti:javascript', + '.stylelintrc': 'seti:stylelint', + '.stylelintrc.json': 'seti:stylelint', + '.stylelintrc.yaml': 'seti:stylelint', + '.stylelintrc.yml': 'seti:stylelint', + '.stylelintrc.js': 'seti:stylelint', + '.stylelintignore': 'seti:stylelint', + '.direnv': 'seti:config', + '.env': 'seti:config', + '.static': 'seti:config', + '.editorconfig': 'seti:config', + '.slugignore': 'seti:config', + '.tmp': 'seti:clock', + '.htaccess': 'seti:config', + '.key': 'seti:lock', + '.cert': 'seti:lock', + '.cer': 'seti:lock', + '.crt': 'seti:lock', + '.pem': 'seti:lock', + '.DS_Store': 'seti:ignored', + }, + partials: { + mix: 'seti:hex', + Gemfile: 'seti:ruby', + gemfile: 'seti:ruby', + dockerfile: 'seti:docker', + Dockerfile: 'seti:docker', + DOCKERFILE: 'seti:docker', + '.dockerignore': 'seti:docker', + 'docker-healthcheck': 'seti:docker', + 'docker-compose.yml': 'seti:docker', + 'docker-compose.yaml': 'seti:docker', + 'docker-compose.override.yml': 'seti:docker', + 'docker-compose.override.yaml': 'seti:docker', + GULPFILE: 'seti:gulp', + Gulpfile: 'seti:gulp', + gulpfile: 'seti:gulp', + 'gulpfile.js': 'seti:gulp', + LICENSE: 'seti:license', + LICENCE: 'seti:license', + 'LICENSE.txt': 'seti:license', + 'LICENCE.txt': 'seti:license', + 'LICENSE.md': 'seti:license', + 'LICENCE.md': 'seti:license', + COPYING: 'seti:license', + 'COPYING.txt': 'seti:license', + 'COPYING.md': 'seti:license', + COMPILING: 'seti:license', + 'COMPILING.txt': 'seti:license', + 'COMPILING.md': 'seti:license', + CONTRIBUTING: 'seti:license', + 'CONTRIBUTING.txt': 'seti:license', + 'CONTRIBUTING.md': 'seti:license', + MAKEFILE: 'seti:makefile', + Makefile: 'seti:makefile', + makefile: 'seti:makefile', + QMAKEFILE: 'seti:makefile', + QMakefile: 'seti:makefile', + qmakefile: 'seti:makefile', + OMAKEFILE: 'seti:makefile', + OMakefile: 'seti:makefile', + omakefile: 'seti:makefile', + 'CMAKELISTS.TXT': 'seti:makefile', + 'CMAKELISTS.txt': 'seti:makefile', + 'CMakeLists.txt': 'seti:makefile', + 'cmakelists.txt': 'seti:makefile', + Procfile: 'seti:heroku', + TODO: 'seti:todo', + 'TODO.txt': 'seti:todo', + 'TODO.md': 'seti:todo', + }, +}; + +export const FileIcons = { + 'seti:folder': + '<path d="M22.073 4.900L22.073 4.900L12.148 4.900L12.148 3.950Q12.148 3.125 11.585 2.563Q11.023 2 10.198 2L10.198 2L0.048 2L0.048 22L23.948 22L23.948 6.850Q23.998 6.025 23.448 5.462Q22.898 4.900 22.073 4.900Z"/>', + 'seti:bsl': + '<path d="M23.696 15.213L12.850 15.213L12.850 18.375L23.696 18.375L23.696 15.213ZM2.446 18.375L2.446 5.625L5.642 5.625L5.642 18.375L2.446 18.375ZM0.304 9.875L0.304 6.713L2.446 6.713L2.446 9.875L0.304 9.875ZM9.892 12.017L9.892 12.017Q9.892 10.657 10.793 9.739Q11.694 8.821 13.054 8.821L13.054 8.821Q14.108 8.821 14.907 9.416Q15.706 10.011 16.046 10.963L16.046 10.963L19.344 10.963Q19.072 9.467 18.188 8.260Q17.304 7.053 15.961 6.339Q14.618 5.625 13.054 5.625L13.054 5.625Q11.354 5.625 9.875 6.492Q8.396 7.359 7.546 8.821Q6.696 10.283 6.696 12.017Q6.696 13.751 7.546 15.213Q8.396 16.675 9.875 17.525Q11.354 18.375 13.071 18.375Q14.788 18.375 16.284 17.508Q17.780 16.641 18.596 15.213L18.596 15.213L13.054 15.213Q11.694 15.213 10.793 14.295Q9.892 13.377 9.892 12.017Z"/>', + 'seti:mdo': + '<path d="M14.375 14.128L14.375 14.014Q13.463 14.014 12.836 13.387Q12.209 12.760 12.209 11.867Q12.209 10.974 12.836 10.366Q13.463 9.758 14.375 9.758L14.375 9.758Q14.983 9.758 15.553 10.100Q16.123 10.442 16.389 11.050L16.389 11.050L18.175 11.050Q17.795 9.720 16.750 8.903Q15.705 8.086 14.375 8.086L14.375 8.086Q13.311 8.086 12.399 8.618Q11.487 9.150 10.955 10.043Q10.423 10.936 10.423 12Q10.423 13.064 10.955 13.957Q11.487 14.850 12.399 15.382Q13.311 15.914 14.375 15.914L14.375 15.914L19.923 15.914L19.923 14.128L14.375 14.128ZM7.839 15.800L7.839 8.086L9.625 8.086L9.625 15.800L7.839 15.800ZM6.167 11.164L6.167 9.378L7.953 9.378L7.953 11.164L6.167 11.164ZM20.189 3.792L20.189 3.792L4.153 3.792L0.125 12L2.139 16.066Q4.153 20.132 4.153 20.208L4.153 20.208L20.189 20.208Q21.671 20.208 22.773 19.125Q23.875 18.042 23.875 16.522L23.875 16.522L23.875 7.364Q23.875 5.920 22.811 4.856Q21.747 3.792 20.189 3.792ZM22.089 7.478L22.089 16.636Q22.089 17.396 21.557 17.909Q21.025 18.422 20.303 18.422L20.303 18.422L5.559 18.422L3.735 15.458Q1.873 12.456 1.873 12.228L1.873 12.228L5.559 5.692L20.303 5.692Q21.063 5.692 21.576 6.224Q22.089 6.756 22.089 7.478L22.089 7.478Z"/>', + 'seti:salesforce': + '<path d="M6.648 3.525L6.696 3.525Q8.232 3.765 9.240 4.581L9.240 4.581L9.528 4.869Q9.864 5.109 9.960 5.301L9.960 5.301L10.104 5.301Q10.248 5.157 10.560 4.941Q10.872 4.725 11.016 4.581L11.016 4.581L12.072 4.101Q12.360 4.101 12.696 3.957L12.696 3.957L13.560 3.957Q14.376 3.957 15.096 4.437L15.096 4.437Q16.104 5.061 16.728 6.069L16.728 6.069Q16.728 6.165 16.800 6.165Q16.872 6.165 16.872 6.069L16.872 6.069L17.160 5.973Q17.736 5.781 18.072 5.781L18.072 5.781L19.272 5.781Q20.040 5.781 21.240 6.357L21.240 6.357L21.576 6.597Q22.200 6.933 22.440 7.269L22.440 7.269Q23.016 7.893 23.496 8.757L23.496 8.757Q23.928 9.429 23.928 10.437L23.928 10.437L23.928 11.637Q23.928 12.117 23.736 12.645L23.736 12.645Q23.640 12.981 23.304 13.557L23.304 13.557Q22.872 14.469 22.104 15.237L22.104 15.237Q21.576 15.765 20.904 15.957L20.904 15.957L19.560 16.437L17.640 16.437Q17.400 16.869 16.776 17.445L16.776 17.445L16.440 17.781Q15.864 18.117 14.904 18.357L14.904 18.357L14.040 18.357Q13.656 18.357 13.080 18.165L13.080 18.165L12.840 18.069L12.696 18.069Q12.552 18.405 12.168 18.885L12.168 18.885L11.928 19.269Q11.496 19.941 10.728 20.181L10.728 20.181Q9.336 20.853 7.824 20.493Q6.312 20.133 5.304 18.837L5.304 18.837Q4.968 18.453 4.728 17.781L4.728 17.781Q4.728 17.685 4.632 17.733L4.632 17.733L4.584 17.781L3.528 17.781Q3.288 17.781 2.952 17.709Q2.616 17.637 2.472 17.637L2.472 17.637Q1.896 17.445 1.272 17.013L1.272 17.013Q0.360 16.149 0.072 15.525L0.072 15.525Q0.312 14.613 0.072 14.181L0.072 14.181L0.072 13.269Q0.072 12.693 0.360 12.093Q0.648 11.493 0.960 11.181Q1.272 10.869 1.272 10.725L1.272 10.725Q1.704 10.293 2.040 10.149L2.040 10.149L2.088 10.101Q2.136 10.053 2.040 9.957L2.040 9.957Q1.704 9.381 1.704 8.949L1.704 8.949L1.704 7.557Q1.944 5.877 3.168 4.677Q4.392 3.477 6.072 3.381L6.072 3.381L6.360 3.381Q6.504 3.525 6.648 3.525L6.648 3.525L6.648 3.525Z"/>', + 'seti:asm': + '<path d="M1.322 16.313L0.106 16.313L3.222 7.687L4.856 7.687L7.972 16.313L6.300 16.313L5.426 13.995L2.158 13.995L1.322 16.313ZM3.792 9.435L2.538 12.931L5.008 12.931L3.792 9.435ZM8.390 16.237L8.390 16.237L8.390 14.793Q10.214 15.401 11.240 15.401L11.240 15.401Q12.000 15.401 12.570 15.097L12.570 15.097Q12.836 14.907 12.950 14.717Q13.064 14.527 13.064 14.223L13.064 14.223Q13.064 13.767 12.798 13.539L12.798 13.539Q12.456 13.159 11.658 12.855L11.658 12.855L10.936 12.551Q9.758 11.943 8.960 11.221L8.960 11.221Q8.390 10.613 8.390 9.853L8.390 9.853Q8.390 8.713 9.340 8.143L9.340 8.143Q10.290 7.459 11.886 7.459L11.886 7.459Q13.330 7.459 14.622 7.763L14.622 7.763L14.622 9.131Q13.026 8.675 12.076 8.675L12.076 8.675Q11.392 8.675 10.936 8.903L10.936 8.903Q10.518 9.245 10.518 9.625Q10.518 10.005 10.822 10.233L10.822 10.233Q11.240 10.537 11.962 10.917L11.962 10.917L12.646 11.221Q14.128 11.943 14.698 12.551Q15.268 13.159 15.268 13.995L15.268 13.995Q15.268 14.603 15.002 15.097Q14.736 15.591 14.204 15.857L14.204 15.857Q13.254 16.541 11.316 16.541L11.316 16.541Q9.910 16.541 8.390 16.237ZM17.168 16.313L15.914 16.313L15.914 7.763L18.118 7.763L20.018 13.843L21.994 7.763L23.894 7.763L23.894 16.313L22.336 16.313L22.336 9.777L20.436 15.705L19.106 15.705L17.168 9.701L17.168 16.313Z"/>', + 'seti:bicep': + '<path d="M19.224 14.604L19.224 14.604L8.052 14.604L10.698 8.052L15.024 8.052L15.948 6.078L12 6.078L10.698 4.104L12 2.172L15.948 2.172L15.024 0.198L10.698 0.198L7.800 4.104L8.976 6.078L1.122 15.948Q0.702 16.452 0.450 17.166Q0.198 17.880 0.198 18.552L0.198 18.552Q0.198 20.022 1.143 21.156Q2.088 22.290 3.474 22.500L3.474 22.500L10.614 23.172Q18.006 23.802 19.224 23.802Q20.442 23.802 21.492 23.172Q22.542 22.542 23.172 21.492Q23.802 20.442 23.802 19.224Q23.802 18.006 23.172 16.935Q22.542 15.864 21.492 15.234Q20.442 14.604 19.224 14.604ZM4.146 20.526L4.146 20.526Q3.348 20.526 2.760 19.938Q2.172 19.350 2.172 18.552Q2.172 17.754 2.760 17.166Q3.348 16.578 4.125 16.578Q4.902 16.578 5.490 17.166Q6.078 17.754 6.078 18.552Q6.078 19.350 5.490 19.938Q4.902 20.526 4.146 20.526ZM19.224 21.828L19.224 21.828Q18.132 21.828 17.355 21.072Q16.578 20.316 16.578 19.224Q16.578 18.132 17.355 17.355Q18.132 16.578 19.224 16.578Q20.316 16.578 21.072 17.355Q21.828 18.132 21.828 19.224Q21.828 20.316 21.072 21.072Q20.316 21.828 19.224 21.828Z"/>', + 'seti:bazel': + '<path d="M0.198 6.078L6.078 0.198L12 6.078L17.922 0.198L23.802 6.078L23.802 12L12 23.802L0.198 12L0.198 6.078Z"/>', + 'seti:c': + '<path d="M21.330 17.405L21.330 22.152Q19.732 22.951 18.063 23.398Q16.395 23.844 14.562 23.844L14.562 23.844Q9.063 23.844 5.867 20.648Q2.671 17.452 2.671 12Q2.671 6.548 5.867 3.352Q9.063 0.156 14.562 0.156L14.562 0.156Q16.395 0.156 18.087 0.579Q19.779 1.002 21.330 1.848L21.330 1.848L21.330 6.595Q19.732 5.467 18.204 4.950Q16.677 4.433 15.031 4.433L15.031 4.433Q11.976 4.433 10.238 6.454Q8.499 8.475 8.499 12Q8.499 15.525 10.238 17.546Q11.976 19.567 15.031 19.567L15.031 19.567Q16.677 19.567 18.204 19.050Q19.732 18.533 21.330 17.405L21.330 17.405Z"/>', + 'seti:c-sharp': + '<path d="M0.261 11.937L0.261 11.937Q0.261 9.417 1.038 7.464Q1.815 5.511 3.117 4.209Q4.419 2.907 6.309 2.067L6.309 2.067Q7.779 1.437 10.089 1.437L10.089 1.437Q12.063 1.437 13.638 2.214Q15.213 2.991 16.263 4.041L16.263 4.041L13.365 7.317L13.029 7.065Q12.357 6.519 11.937 6.435L11.937 6.435L11.517 6.309Q10.677 6.015 10.089 6.015L10.089 6.015Q9.165 6.015 8.409 6.435L8.409 6.435Q7.485 6.855 6.939 7.590Q6.393 8.325 6.015 9.480Q5.637 10.635 5.637 11.937L5.637 11.937Q5.637 14.961 6.939 16.263L6.939 16.263Q7.653 17.061 8.472 17.460Q9.291 17.859 10.341 17.859Q11.391 17.859 12.189 17.439L12.189 17.439Q13.071 17.019 13.659 16.263L13.659 16.263L16.515 19.539Q15.297 20.925 13.659 21.765L13.659 21.765Q12.063 22.563 10.089 22.563L10.089 22.563Q8.283 22.563 6.309 21.891L6.309 21.891Q4.503 21.303 3.159 19.959L3.159 19.959Q2.529 19.329 2.025 18.321L2.025 18.321Q1.689 17.691 1.185 16.389L1.185 16.389Q0.261 14.751 0.261 11.937ZM19.203 15.129L19.539 13.491L18.237 13.491L17.733 16.641L16.137 16.641L16.683 13.491L15.087 13.491L15.087 12.063L17.061 12.063L17.313 9.963L15.633 9.963L15.633 8.535L17.565 8.535L18.111 5.385L19.665 5.385L19.161 8.535L20.463 8.535L21.009 5.385L22.563 5.385L22.059 8.535L23.739 8.535L23.739 9.963L21.639 9.963L21.387 12.063L23.109 12.063L23.109 13.491L21.009 13.491L20.463 16.641L18.909 16.641Q18.909 16.725 19.203 15.129L19.203 15.129ZM18.783 10.089L18.489 12.189L19.833 12.189L20.085 10.089L18.783 10.089Z"/>', + 'seti:html': + '<path d="M0 13.488L0 10.512L9.024 2.112L9.024 6L2.256 12L9.024 18L9.024 21.888L0 13.488ZM24 10.368L24 13.632L15.024 22.032L15.024 18L21.888 12L15.024 6L15.024 1.968L24 10.368Z"/>', + 'seti:cpp': + '<path d="M0.024 11.935L0.024 11.935Q0.024 9.398 0.841 7.377Q1.659 5.356 2.970 4.045Q4.282 2.733 6.216 1.873L6.216 1.873Q7.722 1.185 10.130 1.185L10.130 1.185Q12.151 1.185 13.763 2.002Q15.376 2.819 16.451 3.894L16.451 3.894L13.484 7.248L13.140 6.990Q12.409 6.431 12.021 6.302L12.021 6.302L11.549 6.173Q10.689 5.915 10.130 5.915L10.130 5.915Q9.184 5.915 8.367 6.302L8.367 6.302Q7.463 6.775 6.905 7.528Q6.346 8.280 5.959 9.441Q5.572 10.602 5.572 11.935L5.572 11.935Q5.572 15.031 6.905 16.364L6.905 16.364Q7.593 17.224 8.453 17.611Q9.313 17.998 10.387 17.998Q11.463 17.998 12.280 17.611L12.280 17.611Q13.183 17.138 13.742 16.364L13.742 16.364L16.709 19.761Q15.462 21.180 13.742 22.041L13.742 22.041Q12.151 22.814 10.130 22.814L10.130 22.814Q8.238 22.814 6.216 22.169L6.216 22.169Q4.411 21.567 2.992 20.148L2.992 20.148Q2.389 19.503 1.831 18.471L1.831 18.471Q1.530 17.869 0.970 16.537L0.970 16.537Q0.024 14.644 0.024 11.935ZM13.355 10.731L13.355 8.452L11.463 8.452L11.463 10.731L9.313 10.731L9.313 12.623L11.463 12.623L11.463 15.031L13.355 15.031L13.355 12.623L15.505 12.623L15.505 10.731L13.355 10.731ZM23.976 10.602L21.396 10.602L21.396 7.936L19.117 7.936L19.117 10.602L16.580 10.602L16.580 12.881L19.117 12.881L19.117 15.720L21.396 15.720L21.396 12.881L23.976 12.881L23.976 10.602Z"/>', + 'seti:clojure': + '<path d="M11.426 12.105L11.426 12.105L11.006 12.903Q9.998 14.919 9.830 16.179L9.830 16.179Q9.704 16.473 9.704 17.229L9.704 17.229L9.704 17.775Q10.670 18.153 11.804 18.153L11.804 18.153Q12.476 18.153 13.778 17.901L13.778 17.901L13.400 17.523Q12.896 16.683 12.434 15.339L12.434 15.339Q12.056 14.247 11.426 12.105ZM8.402 6.729L8.402 6.729Q7.184 7.653 6.470 8.997Q5.756 10.341 5.756 11.874Q5.756 13.407 6.470 14.730Q7.184 16.053 8.402 16.977L8.402 16.977Q8.570 16.263 8.990 15.339L8.990 15.339Q9.242 14.751 9.956 13.407L9.956 13.407Q10.712 11.895 11.132 10.929L11.132 10.929Q11.090 10.803 11.027 10.551Q10.964 10.299 10.880 10.173L10.880 10.173Q10.208 8.367 9.452 7.401L9.452 7.401Q8.864 7.191 8.402 6.729ZM17.432 19.077L17.432 19.077Q15.878 18.825 15.332 18.699L15.332 18.699Q13.778 19.455 12.056 19.455L12.056 19.455Q9.998 19.455 8.297 18.447Q6.596 17.439 5.588 15.717Q4.580 13.995 4.580 11.979L4.580 11.979Q4.580 10.383 5.294 8.871L5.294 8.871Q5.924 7.485 7.100 6.351L7.100 6.351Q6.680 6.225 5.756 6.225L5.756 6.225Q3.950 6.225 2.564 7.233L2.564 7.233Q1.010 8.409 0.254 10.803L0.254 10.803Q0.128 11.349 0.128 12.105L0.128 12.105Q0.128 15.339 1.703 18.048Q3.278 20.757 5.987 22.353Q8.696 23.949 11.930 23.949L11.930 23.949Q14.828 23.949 17.432 22.563L17.432 22.563Q19.952 21.261 21.632 18.951L21.632 18.951Q19.868 19.329 18.356 19.329L18.356 19.329Q17.978 19.077 17.432 19.077ZM11.930 0.051L11.930 0.051Q9.032 0.051 6.491 1.395Q3.950 2.739 2.354 5.049L2.354 5.049Q3.824 4.125 5.630 4.125L5.630 4.125Q6.512 4.125 7.436 4.335L7.436 4.335Q8.150 4.545 8.654 4.755L8.654 4.755Q8.738 4.839 8.864 4.902Q8.990 4.965 9.032 5.049L9.032 5.049Q10.586 4.377 12.056 4.377L12.056 4.377Q14.114 4.377 15.836 5.406Q17.558 6.435 18.545 8.136Q19.532 9.837 19.532 11.853L19.532 11.853Q19.532 14.793 17.306 17.229L17.306 17.229L18.356 17.229Q20.834 17.229 22.178 16.053L22.178 16.053Q23.396 15.087 23.732 13.323L23.732 13.323Q23.732 13.029 23.816 12.483L23.816 12.483Q23.900 12.063 23.858 11.853L23.858 11.853Q23.816 8.619 22.199 5.910Q20.582 3.201 17.936 1.647L17.936 1.647Q15.164 0.051 11.930 0.051Z"/>', + 'seti:coldfusion': + '<path d="M6.963 10.543L6.963 10.543Q6.808 10.543 6.560 10.512L6.560 10.512Q5.940 10.481 5.692 10.543L5.692 10.543L5.382 10.574Q3.925 10.760 3.305 10.977L3.305 10.977Q2.220 11.349 1.631 12.186L1.631 12.186Q0.577 13.519 0.407 14.945Q0.236 16.371 0.949 17.797L0.949 17.797Q2.313 20.556 5.692 20.711L5.692 20.711L9.567 20.711Q13.163 20.587 15.364 17.611L15.364 17.611Q16.542 16.154 17.131 14.418L17.131 14.418Q17.348 13.829 17.674 13.597Q17.999 13.364 18.588 13.364L18.588 13.364Q19.084 13.426 20.045 13.364L20.045 13.364L20.789 13.364Q21.130 13.364 21.254 13.302L21.254 13.302Q21.471 13.209 21.471 12.961L21.471 12.961L21.533 12.620Q21.626 11.969 21.626 11.659L21.626 11.659Q21.595 11.132 21.378 10.729L21.378 10.729Q21.254 10.481 20.975 10.419L20.975 10.419Q20.820 10.388 20.448 10.434Q20.076 10.481 19.921 10.450L19.921 10.450L19.456 10.450Q19.053 10.450 18.945 10.311Q18.836 10.171 18.960 9.768L18.960 9.768Q19.921 7.536 21.967 6.854L21.967 6.854Q22.122 6.792 22.510 6.761Q22.897 6.730 23.052 6.637L23.052 6.637Q23.331 6.544 23.424 6.296L23.424 6.296Q23.579 6.079 23.610 5.707L23.610 5.707Q23.641 5.490 23.610 4.994L23.610 4.994L23.610 3.754Q23.610 3.289 23.021 3.289L23.021 3.289Q21.471 3.444 20.386 3.878L20.386 3.878Q19.084 4.405 18.278 5.397L18.278 5.397Q17.410 6.575 16.635 8.001L16.635 8.001Q16.015 9.210 15.364 10.822L15.364 10.822L15.178 11.411Q14.558 13.054 14.217 13.829L14.217 13.829Q13.597 15.100 12.853 15.968L12.853 15.968Q11.954 17.022 10.621 17.332L10.621 17.332Q7.986 17.735 5.103 17.146L5.103 17.146Q4.390 16.991 4.018 16.526Q3.646 16.061 3.646 15.364Q3.646 14.666 4.080 14.170Q4.514 13.674 5.289 13.457L5.289 13.457Q5.878 13.333 7.025 13.302L7.025 13.302Q7.831 13.302 8.234 13.287Q8.637 13.271 8.808 13.101Q8.978 12.930 8.978 12.496L8.978 12.496L8.978 11.938Q8.978 11.070 8.947 10.853L8.947 10.853Q8.885 10.543 8.637 10.481L8.637 10.481Q8.482 10.419 7.800 10.450L7.800 10.450L7.056 10.450Q7.118 10.512 7.087 10.527Q7.056 10.543 6.963 10.543Z"/>', + 'seti:config': + '<path d="M23.165 13.645L23.165 13.645Q22.829 13.561 22.199 13.309L22.199 13.309L21.695 13.099Q21.695 12.637 21.632 11.797Q21.569 10.957 21.569 10.495L21.569 10.495Q21.569 10.411 21.632 10.348Q21.695 10.285 21.695 10.201L21.695 10.201L23.165 9.571Q23.543 9.361 23.669 9.004Q23.795 8.647 23.669 8.269L23.669 8.269L22.493 5.623Q22.283 5.203 21.926 5.056Q21.569 4.909 21.191 5.119L21.191 5.119L19.721 5.749Q19.469 5.749 19.469 5.623L19.469 5.623Q19.301 5.371 18.839 4.951L18.839 4.951L18.545 4.699Q18.419 4.573 18.104 4.300Q17.789 4.027 17.621 3.901L17.621 3.901Q17.789 3.649 17.978 3.124Q18.167 2.599 18.293 2.347L18.293 2.347Q18.503 1.843 18.314 1.465Q18.125 1.087 17.621 0.919L17.621 0.919Q17.075 0.793 15.815 0.373L15.815 0.373L15.143 0.121Q14.639-0.089 14.261 0.100Q13.883 0.289 13.715 0.751L13.715 0.751Q13.631 1.087 13.379 1.717L13.379 1.717L13.169 2.221Q12.707 2.221 11.867 2.284Q11.027 2.347 10.565 2.347L10.565 2.347Q10.481 2.347 10.418 2.284Q10.355 2.221 10.271 2.221L10.271 2.221L9.641 0.751Q9.431 0.373 9.074 0.247Q8.717 0.121 8.339 0.247L8.339 0.247L5.693 1.423Q5.273 1.633 5.126 1.990Q4.979 2.347 5.189 2.725L5.189 2.725L5.819 4.195Q5.819 4.447 5.693 4.447L5.693 4.447L5.399 4.699Q5.105 4.909 5.021 5.077L5.021 5.077Q4.853 5.287 4.517 5.686Q4.181 6.085 3.971 6.295L3.971 6.295Q3.677 6.211 3.047 5.959L3.047 5.959L2.543 5.749Q2.039 5.539 1.661 5.728Q1.283 5.917 1.115 6.421L1.115 6.421L0.905 6.925Q0.401 8.185 0.191 8.773Q-0.019 9.361 0.128 9.697Q0.275 10.033 0.821 10.201L0.821 10.201Q1.157 10.285 1.787 10.537L1.787 10.537L2.291 10.747Q2.291 11.209 2.354 12.049Q2.417 12.889 2.417 13.351L2.417 13.351Q2.417 13.435 2.354 13.498Q2.291 13.561 2.291 13.645L2.291 13.645L0.821 14.275Q0.443 14.485 0.317 14.842Q0.191 15.199 0.317 15.577L0.317 15.577L1.493 18.223Q1.703 18.643 2.060 18.790Q2.417 18.937 2.795 18.727L2.795 18.727L4.265 18.097Q4.517 18.097 4.517 18.223L4.517 18.223Q4.685 18.475 5.147 18.895L5.147 18.895L5.441 19.147Q5.567 19.273 5.882 19.525Q6.197 19.777 6.365 19.945L6.365 19.945Q6.239 20.197 6.029 20.722Q5.819 21.247 5.693 21.499L5.693 21.499Q5.483 22.003 5.672 22.381Q5.861 22.759 6.365 22.969L6.365 22.969Q6.659 23.053 7.331 23.305L7.331 23.305Q8.297 23.725 8.864 23.893Q9.431 24.061 9.767 23.935Q10.103 23.809 10.271 23.221L10.271 23.221Q10.355 22.885 10.607 22.255L10.607 22.255L10.817 21.751Q11.279 21.751 12.119 21.688Q12.959 21.625 13.421 21.625L13.421 21.625Q13.505 21.625 13.568 21.688Q13.631 21.751 13.715 21.751L13.715 21.751L14.345 23.221Q14.555 23.599 14.912 23.725Q15.269 23.851 15.647 23.725L15.647 23.725L18.293 22.549Q18.713 22.339 18.860 21.982Q19.007 21.625 18.797 21.247L18.797 21.247L18.167 19.819Q18.167 19.525 18.293 19.525L18.293 19.525Q18.545 19.357 18.965 18.895L18.965 18.895L19.217 18.601Q19.343 18.475 19.595 18.160Q19.847 17.845 20.015 17.719L20.015 17.719Q20.309 17.761 20.939 18.055L20.939 18.055L21.443 18.223Q21.947 18.433 22.325 18.244Q22.703 18.055 22.871 17.551L22.871 17.551Q22.997 17.257 23.249 16.585L23.249 16.585Q23.669 15.619 23.795 15.073L23.795 15.073Q24.257 13.981 23.165 13.645ZM13.967 16.375L13.967 16.375Q12.077 17.173 10.250 16.459Q8.423 15.745 7.541 13.897L7.541 13.897Q6.743 12.007 7.457 10.180Q8.171 8.353 10.019 7.471L10.019 7.471Q11.909 6.673 13.736 7.387Q15.563 8.101 16.445 9.949L16.445 9.949Q17.243 11.839 16.529 13.666Q15.815 15.493 13.967 16.375Z"/>', + 'seti:crystal': + '<path d="M17.084 3.165L12.000 0.220L6.916 3.165L1.801 6.110L1.801 17.890L12.000 23.780L22.199 17.890L22.199 6.110L17.084 3.165ZM12.000 11.938L9.334 16.557L6.668 11.938L4.002 7.319L14.666 7.319L12.000 11.938Z"/>', + 'seti:crystal_embedded': + '<path d="M17.084 3.165L12.000 0.220L6.916 3.165L1.801 6.110L1.801 17.890L12.000 23.780L22.199 17.890L22.199 6.110L17.084 3.165ZM11.411 15.596L10.140 16.867L4.653 12.248L10.140 7.660L11.411 8.931L7.381 12.248L11.411 15.596ZM12.620 8.931L13.860 7.660L19.347 12.248L13.860 16.867L12.620 15.596L16.619 12.279L12.620 8.931Z"/>', + 'seti:json': + '<path d="M0.734 13.269L0.562 10.732Q1.938 10.732 2.497 10.087L2.497 10.087Q2.884 9.614 2.884 8.711L2.884 8.711Q2.884 8.324 2.798 7.571Q2.712 6.819 2.712 6.410Q2.712 6.002 2.669 5.185L2.669 5.185Q2.583 4.454 2.583 4.153L2.583 4.153Q2.583 2.089 3.787 1.099Q4.991 0.111 7.184 0.111L7.184 0.111L8.259 0.111L8.259 2.648L7.700 2.648Q6.754 2.648 6.345 3.185Q5.937 3.723 5.937 4.798L5.937 4.798Q5.937 5.056 6.023 5.572L6.023 5.572Q6.109 6.217 6.109 6.561L6.109 6.561Q6.109 6.819 6.152 7.378L6.152 7.378Q6.238 8.152 6.238 8.582L6.238 8.582Q6.238 10.216 5.550 11.033L5.550 11.033Q4.948 11.764 3.658 12.065L3.658 12.065Q4.948 12.409 5.550 13.097L5.550 13.097Q6.238 13.957 6.238 15.548L6.238 15.548Q6.238 16.021 6.152 16.795L6.152 16.795Q6.066 17.354 6.088 17.612Q6.109 17.870 6.023 18.515L6.023 18.515Q5.937 18.988 5.937 19.203L5.937 19.203Q5.937 20.278 6.345 20.815Q6.754 21.353 7.700 21.353L7.700 21.353L8.259 21.353L8.259 23.890L7.184 23.890Q2.712 23.890 2.712 19.848L2.712 19.848Q2.712 18.386 2.862 17.590Q3.013 16.795 3.013 15.290L3.013 15.290Q3.013 13.269 0.734 13.269L0.734 13.269ZM23.438 10.732L23.438 13.011Q21.159 13.011 21.159 15.032L21.159 15.032Q21.159 15.419 21.224 16.171Q21.288 16.924 21.288 17.311L21.288 17.311Q21.417 18.128 21.417 19.590L21.417 19.590Q21.417 23.632 16.859 23.632L16.859 23.632L15.784 23.632L15.784 21.353L16.300 21.353Q17.246 21.353 17.654 20.815Q18.063 20.278 18.063 19.203Q18.063 18.128 17.934 17.569L17.934 17.569Q17.934 17.225 17.848 16.558Q17.762 15.892 17.762 15.548L17.762 15.548Q17.762 13.957 18.450 13.097L18.450 13.097Q19.052 12.409 20.342 12.065L20.342 12.065Q19.052 11.764 18.450 11.033L18.450 11.033Q17.762 10.216 17.762 8.582L17.762 8.582Q17.762 8.152 17.848 7.378L17.848 7.378Q17.934 6.819 17.934 6.561L17.934 6.561Q18.063 5.873 18.063 4.841Q18.063 3.809 17.633 3.293Q17.203 2.777 16.300 2.648L16.300 2.648L15.784 2.648L15.784 0.111L16.859 0.111Q19.009 0.111 20.213 1.099Q21.417 2.089 21.417 4.153L21.417 4.153Q21.417 4.540 21.352 5.292Q21.288 6.045 21.288 6.432L21.288 6.432Q21.159 7.249 21.116 8.711L21.116 8.711Q21.159 9.614 21.503 10.087L21.503 10.087Q22.062 10.732 23.438 10.732L23.438 10.732Z"/>', + 'seti:css': + '<path d="M7.486 23.628L2.845 23.628L4.120 17.253L0.142 17.253L0.142 13.887L4.936 13.887L5.701 9.909L1.570 9.909L1.570 6.594L6.517 6.594L7.792 0.372L12.229 0.372L10.954 6.594L15.442 6.594L16.717 0.372L21.154 0.372L19.880 6.594L23.858 6.594L23.858 9.909L19.267 9.909L18.299 13.887L22.429 13.887L22.429 17.253L17.686 17.253L16.412 23.628L11.924 23.628L13.198 17.253L8.761 17.253L7.486 23.628ZM9.373 13.938L13.861 13.938L14.627 9.909L10.189 9.909L9.373 13.938Z"/>', + 'seti:csv': + '<path d="M23.802 0.324L0.198 0.324L0.198 23.676L23.802 23.676L23.802 0.324ZM3.978 6.876L3.978 5.154L10.698 5.154L10.698 6.876L3.978 6.876ZM13.176 6.876L13.176 5.154L19.896 5.154L19.896 6.876L13.176 6.876ZM3.978 10.824L3.978 9.102L10.698 9.102L10.698 10.824L3.978 10.824ZM13.176 10.824L13.176 9.102L19.896 9.102L19.896 10.824L13.176 10.824ZM3.978 14.772L3.978 13.050L10.698 13.050L10.698 14.772L3.978 14.772ZM13.176 14.772L13.176 13.050L19.896 13.050L19.896 14.772L13.176 14.772ZM3.978 18.678L3.978 16.998L10.698 16.998L10.698 18.678L3.978 18.678ZM13.176 18.678L13.176 16.998L19.896 16.998L19.896 18.678L13.176 18.678Z"/>', + 'seti:xls': + '<path d="M23.780 3.944L23.818 3.944L23.818 20.094Q23.818 20.132 23.742 20.246Q23.666 20.360 23.666 20.436L23.666 20.436Q23.286 21.044 22.716 21.044L22.716 21.044L13.596 21.044L13.596 23.400Q13.406 23.362 12.988 23.286Q12.570 23.210 12.418 23.172L12.418 23.172Q12 23.096 11.107 22.925Q10.214 22.754 9.758 22.697Q9.302 22.640 8.352 22.450Q7.402 22.260 6.927 22.203Q6.452 22.146 5.502 21.975Q4.552 21.804 4.115 21.747Q3.678 21.690 2.785 21.500Q1.892 21.310 1.474 21.272L1.474 21.272Q1.246 21.196 0.828 21.139Q0.410 21.082 0.182 21.044L0.182 21.044L0.182 3.564Q0.220 3.564 0.410 3.507Q0.600 3.450 0.638 3.450L0.638 3.450Q1.664 2.728 3.374 2.500L3.374 2.500Q3.830 2.424 4.742 2.234L4.742 2.234Q5.426 2.082 5.730 2.044L5.730 2.044L6.034 1.968Q7.364 1.778 8.010 1.550L8.010 1.550Q8.428 1.512 9.321 1.322Q10.214 1.132 10.651 1.075Q11.088 1.018 11.981 0.847Q12.874 0.676 13.368 0.600L13.368 0.600L13.482 0.600L13.482 2.842L22.716 2.842Q23.096 2.842 23.400 3.089Q23.704 3.336 23.780 3.678L23.780 3.678L23.780 3.944ZM22.868 19.714L22.868 3.792L13.482 3.792L13.482 5.236L16.674 5.236L16.674 7.250L13.482 7.250L13.482 7.972L16.674 7.972L16.674 9.986L13.482 9.986L13.482 10.708L16.674 10.708L16.674 12.722L13.482 12.722L13.482 13.558L16.788 13.558L16.788 15.572L13.482 15.572L13.482 16.294L16.674 16.294L16.674 18.308L13.482 18.308L13.482 19.714L22.868 19.714ZM10.366 17.472L10.366 17.472Q10.366 17.434 10.347 17.396Q10.328 17.358 10.252 17.358L10.252 17.358Q9.834 16.522 8.941 14.850Q8.048 13.178 7.630 12.342L7.630 12.342L7.630 12.114Q8.846 9.758 10.252 7.250L10.252 7.250L10.252 7.136L10.138 7.136Q9.530 7.136 9.302 7.250L9.302 7.250Q8.618 7.250 8.124 7.364L8.124 7.364Q8.048 7.364 8.029 7.383Q8.010 7.402 8.010 7.478L8.010 7.478L7.060 9.492L6.338 11.164Q6.300 11.050 6.224 10.746Q6.148 10.442 6.110 10.328L6.110 10.328L5.046 7.744Q4.932 7.554 4.894 7.516Q4.856 7.478 4.647 7.478Q4.438 7.478 3.963 7.535Q3.488 7.592 3.260 7.592L3.260 7.592L2.766 7.592L2.766 7.744L3.146 8.542L4.932 12.114L4.932 12.228Q4.552 12.950 3.754 14.470L3.754 14.470Q3.032 15.800 2.652 16.522L2.652 16.522Q2.652 16.560 2.595 16.636Q2.538 16.712 2.538 16.750L2.538 16.750L3.260 16.750Q3.488 16.750 3.906 16.807Q4.324 16.864 4.552 16.864L4.552 16.864Q4.666 16.864 4.666 16.845Q4.666 16.826 4.666 16.750L4.666 16.750Q5.388 15.344 5.768 14.508L5.768 14.508Q5.806 14.318 5.977 13.957Q6.148 13.596 6.224 13.444L6.224 13.444Q6.224 13.178 6.338 13.064L6.338 13.064L6.338 13.178Q6.376 13.292 6.452 13.501Q6.528 13.710 6.566 13.786L6.566 13.786Q6.870 14.394 7.402 15.610L7.402 15.610L7.896 16.750L7.972 16.864Q8.086 16.978 8.238 16.978L8.238 16.978Q8.542 16.978 9.131 17.054Q9.720 17.130 10.024 17.130L10.024 17.130Q10.100 17.358 10.176 17.415Q10.252 17.472 10.366 17.472ZM17.624 5.236L21.310 5.236L21.310 7.250L17.624 7.250L17.624 5.236ZM21.310 18.536L17.624 18.536L17.624 16.522L21.310 16.522L21.310 18.536ZM21.310 12.950L17.624 12.950L17.624 10.936L21.310 10.936L21.310 12.950ZM17.624 8.086L21.310 8.086L21.310 10.100L17.624 10.100L17.624 8.086ZM17.624 13.786L21.310 13.786L21.310 15.800L17.624 15.800L17.624 13.786Z"/>', + 'seti:cu': + '<path d="M0.024 11.875L0.024 11.875Q0.024 8.736 1.745 6.070L1.745 6.070Q3.335 3.533 5.937 2.200Q8.539 0.867 11.248 1.211L11.248 1.211Q14.215 1.555 16.451 3.834L16.451 3.834L13.484 7.188Q11.549 5.898 9.957 5.855L9.957 5.855Q8.539 5.769 7.506 6.715L7.506 6.715Q6.561 7.575 6.088 9.080L6.088 9.080Q5.658 10.499 5.701 12.155Q5.744 13.810 6.303 15.229Q6.861 16.648 7.851 17.379L7.851 17.379Q8.969 18.239 10.345 18.024L10.345 18.024Q11.936 17.809 13.742 16.304L13.742 16.304L16.709 19.701Q14.473 22.238 11.506 22.754L11.506 22.754Q8.754 23.184 6.088 21.851Q3.421 20.518 1.787 17.895L1.787 17.895Q0.024 15.143 0.024 11.875ZM22.084 9.209L23.976 14.971L22.901 14.971L22.471 13.638L20.622 13.638L20.192 14.971L19.117 14.971L21.009 9.209L22.084 9.209ZM20.880 12.692L22.213 12.692L21.524 10.542L20.880 12.692ZM10.044 9.209L10.087 9.209L11.033 9.209L11.033 12.348Q11.033 13.079 11.076 13.294L11.076 13.294Q11.119 13.681 11.355 13.896Q11.591 14.111 11.979 14.111L11.979 14.111Q12.280 14.111 12.495 13.961Q12.710 13.810 12.796 13.552Q12.882 13.294 12.882 12.434L12.882 12.434L12.882 9.209L13.828 9.209L13.828 12.262Q13.828 13.423 13.720 13.939Q13.613 14.455 13.161 14.778Q12.710 15.100 12 15.100Q11.291 15.100 10.861 14.821Q10.431 14.541 10.237 14.047Q10.044 13.552 10.044 12.305L10.044 12.305L10.044 9.209ZM14.817 14.971L14.817 9.209L16.580 9.209Q17.225 9.209 17.569 9.360Q17.913 9.510 18.192 9.854Q18.472 10.198 18.644 10.779Q18.816 11.359 18.816 12.133Q18.816 12.907 18.622 13.466Q18.429 14.025 18.192 14.348Q17.956 14.670 17.569 14.821Q17.182 14.971 16.623 14.971L16.623 14.971L14.817 14.971ZM16.193 10.198L15.806 10.198L15.806 13.982L16.494 13.982Q16.966 13.982 17.182 13.918Q17.397 13.853 17.526 13.681Q17.655 13.509 17.741 13.122Q17.827 12.735 17.827 12.090Q17.827 11.445 17.741 11.123Q17.655 10.800 17.440 10.564Q17.225 10.327 17.010 10.263Q16.795 10.198 16.193 10.198L16.193 10.198Z"/>', + 'seti:cake': + '<path d="M23.692 12.305L16.958 13.119Q17.328 14.340 18.179 17.522L18.179 17.522L18.956 20.408L23.692 19.816L23.692 12.305ZM10.372 21.444L8.892 13.933L0.308 14.858L0.308 22.739L10.372 21.444ZM16.033 6.311L16.033 6.311Q15.589 7.236 15.219 7.569L15.219 7.569L15.922 9.900L23.581 8.975L22.989 8.087Q22.249 7.051 21.435 6.163L21.435 6.163Q20.288 4.942 19.178 4.239L19.178 4.239Q17.772 3.351 16.403 2.944L16.403 2.944Q16.810 4.461 16.033 6.311ZM7.708 10.011L7.708 10.011Q5.747 9.826 4.489 8.383L4.489 8.383L0.308 11.639L7.967 10.714Q7.893 10.566 7.838 10.344Q7.782 10.122 7.708 10.011ZM13.998 10.825L13.147 7.680Q13.073 7.421 13.092 7.236Q13.110 7.051 13.258 6.866L13.258 6.866Q13.739 6.200 13.961 5.719L13.961 5.719Q14.775 3.906 13.850 2.500L13.850 2.500Q12.851 0.835 10.853 1.205L10.853 1.205Q10.594 1.205 10.520 1.427Q10.446 1.649 10.631 1.908L10.631 1.908L11.667 3.980L11.667 4.091Q11.704 4.165 11.686 4.202Q11.667 4.239 11.556 4.239L11.556 4.239Q10.150 5.164 9.558 5.497L9.558 5.497Q9.410 5.682 9.225 5.497L9.225 5.497Q8.781 5.016 8.078 4.091L8.078 4.091Q7.930 3.980 7.708 3.795L7.708 3.795L7.486 3.647L7.301 3.610Q7.116 3.610 7.042 3.758L7.042 3.758Q6.561 4.535 6.450 5.497L6.450 5.497Q6.302 6.607 6.783 7.347L6.783 7.347Q7.671 8.716 9.225 8.716L9.225 8.716Q9.447 8.716 9.595 8.790Q9.743 8.864 9.817 9.086L9.817 9.086L10.335 11.417Q12.518 20.556 12.703 21.703L12.703 21.703Q12.777 22.221 13.110 22.572Q13.443 22.924 13.850 22.850L13.850 22.850L14.220 22.776Q14.960 22.702 15.293 22.591L15.293 22.591Q15.885 22.406 16.292 22.036L16.292 22.036Q16.921 21.407 16.736 20.519L16.736 20.519Q16.477 20.038 13.998 10.825L13.998 10.825Z"/>', + 'seti:cake_php': + '<path d="M11.924 10.157L11.924 10.157L11.924 13.843L10.518 13.843Q8.542 13.729 7.554 13.615L7.554 13.615Q5.958 13.425 4.666 13.007L4.666 13.007Q3.716 12.779 2.082 12.057L2.082 12.057Q1.588 11.943 0.866 11.487L0.866 11.487Q0.448 11.107 0.258 10.727Q0.068 10.347 0.068 9.815L0.068 9.815L0.068 6.699Q0.068 6.015 0.638 5.407L0.638 5.407Q1.398 4.647 2.918 4.229L2.918 4.229Q5.350 3.355 8.010 3.165L8.010 3.165L8.314 3.127Q11.316 2.899 12.874 2.899L12.874 2.899Q17.092 2.899 20.816 4.115L20.816 4.115Q21.310 4.267 22.222 4.761L22.222 4.761L22.982 5.179Q23.932 5.749 23.932 6.965L23.932 6.965L23.932 9.929Q23.932 11.107 23.096 11.601L23.096 11.601Q22.716 11.867 21.918 12.247L21.918 12.247L21.538 12.437Q21.462 12.513 21.196 12.437L21.196 12.437L21.082 12.437Q15.382 10.993 12.418 10.271L12.418 10.271Q12.152 10.157 11.924 10.157ZM11.924 17.985L11.924 21.101L9.568 21.101Q5.996 20.873 3.602 20.151L3.602 20.151Q3.108 19.999 2.348 19.657L2.348 19.657L1.132 19.049Q0.068 18.365 0.068 17.035L0.068 17.035L0.068 14.299Q0.752 15.249 1.968 15.857L1.968 15.857Q2.652 16.199 4.210 16.693L4.210 16.693Q7.516 17.529 11.468 17.529L11.468 17.529Q11.734 17.529 11.829 17.624Q11.924 17.719 11.924 17.985L11.924 17.985ZM23.818 14.185L23.818 14.185L23.818 17.529Q23.780 18.175 23.096 18.707L23.096 18.707Q21.918 19.429 21.310 19.657L21.310 19.657Q21.234 19.733 20.968 19.695L20.968 19.695L20.702 19.657L12.152 17.529Q12.076 17.529 12.000 17.415L12.000 17.415L11.924 17.301L11.924 13.957Q12.342 14.071 13.121 14.261Q13.900 14.451 14.318 14.565L14.318 14.565Q15.420 14.869 17.624 15.401Q19.828 15.933 20.968 16.199L20.968 16.199L21.424 16.199L21.880 15.933Q22.602 15.515 22.944 15.249L22.944 15.249Q23.476 14.793 23.818 14.185Z"/>', + 'seti:d': + '<path d="M23.232 11.712L23.232 11.712Q23.232 17.760 19.464 20.880Q15.696 24 8.400 24L8.400 24L0.768 24L0.768 0L9.312 0Q16.032 0 19.632 3.168L19.632 3.168Q21.456 4.608 22.344 6.792Q23.232 8.976 23.232 11.712ZM17.232 11.856L17.232 11.856Q17.232 4.032 9.456 4.032L9.456 4.032L6.432 4.032L6.432 19.776L9.024 19.776Q13.152 19.776 15.192 17.832Q17.232 15.888 17.232 11.856Z"/>', + 'seti:word': + '<path d="M23.875 6.585L23.875 6.585L23.875 3.507Q23.875 3.127 23.609 2.842Q23.343 2.557 22.925 2.557L22.925 2.557L14.223 2.557L14.223 0.429L12.589 0.429Q12.475 0.429 12.285 0.486Q12.095 0.543 11.981 0.543L11.981 0.543Q11.563 0.581 10.727 0.771Q9.891 0.961 9.473 0.999L9.473 0.999Q7.839 1.265 7.117 1.493L7.117 1.493Q5.445 1.721 4.495 1.949L4.495 1.949L1.873 2.329Q0.695 2.557 0.239 2.557L0.239 2.557L0.125 2.557L0.125 21.443Q0.581 21.481 1.531 21.671Q2.481 21.861 2.956 21.918Q3.431 21.975 4.438 22.146Q5.445 22.317 5.920 22.374Q6.395 22.431 7.345 22.621Q8.295 22.811 8.789 22.849L8.789 22.849Q9.967 23.001 11.753 23.457L11.753 23.457Q12.095 23.571 12.931 23.571L12.931 23.571L13.995 23.571L13.995 21.557Q13.995 21.481 14.014 21.462Q14.033 21.443 14.109 21.443L14.109 21.443L22.773 21.443Q23.153 21.443 23.267 21.329L23.267 21.329Q23.609 21.329 23.609 20.949L23.609 20.949Q23.609 20.835 23.666 20.664Q23.723 20.493 23.723 20.379L23.723 20.379L23.723 6.585L23.837 6.699Q23.875 6.699 23.875 6.585ZM10.803 8.371L10.803 8.371L9.739 13.007Q9.587 13.463 9.397 14.413L9.397 14.413Q9.245 15.211 9.131 15.629L9.131 15.629Q9.131 15.705 9.055 15.705L9.055 15.705L9.017 15.743Q8.865 15.819 8.523 15.781L8.523 15.781L8.295 15.743L7.573 15.743Q7.497 15.743 7.478 15.724Q7.459 15.705 7.459 15.629L7.459 15.629Q7.421 15.249 7.231 14.489Q7.041 13.729 7.003 13.349L7.003 13.349Q6.889 12.893 6.699 11.943Q6.509 10.993 6.395 10.499L6.395 10.499Q6.395 10.613 6.338 10.860Q6.281 11.107 6.281 11.221L6.281 11.221L5.559 14.793Q5.559 14.907 5.502 15.211Q5.445 15.515 5.445 15.610Q5.445 15.705 5.426 15.724Q5.407 15.743 5.331 15.743L5.331 15.743Q5.103 15.743 4.628 15.686Q4.153 15.629 3.925 15.629L3.925 15.629Q3.811 15.629 3.792 15.610Q3.773 15.591 3.773 15.515L3.773 15.515Q3.089 11.715 2.595 9.701L2.595 9.701Q2.557 9.511 2.481 9.093Q2.405 8.675 2.367 8.485L2.367 8.485L2.367 8.371L3.773 8.371Q3.887 9.131 4.153 10.689L4.153 10.689Q4.495 12.513 4.609 13.463L4.609 13.463Q4.609 13.349 4.666 13.121Q4.723 12.893 4.723 12.779L4.723 12.779Q4.913 12.057 5.217 10.575Q5.521 9.093 5.673 8.371L5.673 8.371Q5.673 8.295 5.692 8.276Q5.711 8.257 5.825 8.257L5.825 8.257L7.003 8.257Q7.155 8.257 7.212 8.295Q7.269 8.333 7.345 8.485L7.345 8.485Q8.067 11.829 8.409 13.615L8.409 13.615L8.409 13.729Q8.485 13.235 8.656 12.285Q8.827 11.335 8.884 10.898Q8.941 10.461 9.131 9.568Q9.321 8.675 9.359 8.257L9.359 8.257L9.397 8.181Q9.397 8.143 9.473 8.143L9.473 8.143Q10.423 8.143 11.031 8.029L11.031 8.029L11.145 8.029Q10.993 8.029 10.898 8.143Q10.803 8.257 10.803 8.371ZM23.039 3.507L23.039 3.507Q23.039 3.545 23.039 3.545L23.039 3.545L23.039 3.507L23.039 20.721L14.109 20.721L14.109 18.593L21.139 18.593L21.139 17.529L14.375 17.529Q14.261 17.529 14.242 17.510Q14.223 17.491 14.223 17.415L14.223 17.415L14.223 16.313Q14.223 16.237 14.242 16.218Q14.261 16.199 14.375 16.199L14.375 16.199L21.253 16.199L21.253 15.135L14.223 15.135L14.223 13.843L21.139 13.843Q21.215 13.843 21.234 13.824Q21.253 13.805 21.253 13.729L21.253 13.729L21.253 12.893Q21.253 12.817 21.234 12.798Q21.215 12.779 21.139 12.779L21.139 12.779L14.375 12.779Q14.261 12.779 14.242 12.760Q14.223 12.741 14.223 12.665L14.223 12.665L14.223 11.449L21.253 11.449L21.253 10.385L14.489 10.385Q14.375 10.385 14.356 10.366Q14.337 10.347 14.337 10.271L14.337 10.271L14.337 9.207Q14.337 9.131 14.356 9.112Q14.375 9.093 14.489 9.093L14.489 9.093L21.253 9.093L21.253 8.029L14.223 8.029L14.223 6.585L21.139 6.585Q21.215 6.585 21.234 6.566Q21.253 6.547 21.253 6.471L21.253 6.471L21.253 5.635Q21.253 5.559 21.234 5.540Q21.215 5.521 21.139 5.521L21.139 5.521L14.109 5.521L14.109 3.735Q14.109 3.659 14.128 3.640Q14.147 3.621 14.223 3.621L14.223 3.621L22.925 3.621L23.001 3.431Q23.039 3.431 23.039 3.507Z"/>', + 'seti:elixir': + '<path d="M13.540 5.776L13.540 5.776Q13.995 6.721 14.800 7.736L14.800 7.736Q15.290 8.331 16.375 9.451L16.375 9.451Q17.530 10.711 18.055 11.341L18.055 11.341Q18.895 12.461 19.280 13.511L19.280 13.511Q19.735 14.806 19.595 16.276L19.595 16.276Q19.385 19.006 18.055 20.826L18.055 20.826Q17.005 22.331 15.325 23.101L15.325 23.101Q13.995 23.731 12.542 23.783Q11.090 23.836 9.725 23.416L9.725 23.416Q7.905 22.891 6.680 21.631L6.680 21.631Q5.140 20.056 4.580 17.501L4.580 17.501Q4.090 15.261 4.755 12.321L4.755 12.321Q5.385 9.731 6.785 7.001L6.785 7.001Q8.115 4.481 9.725 2.608Q11.335 0.736 12.630 0.211L12.630 0.211Q12.525 1.436 12.770 2.976L12.770 2.976Q13.015 4.656 13.540 5.776ZM10.495 21.736L10.495 21.736Q11.930 22.051 12.490 22.051L12.490 22.051Q13.295 22.086 13.400 21.666L13.400 21.666Q13.645 20.581 7.485 19.916L7.485 19.916Q8.045 20.476 8.972 21.053Q9.900 21.631 10.495 21.736Z"/>', + 'seti:elixir_script': + '<path d="M15.570 8.681L15.570 8.646Q15.850 8.926 16.375 9.451L16.375 9.451Q17.530 10.711 18.055 11.341L18.055 11.341Q18.895 12.461 19.280 13.511L19.280 13.511Q19.735 14.806 19.595 16.276L19.595 16.276Q19.385 19.006 18.055 20.826L18.055 20.826Q17.005 22.331 15.325 23.101L15.325 23.101Q13.995 23.731 12.542 23.783Q11.090 23.836 9.725 23.416L9.725 23.416Q7.905 22.891 6.680 21.631L6.680 21.631Q5.140 20.056 4.580 17.501L4.580 17.501Q4.090 15.261 4.755 12.321L4.755 12.321Q5.385 9.731 6.785 7.001L6.785 7.001Q8.115 4.481 9.725 2.608Q11.335 0.736 12.630 0.211L12.630 0.211Q12.525 1.366 12.735 2.871L12.735 2.871Q12.980 4.446 13.470 5.601L13.470 5.601Q13.085 5.566 12.735 5.566L12.735 5.566Q10.530 5.566 9.147 6.756Q7.765 7.946 7.765 9.836L7.765 9.836Q7.765 10.921 8.307 11.551Q8.850 12.181 10.495 12.881L10.495 12.881L11.510 13.301Q12.070 13.546 12.385 13.931Q12.700 14.316 12.700 14.841L12.700 14.841Q12.700 15.716 12.035 16.206Q11.370 16.696 10.250 16.696L10.250 16.696Q9.340 16.696 8.412 16.328Q7.485 15.961 6.680 15.296L6.680 15.296L6.190 17.886Q7.170 18.341 8.220 18.586L8.220 18.586Q9.165 18.796 10.145 18.796L10.145 18.796Q12.490 18.796 13.872 17.623Q15.255 16.451 15.255 14.491L15.255 14.491Q15.255 13.336 14.677 12.566Q14.100 11.796 12.840 11.236L12.840 11.236L11.790 10.781Q10.215 10.046 10.215 9.311Q10.215 8.576 10.845 8.103Q11.475 7.631 12.455 7.631Q13.435 7.631 14.222 7.893Q15.010 8.156 15.570 8.681L15.570 8.681ZM10.495 21.736L10.495 21.736Q11.930 22.051 12.490 22.051L12.490 22.051Q13.295 22.086 13.400 21.666L13.400 21.666Q13.645 20.581 7.485 19.916L7.485 19.916Q8.045 20.476 8.972 21.053Q9.900 21.631 10.495 21.736Z"/>', + 'seti:hex': + '<path d="M23.856 12L17.928 22.260L6.072 22.260L0.144 12L6.072 1.740L17.928 1.740L23.856 12ZM8.998 17.206L15.002 17.206L18.004 12L15.002 6.794L8.998 6.794L5.996 12L8.998 17.206Z"/>', + 'seti:elm': + '<path d="M23.193 23.856L12.000 12.663L0.807 23.856L23.193 23.856ZM23.856 13.248L18.864 18.240L23.856 23.193L23.856 13.248ZM0.144 23.193L11.337 12L0.144 0.807L0.144 23.193ZM13.326 0.144L23.856 10.674L23.856 0.144L13.326 0.144ZM12.663 12L18.240 6.384L23.817 11.961L18.240 17.577L12.663 12ZM12.000 0.144L0.807 0.144L5.955 5.331L17.187 5.331L12.000 0.144ZM6.891 6.228L12.000 11.337L17.109 6.228L6.891 6.228Z"/>', + 'seti:favicon': + '<path d="M8.295 8.200L11.981 0.714L15.667 8.200L23.875 9.378L17.909 15.078L19.353 23.286L11.981 19.486L4.609 23.286L6.053 15.078L0.125 9.378L8.295 8.200Z"/>', + 'seti:f-sharp': + '<path d="M11.496 23.130L0.198 11.874L11.328 0.702L11.328 6.330L5.826 11.874L11.496 17.502L11.496 23.130ZM11.496 15.780L7.422 11.874L11.496 7.800L11.496 15.780ZM12.252 23.298L23.802 11.874L12.252 0.702L12.252 6.330L17.922 12L12.252 17.628L12.252 23.298Z"/>', + 'seti:git': + '<path d="M0.355 12.231L0.355 12.231L0.355 11.853Q0.397 11.517 0.565 11.265L0.565 11.265Q0.691 11.097 0.943 10.803L0.943 10.803L1.279 10.425L7.831 3.831L7.873 3.873Q7.957 3.873 7.957 3.957L7.957 3.957L10.309 6.351Q10.519 6.519 10.309 6.729L10.309 6.729Q10.225 7.317 10.435 7.863Q10.645 8.409 11.107 8.703L11.107 8.703Q11.275 8.787 11.317 8.892Q11.359 8.997 11.359 9.207L11.359 9.207L11.359 15.003Q11.359 15.255 11.107 15.507L11.107 15.507Q10.603 15.843 10.372 16.389Q10.141 16.935 10.330 17.502Q10.519 18.069 10.981 18.447Q11.443 18.825 12.031 18.825Q12.619 18.825 13.081 18.489Q13.543 18.153 13.732 17.586Q13.921 17.019 13.753 16.473Q13.585 15.927 13.081 15.507L13.081 15.507Q12.913 15.423 12.871 15.318Q12.829 15.213 12.829 15.003L12.829 15.003L12.829 9.081L12.955 9.081L15.055 11.181Q15.139 11.265 15.139 11.391L15.139 11.391L15.181 11.475L15.181 12.231Q15.265 13.029 15.874 13.470Q16.483 13.911 17.281 13.806Q18.079 13.701 18.562 13.029Q19.045 12.357 18.835 11.601L18.835 11.601Q18.751 10.929 18.100 10.488Q17.449 10.047 16.735 10.131L16.735 10.131Q16.483 10.131 16.231 10.005L16.231 10.005L14.005 7.779Q13.879 7.653 13.879 7.401L13.879 7.401Q14.005 6.813 13.711 6.267Q13.417 5.721 12.871 5.448Q12.325 5.175 11.779 5.301L11.779 5.301Q11.359 5.301 11.359 5.175L11.359 5.175Q9.805 3.579 9.007 2.907L9.007 2.907Q8.797 2.739 9.007 2.529L9.007 2.529Q9.469 2.193 10.183 1.353L10.183 1.353L10.729 0.807Q11.905-0.369 13.081 0.807L13.081 0.807L23.035 10.803Q24.253 11.979 23.035 13.155L23.035 13.155L13.291 22.941Q12.913 23.319 12.745 23.445L12.745 23.445Q12.409 23.739 12.031 23.781L12.031 23.781L11.779 23.781L11.569 23.697Q11.065 23.487 10.855 23.277L10.855 23.277L10.057 22.479Q8.881 21.387 8.335 20.757L8.335 20.757L1.153 13.575Q1.069 13.365 0.775 13.029L0.775 13.029Q0.397 12.525 0.355 12.231Z"/>', + 'seti:go': + '<path d="M6.119 10.273L1.933 10.247Q1.855 10.247 1.881 10.195L1.881 10.195L2.141 9.883Q2.167 9.831 2.271 9.831L2.271 9.831L6.379 9.831Q6.457 9.831 6.431 9.883L6.431 9.883L6.223 10.195Q6.171 10.273 6.119 10.273L6.119 10.273ZM5.651 11.313L0.191 11.313Q0.113 11.313 0.139 11.261L0.139 11.261L0.399 10.949Q0.425 10.897 0.529 10.897L0.529 10.897L5.781 10.897Q5.859 10.897 5.833 10.949L5.833 10.949L5.755 11.235Q5.729 11.313 5.651 11.313L5.651 11.313ZM5.495 12.379L2.973 12.379Q2.895 12.379 2.947 12.301L2.947 12.301L3.103 12.015Q3.155 11.963 3.233 11.963L3.233 11.963L5.521 11.963Q5.599 11.963 5.599 12.041L5.599 12.041L5.573 12.301Q5.573 12.379 5.495 12.379L5.495 12.379ZM14.985 10.039L14.985 10.039Q14.569 10.143 13.893 10.325L13.893 10.325L13.009 10.559Q12.905 10.585 12.853 10.572Q12.801 10.559 12.697 10.429L12.697 10.429Q12.411 10.117 12.151 9.987L12.151 9.987Q11.111 9.493 10.071 10.169L10.071 10.169Q8.875 10.949 8.875 12.379L8.875 12.379Q8.901 13.055 9.330 13.575Q9.759 14.095 10.435 14.173L10.435 14.173Q11.605 14.329 12.411 13.419L12.411 13.419L12.723 13.003L10.487 13.003Q10.305 13.003 10.253 12.899Q10.201 12.795 10.279 12.639L10.279 12.639Q10.591 11.911 10.851 11.391L10.851 11.391Q10.955 11.209 11.137 11.209L11.137 11.209L15.349 11.209L15.349 11.521Q15.323 11.937 15.297 12.145L15.297 12.145Q15.089 13.419 14.335 14.407L14.335 14.407Q13.061 16.097 11.033 16.357L11.033 16.357Q9.265 16.591 7.939 15.603L7.939 15.603Q6.665 14.641 6.457 13.029L6.457 13.029Q6.249 11.209 7.445 9.649L7.445 9.649Q8.693 8.011 10.695 7.647L10.695 7.647Q12.437 7.335 13.737 8.219L13.737 8.219Q14.647 8.817 15.089 9.857L15.089 9.857Q15.193 9.987 14.985 10.039ZM19.119 16.409L18.807 16.435Q17.117 16.409 15.973 15.421L15.973 15.421Q14.933 14.511 14.725 13.185L14.725 13.185Q14.439 11.313 15.661 9.701L15.661 9.701Q16.285 8.869 17.065 8.414Q17.845 7.959 18.911 7.777L18.911 7.777Q20.835 7.439 22.226 8.375Q23.617 9.311 23.825 10.923L23.825 10.923Q24.111 13.211 22.499 14.849L22.499 14.849Q21.381 15.993 19.717 16.331L19.717 16.331Q19.509 16.357 19.119 16.409L19.119 16.409ZM21.537 11.755L21.537 11.755Q21.537 11.729 21.537 11.651L21.537 11.651Q21.537 11.469 21.511 11.391L21.511 11.391Q21.355 10.533 20.666 10.091Q19.977 9.649 19.145 9.857L19.145 9.857Q17.507 10.221 17.143 11.859L17.143 11.859Q16.987 12.535 17.286 13.146Q17.585 13.757 18.209 14.043L18.209 14.043Q19.145 14.459 20.081 13.965L20.081 13.965Q21.459 13.263 21.537 11.755Z"/>', + 'seti:godot': + '<path d="M9.606 0.870L9.606 0.870Q7.800 1.248 6.456 1.920L6.456 1.920Q6.498 3.390 6.624 4.524L6.624 4.524L6.288 4.734Q5.742 5.070 5.490 5.280L5.490 5.280L5.280 5.406Q4.692 5.910 4.398 6.162L4.398 6.162Q3.390 5.490 2.298 4.944L2.298 4.944Q0.996 6.372 0.198 7.716L0.198 7.716Q1.038 9.018 1.626 9.774L1.626 9.774L1.626 16.032L5.490 16.410Q5.658 16.410 5.763 16.515Q5.868 16.620 5.868 16.788L5.868 16.788L5.994 18.468L9.354 18.720L9.564 17.166Q9.606 16.998 9.711 16.893Q9.816 16.788 9.984 16.788L9.984 16.788L14.016 16.788Q14.184 16.788 14.289 16.893Q14.394 16.998 14.436 17.166L14.436 17.166L14.646 18.720L18.006 18.468L18.132 16.788Q18.132 16.620 18.237 16.515Q18.342 16.410 18.510 16.410L18.510 16.410L22.374 16.032L22.374 9.774Q23.088 8.850 23.802 7.716L23.802 7.716Q23.004 6.372 21.702 4.944L21.702 4.944Q20.610 5.490 19.602 6.162L19.602 6.162Q19.308 5.868 18.678 5.406L18.678 5.406L18.510 5.280Q18.258 5.070 17.712 4.734L17.712 4.734L17.334 4.524Q17.502 3.222 17.544 1.920L17.544 1.920Q16.200 1.248 14.394 0.870L14.394 0.870Q13.764 1.962 13.218 3.138L13.218 3.138Q12.630 3.054 12 3.054L12 3.054L12 3.054Q11.370 3.054 10.782 3.138L10.782 3.138Q10.236 1.962 9.606 0.870ZM6.582 10.026L6.582 10.026Q7.506 10.026 8.178 10.698Q8.850 11.370 8.850 12.315Q8.850 13.260 8.178 13.953Q7.506 14.646 6.561 14.646Q5.616 14.646 4.923 13.953Q4.230 13.260 4.230 12.315Q4.230 11.370 4.923 10.698Q5.616 10.026 6.582 10.026ZM17.418 10.026L17.418 10.026Q18.384 10.026 19.056 10.698Q19.728 11.370 19.728 12.315Q19.728 13.260 19.056 13.953Q18.384 14.646 17.439 14.646Q16.494 14.646 15.801 13.953Q15.108 13.260 15.108 12.315Q15.108 11.370 15.801 10.698Q16.494 10.026 17.418 10.026ZM12 11.370L12 11.370Q12.294 11.370 12.525 11.559Q12.756 11.748 12.756 12.042L12.756 12.042L12.756 14.184Q12.756 14.436 12.525 14.646Q12.294 14.856 12 14.856Q11.706 14.856 11.475 14.646Q11.244 14.436 11.244 14.184L11.244 14.184L11.244 12.042Q11.244 11.748 11.475 11.559Q11.706 11.370 12 11.370ZM22.374 16.872L18.930 17.208L18.804 18.888Q18.804 19.056 18.699 19.161Q18.594 19.266 18.426 19.266L18.426 19.266L14.310 19.560Q14.142 19.560 14.037 19.476Q13.932 19.392 13.890 19.224L13.890 19.224L13.680 17.628L10.320 17.628L10.110 19.224Q10.068 19.392 9.942 19.497Q9.816 19.602 9.648 19.560L9.648 19.560L5.574 19.266Q5.406 19.266 5.301 19.161Q5.196 19.056 5.196 18.888L5.196 18.888L5.070 17.208L1.626 16.872L1.626 17.712Q1.626 20.358 4.650 21.786L4.650 21.786Q7.464 23.130 12 23.130L12 23.130L12 23.130Q16.536 23.130 19.350 21.786L19.350 21.786Q22.374 20.358 22.374 17.712L22.374 17.712L22.374 16.872ZM8.304 12.462L8.304 12.462Q8.346 12.882 8.136 13.239Q7.926 13.596 7.569 13.827Q7.212 14.058 6.792 14.058Q6.372 14.058 6.015 13.827Q5.658 13.596 5.448 13.239Q5.238 12.882 5.238 12.462L5.238 12.462Q5.280 11.832 5.721 11.391Q6.162 10.950 6.792 10.950Q7.422 10.950 7.863 11.391Q8.304 11.832 8.304 12.462ZM15.696 12.462L15.696 12.462Q15.696 13.092 16.137 13.533Q16.578 13.974 17.208 13.974Q17.838 13.974 18.300 13.533Q18.762 13.092 18.762 12.462Q18.762 11.832 18.300 11.370Q17.838 10.908 17.208 10.908Q16.578 10.908 16.137 11.370Q15.696 11.832 15.696 12.462Z"/>', + 'seti:gradle': + '<path d="M16.344 11.229L16.344 11.229L15.197 10.640L15.197 10.640Q15.197 10.361 15.414 10.144Q15.631 9.927 15.894 9.927Q16.158 9.927 16.344 10.067Q16.530 10.206 16.607 10.423Q16.685 10.640 16.607 10.857Q16.530 11.074 16.344 11.229ZM22.389 4.502L22.389 4.502Q21.707 3.789 20.777 3.541Q19.847 3.293 18.917 3.510Q17.987 3.727 17.243 4.409L17.243 4.409Q17.150 4.502 17.150 4.657Q17.150 4.812 17.243 4.905L17.243 4.905L17.708 5.370Q17.801 5.463 17.940 5.479Q18.080 5.494 18.173 5.401L18.173 5.401Q18.731 4.998 19.444 4.998L19.444 4.998Q20.312 4.998 20.947 5.618Q21.583 6.238 21.583 7.122Q21.583 8.005 20.978 8.594Q20.374 9.183 19.661 9.276L19.661 9.276Q19.041 9.307 18.204 8.997L18.204 8.997Q17.677 8.780 16.499 8.191L16.499 8.191Q14.639 7.261 13.554 6.889L13.554 6.889Q11.694 6.238 9.834 6.331L9.834 6.331Q7.602 6.424 5.184 7.571L5.184 7.571Q4.719 7.788 4.548 8.300Q4.378 8.811 4.657 9.245L4.657 9.245L6.176 11.911Q6.424 12.345 6.904 12.469Q7.385 12.593 7.819 12.345L7.819 12.345L7.850 12.345L7.819 12.345L8.501 11.973L9.214 11.508Q10.020 10.950 10.640 10.392L10.640 10.392Q10.733 10.299 10.872 10.284Q11.012 10.268 11.136 10.361L11.136 10.361L11.136 10.361Q11.260 10.454 11.260 10.625Q11.260 10.795 11.136 10.888L11.136 10.888Q10.082 11.849 8.873 12.593L8.873 12.593L8.191 12.996Q7.478 13.368 6.718 13.167Q5.959 12.965 5.556 12.283L5.556 12.283L4.130 9.772Q1.929 11.322 0.968 13.988L0.968 13.988Q-0.086 16.840 0.565 20.312L0.565 20.312Q0.596 20.436 0.689 20.514Q0.782 20.591 0.906 20.591L0.906 20.591L2.549 20.591Q2.704 20.591 2.797 20.498Q2.890 20.405 2.921 20.281L2.921 20.281Q3.014 19.382 3.696 18.778Q4.378 18.173 5.292 18.173Q6.207 18.173 6.889 18.778Q7.571 19.382 7.695 20.281L7.695 20.281Q7.695 20.405 7.803 20.498Q7.912 20.591 8.036 20.591L8.036 20.591L9.648 20.591Q9.772 20.591 9.865 20.498Q9.958 20.405 9.989 20.281L9.989 20.281Q10.113 19.382 10.795 18.778Q11.477 18.173 12.376 18.173Q13.275 18.173 13.957 18.778Q14.639 19.382 14.763 20.281L14.763 20.281Q14.794 20.405 14.887 20.498Q14.980 20.591 15.104 20.591L15.104 20.591L16.685 20.591Q16.840 20.591 16.948 20.483Q17.057 20.374 17.057 20.250L17.057 20.250Q17.088 18.359 17.584 16.840L17.584 16.840Q18.204 15.042 19.413 14.143L19.413 14.143Q22.110 12.097 23.133 9.958L23.133 9.958Q23.939 8.253 23.567 6.610L23.567 6.610Q23.257 5.370 22.389 4.502Z"/>', + 'seti:grails': + '<path d="M11.488 18.832L11.488 18.832L11.200 18.832Q11.104 18.736 10.784 18.736L10.784 18.736L9.792 18.448Q9.568 18.288 9.504 18.128Q9.440 17.968 9.600 17.744L9.600 17.744Q9.792 17.456 10.016 16.848L10.016 16.848Q10.432 15.856 10.624 15.184L10.624 15.184Q10.848 14.224 10.688 13.360L10.688 13.360Q10.528 11.728 9.088 11.168Q7.648 10.608 6.912 9.840L6.912 9.840Q5.728 8.752 5.184 7.760L5.184 7.760Q4.544 6.544 4.608 5.136L4.608 5.136L19.392 5.136Q19.392 6.736 18.688 7.856L18.688 7.856Q17.472 10.032 14.912 11.152L14.912 11.152Q13.344 11.920 13.216 13.552L13.216 13.552Q13.120 14.480 13.472 15.568L13.472 15.568Q13.728 16.304 14.304 17.456L14.304 17.456Q14.528 17.872 14.448 18.048Q14.368 18.224 13.888 18.448L13.888 18.448L13.408 18.640Q13.248 18.704 12.896 18.752Q12.544 18.800 12.384 18.864L12.384 18.864L12 18.864Q11.840 18.672 11.488 18.832ZM24 9.360L24 9.936Q23.872 10.064 23.776 10.416L23.776 10.416Q23.744 10.576 23.712 10.640L23.712 10.640Q22.912 12.400 21.312 12.848L21.312 12.848Q20.288 13.104 20.288 14.352L20.288 14.352Q20.224 14.896 20.416 15.472L20.416 15.472Q20.512 15.856 20.800 16.560L20.800 16.560Q21.024 17.008 20.928 17.184Q20.832 17.360 20.288 17.456L20.288 17.456Q19.200 17.616 18.304 17.360L18.304 17.360Q17.824 17.200 18.112 16.752L18.112 16.752Q18.432 16.144 18.592 15.664L18.592 15.664Q18.784 15.056 18.688 14.448L18.688 14.448Q18.624 13.680 18.416 13.408Q18.208 13.136 17.696 13.040L17.696 13.040Q17.344 13.040 17.216 12.752L17.216 12.752Q17.248 12.752 17.296 12.704Q17.344 12.656 17.408 12.656L17.408 12.656Q19.616 11.824 20.896 9.552L20.896 9.552Q20.960 9.424 21.072 9.392Q21.184 9.360 21.408 9.360L21.408 9.360L24 9.360ZM0 10.160L0 9.232L2.496 9.232Q2.688 9.232 2.752 9.264Q2.816 9.296 2.912 9.456L2.912 9.456Q4.160 11.536 6.688 12.656L6.688 12.656Q6.656 12.688 6.560 12.736Q6.464 12.784 6.400 12.848L6.400 12.848Q5.792 13.072 5.552 13.472Q5.312 13.872 5.312 14.544L5.312 14.544Q5.312 15.344 5.792 16.336L5.792 16.336Q6.016 16.752 6.096 16.880Q6.176 17.008 6.160 17.120Q6.144 17.232 6.016 17.232L6.016 17.232Q4.640 17.840 3.296 17.232L3.296 17.232Q3.104 17.232 3.056 17.120Q3.008 17.008 3.104 16.752L3.104 16.752Q3.488 15.952 3.648 15.536L3.648 15.536Q3.872 14.864 3.792 14.256Q3.712 13.648 3.520 13.424Q3.328 13.200 2.816 13.040L2.816 13.040Q1.056 12.528 0.192 10.448L0.192 10.448Q0.160 10.416 0.144 10.288Q0.128 10.160 0 10.160L0 10.160Z"/>', + 'seti:graphql': + '<path d="M21.337 14.958L21.337 14.958Q21.269 14.958 21.201 14.890L21.201 14.890Q20.963 14.754 20.793 14.754L20.793 14.754L20.793 9.246Q21.133 9.246 21.337 9.042L21.337 9.042Q22.085 8.600 22.323 7.767Q22.561 6.934 22.119 6.169Q21.677 5.404 20.827 5.183Q19.977 4.962 19.229 5.404L19.229 5.404Q18.923 5.540 18.787 5.846L18.787 5.846L13.993 3.092Q13.993 2.888 14.061 2.718Q14.129 2.548 14.095 2.446L14.095 2.446Q14.129 1.562 13.500 0.933Q12.871 0.304 11.987 0.304Q11.103 0.304 10.491 0.933Q9.879 1.562 9.879 2.446L9.879 2.446Q9.879 2.854 9.981 3.092L9.981 3.092L5.187 5.846Q5.119 5.676 4.881 5.506L4.881 5.506L4.779 5.404Q3.997 4.962 3.147 5.183Q2.297 5.404 1.889 6.135Q1.481 6.866 1.702 7.699Q1.923 8.532 2.637 9.042L2.637 9.042L2.773 9.110Q3.011 9.246 3.181 9.246L3.181 9.246L3.181 14.754Q2.841 14.754 2.637 14.992L2.637 14.992Q1.889 15.400 1.651 16.233Q1.413 17.066 1.855 17.831Q2.297 18.596 3.147 18.817Q3.997 19.038 4.779 18.596L4.779 18.596Q5.051 18.460 5.187 18.154L5.187 18.154L9.981 20.942Q9.981 21.112 9.930 21.282Q9.879 21.452 9.845 21.554L9.845 21.554Q9.879 22.438 10.491 23.067Q11.103 23.696 11.987 23.696Q12.871 23.696 13.500 23.067Q14.129 22.438 14.129 21.554L14.129 21.554Q14.129 21.146 13.993 20.942L13.993 20.942L18.787 18.154Q18.889 18.392 19.331 18.596L19.331 18.596Q20.045 19.004 20.878 18.783Q21.711 18.562 22.187 17.848L22.187 17.848Q22.595 17.134 22.323 16.301Q22.051 15.468 21.337 14.958ZM18.243 16.352L5.731 16.352Q5.731 16.046 5.493 15.808L5.493 15.808Q5.391 15.604 5.187 15.400L5.187 15.400L11.443 4.452Q11.579 4.452 11.817 4.520L11.817 4.520L11.987 4.554Q12.429 4.554 12.531 4.452L12.531 4.452L18.787 15.400Q18.481 15.706 18.481 15.808L18.481 15.808L18.379 15.978Q18.243 16.216 18.243 16.352L18.243 16.352ZM13.585 3.806L18.243 6.594Q18.073 7.512 18.481 8.158L18.481 8.158Q18.957 8.974 19.739 9.144L19.739 9.144L19.739 14.652L19.637 14.652L13.483 3.908L13.585 3.806ZM5.629 6.696L10.491 3.806Q10.491 3.840 10.491 3.874L10.491 3.874L10.491 3.806L4.235 14.754L4.133 14.754L4.133 9.246Q4.915 9.076 5.391 8.294L5.391 8.294Q5.799 7.614 5.629 6.696L5.629 6.696ZM18.243 17.406L13.483 20.194Q12.837 19.548 11.987 19.548L11.987 19.548Q10.967 19.548 10.491 20.194L10.491 20.194L5.731 17.406L5.731 17.304L18.243 17.304L18.243 17.406Z"/>', + 'seti:hacklang': + '<path d="M11.252 0.202L11.252 0.202L11.252 6.900Q11.252 7.104 11.150 7.206L11.150 7.206L4.350 14.006L4.316 14.074Q4.282 14.142 4.248 14.142L4.248 14.142L4.248 7.342Q4.248 7.240 4.248 7.223Q4.248 7.206 4.350 7.206L4.350 7.206Q5.506 6.050 7.784 3.721Q10.062 1.392 11.252 0.202ZM19.650 9.994L19.752 9.994L19.752 16.794Q19.752 16.862 19.735 16.879Q19.718 16.896 19.650 16.896L19.650 16.896L12.748 23.798L12.612 23.798L12.612 16.998Q12.612 16.930 12.629 16.913Q12.646 16.896 12.748 16.896L12.748 16.896Q13.904 15.774 16.216 13.462Q18.528 11.150 19.752 9.994L19.752 9.994L19.650 9.994ZM12.748 8.396L19.412 8.396L12.612 15.196L12.612 8.498Q12.612 8.430 12.629 8.413Q12.646 8.396 12.748 8.396L12.748 8.396ZM11.354 8.702L11.354 8.702L11.354 15.400Q11.354 15.468 11.337 15.485Q11.320 15.502 11.252 15.502L11.252 15.502L4.554 15.502Q7.886 12.034 11.354 8.702ZM4.248 23.594L4.248 23.594Q4.248 23.560 4.248 23.560L4.248 23.560L4.248 23.594L4.248 16.896Q4.248 16.828 4.248 16.811Q4.248 16.794 4.350 16.794L4.350 16.794L11.014 16.794L8.804 19.038Q5.778 22.098 4.248 23.594Z"/>', + 'seti:haml': + '<path d="M17.267 10.696L17.267 10.696Q16.679 10.444 16.595 9.772L16.595 9.772Q16.511 9.268 16.679 8.638L16.679 8.638L16.889 8.050L18.317 6.748L18.569 6.790Q18.863 6.790 19.094 6.643Q19.325 6.496 19.409 6.286Q19.493 6.076 19.493 5.866L19.493 5.866L19.493 5.698L20.585 4.480Q20.627 4.396 20.543 4.270Q20.459 4.144 20.186 3.871Q19.913 3.598 19.367 3.199Q18.821 2.800 18.359 2.632L18.359 2.632Q18.023 2.464 17.771 2.485Q17.519 2.506 17.393 2.590L17.393 2.590L16.091 3.598L15.839 3.598Q15.587 3.640 15.419 3.724Q15.251 3.808 15.335 4.102L15.335 4.102Q15.377 4.270 15.419 4.396L15.419 4.396L10.043 8.848L7.313 2.548L7.397 2.380Q7.523 2.128 7.481 1.897Q7.439 1.666 7.229 1.540L7.229 1.540L7.019 1.498Q6.599 0.742 6.305 0.448L6.305 0.448Q6.179 0.322 6.095 0.322L6.095 0.322L6.095 0.322Q4.709-0.014 3.701 0.574L3.701 0.574Q3.197 0.868 2.945 1.246L2.945 1.246L2.945 1.246Q2.861 1.330 2.987 1.750L2.987 1.750L3.113 2.170L3.029 2.212Q2.945 2.296 2.924 2.464Q2.903 2.632 2.945 2.926L2.945 2.926Q3.113 3.514 3.449 3.556L3.449 3.556Q3.617 3.556 3.743 3.472L3.743 3.472L7.313 11.326Q7.313 11.998 4.541 22.372L4.541 22.372L4.541 22.372Q5.843 23.758 7.943 23.800L7.943 23.800Q8.993 23.800 9.791 23.548L9.791 23.548L9.791 23.548Q9.791 22.246 11.345 14.644L11.345 14.644L11.345 14.644Q12.479 15.652 13.865 16.114L13.865 16.114Q14.789 16.450 15.545 16.450L15.545 16.450Q15.545 16.996 15.671 17.374L15.671 17.374L16.091 17.500Q16.595 17.584 17.099 17.584L17.099 17.584Q17.813 17.584 18.359 17.332L18.359 17.332Q19.031 16.996 19.493 16.324L19.493 16.324Q19.619 16.198 19.619 15.946L19.619 15.946L19.997 15.736Q20.417 15.484 20.711 15.148L20.711 15.148Q21.089 14.686 21.089 14.098L21.089 14.098Q21.089 12.880 19.661 11.914L19.661 11.914Q18.821 11.326 17.267 10.696ZM19.913 15.400L19.913 15.400Q19.997 15.022 19.955 14.644L19.955 14.644Q19.871 14.350 19.745 14.140L19.745 14.140L19.619 13.972L19.535 14.182Q19.409 14.434 19.115 14.686L19.115 14.686Q18.695 14.980 18.044 15.148Q17.393 15.316 16.931 15.274L16.931 15.274Q16.595 15.190 16.385 15.022L16.385 15.022L16.217 14.896L16.049 15.148Q15.839 15.484 15.713 15.820L15.713 15.820Q12.815 15.316 11.513 13.384L11.513 13.384L11.513 13.300Q11.345 12.922 11.639 11.998L11.639 11.998L15.545 9.100Q15.377 10.276 16.385 11.032L16.385 11.032Q16.889 11.452 17.393 11.620L17.393 11.620L18.191 11.914Q19.073 12.376 19.619 12.838L19.619 12.838Q20.417 13.510 20.417 14.224L20.417 14.224Q20.501 14.686 20.291 15.022L20.291 15.022Q20.165 15.274 19.913 15.400Z"/>', + 'seti:mustache': + '<path d="M2.990 11.701L2.990 11.701Q2.990 11.259 2.888 11.157L2.888 11.157Q2.718 10.987 2.463 11.004Q2.208 11.021 2.140 11.259L2.140 11.259Q1.902 11.667 2.106 12.024Q2.310 12.381 2.786 12.551L2.786 12.551Q3.126 12.619 3.381 12.585Q3.636 12.551 3.840 12.313L3.840 12.313Q4.928 11.463 5.438 10.953L5.438 10.953L5.744 10.681Q6.356 10.137 6.696 9.933L6.696 9.933Q7.240 9.525 7.784 9.355L7.784 9.355Q9.994 8.607 11.388 9.865L11.388 9.865L12.238 10.715Q12.340 10.511 12.544 10.307L12.544 10.307Q13.564 9.151 15.128 9.151L15.128 9.151Q16.862 9.151 18.188 10.307L18.188 10.307Q18.494 10.579 19.089 11.106Q19.684 11.633 19.990 11.905L19.990 11.905Q20.500 12.381 21.044 12.551L21.044 12.551Q21.452 12.619 21.809 12.432Q22.166 12.245 22.319 11.871Q22.472 11.497 22.132 11.157L22.132 11.157Q21.826 10.885 21.486 11.055L21.486 11.055Q21.316 11.123 21.248 11.276Q21.180 11.429 21.282 11.565L21.282 11.565L21.282 11.701Q20.840 11.395 20.840 10.851Q20.840 10.307 21.486 10.103L21.486 10.103Q22.200 9.865 22.829 10.222Q23.458 10.579 23.594 11.361L23.594 11.361Q23.798 12.551 23.390 13.401L23.390 13.401Q23.186 13.911 22.710 14.217L22.710 14.217Q22.336 14.489 21.690 14.659L21.690 14.659Q20.670 14.965 19.548 14.795L19.548 14.795Q18.630 14.693 17.440 14.251L17.440 14.251L14.584 12.959Q12.646 12.075 10.844 12.551L10.844 12.551Q9.790 12.857 8.532 13.401L8.532 13.401L7.852 13.707Q6.492 14.319 5.744 14.557L5.744 14.557Q3.874 15.237 2.242 14.659L2.242 14.659Q0.202 13.911 0.338 11.803L0.338 11.803Q0.440 11.157 0.644 10.783L0.644 10.783Q0.882 10.341 1.392 10.205L1.392 10.205Q1.732 10.035 2.106 10.035Q2.480 10.035 2.786 10.205L2.786 10.205Q3.330 10.443 3.364 10.902Q3.398 11.361 2.990 11.701Z"/>', + 'seti:haskell': + '<path d="M5.673 3.564L9.853 3.564Q10.537 4.590 11.905 6.661Q13.273 8.732 13.995 9.758L13.995 9.758L16.047 12.798Q19.391 17.776 21.025 20.322L21.025 20.322L16.845 20.322L16.731 20.208Q16.199 19.372 15.078 17.700Q13.957 16.028 13.425 15.192L13.425 15.192Q13.349 15.154 13.349 15.135Q13.349 15.116 13.349 15.116Q13.349 15.116 13.349 15.135Q13.349 15.154 13.273 15.192L13.273 15.192Q12.741 16.028 11.620 17.700Q10.499 19.372 9.967 20.208L9.967 20.208L9.853 20.322L5.673 20.322L5.673 20.208Q6.585 18.840 8.428 16.104Q10.271 13.368 11.145 12L11.145 12L11.145 11.886Q10.271 10.518 8.428 7.782Q6.585 5.046 5.673 3.678L5.673 3.678L5.673 3.564ZM4.343 20.360L4.267 20.436L0.125 20.436L0.125 20.322L0.505 19.676Q1.227 18.574 1.645 18.042L1.645 18.042L5.559 12.114L5.559 12Q2.747 7.478 0.125 3.678L0.125 3.678L4.267 3.678L4.381 3.792Q4.875 4.476 5.749 5.825Q6.623 7.174 7.117 7.858L7.117 7.858L7.915 9.036Q9.245 10.974 9.853 12L9.853 12L9.853 12.114Q8.789 13.748 6.547 17.016L6.547 17.016L4.267 20.436L4.343 20.360ZM23.875 8.428L23.875 11.278L16.389 11.278L14.603 8.542L14.603 8.428L23.875 8.428ZM23.875 12.722L23.875 15.572Q23.875 15.534 23.875 15.534L23.875 15.534L23.875 15.572L19.125 15.572L17.339 12.836L17.339 12.722L23.875 12.722Z"/>', + 'seti:haxe': + '<path d="M23.802 17.376L23.676 17.250L21.072 12L23.676 6.750L23.802 6.624L23.802 0.198L17.376 0.198L17.250 0.324L12 2.928L6.750 0.324L6.624 0.198L0.198 0.198L0.198 6.624L0.324 6.750L2.928 12L0.324 17.250L0.198 17.376L0.198 23.802L6.624 23.802L6.750 23.676L12 21.072L17.250 23.676L17.376 23.802L23.802 23.802L23.802 17.376ZM22.374 1.626L19.896 11.454L12.546 4.104L22.374 1.626ZM11.496 4.104L4.146 11.454L1.626 1.626L11.496 4.104ZM1.626 22.374L4.146 12.504L11.496 19.854L1.626 22.374ZM12.546 19.854L19.896 12.504L22.374 22.374L12.546 19.854Z"/>', + 'seti:jade': + '<path d="M23.247 16.411L23.247 16.411Q22.923 14.719 23.103 12.595L23.103 12.595Q23.247 11.911 23.247 11.551L23.247 11.551Q23.283 10.975 23.103 10.435L23.103 10.435Q22.887 9.751 22.671 8.419L22.671 8.419L22.635 8.203Q22.419 6.799 22.275 6.079L22.275 6.079Q22.023 4.855 21.663 3.919L21.663 3.919Q21.447 3.523 21.267 3.343L21.267 3.343Q21.015 3.127 20.655 3.127L20.655 3.127Q19.971 3.127 19.971 3.811L19.971 3.811Q20.007 4.315 20.187 5.377Q20.367 6.439 20.403 6.943L20.403 6.943Q20.475 7.339 20.637 8.077Q20.799 8.815 20.871 9.211L20.871 9.211L20.871 9.643Q20.547 9.643 20.403 9.535L20.403 9.535L20.043 9.283Q19.431 8.851 19.179 8.527L19.179 8.527Q18.351 7.339 17.847 6.151L17.847 6.151L17.307 4.927Q16.371 2.659 15.795 1.687L15.795 1.687Q15.327 0.895 14.607 0.571L14.607 0.571Q14.031 0.319 13.095 0.319L13.095 0.319Q12.663 0.319 12.663 0.751L12.663 0.751L12.735 1.111Q12.843 1.543 12.987 1.795L12.987 1.795Q13.491 2.695 14.445 4.549Q15.399 6.403 15.903 7.303L15.903 7.303Q16.191 7.735 16.839 8.599L16.839 8.599L17.055 8.851Q17.379 9.355 17.307 9.607Q17.235 9.859 16.695 10.111L16.695 10.111L16.587 10.111L16.479 10.219Q15.327 10.507 14.355 9.535L14.355 9.535Q13.419 8.815 12.303 8.635L12.303 8.635Q12.159 8.635 11.763 8.581Q11.367 8.527 11.187 8.527L11.187 8.527Q9.819 8.419 8.883 8.491L8.883 8.491Q7.659 8.599 6.579 8.995L6.579 8.995Q4.995 9.535 3.879 10.831L3.879 10.831Q2.943 11.947 2.295 13.711L2.295 13.711Q2.079 14.395 1.647 15.943L1.647 15.943Q1.503 15.727 1.395 15.619L1.395 15.619Q1.179 15.403 1.179 15.187L1.179 15.187L1.035 15.259Q0.819 15.475 0.747 15.619L0.747 15.619L0.747 16.195Q0.747 16.627 0.963 17.095L0.963 17.095Q2.259 20.227 3.195 22.927L3.195 22.927Q3.555 23.611 4.203 23.611L4.203 23.611Q6.111 23.791 7.479 23.503L7.479 23.503L9.495 23.143Q9.063 22.711 8.847 22.603L8.847 22.603Q8.847 22.531 8.901 22.477Q8.955 22.423 8.955 22.351L8.955 22.351L10.503 22.711Q13.347 23.755 16.047 23.611L16.047 23.611Q16.659 23.611 16.803 23.143L16.803 23.143L17.163 22.495Q17.415 21.415 18.279 20.119L18.279 20.119L18.315 20.047Q18.711 19.507 18.855 19.363Q18.999 19.219 19.197 19.219Q19.395 19.219 19.863 19.363L19.863 19.363L20.187 19.435Q21.195 19.795 22.023 19.345Q22.851 18.895 23.103 17.851L23.103 17.851Q23.247 17.419 23.247 16.411ZM21.987 15.043L21.987 15.043Q21.663 15.403 21.555 15.403L21.555 15.403Q19.683 15.583 18.603 15.043L18.603 15.043Q18.351 14.971 17.955 14.539L17.955 14.539L17.703 14.287Q18.387 14.035 18.603 13.927L18.603 13.927Q20.007 13.783 21.447 14.503L21.447 14.503Q21.483 14.503 21.591 14.539L21.591 14.539L21.663 14.611Q21.987 14.935 21.987 15.043Z"/>', + 'seti:java': + '<path d="M19.896 0.198L19.896 14.940Q19.854 15.108 19.854 15.444L19.854 15.444Q19.854 16.410 19.812 16.914L19.812 16.914Q19.728 17.796 19.518 18.384L19.518 18.384Q18.972 20.106 17.733 21.387Q16.494 22.668 14.856 23.340L14.856 23.340Q14.100 23.634 13.365 23.718Q12.630 23.802 11.454 23.802L11.454 23.802Q9.060 23.802 7.338 23.130L7.338 23.130Q5.448 22.248 4.104 20.610L4.104 20.610L6.750 17.208Q7.548 18.258 8.745 18.846Q9.942 19.434 11.328 19.434L11.328 19.434Q13.176 19.434 14.205 18.216Q15.234 16.998 15.234 14.562L15.234 14.562L15.234 0.198L19.896 0.198Z"/>', + 'seti:javascript': + '<path d="M5.376 14.300L5.376 3.352L9.286 3.352L9.286 14.300Q9.286 17.842 7.630 19.452L7.630 19.452Q6.112 20.924 3.076 20.924L3.076 20.924Q2.386 20.924 1.558 20.809Q0.730 20.694 0.224 20.464L0.224 20.464L0.638 17.336Q1.512 17.750 2.662 17.750L2.662 17.750Q3.950 17.750 4.594 17.060L4.594 17.060Q5.376 16.232 5.376 14.300L5.376 14.300ZM11.862 19.912L12.736 16.600Q13.564 17.060 14.668 17.382L14.668 17.382Q15.910 17.750 17.014 17.750L17.014 17.750Q18.394 17.750 19.084 17.267Q19.774 16.784 19.774 15.910Q19.774 15.036 19.130 14.507Q18.486 13.978 16.876 13.426L16.876 13.426Q12.138 11.770 12.138 8.274L12.138 8.274Q12.138 5.974 13.909 4.525Q15.680 3.076 18.762 3.076L18.762 3.076Q21.200 3.076 23.224 3.950L23.224 3.950L22.350 7.124L22.074 6.986Q21.246 6.664 20.740 6.526L20.740 6.526Q19.774 6.250 18.762 6.250L18.762 6.250Q17.520 6.250 16.853 6.733Q16.186 7.216 16.186 7.998Q16.186 8.780 16.922 9.286L16.922 9.286Q17.474 9.700 19.314 10.436L19.314 10.436Q21.614 11.310 22.695 12.552Q23.776 13.794 23.776 15.588L23.776 15.588Q23.776 17.888 22.028 19.314L22.028 19.314Q20.142 20.924 16.738 20.924L16.738 20.924Q15.404 20.924 13.932 20.556L13.932 20.556Q12.782 20.326 11.862 19.912L11.862 19.912Z"/>', + 'seti:jinja': + '<path d="M23.919 0.975L23.919 0.975Q23.919 0.926 23.772 0.828L23.772 0.828L23.674 0.730L23.527 0.730L21.469 1.661Q17.353 3.425 11.963 3.768L11.963 3.768L7.553 4.062Q5.299 4.209 4.123 4.111L4.123 4.111Q2.261 3.964 0.742 3.278L0.742 3.278Q1.330 4.552 0.056 5.091L0.056 5.091L0.056 5.238L0.301 5.385Q0.644 5.581 0.840 5.630L0.840 5.630L1.085 5.679Q1.722 5.875 2.016 6.120L2.016 6.120Q2.702 6.610 2.898 7.247L2.898 7.247Q2.947 7.394 3.290 7.394L3.290 7.394L3.633 7.443Q4.564 7.492 5.030 7.467Q5.495 7.443 5.814 7.590Q6.132 7.737 6.083 8.031Q6.034 8.325 5.691 8.595Q5.348 8.864 4.981 8.962Q4.613 9.060 3.878 9.011L3.878 9.011L3.437 8.962Q3.094 8.913 2.972 9.035Q2.849 9.158 2.996 9.501L2.996 9.501Q3.045 9.697 3.094 10.187L3.094 10.187L3.143 10.481L5.985 10.481L5.789 14.499L3.584 14.352L3.486 13.764L4.662 12.882Q4.025 12.441 3.070 12.416Q2.114 12.392 1.036 12.833L1.036 12.833L1.281 13.029Q1.575 13.323 1.771 13.421L1.771 13.421Q2.212 13.764 2.188 13.985Q2.163 14.205 1.575 14.499L1.575 14.499Q2.065 15.332 2.163 16.410L2.163 16.410Q2.261 17.145 2.163 18.419L2.163 18.419Q2.163 18.517 2.016 18.738Q1.869 18.958 1.869 19.056L1.869 19.056L1.820 19.252Q1.624 19.987 1.771 20.134L1.771 20.134Q1.967 20.330 2.016 20.624L2.016 20.624Q2.065 20.820 2.016 21.163L2.016 21.163L2.016 21.506Q2.065 21.849 2.016 22.143L2.016 22.143Q1.918 22.731 2.555 22.682L2.555 22.682L3.731 22.682L3.437 20.428L5.397 20.428L5.152 22.437L7.602 22.437L7.602 20.232L8.925 20.134L8.925 22.290L10.395 22.290L10.395 21.702L10.444 21.065Q10.542 20.232 10.542 19.791L10.542 19.791Q10.542 19.546 10.469 19.130Q10.395 18.713 10.346 18.517L10.346 18.517L10.297 17.880Q10.199 17.145 10.199 16.753L10.199 16.753Q10.199 16.116 10.444 15.626L10.444 15.626Q10.836 14.940 10.297 14.597L10.297 14.597Q10.199 14.548 10.224 14.278Q10.248 14.009 10.371 13.837Q10.493 13.666 10.934 13.323L10.934 13.323L11.179 13.078Q9.562 12.441 7.945 13.078L7.945 13.078L8.974 14.352L8.827 14.548L7.406 14.548L7.406 10.383L15.148 9.942L14.903 14.254L13.629 14.254L13.629 13.372L14.854 12.441Q12.992 11.608 10.983 12.392L10.983 12.392L11.816 13.274Q12.110 13.568 12.086 13.715Q12.061 13.862 11.865 14.107L11.865 14.107L11.620 14.352Q11.767 14.499 11.743 14.842Q11.718 15.185 11.767 15.381Q11.816 15.577 12.061 15.724L12.061 15.724Q12.159 15.724 12.110 16.018L12.110 16.018L12.110 16.753Q12.110 17.929 12.061 18.566L12.061 18.566Q12.061 18.909 11.669 19.448L11.669 19.448L11.816 20.134Q11.963 20.967 11.963 21.359L11.963 21.359Q12.012 22.094 11.914 22.682L11.914 22.682Q11.865 22.780 12.012 23.074L12.012 23.074L12.110 23.270L13.972 23.270L13.727 20.673L15.050 20.673L15.050 22.878L17.696 22.878L17.451 20.526L18.627 20.526L18.627 22.633L18.872 22.731Q19.656 22.780 19.901 22.755Q20.146 22.731 20.195 22.486Q20.244 22.241 20.244 21.506L20.244 21.506L20.244 21.457Q20.195 21.016 20.342 20.134L20.342 20.134L20.440 19.399Q20.440 19.252 20.440 19.154L20.440 19.154Q19.999 18.419 19.999 17.439L19.999 17.439Q20.048 16.851 20.244 15.724L20.244 15.724L20.244 15.577Q20.293 15.332 20.195 14.793L20.195 14.793L20.097 14.401L20.048 13.764L21.175 12.784Q19.313 12.098 17.598 12.784L17.598 12.784Q17.696 13.029 18.113 13.299Q18.529 13.568 18.627 13.715L18.627 13.715Q18.823 14.009 18.725 14.401L18.725 14.401L17.402 14.401Q17.304 14.401 17.182 14.328Q17.059 14.254 17.059 14.156L17.059 14.156L16.471 9.942L20.391 9.599L20.440 9.158Q20.587 8.521 20.587 8.178L20.587 8.178Q20.587 8.080 20.416 7.957Q20.244 7.835 20.146 7.835L20.146 7.835L20.146 7.835Q18.872 7.884 18.333 8.080L18.333 8.080Q17.892 8.227 17.500 8.080L17.500 8.080Q17.255 7.982 16.863 7.688L16.863 7.688L16.618 7.541L16.716 7.345Q16.814 7.051 16.912 6.953L16.912 6.953Q17.157 6.610 17.353 6.561L17.353 6.561L20.097 6.169Q20.538 6.071 20.587 5.924L20.587 5.924Q20.783 5.189 21.371 4.846L21.371 4.846Q21.714 4.601 22.547 4.356L22.547 4.356L23.919 3.915L23.919 3.670Q23.968 2.102 23.919 0.975ZM5.544 15.871L5.544 18.860Q4.662 18.909 3.535 19.007L3.535 19.007L3.535 15.724L5.544 15.871ZM7.406 15.871L8.925 15.871Q8.925 16.116 8.925 16.655L8.925 16.655Q8.925 17.880 8.925 18.517L8.925 18.517Q8.925 18.811 8.778 18.860Q8.631 18.909 8.386 18.860L8.386 18.860L8.043 18.860Q7.749 18.909 7.602 18.860Q7.455 18.811 7.455 18.468L7.455 18.468L7.406 15.871ZM8.141 8.668L8.141 8.668Q7.553 8.521 7.553 8.129L7.553 8.129Q7.553 7.835 7.896 7.345L7.896 7.345L9.660 7.198L9.905 8.668L9.317 8.717Q8.484 8.766 8.141 8.668ZM14.952 15.724L14.952 19.154L13.727 19.154L13.727 15.724L14.952 15.724ZM17.304 15.773L18.725 15.724L18.725 19.007L17.500 19.105L17.304 15.773ZM12.600 8.423L12.600 8.423Q12.551 7.688 12.649 7.394Q12.747 7.100 13.139 6.977Q13.531 6.855 14.658 6.806L14.658 6.806L15.197 7.492Q14.756 8.178 14.021 8.374L14.021 8.374Q13.482 8.521 12.600 8.423Z"/>', + 'seti:julia': + '<path d="M0.164 17.896L0.164 17.896Q0.164 19.348 0.890 20.580Q1.616 21.812 2.848 22.538Q4.080 23.264 5.532 23.264Q6.984 23.264 8.216 22.538Q9.448 21.812 10.174 20.580Q10.900 19.348 10.900 17.896Q10.900 16.444 10.174 15.212Q9.448 13.980 8.216 13.254Q6.984 12.528 5.532 12.528Q4.080 12.528 2.848 13.254Q1.616 13.980 0.890 15.212Q0.164 16.444 0.164 17.896ZM13.100 17.896L13.100 17.896Q13.100 19.348 13.826 20.580Q14.552 21.812 15.784 22.538Q17.016 23.264 18.468 23.264Q19.920 23.264 21.152 22.538Q22.384 21.812 23.110 20.580Q23.836 19.348 23.836 17.896Q23.836 16.444 23.110 15.212Q22.384 13.980 21.152 13.276Q19.920 12.572 18.468 12.572Q17.016 12.572 15.784 13.276Q14.552 13.980 13.826 15.212Q13.100 16.444 13.100 17.896ZM6.632 6.104L6.632 6.104Q6.632 7.556 7.358 8.788Q8.084 10.020 9.316 10.724Q10.548 11.428 12.000 11.428Q13.452 11.428 14.684 10.724Q15.916 10.020 16.642 8.788Q17.368 7.556 17.368 6.104Q17.368 4.652 16.642 3.420Q15.916 2.188 14.684 1.462Q13.452 0.736 12.000 0.736Q10.548 0.736 9.316 1.462Q8.084 2.188 7.358 3.420Q6.632 4.652 6.632 6.104Z"/>', + 'seti:karma': + '<path d="M8.964 0.164L2.364 0.164L2.364 6.764L6.896 23.968L8.964 23.968L8.964 17.104L10.064 17.104L14.772 23.968L21.636 23.968L13.496 11.736L13.496 11.032L21.064 0.032L13.804 0.032L10.064 6.104L8.964 6.104L8.964 0.164Z"/>', + 'seti:kotlin': + '<path d="M23.739 23.739L0.261 23.739L12.043 11.957L23.739 23.739ZM0.261 12.989L0.261 0.261L12.043 0.261L0.261 12.989ZM23.739 0.261L12.043 0.261L0.261 12.645L0.261 23.739L23.739 0.261Z"/>', + 'seti:dart': + '<path d="M23.840 19.720L23.840 9.880L18.880 4.960L14.920 1Q14.600 0.640 14.060 0.400Q13.520 0.160 13.080 0.160L13.080 0.160Q12.120 0.160 11.560 0.480L11.560 0.480L4.640 3.960L4.160 4.200L0.480 11.880Q0.160 12.560 0.160 13.040L0.160 13.040Q0.160 14.240 1 15.080L1 15.080L9.760 23.840L19.720 23.840L19.720 19.720L23.840 19.720ZM5.480 4.120L11.840 0.920Q12.280 0.640 13.080 0.640L13.080 0.640Q13.400 0.640 13.840 0.860Q14.280 1.080 14.560 1.360L14.560 1.360L17.360 4.160L17.280 4.160Q16.920 4.120 16.560 4.120L16.560 4.120L5.480 4.120ZM19.200 19.560L19.200 23.320L9.960 23.320L5.320 18.680Q4.880 18.240 4.760 17.900Q4.640 17.560 4.640 16.720L4.640 16.720L4.640 5L19.200 19.560Z"/>', + 'seti:liquid': + '<path d="M14.413 15.173L14.451 15.287Q14.451 15.591 14.394 16.256Q14.337 16.921 14.337 17.225L14.337 17.225Q14.071 20.987 14.071 22.925L14.071 22.925L14.071 23.723Q14.071 23.837 14.052 23.856Q14.033 23.875 13.957 23.875L13.957 23.875L10.385 23.153Q10.119 23.077 9.568 23.020Q9.017 22.963 8.751 22.925L8.751 22.925L8.447 22.849Q7.573 22.659 7.193 22.659L7.193 22.659Q6.433 22.545 4.875 22.260Q3.317 21.975 2.557 21.823L2.557 21.823Q2.063 21.633 0.923 21.405L0.923 21.405L0.657 21.367Q0.543 21.367 0.543 21.139L0.543 21.139Q0.771 19.923 0.999 17.377L0.999 17.377L1.037 17.073Q1.037 16.959 1.094 16.674Q1.151 16.389 1.151 16.275L1.151 16.275Q1.189 16.199 1.189 16.047Q1.189 15.895 1.265 15.781L1.265 15.781Q1.303 15.477 1.379 14.850Q1.455 14.223 1.493 13.881L1.493 13.881Q1.721 12.703 1.721 11.981L1.721 11.981Q2.177 9.017 2.329 7.231L2.329 7.231Q2.329 6.775 2.785 6.509L2.785 6.509L4.951 5.825Q5.027 5.825 5.103 5.730Q5.179 5.635 5.179 5.445L5.179 5.445Q5.483 3.735 6.737 1.873L6.737 1.873Q7.497 0.733 8.485 0.239L8.485 0.239Q8.751 0.239 9.169 0.182Q9.587 0.125 9.815 0.125L9.815 0.125Q10.803 0.125 11.221 0.695L11.221 0.695L11.335 0.809L11.449 0.809Q11.943 0.809 12.342 0.999Q12.741 1.189 13.007 1.531L13.007 1.531Q13.387 2.025 13.843 2.975L13.843 2.975Q13.843 3.089 14.071 3.089L14.071 3.089L14.679 2.823Q14.869 2.823 14.888 2.861Q14.907 2.899 14.907 3.089L14.907 3.089Q14.907 3.621 14.850 4.628Q14.793 5.635 14.793 6.167L14.793 6.167Q14.717 6.813 14.660 8.181Q14.603 9.549 14.565 10.195L14.565 10.195Q14.489 11.031 14.432 12.627Q14.375 14.223 14.299 15.059L14.299 15.059L14.413 15.173ZM5.635 14.717L5.635 14.717Q6.129 15.173 6.471 15.439L6.471 15.439Q7.155 15.857 7.307 16.503L7.307 16.503Q7.421 16.959 7.231 17.282Q7.041 17.605 6.585 17.681L6.585 17.681L6.015 17.681Q5.141 17.529 4.229 16.845L4.229 16.845Q4.153 16.769 4.115 16.788Q4.077 16.807 4.001 16.959L4.001 16.959Q3.735 17.909 3.545 18.403Q3.355 18.897 3.735 19.125L3.735 19.125Q5.369 20.341 7.193 20.189L7.193 20.189Q8.181 20.075 8.865 19.562Q9.549 19.049 9.910 18.156Q10.271 17.263 10.271 16.389Q10.271 15.515 9.701 14.717L9.701 14.717Q9.701 14.641 9.644 14.584Q9.587 14.527 9.587 14.489L9.587 14.489Q9.321 14.071 8.903 13.729L8.903 13.729Q8.637 13.539 8.029 13.159L8.029 13.159Q7.801 13.045 7.307 12.589L7.307 12.589Q7.041 12.095 7.231 11.525Q7.421 10.955 8.029 10.803L8.029 10.803Q9.093 10.651 10.271 11.031L10.271 11.031Q10.347 11.107 10.423 11.050Q10.499 10.993 10.499 10.917L10.499 10.917L11.221 8.789Q11.335 8.523 11.297 8.447Q11.259 8.371 10.993 8.295L10.993 8.295Q9.891 7.991 8.485 8.181L8.485 8.181Q6.965 8.447 5.977 9.397L5.977 9.397Q4.913 10.461 4.837 11.981L4.837 11.981Q4.647 12.741 4.875 13.444Q5.103 14.147 5.635 14.717ZM10.385 1.037L10.385 1.037Q10.309 0.961 10.271 0.961L10.271 0.961L10.157 0.923Q10.005 0.847 9.663 0.923L9.663 0.923L9.321 0.923Q8.371 1.265 7.687 2.139L7.687 2.139Q6.661 3.279 6.015 5.445L6.015 5.445Q6.015 5.521 6.034 5.540Q6.053 5.559 6.129 5.559L6.129 5.559Q6.433 5.521 6.965 5.331Q7.497 5.141 7.801 5.103L7.801 5.103Q7.877 5.103 7.877 5.027L7.877 5.027L7.915 4.989Q7.915 4.837 7.972 4.609Q8.029 4.381 8.029 4.267L8.029 4.267Q8.447 3.127 8.903 2.443L8.903 2.443Q9.511 1.531 10.385 1.037ZM11.221 3.545L11.221 3.545Q11.221 2.975 10.993 1.987L10.993 1.987Q10.917 1.835 10.879 1.816Q10.841 1.797 10.765 1.873L10.765 1.873Q10.195 2.177 10.043 2.481L10.043 2.481Q9.359 3.317 8.979 4.495L8.979 4.495L8.979 4.609L9.093 4.609Q9.435 4.533 10.119 4.343L10.119 4.343L10.765 4.153Q11.107 4.039 11.164 3.963Q11.221 3.887 11.221 3.545ZM12.171 3.773L12.171 3.773Q12.437 3.659 13.121 3.431L13.121 3.431L13.121 3.317Q12.931 2.519 12.437 1.987L12.437 1.987Q12.171 1.759 11.943 1.645L11.943 1.645L11.829 1.645L11.829 1.759Q11.829 1.835 11.886 2.006Q11.943 2.177 11.943 2.253L11.943 2.253Q12.057 2.595 12.057 3.545L12.057 3.545Q12.057 3.773 12.171 3.773ZM22.735 18.289L23.115 19.581L23.457 22.089L23.457 22.203L23.343 22.317Q22.621 22.431 21.253 22.735Q19.885 23.039 19.201 23.153L19.201 23.153Q17.415 23.571 16.237 23.723L16.237 23.723L16.123 23.761Q16.047 23.761 16.047 23.742Q16.047 23.723 16.085 23.609L16.085 23.609Q16.085 22.773 16.199 22.431L16.199 22.431Q16.275 21.595 16.332 19.999Q16.389 18.403 16.465 17.567L16.465 17.567L16.465 16.389Q16.465 15.553 16.579 15.173L16.579 15.173L16.579 14.337L16.921 8.067L16.921 6.889Q17.035 5.939 17.035 4.153L17.035 4.153L17.035 2.937Q17.149 2.937 17.149 2.956Q17.149 2.975 17.149 3.089L17.149 3.089L17.643 3.545L17.909 3.773Q18.175 4.001 18.251 4.153Q18.327 4.305 18.460 4.343Q18.593 4.381 18.840 4.381Q19.087 4.381 19.619 4.438Q20.151 4.495 20.379 4.495L20.379 4.495Q20.455 4.495 20.531 4.571Q20.607 4.647 20.607 4.723L20.607 4.723Q20.683 4.989 20.740 5.464Q20.797 5.939 20.835 6.167L20.835 6.167L21.215 8.523Q21.329 9.131 21.500 10.385Q21.671 11.639 21.785 12.209L21.785 12.209Q21.975 13.235 22.279 15.249Q22.583 17.263 22.735 18.289L22.735 18.289Z"/>', + 'seti:livescript': + '<path d="M12.222 2.158L12.222 2.158L12.222 10.853Q12.296 10.853 12.314 10.835Q12.333 10.816 12.333 10.742L12.333 10.742L12.407 10.705Q12.444 10.668 12.444 10.594L12.444 10.594L12.518 10.594Q12.555 10.557 12.555 10.483L12.555 10.483Q12.666 10.483 12.684 10.483Q12.703 10.483 12.703 10.372L12.703 10.372Q12.777 10.372 12.795 10.354Q12.814 10.335 12.814 10.261L12.814 10.261Q12.925 10.261 12.925 10.039L12.925 10.039L12.925 2.972Q12.925 2.639 13.258 2.639L13.258 2.639L13.961 2.639Q14.220 2.639 14.257 2.676Q14.294 2.713 14.294 2.972L14.294 2.972L14.294 8.744L14.405 8.744Q14.516 8.744 14.534 8.744Q14.553 8.744 14.553 8.633L14.553 8.633L14.553 8.522L14.775 8.300Q14.849 8.226 14.812 8.152L14.812 8.152L14.775 8.078L14.775 3.675L16.033 3.675L16.033 6.894Q16.107 6.894 16.163 6.838Q16.218 6.783 16.255 6.783L16.255 6.783L17.550 5.525Q17.661 5.525 17.661 5.303L17.661 5.303L17.661 3.564Q17.809 3.490 18.105 3.527L18.105 3.527L18.364 3.564L18.623 3.527Q18.956 3.490 19.030 3.564Q19.104 3.638 19.067 4.008L19.067 4.008L19.030 4.267L19.030 4.822L19.067 4.933L19.178 5.044L19.104 5.044L20.214 5.044Q20.325 5.044 20.380 5.100Q20.436 5.155 20.436 5.303L20.436 5.303L20.436 6.450L20.103 6.450Q20.140 6.376 20.251 6.376Q20.362 6.376 20.436 6.339L20.436 6.339L18.808 6.339Q18.734 6.339 18.715 6.358Q18.697 6.376 18.697 6.450L18.697 6.450L18.216 6.894Q17.513 7.560 17.180 7.967L17.180 7.967Q17.180 8.078 17.439 8.078L17.439 8.078L20.214 8.078Q20.362 8.078 20.399 8.097Q20.436 8.115 20.436 8.300L20.436 8.300L20.436 9.114Q20.436 9.299 20.380 9.373Q20.325 9.447 20.103 9.447L20.103 9.447L15.922 9.447L15.848 9.447Q15.774 9.410 15.737 9.428Q15.700 9.447 15.700 9.558L15.700 9.558L14.294 10.964L20.436 10.964L20.436 12Q20.436 12.148 20.362 12.185Q20.288 12.222 20.103 12.222L20.103 12.222L12.814 12.222Q12.703 12.222 12.703 12.241Q12.703 12.259 12.703 12.333L12.703 12.333Q12.592 12.333 12.573 12.352Q12.555 12.370 12.555 12.444L12.555 12.444Q12.481 12.444 12.463 12.463Q12.444 12.481 12.444 12.592L12.444 12.592Q12.370 12.592 12.351 12.592Q12.333 12.592 12.333 12.703L12.333 12.703Q12.259 12.703 12.240 12.722Q12.222 12.740 12.222 12.814L12.222 12.814Q12.148 12.814 12.129 12.832Q12.111 12.851 12.111 12.925L12.111 12.925Q12.037 12.925 12.018 12.944Q12.000 12.962 12.037 13.036Q12.074 13.110 12.148 13.073L12.148 13.073L12.222 13.036L20.880 13.036Q20.991 13.036 21.009 13.055Q21.028 13.073 21.028 13.147L21.028 13.147L21.028 13.961Q21.028 14.220 20.972 14.276Q20.917 14.331 20.658 14.331L20.658 14.331L10.372 14.331L10.261 14.442Q10.187 14.553 10.021 14.720Q9.854 14.886 9.780 14.997L9.780 14.997Q9.854 15.071 10.039 15.034L10.039 15.034L10.150 14.997L21.583 14.997Q21.694 14.997 21.749 15.034Q21.805 15.071 21.805 15.256L21.805 15.256L21.805 16.403L8.633 16.403Q8.411 16.403 8.300 16.514L8.300 16.514L7.005 17.772Q7.005 17.846 7.153 17.883L7.153 17.883L7.264 17.883L22.989 17.883Q23.137 17.883 23.174 17.920Q23.211 17.957 23.211 18.142L23.211 18.142L23.211 20.325Q23.211 20.584 23.174 20.621Q23.137 20.658 22.841 20.658L22.841 20.658L5.858 20.658Q5.784 20.732 5.821 20.843L5.821 20.843L5.858 20.917L5.858 23.544L3.194 23.544Q3.046 23.544 3.009 23.489Q2.972 23.433 2.972 23.322L2.972 23.322L2.972 20.658Q2.898 20.584 2.842 20.621Q2.787 20.658 2.750 20.658L2.750 20.658L0.419 20.658Q0.271 20.658 0.234 20.639Q0.197 20.621 0.197 20.436L0.197 20.436L0.197 18.142Q0.197 17.957 0.252 17.920Q0.308 17.883 0.419 17.883L0.419 17.883L2.972 17.883L0.197 17.883Q0.271 17.809 0.326 17.846Q0.382 17.883 0.419 17.883L0.419 17.883L3.083 17.883Q3.194 17.772 3.083 17.661L3.083 17.661L3.083 0.900Q3.083 0.715 3.120 0.697Q3.157 0.678 3.305 0.678L3.305 0.678L5.525 0.678Q5.784 0.678 5.821 0.715Q5.858 0.752 5.858 1.011L5.858 1.011L5.858 16.958Q6.006 16.884 6.228 16.625L6.228 16.625L6.672 16.144Q7.042 15.737 7.264 15.589L7.264 15.589Q7.375 15.589 7.375 15.367L7.375 15.367L7.375 2.158Q7.523 2.084 7.930 2.158L7.930 2.158L8.189 2.158L8.411 2.158Q8.670 2.084 8.744 2.158Q8.818 2.232 8.781 2.491L8.781 2.491L8.744 2.750L8.744 13.961Q9.669 13.036 10.261 12.592L10.261 12.592Q10.335 12.518 10.372 12.407L10.372 12.407L10.372 12.333L10.372 2.158L11.630 2.158Q11.741 2.158 11.759 2.177Q11.778 2.195 11.778 2.269L11.778 2.269Q12.037 2.121 12.148 2.158L12.148 2.158L12.222 2.158Q12.111 5.044 12.111 10.594L12.111 10.594L12.111 10.853Q12.185 10.779 12.148 10.594L12.148 10.594L12.111 10.483L12.111 2.417Q12.148 2.417 12.148 2.325Q12.148 2.232 12.222 2.158ZM23.544 20.658L6.450 20.658Q6.524 20.584 6.672 20.658L6.672 20.658L6.783 20.658L23.433 20.658Q23.692 20.658 23.747 20.621Q23.803 20.584 23.803 20.325L23.803 20.325L23.803 18.142Q23.803 17.957 23.766 17.920Q23.729 17.883 23.544 17.883L23.544 17.883L7.819 17.883L7.745 17.920Q7.671 17.920 7.634 17.901Q7.597 17.883 7.597 17.772L7.597 17.772L23.655 17.772Q23.766 17.772 23.785 17.809Q23.803 17.846 23.803 17.994L23.803 17.994L23.803 20.436Q23.803 20.621 23.766 20.639Q23.729 20.658 23.544 20.658L23.544 20.658ZM6.450 0.678L6.450 16.736Q6.376 16.662 6.413 16.514L6.413 16.514L6.450 16.403L6.450 0.789Q6.450 0.530 6.394 0.475Q6.339 0.419 6.080 0.419L6.080 0.419L3.897 0.419Q3.712 0.419 3.693 0.456Q3.675 0.493 3.675 0.678L3.675 0.678L3.675 0.567Q3.564 0.456 3.582 0.438Q3.601 0.419 3.786 0.419L3.786 0.419L6.228 0.419Q6.339 0.419 6.394 0.475Q6.450 0.530 6.450 0.678L6.450 0.678ZM15.108 7.967L15.108 7.967Q15.034 7.893 15.071 7.782L15.071 7.782L15.108 7.708L15.108 2.158Q15.108 1.899 15.071 1.862Q15.034 1.825 14.775 1.825L14.775 1.825L14.072 1.825Q13.739 1.825 13.739 2.158L13.739 2.158L13.739 9.225Q13.739 9.447 13.591 9.447L13.591 9.447Q13.739 9.336 13.739 9.114L13.739 9.114L13.739 1.936Q13.739 1.751 13.757 1.733Q13.776 1.714 13.961 1.714L13.961 1.714L14.997 1.714Q15.108 1.714 15.163 1.751Q15.219 1.788 15.219 1.936L15.219 1.936L15.219 7.486Q15.108 7.708 15.108 7.967ZM11.741 13.369L11.778 13.406Q11.852 13.295 12.000 13.369L12.000 13.369L12.111 13.369L22.064 13.369Q22.323 13.406 22.360 13.351Q22.397 13.295 22.397 13.036L22.397 13.036L22.397 12.222Q22.397 12.111 22.378 12.074Q22.360 12.037 22.286 12.111L22.286 12.111L13.369 12.111L22.286 12.111Q22.471 12.111 22.489 12.148Q22.508 12.185 22.508 12.333L22.508 12.333L22.508 13.258Q22.508 13.406 22.471 13.462Q22.434 13.517 22.286 13.517L22.286 13.517L12.111 13.517Q11.889 13.369 11.741 13.369L11.741 13.369ZM7.930 2.010L7.930 1.936Q8.004 2.010 7.967 2.066Q7.930 2.121 7.930 2.158L7.930 2.158L7.930 15.108Q7.930 15.367 7.819 15.367L7.819 15.367L7.819 2.158Q7.893 2.084 7.930 2.010L7.930 2.010ZM22.286 16.292L22.286 16.292L22.286 15.108Q22.286 14.997 22.249 14.942Q22.212 14.886 22.064 14.886L22.064 14.886L10.261 14.886L21.805 14.886Q22.064 14.886 22.119 14.923Q22.175 14.960 22.175 15.256L22.175 15.256L22.175 16.181Q22.249 16.181 22.304 16.236Q22.360 16.292 22.286 16.292ZM10.853 1.936L10.853 1.936L10.853 12.111Q10.853 12.333 10.705 12.333L10.705 12.333L10.705 2.047Q10.779 2.047 10.779 1.992Q10.779 1.936 10.853 1.936ZM17.550 7.634L17.550 7.708Q17.550 7.597 17.772 7.597L17.772 7.597L21.953 7.597Q22.286 7.597 22.286 7.264L22.286 7.264L22.286 6.450Q22.286 6.265 22.249 6.247Q22.212 6.228 22.064 6.228L22.064 6.228L19.289 6.228Q19.030 6.228 19.030 6.117L19.030 6.117L22.397 6.117Q22.471 6.117 22.508 6.154L22.508 6.154L22.508 6.228L22.508 7.597L18.105 7.597Q17.846 7.597 17.735 7.616Q17.624 7.634 17.550 7.708L17.550 7.708L17.550 7.634ZM12.222 1.936L12.222 2.158Q12.148 2.232 12.185 2.343L12.185 2.343L12.222 2.417L12.222 10.594Q12.037 6.487 12.222 2.158L12.222 2.158Q12.148 2.158 12.148 2.084Q12.148 2.010 12.222 1.936L12.222 1.936ZM14.664 10.483L14.664 10.483Q14.738 10.409 14.812 10.446L14.812 10.446L14.886 10.483L21.953 10.483Q22.138 10.483 22.212 10.446Q22.286 10.409 22.286 10.261L22.286 10.261L22.286 9.225Q22.397 9.225 22.397 9.447L22.397 9.447L22.397 10.483Q22.397 10.594 22.360 10.668Q22.323 10.742 22.175 10.742L22.175 10.742Q20.473 10.557 18.401 10.520L18.401 10.520Q17.180 10.483 14.664 10.483ZM0.678 20.436L0.678 17.772L3.453 17.772L0.900 17.772Q0.715 17.772 0.696 17.809Q0.678 17.846 0.678 17.994L0.678 17.994L0.678 20.325Q0.678 20.510 0.696 20.529Q0.715 20.547 0.900 20.547L0.900 20.547L3.453 20.547L0.789 20.547Q0.678 20.547 0.678 20.529Q0.678 20.510 0.678 20.436L0.678 20.436ZM16.625 1.936L16.625 1.936L16.625 2.047Q16.625 2.010 16.588 1.955Q16.551 1.899 16.625 1.936ZM22.286 7.597L17.661 7.597L22.286 7.597ZM17.994 1.936L17.994 5.044Q17.920 5.044 17.957 4.970L17.957 4.970L17.994 4.822L17.994 1.825Q18.068 1.825 18.031 1.899L18.031 1.899L17.994 1.936ZM21.805 4.711L20.436 4.711Q20.436 4.600 20.547 4.600L20.547 4.600L22.175 4.600Q22.101 4.674 21.990 4.674Q21.879 4.674 21.805 4.711L21.805 4.711ZM19.030 6.228L22.286 6.228L19.030 6.228ZM6.339 23.581L6.339 23.544L6.339 20.658L6.339 23.322Q6.413 23.433 6.413 23.451Q6.413 23.470 6.339 23.581L6.339 23.581ZM22.323 4.267L22.286 4.711L22.286 3.564Q22.286 3.453 22.249 3.398Q22.212 3.342 22.064 3.342L22.064 3.342L20.954 3.342L22.286 3.342Q22.360 3.638 22.323 4.267L22.323 4.267ZM19.511 1.936L19.511 1.936Q19.585 1.936 19.548 2.047L19.548 2.047L19.511 2.158L19.511 3.675L19.474 3.786L19.400 3.897Q19.400 3.453 19.474 2.750L19.474 2.750Q19.511 2.195 19.511 1.936ZM14.294 10.964L14.294 10.964Q14.294 10.890 14.312 10.872Q14.331 10.853 14.405 10.853L14.405 10.853L14.368 10.853Q14.294 10.890 14.294 10.964ZM13.480 11.667L13.480 11.667Q13.480 11.556 13.498 11.538Q13.517 11.519 13.628 11.519L13.628 11.519L13.591 11.593Q13.554 11.667 13.480 11.667ZM14.183 11.038L14.183 11.075Q14.183 11.038 14.183 11.001L14.183 11.001L14.183 11.075L14.183 11.038ZM12.296 10.890L12.333 10.853Q12.333 10.890 12.333 10.927L12.333 10.927L12.333 10.853L12.296 10.890ZM14.405 10.742L14.405 10.742Q14.405 10.631 14.460 10.631Q14.516 10.631 14.405 10.742L14.405 10.742Q14.516 10.631 14.516 10.687Q14.516 10.742 14.405 10.742ZM13.850 11.297L13.850 11.297Q13.850 11.223 13.887 11.223Q13.924 11.223 13.850 11.297L13.850 11.297Q13.924 11.223 13.924 11.260Q13.924 11.297 13.850 11.297ZM12.962 10.224L13.036 10.150Q13.036 10.224 12.999 10.224Q12.962 10.224 13.036 10.150L13.036 10.150L12.962 10.224ZM13.184 10.002L13.258 9.928Q13.258 10.002 13.221 10.002Q13.184 10.002 13.258 9.928L13.258 9.928L13.184 10.002ZM13.369 11.778L13.369 11.778ZM13.258 11.926L13.258 12Q13.258 11.963 13.258 11.926L13.258 11.926L13.258 12L13.258 11.926ZM15.589 7.560L15.700 7.486Q15.700 7.560 15.644 7.560Q15.589 7.560 15.700 7.486L15.700 7.486L15.589 7.560ZM12.444 10.742L12.444 10.742ZM12.518 10.594L12.555 10.594Q12.555 10.631 12.555 10.668L12.555 10.668L12.555 10.594L12.518 10.594ZM10.742 2.158L10.853 2.158Q10.779 2.158 10.742 2.158L10.742 2.158ZM22.286 3.342L22.286 3.342ZM10.853 14.294L10.853 14.294ZM14.072 11.075L14.072 11.075ZM14.072 11.149L14.072 11.186Q14.072 11.186 14.072 11.149L14.072 11.149L14.072 11.186L14.072 11.149ZM10.964 14.294L10.964 14.294ZM13.998 11.186L13.961 11.186Q13.961 11.186 13.998 11.186L13.998 11.186L13.961 11.186L13.998 11.186ZM10.964 14.183L10.964 14.183ZM13.850 11.297L13.850 11.297ZM13.850 11.371L13.850 11.408Q13.850 11.408 13.850 11.371L13.850 11.371L13.850 11.408L13.850 11.371ZM13.776 11.408L13.739 11.408Q13.739 11.408 13.776 11.408L13.776 11.408L13.739 11.408L13.776 11.408ZM11.038 14.183L10.964 14.183Q11.001 14.183 11.038 14.183L11.038 14.183L10.964 14.183L11.038 14.183ZM13.739 11.445L13.739 11.519Q13.739 11.482 13.739 11.445L13.739 11.445L13.739 11.519L13.739 11.445ZM13.702 11.519L13.591 11.519Q13.665 11.519 13.702 11.519L13.702 11.519L13.591 11.519L13.702 11.519ZM11.075 14.109L11.075 14.183Q11.075 14.146 11.075 14.109L11.075 14.109L11.075 14.183L11.075 14.109ZM11.112 14.072L11.075 14.072Q11.075 14.072 11.112 14.072L11.112 14.072L11.075 14.072L11.112 14.072ZM13.480 11.667L13.480 11.778Q13.480 11.741 13.480 11.667L13.480 11.667L13.480 11.778L13.480 11.667ZM11.260 13.961L11.186 13.961Q11.223 13.961 11.260 13.961L11.260 13.961L11.186 13.961L11.260 13.961ZM16.514 6.635L16.514 6.561Q16.514 6.598 16.514 6.635L16.514 6.635L16.514 6.561L16.514 6.635ZM11.778 13.517L11.778 13.517ZM11.630 13.517L11.630 13.517ZM11.630 13.591L11.630 13.628Q11.630 13.591 11.630 13.591L11.630 13.591L11.630 13.628L11.630 13.591ZM11.519 13.628L11.519 13.628ZM11.482 13.739L11.408 13.739Q11.445 13.739 11.482 13.739L11.482 13.739L11.408 13.739L11.482 13.739ZM11.408 13.739L11.408 13.739ZM11.408 13.813L11.408 13.850Q11.408 13.813 11.408 13.813L11.408 13.813L11.408 13.850L11.408 13.813ZM11.334 13.850L11.297 13.850Q11.334 13.850 11.334 13.850L11.334 13.850L11.297 13.850L11.334 13.850ZM15.219 7.967L15.219 7.967ZM15.293 7.893L15.330 7.819Q15.330 7.856 15.330 7.856L15.330 7.856L15.293 7.893L15.330 7.819L15.293 7.893ZM15.367 7.819L15.478 7.708Q15.404 7.782 15.367 7.819L15.367 7.819L15.478 7.708L15.367 7.819ZM15.478 7.708L15.478 7.708ZM15.478 7.708L15.478 7.708ZM16.255 6.931L16.255 6.931ZM15.589 7.597L15.589 7.597ZM15.700 7.486L15.700 7.486ZM15.700 7.449L15.700 7.375Q15.700 7.375 15.700 7.375L15.700 7.375L15.700 7.449L15.700 7.375L15.700 7.449ZM15.811 7.375L15.811 7.375ZM15.885 7.301L15.922 7.264Q15.922 7.264 15.885 7.301L15.885 7.301L15.885 7.301L15.922 7.264L15.885 7.301ZM15.922 7.264L15.922 7.264ZM15.959 7.227L16.033 7.153Q16.033 7.153 16.033 7.153L16.033 7.153L15.959 7.227L16.033 7.153L15.959 7.227ZM16.033 7.153L16.033 7.153ZM16.107 7.079L16.144 7.042Q16.144 7.042 16.144 7.042L16.144 7.042L16.107 7.079L16.144 7.042L16.107 7.079ZM16.144 7.042L16.144 7.042ZM16.181 7.005L16.255 6.931Q16.218 6.968 16.181 7.005L16.181 7.005L16.255 6.931L16.181 7.005ZM14.220 10.964L14.183 10.964Q14.220 10.964 14.220 10.964L14.220 10.964L14.183 10.964L14.220 10.964ZM12.407 10.779L12.444 10.742Q12.444 10.742 12.444 10.742L12.444 10.742L12.407 10.779L12.444 10.742L12.407 10.779ZM14.405 10.742L14.405 10.742ZM14.553 10.631L14.553 10.631ZM12.629 10.557L12.703 10.483Q12.666 10.520 12.666 10.520L12.666 10.520L12.629 10.557L12.703 10.483L12.629 10.557ZM12.703 10.483L12.703 10.483ZM12.814 10.372L12.814 10.372ZM12.925 10.298L12.925 10.261Q12.925 10.298 12.925 10.298L12.925 10.298L12.925 10.261L12.925 10.298ZM13.036 10.150L13.036 10.150ZM13.036 10.150L13.036 10.150ZM13.258 9.928L13.258 9.928ZM13.295 9.891L13.369 9.817Q13.332 9.854 13.295 9.891L13.295 9.891L13.369 9.817L13.295 9.891ZM13.369 9.817L13.369 9.817ZM13.443 9.743L13.480 9.706Q13.480 9.706 13.480 9.706L13.480 9.706L13.443 9.743L13.480 9.706L13.443 9.743ZM13.480 9.706L13.480 9.706ZM13.628 9.558L13.628 9.558ZM16.514 6.672L16.514 6.672Z"/>', + 'seti:lua': + '<path d="M10.423 23.875L10.423 23.875Q7.649 23.875 5.274 22.488Q2.899 21.101 1.512 18.726Q0.125 16.351 0.125 13.539Q0.125 10.727 1.531 8.333Q2.937 5.939 5.293 4.609L5.293 4.609Q7.763 3.165 10.689 3.241L10.689 3.241Q13.425 3.279 15.743 4.666Q18.061 6.053 19.391 8.371L19.391 8.371Q20.759 10.765 20.759 13.558Q20.759 16.351 19.372 18.726Q17.985 21.101 15.610 22.488Q13.235 23.875 10.423 23.875ZM14.717 6.205L14.717 6.205Q13.463 6.205 12.551 7.117Q11.639 8.029 11.639 9.283Q11.639 10.537 12.513 11.449Q13.387 12.361 14.679 12.361Q15.971 12.361 16.883 11.487Q17.795 10.613 17.795 9.321Q17.795 8.029 16.902 7.117Q16.009 6.205 14.717 6.205ZM20.759 6.205L20.759 6.205Q19.505 6.205 18.612 5.312Q17.719 4.419 17.795 3.127L17.795 3.127Q17.795 1.873 18.669 0.999Q19.543 0.125 20.873 0.125L20.873 0.125Q22.127 0.125 23.001 1.056Q23.875 1.987 23.875 3.222Q23.875 4.457 22.944 5.331Q22.013 6.205 20.759 6.205Z"/>', + 'seti:markdown': + '<path d="M16.660 1.240L17.940 0.360L17.940 12.760L22.700 12.760Q19.060 16.480 11.820 23.760L11.820 23.760L1.300 12.880L5.700 12.880L5.700 0.240L6.180 0.600Q8.380 2.120 9.500 2.840L9.500 2.840Q11.500 4.120 11.920 4.120Q12.340 4.120 13.860 3.120L13.860 3.120Q14.780 2.560 16.660 1.240L16.660 1.240Z"/>', + 'seti:argdown': + '<path d="M17.421 0.261L17.421 12.780L21.750 12.780L12 23.739L2.250 12.780L6.579 12.780L6.579 0.261L10.245 2.562L10.245 16.875L12 18.864L13.755 16.875L13.755 2.562L17.421 0.261Z"/>', + 'seti:info': + '<path d="M23.780 10.803L23.818 10.803Q23.628 8.029 21.918 5.331L21.918 5.331Q20.664 3.469 18.916 2.234Q17.168 0.999 15.002 0.467L15.002 0.467Q13.748 0.125 12.646 0.125L12.646 0.125L10.746 0.125Q7.326 0.467 4.438 2.595L4.438 2.595Q1.132 5.369 0.296 9.245L0.296 9.245Q0.068 10.423 0.068 11.145L0.068 11.145L0.068 13.045Q0.448 16.351 2.082 18.631L2.082 18.631Q4.172 21.709 7.288 22.925L7.288 22.925Q9.454 23.685 11.202 23.875L11.202 23.875L13.102 23.875Q17.434 23.495 20.474 20.303L20.474 20.303Q22.944 17.833 23.666 14.375L23.666 14.375Q23.742 14.071 23.799 13.539Q23.856 13.007 23.932 12.703L23.932 12.703L23.932 11.411Q23.780 11.145 23.780 10.803L23.780 10.803ZM11.924 21.975L11.924 21.975Q9.188 21.975 6.870 20.569L6.870 20.569Q4.590 19.239 3.279 16.921Q1.968 14.603 1.968 11.867Q1.968 9.131 3.317 6.813Q4.666 4.495 6.984 3.165L6.984 3.165Q9.378 1.759 12.152 1.759L12.152 1.759Q14.850 1.835 17.149 3.184Q19.448 4.533 20.778 6.813L20.778 6.813Q22.146 9.131 22.108 11.867Q22.070 14.603 20.683 16.921Q19.296 19.239 17.016 20.569L17.016 20.569Q14.660 21.975 11.924 21.975ZM15.496 18.289L14.774 18.289Q14.432 18.289 14.166 18.175L14.166 18.175Q14.014 18.175 13.900 17.947L13.900 17.947Q13.862 17.833 13.824 17.795L13.824 17.795L13.824 10.081Q12.874 10.157 11.031 10.214Q9.188 10.271 8.238 10.309L8.238 10.309L8.238 11.259L9.416 11.259Q9.758 11.259 9.948 11.487Q10.138 11.715 10.138 12.095L10.138 12.095L10.138 17.567Q10.138 18.289 9.416 18.289L9.416 18.289L8.352 18.289L8.352 19.239L15.496 19.239L15.496 18.289ZM11.696 8.675L11.696 8.675Q12.570 8.675 13.140 8.067Q13.710 7.459 13.710 6.642Q13.710 5.825 13.102 5.217Q12.494 4.609 11.658 4.609Q10.822 4.609 10.252 5.217Q9.682 5.825 9.682 6.642Q9.682 7.459 10.290 8.067Q10.898 8.675 11.696 8.675Z"/>', + 'seti:clock': + '<path d="M11.328 0.198L11.328 0.198L12.924 0.198Q13.260 0.240 13.848 0.303Q14.436 0.366 14.772 0.450L14.772 0.450Q17.124 1.038 19.098 2.424L19.098 2.424Q20.694 3.642 21.576 5.028L21.576 5.028Q23.298 7.296 23.676 10.278L23.676 10.278Q23.676 10.404 23.739 10.698Q23.802 10.992 23.802 11.202L23.802 11.202L23.802 12.924Q23.760 13.176 23.697 13.659Q23.634 14.142 23.550 14.352L23.550 14.352Q22.920 16.914 21.597 18.804Q20.274 20.694 18.048 22.122L18.048 22.122Q16.788 22.794 15.822 23.130L15.822 23.130Q14.604 23.592 13.428 23.676L13.428 23.676Q13.302 23.676 13.050 23.739Q12.798 23.802 12.672 23.802L12.672 23.802L10.950 23.802Q10.698 23.760 10.215 23.697Q9.732 23.634 9.522 23.550L9.522 23.550Q6.960 22.920 5.070 21.597Q3.180 20.274 1.752 18.048L1.752 18.048Q1.080 16.788 0.744 15.822L0.744 15.822Q0.282 14.604 0.198 13.428L0.198 13.428Q0.282 13.344 0.240 13.071Q0.198 12.798 0.198 12.672L0.198 12.672L0.198 11.076Q0.240 10.740 0.303 10.152Q0.366 9.564 0.450 9.228L0.450 9.228Q1.038 6.876 2.424 4.902L2.424 4.902Q3.642 3.138 5.952 1.752L5.952 1.752Q8.052 0.492 10.278 0.324L10.278 0.324Q10.488 0.324 10.824 0.261Q11.160 0.198 11.328 0.198ZM2.172 12.252L2.172 12.252Q2.214 14.898 3.579 17.124Q4.944 19.350 7.212 20.673Q9.480 21.996 12.168 21.975Q14.856 21.954 17.145 20.589Q19.434 19.224 20.736 16.872Q22.038 14.520 21.996 11.748L21.996 11.748Q21.912 9.144 20.526 6.918Q19.140 4.692 16.872 3.432L16.872 3.432Q14.478 2.088 11.748 2.172L11.748 2.172Q9.144 2.214 6.918 3.558Q4.692 4.902 3.432 7.170L3.432 7.170Q2.088 9.522 2.172 12.252ZM12.546 11.958L12.546 12Q12.672 11.874 12.987 11.685Q13.302 11.496 13.428 11.328L13.428 11.328Q15.822 9.774 16.872 8.976L16.872 8.976L16.998 8.892Q17.124 8.808 17.124 8.724L17.124 8.724Q17.292 8.514 17.565 8.577Q17.838 8.640 18.027 8.829Q18.216 9.018 18.174 9.291Q18.132 9.564 17.922 9.774L17.922 9.774L15.780 11.244Q14.352 12.210 13.722 12.798L13.722 12.798L12.252 13.848Q11.958 14.016 11.643 13.890Q11.328 13.764 11.328 13.428L11.328 13.428L11.328 4.902Q11.328 4.272 11.874 4.272L11.874 4.272Q12.084 4.146 12.315 4.314Q12.546 4.482 12.546 4.776L12.546 4.776L12.546 12L12.546 11.958Z"/>', + 'seti:maven': + '<path d="M12.464 0.865L12.226 1.001Q11.818 1.341 11.138 1.851L11.138 1.851Q9.982 2.769 9.540 3.177L9.540 3.177Q8.894 3.789 8.316 4.605L8.316 4.605Q7.772 5.387 7.636 6.849Q7.500 8.311 7.908 9.671L7.908 9.671Q8.384 11.201 9.370 11.949L9.370 11.949Q9.030 11.949 7.840 11.303L7.840 11.303L6.718 10.657L8.282 12.833Q10.016 15.145 10.764 15.859L10.764 15.859Q13.280 19.531 13.926 23.747L13.926 23.747Q14.402 20.245 12.668 17.049L12.668 17.049L12.668 16.947Q12.566 16.505 12.685 16.182Q12.804 15.859 13.178 15.553L13.178 15.553Q13.722 15.247 15.966 13.105L15.966 13.105L15.966 13.105L14.708 13.819Q13.382 14.533 12.974 14.601L12.974 14.601L13.756 13.785Q14.334 13.173 14.606 12.901L14.606 12.901Q15.082 12.459 15.524 12.153L15.524 12.153Q17.598 10.487 17.224 7.699L17.224 7.699Q17.224 7.359 17.054 6.747L17.054 6.747L17.020 6.543Q16.238 3.143 13.178 0.253L13.178 0.253Q12.940 0.559 12.464 0.865L12.464 0.865Z"/>', + 'seti:nim': + '<path d="M13.806 5.334L12.086 3.829L10.237 5.291Q9.463 5.248 8.345 5.420L8.345 5.420Q7.098 5.592 6.367 5.850L6.367 5.850Q5.808 5.463 5.163 4.990L5.163 4.990L4.647 4.603L3.486 6.495Q2.282 7.140 1.594 7.785L1.594 7.785L0.089 7.140L0.562 8.129Q1.207 9.591 1.637 10.236L1.637 10.236Q2.325 11.311 3.228 11.913L3.228 11.913Q4.174 10.408 6.711 9.634L6.711 9.634Q9.033 8.903 11.979 8.946Q14.924 8.989 17.289 9.720L17.289 9.720Q19.826 10.537 20.815 11.870L20.815 11.870Q21.890 11.311 22.707 9.978L22.707 9.978Q23.137 9.204 23.825 7.441L23.825 7.441L23.911 7.226Q23.051 7.527 22.277 7.785L22.277 7.785Q22.019 7.527 21.524 7.140Q21.030 6.753 20.600 6.495L20.600 6.495L19.482 4.560L17.762 5.764Q15.053 5.248 13.806 5.334L13.806 5.334ZM1.035 11.053L1.035 11.053L3.185 16.299Q4.561 18.105 6.926 19.137L6.926 19.137Q9.205 20.126 11.849 20.169Q14.494 20.212 16.816 19.266L16.816 19.266Q19.267 18.277 20.772 16.385L20.772 16.385L23.137 11.010Q21.890 12.816 19.224 14.321L19.224 14.321Q18.751 14.579 17.676 14.794L17.676 14.794L16.687 14.966L12.043 12.558L7.356 14.923L6.367 14.751Q5.292 14.493 4.819 14.278L4.819 14.278Q3.658 13.676 2.755 12.859L2.755 12.859Q1.895 12.128 1.035 11.053L1.035 11.053Z"/>', + 'seti:github': + '<path d="M14.250 17.360L14.250 17.360Q14.516 17.284 14.972 17.227Q15.428 17.170 15.694 17.132L15.694 17.132Q18.088 16.524 18.886 14.738L18.886 14.738Q19.912 12.686 19.380 10.330L19.380 10.330Q19.266 9.874 19.038 9.418L19.038 9.418Q18.848 9.114 18.430 8.582L18.430 8.582Q18.278 8.430 18.278 8.202L18.278 8.202Q18.658 6.758 18.164 5.466L18.164 5.466Q18.164 5.390 18.069 5.314Q17.974 5.238 17.822 5.238L17.822 5.238Q17.442 5.238 17.024 5.390L17.024 5.390Q16.758 5.466 16.283 5.713Q15.808 5.960 15.086 6.416L15.086 6.416Q14.972 6.530 14.744 6.530L14.744 6.530Q11.932 5.846 9.158 6.530L9.158 6.530Q8.930 6.530 8.778 6.416L8.778 6.416L8.512 6.264Q7.790 5.846 7.448 5.694L7.448 5.694Q6.878 5.428 6.308 5.352L6.308 5.352Q5.852 5.276 5.757 5.333Q5.662 5.390 5.586 5.846L5.586 5.846Q5.244 7.062 5.586 8.316L5.586 8.316L5.586 8.544Q4.826 9.418 4.560 10.558L4.560 10.558Q4.332 11.584 4.522 12.724L4.522 12.724Q4.598 12.952 4.655 13.370Q4.712 13.788 4.750 14.016L4.750 14.016Q5.206 15.270 6.080 16.011Q6.954 16.752 8.322 17.132L8.322 17.132Q9.272 17.360 9.880 17.474L9.880 17.474Q9.386 17.930 9.158 18.880L9.158 18.880Q9.158 18.994 9.044 19.032L9.044 19.032L9.044 19.032Q8.056 19.412 7.220 19.222L7.220 19.222Q6.308 18.994 5.700 18.082L5.700 18.082Q5.092 17.018 4.028 16.866L4.028 16.866L3.458 16.866Q3.268 16.866 3.249 16.999Q3.230 17.132 3.344 17.246L3.344 17.246L3.572 17.474Q4.522 18.044 4.864 19.146L4.864 19.146Q5.244 19.906 5.852 20.305Q6.460 20.704 7.372 20.780L7.372 20.780Q8.436 20.780 9.044 20.666L9.044 20.666L9.044 22.946Q9.044 23.212 8.797 23.345Q8.550 23.478 8.208 23.402L8.208 23.402Q6.764 22.870 5.358 21.996L5.358 21.996Q2.622 20.096 1.330 17.512L1.330 17.512Q-0.038 14.890 0.114 11.660L0.114 11.660Q0.228 8.962 1.520 6.663Q2.812 4.364 4.959 2.806Q7.106 1.248 9.728 0.716L9.728 0.716Q12.768 0.146 15.694 1.096L15.694 1.096Q18.506 2.046 20.596 4.231Q22.686 6.416 23.522 9.380L23.522 9.380Q24.282 12.306 23.522 15.232L23.522 15.232Q22.762 18.082 20.748 20.267Q18.734 22.452 15.922 23.402L15.922 23.402Q15.466 23.592 15.219 23.402Q14.972 23.212 14.972 22.680L14.972 22.680L14.972 19.830Q15.086 19.070 14.934 18.500L14.934 18.500Q14.782 17.854 14.250 17.360Z"/>', + 'seti:notebook': + '<path d="M4.314 0.198L16.746 0.198Q17.838 0.198 18.615 0.975Q19.392 1.752 19.392 2.844L19.392 2.844L19.392 21.156Q19.392 22.248 18.615 23.025Q17.838 23.802 16.746 23.802L16.746 23.802L4.314 23.802Q3.222 23.802 2.445 23.025Q1.668 22.248 1.668 21.156L1.668 21.156L1.668 2.844Q1.668 1.752 2.445 0.975Q3.222 0.198 4.314 0.198L4.314 0.198ZM21.450 15.528L20.568 15.528L21.450 15.528Q21.786 15.528 22.038 15.759Q22.290 15.990 22.332 16.326L22.332 16.326L22.332 18.216Q22.332 18.552 22.122 18.783Q21.912 19.014 21.576 19.098L21.576 19.098L20.568 19.098L20.568 15.528L21.450 15.528ZM21.450 10.824L20.568 10.824L21.450 10.824Q21.786 10.824 22.038 11.034Q22.290 11.244 22.332 11.580L22.332 11.580L22.332 13.470Q22.332 13.806 22.122 14.058Q21.912 14.310 21.576 14.352L21.576 14.352L20.568 14.352L20.568 10.824L21.450 10.824ZM21.450 6.078L20.568 6.078L21.450 6.078Q21.786 6.078 22.038 6.309Q22.290 6.540 22.332 6.876L22.332 6.876L22.332 8.766Q22.332 9.102 22.122 9.333Q21.912 9.564 21.576 9.648L21.576 9.648L20.568 9.648L20.568 6.078L21.450 6.078ZM14.352 4.314L14.352 4.314L6.708 4.314Q6.372 4.314 6.120 4.545Q5.868 4.776 5.826 5.070L5.826 5.070L5.784 7.002Q5.784 7.296 6.015 7.548Q6.246 7.800 6.582 7.842L6.582 7.842L14.352 7.884Q14.688 7.884 14.940 7.653Q15.192 7.422 15.234 7.086L15.234 7.086L15.276 5.196Q15.276 4.818 15.003 4.566Q14.730 4.314 14.352 4.314Z"/>', + 'seti:nunjucks': + '<path d="M23.800 21.475L19.600 6.625L17.700 7.225Q17.050 5.075 16.050 3.425L16.050 3.425Q14.400 0.825 12.400 0.825Q10.400 0.825 8.700 3.525L8.700 3.525Q7.650 5.125 6.950 7.225L6.950 7.225L4.750 6.625L0.200 21.275L5.850 23.025L10.400 8.325L8.350 7.725Q8.800 6.025 9.850 4.425L9.850 4.425Q11.100 2.375 12.250 2.375Q13.400 2.375 14.600 4.425L14.600 4.425Q15.550 5.975 16.000 7.725L16.000 7.725L13.650 8.475L18.200 23.175L23.800 21.475Z"/>', + 'seti:npm': + '<path d="M24 7.296L0 7.296L0 15.296L6.816 15.296L6.816 16.704L12.096 16.704L12.096 15.392L24 15.392L24 7.296ZM6.592 8.704L6.592 13.984L5.312 13.984L5.312 10.112L4 10.112L4 13.984L1.312 13.984L1.312 8.704L6.592 8.704ZM13.184 13.984L13.216 13.984L10.496 13.984L10.496 15.392L7.808 15.392L7.808 8.800L13.088 8.800Q13.216 10.400 13.184 13.984L13.184 13.984ZM22.592 8.704L22.592 13.984L21.312 13.984L21.312 10.112L20 10.112L20 13.984L18.592 13.984L18.592 10.112L17.312 10.112L17.312 13.984L14.592 13.984L14.592 8.704L22.592 8.704ZM11.904 12.704L11.904 10.112L10.592 10.112L10.592 12.704L11.904 12.704Z"/>', + 'seti:ocaml': + '<path d="M23.306 21.102L23.343 21.028L23.343 5.414Q23.343 4.489 23.195 4.008L23.195 4.008Q23.047 3.083 22.048 2.306L22.048 2.306Q21.715 2.047 21.530 1.973L21.530 1.973Q21.197 1.825 20.901 1.825L20.901 1.825Q20.827 1.825 20.808 1.806Q20.790 1.788 20.790 1.714L20.790 1.714L2.623 1.714Q2.623 1.936 2.179 1.936L2.179 1.936Q0.884 2.417 0.329 3.897L0.329 3.897Q0.218 4.156 0.218 4.600L0.218 4.600L0.218 9.928Q0.218 10.187 0.255 10.206Q0.292 10.224 0.551 10.150L0.551 10.150L1.143 9.928Q1.439 9.854 1.735 9.373L1.735 9.373Q1.846 9.188 1.920 9.114L1.920 9.114L2.031 8.966Q2.327 8.485 2.623 8.300L2.623 8.300Q2.808 8.115 2.993 8.115Q3.178 8.115 3.437 8.300L3.437 8.300L3.696 8.485Q4.029 8.707 4.251 8.781L4.251 8.781Q4.991 9.003 5.398 8.892L5.398 8.892Q5.620 8.892 5.731 8.707L5.731 8.707Q5.842 8.633 5.953 8.411L5.953 8.411L5.990 8.300Q6.212 7.856 6.360 7.745Q6.508 7.634 6.619 7.634L6.619 7.634L7.026 7.597Q7.470 7.671 7.914 8.078L7.914 8.078Q8.173 8.300 8.654 8.892L8.654 8.892Q8.802 9.188 9.098 9.336L9.098 9.336Q9.320 9.447 9.801 9.928L9.801 9.928Q10.134 10.335 10.948 10.964L10.948 10.964Q11.503 11.408 11.762 11.667L11.762 11.667Q12.391 12.259 13.168 12.592L13.168 12.592Q13.760 12.777 14.130 12.740L14.130 12.740Q14.611 12.666 15.018 12.111L15.018 12.111Q15.758 11.186 15.943 10.150L15.943 10.150Q16.017 9.928 16.313 9.521L16.313 9.521L16.498 9.225L16.609 9.225Q17.275 9.114 18.237 9.336L18.237 9.336Q18.570 9.336 18.829 9.447L18.829 9.447L19.273 9.558Q19.902 9.669 20.216 9.817Q20.531 9.965 20.642 10.279Q20.753 10.594 20.679 10.964L20.679 10.964Q20.605 11.186 20.549 11.223Q20.494 11.260 20.383 11.223Q20.272 11.186 20.198 11.186L20.198 11.186L19.865 11.186Q19.384 11.297 18.459 11.778L18.459 11.778Q18.274 11.852 18.144 12.018Q18.015 12.185 18.015 12.370L18.015 12.370Q17.830 13.036 17.312 13.406L17.312 13.406L17.238 13.480Q17.090 13.554 17.090 13.739L17.090 13.739Q16.979 13.813 16.849 13.980Q16.720 14.146 16.609 14.220L16.609 14.220Q15.536 15.293 13.612 15.478L13.612 15.478L11.762 15.478Q11.614 15.478 11.577 15.534Q11.540 15.589 11.540 15.700L11.540 15.700Q11.577 15.922 11.577 16.384Q11.577 16.847 11.669 17.087Q11.762 17.328 11.762 17.772L11.762 17.772Q11.762 18.475 12.354 19.067L12.354 19.067Q12.465 19.178 12.465 19.400L12.465 19.400Q12.465 20.214 12.576 20.547L12.576 20.547L12.613 20.806Q12.835 21.694 13.020 22.064L13.020 22.064Q13.168 22.175 13.242 22.212Q13.316 22.249 13.408 22.194Q13.501 22.138 13.723 22.064Q13.945 21.990 14.093 21.953L14.093 21.953Q14.463 21.805 15.018 21.731L15.018 21.731Q15.351 21.731 16.054 21.731L16.054 21.731Q16.424 21.731 17.201 21.694L17.201 21.694Q18.163 21.620 18.644 21.657L18.644 21.657Q19.421 21.657 20.087 21.842L20.087 21.842Q20.309 21.879 20.716 21.934Q21.123 21.990 21.345 22.064L21.345 22.064Q21.826 22.212 22.344 22.249L22.344 22.249Q22.677 22.286 23.343 22.286L23.343 22.286Q23.787 22.286 23.787 21.842L23.787 21.842Q23.454 21.583 23.380 21.435Q23.306 21.287 23.306 21.102L23.306 21.102ZM5.620 18.031L5.620 17.772L5.768 17.661Q5.953 16.662 6.545 16.033L6.545 16.033L6.434 16.033Q5.361 16.033 4.140 15.700L4.140 15.700Q2.993 15.478 2.401 14.886L2.401 14.886Q2.142 14.627 1.827 14.701Q1.513 14.775 1.365 15.145L1.365 15.145Q1.365 15.182 1.309 15.348Q1.254 15.515 1.254 15.589L1.254 15.589Q0.884 16.292 0.440 16.736L0.440 16.736Q0.181 17.217 0.218 17.550L0.218 17.550L0.218 19.733Q0.218 20.103 0.551 20.140Q0.884 20.177 1.439 20.362L1.439 20.362Q1.846 20.510 2.031 20.547L2.031 20.547L2.586 20.732Q3.622 21.139 4.140 21.139L4.140 21.139Q4.473 21.139 4.547 21.084Q4.621 21.028 4.695 20.658L4.695 20.658Q4.695 20.621 4.769 20.566Q4.843 20.510 4.843 20.436L4.843 20.436L4.695 20.436L4.843 20.436L4.843 20.214L4.843 20.325Q4.843 20.288 4.898 20.214Q4.954 20.140 4.954 20.103L4.954 20.103L4.954 19.992Q5.065 19.733 5.065 19.400L5.065 19.400Q5.065 18.956 5.176 18.808L5.176 18.808L5.176 18.697Q5.361 18.623 5.583 18.179L5.583 18.179L5.620 18.031ZM11.429 19.992L11.429 19.992Q11.133 19.696 10.948 19.178L10.948 19.178Q10.948 18.808 10.837 18.808L10.837 18.808Q10.837 18.549 10.689 18.105L10.689 18.105L10.615 17.883Q10.245 16.699 9.209 15.811L9.209 15.811Q8.765 15.552 8.524 15.571Q8.284 15.589 7.951 15.922L7.951 15.922Q7.877 15.996 7.821 16.107Q7.766 16.218 7.729 16.292L7.729 16.292Q7.026 17.439 6.693 18.142L6.693 18.142L6.619 18.253Q6.434 18.549 6.434 18.845L6.434 18.845Q6.360 18.882 6.304 19.085Q6.249 19.289 6.212 19.400L6.212 19.400Q5.916 19.696 5.546 20.510L5.546 20.510L5.398 20.806Q5.398 20.843 5.361 20.898Q5.324 20.954 5.398 21.028L5.398 21.028L5.620 21.028Q6.545 20.806 7.026 20.547L7.026 20.547Q8.025 20.066 9.209 20.436L9.209 20.436Q9.690 20.621 10.134 20.880L10.134 20.880Q10.430 21.065 10.948 21.472L10.948 21.472Q11.318 21.731 11.984 21.953L11.984 21.953L12.243 21.953L12.243 21.842Q12.058 21.509 11.873 20.954L11.873 20.954Q11.614 20.288 11.429 19.992Z"/>', + 'seti:odata': + '<path d="M20.586 0.324L20.586 0.324L3.534 0.324Q2.148 0.324 1.203 1.269Q0.258 2.214 0.258 3.600L0.258 3.600L0.258 20.400Q0.258 21.786 1.203 22.731Q2.148 23.676 3.534 23.676L3.534 23.676L20.460 23.676Q21.846 23.676 22.791 22.731Q23.736 21.786 23.736 20.400L23.736 20.400L23.736 3.600Q23.820 2.214 22.896 1.269Q21.972 0.324 20.586 0.324ZM6.684 21.072L6.684 21.072Q5.298 21.072 4.290 20.043Q3.282 19.014 3.282 17.649Q3.282 16.284 4.290 15.255Q5.298 14.226 6.684 14.226Q8.070 14.226 9.078 15.255Q10.086 16.284 10.086 17.670Q10.086 19.056 9.099 20.064Q8.112 21.072 6.684 21.072ZM11.682 12.504L11.808 12.504L3.408 12.504L3.408 10.278L11.682 10.278L11.682 12.504ZM11.682 9.228L11.808 9.228L3.408 9.228L3.408 7.002L11.682 7.002L11.682 9.228ZM11.682 5.952L11.808 5.952L3.408 5.952L3.408 3.852L11.682 3.852L11.682 5.952ZM20.712 13.302L20.712 15.528L12.438 15.528L12.438 13.302L20.712 13.302ZM20.712 10.152L20.712 12.378L12.438 12.378L12.438 10.152L20.712 10.152ZM20.712 6.876L20.712 9.102L12.438 9.102L12.438 6.876L20.712 6.876ZM20.712 3.726L20.712 5.952L12.438 5.952L12.438 3.726L20.712 3.726Z"/>', + 'seti:perl': + '<path d="M9.194 22.393L8.966 23.875L7.180 23.875Q7.218 23.723 7.275 23.362Q7.332 23.001 7.408 22.925L7.408 22.925Q8.054 22.697 8.206 22.165L8.206 22.165Q8.320 21.861 8.282 21.101L8.282 21.101L8.244 20.569L8.244 13.197Q7.826 13.121 6.952 13.045L6.952 13.045Q6.268 12.969 5.926 12.931L5.926 12.931Q5.394 12.817 5.052 12.627L5.052 12.627Q3.114 11.373 2.563 9.454Q2.012 7.535 2.886 5.369L2.886 5.369Q3.494 4.001 2.050 3.811L2.050 3.811Q1.822 3.811 1.100 3.583L1.100 3.583L1.100 3.355Q1.480 3.165 2.126 2.747Q2.772 2.329 3.152 2.177L3.152 2.177Q3.228 2.101 3.494 2.101L3.494 2.101Q3.950 2.063 4.102 1.911L4.102 1.911Q5.090 1.417 5.584 1.341Q6.078 1.265 6.458 1.626Q6.838 1.987 7.408 2.975L7.408 2.975Q7.826 3.849 7.788 4.685Q7.750 5.521 7.294 6.433L7.294 6.433Q6.914 7.079 6.876 7.421L6.876 7.421Q6.800 7.991 7.408 8.219L7.408 8.219L8.168 7.155Q9.536 5.179 10.296 4.267L10.296 4.267Q11.512 2.747 12.766 1.835L12.766 1.835Q14.248 0.695 15.958 0.125L15.958 0.125L16.794 0.125Q17.022 0.467 17.592 1.075L17.592 1.075Q18.428 1.949 18.694 2.519L18.694 2.519Q19.302 3.507 20.366 5.559L20.366 5.559Q21.544 7.839 22.266 8.941L22.266 8.941Q22.722 9.625 22.855 10.689Q22.988 11.753 22.722 12.722Q22.456 13.691 21.886 14.147L21.886 14.147L21.886 10.005L21.430 10.005Q20.898 10.765 20.822 11.791L20.822 11.791Q20.746 12.399 20.860 13.691L20.860 13.691Q20.936 14.641 20.936 15.097L20.936 15.097Q20.936 16.617 20.898 19.581L20.898 19.581Q20.822 22.469 20.822 23.875L20.822 23.875L19.986 23.875L19.986 23.571Q19.910 23.191 19.986 22.925L19.986 22.925Q20.708 17.491 18.694 12.019L18.694 12.019Q17.212 13.349 17.022 15.591L17.022 15.591Q16.946 16.313 16.718 17.187L16.718 17.187Q16.566 17.719 16.186 18.783L16.186 18.783Q16.110 19.011 15.882 19.429L15.882 19.429Q15.540 20.113 15.502 20.455L15.502 20.455Q15.464 21.025 16.072 21.519L16.072 21.519Q16.148 21.595 16.053 22.070Q15.958 22.545 15.958 22.811L15.958 22.811L15.502 22.241Q15.160 21.785 15.008 21.633L15.008 21.633L15.008 22.013Q14.590 22.127 13.697 22.298Q12.804 22.469 12.386 22.583L12.386 22.583Q12.386 22.545 12.329 22.355Q12.272 22.165 12.272 22.127L12.272 22.127Q12.766 21.861 12.994 21.633L12.994 21.633Q13.868 21.101 13.963 20.550Q14.058 19.999 13.336 19.391L13.336 19.391Q11.018 17.567 12.044 14.983L12.044 14.983Q12.196 14.679 12.234 13.919L12.234 13.919Q12.234 13.349 12.272 12.969L12.272 12.969L11.588 13.349Q11.094 13.577 10.942 13.691L10.942 13.691Q10.676 13.881 10.638 14.033L10.638 14.033Q10.182 15.705 9.726 19.201L9.726 19.201L9.688 19.505Q9.422 20.569 9.194 22.393L9.194 22.393ZM12.994 17.605L14.438 19.391Q15.654 17.795 15.844 16.123Q16.034 14.451 15.122 13.197L15.122 13.197Q13.716 16.047 12.994 17.605L12.994 17.605Z"/>', + 'seti:php': + '<path d="M8.154 16.514L8.154 16.514Q7.964 15.298 6.976 14.956L6.976 14.956L6.140 14.462Q5.418 14.234 5.190 14.120L5.190 14.120Q4.848 13.968 4.468 14.348L4.468 14.348Q4.316 14.690 4.582 14.956L4.582 14.956Q4.696 15.184 5.076 15.564L5.076 15.564Q5.304 15.906 5.912 16.514L5.912 16.514L5.988 16.628Q6.178 16.894 6.216 17.046L6.216 17.046Q6.330 17.274 6.254 17.578L6.254 17.578Q6.064 18.946 5.190 19.820L5.190 19.820Q5.114 19.896 5.000 19.934L5.000 19.934L4.962 19.934Q4.696 19.934 4.373 19.801Q4.050 19.668 3.860 19.478L3.860 19.478Q3.632 19.212 3.670 18.965Q3.708 18.718 4.012 18.528L4.012 18.528Q4.088 18.528 4.164 18.452Q4.240 18.376 4.240 18.262L4.240 18.262Q4.620 17.882 4.468 17.464L4.468 17.464Q4.392 17.388 4.335 17.274Q4.278 17.160 4.240 17.084L4.240 17.084Q3.746 16.628 2.568 15.678L2.568 15.678Q0.364 13.968 0.212 11.384L0.212 11.384Q0.022 8.648 1.504 6.064L1.504 6.064Q2.150 4.962 3.062 4.506L3.062 4.506Q3.518 4.278 4.468 4.012L4.468 4.012Q6.862 3.366 8.610 3.670L8.610 3.670Q10.624 4.088 11.118 5.684L11.118 5.684Q11.498 7.052 11.346 8.078L11.346 8.078Q11.270 9.294 10.415 10.282Q9.560 11.270 8.382 11.612L8.382 11.612Q7.850 11.802 7.546 11.707Q7.242 11.612 6.976 11.156L6.976 11.156L6.786 10.890Q6.330 10.206 6.140 9.864L6.140 9.864L6.140 9.712Q6.140 9.674 6.083 9.617Q6.026 9.560 6.026 9.484L6.026 9.484Q6.140 10.206 6.216 10.548L6.216 10.548Q6.368 11.118 6.596 11.498L6.596 11.498Q6.824 11.802 7.033 11.954Q7.242 12.106 7.546 12.106L7.546 12.106Q9.864 12.296 11.232 10.548L11.232 10.548Q12.562 8.724 12.182 6.064L12.182 6.064Q12.182 5.760 12.030 5.304L12.030 5.304L11.954 5.114Q11.954 4.886 11.992 4.791Q12.030 4.696 12.182 4.620L12.182 4.620Q12.410 4.620 12.410 4.506L12.410 4.506Q14.462 4.088 16.096 4.278L16.096 4.278Q18.452 4.468 20.010 5.570L20.010 5.570Q22.746 7.280 23.696 10.662L23.696 10.662Q23.810 11.042 23.810 11.612L23.810 11.612Q23.810 11.802 23.734 11.821Q23.658 11.840 23.487 11.745Q23.316 11.650 23.088 11.422L23.088 11.422L23.012 11.270Q22.936 11.232 22.822 11.042Q22.708 10.852 22.632 10.776Q22.556 10.700 22.480 10.700Q22.404 10.700 22.404 10.776Q22.404 10.852 22.347 10.966Q22.290 11.080 22.290 11.156L22.290 11.156Q21.682 13.208 20.618 14.234L20.618 14.234Q20.542 14.348 20.466 14.481Q20.390 14.614 20.390 14.728L20.390 14.728L20.352 15.184Q20.314 15.830 20.390 16.134L20.390 16.134L20.732 19.098Q20.808 19.516 20.675 19.744Q20.542 19.972 20.124 20.162L20.124 20.162Q19.440 20.428 18.946 20.428L18.946 20.428L17.046 20.428Q17.046 19.706 16.970 19.402L16.970 19.402Q16.856 18.870 16.476 18.642L16.476 18.642Q16.704 17.692 16.837 17.084Q16.970 16.476 16.590 15.906L16.590 15.906Q16.286 15.450 15.640 15.678L15.640 15.678Q14.348 16.476 12.676 15.906L12.676 15.906Q12.258 15.792 12.011 15.868Q11.764 15.944 11.612 16.248L11.612 16.248Q11.232 16.970 11.232 17.692Q11.232 18.414 11.460 19.592L11.460 19.592Q11.460 19.896 11.422 19.991Q11.384 20.086 11.118 20.162L11.118 20.162Q9.978 20.504 8.762 20.314L8.762 20.314L8.610 20.314Q8.610 19.592 8.534 19.288L8.534 19.288Q8.344 18.756 7.812 18.528L7.812 18.528Q8.382 17.920 8.154 16.514ZM3.290 13.778L3.290 13.778Q3.518 13.512 3.518 13.284L3.518 13.284Q3.594 13.018 3.404 12.676Q3.214 12.334 2.910 12.220L2.910 12.220Q2.758 12.144 2.663 12.182Q2.568 12.220 2.454 12.334L2.454 12.334Q2.264 12.524 1.979 12.885Q1.694 13.246 1.504 13.398L1.504 13.398Q1.504 13.474 1.447 13.531Q1.390 13.588 1.390 13.664L1.390 13.664Q1.276 13.816 1.352 13.968Q1.428 14.120 1.618 14.120L1.618 14.120Q1.960 14.120 2.112 14.234L2.112 14.234Q2.796 14.234 3.290 13.778ZM3.290 9.864L3.290 9.864Q3.290 9.674 3.138 9.522Q2.986 9.370 2.796 9.370Q2.606 9.370 2.435 9.541Q2.264 9.712 2.340 9.978L2.340 9.978Q2.340 10.168 2.511 10.301Q2.682 10.434 2.910 10.434L2.910 10.434Q3.290 10.092 3.290 9.864Z"/>', + 'seti:pipeline': + '<path d="M15.948 15.948L15.948 18.888L7.926 18.888Q7.800 18.384 7.506 17.922L7.506 17.922L17.922 7.506Q18.804 8.052 19.896 8.052L19.896 8.052Q21.408 8.052 22.542 7.023Q23.676 5.994 23.802 4.461Q23.928 2.928 22.983 1.710Q22.038 0.492 20.526 0.240Q19.014-0.012 17.733 0.828Q16.452 1.668 16.074 3.138L16.074 3.138L7.926 3.138Q7.548 1.710 6.330 0.870Q5.112 0.030 3.621 0.219Q2.130 0.408 1.164 1.521Q0.198 2.634 0.198 4.125Q0.198 5.616 1.164 6.729Q2.130 7.842 3.621 8.031Q5.112 8.220 6.330 7.380Q7.548 6.540 7.926 5.112L7.926 5.112L16.074 5.112Q16.200 5.616 16.494 6.078L16.494 6.078L6.078 16.494Q5.196 15.948 4.146 15.948L4.146 15.948Q2.592 15.948 1.458 16.977Q0.324 18.006 0.198 19.539Q0.072 21.072 1.017 22.290Q1.962 23.508 3.474 23.760Q4.986 24.012 6.267 23.172Q7.548 22.332 7.926 20.862L7.926 20.862L15.948 20.862L15.948 23.802L23.802 23.802L23.802 15.948L15.948 15.948ZM4.146 6.078L4.146 6.078Q3.432 6.078 2.886 5.637Q2.340 5.196 2.214 4.503Q2.088 3.810 2.403 3.201Q2.718 2.592 3.369 2.319Q4.020 2.046 4.692 2.256Q5.364 2.466 5.763 3.033Q6.162 3.600 6.099 4.314Q6.036 5.028 5.532 5.532L5.532 5.532Q4.944 6.078 4.146 6.078ZM19.854 2.172L19.854 2.172Q20.484 2.172 20.967 2.487Q21.450 2.802 21.681 3.369Q21.912 3.936 21.807 4.524Q21.702 5.112 21.282 5.532Q20.862 5.952 20.274 6.057Q19.686 6.162 19.119 5.931Q18.552 5.700 18.237 5.217Q17.922 4.734 17.922 4.104L17.922 4.104Q17.922 3.306 18.489 2.739Q19.056 2.172 19.854 2.172ZM4.146 21.828L4.146 21.828Q3.306 21.828 2.739 21.261Q2.172 20.694 2.172 19.875Q2.172 19.056 2.739 18.489Q3.306 17.922 4.125 17.922Q4.944 17.922 5.532 18.489Q6.120 19.056 6.120 19.875Q6.120 20.694 5.532 21.261Q4.944 21.828 4.146 21.828ZM17.922 21.828L17.922 17.922L21.828 17.922L21.828 21.828L17.922 21.828Z"/>', + 'seti:pddl': + '<path d="M4.608 21.520L4.608 21.800L2.480 21.800Q2.004 20.792 1.598 19.728Q1.192 18.664 0.912 17.432L0.912 17.432Q0.632 16.312 0.478 14.912Q0.324 13.512 0.324 12L0.324 12Q0.324 10.376 0.492 9.032Q0.660 7.688 0.912 6.596L0.912 6.596Q1.192 5.392 1.584 4.314Q1.976 3.236 2.480 2.200L2.480 2.200L4.608 2.200L4.608 2.508Q4.132 3.236 3.712 4.146Q3.292 5.056 2.942 6.274Q2.592 7.492 2.368 8.934Q2.144 10.376 2.144 12L2.144 12Q2.144 13.708 2.354 15.094Q2.564 16.480 2.928 17.712L2.928 17.712Q3.264 18.888 3.698 19.854Q4.132 20.820 4.608 21.520L4.608 21.520ZM23.676 12L23.676 12Q23.676 13.512 23.522 14.898Q23.368 16.284 23.088 17.432L23.088 17.432Q22.808 18.664 22.402 19.728Q21.996 20.792 21.520 21.800L21.520 21.800L19.392 21.800L19.392 21.520Q19.840 20.820 20.288 19.854Q20.736 18.888 21.086 17.684Q21.436 16.480 21.646 15.094Q21.856 13.708 21.856 12L21.856 12Q21.856 10.376 21.632 8.934Q21.408 7.492 21.058 6.274Q20.708 5.056 20.288 4.146Q19.868 3.236 19.392 2.508L19.392 2.508L19.392 2.200L21.520 2.200Q22.024 3.236 22.416 4.314Q22.808 5.392 23.088 6.596L23.088 6.596Q23.340 7.688 23.508 9.032Q23.676 10.376 23.676 12ZM6.260 10.068L6.260 10.068Q5.476 10.068 4.958 9.522Q4.440 8.976 4.440 8.150Q4.440 7.324 4.972 6.792Q5.504 6.260 6.316 6.260Q7.128 6.260 7.646 6.792Q8.164 7.324 8.164 8.164Q8.164 9.004 7.632 9.536Q7.100 10.068 6.260 10.068ZM6.260 18.552L6.260 18.552Q5.476 18.552 4.958 17.992Q4.440 17.432 4.440 16.606Q4.440 15.780 4.972 15.248Q5.504 14.716 6.316 14.716Q7.128 14.716 7.646 15.262Q8.164 15.808 8.164 16.634Q8.164 17.460 7.632 18.006Q7.100 18.552 6.260 18.552ZM18.972 11.160L18.972 18.244L15.976 18.244L15.976 16.564L15.920 16.564Q14.884 18.552 12.868 18.552L12.868 18.552Q11.384 18.552 10.530 17.572Q9.676 16.592 9.676 14.968L9.676 14.968Q9.676 11.496 13.204 10.964L13.204 10.964L15.976 10.544Q15.976 8.612 14.156 8.612Q12.336 8.612 10.684 9.872L10.684 9.872L10.684 7.100Q11.328 6.708 12.476 6.414Q13.624 6.120 14.576 6.120L14.576 6.120Q18.972 6.120 18.972 11.160L18.972 11.160ZM16.004 13.428L16.004 13.428L16.004 12.644L14.128 12.924Q12.588 13.148 12.588 14.520L12.588 14.520Q12.588 15.164 12.966 15.556Q13.344 15.948 13.988 15.948L13.988 15.948Q14.856 15.948 15.430 15.234Q16.004 14.520 16.004 13.428Z"/>', + 'seti:plan': + '<path d="M0.127 6.839L0.127 0.608L16.929 0.608L16.929 6.839L0.127 6.839ZM7.040 15.116L7.040 8.885L23.873 8.885L23.873 15.116L7.040 15.116ZM17.053 23.393L17.053 17.162L23.873 17.162L23.873 23.393L17.053 23.393Z"/>', + 'seti:happenings': + '<path d="M7.635 6.765L7.635 0.735L23.925 0.735L23.925 6.765L7.635 6.765ZM0.015 3.735L0.015 3.735Q0.015 4.845 0.735 5.610Q1.455 6.375 2.475 6.375Q3.495 6.375 4.230 5.610Q4.965 4.845 4.965 3.750Q4.965 2.655 4.230 1.890Q3.495 1.125 2.475 1.125Q1.455 1.125 0.735 1.890Q0.015 2.655 0.015 3.735ZM7.695 15.015L7.695 8.985L23.985 8.985L23.985 15.015L7.695 15.015ZM0.075 11.985L0.075 11.985Q0.075 13.065 0.795 13.830Q1.515 14.595 2.550 14.595Q3.585 14.595 4.305 13.830Q5.025 13.065 5.025 11.985Q5.025 10.905 4.305 10.140Q3.585 9.375 2.550 9.375Q1.515 9.375 0.795 10.140Q0.075 10.905 0.075 11.985ZM7.695 23.265L7.695 17.205L23.985 17.205L23.985 23.265L7.695 23.265ZM0.075 20.235L0.075 20.235Q0.075 21.315 0.795 22.080Q1.515 22.845 2.550 22.845Q3.585 22.845 4.305 22.080Q5.025 21.315 5.025 20.235Q5.025 19.155 4.305 18.390Q3.585 17.625 2.550 17.625Q1.515 17.625 0.795 18.390Q0.075 19.155 0.075 20.235Z"/>', + 'seti:powershell': + '<path d="M0.090 22.968L0.090 17.023L9.438 11.980L0.131 6.322L0.131 0.336L15.875 10.504L15.875 13.948L0.090 22.968ZM23.910 20.262L23.910 23.665L10.258 23.665L10.258 20.262L23.910 20.262Z"/>', + 'seti:prisma': + '<path d="M20.093 18.987L20.093 18.987L9.113 22.155Q8.861 22.227 8.663 22.047Q8.465 21.867 8.537 21.651L8.537 21.651L12.461 3.327Q12.497 3.075 12.785 3.039Q13.073 3.003 13.181 3.255L13.181 3.255L20.417 18.267Q20.525 18.483 20.435 18.699Q20.345 18.915 20.093 18.987ZM22.001 18.231L22.001 18.231L13.577 0.843Q13.397 0.519 13.091 0.321Q12.785 0.123 12.425 0.087Q12.065 0.051 11.723 0.231Q11.381 0.411 11.201 0.699L11.201 0.699L2.093 15.099Q1.877 15.423 1.877 15.819Q1.877 16.215 2.093 16.539L2.093 16.539L6.557 23.271Q6.737 23.595 7.061 23.757Q7.385 23.919 7.745 23.919L7.745 23.919Q7.961 23.919 8.177 23.847L8.177 23.847L21.101 20.139Q21.713 19.959 21.983 19.383Q22.253 18.807 22.001 18.231Z"/>', + 'seti:pug': + '<path d="M16.267 5.578L16.267 5.578L16.267 5.578L16.267 5.578ZM13.717 12.276L13.717 12.276Q13.343 12.106 13.207 11.885Q13.071 11.664 12.782 11.562Q12.493 11.460 12.170 11.460Q11.847 11.460 11.558 11.562Q11.269 11.664 11.116 11.885Q10.963 12.106 10.623 12.276L10.623 12.276Q9.569 12.752 8.957 13.755Q8.345 14.758 8.413 15.914L8.413 15.914Q8.379 15.914 8.464 16.509Q8.549 17.104 8.651 17.546L8.651 17.546Q8.821 18.158 8.991 18.277Q9.161 18.396 10.147 18.566L10.147 18.566Q11.337 18.804 12.170 18.804Q13.003 18.804 14.227 18.566L14.227 18.566Q15.247 18.396 15.417 18.277Q15.587 18.158 15.723 17.546L15.723 17.546Q15.825 17.104 15.893 16.458L15.893 16.458Q15.961 15.914 15.927 15.914L15.927 15.914Q15.961 14.758 15.366 13.755Q14.771 12.752 13.717 12.276ZM22.455 8.094L22.455 8.094Q22.285 7.958 21.979 7.652L21.979 7.652Q21.027 6.700 20.449 6.326Q19.871 5.952 19.021 5.782L19.021 5.782Q18.443 5.646 17.457 5.578L17.457 5.578Q17.355 5.748 17.525 5.952L17.525 5.952L18.069 6.496Q19.633 8.094 19.973 9.964L19.973 9.964L20.007 10.406Q20.381 13.092 20.449 13.160L20.449 13.160Q20.585 13.534 20.721 13.568Q20.857 13.602 21.129 13.296L21.129 13.296Q21.163 13.262 21.401 12.786L21.401 12.786Q21.945 11.596 22.183 11.290Q22.421 10.984 23.237 10.304L23.237 10.304Q23.781 9.896 23.815 9.794Q23.849 9.692 23.356 9.097Q22.863 8.502 22.455 8.094ZM5.897 6.496L6.407 5.986Q6.407 5.952 6.441 5.952L6.441 5.952Q6.611 5.748 6.509 5.578L6.509 5.578Q5.523 5.646 4.945 5.782L4.945 5.782Q4.095 5.952 3.517 6.326Q2.939 6.700 1.987 7.652L1.987 7.652L1.511 8.094Q1.103 8.502 0.661 9.080L0.661 9.080Q0.151 9.692 0.185 9.794Q0.219 9.896 0.729 10.304L0.729 10.304Q1.545 10.984 1.800 11.290Q2.055 11.596 2.599 12.786L2.599 12.786Q2.803 13.262 2.837 13.296L2.837 13.296Q3.109 13.602 3.245 13.568Q3.381 13.534 3.517 13.160L3.517 13.160Q3.585 13.092 3.959 10.406L3.959 10.406L4.027 9.930Q4.333 8.094 5.897 6.496L5.897 6.496ZM19.259 13.160L19.259 13.160L19.259 13.160ZM16.879 6.496L16.879 6.496Q16.811 6.428 16.709 6.326L16.709 6.326L16.335 5.918Q16.165 5.748 16.267 5.578L16.267 5.578L15.111 5.442Q13.989 5.306 13.411 5.238L13.411 5.238Q10.827 5.068 8.243 5.578L8.243 5.578L8.175 5.612Q7.903 5.646 7.767 5.578L7.767 5.578L7.733 5.646Q7.767 5.782 7.631 5.918L7.631 5.918L7.087 6.496Q5.523 8.094 5.217 9.930L5.217 9.930L5.047 10.984L5.047 11.120L5.047 11.086Q4.979 11.596 4.928 12.276Q4.877 12.956 4.911 13.160L4.911 13.160L4.945 13.228Q5.047 13.976 5.285 14.282L5.285 14.282Q5.387 14.452 5.625 14.758L5.625 14.758Q6.033 15.268 6.067 15.608L6.067 15.608Q6.339 17.036 7.767 17.546L7.767 17.546Q7.563 17.138 7.393 16.152L7.393 16.152Q7.257 15.234 7.325 15.200L7.325 15.200Q7.257 13.942 8.022 12.854Q8.787 11.766 10.147 11.256L10.147 11.256Q10.589 11.086 10.776 10.848Q10.963 10.610 11.320 10.508Q11.677 10.406 12.102 10.406Q12.527 10.406 12.884 10.508Q13.241 10.610 13.428 10.848Q13.615 11.086 14.057 11.256L14.057 11.256Q15.417 11.766 16.182 12.854Q16.947 13.942 16.879 15.200L16.879 15.200Q16.947 15.234 16.811 16.118L16.811 16.118Q16.641 17.070 16.437 17.512L16.437 17.512Q17.729 16.968 17.967 15.744L17.967 15.744Q18.069 15.234 18.375 14.860L18.375 14.860L18.409 14.792Q18.613 14.554 18.647 14.384L18.647 14.384Q18.783 14.282 18.919 13.976L18.919 13.976L18.987 13.738Q19.123 13.330 19.259 13.160L19.259 13.160Q19.191 13.024 18.851 10.440L18.851 10.440L18.783 9.930Q18.443 8.094 16.879 6.496ZM6.747 8.060L6.747 8.060Q6.713 8.026 6.730 8.026Q6.747 8.026 6.747 8.060ZM7.699 11.630L7.699 11.630Q7.087 11.630 6.662 11.205Q6.237 10.780 6.237 10.168Q6.237 9.556 6.662 9.114Q7.087 8.672 7.699 8.672Q8.311 8.672 8.753 9.114Q9.195 9.556 9.195 10.168Q9.195 10.780 8.753 11.205Q8.311 11.630 7.699 11.630ZM15.315 11.052L15.315 11.052Q15.315 11.052 15.315 11.052L15.315 11.052L15.315 11.052ZM16.607 11.630L16.607 11.630Q15.995 11.630 15.553 11.205Q15.111 10.780 15.111 10.168Q15.111 9.556 15.553 9.114Q15.995 8.672 16.607 8.672Q17.219 8.672 17.644 9.114Q18.069 9.556 18.069 10.168Q18.069 10.780 17.644 11.205Q17.219 11.630 16.607 11.630ZM18.171 10.746L18.171 10.746Q18.171 10.712 18.171 10.678L18.171 10.678L18.171 10.576L18.171 10.610Q18.171 10.678 18.171 10.746ZM18.171 10.406L18.171 10.406Q18.171 10.406 18.171 10.440L18.171 10.440L18.171 10.406Q18.205 10.372 18.171 10.406Z"/>', + 'seti:puppet': + '<path d="M4.426 7.310L4.426 0.338L11.398 0.338L11.426 5.658L14.254 8.486L14.282 8.486L19.574 8.486L19.574 15.486L14.310 15.486Q14.254 15.458 14.170 15.570L14.170 15.570L11.426 18.314L11.398 23.662L4.426 23.662L4.426 16.662L9.774 16.662L12.630 13.806L12.630 10.166L9.774 7.310L4.426 7.310ZM6.778 4.986L6.778 2.662L9.074 2.662L9.074 4.986L6.778 4.986ZM6.778 21.310L6.778 19.014L9.074 19.014L9.074 21.310L6.778 21.310Z"/>', + 'seti:purescript': + '<path d="M16.968 17.184L15.132 15.456L7.032 15.456L8.868 17.184L16.968 17.184ZM8.868 11.136L7.032 12.864L15.132 12.864L16.968 11.136L8.868 11.136ZM16.968 8.544L15.132 6.816L7.032 6.816L8.868 8.544L16.968 8.544ZM2.244 14.160L6.168 10.236L4.944 9.012L0.408 13.548Q0.156 13.800 0.156 14.160Q0.156 14.520 0.408 14.772L0.408 14.772L4.944 19.308L6.168 18.084L2.244 14.160ZM23.592 9.228L23.592 9.228L19.056 4.692L17.832 5.916L21.756 9.840L17.832 13.764L19.056 14.988L23.592 10.452Q23.844 10.200 23.844 9.840Q23.844 9.480 23.592 9.228Z"/>', + 'seti:python': + '<path d="M11.460 11.300L11.460 11.300L8.688 11.300Q7.236 11.300 6.378 12.158Q5.520 13.016 5.520 14.468L5.520 14.468L5.520 16.932Q5.520 17.372 5.124 17.372L5.124 17.372L3.892 17.372Q1.956 17.372 1.120 15.700L1.120 15.700Q0.460 14.336 0.460 13.236L0.460 13.236Q0.196 10.508 0.856 8.704L0.856 8.704Q1.560 6.592 3.452 6.240L3.452 6.240L11.416 6.240Q11.856 6.240 11.856 6.108L11.856 6.108L11.856 5.404L11.680 5.316Q11.504 5.272 11.460 5.272L11.460 5.272L6.752 5.272Q6.444 5.272 6.334 5.140Q6.224 5.008 6.224 4.700L6.224 4.700L6.224 2.940Q6.224 1.400 7.456 1.004L7.456 1.004Q8.820 0.432 9.524 0.300L9.524 0.300Q12.164-0.140 14.452 0.432L14.452 0.432Q15.596 0.696 16.388 1.268L16.388 1.268Q16.872 1.752 17.048 2.148L17.048 2.148Q17.312 2.632 17.224 3.204L17.224 3.204L17.224 8.132Q17.224 9.584 16.432 10.376Q15.640 11.168 14.188 11.168L14.188 11.168Q13.220 11.300 11.460 11.300ZM7.588 3.072L7.588 3.072Q7.588 3.512 7.896 3.842Q8.204 4.172 8.644 4.172Q9.084 4.172 9.436 3.820Q9.788 3.468 9.788 3.072Q9.788 2.676 9.458 2.368Q9.128 2.060 8.688 1.972L8.688 1.972Q8.204 1.972 7.896 2.302Q7.588 2.632 7.588 3.072ZM12.560 12.708L12.560 12.708L15.288 12.708Q16.740 12.708 17.598 11.850Q18.456 10.992 18.456 9.540L18.456 9.540L18.456 7.032Q18.456 6.636 18.852 6.636L18.852 6.636L20.084 6.636Q22.020 6.636 22.856 8.308L22.856 8.308Q23.560 9.672 23.560 10.772L23.560 10.772Q23.780 13.500 23.120 15.304L23.120 15.304Q22.416 17.416 20.524 17.768L20.524 17.768L12.560 17.768Q12.120 17.768 12.120 17.900L12.120 17.900L12.120 18.604L12.296 18.692Q12.472 18.736 12.560 18.736L12.560 18.736L17.224 18.736Q17.532 18.736 17.642 18.868Q17.752 19.000 17.752 19.308L17.752 19.308L17.752 21.068Q17.752 22.608 16.520 23.004L16.520 23.004Q15.156 23.532 14.452 23.708L14.452 23.708Q11.812 24.148 9.524 23.532L9.524 23.532Q8.380 23.312 7.588 22.740L7.588 22.740Q7.104 22.256 6.928 21.860L6.928 21.860Q6.664 21.376 6.752 20.804L6.752 20.804L6.752 15.832Q6.752 14.424 7.544 13.632Q8.336 12.840 9.788 12.840L9.788 12.840Q10.756 12.708 12.560 12.708ZM16.388 20.936L16.388 20.936Q16.388 20.496 16.080 20.166Q15.772 19.836 15.332 19.836Q14.892 19.836 14.540 20.188Q14.188 20.540 14.188 20.936Q14.188 21.332 14.518 21.640Q14.848 21.948 15.288 22.036L15.288 22.036Q15.772 22.036 16.080 21.706Q16.388 21.376 16.388 20.936Z"/>', + 'seti:react': + '<path d="M18.955 15.993L18.993 15.993Q18.993 16.107 18.993 16.297L18.993 16.297Q19.221 18.615 19.221 19.774Q19.221 20.933 18.651 21.693Q18.081 22.453 17.207 22.529L17.207 22.529Q16.333 22.719 15.307 22.301L15.307 22.301Q14.547 21.921 13.179 21.009L13.179 21.009Q12.305 20.439 11.849 20.173L11.849 20.173Q10.671 21.123 9.949 21.579L9.949 21.579Q9.341 21.997 8.771 22.187L8.771 22.187Q7.707 22.643 6.795 22.472Q5.883 22.301 5.332 21.579Q4.781 20.857 4.762 19.679Q4.743 18.501 4.971 15.879L4.971 15.879Q3.527 15.423 2.805 14.929L2.805 14.929Q1.855 14.473 0.905 13.523L0.905 13.523Q0.145 12.725 0.183 11.794Q0.221 10.863 1.057 10.065L1.057 10.065Q1.665 9.343 2.691 8.849L2.691 8.849Q3.299 8.507 4.591 8.051L4.591 8.051Q4.667 8.051 4.838 7.994Q5.009 7.937 5.085 7.937L5.085 7.937L4.743 5.315Q4.705 4.479 4.971 3.073L4.971 3.073Q5.237 2.085 6.054 1.667Q6.871 1.249 7.935 1.515L7.935 1.515Q8.885 1.743 9.835 2.351L9.835 2.351Q10.519 2.769 11.393 3.529L11.393 3.529Q11.545 3.605 11.735 3.871L11.735 3.871L11.849 4.023Q13.749 2.579 14.813 1.971L14.813 1.971Q16.029 1.173 17.207 1.515L17.207 1.515Q18.081 1.705 18.594 2.446Q19.107 3.187 19.221 4.365L19.221 4.365L19.221 6.265Q19.221 6.645 19.031 7.405L19.031 7.405Q18.917 7.899 18.841 8.165L18.841 8.165Q19.905 8.507 20.874 8.982Q21.843 9.457 22.261 9.761L22.261 9.761Q22.983 10.255 23.401 10.882Q23.819 11.509 23.819 12.193Q23.819 12.877 23.401 13.504Q22.983 14.131 22.261 14.625L22.261 14.625Q21.805 14.929 20.855 15.423L20.855 15.423Q20.171 15.537 18.955 15.993L18.955 15.993ZM10.861 15.841L12.077 15.879Q12.267 15.879 12.685 15.841L12.685 15.841Q13.255 15.765 13.521 15.765L13.521 15.765Q14.015 15.765 14.357 15.271L14.357 15.271Q15.535 13.371 15.991 12.307L15.991 12.307Q16.105 12.155 16.105 11.927Q16.105 11.699 15.991 11.623L15.991 11.623Q15.421 10.521 14.205 8.659L14.205 8.659Q14.053 8.279 13.635 8.279L13.635 8.279Q11.621 8.279 10.557 8.165L10.557 8.165Q9.607 8.165 9.113 9.001L9.113 9.001Q8.657 9.723 8.391 10.179L8.391 10.179L7.859 11.167Q7.517 11.661 7.460 11.870Q7.403 12.079 7.460 12.288Q7.517 12.497 7.859 13.029L7.859 13.029L8.391 13.979L8.847 14.739Q9.227 15.347 9.379 15.499L9.379 15.499Q9.607 15.765 9.911 15.803L9.911 15.803Q10.139 15.841 10.861 15.841L10.861 15.841ZM5.199 14.929L5.199 14.929Q5.921 13.029 6.263 12.193L6.263 12.193L6.263 11.737L5.199 9.001Q3.071 9.647 1.893 10.521L1.893 10.521Q1.057 11.167 1.057 11.908Q1.057 12.649 1.893 13.257L1.893 13.257Q2.501 13.903 3.451 14.321L3.451 14.321Q4.021 14.587 5.199 14.929ZM18.613 8.887L18.613 8.887Q18.157 9.951 17.435 11.851L17.435 11.851L17.397 11.965Q17.359 12.079 17.435 12.079L17.435 12.079Q18.157 13.979 18.613 15.157L18.613 15.157Q19.069 14.929 20.019 14.435L20.019 14.435Q21.273 13.865 21.805 13.523L21.805 13.523Q22.793 12.877 22.793 12.079Q22.793 11.281 21.843 10.673L21.843 10.673Q21.197 10.103 19.753 9.419L19.753 9.419Q18.955 9.077 18.613 8.887ZM5.883 7.481L5.921 7.671Q7.821 7.481 8.885 7.215L8.885 7.215Q8.961 7.215 9.037 7.139L9.037 7.139L9.113 7.101Q9.797 6.151 11.013 4.707L11.013 4.707Q10.063 3.909 9.569 3.529L9.569 3.529Q8.733 2.883 7.935 2.579L7.935 2.579Q6.947 2.237 6.339 2.598Q5.731 2.959 5.541 4.023L5.541 4.023Q5.465 4.745 5.579 5.695L5.579 5.695Q5.655 6.265 5.883 7.481L5.883 7.481ZM17.777 7.709L17.777 7.671Q17.777 7.633 17.834 7.462Q17.891 7.291 17.891 7.215L17.891 7.215Q18.157 6.037 18.157 5.391L18.157 5.391Q18.233 4.327 17.891 3.529L17.891 3.529Q17.739 2.921 17.321 2.655Q16.903 2.389 16.371 2.465L16.371 2.465Q15.421 2.617 14.509 3.225L14.509 3.225Q13.939 3.567 12.951 4.479L12.951 4.479L12.685 4.707Q13.293 5.543 14.471 6.987L14.471 6.987L14.813 7.329L17.777 7.709ZM5.921 16.221L5.921 16.221Q5.883 16.449 5.807 16.867L5.807 16.867Q5.579 17.931 5.541 18.425L5.541 18.425Q5.465 19.299 5.693 20.059L5.693 20.059Q5.845 20.933 6.434 21.275Q7.023 21.617 7.935 21.351L7.935 21.351Q8.695 21.123 9.493 20.591L9.493 20.591Q9.949 20.249 10.823 19.489L10.823 19.489L11.127 19.223Q10.443 18.273 9.227 16.829L9.227 16.829Q8.999 16.601 8.885 16.601L8.885 16.601Q7.517 16.601 5.921 16.221ZM12.571 19.223L12.571 19.223Q13.065 19.869 14.015 20.553L14.015 20.553Q14.889 21.199 15.649 21.465L15.649 21.465Q17.549 22.035 17.891 20.173L17.891 20.173Q18.043 19.337 17.967 18.349L17.967 18.349Q17.929 17.741 17.701 16.525L17.701 16.525L17.663 16.373L16.903 16.449Q15.307 16.563 14.585 16.829L14.585 16.829Q14.243 17.019 13.939 17.361L13.939 17.361Q13.749 17.589 13.445 18.045L13.445 18.045Q13.179 18.425 13.046 18.634Q12.913 18.843 12.571 19.223ZM10.443 7.101L13.293 7.101Q13.027 6.797 12.552 6.265Q12.077 5.733 11.849 5.429L11.849 5.429L11.659 5.695Q10.937 6.607 10.443 7.101L10.443 7.101ZM12.837 17.361L13.293 16.829L10.557 16.829Q10.785 17.133 11.260 17.665Q11.735 18.197 11.963 18.501L11.963 18.501Q12.229 18.083 12.837 17.361L12.837 17.361ZM8.391 15.651L8.391 15.651Q8.239 15.385 7.935 14.853L7.935 14.853Q7.289 13.789 6.985 13.143L6.985 13.143L6.263 15.157Q6.909 15.423 8.391 15.651ZM16.713 13.143L16.713 13.143L15.307 15.651L17.435 15.271Q17.283 14.511 16.713 13.143ZM6.985 10.787L6.985 10.787L8.391 8.279L6.263 8.621L6.415 9.115Q6.681 10.217 6.985 10.787ZM15.307 8.279L15.307 8.279Q15.535 8.773 16.010 9.476Q16.485 10.179 16.713 10.673L16.713 10.673Q17.207 9.229 17.435 8.659L17.435 8.659Q16.523 8.621 15.307 8.279Z"/>', + 'seti:rescript': + '<path d="M23.825 5.486L23.825 5.486Q23.825 6.861 23.115 8.066Q22.406 9.270 21.202 10.000Q19.998 10.732 18.557 10.732Q17.117 10.732 15.913 10.044Q14.709 9.355 14.021 8.151Q13.333 6.948 13.333 5.486Q13.333 4.023 14.021 2.820Q14.709 1.616 15.913 0.928Q17.117 0.239 18.536 0.239Q19.955 0.239 21.159 0.928Q22.363 1.616 23.094 2.820Q23.825 4.023 23.825 5.486ZM4.862 0.111L9.291 0.111L9.291 19.332Q9.291 20.492 9.248 20.922L9.248 20.922Q9.205 21.568 9.011 22.041Q8.818 22.514 8.366 22.965Q7.915 23.416 7.399 23.632L7.399 23.632Q7.055 23.803 6.410 23.847L6.410 23.847Q6.023 23.890 4.733 23.890L4.733 23.890Q3.572 23.890 3.142 23.847L3.142 23.847Q2.497 23.803 2.024 23.610Q1.551 23.416 1.099 22.965Q0.648 22.514 0.433 21.998L0.433 21.998Q0.261 21.654 0.175 21.009L0.175 21.009Q0.175 20.579 0.175 19.332L0.175 19.332L0.175 4.797Q0.175 3.378 0.175 2.863L0.175 2.863Q0.261 2.088 0.454 1.701Q0.648 1.315 1.013 0.949Q1.379 0.584 1.809 0.390Q2.239 0.197 2.970 0.154L2.970 0.154Q3.443 0.111 4.862 0.111L4.862 0.111Z"/>', + 'seti:R': + '<path d="M12.000 18.678L12.000 18.678Q8.808 18.678 6.120 17.628Q3.432 16.578 1.836 14.772Q0.240 12.966 0.240 10.824Q0.240 8.682 1.836 6.876Q3.432 5.070 6.120 3.999Q8.808 2.928 12.000 2.928Q15.192 2.928 17.880 3.999Q20.568 5.070 22.164 6.876Q23.760 8.682 23.760 10.824Q23.760 12.966 22.164 14.772Q20.568 16.578 17.880 17.628Q15.192 18.678 12.000 18.678ZM13.806 6.036L13.806 6.036Q11.370 6.036 9.312 6.750Q7.254 7.464 6.057 8.703Q4.860 9.942 4.860 11.391Q4.860 12.840 6.057 14.079Q7.254 15.318 9.312 16.053Q11.370 16.788 13.806 16.788L13.806 16.788Q17.712 16.788 19.938 15.486L19.938 15.486Q22.374 14.100 22.374 11.412Q22.374 8.724 19.938 7.296L19.938 7.296Q17.712 6.036 13.806 6.036ZM18.678 15.024L18.132 15.108Q18.342 15.192 18.552 15.276L18.552 15.276Q19.014 15.402 19.266 15.570L19.266 15.570Q19.602 15.738 19.854 15.948L19.854 15.948Q19.938 16.074 20.022 16.200L20.022 16.200L22.920 21.030L18.384 21.030L16.242 17.082L15.990 16.662Q15.738 16.242 15.570 16.116L15.570 16.116Q15.234 15.864 15.024 15.864L15.024 15.864L13.932 15.864L13.932 21.072L9.942 21.072L9.942 7.842L18.006 7.842L18.552 7.884Q19.266 8.010 19.812 8.304L19.812 8.304Q20.610 8.682 21.072 9.354L21.072 9.354Q21.660 10.194 21.660 11.391Q21.660 12.588 21.114 13.428L21.114 13.428Q20.652 14.142 19.896 14.562L19.896 14.562Q19.350 14.856 18.678 15.024L18.678 15.024ZM16.410 10.698L16.410 10.698L13.974 10.698L13.974 12.966L16.410 12.924L16.704 12.882Q17.040 12.798 17.250 12.588L17.250 12.588Q17.544 12.294 17.502 11.790L17.502 11.790Q17.544 11.076 16.956 10.824L16.956 10.824Q16.662 10.698 16.410 10.698L16.410 10.698Z"/>', + 'seti:ruby': + '<path d="M13.913 0.300L14.453 0.030L20.212 0.030Q20.302 0.030 20.438 0.098Q20.573 0.165 20.663 0.165L20.663 0.165Q23.363 0.840 23.768 3.270L23.768 3.270Q23.768 3.405 23.835 3.698Q23.902 3.990 23.902 4.125L23.902 4.125L23.902 5.250Q23.902 5.385 23.835 5.678Q23.768 5.970 23.768 6.105L23.768 6.105L23.272 12.855Q22.732 18.975 22.643 22.125L22.643 22.125Q22.598 22.530 22.463 22.688Q22.327 22.845 21.923 22.845L21.923 22.845Q21.157 22.890 19.672 22.957Q18.188 23.025 17.422 23.115L17.422 23.115Q15.892 23.160 12.788 23.385Q9.683 23.610 8.152 23.655L8.152 23.655Q7.297 23.655 5.588 23.970L5.588 23.970L4.193 23.970Q4.148 23.970 3.990 23.880Q3.832 23.790 3.787 23.790L3.787 23.790Q2.482 23.610 1.605 22.845Q0.728 22.080 0.413 20.865L0.413 20.865Q0.322 20.640 0.255 20.212Q0.188 19.785 0.098 19.605L0.098 19.605L0.098 18.885Q0.098 18.840 0.188 18.660Q0.277 18.480 0.277 18.345L0.277 18.345Q0.277 17.760 0.345 16.567Q0.413 15.375 0.413 14.835L0.413 14.835Q0.413 13.530 0.548 12.990L0.548 12.990Q1.402 10.785 2.213 9.345L2.213 9.345Q3.248 7.455 4.598 6.105L4.598 6.105Q6.532 4.035 8.468 2.775L8.468 2.775Q10.672 1.335 13.058 0.750L13.058 0.750Q13.328 0.570 13.913 0.300L13.913 0.300Z"/>', + 'seti:rust': + '<path d="M18.419 2.539L18.419 2.983L18.419 3.686L18.530 3.797L18.642 3.797Q18.826 3.760 19.178 3.704Q19.529 3.649 19.696 3.575Q19.863 3.501 19.992 3.630Q20.122 3.760 20.047 3.926Q19.973 4.093 19.918 4.444Q19.863 4.796 19.825 4.981L19.825 4.981L19.825 5.092L19.936 5.203Q19.936 5.314 20.159 5.314L20.159 5.314L21.194 5.314Q21.564 5.314 21.527 5.647L21.527 5.647L21.527 5.906Q21.453 6.128 21.232 6.572L21.232 6.572L21.084 6.831L21.084 6.942L21.157 7.016Q21.194 7.090 21.194 7.164L21.194 7.164L21.305 7.164Q21.491 7.238 21.842 7.293Q22.194 7.349 22.360 7.367Q22.526 7.386 22.601 7.589Q22.674 7.793 22.601 7.978L22.601 7.978L22.305 8.385Q22.082 8.644 22.008 8.792L22.008 8.792L22.008 9.014Q22.008 9.088 22.119 9.162L22.119 9.162L22.230 9.236L23.155 9.606Q23.340 9.680 23.396 9.846Q23.451 10.013 23.267 10.161L23.267 10.161Q22.822 10.642 22.489 10.864L22.489 10.864L22.489 11.197L22.526 11.271Q22.637 11.308 22.712 11.308L22.712 11.308L22.970 11.493Q23.303 11.715 23.488 11.789Q23.674 11.863 23.674 12.066Q23.674 12.270 23.526 12.381L23.526 12.381L22.601 12.936L22.601 13.047Q22.601 13.232 22.601 13.269Q22.601 13.306 22.712 13.417L22.712 13.417Q23.155 13.861 23.415 13.972L23.415 13.972Q23.563 14.157 23.507 14.305Q23.451 14.453 23.267 14.564L23.267 14.564Q22.601 14.786 22.341 14.897L22.341 14.897L22.305 14.934Q22.230 14.971 22.194 15.045Q22.156 15.119 22.230 15.267L22.230 15.267L22.230 15.378Q22.415 15.526 22.637 15.933L22.637 15.933L22.822 16.192Q22.896 16.266 22.878 16.414Q22.860 16.562 22.712 16.636L22.712 16.636L22.601 16.673L22.453 16.747Q22.305 16.747 22.008 16.821Q21.712 16.895 21.564 16.895L21.564 16.895L21.416 16.895Q21.416 16.932 21.361 16.987Q21.305 17.043 21.305 17.117L21.305 17.117L21.343 17.228L21.416 17.339L21.787 18.153Q21.860 18.227 21.805 18.375Q21.749 18.523 21.675 18.597L21.675 18.597L20.270 18.597Q20.159 18.745 20.159 18.967L20.159 18.967Q20.232 19.115 20.288 19.411Q20.343 19.707 20.418 19.873Q20.491 20.040 20.343 20.188Q20.195 20.336 19.936 20.336L19.936 20.336Q19.752 20.299 19.400 20.243Q19.049 20.188 18.901 20.114L18.901 20.114L18.790 20.114L18.604 20.299Q18.567 20.336 18.642 20.336L18.642 20.336L18.642 21.372Q18.642 21.742 18.308 21.742L18.308 21.742L18.087 21.742Q17.605 21.594 17.162 21.261L17.162 21.261L17.050 21.261Q16.939 21.261 16.866 21.335Q16.791 21.409 16.791 21.520L16.791 21.520Q16.791 21.668 16.736 21.964Q16.680 22.260 16.680 22.426Q16.680 22.593 16.477 22.667Q16.273 22.741 16.125 22.667L16.125 22.667Q15.756 22.297 15.311 22.075L15.311 22.075L15.200 22.075Q15.090 22.075 15.015 22.149Q14.942 22.223 14.942 22.297L14.942 22.297L14.608 23.222Q14.497 23.481 14.276 23.481L14.276 23.481Q14.201 23.481 14.165 23.407L14.165 23.407L14.128 23.370Q13.683 22.889 13.462 22.556L13.462 22.556L13.203 22.556Q13.128 22.556 13.055 22.630Q12.980 22.704 12.980 22.778L12.980 22.778L12.537 23.592Q12.425 23.740 12.222 23.740Q12.018 23.740 11.945 23.592L11.945 23.592L11.352 22.667L11.020 22.667L10.206 23.481Q10.095 23.592 9.762 23.592L9.762 23.592Q9.651 23.592 9.651 23.370L9.651 23.370L9.280 22.260Q9.243 22.186 9.169 22.186L9.169 22.186L8.837 22.186Q8.651 22.371 8.281 22.593L8.281 22.593L8.023 22.778L7.800 22.667Q7.467 22.519 7.338 22.426Q7.208 22.334 7.208 22.186L7.208 22.186Q7.097 21.853 7.097 21.150L7.097 21.150L7.060 21.113Q7.060 21.039 6.986 21.039Q6.912 21.039 6.857 20.983Q6.801 20.928 6.764 20.928L6.764 20.928L6.616 20.928L6.505 21.039L5.691 21.372Q5.543 21.483 5.395 21.409Q5.247 21.335 5.247 21.150L5.247 21.150L5.247 19.892L5.136 19.781L5.026 19.781Q4.840 19.818 4.489 19.873Q4.138 19.929 3.971 20.003Q3.804 20.077 3.675 19.947Q3.545 19.818 3.619 19.651Q3.693 19.485 3.749 19.133Q3.804 18.782 3.841 18.597L3.841 18.597L3.841 18.486L3.731 18.375L2.583 18.375Q2.250 18.375 2.250 18.042L2.250 18.042L2.250 17.783Q2.324 17.561 2.583 17.117L2.583 17.117L2.694 16.858L2.694 16.710Q2.657 16.636 2.583 16.636L2.583 16.636Q2.583 16.562 2.510 16.562L2.510 16.562L2.472 16.525Q2.287 16.525 1.936 16.469Q1.584 16.414 1.418 16.414Q1.251 16.414 1.177 16.210Q1.103 16.007 1.214 15.822L1.214 15.822Q1.548 15.489 1.769 15.008L1.769 15.008L1.769 14.786L1.584 14.638Q1.510 14.564 1.436 14.564L1.436 14.564L0.622 14.231Q0.437 14.120 0.382 13.953Q0.326 13.787 0.511 13.639L0.511 13.639Q0.696 13.565 1.066 13.269L1.066 13.269Q1.288 13.047 1.436 12.936L1.436 12.936L1.436 12.714Q1.436 12.492 1.325 12.492L1.325 12.492L0.511 12.011Q0.326 11.937 0.326 11.733Q0.326 11.530 0.511 11.456L0.511 11.456L1.436 10.864L1.436 10.642L0.622 9.828Q0.548 9.754 0.548 9.606Q0.548 9.458 0.622 9.347L0.622 9.347L0.659 9.347Q0.733 9.310 0.733 9.236L0.733 9.236L1.769 8.903L1.769 8.792Q1.843 8.718 1.806 8.533L1.806 8.533L1.769 8.422Q1.658 8.311 1.492 8.089Q1.325 7.867 1.214 7.719Q1.103 7.571 1.177 7.367Q1.251 7.164 1.418 7.127Q1.584 7.090 1.936 7.034Q2.287 6.979 2.472 6.942L2.472 6.942L2.583 6.942Q2.583 6.868 2.639 6.812Q2.694 6.757 2.694 6.683L2.694 6.683L2.694 6.572L2.583 6.461L2.250 5.647Q2.139 5.499 2.213 5.351Q2.287 5.203 2.472 5.203L2.472 5.203L3.731 5.203L3.767 5.129Q3.767 5.092 3.841 5.092L3.841 5.092L3.841 4.981Q3.619 4.278 3.619 3.945L3.619 3.945Q3.545 3.760 3.675 3.630Q3.804 3.501 3.989 3.575L3.989 3.575Q4.322 3.575 5.026 3.797L5.026 3.797L5.136 3.797L5.284 3.649Q5.321 3.575 5.247 3.575L5.247 3.575L5.247 2.539Q5.247 2.206 5.580 2.206L5.580 2.206L5.840 2.206Q6.061 2.280 6.505 2.539L6.505 2.539L6.764 2.650L6.912 2.650Q6.986 2.613 6.986 2.539L6.986 2.539Q7.060 2.539 7.060 2.465L7.060 2.465L7.097 2.428Q7.097 2.243 7.153 1.891Q7.208 1.540 7.208 1.373Q7.208 1.207 7.412 1.133Q7.615 1.059 7.800 1.133L7.800 1.133Q8.133 1.503 8.614 1.725L8.614 1.725L8.837 1.725L8.947 1.614L8.947 1.540Q8.985 1.466 9.058 1.392L9.058 1.392L9.392 0.578Q9.503 0.430 9.576 0.393Q9.651 0.356 9.872 0.356L9.872 0.356L9.983 0.467Q10.058 0.652 10.354 1.022L10.354 1.022Q10.576 1.244 10.686 1.392L10.686 1.392L10.797 1.392Q10.872 1.392 10.945 1.318L10.945 1.318L11.020 1.281L11.500 0.467Q11.648 0.282 11.815 0.263Q11.982 0.245 12.055 0.356L12.055 0.356L12.166 0.467L12.759 1.392L13.091 1.392Q13.166 1.392 13.203 1.318L13.203 1.318L13.239 1.281Q13.683 0.800 13.794 0.578L13.794 0.578Q13.869 0.504 14.017 0.504Q14.165 0.504 14.276 0.578L14.276 0.578L14.276 0.689Q14.497 1.392 14.608 1.614L14.608 1.614L14.720 1.725L14.942 1.725Q15.459 1.540 15.866 1.133L15.866 1.133Q16.052 1.059 16.255 1.133Q16.459 1.207 16.459 1.373Q16.459 1.540 16.514 1.891Q16.569 2.243 16.569 2.428L16.569 2.428L16.607 2.465Q16.607 2.539 16.680 2.539L16.680 2.539L16.791 2.539Q16.902 2.613 16.976 2.613Q17.050 2.613 17.050 2.539L17.050 2.539Q17.273 2.428 17.976 2.206L17.976 2.206Q18.160 2.095 18.290 2.187Q18.419 2.280 18.419 2.539L18.419 2.539ZM5.580 6.128L5.580 6.128L14.386 6.128Q15.090 6.128 15.422 6.239L15.422 6.239Q16.532 6.609 17.050 7.275L17.050 7.275Q17.605 7.867 17.605 8.681L17.605 8.681Q17.605 9.347 17.273 10.050L17.273 10.050Q16.902 10.605 16.348 10.975L16.348 10.975Q16.125 11.197 15.977 11.197L15.977 11.197Q16.052 11.271 16.163 11.326Q16.273 11.382 16.348 11.456L16.348 11.456L16.532 11.604Q16.939 11.974 17.050 12.233L17.050 12.233Q17.383 12.788 17.383 13.417L17.383 13.417Q17.383 13.528 17.605 13.750L17.605 13.750Q17.753 13.898 18.049 13.972L18.049 13.972Q18.197 13.972 18.549 13.972Q18.901 13.972 19.122 13.750L19.122 13.750Q19.270 13.602 19.381 13.306L19.381 13.306L19.456 13.047L19.456 12.492Q19.456 12.381 19.474 12.381Q19.492 12.381 19.566 12.381L19.566 12.381L20.380 12.381L20.380 10.864Q20.232 10.790 19.881 10.623Q19.529 10.457 19.345 10.383L19.345 10.383Q19.308 10.346 19.122 10.290Q18.938 10.235 18.901 10.161L18.901 10.161Q18.346 9.976 18.530 9.236L18.530 9.236Q19.011 8.089 19.345 7.497L19.345 7.497L19.345 7.386Q18.901 6.683 18.642 6.387L18.642 6.387Q18.197 5.832 17.716 5.425L17.716 5.425Q16.014 3.871 13.573 3.353L13.573 3.353L13.462 3.353Q12.759 4.056 12.314 4.389L12.314 4.389Q12.130 4.574 11.834 4.574Q11.538 4.574 11.352 4.389L11.352 4.389L10.317 3.353L10.206 3.353Q9.762 3.464 9.058 3.686L9.058 3.686Q7.245 4.352 5.802 5.758L5.802 5.758Q5.580 6.017 5.580 6.128ZM18.642 16.747L18.642 16.747L15.200 16.747Q14.831 16.747 14.720 16.636L14.720 16.636Q14.128 16.340 13.905 15.489L13.905 15.489L13.869 15.267Q13.683 14.601 13.683 14.231L13.683 14.231Q13.683 13.972 13.480 13.528Q13.276 13.084 12.944 12.843Q12.610 12.603 12.166 12.603L12.166 12.603L10.095 12.603L10.095 14.083L12.166 14.083Q12.277 14.083 12.296 14.101Q12.314 14.120 12.314 14.231L12.314 14.231L12.314 16.525Q12.314 16.599 12.296 16.617Q12.277 16.636 12.166 16.636L12.166 16.636L5.247 16.636Q5.469 17.006 5.950 17.450L5.950 17.450L6.061 17.450Q6.986 17.228 7.430 17.228L7.430 17.228Q7.689 17.154 7.930 17.283Q8.171 17.413 8.244 17.672L8.244 17.672L8.614 19.189L8.614 19.300Q9.540 19.670 9.983 19.781L9.983 19.781Q10.761 20.003 11.352 20.003L11.352 20.003Q11.907 20.077 12.573 20.040L12.573 20.040Q12.980 20.003 13.794 19.892L13.794 19.892Q14.386 19.781 15.534 19.300L15.534 19.300L15.534 19.189L15.866 17.672Q16.088 17.080 16.680 17.228L16.680 17.228L18.087 17.561L18.197 17.561Q18.197 17.228 18.642 16.747ZM6.283 8.681L4.914 8.681L5.247 9.347L5.284 9.458Q5.321 9.643 5.247 9.717L5.247 9.717Q5.247 9.902 4.988 10.087L4.988 10.087L4.914 10.161Q3.989 10.642 3.508 10.753L3.508 10.753L3.434 10.753Q3.397 10.790 3.397 10.864L3.397 10.864L3.397 11.456Q3.397 12.603 3.731 13.972L3.731 13.972L3.767 14.046Q3.767 14.120 3.841 14.120L3.841 14.120L6.283 14.120L6.283 8.681ZM9.872 10.272L9.872 10.272Q9.910 10.272 9.947 10.272L9.947 10.272L9.872 10.272L12.537 10.272Q12.980 10.272 13.239 10.161L13.239 10.161L13.351 10.087Q13.498 9.976 13.573 9.809Q13.646 9.643 13.628 9.402Q13.610 9.162 13.462 9.014L13.462 9.014Q13.091 8.681 12.648 8.681L12.648 8.681L9.762 8.681Q9.872 9.236 9.872 10.272ZM2.917 9.125L2.917 9.125Q2.917 9.384 3.138 9.606Q3.360 9.828 3.619 9.828Q3.878 9.828 4.100 9.606Q4.322 9.384 4.322 9.125Q4.322 8.866 4.100 8.644Q3.878 8.422 3.619 8.422Q3.360 8.422 3.138 8.644Q2.917 8.866 2.917 9.125ZM17.605 18.856L17.605 18.856Q17.605 18.597 17.402 18.375Q17.198 18.153 16.921 18.153Q16.643 18.153 16.440 18.375Q16.236 18.597 16.236 18.856Q16.236 19.115 16.440 19.318Q16.643 19.522 16.921 19.522Q17.198 19.522 17.402 19.337Q17.605 19.152 17.605 18.856ZM6.764 18.153L6.764 18.153Q6.468 18.153 6.265 18.375Q6.061 18.597 6.061 18.856Q6.061 19.115 6.265 19.318Q6.468 19.522 6.746 19.522Q7.023 19.522 7.227 19.318Q7.430 19.115 7.430 18.856Q7.430 18.597 7.227 18.375Q7.023 18.153 6.764 18.153ZM12.537 2.983L12.537 2.983Q12.537 2.724 12.352 2.520Q12.166 2.317 11.852 2.317Q11.538 2.317 11.334 2.502Q11.131 2.687 11.131 2.983Q11.131 3.279 11.316 3.482Q11.500 3.686 11.834 3.686L11.834 3.686Q12.314 3.686 12.537 2.983ZM20.047 9.939L20.047 9.939Q20.306 9.939 20.529 9.717Q20.750 9.495 20.750 9.236Q20.750 8.977 20.529 8.755Q20.306 8.533 20.047 8.533Q19.788 8.533 19.566 8.755Q19.345 8.977 19.345 9.254Q19.345 9.532 19.529 9.735Q19.715 9.939 20.047 9.939Z"/>', + 'seti:sass': + '<path d="M14.594 13.680L14.594 13.806Q13.838 14.268 12.284 15.234L12.284 15.234L9.974 16.662Q10.730 18.384 10.100 20.232L10.100 20.232Q9.638 21.744 8.525 22.647Q7.412 23.550 5.900 23.760L5.900 23.760Q5.312 23.928 4.472 23.634L4.472 23.634Q3.800 23.466 3.548 22.710L3.548 22.710Q2.750 20.946 3.926 19.560L3.926 19.560L4.346 19.140Q5.144 18.300 5.648 18.006L5.648 18.006Q6.026 17.670 6.950 17.166L6.950 17.166Q7.664 16.788 8.000 16.536L8.000 16.536Q8.084 16.452 8.294 16.410L8.294 16.410L8.546 16.284Q8.378 16.200 8.147 15.990Q7.916 15.780 7.748 15.780L7.748 15.780Q5.984 14.646 4.724 13.386L4.724 13.386Q3.674 12.336 3.296 11.706L3.296 11.706Q2.414 11.034 2.267 10.110Q2.120 9.186 2.624 8.262L2.624 8.262Q3.254 6.750 4.976 4.986L4.976 4.986Q8.000 2.340 12.074 0.912L12.074 0.912Q14.972-0.096 17.576 0.282L17.576 0.282Q17.870 0.408 18.521 0.597Q19.172 0.786 19.424 0.912L19.424 0.912Q20.936 1.542 21.482 2.676Q22.028 3.810 21.524 5.406L21.524 5.406Q20.684 8.094 18.374 9.438L18.374 9.438Q16.778 10.446 15.140 10.824Q13.502 11.202 11.696 10.908L11.696 10.908Q10.604 10.740 9.596 9.732L9.596 9.732Q9.344 9.186 9.176 9.060L9.176 9.060L9.218 8.976Q9.260 8.892 9.344 8.808L9.344 8.808L9.386 8.808Q9.512 8.850 9.596 8.934L9.596 8.934Q10.940 10.320 12.998 9.858L12.998 9.858Q14.804 9.522 16.106 8.892L16.106 8.892Q17.618 8.178 18.626 6.960Q19.634 5.742 19.970 4.608L19.970 4.608Q20.306 3.138 18.794 2.256L18.794 2.256Q17.534 1.626 15.644 1.836L15.644 1.836Q12.116 2.382 8.546 4.608L8.546 4.608Q6.572 5.700 5.522 7.086L5.522 7.086Q5.144 7.632 4.598 8.682L4.598 8.682Q4.304 9.480 4.430 10.236Q4.556 10.992 5.144 11.538L5.144 11.538Q6.194 12.588 6.698 13.008L6.698 13.008L9.176 15.108L9.344 15.150Q9.512 15.192 9.596 15.108L9.596 15.108Q10.100 14.772 10.646 14.562L10.646 14.562Q12.620 13.470 14.300 13.134L14.300 13.134Q14.300 13.428 14.342 13.533Q14.384 13.638 14.510 13.722L14.510 13.722L14.594 13.806L14.594 13.680ZM8.924 17.082L8.924 17.082Q7.160 18.048 5.900 19.308L5.900 19.308Q5.186 20.022 4.976 20.988L4.976 20.988Q4.892 21.576 5.228 21.870Q5.564 22.164 6.194 22.038L6.194 22.038Q7.664 21.702 8.546 20.358L8.546 20.358Q9.008 19.602 9.092 18.804L9.092 18.804Q9.134 18.132 8.924 17.082Z"/>', + 'seti:spring': + '<path d="M21.571 1.813L21.655 1.603Q22.915 5.005 23.377 7.483L23.377 7.483Q24.007 10.675 23.629 13.531L23.629 13.531Q23.041 18.067 19.555 21.175L19.555 21.175Q17.749 22.561 15.775 23.275L15.775 23.275Q13.675 24.031 11.575 23.905L11.575 23.905Q6.451 23.737 3.154 19.873Q-0.143 16.009 0.277 11.053L0.277 11.053Q0.487 7.231 3.049 4.501L3.049 4.501Q5.569 1.057 10.651 0.175L10.651 0.175Q15.187-0.413 19.177 2.527L19.177 2.527Q19.975 3.199 20.227 3.283L20.227 3.283Q20.563 3.451 20.815 3.157L20.815 3.157Q20.983 2.947 21.403 1.981L21.403 1.981Q21.487 1.981 21.571 1.813L21.571 1.813ZM20.605 9.205L20.605 9.205Q19.723 13.153 15.775 16.429L15.775 16.429Q14.767 17.269 13.339 17.941L13.339 17.941Q12.457 18.361 10.609 19.033L10.609 19.033L9.853 19.327Q9.601 19.411 9.076 19.600Q8.551 19.789 8.299 19.873L8.299 19.873Q8.299 20.125 8.425 20.251L8.425 20.251Q9.223 20.209 10.903 20.167L10.903 20.167Q13.045 20.125 14.095 20.083L14.095 20.083Q15.817 19.957 17.203 19.705L17.203 19.705Q19.807 19.327 21.214 17.857Q22.621 16.387 23.125 13.699L23.125 13.699Q23.629 10.507 22.579 6.727L22.579 6.727Q22.369 6.055 21.991 4.669L21.991 4.669L21.529 3.031Q21.193 3.577 21.025 3.577L21.025 3.577Q19.471 5.971 16.153 7.525L16.153 7.525Q15.187 7.945 13.843 8.155L13.843 8.155Q13.003 8.281 11.365 8.365L11.365 8.365L10.525 8.449Q7.585 8.659 5.905 10.003L5.905 10.003Q4.897 10.759 4.288 12.019Q3.679 13.279 3.658 14.602Q3.637 15.925 4.225 16.975L4.225 16.975Q4.687 17.941 5.317 18.214Q5.947 18.487 6.955 18.277L6.955 18.277Q7.291 18.193 7.942 18.004Q8.593 17.815 8.929 17.731L8.929 17.731Q13.045 16.681 15.775 14.833L15.775 14.833Q18.841 12.691 20.605 9.205ZM4.729 18.781L4.729 18.781Q4.351 18.781 4.078 19.117Q3.805 19.453 3.805 19.852Q3.805 20.251 4.141 20.503Q4.477 20.755 4.855 20.755Q5.233 20.755 5.506 20.440Q5.779 20.125 5.779 19.663Q5.779 19.201 5.548 18.991Q5.317 18.781 4.729 18.781Z"/>', + 'seti:slim': + '<path d="M0.135 20.463L0.135 20.463L0.135 3.663Q0.135 3.579 0.198 3.516Q0.261 3.453 0.261 3.411L0.261 3.411Q0.723 1.731 1.983 1.017L1.983 1.017L3.537 0.261L20.337 0.261Q20.421 0.261 20.484 0.324Q20.547 0.387 20.589 0.387L20.589 0.387Q22.311 0.975 23.361 2.613L23.361 2.613Q23.571 3.201 23.865 3.537L23.865 3.537L23.865 20.337Q23.865 20.379 23.802 20.463Q23.739 20.547 23.739 20.589L23.739 20.589Q23.319 22.017 22.059 22.941L22.059 22.941Q21.219 23.571 20.337 23.739L20.337 23.739L3.537 23.739Q3.453 23.739 3.390 23.676Q3.327 23.613 3.285 23.613L3.285 23.613Q1.563 23.025 0.513 21.387L0.513 21.387Q0.387 21.261 0.135 20.463ZM3.789 6.687L3.789 6.687Q4.209 7.191 5.049 8.241L5.049 8.241Q6.435 10.047 7.233 10.887L7.233 10.887Q7.317 10.971 7.485 11.055Q7.653 11.139 7.737 11.139L7.737 11.139L16.137 11.139Q16.221 11.139 16.410 11.076Q16.599 11.013 16.683 11.013L16.683 11.013L17.901 9.459Q19.329 7.653 20.085 6.813L20.085 6.813Q18.111 4.461 15.087 3.579Q12.063 2.697 9.081 3.453L9.081 3.453Q5.889 4.251 3.789 6.687ZM14.037 6.015L14.961 4.713Q14.709 5.553 14.310 7.401Q13.911 9.249 13.659 10.089L13.659 10.089L11.139 10.089Q12.231 8.703 14.037 6.015L14.037 6.015Z"/>', + 'seti:smarty': + '<path d="M11.882 16.016L11.882 16.016L9.572 16.016Q8.977 16.016 8.837 15.911Q8.697 15.806 8.592 15.246L8.592 15.246Q8.102 12.761 6.947 10.661L6.947 10.661Q6.387 9.681 5.862 8.246L5.862 8.246Q5.232 6.461 5.547 4.501L5.547 4.501Q5.687 3.241 6.439 2.279Q7.192 1.316 8.382 0.791L8.382 0.791Q10.202-0.014 12.057 0.004Q13.912 0.021 15.697 0.896L15.697 0.896Q17.342 1.631 18.059 3.206Q18.777 4.781 18.462 6.706L18.462 6.706Q18.287 7.826 17.832 8.981L17.832 8.981Q17.517 9.786 16.817 11.081L16.817 11.081Q15.662 13.391 15.382 15.141L15.382 15.141Q15.277 15.666 15.189 15.841Q15.102 16.016 14.909 16.069Q14.717 16.121 14.192 16.121L14.192 16.121Q13.317 16.016 11.882 16.016ZM11.777 23.996L11.777 23.996L9.152 23.996Q8.802 23.996 8.644 23.856Q8.487 23.716 8.487 23.331L8.487 23.331L8.487 22.876Q8.487 22.386 8.522 22.229Q8.557 22.071 8.749 22.036Q8.942 22.001 9.502 22.001L9.502 22.001L14.507 22.036Q14.892 22.001 15.032 22.159Q15.172 22.316 15.172 22.666L15.172 22.666Q15.172 23.331 15.119 23.559Q15.067 23.786 14.839 23.839Q14.612 23.891 13.947 23.891L13.947 23.891Q13.317 23.996 11.777 23.996ZM14.227 20.041L11.882 20.041L9.152 20.041Q8.837 20.041 8.714 19.936Q8.592 19.831 8.592 19.516L8.592 19.516L8.592 19.201Q8.592 18.641 8.627 18.466Q8.662 18.291 8.837 18.239Q9.012 18.186 9.537 18.186L9.537 18.186L14.507 18.186Q15.172 18.186 15.172 18.851L15.172 18.851L15.172 19.131Q15.172 19.656 15.137 19.814Q15.102 19.971 14.927 20.006Q14.752 20.041 14.227 20.041L14.227 20.041Z"/>', + 'seti:sbt': + '<path d="M23.839 13.145L23.877 13.145Q23.877 13.677 23.687 14.551L23.687 14.551L23.611 14.817L7.955 14.817Q6.397 14.817 6.397 16.375L6.397 16.375Q6.397 16.983 6.834 17.325Q7.271 17.667 8.069 17.667L8.069 17.667L22.547 17.667Q21.141 20.365 18.842 21.923Q16.543 23.481 13.484 23.842Q10.425 24.203 7.537 23.025L7.537 23.025Q4.763 21.847 2.825 19.529Q0.887 17.211 0.355 14.209L0.355 14.209Q-0.253 11.131 0.735 8.205L0.735 8.205Q1.723 5.355 3.927 3.284Q6.131 1.213 9.133 0.453L9.133 0.453Q11.603-0.193 14.130 0.263Q16.657 0.719 18.785 2.163Q20.913 3.607 22.205 5.773L22.205 5.773Q21.939 5.925 21.255 5.925L21.255 5.925L13.541 5.925Q12.895 5.925 12.496 6.324Q12.097 6.723 12.097 7.350Q12.097 7.977 12.439 8.300Q12.781 8.623 13.427 8.623L13.427 8.623L23.383 8.623Q23.725 9.535 23.725 10.409L23.725 10.409L10.805 10.409Q9.133 10.409 9.133 11.853L9.133 11.853Q9.133 12.461 9.570 12.803Q10.007 13.145 10.805 13.145L10.805 13.145L22.775 13.145Q23.307 12.993 23.839 13.145L23.839 13.145Z"/>', + 'seti:scala': + '<path d="M19.350 0.198L19.350 0.198L19.350 5.700L19.224 5.826Q19.182 5.952 19.098 5.952L19.098 5.952Q18.510 6.540 17.628 6.750L17.628 6.750Q16.662 7.086 14.520 7.548L14.520 7.548L13.974 7.674Q11.622 8.094 7.800 8.598L7.800 8.598Q5.700 8.850 4.650 9.102L4.650 9.102L4.650 3.600Q4.776 3.474 5.196 3.474L5.196 3.474Q8.220 2.970 10.152 2.802L10.152 2.802L11.622 2.592Q13.596 2.298 14.604 2.088L14.604 2.088Q16.242 1.794 17.502 1.374L17.502 1.374L17.670 1.290Q18.300 1.038 18.594 0.870L18.594 0.870Q19.098 0.576 19.350 0.198ZM19.350 7.548L19.350 7.548L19.350 13.050L19.098 13.302Q18.510 13.764 17.250 14.268L17.250 14.268L16.998 14.352Q14.898 14.898 13.848 15.024L13.848 15.024Q13.176 15.150 11.937 15.339Q10.698 15.528 10.026 15.654L10.026 15.654L8.304 15.906Q5.910 16.200 4.650 16.452L4.650 16.452L4.650 10.950Q4.776 10.824 5.028 10.824L5.028 10.824Q6.162 10.698 8.388 10.362Q10.614 10.026 11.748 9.900L11.748 9.900Q14.772 9.480 17.376 8.724L17.376 8.724Q18.090 8.472 18.468 8.262L18.468 8.262Q18.972 7.968 19.350 7.548ZM5.028 23.760L4.776 23.802L4.650 23.802L4.650 18.300Q4.776 18.174 5.028 18.174L5.028 18.174Q5.826 18.048 7.338 17.838Q8.850 17.628 9.648 17.502L9.648 17.502L11.034 17.292Q13.134 16.998 14.142 16.830L14.142 16.830Q15.864 16.494 17.250 16.074L17.250 16.074Q18.048 15.822 18.384 15.612L18.384 15.612Q19.014 15.318 19.350 14.898L19.350 14.898L19.350 20.400Q19.266 20.568 18.972 20.820L18.972 20.820L18.678 21.072Q17.712 21.534 16.200 21.954L16.200 21.954Q14.814 22.332 11.916 22.794L11.916 22.794L11.328 22.878Q7.926 23.424 6.246 23.550L6.246 23.550Q5.784 23.550 5.028 23.760L5.028 23.760Z"/>', + 'seti:ethereum': + '<path d="M6.740 12.560L7.460 13L11.940 15.640L12.060 15.640Q16.580 12.880 18.940 11.640L18.940 11.640L18.940 11.520Q18.100 10 16.940 8.240L16.940 8.240L12.060 0.120L11.060 1.760Q10.020 3.480 9.580 4.360L9.580 4.360Q9.260 4.920 8.560 6.060Q7.860 7.200 7.580 7.760L7.580 7.760Q6.060 10.240 5.300 11.360L5.300 11.360L5.300 11.520Q5.660 11.920 6.740 12.560L6.740 12.560ZM12.820 17.760L12.820 17.760Q12.700 17.800 12.380 18L12.380 18L11.940 18.240Q11.460 17.920 10.460 17.360Q9.460 16.800 8.920 16.500Q8.380 16.200 7.260 15.500Q6.140 14.800 5.580 14.480L5.580 14.480Q5.500 14.440 5.300 14.360L5.300 14.360L5.060 14.240L6.060 15.640Q7.820 18.120 8.820 19.360L8.820 19.360Q9.300 20.120 10.360 21.560Q11.420 23 11.940 23.760L11.940 23.760L11.940 23.800Q11.980 23.880 12.060 23.880L12.060 23.880L16.700 17.360Q17.060 16.880 17.820 15.820Q18.580 14.760 18.940 14.240L18.940 14.240Q15.500 16.080 12.820 17.760Z"/>', + 'seti:stylus': + '<path d="M20.197 0.406L20.197 0.406Q19.936 0.406 19.559 0.580L19.559 0.580Q19.037 0.754 18.515 1.218L18.515 1.218Q18.225 1.479 17.674 2.117L17.674 2.117Q16.079 3.828 14.948 6.119L14.948 6.119Q13.556 8.555 12.686 11.542L12.686 11.542Q12.309 12.992 12.309 13.920L12.309 13.920Q12.338 14.239 12.556 14.427Q12.773 14.616 13.034 14.558L13.034 14.558Q13.556 14.500 13.962 14.152L13.962 14.152Q14.223 13.920 14.658 13.427L14.658 13.427L14.774 13.282L14.774 12.992Q14.223 13.543 13.962 13.717L13.962 13.717Q13.759 13.862 13.629 13.804Q13.498 13.746 13.498 13.543L13.498 13.543L13.498 12.644Q13.498 11.223 14.136 9.454L14.136 9.454Q14.861 7.482 15.325 6.583L15.325 6.583Q16.427 4.176 17.848 2.755L17.848 2.755Q18.573 1.624 19.849 1.508L19.849 1.508Q20.197 1.508 20.400 1.595Q20.603 1.682 20.661 1.943L20.661 1.943Q20.661 2.030 20.748 2.030L20.748 2.030L20.806 2.001Q20.864 1.943 20.922 1.943L20.922 1.943Q21.125 1.392 21.125 1.116Q21.125 0.841 20.835 0.594Q20.545 0.348 20.197 0.406ZM11.149 9.570L11.149 9.570Q10.685 9.570 10.076 9.990Q9.467 10.411 9.235 10.817L9.235 10.817L9.235 11.020L9.322 10.991L9.438 10.904L9.496 10.817Q9.670 10.614 9.786 10.556L9.786 10.556Q9.960 10.382 10.076 10.324L10.076 10.324Q10.250 10.237 10.424 10.295Q10.598 10.353 10.642 10.556Q10.685 10.759 10.598 10.904L10.598 10.904Q10.511 11.890 10.221 13.572L10.221 13.572L10.134 13.920Q9.525 16.298 8.713 17.806L8.713 17.806Q7.495 20.213 5.987 21.605L5.987 21.605Q5.465 22.040 5.088 22.243L5.088 22.243Q4.566 22.504 4.073 22.504L4.073 22.504Q3.725 22.504 3.566 22.402Q3.406 22.301 3.348 21.982L3.348 21.982Q3.348 21.924 3.261 21.866L3.261 21.866L3.174 21.779Q2.768 22.330 2.913 22.968Q3.058 23.606 3.435 23.606L3.435 23.606Q3.899 23.606 4.450 23.432L4.450 23.432Q4.798 23.316 5.175 23.026L5.175 23.026Q5.378 22.852 5.784 22.446L5.784 22.446L5.987 22.243Q7.553 20.677 8.713 18.531L8.713 18.531Q10.482 15.486 11.410 12.180L11.410 12.180L11.468 12.035Q11.613 11.397 11.671 11.078L11.671 11.078Q11.758 10.556 11.700 10.092L11.700 10.092Q11.700 9.889 11.526 9.729Q11.352 9.570 11.149 9.570Z"/>', + 'seti:svelte': + '<path d="M10.924 1.248L5.422 4.734L10.924 1.248Q12.436 0.240 14.284 0.177Q16.132 0.114 17.812 0.933Q19.492 1.752 20.584 3.306L20.584 3.306Q21.382 4.398 21.676 5.721Q21.970 7.044 21.739 8.367Q21.508 9.690 20.794 10.740L20.794 10.740Q21.844 12.798 21.424 15.024L21.424 15.024Q21.214 16.242 20.542 17.292Q19.870 18.342 18.862 19.056L18.862 19.056L13.066 22.752Q11.554 23.760 9.706 23.823Q7.858 23.886 6.178 23.067Q4.498 22.248 3.406 20.694L3.406 20.694Q2.650 19.602 2.335 18.258Q2.020 16.914 2.272 15.612Q2.524 14.310 3.238 13.218L3.238 13.218Q2.146 11.202 2.566 8.976L2.566 8.976Q2.776 7.758 3.448 6.708Q4.120 5.658 5.128 4.944L5.128 4.944L10.924 1.248ZM18.316 4.776L18.316 4.776Q17.518 3.642 16.237 3.159Q14.956 2.676 13.612 3.012L13.612 3.012Q13.192 3.138 12.772 3.348L12.772 3.348L7.018 7.002Q6.304 7.422 5.863 8.094Q5.422 8.766 5.275 9.564Q5.128 10.362 5.317 11.160Q5.506 11.958 5.968 12.630L5.968 12.630Q6.766 13.764 8.047 14.226Q9.328 14.688 10.672 14.352L10.672 14.352Q11.092 14.226 11.512 14.016L11.512 14.016L13.864 12.546Q14.032 12.420 14.200 12.378L14.200 12.378Q14.620 12.294 15.019 12.420Q15.418 12.546 15.628 12.924L15.628 12.924Q15.922 13.302 15.838 13.806L15.838 13.806Q15.754 14.226 15.460 14.478L15.460 14.478L9.832 18.090Q9.664 18.216 9.496 18.258L9.496 18.258Q9.076 18.342 8.698 18.195Q8.320 18.048 8.089 17.733Q7.858 17.418 7.858 17.082L7.858 17.082L7.858 16.704L7.648 16.620Q6.682 16.326 5.842 15.780L5.842 15.780L5.212 15.360L5.128 15.654Q5.044 15.906 5.002 16.200L5.002 16.200Q4.834 16.998 5.023 17.796Q5.212 18.594 5.674 19.224L5.674 19.224Q6.430 20.316 7.627 20.799Q8.824 21.282 10.126 21.030L10.126 21.030L10.378 20.988Q10.840 20.862 11.218 20.652L11.218 20.652L17.014 16.998Q17.686 16.578 18.127 15.906Q18.568 15.234 18.715 14.436Q18.862 13.638 18.673 12.840Q18.484 12.042 18.022 11.370L18.022 11.370Q17.224 10.236 15.943 9.774Q14.662 9.312 13.318 9.648L13.318 9.648Q12.898 9.774 12.478 9.984L12.478 9.984L10.126 11.454Q9.958 11.580 9.790 11.622L9.790 11.622Q9.370 11.706 8.992 11.580Q8.614 11.454 8.362 11.076L8.362 11.076Q8.068 10.698 8.152 10.194L8.152 10.194Q8.236 9.774 8.530 9.522L8.530 9.522L14.158 5.910Q14.326 5.784 14.494 5.742L14.494 5.742Q14.914 5.658 15.292 5.805Q15.670 5.952 15.901 6.267Q16.132 6.582 16.132 6.918L16.132 6.918L16.132 7.296L16.342 7.380Q17.308 7.674 18.148 8.220L18.148 8.220L18.778 8.640L18.862 8.346Q18.946 8.052 18.988 7.800L18.988 7.800Q19.156 7.002 18.967 6.204Q18.778 5.406 18.316 4.776Z"/>', + 'seti:swift': + '<path d="M4.419 7.307L4.419 7.307Q4.419 7.231 4.362 7.174Q4.305 7.117 4.305 7.041L4.305 7.041Q4.191 6.889 3.887 6.528Q3.583 6.167 3.469 5.977L3.469 5.977Q3.013 5.559 2.861 5.331L2.861 5.331Q2.557 4.989 2.405 4.685L2.405 4.685Q2.861 5.179 3.583 5.635L3.583 5.635Q3.697 5.711 3.887 5.882Q4.077 6.053 4.191 6.091L4.191 6.091Q4.419 6.281 4.837 6.642Q5.255 7.003 5.483 7.193L5.483 7.193Q5.825 7.497 6.585 8.067L6.585 8.067L7.041 8.371Q8.219 9.321 8.827 9.663L8.827 9.663Q9.283 10.043 10.233 10.689Q11.183 11.335 11.677 11.677L11.677 11.677L11.677 11.563Q10.233 9.929 9.397 9.093L9.397 9.093Q8.447 7.877 7.991 7.421L7.991 7.421L6.813 5.863Q6.813 5.825 6.737 5.768Q6.661 5.711 6.661 5.635L6.661 5.635L5.597 4.191L5.445 3.925Q5.217 3.621 5.141 3.393L5.141 3.393Q5.445 3.621 5.977 4.153Q6.509 4.685 6.794 4.951Q7.079 5.217 7.744 5.806Q8.409 6.395 8.675 6.699L8.675 6.699Q8.941 6.889 9.416 7.307Q9.891 7.725 10.119 7.877L10.119 7.877L11.563 8.941Q11.715 9.093 12.019 9.321Q12.323 9.549 12.475 9.663L12.475 9.663Q15.097 11.563 16.541 12.513L16.541 12.513Q16.617 12.627 16.693 12.608Q16.769 12.589 16.769 12.399L16.769 12.399Q17.377 10.917 17.377 8.713L17.377 8.713Q17.377 7.117 16.769 5.521L16.769 5.521Q16.769 5.293 16.541 4.571L16.541 4.571L16.351 4.191Q15.971 3.393 15.705 3.013L15.705 3.013Q15.553 2.405 14.869 1.721L14.869 1.721Q14.869 1.645 14.812 1.588Q14.755 1.531 14.755 1.493L14.755 1.493Q15.211 1.721 15.933 2.177L15.933 2.177Q18.479 4.077 20.341 6.813L20.341 6.813L20.607 7.383Q21.215 8.523 21.405 9.093L21.405 9.093Q22.241 11.145 22.241 12.893L22.241 12.893L22.241 13.007Q22.241 14.071 22.127 14.527L22.127 14.527Q22.051 14.793 21.994 15.268Q21.937 15.743 21.899 15.971Q21.861 16.199 21.975 16.313L21.975 16.313Q23.419 18.099 23.761 20.227L23.761 20.227Q23.875 20.607 23.875 21.443L23.875 21.443Q23.875 22.013 23.761 22.393L23.761 22.393Q23.761 22.469 23.761 22.488Q23.761 22.507 23.666 22.507Q23.571 22.507 23.571 22.431L23.571 22.431L23.533 22.393Q22.735 20.759 21.291 20.607L21.291 20.607Q20.607 20.417 19.923 20.569L19.923 20.569Q19.391 20.645 18.669 20.949L18.669 20.949Q18.403 21.063 17.947 21.291L17.947 21.291Q17.377 21.595 17.111 21.671L17.111 21.671Q14.603 22.735 11.905 22.393L11.905 22.393Q9.929 22.165 8.333 21.557L8.333 21.557L8.219 21.557Q7.877 21.367 7.155 21.063Q6.433 20.759 6.091 20.607L6.091 20.607Q2.633 18.707 0.277 15.249L0.277 15.249L0.125 15.135L0.277 15.135L0.391 15.249Q1.075 15.743 1.569 15.971L1.569 15.971L2.025 16.237Q2.671 16.617 2.975 16.693L2.975 16.693Q3.849 17.187 5.027 17.377L5.027 17.377Q5.065 17.453 5.122 17.453Q5.179 17.453 5.255 17.529L5.255 17.529Q6.851 17.985 9.055 17.985L9.055 17.985Q11.487 17.795 13.311 16.807L13.311 16.807Q13.501 16.693 13.501 16.674Q13.501 16.655 13.311 16.579L13.311 16.579Q12.779 16.161 11.715 15.211L11.715 15.211L10.955 14.527Q10.651 14.299 10.119 13.767Q9.587 13.235 9.283 13.007L9.283 13.007Q8.827 12.627 8.105 11.677L8.105 11.677Q7.991 11.525 7.687 11.221Q7.383 10.917 7.269 10.727L7.269 10.727Q7.041 10.499 6.566 9.967Q6.091 9.435 5.882 9.188Q5.673 8.941 5.312 8.542Q4.951 8.143 4.761 7.877L4.761 7.877Q4.761 7.649 4.419 7.307Z"/>', + 'seti:db': + '<path d="M12.546 9.327L12.546 9.327Q9.858 9.327 7.884 9.201L7.884 9.201Q5.448 9.033 3.348 8.571L3.348 8.571Q2.844 8.487 1.920 8.109L1.920 8.109Q1.416 7.857 1.122 7.773L1.122 7.773Q0.576 7.605 0.576 6.975L0.576 6.975L0.576 2.397Q0.576 2.187 0.681 2.019Q0.786 1.851 0.954 1.851L0.954 1.851L1.374 1.683Q2.802 1.053 3.600 0.927L3.600 0.927Q5.784 0.423 8.472 0.255L8.472 0.255Q10.068 0.171 13.302 0.171L13.302 0.171Q17.712 0.171 21.198 1.095L21.198 1.095Q21.996 1.263 22.878 1.725L22.878 1.725Q23.424 1.893 23.424 2.523L23.424 2.523L23.424 7.101Q23.424 7.395 23.046 7.773L23.046 7.773Q21.996 8.277 21.450 8.445L21.450 8.445L19.602 8.739Q17.166 9.117 15.948 9.201L15.948 9.201Q15.360 9.285 14.205 9.285Q13.050 9.285 12.546 9.327ZM23.424 9.621L23.424 9.621L23.424 14.325Q23.424 14.535 23.193 14.766Q22.962 14.997 22.752 14.997L22.752 14.997L22.080 15.249Q20.820 15.669 20.274 15.795L20.274 15.795Q15.360 16.635 8.976 16.425L8.976 16.425L8.892 16.425Q6.792 16.299 5.700 16.173L5.700 16.173Q3.936 15.963 2.550 15.501L2.550 15.501Q2.004 15.375 0.996 14.871L0.996 14.871Q0.576 14.661 0.576 14.199L0.576 14.199L0.576 9.621Q3.180 10.503 6.288 10.839L6.288 10.839Q8.514 11.049 12 11.049L12 11.049Q15.150 11.175 17.712 10.881L17.712 10.881Q20.736 10.545 23.424 9.621ZM23.424 16.971L23.424 16.971L23.424 21.549Q23.424 21.759 23.193 21.990Q22.962 22.221 22.752 22.347L22.752 22.347Q21.702 22.725 21.198 22.893L21.198 22.893Q20.316 23.187 19.602 23.271L19.602 23.271Q11.580 24.447 3.726 23.145L3.726 23.145Q3.054 23.019 1.710 22.557L1.710 22.557L1.122 22.347Q0.828 22.263 0.702 22.053Q0.576 21.843 0.576 21.423L0.576 21.423L0.576 16.971Q3.096 17.853 6.204 18.189L6.204 18.189Q8.430 18.399 12 18.399L12 18.399Q15.486 18.399 17.712 18.189L17.712 18.189Q20.820 17.853 23.424 16.971Z"/>', + 'seti:terraform': + '<path d="M8.850 11.880L8.850 4.200L15.150 8.040L15.150 15.720L8.850 11.880ZM22.590 4.200L15.900 8.040L15.900 15.720L22.590 11.880L22.590 4.200ZM8.100 3.840L1.410 0.120L1.410 7.560L8.100 11.280L8.100 3.840ZM8.850 12.750L8.850 20.160L15.150 23.880L15.150 16.470L8.850 12.750Z"/>', + 'seti:tex': + '<path d="M3.651 6.951L3.651 13.650L2.199 13.650L2.199 14.970L6.753 14.970L6.753 13.650L5.400 13.650L5.400 6.951L5.829 6.951Q6.456 6.951 6.753 7.017Q7.050 7.083 7.198 7.281Q7.347 7.479 7.479 7.974L7.479 7.974L8.700 7.974L8.502 5.598L0.450 5.598L0.153 9.327L1.374 9.327L1.374 8.799Q1.473 7.842 1.605 7.545L1.605 7.545Q1.770 7.149 2.100 7.050L2.100 7.050Q2.397 6.951 3.222 6.951L3.222 6.951L3.651 6.951ZM11.802 17.346L11.802 17.346L10.053 17.346L10.053 14.475L10.647 14.475Q11.076 14.475 11.191 14.508Q11.307 14.541 11.340 14.706Q11.373 14.871 11.373 15.399L11.373 15.399L11.373 15.927L12.627 15.927L12.627 11.670L11.373 11.670L11.373 12.198Q11.373 12.726 11.340 12.891Q11.307 13.056 11.191 13.089Q11.076 13.122 10.647 13.122L10.647 13.122L10.053 13.122L10.053 10.647L11.703 10.647Q12.462 10.647 12.809 10.812Q13.155 10.977 13.287 11.373L13.287 11.373Q13.386 11.703 13.452 12.495L13.452 12.495L14.673 12.495L14.376 9.195L7.149 9.195L7.149 10.548L8.172 10.548L8.172 17.148L7.149 17.148L7.149 18.501L14.475 18.501L14.871 15.795L13.551 15.795Q13.551 16.686 13.171 17.016Q12.792 17.346 11.802 17.346ZM17.874 14.970L17.874 13.749L17.379 13.749L18.897 11.472L20.448 13.749L20.151 13.749L20.151 14.871L23.847 14.871L23.847 13.650L23.352 13.650Q22.890 13.650 22.791 13.617Q22.692 13.584 22.626 13.452L22.626 13.452L20.151 9.822L21.801 7.446L21.900 7.347Q22.098 7.116 22.263 7.017L22.263 7.017Q22.527 6.852 22.923 6.852L22.923 6.852L23.451 6.852L23.451 5.499L20.250 5.499L20.250 6.720L20.778 6.720L20.679 6.852L19.425 8.601L18.072 6.951L18.402 6.951L18.402 5.499L14.673 5.499L14.673 6.951L15.201 6.951Q15.663 6.951 15.745 6.967Q15.828 6.984 15.927 7.149L15.927 7.149L18.072 10.350L16.224 13.122L15.927 13.452Q15.597 13.749 15.102 13.749L15.102 13.749L14.574 13.749L14.574 14.970L17.874 14.970Z"/>', + 'seti:default': + '<path d="M1.082 16.876L1.082 14.014L22.918 14.014L22.918 16.876L1.082 16.876ZM1.082 9.986L1.082 7.071L13.272 7.071L13.272 9.986L1.082 9.986ZM1.082 3.096L1.082 0.181L22.918 0.181L22.918 3.096L1.082 3.096ZM1.082 23.819L1.082 20.904L17.300 20.904L17.300 23.819L1.082 23.819Z"/>', + 'seti:twig': + '<path d="M17.640 0.080L17.640 0.120Q17.680 0.120 17.760 0.120L17.760 0.120L18.080 0.120L18.080 0.120L17.640 0.120L17.640 0.080ZM16.680 0.720L16.360 0.720Q17.080 0.160 17.640 0.120L17.640 0.120L18.160 0.120Q18.280 0.120 18.280 0.160L18.280 0.160L17.920 0.160Q17.400 0.160 16.680 0.720L16.680 0.720ZM16.680 0.720L16.680 0.720Q17.400 0.160 17.920 0.160L17.920 0.160Q17.360 0.360 17.040 0.640L17.040 0.640Q16.880 0.760 16.640 1.040L16.640 1.040L16.440 1.200Q16.240 1.160 16.080 1.320L16.080 1.320Q16.320 1 16.680 0.720ZM17.920 0.160L17.920 0.160Q18.040 0.160 18.280 0.160L18.280 0.160Q18.920 0.280 19.560 1.040L19.560 1.040L19.520 1.120Q18.880 0.480 18.240 0.360L18.240 0.360Q18.080 0.320 18 0.360L18 0.360Q17.640 0.440 17.400 0.600L17.400 0.600Q17.280 0.640 17.120 0.800L17.120 0.800L17 0.920Q16.880 0.840 17 0.680L17 0.680L17.040 0.640Q17.360 0.360 17.920 0.160ZM18 0.360L18 0.360Q18.080 0.320 18.240 0.360L18.240 0.360Q18.120 0.440 18 0.360ZM16 1.800L16.440 1.200Q16.480 1.160 16.640 1.040L16.640 1.040Q16.880 0.760 17.040 0.640L17.040 0.640L17 0.680Q16.880 0.840 17 0.920L17 0.920Q16.600 1.440 16 2.560L16 2.560L15.960 2.680Q15.920 2.800 15.840 2.840L15.840 2.840L15.880 2.680L15.520 2.640L15.520 2.600L16 1.800ZM15.440 1.640L15.480 1.520Q15.600 1.440 15.800 1.200L15.800 1.200Q16.160 0.840 16.360 0.720L16.360 0.720L16.680 0.720Q16.360 0.960 16.080 1.320L16.080 1.320L15.840 1.600Q15.760 1.640 15.600 1.560L15.600 1.560L15.560 1.520L15.520 1.560Q15.480 1.640 15.440 1.640L15.440 1.640ZM19.520 1.120L19.560 1.040Q19.680 1.160 19.720 1.280L19.720 1.280L19.720 1.320L19.640 1.240Q19.520 1.160 19.520 1.120L19.520 1.120ZM15.840 1.600L16.080 1.320Q16.240 1.160 16.440 1.200L16.440 1.200L16 1.800L15.840 1.920L15.640 1.880L15.840 1.600ZM19.720 1.320L19.720 1.280Q19.840 1.360 19.880 1.520L19.880 1.520Q19.760 1.440 19.720 1.320L19.720 1.320ZM15.520 1.560L15.560 1.520Q15.560 1.560 15.600 1.560L15.600 1.560Q15.760 1.640 15.840 1.600L15.840 1.600L15.640 1.880Q15.280 2.440 14.960 3L14.960 3L14.600 3.760L14.080 3.720L13.920 3.880Q14.480 2.800 15.240 1.840L15.240 1.840L15.280 1.760Q15.360 1.640 15.420 1.640Q15.480 1.640 15.520 1.560L15.520 1.560ZM15.640 1.880L15.840 1.920Q15.880 1.920 15.920 1.880L15.920 1.880L16 1.800L15.560 2.600L15.400 2.680L15.240 2.640Q15.200 2.680 15.120 2.840Q15.040 3 14.960 3L14.960 3Q15.280 2.400 15.640 1.880L15.640 1.880ZM15.240 2.640L15.400 2.680Q15.440 2.680 15.480 2.640L15.480 2.640L15.560 2.600L15.520 2.640Q15.320 3.040 14.960 3.920L14.960 3.920L14.720 4.560Q14.520 5.040 14.480 5.280L14.480 5.280L14.440 5.400Q14.360 5.440 14.280 5.640Q14.200 5.840 14.120 5.880Q14.040 5.920 13.980 5.780Q13.920 5.640 13.840 5.640L13.840 5.640L13.920 5.280L14.560 3.760L14.960 3Q15.040 3 15.120 2.840Q15.200 2.680 15.240 2.640L15.240 2.640ZM15.520 2.640L15.520 2.640Q15.760 2.640 15.880 2.680L15.880 2.680L15.840 2.840Q15.320 4.080 14.880 5.360L14.880 5.360L14.800 5.320Q14.560 5.320 14.480 5.280L14.480 5.280Q14.520 5.040 14.720 4.560L14.720 4.560L14.960 3.920Q15.320 3.040 15.520 2.640ZM13.920 3.880L13.920 3.880Q13.960 3.840 14.040 3.760L14.040 3.760L14.080 3.720L14.560 3.760L13.920 5.280Q13.880 5.320 13.840 5.420Q13.800 5.520 13.760 5.520L13.760 5.520L13.720 5.440Q13.560 5.240 13.560 5.120L13.560 5.120Q13.440 5.080 13.400 5.180Q13.360 5.280 13.300 5.460Q13.240 5.640 13.160 5.720L13.160 5.720Q13.160 5.600 13.240 5.400L13.240 5.400L13.360 5.120Q13.720 4.280 13.920 3.880ZM13.400 5.200L13.400 5.200Q13.440 5.080 13.560 5.120L13.560 5.120Q13.560 5.240 13.720 5.440L13.720 5.440L13.760 5.520Q13.800 5.520 13.840 5.420Q13.880 5.320 13.920 5.280L13.920 5.280L13.840 5.640Q13.400 6.800 13.240 7.480L13.240 7.480Q13.120 7.840 12.960 8.560L12.960 8.560L12.840 9.160L12.760 9.200Q12.640 9.280 12.560 9.280L12.560 9.280Q12.240 9.440 12.160 9.720L12.160 9.720Q12.160 9.640 12.160 9.560L12.160 9.560Q12.560 7.520 13.080 5.880L13.080 5.880L13.160 5.720Q13.240 5.640 13.300 5.460Q13.360 5.280 13.400 5.200ZM14.240 5.920L14.480 5.280Q14.560 5.320 14.800 5.320L14.800 5.320L14.880 5.360Q14.800 5.400 14.800 5.520L14.800 5.520L14.800 5.560Q14.760 5.800 14.600 6.280L14.600 6.280L14.440 6.760Q14.240 7.520 14.040 8.320L14.040 8.320L14.040 8.400Q14.040 8.440 14 8.440L14 8.440Q13.840 8.440 13.640 8.440L13.640 8.440Q13.560 8.520 13.480 8.680L13.480 8.680Q13.560 8.240 13.800 7.400L13.800 7.400L13.920 6.920Q14.040 6.560 14.240 5.920L14.240 5.920ZM14.800 5.560L14.800 5.560Q14.800 5.560 14.800 5.520L14.800 5.520Q14.800 5.400 14.880 5.360L14.880 5.360L14.840 5.400Q14.840 5.560 14.800 5.560ZM14.160 5.920L14.160 5.920Q14.200 5.840 14.280 5.640Q14.360 5.440 14.440 5.400L14.440 5.400L13.920 6.920Q13.880 6.960 13.760 7.120L13.760 7.120L13.760 7.200Q13.640 7.200 13.580 7.180Q13.520 7.160 13.520 7.100Q13.520 7.040 13.440 7.080L13.440 7.080L13.440 7.120Q13.360 7.400 13.240 7.480L13.240 7.480Q13.400 6.800 13.840 5.640L13.840 5.640Q13.920 5.640 13.980 5.780Q14.040 5.920 14.160 5.920ZM13.760 7.200L13.760 7.200Q13.760 7.160 13.760 7.120L13.760 7.120Q13.880 6.960 13.920 6.920L13.920 6.920L13.800 7.440Q13.560 8.240 13.480 8.680L13.480 8.680L13.320 9.240Q13.240 9.360 13.180 9.600Q13.120 9.840 13.080 9.920L13.080 9.920L13 9.960Q12.800 10 12.720 10.040L12.720 10.040L12.640 10.440Q12.640 10.320 12.660 10.160Q12.680 10 12.760 9.660Q12.840 9.320 12.840 9.160L12.840 9.160L12.960 8.560Q13.120 7.840 13.240 7.480L13.240 7.480Q13.360 7.400 13.440 7.120L13.440 7.120L13.440 7.080Q13.520 7.040 13.520 7.100Q13.520 7.160 13.580 7.180Q13.640 7.200 13.760 7.200ZM13.640 8.440L13.640 8.440Q13.840 8.440 14 8.440L14 8.440L13.840 9.480Q13.640 10.440 13.560 10.920L13.560 10.920L13.560 10.920Q13.520 10.760 13.600 10.440L13.600 10.440L13.600 10.400Q13.520 10.360 13.360 10.420Q13.200 10.480 13.140 10.500Q13.080 10.520 13.080 10.600L13.080 10.600L13.040 10.640Q13.080 10.360 13.200 9.840L13.200 9.840L13.320 9.240L13.480 8.680Q13.560 8.520 13.640 8.440ZM12.560 9.280L12.560 9.280Q12.640 9.280 12.760 9.200L12.760 9.200L12.840 9.160Q12.840 9.320 12.760 9.660Q12.680 10 12.640 10.200L12.640 10.200Q12.360 10.120 12.080 10.200L12.080 10.200Q12.080 10.080 12.120 9.940Q12.160 9.800 12.160 9.720L12.160 9.720Q12.240 9.440 12.560 9.280ZM13 9.960L13.080 9.920Q13.120 9.840 13.180 9.600Q13.240 9.360 13.320 9.240L13.320 9.240L13.200 9.840Q13.080 10.360 13.040 10.640L13.040 10.640L13.040 10.800L13 10.680Q12.960 10.680 12.960 10.760Q12.960 10.840 12.940 10.880Q12.920 10.920 12.760 10.880L12.760 10.880L12.640 10.880L12.560 11.040L12.560 10.800L12.720 10.040Q12.800 10 13 9.960L13 9.960ZM12.080 10.200L12.080 10.200Q12.400 10.120 12.640 10.200L12.640 10.200Q12.640 10.320 12.640 10.440L12.640 10.440L12.560 10.800Q12.480 10.840 12.320 10.820Q12.160 10.800 12.080 10.840Q12 10.880 11.960 11.040L11.960 11.040L11.960 11.080Q11.960 10.640 12.080 10.200ZM13.120 10.480L13.120 10.480Q13.200 10.480 13.360 10.420Q13.520 10.360 13.600 10.400L13.600 10.400L13.600 10.480Q13.520 10.760 13.560 10.920L13.560 10.920Q13.520 11.200 13.480 11.680L13.480 11.680L13.440 11.680Q13.480 11.560 13.360 11.440L13.360 11.440L13 11.440L12.880 11.720L12.920 11.360L13.080 10.560Q13.120 10.520 13.120 10.480ZM12.960 10.840L12.960 10.840Q12.960 10.840 12.960 10.760Q12.960 10.680 13 10.680L13 10.680L13.040 10.800L12.920 11.360L12.800 11.600L12.560 11.560L12.440 11.760L12.480 11.320Q12.520 11.120 12.560 11.040L12.560 11.040L12.640 10.880L12.760 10.880Q12.920 10.920 12.960 10.840ZM12.080 10.840L12.080 10.840Q12.160 10.800 12.320 10.820Q12.480 10.840 12.560 10.800L12.560 10.800L12.560 11.040Q12.520 11.120 12.480 11.320L12.480 11.320L12.440 11.520Q12.360 11.600 12.160 11.560L12.160 11.560L12 11.520L11.840 11.800Q11.840 11.440 11.960 11.080L11.960 11.080L11.960 11.040Q12 10.880 12.080 10.840ZM16 11L16 11Q16.040 11 16.080 10.960L16.080 10.960Q16.240 10.840 16.320 10.880L16.320 10.880Q14.800 12.480 14.240 15.560L14.240 15.560L14.200 15.520Q14.040 15.480 13.880 15.480L13.880 15.480L13.880 15.320Q14.160 14.200 14.360 13.640L14.360 13.640Q14.640 12.720 15.080 12.040L15.080 12.040L15.120 12Q15.200 11.880 15.180 11.820Q15.160 11.760 15.240 11.640L15.240 11.640L15.400 11.520Q15.760 11.160 16 11ZM12.560 11.560L12.800 11.600Q12.800 11.600 12.800 11.560L12.800 11.560L12.920 11.360L12.880 11.720Q12.840 11.800 12.760 12L12.760 12L12.720 12.160L12.480 12.120L12.360 12.400L12.360 12.360Q12.400 12.040 12.440 11.760L12.440 11.760L12.560 11.560ZM12.880 11.720L13 11.440L13.360 11.440Q13.480 11.560 13.440 11.680Q13.400 11.800 13.400 11.940Q13.400 12.080 13.360 12.400Q13.320 12.720 13.320 12.840L13.320 12.840L13.280 12.840L13.280 12.720Q13.320 12.520 13.240 12.500Q13.160 12.480 13.040 12.440L13.040 12.440Q12.800 12.400 12.800 12.560L12.800 12.560L12.760 12.520L12.760 12.400L12.800 12.120Q12.880 11.880 12.880 11.720L12.880 11.720ZM11.840 11.800L12 11.520Q12.040 11.520 12.160 11.560L12.160 11.560Q12.360 11.600 12.440 11.520L12.440 11.520L12.440 11.760Q12.400 12.040 12.360 12.360L12.360 12.360L12.280 12.560Q12.240 12.600 12.040 12.540Q11.840 12.480 11.800 12.640Q11.760 12.800 11.720 13L11.720 13Q11.680 12.800 11.760 12.400L11.760 12.400L11.800 12.160Q11.800 11.920 11.840 11.800L11.840 11.800ZM13.400 11.920L13.400 11.920Q13.400 11.800 13.440 11.680L13.440 11.680Q13.520 11.880 13.400 11.920ZM12.480 12.120L12.720 12.160Q12.720 12.120 12.760 12L12.760 12Q12.840 11.800 12.880 11.720L12.880 11.720Q12.880 11.880 12.800 12.120L12.800 12.120L12.760 12.400L12.640 12.680L12.440 12.640Q12.400 12.680 12.360 12.840L12.360 12.840L12.360 12.880L12.360 12.400L12.480 12.120ZM14.800 12.280L14.800 12.280Q14.840 12.240 14.880 12.120L14.880 12.120Q15.040 11.880 15.160 11.800L15.160 11.800Q15.200 11.880 15.120 12L15.120 12L15.080 12.040Q14.640 12.720 14.360 13.640L14.360 13.640Q14.160 14.200 13.880 15.320L13.880 15.320L13.880 15.480Q13.760 15.640 13.720 16.040L13.720 16.040L13.680 16.320Q13.600 16.320 13.480 16.200L13.480 16.200L13.400 16.080Q13.360 16.080 13.240 16.120L13.240 16.120L13.200 16.120Q13.280 15.720 13.520 15L13.520 15L13.640 14.640Q14.200 13.160 14.800 12.280ZM12.280 12.560L12.280 12.560Q12.320 12.520 12.320 12.440L12.320 12.440L12.360 12.360L12.280 13.560L12.200 15.320Q12.160 15.640 12.160 16.200L12.160 16.200L12.160 17.760L12.120 17.760L11.920 17.360Q11.760 17.040 11.640 16.880L11.640 16.880L11.600 16.880Q11.560 16.800 11.520 16.820Q11.480 16.840 11.540 17.020Q11.600 17.200 11.720 17.600L11.720 17.600Q11.920 18.200 11.920 18.560L11.920 18.560L11.840 18.320Q11.720 17.680 11.480 17.120L11.480 17.120L11.400 16.880Q11.440 16.680 11.440 16.560L11.440 16.560L11.440 16.360Q11.480 16.080 11.480 15.840L11.480 15.840L11.480 15.600Q11.480 15.440 11.520 15.120L11.520 15.120L11.560 14.600Q11.600 14.480 11.600 14.360L11.600 14.360L11.600 14.120Q11.600 13.760 11.680 13.400L11.680 13.400L11.720 13Q11.760 12.800 11.800 12.640Q11.840 12.480 12.040 12.540Q12.240 12.600 12.280 12.560ZM12.640 12.720L12.640 12.680Q12.640 12.680 12.640 12.680L12.640 12.680L12.760 12.400L12.760 12.520L12.680 12.880Q12.640 13.200 12.560 13.400L12.560 13.400L12.400 13.360Q12.360 13.480 12.280 13.720L12.280 13.720L12.280 13.760L12.360 12.840Q12.400 12.680 12.440 12.640L12.440 12.640L12.640 12.720ZM12.800 12.560L12.800 12.560Q12.800 12.400 13.040 12.440L13.040 12.440Q13.160 12.480 13.240 12.500Q13.320 12.520 13.280 12.720L13.280 12.720L13.280 12.840Q13.320 13.280 13.200 13.720L13.200 13.720L13.200 14Q13.160 14.200 13.160 14.400L13.160 14.400L13.160 14.960L13.120 15.240Q13.080 15.440 13.080 15.680L13.080 15.680L13.040 16.640L13 16.760Q12.920 16.960 12.920 17.040L12.920 17.040Q12.880 17.040 12.880 17.120L12.880 17.120L12.880 17.200Q12.760 17.280 12.680 17.360L12.680 17.360Q12.720 17.120 12.680 16.600L12.680 16.600L12.640 16.120Q12.560 15.480 12.640 14.160L12.640 14.160L12.640 13.520Q12.680 13.200 12.800 12.560ZM12.680 12.880L12.760 12.520L12.800 12.560Q12.680 13.200 12.640 13.520L12.640 13.520Q12.480 15 12.600 16.520L12.600 16.520Q12.560 16.840 12.400 17.440L12.400 17.440L12.280 18.040Q12.280 18.080 12.200 18.120L12.200 18.120L12.160 18.120L12.160 16.440Q12.200 16.160 12.200 15.600L12.200 15.600L12.200 15.320L12.280 13.720Q12.360 13.480 12.400 13.360L12.400 13.360L12.560 13.400Q12.640 13.200 12.680 12.880L12.680 12.880ZM5.360 13.080L5.360 12.680Q5.440 12.680 5.440 12.800L5.440 12.800L5.400 13.080L5.360 13.080ZM5.400 13.080L5.400 13.080L5.440 12.840L5.640 13.840Q5.680 13.920 5.640 14L5.640 14Q5.600 14.200 5.680 14.600L5.680 14.600Q5.760 15.200 5.600 15.440L5.600 15.440L5.520 15.360L5.520 15.200Q5.520 15.040 5.480 14.960L5.480 14.960L5.480 14.400Q5.520 14.280 5.480 14.160Q5.440 14.040 5.440 13.880L5.440 13.880L5.440 13.760Q5.440 13.560 5.420 13.400Q5.400 13.240 5.400 13.080ZM11.680 13.080L11.680 13.400Q11.680 13.360 11.660 13.220Q11.640 13.080 11.680 13.080L11.680 13.080ZM5.440 13.440L5.440 13.440Q5.440 13.560 5.440 13.760L5.440 13.760L5.440 13.880L5.400 13.880Q5.400 13.680 5.440 13.440ZM12.600 16.520L12.600 16.520Q12.480 15 12.640 13.520L12.640 13.520L12.640 14.160Q12.560 15.480 12.640 16.120L12.640 16.120L12.680 16.600Q12.720 17.120 12.680 17.360L12.680 17.360Q12.760 17.280 12.880 17.200L12.880 17.200L12.880 17.280L12.600 18.640L12.560 18.600Q12.520 18.560 12.480 18.600L12.480 18.600L12.360 18.600Q12.200 18.640 12.160 18.720L12.160 18.720L12.160 18.120L12.200 18.120Q12.280 18.080 12.280 18.040L12.280 18.040L12.400 17.440Q12.560 16.840 12.600 16.520ZM13.200 14.040L13.200 14Q13.200 14 13.200 13.960L13.200 13.960L13.200 13.720Q13.240 13.880 13.200 14.040L13.200 14.040ZM7.680 14.040L7.680 14.040Q7.640 14.080 7.540 14.020Q7.440 13.960 7.460 13.920Q7.480 13.880 7.640 13.960L7.640 13.960Q8.280 13.920 9 14.160L9 14.160L9 14.160L8.720 14.480L8.400 14.320Q7.920 14.080 7.680 14.040ZM5.520 15.360L5.640 15.440Q5.760 15.200 5.680 14.600L5.680 14.600Q5.600 14.200 5.640 14L5.640 14Q5.720 14.200 5.800 14.600L5.800 14.600L5.840 14.920Q5.760 14.840 5.720 14.940Q5.680 15.040 5.720 15.080L5.720 15.080Q5.760 15.320 5.720 15.800L5.720 15.800L5.720 16.080L5.640 16.240Q5.560 16.200 5.520 16.040L5.520 16.040L5.520 15.360ZM13.200 14.400L13.160 14.400Q13.160 14.200 13.200 14.040L13.200 14.040L13.200 14.400ZM11.600 14.360L11.560 14.360Q11.480 14.160 11.600 14.120L11.600 14.120L11.600 14.360ZM5.480 14.160L5.480 14.160Q5.520 14.280 5.480 14.400L5.480 14.400L5.480 14.400Q5.400 14.280 5.480 14.160ZM8.720 14.480L9 14.160Q9.240 14.240 9.440 14.360L9.440 14.360L9.360 14.480L9.480 14.560Q9.640 14.680 9.720 14.760Q9.800 14.840 9.820 15.080Q9.840 15.320 9.960 15.400L9.960 15.400Q9.920 15.440 9.960 15.560L9.960 15.560L9.960 15.720Q9.880 15.640 9.800 15.480L9.800 15.480L9.680 15.320L9.480 15.120Q9.040 14.720 8.800 14.560L8.800 14.560L8.760 14.520Q8.720 14.480 8.720 14.480L8.720 14.480ZM11.560 14.360L11.560 14.360L11.600 14.360Q11.600 14.480 11.560 14.600L11.560 14.600Q11.520 14.440 11.560 14.360ZM9.480 14.560L9.360 14.480Q9.400 14.400 9.440 14.360L9.440 14.360Q10.320 14.880 11 16.080L11 16.080Q10.920 16.160 10.800 16.240L10.800 16.240Q10.800 16.440 10.960 16.720L10.960 16.720Q11.080 17.320 10.880 17.880L10.880 17.880L10.920 18.280L10.880 18.280Q10.760 17.080 9.960 15.720L9.960 15.720L9.960 15.560Q9.920 15.440 9.960 15.400L9.960 15.400Q9.840 15.320 9.820 15.080Q9.800 14.840 9.720 14.760Q9.640 14.680 9.480 14.560L9.480 14.560ZM13.160 14.680L13.160 14.400L13.200 14.400L13.200 14.480Q13.200 14.640 13.160 14.680L13.160 14.680ZM5.480 14.400L5.480 14.400L5.480 14.400L5.480 14.680L5.440 14.680Q5.400 14.520 5.480 14.400ZM11.560 14.640L11.520 14.920Q11.520 14.880 11.520 14.840L11.520 14.840Q11.480 14.640 11.560 14.640L11.560 14.640ZM5.440 14.680L5.440 14.680L5.480 14.680L5.480 14.920L5.440 14.960Q5.440 14.800 5.440 14.680ZM5.720 15.080L5.720 15.080Q5.680 15.040 5.720 14.940Q5.760 14.840 5.840 14.920L5.840 14.920L5.920 15.520L5.880 15.520Q5.760 15.600 5.840 15.720L5.840 15.720Q5.800 15.840 5.840 16.040Q5.880 16.240 5.840 16.360L5.840 16.360L5.760 16.520L5.720 16.080L5.720 15.800Q5.760 15.320 5.720 15.080ZM5.480 14.960L5.480 14.960Q5.520 15.040 5.520 15.200L5.520 15.200L5.520 15.280L5.480 15.280Q5.480 15.120 5.480 14.960ZM13.120 15.280L13.120 15.240Q13.120 15.200 13.120 15.160L13.120 15.160L13.160 14.960L13.160 15.280L13.120 15.280ZM13.120 15.680L13.080 15.680Q13.080 15.360 13.120 15.240L13.120 15.240L13.120 15.360Q13.120 15.560 13.120 15.680L13.120 15.680ZM5.480 15.600L5.480 15.280L5.520 15.280L5.520 15.600L5.480 15.600ZM12.160 16.440L12.160 16.440Q12.160 16.360 12.160 16.200L12.160 16.200Q12.160 15.640 12.200 15.320L12.200 15.320L12.200 15.600Q12.200 16.160 12.160 16.440ZM13.680 16.320L13.680 16.320Q13.720 16.240 13.720 16.040L13.720 16.040Q13.760 15.640 13.880 15.480L13.880 15.480Q14 15.480 14.200 15.520L14.200 15.520Q14.160 15.680 14.160 15.920L14.160 15.920L14.160 15.960Q14.120 16.120 14.080 16.280Q14.040 16.440 14.060 16.540Q14.080 16.640 14.040 16.760L14.040 16.760L14 16.840Q13.880 16.840 13.840 16.880L13.840 16.880L13.680 17.040Q13.600 17.240 13.560 17.600L13.560 17.600Q13.480 18.120 13.360 18.360L13.360 18.360Q13.320 18.360 13.200 18.320L13.200 18.320L13.120 18.280L13.040 18.280Q12.920 18.240 12.840 18.200Q12.760 18.160 12.840 18.040L12.840 18.040Q12.880 17.480 13.080 16.680L13.080 16.680Q13.120 16.560 13.080 16.480L13.080 16.480L13.080 16.360Q13.160 16.280 13.200 16.120L13.200 16.120L13.240 16.120Q13.360 16.080 13.400 16.080L13.400 16.080L13.480 16.200Q13.600 16.320 13.680 16.320ZM5.840 15.720L5.840 15.720Q5.760 15.600 5.880 15.520L5.880 15.520L5.920 15.520L6.080 16.400Q6 16.360 5.960 16.440L5.960 16.440L5.960 17L5.880 17.080Q5.840 17.160 5.840 17.240L5.840 17.240Q5.800 17.080 5.720 16.960L5.720 16.960L5.760 16.520L5.840 16.360Q5.880 16.240 5.840 16.040Q5.800 15.840 5.840 15.720ZM14.160 15.960L14.160 15.960Q14.160 15.960 14.160 15.920L14.160 15.920Q14.160 15.680 14.200 15.520L14.200 15.520Q14.200 15.600 14.200 15.760Q14.200 15.920 14.160 15.960ZM5.480 15.920L5.480 15.600L5.520 15.600L5.520 15.920L5.480 15.920ZM11.480 15.840L11.480 15.840Q11.400 15.640 11.480 15.600L11.480 15.600L11.480 15.840ZM13.080 15.920L13.080 15.680L13.120 15.680Q13.160 15.800 13.120 15.920L13.120 15.920L13.080 15.920ZM11.480 15.840L11.480 15.840L11.480 15.840Q11.480 16.160 11.440 16.360L11.440 16.360L11.440 16.120Q11.440 15.920 11.480 15.840ZM5.480 16.040L5.480 15.920L5.520 15.920L5.520 16.280Q5.440 16.240 5.480 16.040L5.480 16.040ZM13.080 16.400L13.080 15.920L13.120 15.920L13.120 16.160Q13.120 16.200 13.140 16.160Q13.160 16.120 13.200 16.120L13.200 16.120Q13.160 16.280 13.080 16.400L13.080 16.400ZM13.080 16.360L13.040 16.640Q13.040 16.480 13.040 16.240L13.040 16.240L13.080 15.920L13.080 16.360ZM5.520 16.600L5.520 16Q5.520 16 5.520 16.040L5.520 16.040Q5.560 16.200 5.640 16.240L5.640 16.240L5.720 16.080L5.760 16.520L5.720 16.960Q5.640 16.920 5.560 16.920L5.560 16.920L5.560 16.800Q5.560 16.680 5.520 16.600L5.520 16.600ZM10.800 16.240L10.800 16.240Q10.920 16.160 11 16.080L11 16.080Q11.160 16.320 11.320 16.680L11.320 16.680L11.160 16.800L11.240 17.080Q11.360 17.520 11.320 17.760L11.320 17.760L11.240 18Q11.040 18.440 11 18.680L11 18.680L10.960 18.680Q10.960 18.600 10.920 18.480L10.920 18.480L10.880 17.880Q11.080 17.320 10.960 16.720L10.960 16.720Q10.840 16.480 10.800 16.240ZM11.440 16.560L11.400 16.560Q11.440 16.520 11.420 16.360Q11.400 16.200 11.440 16.200L11.440 16.200L11.440 16.560ZM14.080 16.600L14.080 16.560Q14.040 16.440 14.080 16.320L14.080 16.320Q14.200 16.520 14.080 16.600L14.080 16.600ZM5.920 17L5.960 16.440Q6 16.360 6.040 16.420Q6.080 16.480 6.120 16.660Q6.160 16.840 6.100 16.940Q6.040 17.040 6.080 17.160L6.080 17.160Q6.080 17.800 6.160 18.400L6.160 18.400L6.200 18.640Q6.200 18.920 6.280 19.040L6.280 19.040L6.280 19.040L6.200 19.160L6.120 19.160Q5.960 19.120 5.920 19.160L5.920 19.160L5.880 18.520Q5.880 18.280 5.840 17.800L5.840 17.800L5.840 17.240Q5.840 17.160 5.880 17.080L5.880 17.080L5.920 17ZM13 16.760L13.040 16.640L13.080 16.480Q13.120 16.560 13.080 16.680L13.080 16.680Q12.880 17.360 12.840 18.040L12.840 18.040Q12.760 18.160 12.840 18.200Q12.920 18.240 13.040 18.280L13.040 18.280L13.120 18.280L13.200 18.320Q13.320 18.360 13.360 18.360L13.360 18.360Q13.480 18.120 13.560 17.600L13.560 17.600Q13.600 17.240 13.680 17.040L13.680 17.040L13.840 16.880Q13.880 16.840 14 16.840L14 16.840L14 17.080Q14 17.200 13.960 17.480L13.960 17.480L13.880 18.040Q13.800 18.160 13.640 18.160L13.640 18.160Q13.520 18.280 13.480 18.560L13.480 18.560L13.400 18.800Q13.280 18.800 13.120 18.640Q12.960 18.480 12.800 18.500Q12.640 18.520 12.680 18.240L12.680 18.240L12.920 17.040Q12.920 16.960 13 16.760L13 16.760ZM11.400 16.880L11.400 16.560L11.440 16.560Q11.440 16.680 11.400 16.880L11.400 16.880ZM5.520 16.600L5.520 16.600Q5.560 16.680 5.560 16.840L5.560 16.840L5.560 16.960L5.520 16.960L5.520 16.960Q5.520 16.720 5.520 16.600ZM11.240 17.080L11.160 16.800Q11.200 16.760 11.320 16.680L11.320 16.680L11.320 16.760Q11.360 16.840 11.400 16.880L11.400 16.880L11.480 17.120L11.480 17.240Q11.400 17.280 11.440 17.480L11.440 17.480L11.480 17.760Q11.520 18.080 11.520 18.240L11.520 18.240L11.360 18.520Q11.160 18.880 11.120 19.080L11.120 19.080Q11.080 19.160 11.100 19.360Q11.120 19.560 11.120 19.640L11.120 19.640L11.080 19.640L11.040 19.360Q11.080 19.240 11.040 19.120Q11 19 11 18.720L11 18.720L11 18.680Q11.040 18.440 11.240 18L11.240 18L11.320 17.760Q11.360 17.520 11.240 17.080L11.240 17.080ZM14 17.080L14 16.840Q14 16.800 14.040 16.800L14.040 16.800L14.040 16.880Q14.080 17.040 14 17.080L14 17.080ZM11.560 17L11.560 17Q11.480 16.840 11.520 16.820Q11.560 16.800 11.600 16.880L11.600 16.880L11.640 16.880Q11.760 17.040 11.920 17.360L11.920 17.360L12.120 17.760L12.160 17.760L12.160 18.320Q12.080 18.440 11.960 18.560L11.960 18.560L11.920 18.800L11.800 18.800Q11.920 18.640 11.920 18.560L11.920 18.560Q11.920 18.200 11.720 17.600L11.720 17.600Q11.600 17.200 11.560 17ZM5.560 18.200L5.560 16.920Q5.640 16.920 5.720 16.960L5.720 16.960Q5.800 17.080 5.840 17.240L5.840 17.240L5.840 17.800Q5.880 18.280 5.880 18.520L5.880 18.520L5.840 18.360Q5.800 18.120 5.760 18L5.760 18Q5.680 18 5.640 18.120L5.640 18.120L5.560 18.200ZM6.080 17.160L6.080 17.160Q6.040 17.040 6.160 16.920L6.160 16.920Q6.200 17.320 6.320 18.080L6.320 18.080L6.400 18.640Q6.360 18.680 6.400 18.840Q6.440 19 6.440 19.080L6.440 19.080L6.360 18.960L6.280 19.040Q6.200 18.920 6.200 18.640L6.200 18.640L6.160 18.400Q6.080 17.800 6.080 17.160ZM5.520 17.360L5.520 16.960L5.560 16.960L5.560 17.360L5.520 17.360ZM12.880 17.280L12.880 17.200Q12.880 17.160 12.880 17.100Q12.880 17.040 12.920 17.040L12.920 17.040L12.880 17.280ZM11.480 17.240L11.480 17.120Q11.720 17.640 11.840 18.320L11.840 18.320L11.760 18.280L11.760 18.160Q11.640 17.680 11.480 17.240L11.480 17.240ZM11.480 17.760L11.480 17.560Q11.480 17.520 11.440 17.480L11.440 17.480Q11.400 17.280 11.480 17.240L11.480 17.240Q11.680 17.760 11.760 18.160L11.760 18.160L11.640 18.240Q11.600 18.280 11.620 18.380Q11.640 18.480 11.600 18.520L11.600 18.520L11.520 18.640Q11.320 18.840 11.320 18.960L11.320 18.960Q11.240 19.200 11.340 19.600Q11.440 20 11.400 20.200L11.400 20.200Q11.400 20.320 11.280 20.560L11.280 20.560L11.240 20.600Q11.200 20.680 11.180 20.840Q11.160 21 11.120 21.080L11.120 21.080L11.120 19.640Q11.120 19.560 11.100 19.360Q11.080 19.160 11.120 19.080L11.120 19.080Q11.160 18.880 11.360 18.520L11.360 18.520L11.520 18.240Q11.520 18.080 11.480 17.760L11.480 17.760ZM5.520 17.800L5.520 17.360L5.560 17.360L5.560 17.800L5.520 17.800ZM13.960 17.920L13.920 17.920Q13.920 17.880 13.920 17.840L13.920 17.840L13.960 17.560L13.960 17.920ZM13.920 18.400L13.880 18.040L13.920 17.920L13.920 18.400L13.920 18.400ZM5.600 18.880L5.560 18.200Q5.600 18.160 5.640 18.080Q5.680 18 5.760 18L5.760 18Q5.800 18.120 5.840 18.360L5.840 18.360L5.880 18.520L5.880 19Q5.880 19.240 5.800 19.200Q5.720 19.160 5.640 19L5.640 19L5.600 18.880ZM13.640 18.160L13.640 18.160Q13.800 18.160 13.880 18.040L13.880 18.040L13.880 18.640Q13.840 18.640 13.740 18.760Q13.640 18.880 13.520 18.840L13.520 18.840Q13.440 18.920 13.400 19.120L13.400 19.120L13.360 19.240Q13.360 19.040 13.220 18.860Q13.080 18.680 12.880 18.660Q12.680 18.640 12.640 18.440L12.640 18.440L12.680 18.240Q12.640 18.520 12.800 18.500Q12.960 18.480 13.120 18.640Q13.280 18.800 13.400 18.800L13.400 18.800L13.480 18.560Q13.520 18.280 13.640 18.160ZM11.760 18.280L11.640 18.240Q11.680 18.200 11.760 18.160L11.760 18.160L11.760 18.280ZM5.560 18.200L5.560 18.200Q5.600 18.320 5.600 18.560L5.600 18.560L5.600 18.640L5.560 18.640Q5.560 18.440 5.560 18.200ZM11.520 18.640L11.600 18.520Q11.640 18.480 11.620 18.380Q11.600 18.280 11.640 18.240L11.640 18.240L11.800 18.320Q11.720 18.360 11.660 18.500Q11.600 18.640 11.560 18.680L11.560 18.680Q11.440 18.840 11.380 19.020Q11.320 19.200 11.380 19.360Q11.440 19.520 11.600 19.760L11.600 19.760L11.680 19.920Q11.720 20.200 11.520 20.720L11.520 20.720Q11.440 21.040 11.400 21.200L11.400 21.200L11.400 21.280Q11.400 22.240 11.520 22.680L11.520 22.680L11.280 22.640Q11.240 22.600 11.240 22.600L11.240 22.600L11.040 21.800Q11.080 21.760 11.080 21.640L11.080 21.640L11.120 21.080Q11.160 21 11.180 20.840Q11.200 20.680 11.240 20.600L11.240 20.600L11.280 20.560Q11.400 20.320 11.400 20.200L11.400 20.200Q11.440 20 11.340 19.600Q11.240 19.200 11.320 18.960L11.320 18.960Q11.320 18.840 11.520 18.640L11.520 18.640ZM11.560 18.680L11.560 18.680Q11.600 18.640 11.660 18.500Q11.720 18.360 11.800 18.320L11.800 18.320L11.840 18.320Q11.880 18.440 11.720 18.560L11.720 18.560Q11.680 18.640 11.560 18.780Q11.440 18.920 11.440 19.040L11.440 19.040Q11.360 19.240 11.460 19.420Q11.560 19.600 11.760 19.760L11.760 19.760Q11.840 19.760 11.840 19.880L11.840 19.880L11.840 19.920Q11.920 20.400 11.840 21.160L11.840 21.160L11.800 21.480Q11.800 22.160 11.840 22.520L11.840 22.520Q11.880 22.640 11.840 22.760L11.840 22.760L11.520 22.680Q11.400 22.240 11.400 21.240L11.400 21.240L11.400 21.200Q11.440 21.040 11.520 20.720L11.520 20.720Q11.720 20.200 11.680 19.920L11.680 19.920L11.600 19.760Q11.440 19.520 11.380 19.360Q11.320 19.200 11.380 19.020Q11.440 18.840 11.560 18.680ZM11.840 18.320L11.840 18.320L11.920 18.560Q11.920 18.640 11.800 18.800L11.800 18.800Q11.520 18.920 11.520 19.200L11.520 19.200Q11.480 19.360 11.720 19.560L11.720 19.560L11.880 19.680Q11.920 19.920 11.960 20.360L11.960 20.360L11.960 20.680Q12.040 21.480 12 22.760L12 22.760L11.840 22.760Q11.880 22.640 11.840 22.520L11.840 22.520Q11.800 22.160 11.800 21.520L11.800 21.520L11.840 21.160Q11.920 20.400 11.840 19.920L11.840 19.920L11.840 19.880Q11.840 19.760 11.760 19.760L11.760 19.760Q11.560 19.600 11.460 19.420Q11.360 19.240 11.440 19.040L11.440 19.040Q11.440 18.920 11.560 18.780Q11.680 18.640 11.720 18.560L11.720 18.560Q11.880 18.440 11.840 18.320ZM11.920 18.800L11.960 18.560Q12.080 18.440 12.160 18.320L12.160 18.320L12.160 18.720L12.080 18.840L11.920 18.800ZM13.880 18.920L13.920 18.400L13.920 18.400L13.920 18.920L13.880 18.920ZM12.760 18.720L12.600 18.640L12.640 18.440Q12.680 18.640 12.880 18.660Q13.080 18.680 13.220 18.860Q13.360 19.040 13.360 19.240L13.360 19.240L13.400 19.120Q13.440 18.920 13.520 18.840L13.520 18.840Q13.640 18.880 13.740 18.760Q13.840 18.640 13.880 18.640L13.880 18.640L13.880 18.920L13.880 18.960Q13.720 19.080 13.640 19.240L13.640 19.240L13.600 19.200Q13.520 19.160 13.480 19.120L13.480 19.120L13.480 19.240Q13.440 19.440 13.440 19.520L13.440 19.520Q13.440 19.720 13.380 20.120Q13.320 20.520 13.320 20.760L13.320 20.760L13.240 21.080Q13.120 21.040 12.920 21.080Q12.720 21.120 12.640 21.120L12.640 21.120Q12.520 21 12.520 20.800L12.520 20.800L12.640 21L12.720 20.920Q12.880 20.800 12.960 20.820Q13.040 20.840 13.160 20.760L13.160 20.760L13.240 20.720Q13.320 20.520 13.320 20.080L13.320 20.080L13.360 19.800Q13.400 19.560 13.320 19.360L13.320 19.360L13.120 19.640L13.040 19.680Q12.800 19.760 12.700 19.740Q12.600 19.720 12.440 19.720L12.440 19.720L12.440 19.720L12.440 19.720Q12.520 19.640 12.720 19.620Q12.920 19.600 13 19.560L13 19.560Q13.160 19.440 13.180 19.220Q13.200 19 13.040 18.840L13.040 18.840Q13 18.760 12.760 18.720L12.760 18.720ZM4.240 18.560L4.120 18.480Q4.320 18.560 4.680 18.920L4.680 18.920L4.680 18.960Q4.600 18.960 4.600 19.080L4.600 19.080L4.560 19.080Q4.480 18.880 4.240 18.560L4.240 18.560ZM12.080 18.880L12.160 18.720Q12.200 18.640 12.360 18.600L12.360 18.600L12.480 18.600Q12.520 18.560 12.560 18.600L12.560 18.600L12.600 18.640L12.600 18.840Q12.440 18.880 12.400 19.060Q12.360 19.240 12.480 19.360L12.480 19.360Q12.480 19.480 12.440 19.580Q12.400 19.680 12.320 19.680Q12.240 19.680 12.200 19.600L12.200 19.600L12.080 19.360Q12.200 19.240 12.200 19.100Q12.200 18.960 12.080 18.880L12.080 18.880ZM5.560 19.120L5.560 18.640L5.600 18.640L5.600 19.120L5.560 19.120ZM12.600 18.840L12.600 18.640L12.600 18.640L12.760 18.720Q13 18.760 13.040 18.840L13.040 18.840Q13.200 19 13.180 19.220Q13.160 19.440 13 19.560L13 19.560Q12.920 19.600 12.720 19.620Q12.520 19.640 12.440 19.720L12.440 19.720L12.440 19.600Q12.480 19.480 12.480 19.360L12.480 19.360Q12.600 19.480 12.780 19.440Q12.960 19.400 13.040 19.240Q13.120 19.080 12.940 18.920Q12.760 18.760 12.600 18.840L12.600 18.840ZM11.520 19.200L11.520 19.200Q11.520 18.920 11.800 18.800L11.800 18.800L11.920 18.800L12.080 18.840Q12.200 18.960 12.200 19.100Q12.200 19.240 12.080 19.360L12.080 19.360L12 19.440Q11.680 19.520 11.520 19.200ZM12.600 18.840L12.600 18.840Q12.760 18.760 12.940 18.920Q13.120 19.080 13.040 19.240Q12.960 19.400 12.780 19.440Q12.600 19.480 12.480 19.360Q12.360 19.240 12.400 19.060Q12.440 18.880 12.600 18.840ZM5.600 19.280L5.600 18.880Q5.640 18.920 5.680 19.040Q5.720 19.160 5.800 19.200Q5.880 19.240 5.880 19L5.880 19L5.880 18.960L5.920 19.320L5.920 19.560L5.720 19.480Q5.680 19.440 5.640 19.360L5.640 19.360L5.600 19.280ZM13.880 19.240L13.840 18.960L13.880 18.920L13.880 19.240L13.880 19.240ZM4.680 19.280L4.600 19.080Q4.600 18.960 4.680 18.960L4.680 18.960Q5.040 19.280 5.280 19.800L5.280 19.800L5.200 19.880Q5.040 20.040 5 20.120L5 20.120L5 20.120Q4.920 19.840 4.680 19.280L4.680 19.280ZM6.280 19.080L6.280 19.040Q6.320 19 6.360 18.960L6.360 18.960L6.440 19.080L6.440 19.200Q6.480 19.360 6.480 19.440L6.480 19.440Q6.360 19.520 6.340 19.700Q6.320 19.880 6.300 19.960Q6.280 20.040 6.080 20.080L6.080 20.080L5.960 20.120L5.960 19.840Q5.960 19.760 6.100 19.760Q6.240 19.760 6.280 19.720L6.280 19.720L6.280 19.320Q6.320 19.160 6.280 19.080L6.280 19.080ZM13.600 19.200L13.640 19.240Q13.720 19.080 13.840 18.960L13.840 18.960L13.880 20.240Q13.760 20.160 13.620 20.300Q13.480 20.440 13.400 20.440L13.400 20.440L13.320 20.760Q13.320 20.520 13.380 20.120Q13.440 19.720 13.440 19.520L13.440 19.520Q13.440 19.440 13.480 19.240L13.480 19.240L13.480 19.120Q13.520 19.160 13.600 19.200L13.600 19.200ZM6.120 19.160L6.200 19.160Q6.200 19.160 6.240 19.120L6.240 19.120L6.280 19.040Q6.320 19.160 6.320 19.320L6.320 19.320L6.280 19.440Q6.240 19.480 6.100 19.460Q5.960 19.440 5.920 19.560L5.920 19.560L5.920 19.200Q5.960 19.120 6.120 19.160L6.120 19.160ZM5.560 19.600L5.560 19.120L5.600 19.120L5.600 19.600L5.560 19.600ZM11.040 19.120L11.040 19.120Q11.080 19.240 11.040 19.360L11.040 19.360L11.040 19.360Q11 19.240 11.040 19.120ZM11.880 19.680L11.880 19.680Q11.840 19.640 11.720 19.560L11.720 19.560Q11.480 19.360 11.520 19.200L11.520 19.200Q11.680 19.520 12 19.440L12 19.440L11.840 19.480Q11.880 19.520 11.960 19.580Q12.040 19.640 12.080 19.680L12.080 19.680L12.120 19.840Q12.160 19.960 12.200 20.040L12.200 20.040Q12.240 20.280 12.240 20.520L12.240 20.520L12.120 20.480L12.120 20.600Q12.080 20.760 12.080 20.840L12.080 20.840Q12.080 21.120 12.080 21.720L12.080 21.720Q12.080 22.440 12.120 22.800L12.120 22.800L12 22.800L12 22.760Q12.040 21.480 11.960 20.680L11.960 20.680L11.960 20.360Q11.920 19.920 11.880 19.680ZM13.880 20.080L13.880 19.240L13.880 19.240L13.920 19.520Q13.920 19.880 13.880 20.080L13.880 20.080L13.880 20.080ZM5.600 19.720L5.600 19.280Q5.600 19.280 5.640 19.360Q5.680 19.440 5.720 19.480L5.720 19.480L5.920 19.560L5.920 19.680L5.920 19.720Q5.880 19.960 5.680 19.880L5.680 19.880Q5.640 19.880 5.640 19.800L5.640 19.800L5.600 19.720ZM11.040 19.440L11.040 19.360L11.040 19.360L11.080 19.640Q11 19.640 11.040 19.440L11.040 19.440ZM11.840 19.480L12 19.440Q12.040 19.360 12.080 19.360L12.080 19.360L12.200 19.600L12.200 20.040Q12.160 19.960 12.120 19.840L12.120 19.840L12.080 19.680Q12.040 19.640 11.960 19.580Q11.880 19.520 11.840 19.480L11.840 19.480ZM13.120 19.680L13.120 19.640Q13.160 19.600 13.280 19.440L13.280 19.440L13.320 19.360Q13.360 19.480 13.360 19.800L13.360 19.800L13.320 20.080Q13.320 20.520 13.240 20.720L13.240 20.720L13.160 20.760Q13.040 20.840 12.960 20.820Q12.880 20.800 12.720 20.920L12.720 20.920L12.640 21L12.520 20.800Q12.440 20.600 12.400 20.200L12.400 20.200L12.400 20Q12.400 19.880 12.440 19.760L12.440 19.760L12.440 19.720Q12.600 19.720 12.700 19.740Q12.800 19.760 13.040 19.680L13.040 19.680L13.120 19.680ZM5.960 19.840L5.920 19.560Q5.960 19.440 6.100 19.460Q6.240 19.480 6.280 19.440L6.280 19.440L6.280 19.720Q6.240 19.760 6.100 19.760Q5.960 19.760 5.960 19.840L5.960 19.840ZM6.280 19.960L6.320 19.960Q6.320 19.880 6.340 19.700Q6.360 19.520 6.480 19.440L6.480 19.440L6.480 19.480Q6.520 19.720 6.520 19.800L6.520 19.800L6.480 19.840Q6.400 19.880 6.400 19.920L6.400 19.920L6.360 20.160Q6.360 20.440 6.280 20.600L6.280 20.600L6 20.840L5.960 20.120L6.080 20.080Q6.280 20.040 6.280 19.960L6.280 19.960ZM12.200 20.040L12.200 19.600Q12.240 19.680 12.320 19.680Q12.400 19.680 12.440 19.600L12.440 19.600L12.440 19.720Q12.400 19.880 12.400 20L12.400 20L12.360 20.240Q12.320 20.520 12.280 20.640L12.280 20.640L12.240 20.520Q12.240 20.280 12.200 20.040L12.200 20.040ZM11.080 19.960L11.080 19.640L11.120 19.640L11.080 19.960L11.080 19.960ZM5.920 19.720L5.920 19.680Q5.920 19.760 5.960 19.840L5.960 19.840L5.960 20.200L5.640 20.240L5.600 20.080Q5.560 19.920 5.600 19.720L5.600 19.720L5.640 19.800Q5.640 19.880 5.680 19.880L5.680 19.880Q5.880 19.960 5.920 19.720L5.920 19.720ZM5.080 20.520L5 20.120Q5.040 20.040 5.200 19.880L5.200 19.880L5.280 19.800Q5.480 20.120 5.560 20.400L5.560 20.400L5.640 20.600Q5.760 20.880 5.800 21.040L5.800 21.040Q5.680 21.080 5.700 21.280Q5.720 21.480 5.680 21.520L5.680 21.520L5.600 21.560Q5.320 21.720 5.320 21.840L5.320 21.840L5.320 21.840Q5.320 21.400 5.080 20.520L5.080 20.520ZM6.360 20.160L6.400 19.920Q6.400 19.880 6.480 19.840L6.480 19.840L6.520 19.800Q6.560 20.080 6.600 20.600L6.600 20.600L6.600 20.760Q6.600 21 6.500 21.060Q6.400 21.120 6.320 21.360L6.320 21.360L6.320 21.360Q6.280 21.440 6.240 21.640L6.240 21.640L6.240 21.680L6.160 21.800L6.080 22.280L6.040 22.320Q6 22.120 6 21.960L6 21.960L6 21.760Q6.040 21.600 6 21.300Q5.960 21 6 20.840L6 20.840L6.280 20.600Q6.360 20.440 6.360 20.160L6.360 20.160ZM11.040 19.960L11.080 19.960L11.080 19.960L11.080 21.040L11.080 21.040L11.040 19.960ZM12.320 20.680L12.280 20.640Q12.320 20.520 12.360 20.240L12.360 20.240L12.400 20L12.400 20.200Q12.440 20.600 12.480 20.800Q12.520 21 12.640 21.120L12.640 21.120Q12.720 21.120 12.920 21.080Q13.120 21.040 13.240 21.080L13.240 21.080L13.320 20.800L13.320 21L13.240 21.560Q13.160 21.520 12.980 21.600Q12.800 21.680 12.720 21.640L12.720 21.640L12.560 21.280Q12.520 21.240 12.440 21.200L12.440 21.200L12.320 21.120L12.320 20.960Q12.360 20.800 12.320 20.680L12.320 20.680ZM13.880 20.240L13.880 20.080L13.880 20.080Q13.920 20.120 13.920 20.240L13.920 20.240L13.880 20.320L13.880 20.240ZM5.560 20.400L5.600 20.080Q5.600 20.160 5.640 20.240L5.640 20.240L5.600 20.520L5.560 20.400ZM5.600 20.520L5.640 20.240Q5.680 20.240 5.840 20.240L5.840 20.240L5.960 20.200L6 20.840Q5.960 21 6 21.300Q6.040 21.600 6 21.760L6 21.760L5.880 21.720Q5.920 21.560 5.840 21.240L5.840 21.240L5.800 21.040Q5.760 20.880 5.640 20.600L5.640 20.600L5.600 20.520ZM13.320 20.800L13.400 20.440Q13.480 20.440 13.620 20.300Q13.760 20.160 13.880 20.240L13.880 20.240L13.880 20.320Q13.840 20.520 13.880 20.720L13.880 20.720L13.880 20.880L13.840 20.720L13.720 20.760Q13.520 20.840 13.420 20.900Q13.320 20.960 13.320 21.120L13.320 21.120L13.320 20.800ZM13.880 20.760L13.880 20.280L13.920 20.280L13.920 20.760L13.880 20.760ZM13.880 20.320L13.880 20.720Q13.840 20.520 13.880 20.320L13.880 20.320ZM7.560 20.440L7.560 20.400L7.960 20.400L7.960 20.440L7.560 20.440ZM6.600 20.640L6.640 20.880Q7.040 20.440 7.560 20.440L7.560 20.440L8.040 20.440Q8.160 20.400 8.120 20.440L8.120 20.440Q8 20.440 7.880 20.480L7.880 20.480Q7.400 20.560 7.160 21.040L7.160 21.040Q7.120 21.080 7.080 21.200L7.080 21.200L7 21.280Q6.920 21.600 6.880 22.040L6.880 22.040L6.840 22.040Q6.800 21.840 6.680 21.640L6.680 21.640L6.560 21.600Q6.320 21.480 6.360 21.360L6.360 21.360L6.400 21.280Q6.480 21.160 6.540 21.080Q6.600 21 6.600 20.760L6.600 20.760L6.600 20.640L6.600 20.640ZM7.880 20.480L7.880 20.480Q8 20.440 8.120 20.440L8.120 20.440Q8.120 20.520 8.040 20.520Q7.960 20.520 7.880 20.480ZM12.120 20.640L12.120 20.480Q12.200 20.520 12.240 20.520L12.240 20.520L12.320 20.680L12.320 20.880Q12.280 21.080 12.320 21.160Q12.360 21.240 12.360 21.360L12.360 21.360L12.400 21.920L12.400 22.200Q12.440 22.520 12.480 22.640L12.480 22.640Q12.360 22.640 12.360 22.740Q12.360 22.840 12.320 22.840L12.320 22.840L12.120 22.800Q12.080 22.440 12.080 21.720L12.080 21.720Q12.080 21.120 12.080 20.840L12.080 20.840Q12.080 20.760 12.120 20.640L12.120 20.640ZM12.320 20.880L12.320 20.680Q12.360 20.800 12.320 20.960L12.320 20.960L12.320 21.160Q12.280 21.080 12.320 20.880L12.320 20.880ZM13.320 21.120L13.320 21.120Q13.320 20.960 13.420 20.900Q13.520 20.840 13.720 20.760L13.720 20.760L13.840 20.720L13.880 20.880L13.880 21.040L13.720 21.160Q13.480 21.280 13.400 21.400L13.400 21.400Q13.320 21.760 13.320 22.520L13.320 22.520L13.320 22.640L13.280 22.680L13.280 22.520Q13.280 21.600 13.320 21.120ZM13.880 21.040L13.880 20.760L13.920 20.720L13.920 21.080L13.880 21.040ZM10.760 21.480L10.760 21.040Q10.880 21.080 10.840 21.120L10.840 21.120Q10.800 21.280 10.800 21.440L10.800 21.440L10.800 21.480L10.760 21.480ZM11.080 21.480L11.080 21.040L11.080 21.040L11.080 21.480ZM13.240 21.560L13.240 21.560Q13.280 21.520 13.280 21.400L13.280 21.400L13.320 21L13.320 21.120Q13.280 21.600 13.280 22.520L13.280 22.520L13.280 22.680L12.760 22.680L12.720 22.320Q12.680 21.800 12.560 21.560L12.560 21.560Q12.400 21.520 12.360 21.360L12.360 21.360L12.360 21.360Q12.360 21.240 12.320 21.160L12.320 21.160L12.320 21.120L12.440 21.200Q12.520 21.240 12.560 21.280L12.560 21.280L12.720 21.640Q12.800 21.680 12.980 21.600Q13.160 21.520 13.240 21.560ZM5.600 21.560L5.680 21.520Q5.720 21.480 5.700 21.280Q5.680 21.080 5.800 21.040L5.800 21.040L5.840 21.240Q5.920 21.560 5.880 21.720L5.880 21.720Q5.760 21.680 5.680 21.720Q5.600 21.760 5.600 21.880L5.600 21.880Q5.600 22.080 5.840 22.120L5.840 22.120L5.720 22.160Q5.840 22.240 5.880 22.320L5.880 22.320L5.880 22.440Q5.880 22.640 5.840 22.720L5.840 22.720L5.400 22.720L5.400 22.600L5.320 21.840Q5.320 21.680 5.600 21.560L5.600 21.560ZM6.360 21.360L6.320 21.360Q6.320 21.360 6.320 21.360L6.320 21.360Q6.400 21.120 6.520 21.040L6.520 21.040Q6.480 21.160 6.400 21.280L6.400 21.280L6.360 21.360ZM13.400 21.400L13.400 21.400Q13.480 21.280 13.720 21.160L13.720 21.160L13.880 21.040L13.880 21.120Q13.880 21.320 13.920 21.440L13.920 21.440L13.920 21.600L13.880 21.560L13.800 21.680Q13.600 21.880 13.560 22.040L13.560 22.040Q13.560 22.120 13.480 22.120L13.480 22.120L13.400 22.160Q13.400 22.320 13.320 22.560L13.320 22.560L13.320 22.520Q13.320 21.760 13.400 21.400ZM13.880 21.120L13.880 21.040L13.920 21.080L13.920 21.440Q13.880 21.320 13.880 21.120L13.880 21.120ZM10.800 21.440L10.800 21.440Q10.800 21.280 10.840 21.120L10.840 21.120Q10.880 21.400 11 21.720L11 21.720Q11.040 21.760 11.020 21.660Q11 21.560 11.040 21.600L11.040 21.600L11.080 21.640Q11.080 21.760 11.040 21.800L11.040 21.800L11.240 22.600Q11.240 22.600 11.280 22.640L11.280 22.640L11.360 22.640Q11.240 22.640 11.280 22.800L11.280 22.800L11.360 23L11.160 23Q10.920 23 10.840 22.920L10.840 22.920L10.840 22.360Q10.840 21.760 10.800 21.440ZM13.920 21.560L13.920 21.280Q14 21.280 13.960 21.440L13.960 21.440L13.960 21.560L13.920 21.560ZM6.320 21.360L6.320 21.360L6.360 21.360Q6.320 21.480 6.560 21.600L6.560 21.600L6.680 21.640Q6.800 21.840 6.840 22.040L6.840 22.040L6.800 22.520Q6.640 22.520 6.580 22.580Q6.520 22.640 6.520 22.840L6.520 22.840L6.520 22.920L6.440 23.160Q6.280 23.200 6.080 23.200L6.080 23.200L6.040 22.720L6.160 22.840L6.440 22.760Q6.520 22.520 6.560 22.240L6.560 22.240L6.400 22.240Q6.160 22.200 6.080 22.280L6.080 22.280L6.160 21.800Q6.040 22 6.240 22.080Q6.440 22.160 6.520 22.020Q6.600 21.880 6.480 21.760Q6.360 21.640 6.240 21.720L6.240 21.720L6.240 21.640Q6.280 21.440 6.320 21.360ZM12.400 21.920L12.360 21.360Q12.400 21.520 12.560 21.560L12.560 21.560Q12.680 21.800 12.720 22.320L12.720 22.320L12.760 22.680L12.720 22.680L12.600 22.200Q12.520 22.240 12.480 22.080Q12.440 21.920 12.400 21.920L12.400 21.920ZM10.800 22.960L10.800 21.440Q10.840 21.760 10.840 22.360L10.840 22.360L10.840 22.920L10.800 22.960ZM13.800 21.680L13.880 21.560L13.920 21.600L13.920 21.640Q13.920 21.840 13.960 21.920L13.960 21.920L13.960 22Q14 22.120 14 22.200L14 22.200L14.040 22.640L13.320 22.640L13.360 22.560Q13.400 22.320 13.400 22.120L13.400 22.120L13.480 22.120Q13.560 22.120 13.560 22.040L13.560 22.040Q13.600 21.880 13.800 21.680L13.800 21.680ZM13.920 21.680L13.920 21.560L13.960 21.560L13.960 21.600Q13.960 21.840 13.960 21.920L13.960 21.920Q13.920 21.840 13.920 21.680L13.920 21.680ZM6.160 21.800L6.240 21.680Q6.360 21.640 6.480 21.760Q6.600 21.880 6.520 22.020Q6.440 22.160 6.240 22.080Q6.040 22 6.160 21.800L6.160 21.800ZM5.600 21.880L5.600 21.880Q5.600 21.760 5.680 21.720Q5.760 21.680 5.880 21.720L5.880 21.720L6 21.800L6 21.960Q5.960 22.040 5.840 22.120L5.840 22.120Q5.600 22.080 5.600 21.880ZM14.080 22.880L14.360 22.360Q14.400 22.320 14.480 22.160L14.480 22.160Q14.640 21.840 14.760 21.680L14.760 21.680Q14.720 21.880 14.600 22.280L14.600 22.280L14.400 22.760Q14.360 22.920 14.320 22.960L14.320 22.960L14.040 22.960Q14.040 22.920 14.080 22.880L14.080 22.880ZM12.400 22.200L12.360 21.920Q12.440 21.920 12.480 22.080Q12.520 22.240 12.600 22.200L12.600 22.200L12.720 22.680L12.480 22.640Q12.440 22.520 12.400 22.200L12.400 22.200ZM5.720 22.160L5.840 22.120Q5.960 22.040 6 21.960L6 21.960Q6 22.160 6.040 22.320L6.040 22.320L6.040 22.720Q6 22.960 6.040 23.320L6.040 23.320L5.920 23.200Q5.880 23.040 5.900 22.760Q5.920 22.480 5.880 22.360Q5.840 22.240 5.720 22.160L5.720 22.160ZM9.760 22L9.760 22Q9.800 22.040 9.920 22.200L9.920 22.200L10.240 22.600Q10.080 22.680 9.960 22.440L9.960 22.440L9.840 22.240Q9.760 22.120 9.760 22ZM15.360 22.240L15.440 22.160L15.480 22.160Q15.360 22.400 15.240 22.640L15.240 22.640L15 22.640Q15.080 22.520 15.360 22.240L15.360 22.240ZM10 22.320L10.040 22.320Q10.160 22.360 10.420 22.280Q10.680 22.200 10.800 22.200L10.800 22.200L10.800 22.280Q10.600 22.280 10.440 22.360L10.440 22.360L10.440 22.360Q10.280 22.480 10.320 22.600L10.320 22.600Q10.480 22.720 10.800 22.800L10.800 22.800L10.800 22.880Q10.160 22.760 9.800 22.600L9.800 22.600Q9.800 22.400 9.880 22.360L9.880 22.360L9.960 22.440Q10.080 22.680 10.240 22.600L10.240 22.600L10 22.320ZM14.040 22.680L14 22.200Q14.040 22.200 14.040 22.260Q14.040 22.320 14.080 22.320L14.080 22.320L14.360 22.400L14.160 22.720Q14.160 22.640 14.040 22.680L14.040 22.680L14.040 22.680ZM6.040 22.320L6.080 22.280Q6.160 22.200 6.400 22.240L6.400 22.240L6.560 22.240Q6.520 22.520 6.440 22.760L6.440 22.760L6.160 22.840L6.040 22.720L6.040 22.320ZM6.800 22.600L6.800 22.520Q6.800 22.360 6.840 22.240L6.840 22.240L6.840 22.320Q6.840 22.520 6.840 22.600L6.840 22.600L6.800 22.600ZM10.440 22.360L10.440 22.360Q10.600 22.280 10.800 22.280L10.800 22.280L10.800 22.320Q10.600 22.360 10.600 22.520Q10.600 22.680 10.800 22.720L10.800 22.720L10.800 22.800Q10.480 22.720 10.320 22.600L10.320 22.600Q10.280 22.480 10.440 22.360L10.440 22.360ZM5.880 22.440L5.880 22.320Q5.920 22.480 5.900 22.760Q5.880 23.040 5.920 23.200L5.920 23.200L5.960 23.680Q5.840 23.680 5.720 23.680L5.720 23.680L5.480 23.640L5.400 23.360L5.400 22.720L5.840 22.720Q5.880 22.640 5.880 22.440L5.880 22.440ZM10.560 22.520L10.560 22.520Q10.600 22.360 10.800 22.320L10.800 22.320L10.800 22.720Q10.600 22.680 10.560 22.520ZM5.040 22.560L5.040 22.440Q5.080 22.440 5.120 22.560L5.120 22.560L5.080 22.720Q5 22.760 5.040 22.560L5.040 22.560ZM6.560 22.560L6.560 22.560Q6.640 22.520 6.800 22.520L6.800 22.520L6.800 22.800Q6.600 22.800 6.520 22.920L6.520 22.920L6.520 22.840Q6.520 22.640 6.560 22.560ZM5.200 23.880L5.080 22.720Q5.080 22.640 5.120 22.600L5.120 22.600L5.560 23.840L5.400 23.880L5.200 23.880ZM6.800 22.840L6.800 22.600L6.840 22.600Q6.840 22.720 6.840 22.840L6.840 22.840L6.800 22.840ZM5.400 22.600L5.400 22.600L5.400 22.720L5.400 23.040L5.360 23.040Q5.360 22.840 5.400 22.600ZM11.720 22.840L11.280 22.800Q11.240 22.640 11.360 22.640L11.360 22.640L11.400 22.720Q11.760 22.800 12.120 22.800L12.120 22.800L12.320 22.840L12.320 22.880Q12.080 22.880 11.720 22.840L11.720 22.840ZM11.400 22.720L11.360 22.640Q11.440 22.680 11.520 22.680L11.520 22.680L12 22.760L12 22.800Q11.680 22.800 11.400 22.720L11.400 22.720ZM12.560 22.720L12.360 22.760Q12.360 22.640 12.480 22.640L12.480 22.640L12.760 22.680Q12.720 22.720 12.560 22.720L12.560 22.720ZM12.760 22.680L12.760 22.680Q12.920 22.680 13.040 22.680L13.040 22.680Q12.760 22.800 12.400 22.760L12.400 22.760L12.560 22.720Q12.720 22.720 12.760 22.680ZM13.040 22.680L13.040 22.680Q13.160 22.680 13.280 22.680L13.280 22.680Q13.200 22.720 13 22.760L13 22.760L12.800 22.800L12.440 22.800L12.400 22.880L12.320 22.880L12.320 22.840Q12.360 22.840 12.360 22.760L12.360 22.760L12.400 22.760Q12.800 22.800 13.040 22.680ZM13.280 22.680L13.280 22.680L13.280 22.680L14.040 22.640L14.040 22.680L13.920 22.720L13.640 22.720Q13.520 22.680 13.240 22.740Q12.960 22.800 12.840 22.800L12.840 22.800L12.800 22.800L13 22.760Q13.200 22.720 13.280 22.680ZM13.920 22.720L14.040 22.680Q14.040 22.680 14.040 22.680L14.040 22.680Q14.160 22.640 14.160 22.720L14.160 22.720L14.080 22.880L14.080 22.800Q12.720 23 11.320 22.920L11.320 22.920L11.280 22.800L11.720 22.840Q12.080 22.880 12.320 22.880L12.320 22.880L12.400 22.880Q12.880 22.880 13.160 22.840L13.160 22.840Q13.560 22.880 13.920 22.720L13.920 22.720ZM7.280 23.760L7.640 22.720L7.680 22.680Q7.680 22.920 7.560 23.360L7.560 23.360L7.480 23.760L7.280 23.760ZM12.840 22.800L12.840 22.800Q12.960 22.800 13.240 22.740Q13.520 22.680 13.680 22.720L13.680 22.720Q13.520 22.760 13.240 22.800L13.240 22.800L13.160 22.840Q12.760 22.880 12.400 22.880L12.400 22.880L12.400 22.840L12.560 22.840Q12.760 22.840 12.840 22.800ZM13.640 22.720L13.680 22.720L13.920 22.720Q13.560 22.880 13.160 22.840L13.160 22.840L13.240 22.800Q13.520 22.760 13.640 22.720L13.640 22.720ZM6.040 23.560L6.040 23.320Q6 23 6.040 22.720L6.040 22.720L6.080 23.200Q6.280 23.200 6.440 23.160L6.440 23.160L6.520 22.920L6.560 23.440L6.040 23.560ZM6.560 23.360L6.520 22.920Q6.600 22.800 6.800 22.800L6.800 22.800L6.800 22.920Q6.800 23.120 6.840 23.200L6.840 23.200L6.840 23.320L6.800 23.320Q6.720 23.240 6.640 23.280L6.640 23.280L6.560 23.360ZM12.400 22.840L12.440 22.800L12.800 22.800L12.840 22.800Q12.760 22.840 12.560 22.840L12.560 22.840L12.400 22.840ZM6.800 22.920L6.800 22.840L6.840 22.840Q6.840 23 6.840 23.200L6.840 23.200Q6.800 23.120 6.800 22.920L6.800 22.920ZM8.120 23.120L8.120 23.120L8.160 23.120L8.080 23.480L7.880 23.480Q7.960 23.360 8.120 23.120ZM4.400 23.160L4.400 23.160Q4.480 23.200 4.600 23.320L4.600 23.320L4.680 23.440Q4.920 23.640 4.720 23.640L4.720 23.640Q4.640 23.600 4.560 23.440L4.560 23.440L4.480 23.320Q4.440 23.200 4.400 23.160ZM5.960 23.680L5.920 23.200Q6 23.240 6.040 23.320L6.040 23.320L6.040 23.720L5.960 23.720L5.960 23.680ZM6.840 23.520L6.840 23.200Q6.880 23.160 6.880 23.280L6.880 23.280L6.840 23.520ZM5.120 23.360L5.160 23.240Q5.160 23.520 5.200 23.760L5.200 23.760Q5.080 23.760 5.020 23.680Q4.960 23.600 5 23.520L5 23.520L5.040 23.480Q5.120 23.440 5.120 23.360L5.120 23.360ZM6.600 23.760L6.560 23.360Q6.560 23.360 6.600 23.320L6.600 23.320L6.640 23.280Q6.720 23.240 6.800 23.320L6.800 23.320L6.920 23.680Q6.840 23.720 6.640 23.760L6.640 23.760L6.600 23.760ZM4.680 23.440L4.680 23.440Q4.760 23.440 4.920 23.400L4.920 23.400L5.120 23.360Q5.120 23.440 5.040 23.480L5.040 23.480L5 23.520Q4.960 23.600 5.020 23.680Q5.080 23.760 5.200 23.760L5.200 23.760L5.200 23.840L5.120 23.800Q4.840 23.760 4.720 23.640L4.720 23.640Q4.920 23.640 4.680 23.440ZM6.880 23.440L6.880 23.360Q6.920 23.400 7.040 23.400L7.040 23.400Q7.280 23.440 7.360 23.480L7.360 23.480L7.280 23.760Q6.760 23.880 6.200 23.840L6.200 23.840L6.240 23.840Q6.480 23.800 6.600 23.800L6.600 23.800L6.720 23.800Q7 23.760 7.080 23.640Q7.160 23.520 6.880 23.440L6.880 23.440L6.880 23.440ZM4.320 23.520L4.360 23.520Q4.400 23.480 4.520 23.400L4.520 23.400L4.520 23.400L4.560 23.440Q4.640 23.600 4.740 23.680Q4.840 23.760 5.120 23.800L5.120 23.800L5.200 23.840L5.200 23.880Q5.040 23.880 4.760 23.800L4.760 23.800L4.560 23.760Q4.360 23.760 4.240 23.600L4.240 23.600Q4.200 23.560 4.320 23.520L4.320 23.520ZM6.040 23.880L6.040 23.560Q6.160 23.520 6.400 23.480L6.400 23.480L6.560 23.440L6.600 23.800Q6.480 23.800 6.240 23.840L6.240 23.840L6.040 23.880ZM6.840 23.520L6.880 23.440Q6.880 23.440 6.880 23.440L6.880 23.440Q7.160 23.520 7.080 23.640Q7 23.760 6.720 23.800L6.720 23.800L6.600 23.800L6.600 23.760L6.600 23.760Q6.800 23.720 6.920 23.680L6.920 23.680L6.840 23.520ZM5.520 23.720L5.480 23.640Q5.600 23.680 5.720 23.720Q5.840 23.760 5.960 23.720L5.960 23.720L6.040 23.720L6.040 23.760L5.520 23.720ZM5.720 23.680L5.720 23.680Q5.840 23.680 5.960 23.680L5.960 23.680L5.960 23.720Q5.840 23.760 5.720 23.680ZM5.560 23.800L5.520 23.720Q5.560 23.720 5.600 23.720L5.600 23.720L6.040 23.760L6.040 23.800L5.840 23.800Q5.640 23.760 5.560 23.800L5.560 23.800ZM5.560 23.840L5.560 23.800Q5.640 23.760 5.840 23.800L5.840 23.800L6.040 23.800L6.040 23.840L5.560 23.840ZM5.400 23.880L5.560 23.840Q5.680 23.840 5.960 23.840L5.960 23.840L6.040 23.840L6.040 23.880L6 23.880Q5.600 23.880 5.400 23.920L5.400 23.920L5.400 23.880Z"/>', + 'seti:typescript': + '<path d="M11.376 6.833L11.532 6.833L7.359 6.833L7.359 19.235L4.317 19.235L4.317 6.833L0.183 6.833L0.183 4.610L11.376 4.610L11.376 6.833ZM20.892 15.491L20.892 15.491Q20.892 15.062 20.736 14.750Q20.580 14.438 20.307 14.126L20.307 14.126Q20.073 13.931 19.605 13.697L19.605 13.697Q19.293 13.580 18.513 13.268L18.513 13.268L18.201 13.151Q15.666 12.410 14.184 11.318L14.184 11.318Q12.858 10.187 12.858 8.510L12.858 8.510Q12.858 6.677 14.457 5.585L14.457 5.585Q15.900 4.492 18.299 4.492Q20.697 4.492 22.257 5.858L22.257 5.858Q23.700 7.145 23.700 9.017L23.700 9.017L20.892 9.017Q20.892 8.471 20.716 8.081Q20.541 7.691 20.151 7.301L20.151 7.301Q19.371 6.716 18.201 6.716Q17.031 6.716 16.407 7.184Q15.783 7.652 15.783 8.510L15.783 8.510Q15.783 9.212 16.524 9.758L16.524 9.758Q16.836 9.992 17.460 10.226L17.460 10.226Q17.928 10.421 18.942 10.733L18.942 10.733Q21.321 11.434 22.569 12.507Q23.817 13.580 23.817 15.491L23.817 15.491Q23.817 16.427 23.447 17.187Q23.076 17.948 22.374 18.416L22.374 18.416Q20.892 19.508 18.474 19.508L18.474 19.508Q15.900 19.508 14.301 18.260L14.301 18.260Q12.468 16.817 12.624 14.750L12.624 14.750L15.549 14.750Q15.549 15.998 16.407 16.700L16.407 16.700Q16.758 16.973 17.343 17.129Q17.928 17.285 18.591 17.285L18.591 17.285Q19.917 17.285 20.424 16.817L20.424 16.817Q20.892 16.076 20.892 15.491Z"/>', + 'seti:tsconfig': + '<path d="M1.668 0.198L1.668 0.198L22.332 0.198Q22.962 0.198 23.382 0.618Q23.802 1.038 23.802 1.668L23.802 1.668L23.802 22.332Q23.802 22.962 23.382 23.382Q22.962 23.802 22.332 23.802L22.332 23.802L1.668 23.802Q1.038 23.802 0.618 23.382Q0.198 22.962 0.198 22.332L0.198 22.332L0.198 1.668Q0.198 1.038 0.618 0.618Q1.038 0.198 1.668 0.198ZM10.572 12.546L13.470 12.546L13.470 10.530L5.364 10.530L5.364 12.546L8.262 12.546L8.262 21.576L10.572 21.576L10.572 12.546ZM14.268 19.140L14.268 21.702Q14.898 22.038 15.675 22.185Q16.452 22.332 17.313 22.332Q18.174 22.332 18.951 22.164Q19.728 21.996 20.337 21.576Q20.946 21.156 21.282 20.526Q21.618 19.896 21.618 18.930L21.618 18.930Q21.618 18.216 21.408 17.712Q21.198 17.208 20.820 16.788Q20.442 16.368 19.917 16.032Q19.392 15.696 18.804 15.444L18.804 15.444Q18.342 15.234 17.985 15.045Q17.628 14.856 17.355 14.667Q17.082 14.478 16.914 14.226Q16.746 13.974 16.746 13.701Q16.746 13.428 16.893 13.218Q17.040 13.008 17.271 12.861Q17.502 12.714 17.838 12.630Q18.174 12.546 18.594 12.546L18.594 12.546Q19.602 12.546 20.526 13.008L20.526 13.008Q20.862 13.134 21.114 13.344L21.114 13.344L21.114 10.950Q20.526 10.740 19.938 10.614L19.938 10.614Q19.182 10.530 18.426 10.530L18.426 10.530Q17.586 10.530 16.809 10.719Q16.032 10.908 15.465 11.328Q14.898 11.748 14.562 12.378Q14.226 13.008 14.226 13.932L14.226 13.932Q14.226 15.066 14.835 15.864Q15.444 16.662 16.704 17.208L16.704 17.208L17.628 17.628Q18.048 17.838 18.363 18.069Q18.678 18.300 18.867 18.573Q19.056 18.846 19.056 19.140L19.056 19.140Q19.056 19.686 18.594 19.980L18.594 19.980Q18.384 20.148 18.006 20.232Q17.628 20.316 17.208 20.316L17.208 20.316Q16.410 20.316 15.654 20.022Q14.898 19.728 14.268 19.140L14.268 19.140Z"/>', + 'seti:vala': + '<path d="M13.452 8.241L13.490 8.241Q15.010 8.241 16.454 8.583L16.454 8.583L17.024 8.849Q18.050 9.343 18.278 10.255L18.278 10.255Q18.506 11.053 18.088 11.927L18.088 11.927Q17.974 12.307 17.670 12.725L17.670 12.725Q17.480 12.953 17.024 13.333L17.024 13.333L16.796 13.599Q16.112 14.169 14.592 15.157L14.592 15.157L13.718 15.727Q13.414 15.917 12.806 16.297L12.806 16.297Q11.704 17.019 11.210 17.513L11.210 17.513Q11.096 17.627 10.925 17.855Q10.754 18.083 10.602 18.197L10.602 18.197Q10.450 18.463 10.431 18.786Q10.412 19.109 10.488 19.413L10.488 19.413Q10.754 19.945 11.267 20.363Q11.780 20.781 12.445 20.952Q13.110 21.123 13.604 20.743Q14.098 20.363 14.174 19.641L14.174 19.641L14.174 19.147Q14.174 18.691 14.554 18.349L14.554 18.349Q15.162 17.893 15.846 17.741L15.846 17.741Q17.100 17.475 17.746 17.627L17.746 17.627Q17.974 17.627 18.088 17.741L18.088 17.741Q18.544 17.931 18.658 18.197Q18.772 18.463 18.696 18.919L18.696 18.919Q18.202 20.895 16.568 22.377L16.568 22.377Q15.124 23.631 13.338 23.783L13.338 23.783Q11.932 23.973 10.488 23.441L10.488 23.441Q5.814 21.655 4.218 16.791L4.218 16.791Q3.686 15.005 4.180 13.447Q4.674 11.889 6.118 10.749L6.118 10.749Q7.752 9.229 10.754 8.583L10.754 8.583Q11.704 8.355 12.160 8.355L12.160 8.355Q12.768 8.241 13.452 8.241L13.452 8.241ZM15.010 4.783L15.010 4.783Q15.200 1.933 17.518 0.641L17.518 0.641Q18.924-0.081 20.368 0.299L20.368 0.299Q21.166 0.451 21.470 0.907Q21.774 1.363 21.641 2.199Q21.508 3.035 20.824 3.966Q20.140 4.897 19.722 5.353L19.722 5.353Q19.038 6.075 18.354 6.455L18.354 6.455Q17.594 7.025 16.796 7.177L16.796 7.177Q16.226 7.253 15.827 7.063Q15.428 6.873 15.238 6.341L15.238 6.341Q15.010 5.619 15.010 4.783ZM13.338 2.769L13.338 2.769Q13.338 4.479 12.502 5.619L12.502 5.619Q12.350 5.961 12.046 6.113L12.046 6.113Q11.780 6.379 11.457 6.379Q11.134 6.379 10.868 6.113L10.868 6.113Q10.488 5.733 10.260 5.049L10.260 5.049Q9.842 3.605 10.146 2.427L10.146 2.427Q10.526 1.097 11.932 1.097L11.932 1.097Q12.388 1.097 12.711 1.287Q13.034 1.477 13.110 1.819L13.110 1.819Q13.224 1.933 13.224 2.199L13.224 2.199Q13.224 2.541 13.338 2.769ZM8.474 4.897L8.474 5.277Q8.474 5.847 8.436 6.151L8.436 6.151Q8.360 6.607 8.132 6.949L8.132 6.949Q7.942 7.405 7.600 7.462Q7.258 7.519 6.840 7.177L6.840 7.177Q5.814 6.341 5.624 5.049L5.624 5.049L5.624 4.213Q5.738 3.643 6.137 3.263Q6.536 2.883 7.068 2.883L7.068 2.883Q7.676 2.883 8.018 3.377L8.018 3.377Q8.474 4.023 8.474 4.897L8.474 4.897ZM5.168 8.735L5.168 8.697Q5.168 9.077 4.940 9.533L4.940 9.533Q4.750 10.065 4.218 9.913L4.218 9.913L4.104 9.875L3.990 9.799Q3.268 9.533 2.793 8.716Q2.318 7.899 2.318 7.177L2.318 7.177Q2.318 6.759 2.584 6.417Q2.850 6.075 3.268 5.847L3.268 5.847Q3.800 5.695 4.332 6.227L4.332 6.227Q4.636 6.531 4.788 7.025L4.788 7.025Q4.902 7.291 5.016 7.899L5.016 7.899L5.054 8.013Q5.168 8.355 5.168 8.735L5.168 8.735Z"/>', + 'seti:vite': + '<path d="M16.232 0.179L16.232 0.179L6.392 2.139Q6.152 2.179 6.112 2.459L6.112 2.459L5.512 12.659Q5.512 12.859 5.652 12.979Q5.792 13.099 5.952 13.059L5.952 13.059L8.672 12.419Q8.872 12.379 9.012 12.519Q9.152 12.659 9.112 12.819L9.112 12.819L8.312 16.819Q8.272 17.019 8.432 17.159Q8.592 17.299 8.752 17.219L8.752 17.219L10.472 16.699Q10.672 16.659 10.812 16.799Q10.952 16.939 10.912 17.139L10.912 17.139L9.632 23.379Q9.552 23.699 9.832 23.799Q10.112 23.899 10.272 23.659L10.272 23.659L10.432 23.419L18.432 7.459Q18.552 7.259 18.412 7.079Q18.272 6.899 18.032 6.939L18.032 6.939L15.232 7.459Q15.032 7.499 14.892 7.359Q14.752 7.219 14.832 7.019L14.832 7.019L16.672 0.659Q16.712 0.459 16.572 0.299Q16.432 0.139 16.232 0.179Z"/>', + 'seti:vue': + '<path d="M6.117 1.659L12.000 11.870L17.883 1.659L14.775 1.659L12.000 6.469L9.225 1.659L6.117 1.659ZM23.951 1.659L19.178 1.659L12.000 14.090L4.822 1.659L0.049 1.659L12.000 22.341L23.951 1.659Z"/>', + 'seti:wasm': + '<path d="M9.396 0.198L0.198 0.198L0.198 23.802L23.802 23.802L23.802 0.198L14.646 0.198Q14.646 1.164 13.806 1.983Q12.966 2.802 12 2.802Q11.034 2.802 10.215 1.983Q9.396 1.164 9.396 0.198L9.396 0.198ZM8.976 21.198L7.002 13.302L8.598 13.302L9.774 17.838L10.950 13.302L12.126 13.302L13.302 17.838L14.478 13.302L16.074 13.302L14.100 21.198L12.714 21.198L11.538 16.074L11.328 17.166Q10.782 19.770 10.362 21.198L10.362 21.198L8.976 21.198ZM15.486 21.198L17.460 13.302L19.812 13.302L21.786 21.198L20.022 21.198L19.602 19.224L17.628 19.224L17.250 21.198L15.486 21.198ZM19.434 17.838L18.846 14.898L18.426 14.898L17.838 17.838L19.434 17.838Z"/>', + 'seti:wat': + '<path d="M11.702 18.563L9.532 18.563L7.327 9.813L5.157 18.563L2.952 18.563L0.222 5.438L2.532 5.438L4.072 13.102L6.242 5.438L8.447 5.438L10.617 13.102L12.158 5.438L14.467 5.438L11.702 18.563ZM23.778 18.563L21.013 5.438L16.638 5.438L13.943 18.563L16.638 18.563L17.197 15.308L20.453 15.308L21.013 18.563L23.778 18.563ZM20.208 13.102L17.443 13.102L18.282 8.203L19.367 8.203L20.208 13.102Z"/>', + 'seti:xml': + '<path d="M0.372 0.202L0.372 0.202Q6.803 0.084 12.408 3.506L12.408 3.506Q17.718 6.751 20.845 12.208Q23.972 17.666 23.795 23.625L23.795 23.625L19.016 23.625Q18.839 19.731 17.541 16.486Q16.243 13.241 13.677 10.527Q11.110 7.813 7.688 6.456L7.688 6.456Q4.384 5.158 0.549 5.158L0.549 5.158Q0.372 3.506 0.372 0.202ZM16.243 23.802L16.243 23.802L11.464 23.802L10.874 20.852Q9.753 17.489 7.600 15.542Q5.446 13.595 2.024 12.946L2.024 12.946Q1.670 12.710 0.726 12.710L0.726 12.710Q0.490 12.710 0.431 12.621Q0.372 12.533 0.372 12.356L0.372 12.356L0.372 7.754Q5.977 7.754 10.520 11.471L10.520 11.471Q15.948 16.368 16.243 23.802ZM6.862 20.498L6.862 20.498Q6.862 21.855 5.889 22.828Q4.915 23.802 3.529 23.802Q2.142 23.802 1.228 22.858Q0.313 21.914 0.195 20.498L0.195 20.498Q0.195 19.082 1.169 18.108Q2.142 17.135 3.529 17.135Q4.915 17.135 5.889 18.108Q6.862 19.082 6.862 20.498Z"/>', + 'seti:yml': + '<path d="M13.615 15.116L13.415 16.076Q13.095 16.076 12.575 16.156L12.575 16.156Q12.215 16.196 12.055 16.196L12.055 16.196L9.815 16.196Q10.055 13.516 10.495 8.196Q10.935 2.876 11.175 0.196L11.175 0.196L12.655 0.196Q14.375 0.116 15.175 0.196L15.175 0.196Q15.455 0.196 15.735 0.556Q16.015 0.916 15.935 1.196L15.935 1.196Q15.655 3.196 14.935 7.236L14.935 7.236L14.415 9.956Q14.215 11.636 13.615 15.116L13.615 15.116ZM13.935 21.076L13.935 21.076Q14.015 22.116 13.255 22.936Q12.495 23.756 11.295 23.836Q10.095 23.916 9.115 23.256Q8.135 22.596 8.055 21.596L8.055 21.596Q7.975 20.436 8.735 19.676Q9.495 18.916 10.815 18.836Q12.135 18.756 12.995 19.356Q13.855 19.956 13.935 21.076Z"/>', + 'seti:prolog': + '<path d="M20.167 0.198L20.167 0.198Q19.915 0.450 19.621 0.744L19.621 0.744Q18.907 1.374 18.067 1.962L18.067 1.962Q16.849 2.718 15.505 3.138L15.505 3.138Q13.783 3.684 11.977 3.684Q10.171 3.684 8.491 3.138L8.491 3.138Q7.147 2.718 5.929 1.962L5.929 1.962Q5.089 1.374 4.375 0.744L4.375 0.744L3.829 0.198L3.367 0.996Q2.821 2.004 2.359 3.054L2.359 3.054Q1.729 4.566 1.435 5.994L1.435 5.994Q1.015 7.800 1.099 9.354L1.099 9.354Q1.267 11.790 1.981 13.722L1.981 13.722Q2.863 16.116 4.753 18.258L4.753 18.258Q7.357 21.156 11.977 23.802L11.977 23.802Q16.219 21.408 18.739 18.804L18.739 18.804Q20.923 16.536 21.931 13.974L21.931 13.974Q22.729 11.916 22.897 9.354L22.897 9.354Q23.065 6.540 21.637 3.054L21.637 3.054Q20.923 1.332 20.167 0.198L20.167 0.198ZM4.249 2.676L4.249 2.676Q5.047 3.264 5.887 3.684L5.887 3.684Q4.207 4.272 3.115 5.658L3.115 5.658Q3.577 4.104 4.249 2.676ZM19.369 15.528L19.369 15.528Q18.277 17.208 16.555 18.720L16.555 18.720L16.555 17.334L15.001 17.334L15.001 20.022Q13.993 20.778 12.775 21.534L12.775 21.534L12.775 19.266L11.221 19.266L11.221 21.534Q10.087 20.820 8.995 20.022L8.995 20.022L8.995 17.334L7.441 17.334L7.441 18.720Q6.643 18.048 5.929 17.250L5.929 17.250Q4.417 15.528 3.619 13.638L3.619 13.638Q4.795 14.772 6.391 15.171Q7.987 15.570 9.541 15.066L9.541 15.066L11.977 17.544L14.455 15.066Q16.009 15.570 17.605 15.171Q19.201 14.772 20.377 13.638L20.377 13.638Q19.957 14.646 19.369 15.528ZM11.977 15.318L11.053 14.394Q11.557 14.058 11.977 13.638L11.977 13.638Q12.439 14.058 12.943 14.394L12.943 14.394L11.977 15.318ZM16.177 13.806L16.177 13.806Q14.749 13.806 13.594 12.966Q12.439 12.126 11.977 10.782L11.977 10.782Q11.473 12.336 10.087 13.155Q8.701 13.974 7.084 13.722Q5.467 13.470 4.417 12.231Q3.367 10.992 3.367 9.375Q3.367 7.758 4.417 6.519Q5.467 5.280 7.084 5.007Q8.701 4.734 10.087 5.574Q11.473 6.414 11.977 7.926L11.977 7.926Q12.523 6.330 14.014 5.511Q15.505 4.692 17.164 5.049Q18.823 5.406 19.810 6.792Q20.797 8.178 20.608 9.858Q20.419 11.538 19.159 12.672Q17.899 13.806 16.177 13.806ZM18.109 3.684L18.109 3.684Q18.949 3.264 19.747 2.676L19.747 2.676Q20.419 4.104 20.881 5.658L20.881 5.658Q19.789 4.272 18.109 3.684ZM5.593 9.354L5.593 9.354Q5.593 10.278 6.244 10.929Q6.895 11.580 7.798 11.580Q8.701 11.580 9.352 10.929Q10.003 10.278 10.003 9.354Q10.003 8.430 9.352 7.800Q8.701 7.170 7.798 7.170Q6.895 7.170 6.244 7.800Q5.593 8.430 5.593 9.354ZM13.993 9.354L13.993 9.354Q13.993 10.278 14.644 10.929Q15.295 11.580 16.198 11.580Q17.101 11.580 17.752 10.929Q18.403 10.278 18.403 9.354Q18.403 8.430 17.752 7.800Q17.101 7.170 16.198 7.170Q15.295 7.170 14.644 7.800Q13.993 8.430 13.993 9.354Z"/>', + 'seti:zig': + '<path d="M3.120 5.821L7.301 4.600L4.526 8.004L3.120 5.821ZM0.197 4.600L7.301 4.600L5.303 6.302L4.526 8.004L3.601 8.004L3.601 15.848L4.970 15.848L3.305 16.625L2.047 19.252L0.197 19.252L0.197 4.600ZM0.826 17.550L4.970 15.848L2.047 19.252L0.826 17.550ZM5.895 8.004L8.855 4.600L9.780 6.746L5.895 8.004ZM8.855 6.154L8.855 4.600L17.328 4.600L17.328 8.004L5.895 8.004L8.855 6.154ZM14.072 17.254L18.105 15.848L15.145 19.252L14.072 17.254ZM6.672 15.848L18.105 15.848L15.626 17.254L15.145 19.252L6.672 19.252L6.672 15.848ZM15.774 4.600L23.322 1.196L8.226 19.252L0.678 22.804L15.774 4.600ZM19.030 8.152L21.953 4.600L21.805 7.375L19.030 8.152ZM21.953 4.600L23.803 4.600L23.803 19.252L16.551 19.252L18.697 17.402L19.474 15.848L20.399 15.848L20.399 8.152L19.030 8.152L20.547 6.746L21.953 4.600ZM16.551 19.252L19.474 15.848L20.251 18.179L16.551 19.252Z"/>', + 'seti:zip': + '<path d="M21.348 23.894L21.348 23.894L2.652 23.894Q2.386 23.894 2.234 23.723Q2.082 23.552 2.082 23.324L2.082 23.324L2.082 0.714Q2.082 0.486 2.234 0.315Q2.386 0.144 2.652 0.144L2.652 0.144L21.348 0.144Q21.576 0.144 21.747 0.315Q21.918 0.486 21.918 0.714L21.918 0.714L21.918 23.324Q21.918 23.552 21.766 23.723Q21.614 23.894 21.348 23.894ZM11.620 14.546L11.620 0.106L12.380 0.106L12.380 14.546L11.620 14.546ZM11.810 1.778L11.810 0.980L14.128 0.980L14.128 1.778L11.810 1.778ZM11.810 3.412L11.810 2.614L14.128 2.614L14.128 3.412L11.810 3.412ZM11.810 5.084L11.810 4.286L14.128 4.286L14.128 5.084L11.810 5.084ZM11.810 6.718L11.810 5.920L14.128 5.920L14.128 6.718L11.810 6.718ZM11.810 8.390L11.810 7.592L14.128 7.592L14.128 8.390L11.810 8.390ZM11.810 10.024L11.810 9.264L14.128 9.264L14.128 10.024L11.810 10.024ZM11.810 11.696L11.810 10.898L14.128 10.898L14.128 11.696L11.810 11.696ZM11.810 13.330L11.810 12.532L14.128 12.532L14.128 13.330L11.810 13.330ZM9.796 2.538L9.796 1.740L12.152 1.740L12.152 2.538L9.796 2.538ZM9.796 4.172L9.796 3.412L12.152 3.412L12.152 4.172L9.796 4.172ZM9.796 5.844L9.796 5.046L12.152 5.046L12.152 5.844L9.796 5.844ZM9.796 7.516L9.796 6.718L12.152 6.718L12.152 7.516L9.796 7.516ZM9.796 9.150L9.796 8.352L12.152 8.352L12.152 9.150L9.796 9.150ZM9.796 10.822L9.796 10.024L12.152 10.024L12.152 10.822L9.796 10.822ZM9.796 12.456L9.796 11.658L12.152 11.658L12.152 12.456L9.796 12.456ZM9.796 0.904L9.796 0.106L12.152 0.106L12.152 0.904L9.796 0.904ZM9.796 14.090L9.796 13.330L12.152 13.330L12.152 14.090L9.796 14.090ZM14.812 19.410L14.812 19.410Q14.736 18.726 14.470 17.358L14.470 17.358L14.318 16.408L14.280 16.294Q14.090 15.914 13.558 15.724Q13.026 15.534 12.019 15.534Q11.012 15.534 10.461 15.724Q9.910 15.914 9.720 16.294L9.720 16.294L9.682 16.408L9.530 17.358Q9.264 18.726 9.188 19.410L9.188 19.410Q9.112 19.942 9.530 20.265Q9.948 20.588 10.746 20.626L10.746 20.626L13.254 20.626Q14.052 20.588 14.470 20.265Q14.888 19.942 14.812 19.410ZM12.038 18.308L12.038 18.308L11.962 18.308Q11.392 18.308 11.050 18.061Q10.708 17.814 10.689 17.377Q10.670 16.940 11.031 16.655Q11.392 16.370 11.962 16.408L11.962 16.408L11.962 16.408L12.038 16.370Q12.608 16.370 12.969 16.655Q13.330 16.940 13.311 17.377Q13.292 17.814 12.950 18.061Q12.608 18.308 12.038 18.308Z"/>', + 'seti:wgt': + '<path d="M11.751 0.458L11.751 0.458Q11.681 0.458 11.646 0.493L11.646 0.493L11.436 0.633Q9.826 1.613 9.056 2.208L9.056 2.208Q7.761 3.293 7.446 4.273L7.446 4.273Q7.341 4.588 7.341 4.833L7.341 4.833Q7.341 4.973 7.411 5.288L7.411 5.288L7.446 5.393Q7.691 6.233 8.251 7.108L8.251 7.108Q8.391 7.388 8.793 7.895Q9.196 8.403 9.231 8.403L9.231 8.403Q11.156 7.178 12.136 6.233L12.136 6.233L12.136 3.538Q12.136 1.823 12.101 1.298Q12.066 0.773 11.978 0.633Q11.891 0.493 11.751 0.458ZM7.061 5.008L7.061 5.008Q6.956 5.008 6.868 5.463Q6.781 5.918 6.448 7.230Q6.116 8.543 5.906 9.208L5.906 9.208Q5.766 9.733 5.713 10.223Q5.661 10.713 5.766 10.853L5.766 10.853Q5.906 11.098 9.476 12.218L9.476 12.218Q10.246 12.463 10.491 12.445Q10.736 12.428 10.876 12.148L10.876 12.148L10.911 12.113Q11.051 11.833 11.033 11.640Q11.016 11.448 10.666 10.923L10.666 10.923Q10.386 10.538 9.406 9.208L9.406 9.208L9.266 8.963Q8.076 7.353 7.743 6.793Q7.411 6.233 7.271 5.498L7.271 5.498Q7.131 5.008 7.061 5.008ZM17.946 5.673L17.946 5.673Q17.806 5.673 17.666 5.673L17.666 5.673Q17.211 5.743 15.846 5.830Q14.481 5.918 13.816 5.953L13.816 5.953Q13.256 5.953 12.766 6.058Q12.276 6.163 12.171 6.303L12.171 6.303Q11.996 6.513 12.066 10.258L12.066 10.258Q12.066 11.063 12.153 11.290Q12.241 11.518 12.521 11.588L12.521 11.588L12.591 11.588Q12.906 11.658 13.081 11.570Q13.256 11.483 13.641 10.958L13.641 10.958Q13.921 10.608 14.901 9.278L14.901 9.278L15.076 9.033Q16.231 7.423 16.668 6.933Q17.106 6.443 17.736 6.058L17.736 6.058Q18.191 5.813 18.156 5.743Q18.121 5.673 17.946 5.673ZM18.961 5.883L18.961 5.883Q18.646 5.883 18.436 5.953L18.436 5.953Q18.261 5.988 18.016 6.163L18.016 6.163L17.911 6.198Q17.176 6.688 16.511 7.493L16.511 7.493Q16.301 7.738 15.933 8.280Q15.566 8.823 15.601 8.858L15.601 8.858Q17.351 10.328 18.576 10.923L18.576 10.923L21.131 10.118Q22.741 9.593 23.248 9.400Q23.756 9.208 23.861 9.068Q23.966 8.928 23.931 8.788L23.931 8.788Q23.896 8.718 23.861 8.718L23.861 8.718L23.686 8.543Q22.251 7.318 21.411 6.793L21.411 6.793Q20.011 5.883 18.961 5.883ZM0.411 9.243L0.411 9.243Q0.341 9.243 0.306 9.278L0.306 9.278Q0.131 9.313 0.096 9.453L0.096 9.453Q0.061 9.488 0.061 9.558L0.061 9.558L0.131 9.768Q0.586 11.623 0.901 12.533L0.901 12.533Q1.531 14.108 2.371 14.703L2.371 14.703Q2.651 14.913 2.861 14.983L2.861 14.983Q3.001 15.018 3.316 15.053L3.316 15.053L3.421 15.053Q4.296 15.088 5.311 14.843L5.311 14.843Q5.626 14.773 6.238 14.545Q6.851 14.318 6.851 14.283L6.851 14.283Q6.291 12.078 5.696 10.853L5.696 10.853L3.106 10.013Q0.761 9.243 0.411 9.243ZM18.506 11.028L18.471 10.993Q17.981 10.993 14.726 12.113L14.726 12.113Q13.956 12.358 13.763 12.515Q13.571 12.673 13.606 12.988L13.606 12.988L13.606 13.023Q13.641 13.338 13.781 13.478Q13.921 13.618 14.516 13.863L14.516 13.863Q14.936 14.003 16.546 14.493L16.546 14.493L16.791 14.598Q18.716 15.193 19.311 15.473Q19.906 15.753 20.466 16.243L20.466 16.243Q20.851 16.558 20.921 16.505Q20.991 16.453 20.798 16.033Q20.606 15.613 20.098 14.353Q19.591 13.093 19.381 12.463L19.381 12.463Q19.171 11.938 18.926 11.500Q18.681 11.063 18.506 11.028L18.506 11.028ZM10.421 13.583L10.421 13.583Q10.176 13.583 9.546 13.758L9.546 13.758Q9.126 13.898 7.656 14.353L7.656 14.353L7.411 14.458Q5.486 15.088 4.838 15.210Q4.191 15.333 3.456 15.263L3.456 15.263Q2.966 15.228 2.931 15.315Q2.896 15.403 3.316 15.630Q3.736 15.858 4.873 16.593Q6.011 17.328 6.571 17.713L6.571 17.713Q7.026 17.993 7.481 18.203Q7.936 18.413 8.111 18.378L8.111 18.378Q8.391 18.308 10.526 15.228L10.526 15.228Q11.016 14.563 11.086 14.335Q11.156 14.108 10.911 13.898L10.911 13.898L10.876 13.863Q10.736 13.688 10.648 13.635Q10.561 13.583 10.421 13.583ZM12.871 14.353L12.871 14.353Q12.766 14.353 12.591 14.423L12.591 14.423L12.556 14.458Q12.276 14.563 12.188 14.738Q12.101 14.913 12.066 15.543L12.066 15.543Q12.031 15.998 12.066 17.678L12.066 17.678L12.066 17.958Q12.066 19.953 11.996 20.618Q11.926 21.283 11.611 21.948L11.611 21.948Q11.436 22.403 11.506 22.455Q11.576 22.508 11.926 22.193Q12.276 21.878 13.308 21.020Q14.341 20.163 14.901 19.743L14.901 19.743Q15.321 19.393 15.653 19.025Q15.986 18.658 15.986 18.483L15.986 18.483Q16.021 18.203 13.781 15.228L13.781 15.228Q13.396 14.703 13.203 14.528Q13.011 14.353 12.871 14.353ZM17.141 15.053L17.141 15.053Q17.141 15.053 17.141 15.053L17.141 15.053L17.141 15.053Q16.301 17.188 16.091 18.518L16.091 18.518L17.666 20.688Q18.646 22.053 18.996 22.473Q19.346 22.893 19.503 22.963Q19.661 23.033 19.801 22.928L19.801 22.928Q19.836 22.928 19.836 22.858L19.836 22.858L19.941 22.648Q20.676 20.898 20.921 19.953L20.921 19.953Q21.341 18.343 21.026 17.328L21.026 17.328Q20.921 17.013 20.781 16.838L20.781 16.838Q20.676 16.698 20.466 16.488L20.466 16.488L20.361 16.418Q19.696 15.893 18.716 15.508L18.716 15.508Q18.436 15.403 17.841 15.210Q17.246 15.018 17.141 15.053ZM9.896 18.343L9.896 18.343Q8.881 18.378 8.111 18.483L8.111 18.483L6.536 20.653Q5.521 22.053 5.223 22.490Q4.926 22.928 4.926 23.103Q4.926 23.278 5.031 23.383L5.031 23.383Q5.066 23.418 5.136 23.418L5.136 23.418L5.381 23.418Q7.271 23.593 8.216 23.523L8.216 23.523Q9.896 23.453 10.736 22.823L10.736 22.823Q11.016 22.613 11.156 22.438L11.156 22.438Q11.226 22.298 11.366 22.018L11.366 22.018L11.401 21.913Q11.716 21.108 11.786 20.058L11.786 20.058Q11.821 19.743 11.786 19.095Q11.751 18.448 11.716 18.413L11.716 18.413Q10.666 18.343 9.896 18.343Z"/>', + 'seti:illustrator': + '<path d="M23.802 23.151L23.802 0.849L0.198 0.849L0.198 23.151L23.802 23.151ZM13.848 16.977L13.848 16.977L12.546 16.977Q12.336 16.977 12.273 16.956Q12.210 16.935 12.126 16.725L12.126 16.725Q12 16.263 11.664 15.276Q11.328 14.289 11.202 13.827L11.202 13.827Q11.202 13.743 11.097 13.659Q10.992 13.575 10.824 13.575L10.824 13.575L8.052 13.575Q7.884 13.575 7.758 13.743L7.758 13.743L7.674 13.827L6.876 16.725Q6.876 16.809 6.792 16.893Q6.708 16.977 6.624 16.977L6.624 16.977L5.196 16.977Q4.986 16.977 4.944 16.914Q4.902 16.851 4.902 16.725L4.902 16.725Q5.154 15.885 5.616 14.289L5.616 14.289Q6.078 12.441 6.372 11.601L6.372 11.601Q6.624 10.635 7.212 8.598Q7.800 6.561 8.052 5.595L8.052 5.595L8.136 5.469Q8.178 5.301 8.241 5.259Q8.304 5.217 8.472 5.301L8.472 5.301L10.446 5.301Q10.572 5.301 10.635 5.343Q10.698 5.385 10.698 5.595L10.698 5.595Q11.034 6.561 11.622 8.598Q12.210 10.635 12.546 11.601L12.546 11.601L14.100 16.725Q14.184 16.935 14.163 16.956Q14.142 16.977 13.848 16.977ZM17.796 16.347L17.796 16.347Q17.796 16.809 17.712 16.893Q17.628 16.977 17.124 16.977L17.124 16.977L16.200 16.977Q15.990 16.977 15.969 16.956Q15.948 16.935 15.948 16.725L15.948 16.725L15.948 8.199Q15.948 7.989 16.032 7.905Q16.116 7.821 16.200 7.947L16.200 7.947L17.376 7.947Q17.544 7.947 17.586 8.010Q17.628 8.073 17.628 8.199L17.628 8.199Q17.754 10.971 17.796 16.347ZM16.872 7.023L16.872 7.023Q16.452 7.023 16.137 6.750Q15.822 6.477 15.822 6.078Q15.822 5.679 16.095 5.364Q16.368 5.049 16.809 5.049Q17.250 5.049 17.586 5.322Q17.922 5.595 17.922 5.973L17.922 5.973Q17.922 6.477 17.628 6.750Q17.334 7.023 16.872 7.023ZM9.648 7.821L9.648 7.821Q9.648 7.695 9.564 7.695Q9.480 7.695 9.396 7.821L9.396 7.821Q9.396 7.863 9.312 7.989Q9.228 8.115 9.228 8.199L9.228 8.199Q8.724 10.551 8.304 11.601L8.304 11.601Q8.346 11.895 8.472 11.895L8.472 11.895L10.278 11.895Q10.488 11.895 10.509 11.811Q10.530 11.727 10.446 11.601L10.446 11.601Q10.236 9.543 9.648 7.821Z"/>', + 'seti:photoshop': + '<path d="M23.802 23.172L23.802 0.702L23.802 0.198L0.198 0.198L0.198 23.802L23.172 23.802Q23.550 23.802 23.676 23.676Q23.802 23.550 23.802 23.172L23.802 23.172ZM9.900 13.428L9.900 13.428Q9.144 13.638 7.716 13.764L7.716 13.764L6.750 13.848L6.750 18.552L4.398 18.552Q4.314 18.552 4.230 18.342Q4.146 18.132 4.146 17.922L4.146 17.922L4.146 5.448Q4.146 5.364 4.839 5.259Q5.532 5.154 6.078 5.154L6.078 5.154Q8.472 5.154 9.522 5.322L9.522 5.322Q11.118 5.490 12.042 6.477Q12.966 7.464 13.050 8.976L13.050 8.976Q13.134 10.656 12.294 11.853Q11.454 13.050 9.900 13.428ZM20.022 16.074L20.022 16.074Q19.812 17.796 18.174 18.426L18.174 18.426Q15.948 19.350 13.428 18.300L13.428 18.300Q13.344 18.300 13.260 18.153Q13.176 18.006 13.176 17.922L13.176 17.922Q13.428 16.872 13.554 16.452L13.554 16.452Q14.100 16.536 15.108 16.746L15.108 16.746Q15.864 16.914 16.242 16.998Q16.620 17.082 16.956 16.872Q17.292 16.662 17.376 16.200L17.376 16.200Q17.544 15.486 16.578 14.898L16.578 14.898Q16.284 14.688 15.528 14.436L15.528 14.436L15.276 14.352Q14.184 13.848 13.701 13.134Q13.218 12.420 13.302 11.328L13.302 11.328Q13.428 10.446 14.079 9.795Q14.730 9.144 15.822 8.850L15.822 8.850Q17.502 8.472 19.224 9.102L19.224 9.102Q19.308 9.102 19.434 9.333Q19.560 9.564 19.476 9.648L19.476 9.648L19.098 11.076Q17.796 10.824 17.250 10.698L17.250 10.698Q16.578 10.698 16.326 10.824L16.326 10.824Q15.822 11.034 15.738 11.496Q15.654 11.958 16.074 12.252L16.074 12.252Q16.200 12.420 16.515 12.546Q16.830 12.672 17.019 12.798Q17.208 12.924 17.796 13.176L17.796 13.176Q18.216 13.344 18.426 13.428L18.426 13.428Q20.022 14.016 20.022 16.074ZM9.228 7.422L9.228 7.422Q8.724 7.338 7.842 7.254L7.842 7.254L6.750 7.128L6.750 11.622Q7.800 11.706 8.325 11.664Q8.850 11.622 9.480 11.349Q10.110 11.076 10.362 10.446L10.362 10.446Q10.572 9.984 10.572 9.270Q10.572 8.556 10.215 8.073Q9.858 7.590 9.228 7.422Z"/>', + 'seti:pdf': + '<path d="M0.051 21.261L0.051 21.261Q0.135 20.715 0.471 20.211L0.471 20.211Q0.681 19.917 1.227 19.392Q1.773 18.867 3.201 18.069L3.201 18.069L3.579 17.817Q4.503 17.313 6.351 16.515L6.351 16.515Q6.435 16.515 6.519 16.431Q6.603 16.347 6.603 16.263L6.603 16.263Q8.157 13.113 8.829 11.517L8.829 11.517Q9.039 11.055 9.354 10.152Q9.669 9.249 9.879 8.787L9.879 8.787L9.879 8.661Q9.123 6.855 8.955 5.637L8.955 5.637Q8.619 4.209 8.829 2.487L8.829 2.487Q8.997 1.647 9.879 0.765L9.879 0.765Q10.005 0.639 10.551 0.639L10.551 0.639L11.601 0.639Q12.063 0.639 12.231 1.017L12.231 1.017Q12.651 1.311 13.155 2.067L13.155 2.067Q13.323 2.445 13.449 3.117L13.449 3.117L13.575 3.663Q13.575 4.713 13.407 5.931L13.407 5.931Q13.281 6.687 13.029 8.115L13.029 8.115L12.651 9.585L12.651 9.711Q13.617 11.475 15.549 13.617L15.549 13.617Q15.633 13.743 15.675 13.764Q15.717 13.785 15.927 13.743L15.927 13.743Q17.355 13.491 20.127 13.491L20.127 13.491Q21.555 13.491 22.605 14.037L22.605 14.037Q23.403 14.541 23.655 14.961L23.655 14.961Q23.949 15.465 23.949 15.717L23.949 15.717L23.949 16.641Q23.949 17.103 23.529 17.313L23.529 17.313L23.403 17.439Q23.193 17.691 23.025 17.775L23.025 17.775Q22.773 17.985 22.479 17.943L22.479 17.943Q22.353 17.985 22.017 18.048Q21.681 18.111 21.555 18.111L21.555 18.111Q20.043 18.195 18.657 17.733L18.657 17.733Q17.397 17.313 16.053 16.389L16.053 16.389Q15.927 16.263 15.591 15.990Q15.255 15.717 15.129 15.591L15.129 15.591Q15.087 15.591 15.003 15.528Q14.919 15.465 14.877 15.465L14.877 15.465Q13.281 15.717 12.525 16.011L12.525 16.011Q11.979 16.137 10.929 16.452Q9.879 16.767 9.375 16.893L9.375 16.893Q9.291 16.893 9.228 16.977Q9.165 17.061 9.081 17.061L9.081 17.061Q8.157 18.741 6.855 20.463L6.855 20.463Q5.847 21.681 4.629 22.689L4.629 22.689Q3.915 23.151 3.201 23.361L3.201 23.361L2.151 23.361Q1.731 23.361 1.479 23.193L1.479 23.193Q0.975 23.025 0.618 22.647Q0.261 22.269 0.177 21.765L0.177 21.765Q0.051 21.765 0.051 21.261ZM12.273 12.945L11.601 12.063Q11.391 12.567 10.929 13.617Q10.467 14.667 10.299 15.213L10.299 15.213L13.449 14.415Q13.029 13.953 12.273 12.945L12.273 12.945ZM17.229 15.465L17.229 15.465Q18.363 16.221 19.875 16.641L19.875 16.641Q20.127 16.725 20.379 16.683L20.379 16.683Q20.505 16.641 20.736 16.536Q20.967 16.431 21.030 16.200Q21.093 15.969 20.925 15.843L20.925 15.843Q20.925 15.717 20.631 15.717L20.631 15.717Q20.505 15.675 20.148 15.612Q19.791 15.549 19.581 15.465L19.581 15.465Q18.405 15.255 17.229 15.465ZM4.377 19.749L4.881 19.161Q4.881 19.161 4.839 19.161L4.839 19.161L4.881 19.161Q3.747 19.707 2.655 20.589L2.655 20.589Q2.277 20.841 1.731 21.639L1.731 21.639L1.731 21.891L1.899 22.017L2.025 22.017L2.445 21.681Q2.781 21.471 2.949 21.387L2.949 21.387Q3.495 20.883 4.377 19.749L4.377 19.749ZM10.425 5.511L10.551 5.889Q10.593 5.889 10.635 5.889L10.635 5.889L10.551 5.889Q10.929 4.713 10.929 3.663L10.929 3.663Q10.929 2.865 10.803 2.487L10.803 2.487Q10.803 2.361 10.551 2.361L10.551 2.361Q10.467 2.361 10.404 2.424Q10.341 2.487 10.299 2.487L10.299 2.487Q10.089 2.739 10.047 3.075L10.047 3.075Q10.005 3.285 10.005 3.789L10.005 3.789Q10.005 4.461 10.131 4.839L10.131 4.839Q10.341 5.007 10.425 5.511L10.425 5.511Z"/>', + 'seti:font': + '<path d="M19.565 16.346L18.663 14.952L14.440 14.952L13.948 16.100L13.825 16.387Q13.661 16.797 13.661 17.002L13.661 17.002Q13.702 17.576 14.071 17.781L14.071 17.781Q14.153 17.863 14.645 17.904L14.645 17.904L15.219 18.027L15.219 18.396L11.242 18.396L11.242 18.027Q12.021 17.781 12.267 17.494L12.267 17.494Q12.718 17.043 13.292 15.731L13.292 15.731L17.515 6.219L17.638 6.219L21.902 15.977Q22.476 17.330 22.927 17.781L22.927 17.781Q23.419 18.027 23.788 18.027L23.788 18.027L23.788 18.396L18.047 18.396L18.047 18.027L18.540 18.027Q19.073 18.027 19.565 17.781L19.565 17.781Q19.852 17.494 19.811 17.371L19.811 17.371L19.811 17.002L19.565 16.346ZM14.850 14.173L18.416 14.173L16.613 10.073L14.850 14.173ZM0.213 20.856L0.213 20.200Q1.074 20.200 1.709 19.298Q2.345 18.396 2.796 17.125L2.796 17.125L8.413 3.144L9.192 3.144L14.973 16.592Q15.465 17.822 16.162 19.175L16.162 19.175L16.367 19.544Q16.695 20.200 17.802 20.200L17.802 20.200L17.802 20.856L9.438 20.856L9.438 20.200Q10.586 20.200 11.119 19.954L11.119 19.954Q11.488 19.749 11.488 19.175L11.488 19.175Q11.488 18.970 11.365 18.560L11.365 18.560L11.242 18.273Q10.996 17.781 10.873 17.371L10.873 17.371L10.217 15.854L4.477 15.854L3.698 17.904Q3.288 18.847 3.288 19.298L3.288 19.298Q3.288 19.872 4.067 20.077L4.067 20.077Q4.313 20.200 5.338 20.200L5.338 20.200L5.338 20.856L0.213 20.856ZM4.846 14.829L9.848 14.829L7.388 8.925L7.142 8.925L4.846 14.829Z"/>', + 'seti:image': + '<path d="M18.640 13.480L18.640 13.480Q19.560 13.480 20.220 12.840Q20.880 12.200 20.880 11.260Q20.880 10.320 20.220 9.660Q19.560 9 18.620 9Q17.680 9 17.020 9.660Q16.360 10.320 16.360 11.260Q16.360 12.200 17.020 12.840Q17.680 13.480 18.640 13.480ZM23.880 6.640L4.760 6.640L4.760 22.120L23.880 22.120L23.880 6.640ZM5.640 19L5.640 7.480L23 7.480L23 21L18.520 15.880L15.760 19.120L10.240 13.240L5.640 19ZM17.880 4L17.880 1.880L0.120 1.880L0.120 15.360L2.520 15.360L2.520 4L17.880 4Z"/>', + 'seti:svg': + '<path d="M6.360 13.120L6.360 6.240L13.240 6.240Q13.240 5 12.360 3.540Q11.480 2.080 10.080 1.160L10.080 1.160Q8.520 0.120 6.840 0.120Q5.160 0.120 3.620 1.020Q2.080 1.920 1.160 3.420Q0.240 4.920 0.240 6.600Q0.240 8.280 1.280 9.880L1.280 9.880Q2.200 11.280 3.660 12.200Q5.120 13.120 6.360 13.120L6.360 13.120ZM9.000 23.880L9.000 9.120L23.760 9.120L23.760 23.880L9.000 23.880Z"/>', + 'seti:sublime': + '<path d="M23.787 11.131L23.787 11.131L23.787 10.501Q23.409 8.023 22.233 5.881L22.233 5.881Q21.057 4.117 19.461 2.731L19.461 2.731Q18.159 1.639 16.563 1.051L16.563 1.051Q11.355-0.965 6.483 1.555L6.483 1.555Q3.669 3.151 2.031 5.755L2.031 5.755Q1.107 7.183 0.645 8.569L0.645 8.569Q0.183 10.039 0.183 11.677L0.183 11.677L0.183 13.105Q0.561 16.171 2.031 18.481L2.031 18.481Q3.585 20.749 5.433 21.883L5.433 21.883Q6.903 22.891 8.163 23.227L8.163 23.227Q11.061 24.109 13.413 23.731L13.413 23.731Q19.965 22.765 22.737 16.801L22.737 16.801Q23.997 14.281 23.787 11.131ZM14.883 17.431L14.883 17.431Q14.169 17.809 13.287 17.893L13.287 17.893Q12.783 17.977 11.733 17.977L11.733 17.977Q9.717 17.977 7.533 16.633L7.533 16.633Q7.155 16.465 7.407 16.255L7.407 16.255L8.163 14.701L8.331 14.575L8.457 14.533Q9.927 15.667 11.985 15.877L11.985 15.877Q12.783 15.877 13.161 15.751L13.161 15.751Q13.833 15.583 14.085 14.827L14.085 14.827Q14.085 14.113 13.413 13.777L13.413 13.777Q12.657 13.357 11.061 12.853L11.061 12.853L10.893 12.811Q10.011 12.559 9.591 12.349L9.591 12.349Q8.835 12.013 8.457 11.551L8.457 11.551Q7.785 10.879 7.785 9.451L7.785 9.451Q7.869 7.939 8.835 7.057L8.835 7.057Q9.675 6.217 11.061 6.007L11.061 6.007Q13.665 5.629 15.933 7.057L15.933 7.057Q16.059 7.183 16.059 7.477L16.059 7.477L15.261 8.905Q15.219 9.031 15.177 9.052Q15.135 9.073 15.051 9.073L15.051 9.073L14.883 9.031Q14.001 8.527 13.245 8.275L13.245 8.275Q12.405 8.023 11.481 8.107L11.481 8.107Q11.313 8.107 11.061 8.170Q10.809 8.233 10.683 8.233L10.683 8.233Q10.347 8.485 10.179 8.716Q10.011 8.947 10.011 9.325L10.011 9.325Q10.011 9.997 10.578 10.375Q11.145 10.753 11.733 10.753L11.733 10.753Q12.153 10.879 13.077 11.131L13.077 11.131L14.211 11.425Q14.337 11.257 14.757 11.257L14.757 11.257Q14.337 11.257 14.211 11.383L14.211 11.383L15.219 11.803Q15.261 11.845 15.261 11.929L15.261 11.929L15.345 11.929Q15.387 11.971 15.387 12.055L15.387 12.055L15.555 12.181Q15.639 12.223 15.639 12.307L15.639 12.307L15.807 12.475Q16.395 12.979 16.584 13.987Q16.773 14.995 16.353 15.919L16.353 15.919Q15.933 16.969 14.883 17.431Z"/>', + 'seti:code-search': + '<path d="M15.067 0.258L15.067 0.223Q12.792 0.223 10.849 1.500Q8.907 2.777 7.979 4.895Q7.052 7.012 7.384 9.305Q7.717 11.598 9.257 13.348L9.257 13.348L1.627 22.098L2.677 23.043L10.272 14.328Q11.777 15.518 13.632 15.867Q15.487 16.218 17.289 15.675Q19.092 15.133 20.457 13.803Q21.822 12.473 22.434 10.670Q23.047 8.867 22.784 6.995Q22.522 5.122 21.419 3.565Q20.317 2.008 18.637 1.133Q16.957 0.258 15.067 0.258L15.067 0.258ZM15.067 14.572L15.067 14.572Q13.142 14.572 11.532 13.470Q9.922 12.367 9.187 10.565Q8.452 8.762 8.837 6.855Q9.222 4.947 10.587 3.565Q11.952 2.183 13.842 1.797Q15.732 1.412 17.517 2.165Q19.302 2.918 20.369 4.545Q21.437 6.172 21.437 8.098L21.437 8.098Q21.437 9.392 20.964 10.582Q20.492 11.773 19.599 12.683Q18.707 13.593 17.534 14.082Q16.362 14.572 15.067 14.572ZM15.102 1.657L15.102 1.657Q13.212 1.657 11.602 2.690Q9.992 3.723 9.204 5.473Q8.417 7.223 8.714 9.113Q9.012 11.003 10.272 12.438L10.272 12.438L3.937 19.648L4.847 20.453L11.112 13.277Q12.372 14.258 13.912 14.537Q15.452 14.818 16.939 14.380Q18.427 13.943 19.564 12.840Q20.702 11.738 21.209 10.250Q21.717 8.762 21.489 7.205Q21.262 5.648 20.352 4.370Q19.442 3.092 18.059 2.375Q16.677 1.657 15.102 1.657L15.102 1.657ZM15.102 13.453L15.102 13.453Q13.492 13.453 12.162 12.560Q10.832 11.668 10.219 10.180Q9.607 8.692 9.922 7.117Q10.237 5.543 11.374 4.387Q12.512 3.232 14.087 2.918Q15.662 2.602 17.132 3.232Q18.602 3.863 19.512 5.192L19.512 5.192Q20.562 6.767 20.369 8.657Q20.177 10.547 18.847 11.913L18.847 11.913Q18.112 12.648 17.132 13.050Q16.152 13.453 15.102 13.453ZM3.622 23.778L1.137 21.608L9.782 11.808L12.232 13.978L3.622 23.778Z"/>', + 'seti:shell': + '<path d="M9.977 3.222L9.935 3.222Q9.305 3.432 8.717 3.810L8.717 3.810Q8.549 3.894 8.213 4.146L8.213 4.146Q7.709 4.524 7.289 5.070L7.289 5.070L6.995 5.448Q6.575 6.120 6.449 6.666L6.449 6.666Q6.365 6.918 6.323 7.254L6.323 7.254Q6.239 7.884 6.323 8.556L6.323 8.556Q6.365 8.976 6.449 9.396L6.449 9.396Q6.617 10.026 6.995 10.614L6.995 10.614L7.289 10.992Q7.667 11.454 8.255 11.874L8.255 11.874L8.885 12.336Q9.347 12.672 10.061 12.966L10.061 12.966L11.069 13.386L11.531 13.554Q12.119 13.764 12.329 13.848L12.329 13.848L12.413 13.932Q13.757 14.310 14.345 15.360L14.345 15.360Q14.597 15.864 14.597 16.284L14.597 16.284L14.597 16.452Q14.681 16.998 14.555 17.250L14.555 17.250Q14.051 18.258 13.253 18.552L13.253 18.552Q12.749 18.720 11.447 18.678L11.447 18.678Q10.565 18.468 10.061 17.922L10.061 17.922Q9.599 17.418 9.305 16.494L9.305 16.494L9.263 16.326Q9.221 16.032 9.032 15.843Q8.843 15.654 8.549 15.654L8.549 15.654L6.449 15.654Q6.155 15.654 5.966 15.843Q5.777 16.032 5.819 16.326L5.819 16.326Q5.819 16.956 5.966 17.544Q6.113 18.132 6.449 18.804L6.449 18.804Q6.659 19.140 6.911 19.455Q7.163 19.770 7.877 20.316L7.877 20.316Q8.213 20.568 8.465 20.694L8.465 20.694Q8.843 20.904 9.683 21.240L9.683 21.240L9.977 21.324Q10.271 21.408 10.460 21.597Q10.649 21.786 10.649 22.080L10.649 22.080L10.649 23.130Q10.649 23.424 10.838 23.613Q11.027 23.802 11.321 23.802L11.321 23.802L12.749 23.802Q13.043 23.802 13.232 23.613Q13.421 23.424 13.421 23.130L13.421 23.130L13.421 22.080Q13.421 21.786 13.610 21.555Q13.799 21.324 14.051 21.282L14.051 21.282Q14.219 21.240 14.513 21.114L14.513 21.114Q15.269 20.820 15.731 20.568L15.731 20.568Q16.613 20.022 17.411 18.888L17.411 18.888Q17.873 18.216 17.999 17.712L17.999 17.712Q18.125 17.418 18.167 16.998L18.167 16.998Q18.209 16.326 18.167 15.696L18.167 15.696Q18.125 15.276 17.999 14.982L17.999 14.982Q17.831 14.310 17.453 13.764L17.453 13.764Q16.907 12.882 15.563 11.916L15.563 11.916Q14.975 11.538 14.387 11.244L14.387 11.244Q13.925 11.034 12.959 10.656L12.959 10.656L12.035 10.320Q11.153 9.984 10.859 9.732L10.859 9.732Q10.355 9.312 10.124 8.913Q9.893 8.514 9.851 8.094L9.851 8.094L9.851 8.052Q9.851 7.590 9.914 7.254Q9.977 6.918 10.313 6.414L10.313 6.414Q10.565 6.078 10.943 5.994L10.943 5.994Q11.405 5.826 11.825 5.826L11.825 5.826Q12.539 5.784 12.896 5.847Q13.253 5.910 13.694 6.267Q14.135 6.624 14.345 7.044L14.345 7.044Q14.597 7.590 14.597 8.094L14.597 8.094L14.597 8.094Q14.639 8.388 14.828 8.577Q15.017 8.766 15.269 8.766L15.269 8.766L17.369 8.766Q17.663 8.766 17.852 8.556Q18.041 8.346 17.999 8.094L17.999 8.094Q17.957 7.590 17.852 7.107Q17.747 6.624 17.411 5.868L17.411 5.868Q17.285 5.574 17.117 5.322L17.117 5.322Q16.697 4.650 16.277 4.272L16.277 4.272Q16.067 4.062 15.857 3.894Q15.647 3.726 15.017 3.390L15.017 3.390L14.681 3.222L14.345 3.054Q14.051 2.928 13.862 2.697Q13.673 2.466 13.673 2.214L13.673 2.214L13.673 0.870Q13.673 0.576 13.484 0.387Q13.295 0.198 13.043 0.198L13.043 0.198L11.573 0.198Q11.279 0.198 11.090 0.387Q10.901 0.576 10.901 0.870L10.901 0.870L10.901 2.340Q10.901 2.802 10.313 3.054L10.313 3.054Q10.229 3.138 9.977 3.222L9.977 3.222Z"/>', + 'seti:video': + '<path d="M12.000 23.802L12.000 23.802Q8.808 23.802 6.078 22.185Q3.348 20.568 1.752 17.838L1.752 17.838Q0.114 15.024 0.198 11.748L0.198 11.748Q0.240 8.598 1.836 5.952Q3.432 3.306 6.078 1.794L6.078 1.794Q8.850 0.198 12.126 0.198L12.126 0.198Q15.318 0.198 18.027 1.815Q20.736 3.432 22.290 6.162L22.290 6.162Q23.886 8.976 23.802 12.252L23.802 12.252Q23.760 15.360 22.143 18.027Q20.526 20.694 17.880 22.206L17.880 22.206Q15.150 23.802 12.000 23.802ZM7.800 4.650L7.800 4.650L7.800 19.224L7.926 19.224L18.552 12.126L18.678 12Q18.678 12 18.552 12L18.552 12Q11.496 7.254 7.800 4.902L7.800 4.902Q7.884 4.818 7.884 4.734Q7.884 4.650 7.800 4.650Z"/>', + 'seti:audio': + '<path d="M12.475 21.282L12.323 21.282Q12.171 21.282 11.867 21.054L11.867 21.054L11.639 20.902Q8.067 17.824 6.167 16.266L6.167 16.266L6.053 16.190L5.939 16.152L0.923 16.152Q0.315 16.152 0.125 15.582L0.125 15.582L0.125 8.818Q0.125 8.362 0.372 8.115Q0.619 7.868 1.075 7.868L1.075 7.868L6.053 7.868Q6.281 7.868 6.281 7.716L6.281 7.716L11.753 2.966Q12.095 2.700 12.437 2.719Q12.779 2.738 13.045 3.118L13.045 3.118Q13.159 3.232 13.159 3.574L13.159 3.574L13.159 20.332Q13.159 20.978 12.703 21.168L12.703 21.168L12.589 21.168L12.475 21.282ZM23.837 12.124L23.875 12.124Q23.875 12.846 23.723 13.188L23.723 13.188Q23.571 15.354 22.659 17.482L22.659 17.482Q21.899 19.382 20.759 20.674L20.759 20.674Q20.607 20.978 20.075 21.168L20.075 21.168Q19.581 21.168 19.239 20.788L19.239 20.788Q19.049 20.636 19.049 20.389Q19.049 20.142 19.239 19.952L19.239 19.952Q19.277 19.838 19.467 19.610Q19.657 19.382 19.695 19.268L19.695 19.268Q21.481 16.760 21.823 13.910L21.823 13.910Q22.545 8.514 19.239 4.296L19.239 4.296Q18.783 3.650 19.239 3.232L19.239 3.232Q19.505 2.852 19.904 2.852Q20.303 2.852 20.645 3.232L20.645 3.232Q22.089 5.056 22.659 6.652L22.659 6.652Q23.571 8.780 23.723 11.174L23.723 11.174L23.723 12.010Q23.799 12.010 23.837 12.086L23.837 12.086L23.837 12.124ZM20.645 11.896L20.645 11.896Q20.645 15.468 18.631 18.432L18.631 18.432Q18.479 18.698 17.909 18.888L17.909 18.888Q17.453 18.888 17.073 18.546L17.073 18.546Q16.921 18.356 16.921 18.109Q16.921 17.862 17.073 17.596L17.073 17.596Q17.073 17.520 17.149 17.463Q17.225 17.406 17.187 17.368L17.187 17.368Q18.517 15.582 18.859 13.188L18.859 13.188Q19.391 9.502 17.073 6.310L17.073 6.310Q16.845 5.816 16.845 5.588L16.845 5.588Q16.959 5.284 17.073 5.132Q17.187 4.980 17.453 4.866L17.453 4.866Q18.023 4.676 18.384 5.189Q18.745 5.702 19.467 6.918L19.467 6.918Q20.531 9.236 20.531 11.060L20.531 11.060Q20.645 11.554 20.645 11.896ZM17.339 12.010L17.339 12.010Q17.339 14.366 16.123 16.038L16.123 16.038Q15.971 16.380 15.648 16.475Q15.325 16.570 14.983 16.380Q14.641 16.190 14.546 15.867Q14.451 15.544 14.717 15.202L14.717 15.202Q15.325 14.290 15.553 12.846L15.553 12.846Q15.705 11.820 15.477 10.775Q15.249 9.730 14.717 8.818L14.717 8.818Q14.527 8.438 14.603 8.115Q14.679 7.792 14.945 7.621Q15.211 7.450 15.591 7.526Q15.971 7.602 16.123 7.868L16.123 7.868Q16.655 8.666 17.073 10.110L17.073 10.110L17.149 10.414Q17.339 11.516 17.339 12.010Z"/>', + 'seti:windows': + '<path d="M0.125 11.544L0.125 3.450L9.815 2.120L9.815 11.506L0.125 11.544ZM0.125 12.532L9.815 12.570L9.815 21.956L0.125 20.626L0.125 12.532ZM10.993 11.468L10.993 1.968L23.837 0.106L23.837 11.392L10.993 11.468ZM10.955 12.646L23.875 12.684L23.837 23.894L10.993 22.108L10.955 12.646Z"/>', + 'seti:jenkins': + '<path d="M13.216 8.608L13.216 8.608Q13.248 8.608 13.344 8.608L13.344 8.608L13.376 8.608Q14.176 8.544 15.200 7.904L15.200 7.904Q15.232 7.872 15.264 7.776L15.264 7.776L15.360 7.488Q15.488 7.200 15.232 6.976L15.232 6.976Q14.496 6.304 13.952 5.440L13.952 5.440Q13.888 5.312 13.792 5.088L13.792 5.088L13.696 4.864Q13.664 4.832 13.600 4.768L13.600 4.768L13.568 4.736L13.504 4.896Q13.504 4.992 13.536 5.152L13.536 5.152Q13.664 5.728 14.208 6.400L14.208 6.400Q14.528 6.816 14.848 7.168L14.848 7.168Q14.976 7.328 14.944 7.552Q14.912 7.776 14.688 7.840L14.688 7.840Q14.592 7.872 14.400 7.968L14.400 7.968L14.176 8.096Q13.632 8.320 13.344 8.320L13.344 8.320Q13.152 8.288 13.056 8.224Q12.960 8.160 12.928 8L12.928 8L12.864 7.712Q12.608 7.968 12.800 8.384L12.800 8.384Q12.832 8.544 12.944 8.576Q13.056 8.608 13.216 8.608ZM11.552 9.088L11.680 9.312Q11.936 9.568 12.416 9.728L12.416 9.728Q13.120 9.920 13.824 9.888L13.824 9.888L13.824 9.536Q13.824 9.312 13.632 9.312L13.632 9.312Q12.864 9.312 12.416 9.248L12.416 9.248Q12.224 9.248 11.840 9.152L11.840 9.152L11.552 9.088ZM11.168 5.760L11.136 5.760Q11.008 5.760 10.960 5.808Q10.912 5.856 10.960 5.984Q11.008 6.112 11.104 6.176L11.104 6.176Q11.616 6.400 12.080 6.208Q12.544 6.016 12.384 5.440L12.384 5.440Q12.320 5.184 12.032 4.800Q11.744 4.416 11.632 4.464Q11.520 4.512 11.776 5.184L11.776 5.184Q11.904 5.664 11.888 5.744Q11.872 5.824 11.168 5.760L11.168 5.760ZM10.176 4.352L10.176 4.352Q10.208 4.288 10.272 4.192L10.272 4.192Q10.752 3.232 11.616 3.424L11.616 3.424Q11.776 3.424 11.776 3.296Q11.776 3.168 11.680 3.072Q11.584 2.976 11.456 2.944L11.456 2.944Q11.072 2.848 10.720 3.104L10.720 3.104Q10.080 3.520 10.016 4.096L10.016 4.096Q10.016 4.320 10.176 4.352ZM14.112 9.280L14.112 9.280Q14.048 9.280 14.048 9.376L14.048 9.376L14.048 9.856Q14.528 9.856 14.928 9.536Q15.328 9.216 15.552 8.704L15.552 8.704L15.456 8.736L15.232 8.864Q14.528 9.248 14.112 9.280ZM15.136 6.016L15.136 6.016Q15.616 6.080 16 5.728L16 5.728Q16.096 5.632 16.032 5.504L16.032 5.504L15.840 5.120Q15.552 4.416 15.456 4.432Q15.360 4.448 15.424 4.768L15.424 4.768Q15.488 4.992 15.616 5.248L15.616 5.248Q15.680 5.440 15.648 5.488Q15.616 5.536 15.424 5.568L15.424 5.568L15.296 5.568Q14.912 5.536 14.864 5.632Q14.816 5.728 14.896 5.872Q14.976 6.016 15.136 6.016ZM19.264 16.960L19.264 16.960Q19.072 16.320 18.688 16.112Q18.304 15.904 17.632 16.064L17.632 16.064Q17.408 16.128 16.896 16.320L16.896 16.320L16.384 16.544L17.600 12.896Q17.856 12.128 17.248 11.648L17.248 11.648L16.608 11.136L16.224 10.816Q16 10.592 15.984 10.496Q15.968 10.400 16.128 10.112L16.128 10.112Q16.640 9.248 16.880 7.808Q17.120 6.368 17.088 5.056L17.088 5.056Q16.992 3.264 16.160 2.144L16.160 2.144Q14.848 0.352 12.800 0.128L12.800 0.128L12.480 0.096L11.776 0.096L10.944 0.224Q9.536 0.448 8.128 1.312L8.128 1.312L7.744 1.568Q7.008 2.016 6.720 2.816L6.720 2.816Q6.656 2.912 6.528 3.008L6.528 3.008Q5.888 3.456 5.856 4.320L5.856 4.320Q5.856 4.608 5.856 5.120L5.856 5.120L5.888 5.664Q5.888 5.728 5.824 5.856L5.824 5.856L5.728 6.144Q5.600 6.432 5.568 6.592L5.568 6.592Q5.408 7.840 6.208 8.736L6.208 8.736Q6.464 9.024 6.976 9.152L6.976 9.152Q7.104 9.216 7.136 9.344L7.136 9.344Q7.232 9.920 7.552 10.400L7.552 10.400Q7.648 10.528 7.680 10.688L7.680 10.688Q7.712 10.944 7.488 11.072L7.488 11.072L5.248 12.448Q5.120 12.512 5.024 12.576L5.024 12.576Q4.544 12.736 4.416 13.120L4.416 13.120L4.416 13.344L4.672 14.016Q5.056 15.040 5.216 15.584L5.216 15.584Q5.568 16.640 5.696 18.304L5.696 18.304L5.728 19.616Q5.760 19.936 6.048 20.064L6.048 20.064L8.000 20.928Q8.544 21.152 9.120 21.120L9.120 21.120Q9.248 21.120 9.312 21.248L9.312 21.248L10.016 23.488Q10.048 23.616 10.208 23.648L10.208 23.648L11.616 23.904L12.928 23.904L13.664 23.840Q14.080 23.744 14.368 23.648L14.368 23.648Q14.752 23.520 14.688 23.040L14.688 23.040Q14.656 22.816 14.704 22.768Q14.752 22.720 14.976 22.656L14.976 22.656L14.976 22.656Q15.424 22.528 15.536 22.336Q15.648 22.144 15.552 21.696L15.552 21.696L15.360 20.672L15.360 20.416Q15.360 20.256 15.536 20.208Q15.712 20.160 15.776 19.936L15.776 19.936Q15.776 19.840 15.840 19.808L15.840 19.808Q16.352 19.584 16.928 19.648L16.928 19.648Q16.992 19.648 16.992 19.648L16.992 19.648Q17.056 19.840 17.184 19.888Q17.312 19.936 17.536 19.936L17.536 19.936L17.536 19.936Q18.144 19.968 18.528 19.936L18.528 19.936Q19.232 19.872 19.488 19.008L19.488 19.008L19.584 18.560L19.584 18.176Q19.392 17.440 19.264 16.960ZM8.160 10.848L8.192 10.816Q7.744 9.920 7.616 9.216L7.616 9.216Q7.584 8.992 7.744 8.832Q7.904 8.672 7.936 8.592Q7.968 8.512 7.904 8.352L7.904 8.352Q7.904 8.352 7.840 8.352L7.840 8.352L7.744 8.384Q7.680 8.416 7.584 8.480L7.584 8.480L7.520 8.512Q7.104 8.800 6.688 8.512L6.688 8.512Q6.208 8.192 6.016 7.456L6.016 7.456Q5.856 6.848 6.144 6.400L6.144 6.400Q6.528 5.888 7.104 5.952L7.104 5.952Q7.456 6.016 7.648 6.400L7.648 6.400Q7.712 6.528 7.776 6.848L7.776 6.848L7.776 6.848Q7.808 6.976 7.936 6.976L7.936 6.976L8.288 6.912Q8.480 6.880 8.544 6.784Q8.608 6.688 8.544 6.464L8.544 6.464L8.384 5.728Q8.320 5.376 8.416 4.736L8.416 4.736L8.416 4.704Q8.576 3.936 8.608 3.552L8.608 3.552Q8.608 3.456 8.544 3.168L8.544 3.168L8.512 2.976Q8.512 2.816 8.544 2.720L8.544 2.720Q8.864 2.112 9.536 1.664Q10.208 1.216 10.944 0.832L10.944 0.832Q11.488 0.544 12.480 0.640Q13.472 0.736 14.464 1.248L14.464 1.248Q14.944 1.472 15.488 2.144L15.488 2.144L15.936 2.720Q15.648 2.688 15.488 2.720L15.488 2.720Q15.232 2.752 15.104 2.944L15.104 2.944Q15.040 3.040 15.008 3.296L15.008 3.296Q15.424 3.008 15.920 3.264Q16.416 3.520 16.576 3.936L16.576 3.936Q16.672 4.256 16.704 4.512L16.704 4.512Q16.832 5.952 16.736 6.880L16.736 6.880Q16.576 8.672 15.840 9.824L15.840 9.824Q15.360 10.624 15.008 10.912L15.008 10.912Q14.464 11.456 13.408 11.712L13.408 11.712Q12.704 11.872 12.096 11.680L12.096 11.680Q11.360 11.424 10.784 10.912L10.784 10.912Q10.336 10.528 9.696 9.632L9.696 9.632L9.568 9.472Q9.504 9.696 9.696 10.016L9.696 10.016Q9.984 10.528 10.656 11.200L10.656 11.200Q10.784 11.328 11.072 11.552L11.072 11.552L11.264 11.680L10.976 11.712Q9.408 11.808 9.088 11.712L9.088 11.712Q8.544 11.584 8.160 10.848L8.160 10.848ZM12.288 14.432L12.480 14.240Q12.768 14.528 13.184 15.328L13.184 15.328Q13.536 15.936 13.760 16.480L13.760 16.480L13.568 16.448Q13.312 16.384 13.184 16.320L13.184 16.320L11.488 15.616Q11.360 15.552 11.424 15.456L11.424 15.456L11.488 15.296Q11.680 14.976 11.808 14.832Q11.936 14.688 12.288 14.432L12.288 14.432ZM13.696 15.328L13.696 15.328Q13.568 15.072 13.280 14.560L13.280 14.560L13.056 14.144Q12.992 14.016 13.024 13.952L13.024 13.952Q13.088 13.792 13.216 13.824L13.216 13.824Q13.312 13.856 13.472 13.760L13.472 13.760Q13.728 13.632 14.016 13.824L14.016 13.824Q14.112 13.888 14.336 13.984L14.336 13.984L14.464 14.048Q14.464 14.592 14.400 15.328L14.400 15.328Q14.336 16.256 14.176 16.448L14.176 16.448L14.080 16.160Q13.824 15.584 13.696 15.328ZM13.152 23.200L13.152 23.200Q12.224 23.328 11.264 23.136L11.264 23.136Q10.976 23.104 10.528 22.976L10.528 22.976Q10.432 22.976 10.400 22.880L10.400 22.880L10.240 22.304Q9.952 21.184 9.824 20.608Q9.696 20.032 9.536 18.848L9.536 18.848L9.440 18.144L9.440 17.984L10.112 17.888Q11.648 17.664 12.768 17.728L12.768 17.728Q12.960 17.728 13.280 17.760L13.280 17.760L13.568 17.824Q13.664 17.824 13.696 17.952L13.696 17.952L13.952 22.240Q13.952 22.432 14.016 22.784L14.016 22.784L14.048 23.040L13.792 23.104Q13.376 23.168 13.152 23.200ZM14.944 22.176L14.944 22.176Q14.848 22.208 14.688 22.240L14.688 22.240L14.432 22.304L14.368 20.448L14.784 20.352Q14.816 20.352 14.864 20.368Q14.912 20.384 14.912 20.416L14.912 20.416L14.944 20.544Q15.104 21.408 15.168 21.856L15.168 21.856L15.168 21.856Q15.168 22.080 15.152 22.112Q15.136 22.144 14.944 22.176L14.944 22.176ZM14.624 16.416L14.624 16.384Q14.592 16.416 14.592 16.416Q14.592 16.416 14.592 16.416L14.592 16.416L14.816 14.656Q14.848 14.464 14.848 14.176L14.848 14.176Q14.848 14.016 15.040 13.968Q15.232 13.920 15.472 14.032Q15.712 14.144 15.808 14.336L15.808 14.336Q15.872 14.400 15.808 14.432L15.808 14.432L14.624 16.416ZM18.112 19.296L18.144 19.296Q18.112 19.296 18.048 19.296L18.048 19.296Q17.632 19.296 17.440 19.264L17.440 19.264L17.440 19.200L18.208 19.040L18.208 19.008L17.952 18.944L16.992 18.976Q16.864 19.008 16.832 18.976Q16.800 18.944 16.800 18.816L16.800 18.816L16.608 17.344Q16.576 17.280 16.640 17.248L16.640 17.248L17.344 16.928L17.824 16.736Q18.048 16.608 18.272 16.672Q18.496 16.736 18.592 16.992L18.592 16.992Q18.848 17.856 18.912 18.336L18.912 18.336Q18.976 18.720 18.752 18.992Q18.528 19.264 18.112 19.296L18.112 19.296ZM15.616 2.912L15.520 3.168Q15.584 3.168 15.648 3.200L15.648 3.200Q15.808 3.264 15.936 3.392L15.936 3.392Q16.160 3.552 16.320 3.808L16.320 3.808Q16.544 4.192 16.672 4.864L16.672 4.864L16.704 5.440L16.704 6.016Q16.704 6.720 16.608 7.296L16.608 7.296Q16.480 8.256 16 9.280L16 9.280Q15.616 10.016 15.104 10.688L15.104 10.688L14.656 11.232L15.808 10.272L16.608 8.640L16.928 6.688L16.928 4.768L16.640 3.136L15.616 2.912Z"/>', + 'seti:babel': + '<path d="M18.766 8.158L18.766 8.158L20.738 6.356Q21.554 5.064 21.554 3.534L21.554 3.534L21.554 3.296Q21.554 2.990 21.418 2.718L21.418 2.718Q20.874 1.630 19.582 1.120L19.582 1.120Q18.562 0.440 15.570 0.304L15.570 0.304Q12.170 0.780 9.450 1.970L9.450 1.970Q8.226 2.820 7.104 3.432L7.104 3.432L7.104 3.602Q7.138 3.602 7.206 3.568Q7.274 3.534 7.308 3.534L7.308 3.534Q7.444 3.534 7.444 3.602L7.444 3.602L7.614 3.534L7.682 3.534L7.682 3.602L7.614 3.704Q7.512 3.806 7.308 3.908Q7.104 4.010 6.424 4.520L6.424 4.520L5.982 4.860L6.220 5.030L6.050 4.928Q6.050 5.030 5.846 5.030L5.846 5.030L5.846 5.098L5.982 5.302Q5.846 5.302 5.744 5.234L5.744 5.234Q5.098 5.336 4.724 5.982L4.724 5.982L4.724 6.288L4.758 6.254Q5.030 5.982 5.234 5.846L5.234 5.846L5.234 6.050L5.166 6.050L5.030 6.152L5.030 6.220L5.166 6.424L5.166 6.526Q5.268 6.356 5.404 6.220L5.404 6.220L5.982 5.608L6.356 5.404Q6.662 5.506 6.662 5.608L6.662 5.608L6.798 5.608Q8.566 4.316 10.334 3.670L10.334 3.670L10.334 3.806Q10.266 3.976 10.028 4.180L10.028 4.180Q9.960 4.282 9.892 4.282L9.892 4.282Q9.892 4.418 10.028 4.554L10.028 4.554Q9.314 6.866 8.430 8.600L8.430 8.600Q5.880 15.298 2.446 21.588L2.446 21.588Q2.446 21.622 2.480 21.707Q2.514 21.792 2.514 21.826L2.514 21.826L2.718 21.758Q2.956 21.656 3.262 21.520L3.262 21.520L3.330 21.520L3.330 21.656L3.466 21.656L3.636 21.588L3.772 21.588L3.772 21.894L3.534 22.438Q3.092 23.152 3.024 23.628L3.024 23.628L3.024 23.696L3.262 23.696L3.466 23.390Q4.350 22.370 4.724 21.520L4.724 21.520L5.472 21.282Q6.220 21.078 6.798 20.840L6.798 20.840L6.934 20.772Q8.430 20.194 9.144 19.820L9.144 19.820Q9.756 19.820 10.385 19.599Q11.014 19.378 11.524 18.970L11.524 18.970L11.524 18.902L11.150 19.072L11.082 19.072L11.082 18.902Q12.034 18.800 12.612 18.392L12.612 18.392Q14.278 17.134 15.944 15.910L15.944 15.910Q19.378 13.360 19.276 10.980L19.276 10.980Q18.630 9.926 17.950 9.348L17.950 9.348L17.712 9.042Q17.712 8.770 18.766 8.158ZM15.196 13.836L15.196 13.836L13.156 15.468Q11.524 16.522 10.708 16.964L10.708 16.964Q8.702 18.188 6.492 18.970L6.492 18.970L6.220 19.072L6.118 19.072Q6.186 18.834 7.818 15.536L7.818 15.536L9.382 12.408Q11.592 12.068 13.666 11.150L13.666 11.150L14.176 11.082Q14.788 10.946 15.366 11.116Q15.944 11.286 16.386 11.660L16.386 11.660L16.386 11.966Q15.842 13.496 15.196 13.836ZM16.454 7.036L16.454 7.036Q15.672 7.818 14.686 8.362L14.686 8.362Q12.680 9.008 11.218 9.790L11.218 9.790Q11.150 9.790 11.082 9.722L11.082 9.722L10.844 9.722L10.844 9.586Q10.844 8.940 11.218 8.464L11.218 8.464Q11.456 7.138 11.728 7.036L11.728 7.036L13.428 3.228Q13.428 3.058 13.717 2.905Q14.006 2.752 14.550 2.718L14.550 2.718L14.754 2.718L14.754 2.922Q15.502 2.786 16.114 2.786L16.114 2.786Q16.998 2.684 17.525 2.854Q18.052 3.024 18.154 3.432L18.154 3.432L18.154 3.602L18.324 3.602L18.324 3.092L18.460 3.092Q18.936 3.330 19.038 3.738L19.038 3.738L19.038 3.908Q19.038 4.350 18.698 4.724L18.698 4.724Q18.528 4.724 18.528 4.486L18.528 4.486L18.392 4.486L18.392 4.928Q17.406 6.526 16.896 6.526L16.896 6.526Q16.726 6.798 16.454 7.036Z"/>', + 'seti:bower': + '<path d="M22.745 11.388L22.745 11.388Q22.631 11.350 22.327 11.198L22.327 11.198Q21.871 11.008 21.567 10.932L21.567 10.932Q19.971 10.476 16.779 9.982L16.779 9.982L15.145 9.754Q14.993 9.754 14.613 9.678Q14.233 9.602 13.967 9.640L13.967 9.640Q14.081 9.146 14.309 8.956Q14.537 8.766 15.145 8.652L15.145 8.652Q15.221 8.728 15.278 8.899Q15.335 9.070 15.373 9.165Q15.411 9.260 15.487 9.298Q15.563 9.336 15.639 9.260L15.639 9.260L16.475 9.260Q17.539 9.070 18.261 8.500Q18.983 7.930 19.439 6.904L19.439 6.904Q19.667 5.954 19.781 5.574L19.781 5.574Q20.009 3.940 20.959 2.952L20.959 2.952L21.225 2.724Q20.351 2.496 19.211 2.781Q18.071 3.066 17.045 3.788L17.045 3.788Q15.943 4.624 15.411 5.802L15.411 5.802Q15.297 5.764 14.993 5.707Q14.689 5.650 14.575 5.612Q14.461 5.574 14.404 5.498Q14.347 5.422 14.347 5.346L14.347 5.346Q13.587 3.332 11.725 2.154L11.725 2.154Q11.041 1.736 10.091 1.584L10.091 1.584Q9.255 1.432 8.381 1.546L8.381 1.546Q4.695 2.078 2.339 5.004L2.339 5.004Q1.199 6.410 0.648 8.120Q0.097 9.830 0.211 11.654L0.211 11.654Q0.363 15.340 2.567 18.646L2.567 18.646Q2.947 19.178 4.011 20.204L4.011 20.204L4.467 20.660Q5.113 21.040 5.835 20.983Q6.557 20.926 7.089 20.432L7.089 20.432Q7.127 20.356 7.260 20.185Q7.393 20.014 7.431 19.938L7.431 19.938Q7.431 20.014 7.488 20.071Q7.545 20.128 7.545 20.204L7.545 20.204Q7.659 20.394 7.849 20.926L7.849 20.926Q8.039 21.534 8.153 21.724L8.153 21.724Q8.343 22.104 8.856 22.294Q9.369 22.484 9.825 22.332L9.825 22.332Q9.977 22.142 10.167 22.332L10.167 22.332Q10.889 22.674 11.611 22.332L11.611 22.332Q11.687 22.294 11.839 22.142L11.839 22.142Q12.029 21.990 12.181 21.933Q12.333 21.876 12.675 21.952L12.675 21.952L12.903 21.990Q13.435 21.876 13.701 21.648L13.701 21.648Q14.081 21.344 14.081 20.774L14.081 20.774L14.119 20.736Q14.119 20.660 14.195 20.660L14.195 20.660Q14.385 20.584 14.537 20.413Q14.689 20.242 14.689 20.052L14.689 20.052Q14.841 19.558 14.689 18.874L14.689 18.874L14.309 18.228Q13.815 17.240 13.511 16.860L13.511 16.860L13.397 16.746Q14.081 16.974 14.575 17.088L14.575 17.088Q15.639 17.316 16.209 16.746L16.209 16.746Q16.285 16.746 16.342 16.803Q16.399 16.860 16.475 16.860L16.475 16.860Q17.159 17.316 18.033 17.164Q18.907 17.012 19.439 16.404L19.439 16.404L19.667 16.404Q20.769 16.556 21.567 15.910L21.567 15.910Q21.795 15.682 21.909 15.530L21.909 15.530Q22.061 15.302 22.061 15.074L22.061 15.074L22.061 14.960Q22.973 14.884 23.391 14.466Q23.809 14.048 23.809 13.174L23.809 13.174Q23.733 12.490 23.505 12.072Q23.277 11.654 22.745 11.388ZM17.539 8.196L17.539 8.196Q16.817 8.538 15.867 8.538L15.867 8.538L15.829 8.538Q15.753 8.500 15.715 8.405Q15.677 8.310 15.620 8.082Q15.563 7.854 15.544 7.740Q15.525 7.626 15.544 7.607Q15.563 7.588 15.639 7.588L15.639 7.588Q15.943 7.588 16.019 7.664Q16.095 7.740 16.095 8.082L16.095 8.082Q16.285 7.816 16.361 7.778Q16.437 7.740 16.703 7.854L16.703 7.854Q16.817 7.892 17.064 7.949Q17.311 8.006 17.425 8.082L17.425 8.082L17.615 8.196Q17.615 8.196 17.539 8.196ZM15.981 5.688L15.981 5.688Q16.475 4.814 17.767 3.788L17.767 3.788Q18.755 3.218 19.667 3.218L19.667 3.218Q19.439 3.446 19.325 3.674L19.325 3.674Q19.059 4.016 18.907 4.890L18.907 4.890L18.831 5.346Q18.603 6.524 18.375 7.132L18.375 7.132Q18.375 7.284 18.223 7.436L18.223 7.436Q18.147 7.550 18.147 7.588L18.147 7.588Q17.843 7.322 17.235 6.866L17.235 6.866L16.931 6.638L16.931 6.410L17.083 6.144Q17.539 5.384 17.805 5.004L17.805 5.004Q18.223 4.396 18.717 4.054L18.717 4.054Q17.919 4.358 17.387 5.004L17.387 5.004Q17.007 5.422 16.475 6.410L16.475 6.410L15.867 6.068Q15.867 5.992 15.924 5.878Q15.981 5.764 15.981 5.688ZM12.789 7.702L12.789 7.702Q12.789 6.676 13.245 6.068L13.245 6.068Q13.245 5.992 13.397 5.954L13.397 5.954L13.511 5.954Q15.221 6.106 16.589 7.132L16.589 7.132Q16.703 7.170 16.874 7.360Q17.045 7.550 17.159 7.588L17.159 7.588Q17.045 7.550 16.760 7.493Q16.475 7.436 16.361 7.360L16.361 7.360Q15.297 7.132 14.461 7.474L14.461 7.474Q13.853 7.930 12.789 7.702L12.789 7.702Q13.017 7.968 13.302 8.006Q13.587 8.044 13.967 7.968L13.967 7.968Q14.271 7.968 14.727 7.778L14.727 7.778L14.917 7.740Q14.917 7.778 14.879 7.892L14.879 7.892L14.803 7.968Q14.423 8.234 13.359 8.652L13.359 8.652L13.017 8.804L12.903 8.804Q12.789 8.424 12.789 7.702ZM9.217 4.852L9.217 4.852Q10.053 4.852 10.699 5.498Q11.345 6.144 11.345 7.018Q11.345 7.892 10.737 8.519Q10.129 9.146 9.236 9.146Q8.343 9.146 7.716 8.519Q7.089 7.892 7.089 6.980Q7.089 6.068 7.697 5.460Q8.305 4.852 9.217 4.852ZM14.689 12.110L14.689 12.110Q15.639 12.338 16.361 12.338L16.361 12.338L18.489 12.718Q18.679 12.718 18.717 12.813Q18.755 12.908 18.603 13.060L18.603 13.060Q18.413 13.326 18.033 13.478Q17.653 13.630 17.311 13.554L17.311 13.554L17.045 13.554Q17.159 13.706 17.083 13.934Q17.007 14.162 16.817 14.238L16.817 14.238Q16.361 14.732 15.639 14.732L15.639 14.732Q15.525 14.732 15.221 14.675Q14.917 14.618 14.803 14.618L14.803 14.618Q14.727 14.960 14.347 15.150Q13.967 15.340 13.454 15.302Q12.941 15.264 12.561 14.960L12.561 14.960Q12.789 15.682 12.903 16.138L12.903 16.138L12.903 16.518Q12.713 17.848 11.763 18.741Q10.813 19.634 9.445 19.710L9.445 19.710Q6.861 19.900 4.695 18.304L4.695 18.304Q2.833 17.088 1.845 14.960L1.845 14.960Q1.845 14.922 1.788 14.846Q1.731 14.770 1.731 14.732L1.731 14.732Q2.681 14.960 3.061 15.074L3.061 15.074Q3.783 15.188 4.277 15.112L4.277 15.112Q4.961 14.998 5.531 14.618L5.531 14.618L5.797 14.618Q7.165 14.998 8.381 14.846L8.381 14.846Q9.331 14.694 10.129 14.162L10.129 14.162Q10.851 13.668 11.611 12.832L11.611 12.832Q11.953 12.490 12.447 11.540L12.447 11.540Q12.675 11.160 13.131 10.704L13.131 10.704L13.397 10.704L16.361 11.046L17.615 11.274Q19.325 11.616 20.275 11.768L20.275 11.768L20.313 11.768Q20.389 11.806 20.389 11.882L20.389 11.882L19.173 11.958Q16.171 12.224 14.689 12.110ZM9.217 8.196L9.217 8.196Q9.787 8.196 10.148 7.873Q10.509 7.550 10.528 7.018Q10.547 6.486 10.167 6.144Q9.787 5.802 9.236 5.802Q8.685 5.802 8.305 6.182Q7.925 6.562 7.925 7.018Q7.925 7.474 8.286 7.835Q8.647 8.196 9.217 8.196ZM8.495 6.068L8.495 6.068Q8.571 5.992 8.780 5.935Q8.989 5.878 9.103 5.802L9.103 5.802L9.711 6.068Q9.863 6.144 9.863 6.315Q9.863 6.486 9.692 6.657Q9.521 6.828 9.141 6.828Q8.761 6.828 8.381 6.638L8.381 6.638Q8.191 6.220 8.495 6.068Z"/>', + 'seti:docker': + '<path d="M10.109 6.473L10.109 4.427L12.188 4.427L12.188 6.473L10.109 6.473ZM10.109 8.849L10.109 6.803L12.188 6.803L12.188 8.849L10.109 8.849ZM10.109 11.324L10.109 9.277L12.188 9.277L12.188 11.324L10.109 11.324ZM7.733 8.849L7.733 6.803L9.812 6.803L9.812 8.849L7.733 8.849ZM7.733 11.324L7.733 9.277L9.812 9.277L9.812 11.324L7.733 11.324ZM5.258 8.849L5.258 6.803L7.337 6.803L7.337 8.849L5.258 8.849ZM5.258 11.324L5.258 9.277L7.337 9.277L7.337 11.324L5.258 11.324ZM2.882 11.324L2.882 9.277L4.961 9.277L4.961 11.324L2.882 11.324ZM12.584 11.324L12.584 9.277L14.663 9.277L14.663 11.324L12.584 11.324ZM23.111 9.575L23.111 9.575Q22.286 9.377 21.758 9.377L21.758 9.377Q21.032 9.509 20.735 8.750Q20.438 7.991 19.811 7.495L19.811 7.495Q19.349 6.968 18.920 7.083Q18.491 7.198 18.260 7.826L18.260 7.826Q17.963 8.816 18.161 10.103L18.161 10.103Q18.326 10.796 18.177 11.043Q18.029 11.291 17.319 11.456Q16.610 11.620 8.492 11.654L8.492 11.654Q4.433 11.654 0.539 11.620L0.539 11.620L0.539 11.620Q0.374 11.620 0.291 11.934Q0.209 12.248 0.209 12.677L0.209 12.677Q0.209 13.238 0.308 13.997L0.308 13.997Q0.407 14.987 0.638 15.449L0.638 15.449Q1.430 17.230 2.717 18.287L2.717 18.287Q4.136 19.442 5.984 19.574L5.984 19.574L10.637 19.574Q12.782 19.508 14.696 18.485L14.696 18.485Q16.412 17.593 18.062 15.878L18.062 15.878Q19.382 14.360 20.108 12.776L20.108 12.776Q20.405 12.215 21.065 12.082Q21.725 11.951 22.055 11.852L22.055 11.852Q22.550 11.720 22.913 11.422L22.913 11.422Q23.012 11.225 23.309 10.928L23.309 10.928Q23.837 10.532 23.787 10.136Q23.738 9.739 23.111 9.575ZM7.733 14.822L7.733 14.822Q8.063 14.822 8.310 15.053Q8.558 15.284 8.558 15.663Q8.558 16.043 8.343 16.257Q8.129 16.471 7.766 16.471Q7.403 16.471 7.155 16.257Q6.908 16.043 6.908 15.663Q6.908 15.284 7.155 15.053Q7.403 14.822 7.733 14.822ZM2.684 17.099L2.684 17.099Q3.047 17.066 3.740 17.099L3.740 17.099Q4.664 17.132 5.060 17.000L5.060 17.000Q5.819 16.736 6.330 16.917Q6.842 17.099 7.238 17.825L7.238 17.825Q7.403 18.188 7.799 18.485L7.799 18.485Q8.030 18.650 8.624 18.980L8.624 18.980L8.987 19.178Q7.271 19.409 5.555 18.831Q3.839 18.254 2.684 17.099Z"/>', + 'seti:code-climate': + '<path d="M15.627 15.494L15.813 15.742Q15.782 15.804 15.689 15.897L15.689 15.897L13.364 18.098Q13.271 18.222 13.178 18.207Q13.085 18.191 12.992 18.067L12.992 18.067L8.094 13.386L3.320 18.005Q3.134 18.160 3.010 18.160Q2.886 18.160 2.731 18.005L2.731 18.005Q2.204 17.478 1.057 16.393L1.057 16.393L0.282 15.649L0.499 15.494Q0.778 15.339 0.871 15.215L0.871 15.215Q4.653 11.619 7.846 8.550L7.846 8.550Q8.001 8.395 8.110 8.395Q8.218 8.395 8.373 8.519L8.373 8.519L15.627 15.494ZM11.535 10.038L15.968 5.791Q16.681 6.473 18.107 7.837L18.107 7.837L23.718 13.200L21.083 15.742L15.968 10.875L14.170 12.580L11.535 10.038Z"/>', + 'seti:eslint': + '<path d="M23.862 12.000L18.570 1.884L5.862 1.884L0.138 12.000L5.862 22.116L18.570 22.116L23.862 12.000ZM19.146 16.176L12.054 20.208L4.962 16.176L4.962 8.184L12.054 3.792L19.146 8.184L19.146 16.176ZM12.054 6.492L7.338 9.408L7.338 14.808L12.054 17.508L16.770 14.808L16.770 9.408L12.054 6.492Z"/>', + 'seti:firebase': + '<path d="M12.297 4.025L14.640 8.777L12.297 10.955L10.119 6.566L11.241 4.025Q11.472 3.662 11.769 3.662Q12.066 3.662 12.297 4.025L12.297 4.025ZM10.119 6.566L12.297 10.955L3.552 19.073L10.119 6.566ZM3.552 19.073L17.214 5.444Q17.511 5.114 17.792 5.213Q18.072 5.312 18.171 5.741L18.171 5.741L20.448 18.974L12.891 23.495Q12.726 23.594 12.297 23.660L12.297 23.660L11.934 23.693L11.571 23.660Q11.208 23.594 11.043 23.495L11.043 23.495L3.552 19.073ZM7.215 0.659L10.119 6.566L3.552 19.073L6.489 0.791Q6.555 0.362 6.770 0.312Q6.984 0.263 7.215 0.659L7.215 0.659Z"/>', + 'seti:firefox': + '<path d="M23.928 10.888L23.886 10.594Q23.718 9.544 23.634 8.998L23.634 8.998L23.214 9.880L23.130 9.880Q23.550 6.058 20.946 3.790L20.946 3.790L20.862 4.000Q20.442 3.454 19.434 2.740L19.434 2.740Q19.308 3.118 19.644 3.454L19.644 3.454Q20.862 4.546 21.576 5.806L21.576 5.806L21.702 6.016Q21.282 5.428 20.232 4.420L20.232 4.420L19.812 4.000Q18.636 2.740 16.746 2.152L16.746 2.152L16.200 1.984L16.662 2.404Q17.544 3.076 17.964 3.454L17.964 3.454Q18.468 3.958 18.909 4.525Q19.350 5.092 19.392 5.302L19.392 5.302Q18.342 4.462 17.376 4.378L17.376 4.378Q19.980 6.730 19.686 10.132L19.686 10.132Q19.308 9.418 18.720 9.040L18.720 9.040L18.888 10.636Q19.014 11.854 18.888 12.484L18.888 12.484L18.636 13.618L18.342 13.030L18.216 13.618Q17.964 14.542 17.838 15.004L17.838 15.004Q17.544 16.054 16.872 16.684L16.872 16.684Q16.704 16.810 16.494 16.936L16.494 16.936Q16.452 16.978 16.368 16.978L16.368 16.978L16.284 16.978L16.284 16.684L16.200 16.684Q16.074 16.684 16.032 16.726L16.032 16.726Q15.864 16.894 15.696 17.062L15.696 17.062Q15.402 17.482 14.898 17.776L14.898 17.776L14.982 17.440L13.890 17.692Q13.218 17.818 12.882 17.860L12.882 17.860Q12.336 17.944 11.874 17.860L11.874 17.860Q11.160 17.734 10.824 17.356L10.824 17.356L11.538 17.356Q11.412 17.230 11.286 17.188L11.286 17.188L10.026 16.894Q9.438 16.726 9.165 16.558Q8.892 16.390 8.430 15.886L8.430 15.886L8.346 15.802Q7.044 14.542 7.338 12.484L7.338 12.484Q7.422 11.854 7.506 11.560L7.506 11.560Q7.674 11.098 8.052 10.804L8.052 10.804Q7.632 10.510 7.170 10.510L7.170 10.510Q6.498 10.468 5.910 10.909Q5.322 11.350 5.112 12.022L5.112 12.022Q4.566 13.618 5.742 15.172L5.742 15.172L5.868 15.340Q5.112 14.710 4.839 13.639Q4.566 12.568 4.986 11.602L4.986 11.602Q5.322 10.804 6.015 10.405Q6.708 10.006 7.485 10.132Q8.262 10.258 8.850 10.846L8.850 10.846L9.060 11.098Q9.186 10.720 9.165 10.237Q9.144 9.754 8.934 9.460L8.934 9.460Q7.884 8.032 8.199 6.457Q8.514 4.882 9.774 3.664L9.774 3.664L9.942 3.496Q9.060 3.286 8.094 3.874Q7.128 4.462 6.204 5.722L6.204 5.722L6.372 4.714L6.036 4.672Q4.104 4.420 2.634 5.638L2.634 5.638Q1.206 6.772 0.576 8.830L0.576 8.830L0.072 10.636L0.114 10.636L0.450 10.132Q0.282 11.056 0.198 12.148Q0.114 13.240 0.156 13.786L0.156 13.786L0.408 13.030Q0.954 17.062 3.516 19.750L3.516 19.750Q4.776 21.052 6.855 22.249Q8.934 23.446 9.858 23.362L9.858 23.362L9.396 23.068Q9.648 23.110 10.110 23.236L10.110 23.236L10.530 23.320L11.916 23.656L12.672 23.656L12.294 23.320L13.596 23.236Q15.528 23.110 17.418 22.438L17.418 22.438Q17.964 22.270 18.468 21.808L18.468 21.808Q18.804 21.472 19.266 20.884L19.266 20.884Q19.434 20.632 19.644 20.506L19.644 20.506Q21.492 19.498 22.542 17.608L22.542 17.608Q23.046 16.726 22.794 15.592L22.794 15.592Q22.752 15.382 22.836 15.172L22.836 15.172L23.088 14.584Q23.382 13.996 23.487 13.681Q23.592 13.366 23.760 12.694L23.760 12.694L23.928 12.064L23.928 10.888ZM8.178 12.946L7.800 12.694Q7.632 13.618 8.052 14.542Q8.472 15.466 9.270 15.928L9.270 15.928Q9.354 15.970 9.480 15.970L9.480 15.970Q11.412 16.096 12.798 14.962L12.798 14.962L13.092 14.710Q13.470 14.374 14.058 14.458L14.058 14.458Q14.268 14.500 14.373 14.395Q14.478 14.290 14.436 14.080L14.436 14.080Q14.352 13.618 13.932 13.366L13.932 13.366Q12.630 12.694 11.412 13.366L11.412 13.366Q11.076 13.576 10.740 13.660L10.740 13.660Q9.942 13.870 9.018 13.408L9.018 13.408Q8.766 13.282 8.178 12.946L8.178 12.946ZM3.894 4.126L3.978 4.084Q4.062 4.000 4.104 3.958L4.104 3.958Q8.430-0.074 14.100 1.102L14.100 1.102Q15.024 1.312 16.830 1.858L16.830 1.858L18.006 2.194Q15.822 0.682 13.134 0.409Q10.446 0.136 7.905 1.018Q5.364 1.900 3.558 3.832L3.558 3.832L3.894 4.126ZM11.664 7.234L11.664 7.234Q11.706 6.982 11.622 6.898Q11.538 6.814 11.328 6.772L11.328 6.772Q10.908 6.730 10.026 6.730L10.026 6.730L9.816 6.730Q9.438 6.688 9.270 6.646L9.270 6.646Q8.934 6.604 8.724 6.352L8.724 6.352Q8.472 6.940 8.682 7.864Q8.892 8.788 9.354 9.208L9.354 9.208L9.858 8.914Q10.614 8.494 11.034 8.284L11.034 8.284Q11.622 7.990 11.664 7.234ZM3.642 4.420L3.642 4.420Q2.844 3.748 2.760 2.614L2.760 2.614Q2.130 3.286 1.836 4.168L1.836 4.168Q1.626 4.882 1.584 5.890L1.584 5.890Q2.550 4.882 3.642 4.420Z"/>', + 'seti:gitlab': + '<path d="M23.424 9.639L23.424 9.639L23.382 9.555L20.190 1.155Q20.064 0.903 19.833 0.756Q19.602 0.609 19.329 0.630Q19.056 0.651 18.846 0.819Q18.636 0.987 18.552 1.239L18.552 1.239L16.410 7.875L7.590 7.875L5.448 1.239Q5.364 0.987 5.154 0.819Q4.944 0.651 4.671 0.630Q4.398 0.609 4.167 0.756Q3.936 0.903 3.852 1.155L3.852 1.155L0.576 9.597Q-0.138 11.487 0.408 13.398Q0.954 15.309 2.550 16.527L2.550 16.527L7.506 20.223L11.412 23.163Q11.664 23.373 12.000 23.373Q12.336 23.373 12.588 23.163L12.588 23.163L21.450 16.527Q23.046 15.309 23.592 13.398Q24.138 11.487 23.424 9.639Z"/>', + 'seti:grunt': + '<path d="M19.485 12.265L19.485 12.265Q19.596 12.228 19.855 12.117L19.855 12.117Q20.632 11.747 21.002 11.488L21.002 11.488Q21.483 11.118 21.668 10.637Q21.853 10.156 21.668 9.712Q21.483 9.268 21.002 9.046L21.002 9.046Q20.706 8.898 20.521 8.343L20.521 8.343Q20.373 7.344 20.891 6.493L20.891 6.493Q21.483 5.642 21.113 5.013Q20.743 4.384 19.596 4.310L19.596 4.310L19.485 4.310L19.374 4.199L19.374 4.125Q19.263 3.607 19.300 3.385L19.300 3.385Q19.374 2.978 19.818 2.682L19.818 2.682Q20.077 2.571 20.743 2.349L20.743 2.349Q21.002 2.238 21.335 2.238L21.335 2.238Q21.335 2.090 21.224 2.090L21.224 2.090L21.224 2.090Q20.669 1.461 19.818 1.202L19.818 1.202Q19.078 0.980 18.227 1.054L18.227 1.054Q17.265 1.165 16.488 1.646L16.488 1.646Q15.896 2.016 15.193 2.793L15.193 2.793Q15.045 3.126 14.638 2.904L14.638 2.904Q14.416 2.793 14.416 2.571L14.416 2.571Q14.416 2.460 14.471 2.220Q14.527 1.979 14.527 1.868L14.527 1.868L14.860 1.165Q14.453 1.165 14.046 1.350L14.046 1.350Q13.824 1.461 13.343 1.757L13.343 1.757L13.121 1.868Q12.862 1.461 12.843 1.091Q12.825 0.721 13.010 0.240L13.010 0.240Q12.159 0.536 11.715 0.906L11.715 0.906Q11.197 1.387 11.049 2.090L11.049 2.090Q10.864 1.942 10.827 1.646L10.827 1.646Q10.790 1.461 10.790 1.128L10.790 1.128L10.827 0.832L10.716 0.832Q10.642 0.832 10.586 0.888Q10.531 0.943 10.457 0.943L10.457 0.943Q9.606 1.646 9.421 2.571L9.421 2.571Q9.421 2.645 9.365 2.756Q9.310 2.867 9.310 2.904L9.310 2.904Q9.273 2.867 9.143 2.812Q9.014 2.756 8.977 2.682L8.977 2.682Q8.755 2.497 8.292 2.109Q7.830 1.720 7.571 1.535L7.571 1.535Q6.535 0.943 5.554 0.925Q4.574 0.906 3.538 1.424L3.538 1.424L2.613 2.349Q2.835 2.460 3.297 2.571Q3.760 2.682 3.982 2.793L3.982 2.793Q4.611 2.978 4.777 3.348Q4.944 3.718 4.685 4.421L4.685 4.421Q4.574 4.421 4.352 4.477Q4.130 4.532 3.982 4.532L3.982 4.532Q3.390 4.717 3.131 5.106Q2.872 5.494 2.946 6.049L2.946 6.049Q3.020 6.197 3.186 6.549Q3.353 6.900 3.427 7.085L3.427 7.085Q3.427 7.122 3.482 7.252Q3.538 7.381 3.538 7.418L3.538 7.418L3.538 8.602Q3.538 8.824 3.057 9.268L3.057 9.268L2.872 9.453Q2.465 9.823 2.391 10.082L2.391 10.082Q2.132 10.489 2.317 10.970Q2.502 11.451 2.946 11.821L2.946 11.821Q3.538 12.265 4.463 12.635L4.463 12.635Q5.388 13.079 5.388 14.004L5.388 14.004Q5.388 15.299 5.277 15.965L5.277 15.965Q5.277 16.076 5.203 16.372L5.203 16.372Q5.166 16.705 5.166 16.890L5.166 16.890Q4.574 16.446 4.259 15.984Q3.945 15.521 3.871 14.929L3.871 14.929Q2.835 15.817 2.835 16.779L2.835 16.779Q2.650 18.000 3.168 18.962L3.168 18.962Q3.723 19.998 5.055 20.479L5.055 20.479Q5.166 20.479 5.388 20.738L5.388 20.738Q6.424 22.440 8.496 22.810L8.496 22.810Q8.755 22.810 8.755 22.921L8.755 22.921Q9.643 23.476 10.642 23.661L10.642 23.661Q11.530 23.809 12.677 23.735L12.677 23.735Q13.417 23.624 13.787 23.513L13.787 23.513Q14.342 23.365 14.749 23.032L14.749 23.032Q14.823 22.995 14.989 22.921Q15.156 22.847 15.193 22.810L15.193 22.810Q17.117 22.477 18.227 20.849L18.227 20.849L18.560 20.479Q19.707 20.109 20.188 19.332L20.188 19.332Q20.595 18.777 20.743 18.000L20.743 18.000Q20.854 17.334 20.780 16.668L20.780 16.668Q20.669 16.187 20.428 15.799Q20.188 15.410 19.707 14.929L19.707 14.929Q19.559 15.558 19.263 16.021Q18.967 16.483 18.449 16.890L18.449 16.890Q18.338 15.854 18.338 13.893L18.338 13.893Q18.523 13.227 18.782 12.839Q19.041 12.450 19.485 12.265ZM14.971 18.407L9.791 18.407L14.971 18.407Z"/>', + 'seti:gulp': + '<path d="M15.840 18.343L15.840 18.343Q15.660 18.643 15.465 19.018Q15.270 19.393 15.270 19.663L15.270 19.663L15 22.573Q15 23.083 14.520 23.233L14.520 23.233Q14.190 23.323 13.500 23.563Q12.810 23.803 12.480 23.893L12.480 23.893L11.430 23.893Q11.400 23.893 11.250 23.848Q11.100 23.803 11.070 23.803L11.070 23.803Q9.930 23.413 9.480 23.143L9.480 23.143Q9.180 22.843 9.180 22.663L9.180 22.663Q9.090 21.913 9.090 20.503L9.090 20.503Q9.090 19.753 9.030 19.423L9.030 19.423Q8.910 18.823 8.520 18.463L8.520 18.463L8.520 18.343Q12.060 19.333 15.840 18.343ZM17.250 6.463L17.250 6.463Q17.190 7.093 17.055 8.413Q16.920 9.733 16.890 10.393L16.890 10.393L16.230 17.233Q16.230 18.103 15.270 18.253L15.270 18.253Q14.250 18.463 12.570 18.643L12.570 18.643Q10.470 18.793 8.640 18.253L8.640 18.253Q8.310 18.193 8.160 17.953L8.160 17.953Q8.070 17.803 7.980 17.413L7.980 17.413Q7.980 16.843 7.770 16.123L7.770 16.123L7.410 12.643Q7.410 12.583 7.365 12.493Q7.320 12.403 7.320 12.373L7.320 12.373Q7.260 11.383 6.960 9.493L6.960 9.493L6.750 7.963Q6.660 7.483 6.660 6.553L6.660 6.553Q12.120 7.693 17.250 6.463ZM6.660 5.893L6.660 5.893Q7.020 5.713 7.230 5.713L7.230 5.713L9.840 5.413Q9.900 5.413 10.080 5.323L10.080 5.323L10.230 5.233Q10.140 4.993 10.020 4.513L10.020 4.513Q9.900 3.943 9.780 3.643L9.780 3.643Q9.600 3.193 9.270 2.893L9.270 2.893Q8.910 2.503 8.205 1.708Q7.500 0.913 7.140 0.553L7.140 0.553Q7.440 0.223 7.560 0.148Q7.680 0.073 7.785 0.133Q7.890 0.193 8.160 0.463L8.160 0.463L8.520 0.823Q8.940 1.303 9.180 1.483L9.180 1.483Q10.770 2.773 11.070 4.753L11.070 4.753Q11.190 5.173 11.400 5.293Q11.610 5.413 12 5.413L12 5.413L16.680 5.713Q16.830 5.713 17.130 5.803L17.130 5.803L17.340 5.893Q16.590 6.463 14.070 6.673L14.070 6.673Q11.760 6.883 9.480 6.673L9.480 6.673Q7.110 6.433 6.660 5.893Z"/>', + 'seti:ionic': + '<path d="M22.555 6.765L22.555 6.765Q23.277 6.081 23.277 4.789Q23.277 3.497 22.384 2.585Q21.491 1.673 20.199 1.673L20.199 1.673Q19.477 1.673 18.527 2.167L18.527 2.167Q15.753 0.115 11.991 0.115L11.991 0.115Q8.761 0.115 6.025 1.749L6.025 1.749Q3.327 3.345 1.731 6.043L1.731 6.043Q0.097 8.779 0.116 12.009Q0.135 15.239 1.731 17.975L1.731 17.975Q3.327 20.673 6.025 22.269L6.025 22.269Q8.761 23.903 11.991 23.884Q15.221 23.865 17.957 22.269L17.957 22.269Q20.655 20.673 22.251 17.975L22.251 17.975Q23.885 15.239 23.885 12.009L23.885 12.009Q23.885 9.197 22.555 6.765ZM11.991 21.965L11.991 21.965Q9.255 22.003 6.937 20.597L6.937 20.597Q4.657 19.305 3.346 17.006Q2.035 14.707 2.035 12.009Q2.035 9.311 3.384 7.031Q4.733 4.751 7.013 3.402Q9.293 2.053 11.991 2.053L11.991 2.053Q15.069 2.015 17.463 3.687L17.463 3.687Q17.235 4.409 17.197 4.751L17.197 4.751Q17.235 6.043 18.109 6.955Q18.983 7.867 20.313 7.867L20.313 7.867Q20.769 7.867 21.035 7.715L21.035 7.715Q21.985 9.843 21.985 12.009L21.985 12.009Q21.985 14.745 20.655 17.044Q19.325 19.343 17.026 20.654Q14.727 21.965 11.991 21.965ZM11.991 7.145L11.991 7.145Q10.661 7.145 9.540 7.791Q8.419 8.437 7.735 9.539Q7.051 10.641 7.032 11.990Q7.013 13.339 7.659 14.460Q8.305 15.581 9.407 16.265Q10.509 16.949 11.858 16.968Q13.207 16.987 14.328 16.341Q15.449 15.695 16.133 14.593Q16.817 13.491 16.836 12.142Q16.855 10.793 16.209 9.634Q15.563 8.475 14.442 7.810Q13.321 7.145 11.991 7.145Z"/>', + 'seti:platformio': + '<path d="M16.482 5.484L16.482 5.484L17.166 3.036Q17.706 3 18.084 2.604Q18.462 2.208 18.462 1.668Q18.462 1.128 18.048 0.714Q17.634 0.300 17.058 0.300Q16.482 0.300 16.068 0.714Q15.654 1.128 15.654 1.668L15.654 1.668Q15.654 2.028 15.834 2.352Q16.014 2.676 16.338 2.856L16.338 2.856L15.618 5.268Q14.754 5.052 13.818 4.944L13.818 4.944Q13.134 4.836 12.486 4.800L12.486 4.800L11.982 4.800L11.694 4.944L11.694 23.592L11.982 23.700Q12.738 23.700 14.358 22.764L14.358 22.764Q16.086 21.756 17.706 20.244L17.706 20.244Q19.614 18.516 20.694 16.644L20.694 16.644Q22.026 14.448 22.026 12.396L22.026 12.396Q22.026 9.552 20.262 7.716L20.262 7.716Q18.858 6.240 16.482 5.484ZM14.502 17.508L14.502 17.508Q13.710 16.248 13.728 14.232Q13.746 12.216 14.718 10.668L14.718 10.668Q15.798 8.904 17.742 8.508L17.742 8.508Q18.678 8.364 19.506 8.940L19.506 8.940Q20.406 9.516 20.694 10.668L20.694 10.668Q21.054 11.856 20.334 13.368L20.334 13.368Q19.686 14.664 18.426 15.888L18.426 15.888Q17.238 17.004 16.086 17.508Q14.934 18.012 14.502 17.508ZM17.022 12.252L17.022 12.252Q16.482 12.252 16.104 12.612Q15.726 12.972 15.726 13.494Q15.726 14.016 16.104 14.376Q16.482 14.736 17.004 14.736Q17.526 14.736 17.904 14.376Q18.282 14.016 18.282 13.494Q18.282 12.972 17.904 12.612Q17.526 12.252 17.022 12.252ZM17.382 13.404L17.382 13.404Q17.274 13.404 17.166 13.314Q17.058 13.224 17.058 13.098Q17.058 12.972 17.166 12.864Q17.274 12.756 17.400 12.756Q17.526 12.756 17.616 12.864Q17.706 12.972 17.706 13.098Q17.706 13.224 17.616 13.314Q17.526 13.404 17.382 13.404ZM8.346 5.304L8.346 5.304L7.662 2.820Q7.950 2.640 8.130 2.334Q8.310 2.028 8.310 1.668L8.310 1.668Q8.310 1.092 7.896 0.696Q7.482 0.300 6.888 0.300Q6.294 0.300 5.898 0.696Q5.502 1.092 5.502 1.650Q5.502 2.208 5.898 2.622Q6.294 3.036 6.906 3.036L6.906 3.036L7.590 5.520Q5.178 6.312 3.774 7.752L3.774 7.752Q1.974 9.588 1.974 12.396L1.974 12.396Q2.010 14.484 3.306 16.680L3.306 16.680Q4.422 18.552 6.330 20.280L6.330 20.280Q7.914 21.792 9.642 22.800L9.642 22.800Q11.262 23.700 11.982 23.700L11.982 23.700L11.982 4.800L11.478 4.836Q10.830 4.872 10.182 4.944L10.182 4.944Q9.210 5.088 8.346 5.304ZM9.750 17.508L9.750 17.508Q9.354 18.012 8.202 17.508Q7.050 17.004 5.862 15.888L5.862 15.888Q4.602 14.664 3.954 13.368L3.954 13.368Q3.234 11.856 3.594 10.668L3.594 10.668Q3.882 9.516 4.782 8.940L4.782 8.940Q5.610 8.364 6.546 8.508L6.546 8.508Q8.454 8.904 9.570 10.668L9.570 10.668Q10.506 12.216 10.542 14.232Q10.578 16.248 9.750 17.508ZM7.194 12.288L7.194 12.288Q6.654 12.288 6.276 12.648Q5.898 13.008 5.898 13.530Q5.898 14.052 6.276 14.412Q6.654 14.772 7.194 14.772Q7.734 14.772 8.112 14.412Q8.490 14.052 8.490 13.530Q8.490 13.008 8.112 12.648Q7.734 12.288 7.194 12.288ZM6.798 13.440L6.798 13.440Q6.654 13.440 6.564 13.350Q6.474 13.260 6.474 13.134Q6.474 13.008 6.564 12.900Q6.654 12.792 6.798 12.792Q6.942 12.792 7.032 12.900Q7.122 13.008 7.122 13.134Q7.122 13.260 7.032 13.350Q6.942 13.440 6.798 13.440Z"/>', + 'seti:rollup': + '<path d="M20.108 22.374L20.108 22.374L16.580 15.276Q16.454 15.066 16.475 14.961Q16.496 14.856 16.706 14.772L16.706 14.772Q17.882 14.184 18.680 13.176L18.680 13.176Q19.730 11.916 20.213 10.362Q20.696 8.808 20.486 7.149Q20.276 5.490 19.562 4.272L19.562 4.272Q19.520 4.188 19.457 4.062Q19.394 3.936 19.310 3.852L19.310 3.852Q18.974 3.516 18.428 3.222L18.428 3.222Q18.050 3.054 17.336 2.802L17.336 2.802Q16.538 2.676 16.160 2.676L16.160 2.676Q15.530 2.634 15.026 2.781Q14.522 2.928 14.249 3.054Q13.976 3.180 13.808 3.474L13.808 3.474Q12.884 4.566 13.262 5.952L13.262 5.952Q13.472 6.666 13.934 7.296L13.934 7.296Q14.270 7.758 14.984 8.304L14.984 8.304Q15.530 8.598 15.908 8.724L15.908 8.724Q16.160 8.724 16.307 8.661Q16.454 8.598 16.580 8.304L16.580 8.304Q16.706 8.178 16.706 7.800L16.706 7.800Q16.706 7.296 16.412 6.498L16.412 6.498Q16.160 5.952 16.160 5.700L16.160 5.700Q16.328 6.162 16.790 7.002L16.790 7.002L17.084 7.548Q17.210 7.842 17.168 8.199Q17.126 8.556 16.958 8.850L16.958 8.850L16.706 9.102Q16.370 9.354 15.719 9.963Q15.068 10.572 14.732 10.824L14.732 10.824Q13.346 12 12.380 13.176L12.380 13.176Q11.288 14.478 9.482 17.124L9.482 17.124Q8.978 17.796 8.180 19.140L8.180 19.140L7.634 20.022Q7.382 20.400 6.920 21.177Q6.458 21.954 6.227 22.353Q5.996 22.752 5.492 23.508L5.492 23.508L5.282 23.802L20.486 23.802Q20.780 23.802 20.885 23.634Q20.990 23.466 20.906 23.172L20.906 23.172Q20.528 22.962 20.360 22.752L20.360 22.752Q20.234 22.626 20.108 22.374ZM7.508 10.824L7.508 10.824Q7.802 10.320 8.348 9.270L8.348 9.270Q9.818 6.666 10.658 5.448L10.658 5.448Q11.708 3.852 12.212 3.222L12.212 3.222Q13.052 2.382 13.934 2.004L13.934 2.004Q15.320 1.752 16.160 1.878L16.160 1.878Q17.798 2.088 18.932 3.222L18.932 3.222L19.184 3.474L19.184 3.348Q16.664 0.198 12.884 0.198L12.884 0.198L3.434 0.198Q3.056 0.198 3.056 0.702L3.056 0.702L3.056 19.602Q3.686 17.922 5.534 14.478L5.534 14.478Q6.206 13.176 7.508 10.824Z"/>', + 'seti:stylelint': + '<path d="M10.540 4.860L10.540 3.060L13.540 3.060L13.540 4.860L10.540 4.860ZM17.060 1.060L17.100 7.020L13.940 5.020Q13.860 4.980 13.860 3.900L13.860 3.900L13.900 2.820L17.060 1.060ZM6.980 0.980L6.900 6.940L10.100 4.980Q10.180 4.900 10.180 3.820L10.180 3.820L10.140 2.780L6.980 0.980ZM11.140 7.540L11.140 7.540Q11.140 7.220 11.380 6.980Q11.620 6.740 11.960 6.740Q12.300 6.740 12.520 6.980Q12.740 7.220 12.740 7.560Q12.740 7.900 12.520 8.140Q12.300 8.380 11.960 8.380Q11.620 8.380 11.380 8.140Q11.140 7.900 11.140 7.540ZM11.140 12.540L11.140 12.540Q11.140 12.180 11.380 11.940Q11.620 11.700 11.960 11.700Q12.300 11.700 12.520 11.940Q12.740 12.180 12.740 12.520Q12.740 12.860 12.520 13.100Q12.300 13.340 11.960 13.340Q11.620 13.340 11.380 13.100Q11.140 12.860 11.140 12.540ZM11.140 17.500L11.140 17.500Q11.140 17.180 11.380 16.940Q11.620 16.700 11.960 16.700Q12.300 16.700 12.520 16.940Q12.740 17.180 12.740 17.520Q12.740 17.860 12.520 18.100Q12.300 18.340 11.960 18.340Q11.620 18.340 11.380 18.100Q11.140 17.860 11.140 17.500ZM21.780 5.580L23.940 3.620L20.500 0.420L18.580 0.420L17.580 3.980L17.500 7.740L16.580 7.220L12.220 23.620L23.300 7.380L21.780 5.580ZM2.220 5.540L0.060 3.540L3.500 0.380L5.460 0.380L6.460 3.900L6.500 7.700L7.420 7.140L11.780 23.540L0.700 7.340L2.220 5.540ZM7.300 7.420L7.300 7.420Z"/>', + 'seti:yarn': + '<path d="M6.729 21.545L6.729 21.545Q6.393 21.377 6.225 21.041L6.225 21.041Q6.099 20.915 6.078 20.915Q6.057 20.915 5.973 21.041Q5.889 21.167 5.826 21.419Q5.763 21.671 5.679 21.839L5.679 21.839Q5.385 22.805 4.839 23.141Q4.293 23.477 3.327 23.267L3.327 23.267Q3.075 23.267 2.529 23.015L2.529 23.015Q1.731 22.595 2.151 21.839L2.151 21.839Q2.151 21.755 2.214 21.629Q2.277 21.503 2.277 21.419L2.277 21.419Q1.563 21.419 1.353 20.789L1.353 20.789Q0.849 19.445 1.017 18.416Q1.185 17.387 2.151 16.421L2.151 16.421L2.235 16.253Q2.403 15.959 2.403 15.791L2.403 15.791Q2.403 14.363 2.697 13.313L2.697 13.313Q3.033 12.053 3.831 11.045L3.831 11.045Q4.503 10.163 5.427 9.617L5.427 9.617Q5.595 9.533 5.616 9.407Q5.637 9.281 5.553 9.071L5.553 9.071Q4.839 8.189 4.629 6.971L4.629 6.971Q4.545 6.635 4.671 6.215L4.671 6.215Q4.755 5.921 5.007 5.417L5.007 5.417L5.175 5.039Q5.427 4.745 5.553 4.745L5.553 4.745Q5.931 4.661 6.561 4.199L6.561 4.199L6.855 3.989Q8.157 2.645 10.131 2.645L10.131 2.645Q10.341 2.645 10.446 2.582Q10.551 2.519 10.551 2.393L10.551 2.393Q10.719 1.595 11.307 0.839L11.307 0.839L11.727 0.419Q11.937 0.209 12.168 0.230Q12.399 0.251 12.525 0.545L12.525 0.545Q12.777 1.007 13.155 1.847L13.155 1.847L13.407 2.393Q13.617 2.729 13.827 2.519L13.827 2.519Q14.331 2.309 14.499 2.288Q14.667 2.267 14.751 2.393Q14.835 2.519 15.003 3.065L15.003 3.065Q16.011 7.265 13.701 10.919L13.701 10.919Q13.617 11.045 13.428 11.318Q13.239 11.591 13.155 11.759Q13.071 11.927 13.092 12.053Q13.113 12.179 13.281 12.389L13.281 12.389Q14.163 13.145 14.751 14.195Q15.339 15.245 15.507 16.421L15.507 16.421Q15.717 17.891 15.507 19.319L15.507 19.319Q15.423 19.697 15.507 19.760Q15.591 19.823 15.927 19.739L15.927 19.739Q17.397 19.277 18.531 18.521L18.531 18.521L18.867 18.353Q19.623 17.891 20.043 17.723L20.043 17.723Q20.673 17.429 21.303 17.345L21.303 17.345L21.681 17.345Q22.101 17.261 22.374 17.366Q22.647 17.471 22.836 17.723Q23.025 17.975 23.025 18.269L23.025 18.269Q23.025 18.857 22.353 19.067L22.353 19.067Q20.631 19.403 18.804 20.726Q16.977 22.049 14.457 22.721L14.457 22.721Q14.373 22.721 14.205 22.805Q14.037 22.889 13.953 23.015L13.953 23.015Q13.659 23.225 13.323 23.309L13.323 23.309Q13.113 23.393 12.651 23.435L12.651 23.435L12.231 23.519L11.895 23.561Q9.375 23.771 8.031 23.771L8.031 23.771Q7.275 23.771 6.729 23.645L6.729 23.645Q5.973 23.393 5.805 22.889L5.805 22.889Q5.595 22.091 6.225 21.671L6.225 21.671Q6.351 21.671 6.519 21.608Q6.687 21.545 6.729 21.545Z"/>', + 'seti:webpack': + '<path d="M18.403 16.275L21.975 18.441L12.475 23.875L12.475 19.619L18.403 16.275ZM19.125 15.819L22.697 17.833L22.697 6.433L19.125 8.447L19.125 15.819ZM5.711 16.275L2.025 18.441L11.639 23.875L11.639 19.619L5.711 16.275ZM4.875 15.819L1.303 17.833L1.303 6.433L4.875 8.447L4.875 15.819ZM5.217 7.611L1.683 5.711L11.525 0.125L11.525 4.191L5.217 7.611ZM18.783 7.611L22.317 5.711L12.475 0.125L12.475 4.191L18.783 7.611ZM11.525 12.513L11.525 18.669L5.597 15.477L5.597 9.055L11.525 12.513ZM12.475 12.513L12.475 18.669L18.403 15.477L18.403 9.055L12.475 12.513ZM12.019 11.677L6.053 8.219L12.019 5.027L17.947 8.219L12.019 11.677Z"/>', + 'seti:lock': + '<path d="M18.838 10.302L22.270 10.302L22.270 23.979L1.730 23.979L1.730 10.302L5.162 10.302L5.162 6.918Q5.162 6.354 5.255 5.884L5.255 5.884Q5.490 4.051 6.642 2.618Q7.793 1.184 9.509 0.503Q11.224-0.179 13.104 0.103L13.104 0.103Q15.548 0.526 17.194 2.453Q18.838 4.380 18.838 6.871L18.838 6.871L18.838 10.302ZM8.545 10.302L15.407 10.302Q15.407 10.255 15.407 10.208L15.407 10.208L15.407 6.777Q15.407 6.542 15.360 6.213L15.360 6.213Q15.078 4.850 14.021 4.098Q12.963 3.346 11.553 3.487L11.553 3.487Q10.284 3.581 9.415 4.592Q8.545 5.602 8.545 6.918L8.545 6.918L8.545 10.302Z"/>', + 'seti:license': + '<path d="M14.768 8.750L14.768 8.750Q14.636 7.067 13.431 5.994Q12.227 4.922 10.445 4.823L10.445 4.823L8.894 4.823Q8.795 3.602 9.356 2.710L9.356 2.710Q10.016 1.556 11.484 1.407Q12.953 1.259 13.943 2.248L13.943 2.248Q14.768 3.206 14.768 4.724L14.768 4.724Q14.768 5.021 14.900 5.152L14.900 5.152L15.824 6.076Q16.253 4.756 15.923 3.271L15.923 3.271Q15.527 1.919 14.454 1.093Q13.382 0.268 11.897 0.203L11.897 0.203Q10.940 0.203 10.280 0.401L10.280 0.401Q9.488 0.631 8.894 1.226L8.894 1.226Q8.168 1.919 7.821 3.041Q7.475 4.163 7.739 5.318L7.739 5.318Q8.036 6.572 8.993 7.495L8.993 7.495Q9.323 7.826 10.148 8.222L10.148 8.222Q10.511 8.387 10.791 8.172Q11.072 7.957 11.072 7.628L11.072 7.628Q11.072 6.934 10.346 6.803L10.346 6.803Q10.247 6.803 10.049 6.572L10.049 6.572L10.049 6.473Q10.346 6.407 10.692 6.489Q11.039 6.572 11.270 6.803L11.270 6.803Q11.732 7.265 11.567 8.024L11.567 8.024Q11.435 8.585 10.989 8.799Q10.544 9.014 9.917 8.849L9.917 8.849Q8.366 8.419 7.574 6.803L7.574 6.803Q7.508 6.637 7.359 6.324Q7.211 6.011 7.145 5.846L7.145 5.846Q6.518 6.506 6.188 6.968L6.188 6.968Q5.759 7.628 5.594 8.321L5.594 8.321Q5.000 11.093 7.046 12.974L7.046 12.974Q7.145 13.073 7.178 13.155Q7.211 13.238 7.145 13.403L7.145 13.403Q6.980 14.822 6.749 15.746L6.749 15.746Q6.584 16.637 6.320 18.336Q6.056 20.035 5.907 20.894Q5.759 21.752 5.924 22.577L5.924 22.577Q6.089 23.236 6.749 23.501L6.749 23.501Q6.782 23.303 6.831 22.890Q6.881 22.478 6.947 22.247L6.947 22.247Q7.112 21.389 7.359 19.689Q7.607 17.989 7.772 17.099L7.772 17.099Q7.871 16.571 8.019 15.498Q8.168 14.426 8.300 13.898L8.300 13.898Q8.300 13.601 8.597 13.601L8.597 13.601Q8.729 13.601 8.762 13.700Q8.795 13.799 8.795 13.997L8.795 13.997Q8.663 15.218 8.300 17.000L8.300 17.000Q8.135 18.089 7.805 20.102L7.805 20.102Q7.409 22.412 7.244 23.501L7.244 23.501Q7.244 23.567 7.310 23.633L7.310 23.633L7.343 23.699Q7.607 23.699 8.069 23.748Q8.531 23.797 8.795 23.797L8.795 23.797Q9.422 23.797 10.049 22.973L10.049 22.973Q10.478 22.544 10.148 21.851L10.148 21.851Q9.950 21.653 9.950 21.521L9.950 21.521Q9.488 20.927 10.148 20.597L10.148 20.597Q10.181 20.564 10.346 20.514Q10.511 20.465 10.544 20.399L10.544 20.399Q10.709 20.333 10.758 20.135Q10.808 19.937 10.643 19.772L10.643 19.772L10.346 19.474Q10.016 19.079 9.851 18.947Q9.686 18.815 9.735 18.567Q9.785 18.320 9.933 18.221Q10.082 18.122 10.445 17.973Q10.808 17.825 10.973 17.726Q11.138 17.627 11.171 17.495Q11.204 17.363 11.072 17.198L11.072 17.198Q10.874 17.000 10.742 16.802L10.742 16.802Q10.544 16.571 10.577 16.241Q10.610 15.911 10.841 15.729Q11.072 15.548 11.270 15.548L11.270 15.548Q11.567 15.416 11.600 15.152L11.600 15.152Q11.567 14.987 11.633 14.673Q11.699 14.360 11.699 14.228L11.699 14.228Q11.699 14.129 11.765 13.997Q11.831 13.865 11.897 13.799L11.897 13.799Q12.194 13.502 13.019 13.073L13.019 13.073Q14.075 12.314 14.504 11.208Q14.933 10.103 14.768 8.750ZM18.497 20.498L18.497 20.498Q18.497 20.102 18.068 20.102L18.068 20.102Q17.837 20.102 17.738 20.069L17.738 20.069Q17.540 20.003 17.474 19.772L17.474 19.772Q17.309 19.309 17.474 18.848L17.474 18.848Q17.804 18.188 17.045 18.023L17.045 18.023Q16.946 18.023 16.715 17.973Q16.484 17.924 16.319 17.924L16.319 17.924Q16.022 17.924 16.022 17.627L16.022 17.627Q16.022 17.528 15.972 17.313Q15.923 17.099 15.923 17.000L15.923 17.000Q15.923 16.802 16.055 16.604L16.055 16.604Q16.121 16.471 16.302 16.257Q16.484 16.043 16.467 15.927Q16.451 15.812 16.220 15.647L16.220 15.647Q16.187 15.614 16.022 15.515Q15.857 15.416 15.824 15.350L15.824 15.350Q15.527 15.185 15.477 15.020Q15.428 14.855 15.593 14.525L15.593 14.525Q15.824 14.327 15.824 14.228L15.824 14.228Q16.088 13.931 15.923 13.601L15.923 13.601L15.824 13.436Q15.659 13.040 15.494 12.875L15.494 12.875Q15.362 12.578 15.494 12.248L15.494 12.248Q16.814 9.640 15.824 7.198L15.824 7.198Q15.032 5.515 13.118 5.053L13.118 5.053L13.019 5.152Q13.085 5.186 13.184 5.351Q13.283 5.515 13.349 5.549L13.349 5.549Q15.296 7.198 15.296 9.575L15.296 9.575Q15.296 12.248 13.019 13.898L13.019 13.898Q12.854 13.997 12.804 14.129Q12.755 14.261 12.821 14.426L12.821 14.426Q13.019 14.921 13.382 15.911Q13.745 16.901 13.943 17.396L13.943 17.396L16.418 23.171L16.484 23.270Q16.583 23.402 16.748 23.402L16.748 23.402Q17.672 22.940 18.167 22.148Q18.662 21.356 18.497 20.498ZM12.293 14.426L12.293 14.426Q12.260 14.624 12.210 14.954Q12.161 15.284 12.095 15.449L12.095 15.449L12.062 15.647Q12.029 15.944 12.095 16.076L12.095 16.076L14.273 21.422Q14.636 22.346 15.296 22.873L15.296 22.873Q15.692 23.072 15.824 23.204L15.824 23.204L15.923 23.072Q14.768 20.201 12.293 14.426Z"/>', + 'seti:makefile': + '<path d="M12 9.249L4.398 0.975L0.198 2.025L0.198 23.025L5.700 23.025L5.700 10.005L10.404 15.129L13.596 15.129L18.300 10.005L18.300 23.025L23.802 23.025L23.802 2.025L19.602 0.975L12 9.249Z"/>', + 'seti:heroku': + '<path d="M8.143 20.493L4.267 23.875L4.267 17.111L8.143 20.493ZM18.213 10.157L18.213 10.157Q19.163 11.069 19.505 12.399L19.505 12.399Q19.733 13.121 19.695 13.729L19.695 13.729L19.695 23.875L16.275 23.875L16.275 13.767Q16.275 13.045 15.857 12.589L15.857 12.589Q15.325 12.019 14.147 12.019L14.147 12.019Q11.943 12.019 9.131 12.893L9.131 12.893Q7.535 13.387 6.699 13.767L6.699 13.767L4.267 14.869L4.267 0.125L7.725 0.125L7.725 9.777Q11.297 8.637 14.147 8.637L14.147 8.637Q16.693 8.637 18.213 10.157ZM17.149 5.673L13.729 5.673Q15.705 3.051 16.275 0.125L16.275 0.125L19.733 0.125Q19.353 3.203 17.149 5.673L17.149 5.673Z"/>', + 'seti:todo': + '<path d="M3.726 0.261L12 0.261L19.476 0.261Q21.030 0.261 22.206 1.227Q23.382 2.193 23.676 3.663L23.676 3.663Q23.802 3.915 23.802 4.461L23.802 4.461L23.802 19.413Q23.802 21.009 22.815 22.206Q21.828 23.403 20.274 23.613L20.274 23.613Q20.148 23.613 19.875 23.676Q19.602 23.739 19.476 23.739L19.476 23.739L4.650 23.739Q2.676 23.739 1.437 22.521Q0.198 21.303 0.198 19.413L0.198 19.413L0.198 4.587Q0.198 2.907 1.164 1.731Q2.130 0.555 3.726 0.261L3.726 0.261ZM3.726 12.063L3.726 12.063L3.726 19.539Q3.726 20.337 4.650 20.337L4.650 20.337L19.350 20.337Q19.728 20.337 20.001 20.064Q20.274 19.791 20.274 19.413L20.274 19.413L20.274 4.713Q20.148 4.209 19.917 3.999Q19.686 3.789 19.224 3.789L19.224 3.789L4.524 3.789Q4.020 3.789 3.810 3.999Q3.600 4.209 3.600 4.713L3.600 4.713Q3.726 7.065 3.726 12.063ZM6.876 10.341L6.876 10.341Q7.002 10.425 7.212 10.467L7.212 10.467L7.548 10.635Q8.010 10.803 8.913 11.265Q9.816 11.727 10.278 11.937L10.278 11.937Q10.488 12.021 10.530 12.021Q10.572 12.021 10.698 11.937L10.698 11.937L12.420 10.635Q15.066 8.661 16.452 7.737L16.452 7.737Q16.620 7.569 16.914 7.443L16.914 7.443Q17.082 7.401 17.124 7.359L17.124 7.359Q17.418 7.233 17.607 7.464Q17.796 7.695 17.796 7.989L17.796 7.989L17.628 8.241Q17.502 8.451 17.502 8.535L17.502 8.535Q16.830 9.417 15.528 11.307L15.528 11.307L14.226 13.113Q12.672 15.255 11.874 16.263L11.874 16.263Q11.370 17.019 10.698 16.977Q10.026 16.935 9.522 16.137L9.522 16.137L6.498 11.685Q6.204 11.391 6.204 11.265L6.204 11.265Q6.120 10.887 6.309 10.614Q6.498 10.341 6.876 10.341Z"/>', + 'seti:ignored': + '<path d="M4.661 20.860L21.083 4.480Q21.335 3.934 21.335 3.682L21.335 3.682Q21.167 2.968 20.600 2.779Q20.033 2.590 19.361 3.010L19.361 3.010L16.715 5.656Q16.589 5.782 16.211 5.782L16.211 5.782Q13.943 4.900 11.738 4.921Q9.533 4.942 7.307 5.908L7.307 5.908Q3.191 7.714 0.335 12.082L0.335 12.082Q0.125 12.502 0.146 12.817Q0.167 13.132 0.461 13.384L0.461 13.384Q1.469 14.602 2.687 15.610L2.687 15.610Q3.485 16.282 5.039 17.332L5.039 17.332Q4.997 17.332 4.934 17.395Q4.871 17.458 4.787 17.458L4.787 17.458L4.115 18.088Q3.317 18.886 2.939 19.306L2.939 19.306Q2.519 19.768 2.687 20.482L2.687 20.482Q2.897 21.112 3.611 21.280L3.611 21.280Q4.283 21.280 4.661 20.860L4.661 20.860ZM7.811 14.560L6.887 15.484L6.635 15.484Q4.241 14.182 2.687 12.502L2.687 12.502Q4.955 9.520 7.559 8.134L7.559 8.134Q5.627 11.410 7.811 14.560L7.811 14.560ZM12.809 8.302L12.809 8.302Q12.599 8.932 11.885 8.932L11.885 8.932Q11.003 8.932 10.373 9.478Q9.743 10.024 9.659 10.906L9.659 10.906L9.659 11.284Q9.659 11.662 9.428 11.872Q9.197 12.082 8.840 12.082Q8.483 12.082 8.273 11.830Q8.063 11.578 8.063 11.158L8.063 11.158Q8.063 9.562 9.197 8.407Q10.331 7.252 11.885 7.252L11.885 7.252Q12.347 7.252 12.620 7.567Q12.893 7.882 12.809 8.302ZM23.561 11.956L23.561 11.956Q23.225 11.578 22.574 10.717Q21.923 9.856 21.587 9.478L21.587 9.478Q21.335 9.142 20.684 8.554Q20.033 7.966 19.739 7.630L19.739 7.630L18.185 9.184Q20.033 10.654 21.335 12.502L21.335 12.502Q21.083 12.754 20.957 12.754L20.957 12.754Q20.159 13.510 19.739 13.804L19.739 13.804Q15.623 17.122 10.961 16.534L10.961 16.534Q10.583 16.534 10.415 16.702L10.415 16.702Q9.911 17.206 9.659 17.584L9.659 17.584L8.861 18.382L8.987 18.382Q12.137 19.054 14.615 18.508L14.615 18.508Q19.739 17.626 23.561 13.132L23.561 13.132Q24.149 12.754 23.561 11.956Z"/>', +}; diff --git a/packages/starlight/user-components/rehype-file-tree.ts b/packages/starlight/user-components/rehype-file-tree.ts new file mode 100644 index 00000000000..72f658a03c1 --- /dev/null +++ b/packages/starlight/user-components/rehype-file-tree.ts @@ -0,0 +1,251 @@ +import { AstroError } from 'astro/errors'; +import type { Element, ElementContent, Text } from 'hast'; +import { type Child, h, s } from 'hastscript'; +import { select } from 'hast-util-select'; +import { fromHtml } from 'hast-util-from-html'; +import { toString } from 'hast-util-to-string'; +import { rehype } from 'rehype'; +import { CONTINUE, SKIP, visit } from 'unist-util-visit'; +import { Icons, type StarlightIcon } from '../components/Icons'; +import { definitions } from './file-tree-icons'; + +declare module 'vfile' { + interface DataMap { + directoryLabel: string; + } +} + +const folderIcon = makeSVGIcon(Icons['seti:folder']); +const defaultFileIcon = makeSVGIcon(Icons['seti:default']); + +/** + * Process the HTML for a file tree to create the necessary markup for each file and directory + * including icons. + * @param html Inner HTML passed to the `<FileTree>` component. + * @param directoryLabel The localized label for a directory. + * @returns The processed HTML for the file tree. + */ +export function processFileTree(html: string, directoryLabel: string) { + const file = fileTreeProcessor.processSync({ data: { directoryLabel }, value: html }); + + return file.toString(); +} + +/** Rehype processor to extract file tree data and turn each entry into its associated markup. */ +const fileTreeProcessor = rehype() + .data('settings', { fragment: true }) + .use(function fileTree() { + return (tree: Element, file) => { + const { directoryLabel } = file.data; + + validateFileTree(tree); + + visit(tree, 'element', (node) => { + // Strip nodes that only contain newlines. + node.children = node.children.filter( + (child) => child.type === 'comment' || child.type !== 'text' || !/^\n+$/.test(child.value) + ); + + // Skip over non-list items. + if (node.tagName !== 'li') return CONTINUE; + + const [firstChild, ...otherChildren] = node.children; + + // Keep track of comments associated with the current file or directory. + const comment: Child[] = []; + + // Extract text comment that follows the file name, e.g. `README.md This is a comment` + if (firstChild?.type === 'text') { + const [filename, ...fragments] = firstChild.value.split(' '); + firstChild.value = filename || ''; + const textComment = fragments.join(' ').trim(); + if (textComment.length > 0) { + comment.push(fragments.join(' ')); + } + } + + // Comments may not always be entirely part of the first child text node, + // e.g. `README.md This is an __important__ comment` where the `__important__` and `comment` + // nodes would also be children of the list item node. + const subTreeIndex = otherChildren.findIndex( + (child) => child.type === 'element' && child.tagName === 'ul' + ); + const commentNodes = + subTreeIndex > -1 ? otherChildren.slice(0, subTreeIndex) : [...otherChildren]; + otherChildren.splice(0, subTreeIndex > -1 ? subTreeIndex : otherChildren.length); + comment.push(...commentNodes); + + const firstChildTextContent = firstChild ? toString(firstChild) : ''; + + // Decide a node is a directory if it ends in a `/` or contains another list. + const isDirectory = + /\/\s*$/.test(firstChildTextContent) || + otherChildren.some((child) => child.type === 'element' && child.tagName === 'ul'); + // A placeholder is a node that only contains 3 dots or an ellipsis. + const isPlaceholder = /^\s*(\.{3}|…)\s*$/.test(firstChildTextContent); + // A node is highlighted if its first child is bold text, e.g. `**README.md**`. + const isHighlighted = firstChild?.type === 'element' && firstChild.tagName === 'strong'; + + // Create an icon for the file or directory (placeholder do not have icons). + const icon = h('span', isDirectory ? folderIcon : getFileIcon(firstChildTextContent)); + if (isDirectory) { + // Add a screen reader only label for directories before the icon so that it is announced + // as such before reading the directory name. + icon.children.unshift(h('span', { class: 'sr-only' }, directoryLabel)); + } + + // Add classes and data attributes to the list item node. + node.properties.class = isDirectory ? 'directory' : 'file'; + if (isPlaceholder) node.properties.class += ' empty'; + + // Create the tree entry node that contains the icon, file name and comment which will end up + // as the list item’s children. + const treeEntryChildren: Child[] = [ + h('span', { class: isHighlighted ? 'highlight' : '' }, [ + isPlaceholder ? null : icon, + firstChild, + ]), + ]; + + if (comment.length > 0) { + treeEntryChildren.push(makeText(' '), h('span', { class: 'comment' }, ...comment)); + } + + const treeEntry = h('span', { class: 'tree-entry' }, ...treeEntryChildren); + + if (isDirectory) { + const hasContents = otherChildren.length > 0; + + node.children = [ + h('details', { open: hasContents }, [ + h('summary', treeEntry), + ...(hasContents ? otherChildren : [h('ul', h('li', '…'))]), + ]), + ]; + + // Continue down the tree. + return CONTINUE; + } + + node.children = [treeEntry, ...otherChildren]; + + // Files can’t contain further files or directories, so skip iterating children. + return SKIP; + }); + }; + }); + +/** Make a text node with the pass string as its contents. */ +function makeText(value = ''): Text { + return { type: 'text', value }; +} + +/** Make a node containing an SVG icon from the passed HTML string. */ +function makeSVGIcon(svgString: string) { + return s( + 'svg', + { + width: 16, + height: 16, + class: 'tree-icon', + 'aria-hidden': 'true', + viewBox: '0 0 24 24', + }, + fromHtml(svgString, { fragment: true }) + ); +} + +/** Return the icon for a file based on its file name. */ +function getFileIcon(fileName: string) { + const name = getFileIconName(fileName); + if (!name) return defaultFileIcon; + if (name in Icons) { + const path = Icons[name as StarlightIcon]; + return makeSVGIcon(path); + } + return defaultFileIcon; +} + +/** Return the icon name for a file based on its file name. */ +function getFileIconName(fileName: string) { + let icon: string | undefined = definitions.files[fileName]; + if (icon) return icon; + icon = getFileIconTypeFromExtension(fileName); + if (icon) return icon; + for (const [partial, partialIcon] of Object.entries(definitions.partials)) { + if (fileName.includes(partial)) return partialIcon; + } + return icon; +} + +/** + * Get an icon from a file name based on its extension. + * Note that an extension in Seti is everything after a dot, so `README.md` would be `.md` and + * `name.with.dots` will try to look for an icon for `.with.dots` and then `.dots` if the first one + * is not found. + */ +function getFileIconTypeFromExtension(fileName: string) { + const firstDotIndex = fileName.indexOf('.'); + if (firstDotIndex === -1) return; + let extension = fileName.slice(firstDotIndex); + while (extension !== '') { + const icon = definitions.extensions[extension]; + if (icon) return icon; + const nextDotIndex = extension.indexOf('.', 1); + if (nextDotIndex === -1) return; + extension = extension.slice(nextDotIndex); + } + return; +} + +/** Validate that the user provided HTML for a file tree is valid. */ +function validateFileTree(tree: Element) { + const rootElements = tree.children.filter(isElementNode); + const [rootElement] = rootElements; + + if (rootElements.length === 0) { + throwFileTreeValidationError( + 'The `<FileTree>` component expects its content to be a single unordered list but found no child elements.' + ); + } + + if (rootElements.length !== 1) { + throwFileTreeValidationError( + `The \`<FileTree>\` component expects its content to be a single unordered list but found multiple child elements: ${rootElements + .map((element) => `\`<${element.tagName}>\``) + .join(' - ')}.` + ); + } + + if (!rootElement || rootElement.tagName !== 'ul') { + throwFileTreeValidationError( + `The \`<FileTree>\` component expects its content to be an unordered list but found the following element: \`<${rootElement?.tagName}>\`.` + ); + } + + const listItemElement = select('li', rootElement); + + if (!listItemElement) { + throwFileTreeValidationError( + 'The `<FileTree>` component expects its content to be an unordered list with at least one list item.' + ); + } +} + +function isElementNode(node: ElementContent): node is Element { + return node.type === 'element'; +} + +/** Throw a validation error for a file tree linking to the documentation. */ +function throwFileTreeValidationError(message: string): never { + throw new AstroError( + message, + 'To learn more about the `<FileTree>` component, see https://starlight.astro.build/components/file-tree/' + ); +} + +export interface Definitions { + files: Record<string, string>; + extensions: Record<string, string>; + partials: Record<string, string>; +} diff --git a/packages/starlight/user-components/rehype-steps.ts b/packages/starlight/user-components/rehype-steps.ts new file mode 100644 index 00000000000..0c6030704b7 --- /dev/null +++ b/packages/starlight/user-components/rehype-steps.ts @@ -0,0 +1,85 @@ +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, vfile: VFile) => { + const rootElements = tree.children.filter( + (item): item is Element => + item.type === 'element' && + // Since Astro 5.16.9, `<script>` elements from nested child elements can end up hoisted + // into the `<Steps>` slot due to our use of `Astro.slots.render()`. We can safely ignore + // these, so we filter them out here. + // TODO: we may be able to remove this in the future if the upstream issue is fixed. + // See: https://github.com/withastro/astro/issues/15627 + item.tagName !== 'script' + ); + const [rootElement] = rootElements; + + if (!rootElement) { + throw new StepsError( + 'The `<Steps>` component expects its content to be a single ordered list (`<ol>`) but found no child elements.' + ); + } else if (rootElements.length > 1) { + throw new StepsError( + 'The `<Steps>` component expects its content to be a single ordered list (`<ol>`) but found multiple child elements: ' + + rootElements.map((element: Element) => `\`<${element.tagName}>\``).join(', ') + + '.', + vfile.value.toString() + ); + } else if (rootElement.tagName !== 'ol') { + throw new StepsError( + 'The `<Steps>` component expects its content to be a single ordered list (`<ol>`) but found the following element: ' + + `\`<${rootElement.tagName}>\`.`, + vfile.value.toString() + ); + } + + // Ensure `role="list"` is set on the ordered list. + // We use `list-style: none` in the styles for this component and need to ensure the list + // retains its semantics in Safari, which will remove them otherwise. + rootElement.properties.role = 'list'; + // Add the required CSS class name, preserving existing classes if present. + if (!Array.isArray(rootElement.properties.className)) { + rootElement.properties.className = ['sl-steps']; + } else { + rootElement.properties.className.push('sl-steps'); + } + + // Add the `start` attribute as a CSS custom property so we can use it as the starting index + // of the steps custom counter. + if (typeof rootElement.properties.start === 'number') { + const styles = [`--sl-steps-start: ${rootElement.properties.start - 1}`]; + if (rootElement.properties.style) styles.push(String(rootElement.properties.style)); + rootElement.properties.style = styles.join(';'); + } + }; + }); + +/** + * Process steps children: validates the HTML and adds `role="list"` to the ordered list. + * @param html Inner HTML passed to the `<Steps>` component. + */ +export const processSteps = (html: string | undefined) => { + const file = stepsProcessor.processSync({ value: html }); + return { html: file.toString() }; +}; + +class StepsError extends AstroError { + constructor(message: string, html?: string) { + let hint = + 'To learn more about the `<Steps>` component, see https://starlight.astro.build/components/steps/'; + if (html) { + hint += '\n\nFull HTML passed to `<Steps>`:\n' + prettyPrintHtml(html); + } + super(message, hint); + } +} diff --git a/packages/starlight/user-components/rehype-tabs.ts b/packages/starlight/user-components/rehype-tabs.ts index 36e2adc3974..b989a81fda8 100644 --- a/packages/starlight/user-components/rehype-tabs.ts +++ b/packages/starlight/user-components/rehype-tabs.ts @@ -1,11 +1,14 @@ +import type { Element } from 'hast'; import { select } from 'hast-util-select'; import { rehype } from 'rehype'; import { CONTINUE, SKIP, visit } from 'unist-util-visit'; +import type { StarlightIcon } from '../components/Icons'; interface Panel { panelId: string; tabId: string; label: string; + icon?: StarlightIcon; } declare module 'vfile' { @@ -44,13 +47,13 @@ const getIDs = () => { /** * Rehype processor to extract tab panel data and turn each - * `<starlight-tab-item>` into a `<section>` with the necessary + * `<starlight-tab-item>` into a `<div>` with the necessary * attributes. */ const tabsProcessor = rehype() .data('settings', { fragment: true }) .use(function tabs() { - return (tree, file) => { + return (tree: Element, file) => { file.data.panels = []; let isFirst = true; visit(tree, 'element', (node) => { @@ -58,17 +61,20 @@ const tabsProcessor = rehype() return CONTINUE; } - const { dataLabel } = node.properties; + const { dataLabel, dataIcon } = node.properties; const ids = getIDs(); - file.data.panels?.push({ + const panel: Panel = { ...ids, label: String(dataLabel), - }); + }; + if (dataIcon) panel.icon = String(dataIcon) as StarlightIcon; + file.data.panels?.push(panel); // Remove `<TabItem>` props delete node.properties.dataLabel; - // Turn into `<section>` with required attributes - node.tagName = 'section'; + delete node.properties.dataIcon; + // Turn into `<div>` with required attributes + node.tagName = 'div'; node.properties.id = ids.panelId; node.properties['aria-labelledby'] = ids.tabId; node.properties.role = 'tabpanel'; diff --git a/packages/starlight/utils/base.ts b/packages/starlight/utils/base.ts index d287ddc27df..49533f68d9d 100644 --- a/packages/starlight/utils/base.ts +++ b/packages/starlight/utils/base.ts @@ -1,15 +1,15 @@ -import { stripLeadingAndTrailingSlashes, stripTrailingSlash } from './path'; +import { stripLeadingSlash, stripTrailingSlash } from './path'; const base = stripTrailingSlash(import.meta.env.BASE_URL); /** Get the a root-relative URL path with the site’s `base` prefixed. */ export function pathWithBase(path: string) { - path = stripLeadingAndTrailingSlashes(path); - return path ? base + '/' + path + '/' : base + '/'; + path = stripLeadingSlash(path); + return path ? base + '/' + path : base + '/'; } /** Get the a root-relative file URL path with the site’s `base` prefixed. */ export function fileWithBase(path: string) { - path = stripLeadingAndTrailingSlashes(path); + path = stripLeadingSlash(path); return path ? base + '/' + path : base; } diff --git a/packages/starlight/utils/canonical.ts b/packages/starlight/utils/canonical.ts new file mode 100644 index 00000000000..5a0da5d4d5d --- /dev/null +++ b/packages/starlight/utils/canonical.ts @@ -0,0 +1,19 @@ +import type { AstroConfig } from 'astro'; +import { ensureTrailingSlash, stripTrailingSlash } from './path'; + +export interface FormatCanonicalOptions { + format: AstroConfig['build']['format']; + trailingSlash: AstroConfig['trailingSlash']; +} + +const canonicalTrailingSlashStrategies = { + always: ensureTrailingSlash, + never: stripTrailingSlash, + ignore: ensureTrailingSlash, +}; + +/** Format a canonical link based on the project config. */ +export function formatCanonical(href: string, opts: FormatCanonicalOptions) { + if (opts.format === 'file') return href; + return canonicalTrailingSlashStrategies[opts.trailingSlash](href); +} diff --git a/packages/starlight/utils/collection-fs.ts b/packages/starlight/utils/collection-fs.ts new file mode 100644 index 00000000000..f641039ab63 --- /dev/null +++ b/packages/starlight/utils/collection-fs.ts @@ -0,0 +1,21 @@ +import { resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { getCollectionUrl, type StarlightCollection } from './collection'; + +/** + * @see {@link file://./collection.ts} for more context about this file. + * + * Below are various functions to easily get paths to collections used in Starlight that rely on + * Node.js builtins. They exist in a separate file from {@link file://./collection.ts} to avoid + * potentially importing Node.js builtins in the final bundle. + */ + +export function resolveCollectionPath(collection: StarlightCollection, srcDir: URL) { + return resolve(fileURLToPath(srcDir), `content/${collection}`); +} + +export function getCollectionPosixPath(collection: StarlightCollection, srcDir: URL) { + // TODO: when Astro minimum Node.js version is >= 20.13.0, refactor to use the `fileURLToPath` + // second optional argument to enforce POSIX paths by setting `windows: false`. + return fileURLToPath(getCollectionUrl(collection, srcDir)).replace(/\\/g, '/'); +} diff --git a/packages/starlight/utils/collection.ts b/packages/starlight/utils/collection.ts new file mode 100644 index 00000000000..d4db3899b9e --- /dev/null +++ b/packages/starlight/utils/collection.ts @@ -0,0 +1,37 @@ +export type StarlightCollection = 'docs' | 'i18n'; + +/** + * We still rely on the content collection folder structure to be fixed for now: + * + * - At build time, if the feature is enabled, we get all the last commit dates for each file in + * the docs folder ahead of time. In the current approach, we cannot know at this time the + * user-defined content folder path in the integration context as this would only be available + * from the loader. A potential solution could be to do that from a custom loader re-implementing + * the glob loader or built on top of it. Although, we don't have access to the Starlight + * configuration from the loader to even know we should do that. + * - Remark plugins get passed down an absolute path to a content file and we need to figure out + * the language from that path. Without knowing the content folder path, we cannot reliably do + * so. + * + * Below are various functions to easily get paths to these collections and avoid having to + * hardcode them throughout the codebase. When user-defined content folder locations are supported, + * these helper functions should be updated to reflect that in one place. + */ + +export function getCollectionUrl(collection: StarlightCollection, srcDir: URL) { + return new URL(`content/${collection}/`, srcDir); +} + +export function getCollectionPathFromRoot( + collection: StarlightCollection, + { root, srcDir }: { root: URL | string; srcDir: URL | string } +) { + return ( + (typeof srcDir === 'string' ? srcDir : srcDir.pathname).replace( + typeof root === 'string' ? root : root.pathname, + '' + ) + + 'content/' + + collection + ); +} diff --git a/packages/starlight/utils/createPathFormatter.ts b/packages/starlight/utils/createPathFormatter.ts new file mode 100644 index 00000000000..52c9527c6d8 --- /dev/null +++ b/packages/starlight/utils/createPathFormatter.ts @@ -0,0 +1,60 @@ +import type { AstroConfig } from 'astro'; +import { fileWithBase, pathWithBase } from './base'; +import { + ensureHtmlExtension, + ensureTrailingSlash, + stripHtmlExtension, + stripTrailingSlash, +} from './path'; + +interface FormatPathOptions { + format?: AstroConfig['build']['format']; + trailingSlash?: AstroConfig['trailingSlash']; +} + +const defaultFormatStrategy = { + addBase: pathWithBase, + handleExtension: (href: string) => stripHtmlExtension(href), +}; + +const formatStrategies = { + file: { + addBase: fileWithBase, + handleExtension: (href: string) => ensureHtmlExtension(href), + }, + directory: defaultFormatStrategy, + preserve: defaultFormatStrategy, +}; + +const trailingSlashStrategies = { + always: ensureTrailingSlash, + never: stripTrailingSlash, + ignore: (href: string) => href, +}; + +/** Format a path based on the project config. */ +function formatPath( + href: string, + { format = 'directory', trailingSlash = 'ignore' }: FormatPathOptions +) { + const formatStrategy = formatStrategies[format]; + const trailingSlashStrategy = trailingSlashStrategies[trailingSlash]; + + // Handle extension + href = formatStrategy.handleExtension(href); + + // Add base + href = formatStrategy.addBase(href); + + // Skip trailing slash handling for `build.format: 'file'` + if (format === 'file') return href; + + // Handle trailing slash + href = href === '/' ? href : trailingSlashStrategy(href); + + return href; +} + +export function createPathFormatter(opts: FormatPathOptions) { + return (href: string) => formatPath(href, opts); +} diff --git a/packages/starlight/utils/createTranslationSystem.ts b/packages/starlight/utils/createTranslationSystem.ts new file mode 100644 index 00000000000..d6e78fd519a --- /dev/null +++ b/packages/starlight/utils/createTranslationSystem.ts @@ -0,0 +1,134 @@ +import i18next, { type ExistsFunction, type TFunction } from 'i18next'; +import type { i18nSchemaOutput } from '../schemas/i18n'; +import builtinTranslations from '../translations/index'; +import { BuiltInDefaultLocale } from './i18n'; +import type { StarlightConfig } from './user-config'; +import type { UserI18nKeys, UserI18nSchema } from './translations'; + +/** + * The namespace for i18next resources used by Starlight. + * All translations handled by Starlight are stored in the same namespace and Starlight always use + * a new instance of i18next configured for this namespace. + */ +export const I18nextNamespace = 'starlight' as const; + +export async function createTranslationSystem<T extends i18nSchemaOutput>( + config: Pick<StarlightConfig, 'defaultLocale' | 'locales'>, + userTranslations: Record<string, T>, + pluginTranslations: Record<string, T> = {} +) { + const defaultLocale = + config.defaultLocale.lang || config.defaultLocale?.locale || BuiltInDefaultLocale.lang; + + const translations = { + [defaultLocale]: buildResources( + builtinTranslations[defaultLocale], + builtinTranslations[stripLangRegion(defaultLocale)], + pluginTranslations[defaultLocale], + userTranslations[defaultLocale] + ), + }; + + if (config.locales) { + for (const locale in config.locales) { + const lang = localeToLang(locale, config.locales, config.defaultLocale); + + translations[lang] = buildResources( + builtinTranslations[lang] || builtinTranslations[stripLangRegion(lang)], + pluginTranslations[lang], + userTranslations[lang] + ); + } + } + + const i18n = i18next.createInstance(); + await i18n.init({ + resources: translations, + fallbackLng: + config.defaultLocale.lang || config.defaultLocale?.locale || BuiltInDefaultLocale.lang, + }); + + /** + * Generate a utility function that returns UI strings for the given language. + * + * Also includes a few utility methods: + * - `all()` method for getting the entire dictionary. + * - `exists()` method for checking if a key exists in the dictionary. + * - `dir()` method for getting the text direction of the locale. + * + * @param {string | undefined} [lang] + * @example + * const t = useTranslations('en'); + * const label = t('search.label'); + * // => 'Search' + * const dictionary = t.all(); + * // => { 'skipLink.label': 'Skip to content', 'search.label': 'Search', ... } + * const exists = t.exists('search.label'); + * // => true + * const dir = t.dir(); + * // => 'ltr' + */ + return (lang: string | undefined) => { + lang ??= config.defaultLocale?.lang || BuiltInDefaultLocale.lang; + + const t = i18n.getFixedT(lang, I18nextNamespace) as I18nT; + t.all = () => i18n.getResourceBundle(lang, I18nextNamespace) as ReturnType<I18nT['all']>; + t.exists = (key, options) => i18n.exists(key, { lng: lang, ns: I18nextNamespace, ...options }); + t.dir = (dirLang = lang) => i18n.dir(dirLang); + + return t; + }; +} + +/** + * Strips the region subtag from a BCP-47 lang string. + * @param {string} [lang] + * @example + * const lang = stripLangRegion('en-GB'); // => 'en' + */ +function stripLangRegion(lang: string) { + return lang.replace(/-[a-zA-Z]{2}/, ''); +} + +/** + * Get the BCP-47 language tag for the given locale. + * @param locale Locale string or `undefined` for the root locale. + */ +function localeToLang( + locale: string | undefined, + locales: StarlightConfig['locales'], + defaultLocale: StarlightConfig['defaultLocale'] +): string { + const lang = locale ? locales?.[locale]?.lang : locales?.root?.lang; + const defaultLang = defaultLocale?.lang || defaultLocale?.locale; + return lang || defaultLang || BuiltInDefaultLocale.lang; +} + +type BuiltInStrings = (typeof builtinTranslations)['en']; + +/** Build an i18next resources dictionary by layering preferred translation sources. */ +function buildResources<T extends Record<string, string | undefined>>( + ...dictionaries: (T | BuiltInStrings | undefined)[] +): { [I18nextNamespace]: BuiltInStrings & T } { + const dictionary: Partial<BuiltInStrings> = {}; + // Iterate over alternate dictionaries to avoid overwriting preceding values with `undefined`. + for (const dict of dictionaries) { + for (const key in dict) { + const value = dict[key as keyof typeof dict]; + if (value) dictionary[key as keyof typeof dictionary] = value; + } + } + return { [I18nextNamespace]: dictionary as BuiltInStrings & T }; +} + +// `keyof BuiltInStrings` and `UserI18nKeys` may contain some identical keys, e.g. the built-in UI +// strings. We let TypeScript merge them into a single union type so that plugins with a TypeScript +// configuration preventing `UserI18nKeys` to be properly inferred can still get auto-completion +// for built-in UI strings. +export type I18nKeys = keyof BuiltInStrings | UserI18nKeys | keyof StarlightApp.I18n; + +export type I18nT = TFunction<'starlight', undefined> & { + all: () => UserI18nSchema; + exists: ExistsFunction; + dir: (lang?: string) => 'ltr' | 'rtl'; +}; diff --git a/packages/starlight/utils/error-map.ts b/packages/starlight/utils/error-map.ts index d1006d35692..da671014e9b 100644 --- a/packages/starlight/utils/error-map.ts +++ b/packages/starlight/utils/error-map.ts @@ -3,6 +3,7 @@ * source: https://github.com/withastro/astro/blob/main/packages/astro/src/content/error-map.ts */ +import { AstroError } from 'astro/errors'; import type { z } from 'astro:content'; type TypeOrLiteralErrByPathEntry = { @@ -11,7 +12,50 @@ type TypeOrLiteralErrByPathEntry = { expected: unknown[]; }; -export const errorMap: z.ZodErrorMap = (baseError, ctx) => { +/** + * Parse data with a Zod schema and throw a nicely formatted error if it is invalid. + * + * @param schema The Zod schema to use to parse the input. + * @param input Input data that should match the schema. + * @param message Error message preamble to use if the input fails to parse. + * @returns Validated data parsed by Zod. + */ +export function parseWithFriendlyErrors<T extends z.Schema>( + schema: T, + input: z.input<T>, + message: string +): z.output<T> { + return processParsedData<T>(schema.safeParse(input, { errorMap }), message); +} + +/** + * Asynchronously parse data with a Zod schema that contains asynchronous refinements or transforms + * and throw a nicely formatted error if it is invalid. + * + * @param schema The Zod schema to use to parse the input. + * @param input Input data that should match the schema. + * @param message Error message preamble to use if the input fails to parse. + * @returns Validated data parsed by Zod. + */ +export async function parseAsyncWithFriendlyErrors<T extends z.Schema>( + schema: T, + input: z.input<T>, + message: string +): Promise<z.output<T>> { + return processParsedData<T>(await schema.safeParseAsync(input, { errorMap }), message); +} + +function processParsedData<T extends z.Schema>( + parsedData: z.SafeParseReturnType<T, T>, + message: string +) { + if (!parsedData.success) { + throw new AstroError(message, parsedData.error.issues.map((i) => i.message).join('\n')); + } + return parsedData.data; +} + +const errorMap: z.ZodErrorMap = (baseError, ctx) => { const baseErrorPath = flattenErrorPath(baseError.path); if (baseError.code === 'invalid_union') { // Optimization: Combine type and literal errors for keys that are common across ALL union types @@ -19,7 +63,7 @@ export const errorMap: z.ZodErrorMap = (baseError, ctx) => { // raise a single error when `key` does not match: // > Did not match union. // > key: Expected `'tutorial' | 'blog'`, received 'foo' - let typeOrLiteralErrByPath: Map<string, TypeOrLiteralErrByPathEntry> = new Map(); + const typeOrLiteralErrByPath: Map<string, TypeOrLiteralErrByPathEntry> = new Map(); for (const unionError of baseError.unionErrors.map((e) => e.errors).flat()) { if (unionError.code === 'invalid_type' || unionError.code === 'invalid_literal') { const flattenedErrorPath = flattenErrorPath(unionError.path); @@ -28,42 +72,68 @@ export const errorMap: z.ZodErrorMap = (baseError, ctx) => { } else { typeOrLiteralErrByPath.set(flattenedErrorPath, { code: unionError.code, - received: (unionError as any).received, + received: unionError.received, expected: [unionError.expected], }); } } } - let messages: string[] = [ - prefix( - baseErrorPath, - typeOrLiteralErrByPath.size ? 'Did not match union:' : 'Did not match union.' - ), - ]; + const messages: string[] = [prefix(baseErrorPath, 'Did not match union.')]; + const details: string[] = [...typeOrLiteralErrByPath.entries()] + // If type or literal error isn't common to ALL union types, + // filter it out. Can lead to confusing noise. + .filter(([, error]) => error.expected.length === baseError.unionErrors.length) + .map(([key, error]) => + key === baseErrorPath + ? // Avoid printing the key again if it's a base error + `> ${getTypeOrLiteralMsg(error)}` + : `> ${prefix(key, getTypeOrLiteralMsg(error))}` + ); + + if (details.length === 0) { + const expectedShapes: string[] = []; + for (const unionError of baseError.unionErrors) { + const expectedShape: string[] = []; + for (const issue of unionError.issues) { + // If the issue is a nested union error, show the associated error message instead of the + // base error message. + if (issue.code === 'invalid_union') { + return errorMap(issue, ctx); + } + const relativePath = flattenErrorPath(issue.path) + .replace(baseErrorPath, '') + .replace(leadingPeriod, ''); + if ('expected' in issue && typeof issue.expected === 'string') { + expectedShape.push( + relativePath ? `${relativePath}: ${issue.expected}` : issue.expected + ); + } else { + expectedShape.push(relativePath); + } + } + if (expectedShape.length === 1 && !expectedShape[0]?.includes(':')) { + // In this case the expected shape is not an object, but probably a literal type, e.g. `['string']`. + expectedShapes.push(expectedShape.join('')); + } else { + expectedShapes.push(`{ ${expectedShape.join('; ')} }`); + } + } + if (expectedShapes.length) { + details.push('> Expected type `' + expectedShapes.join(' | ') + '`'); + details.push('> Received `' + stringify(ctx.data) + '`'); + } + } + return { - message: messages - .concat( - [...typeOrLiteralErrByPath.entries()] - // If type or literal error isn't common to ALL union types, - // filter it out. Can lead to confusing noise. - .filter(([, error]) => error.expected.length === baseError.unionErrors.length) - .map(([key, error]) => - key === baseErrorPath - ? // Avoid printing the key again if it's a base error - `> ${getTypeOrLiteralMsg(error)}` - : `> ${prefix(key, getTypeOrLiteralMsg(error))}` - ) - ) - .join('\n'), + message: messages.concat(details).join('\n'), }; - } - if (baseError.code === 'invalid_literal' || baseError.code === 'invalid_type') { + } else if (baseError.code === 'invalid_literal' || baseError.code === 'invalid_type') { return { message: prefix( baseErrorPath, getTypeOrLiteralMsg({ code: baseError.code, - received: (baseError as any).received, + received: baseError.received, expected: [baseError.expected], }) ), @@ -76,29 +146,30 @@ export const errorMap: z.ZodErrorMap = (baseError, ctx) => { }; const getTypeOrLiteralMsg = (error: TypeOrLiteralErrByPathEntry): string => { - if (error.received === 'undefined') return 'Required'; + // received could be `undefined` or the string `'undefined'` + if (typeof error.received === 'undefined' || error.received === 'undefined') return 'Required'; const expectedDeduped = new Set(error.expected); switch (error.code) { case 'invalid_type': - return `Expected type \`${unionExpectedVals(expectedDeduped)}\`, received ${JSON.stringify( + return `Expected type \`${unionExpectedVals(expectedDeduped)}\`, received \`${stringify( error.received - )}`; + )}\``; case 'invalid_literal': - return `Expected \`${unionExpectedVals(expectedDeduped)}\`, received ${JSON.stringify( + return `Expected \`${unionExpectedVals(expectedDeduped)}\`, received \`${stringify( error.received - )}`; + )}\``; } }; const prefix = (key: string, msg: string) => (key.length ? `**${key}**: ${msg}` : msg); const unionExpectedVals = (expectedVals: Set<unknown>) => - [...expectedVals] - .map((expectedVal, idx) => { - if (idx === 0) return JSON.stringify(expectedVal); - const sep = ' | '; - return `${sep}${JSON.stringify(expectedVal)}`; - }) - .join(''); + [...expectedVals].map((expectedVal) => stringify(expectedVal)).join(' | '); const flattenErrorPath = (errorPath: (string | number)[]) => errorPath.join('.'); + +/** `JSON.stringify()` a value with spaces around object/array entries. */ +const stringify = (val: unknown) => + JSON.stringify(val, null, 1).split(newlinePlusWhitespace).join(' '); +const newlinePlusWhitespace = /\n\s*/; +const leadingPeriod = /^\./; diff --git a/packages/starlight/utils/format-path.ts b/packages/starlight/utils/format-path.ts new file mode 100644 index 00000000000..147045a4baf --- /dev/null +++ b/packages/starlight/utils/format-path.ts @@ -0,0 +1,7 @@ +import project from 'virtual:starlight/project-context'; +import { createPathFormatter } from './createPathFormatter'; + +export const formatPath = createPathFormatter({ + format: project.build.format, + trailingSlash: project.trailingSlash, +}); diff --git a/packages/starlight/components/TableOfContents/generateToC.ts b/packages/starlight/utils/generateToC.ts similarity index 86% rename from packages/starlight/components/TableOfContents/generateToC.ts rename to packages/starlight/utils/generateToC.ts index 73c08e3d472..b961ad54e1d 100644 --- a/packages/starlight/components/TableOfContents/generateToC.ts +++ b/packages/starlight/utils/generateToC.ts @@ -1,4 +1,5 @@ import type { MarkdownHeading } from 'astro'; +import { PAGE_TITLE_ID } from '../constants'; export interface TocItem extends MarkdownHeading { children: TocItem[]; @@ -16,7 +17,7 @@ export function generateToC( { minHeadingLevel, maxHeadingLevel, title }: TocOpts ) { headings = headings.filter(({ depth }) => depth >= minHeadingLevel && depth <= maxHeadingLevel); - const toc: Array<TocItem> = [{ depth: 2, slug: '_top', text: title, children: [] }]; + const toc: Array<TocItem> = [{ depth: 2, slug: PAGE_TITLE_ID, text: title, children: [] }]; for (const heading of headings) injectChild(toc, { ...heading, children: [] }); return toc; } diff --git a/packages/starlight/utils/git.ts b/packages/starlight/utils/git.ts index ed253421726..f05fd88ef8f 100644 --- a/packages/starlight/utils/git.ts +++ b/packages/starlight/utils/git.ts @@ -1,96 +1,121 @@ /** - * Heavily inspired by - * https://github.com/facebook/docusaurus/blob/46d2aa231ddb18ed67311b6195260af46d7e8bdc/packages/docusaurus-utils/src/gitUtils.ts - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. + * Git module to be used from the dev server and from the integration. */ -import path from 'node:path'; -import { execaSync } from 'execa'; +import { basename, dirname, relative, resolve } from 'node:path'; +import { realpathSync } from 'node:fs'; +import { spawnSync } from 'node:child_process'; -/** Custom error thrown when git is not found in `PATH`. */ -class GitNotFoundError extends Error {} +export type GitAPI = { + getNewestCommitDate: (file: string) => Date; +}; -/** Custom error thrown when the current file is not tracked by git. */ -class FileNotTrackedError extends Error {} +export const makeAPI = (directory: string): GitAPI => { + return { + getNewestCommitDate: (file) => getNewestCommitDate(resolve(directory, file)), + }; +}; -/** - * Fetches the git history of a file and returns a relevant commit date. - * It gets the commit date instead of author date so that amended commits - * can have their dates updated. - * - * @throws {GitNotFoundError} If git is not found in `PATH`. - * @throws {FileNotTrackedError} If the current file is not tracked by git. - * @throws Also throws when `git log` exited with non-zero, or when it outputs - * unexpected text. - */ -export function getFileCommitDate( - file: string, - age: 'oldest' | 'newest' = 'oldest' -): { - date: Date; - timestamp: number; -} { - try { - const { stdout } = execaSync('which', ['git']); - if (!stdout) { - throw new GitNotFoundError( - `Failed to retrieve git history for "${file}" because git is not installed.` - ); - } - } catch {} +export function getNewestCommitDate(file: string): Date { + const result = spawnSync('git', ['log', '--format=%ct', '--max-count=1', basename(file)], { + cwd: dirname(file), + encoding: 'utf-8', + }); + + if (result.error) { + throw new Error(`Failed to retrieve the git history for file "${file}"`); + } + const output = result.stdout.trim(); + const regex = /^(?<timestamp>\d+)$/; + const match = output.match(regex); + + if (!match?.groups?.timestamp) { + throw new Error(`Failed to validate the timestamp for file "${file}"`); + } + + const timestamp = Number(match.groups.timestamp); + const date = new Date(timestamp * 1000); + return date; +} + +function getRepoRoot(directory: string): string { + const result = spawnSync('git', ['rev-parse', '--show-toplevel'], { + cwd: directory, + encoding: 'utf-8', + }); + + if (result.error) { + return directory; + } try { - const { stdout } = execaSync('test', ['-f', file]); - if (!stdout) { - throw new Error( - `Failed to retrieve git history for "${file}" because the file does not exist.` - ); - } - } catch {} + return realpathSync(result.stdout.trim()); + } catch { + return directory; + } +} + +export function getAllNewestCommitDate(rootPath: string, docsPath: string): [string, number][] { + const repoRoot = getRepoRoot(docsPath); - const result = execaSync( + const gitLog = spawnSync( 'git', [ 'log', - `--format=%ct`, - '--max-count=1', - ...(age === 'oldest' ? ['--follow', '--diff-filter=A'] : []), + // Format each history entry as t:<seconds since epoch> + '--format=t:%ct', + // In each entry include the name and status for each modified file + '--name-status', '--', - path.basename(file), + docsPath, ], { - cwd: path.dirname(file), + cwd: repoRoot, + encoding: 'utf-8', + // The default `maxBuffer` for `spawnSync` is 1024 * 1024 bytes, a.k.a 1 MB. In big projects, + // the full git history can be larger than this, so we increase this to ~10 MB. For example, + // Cloudflare passed 1 MB with ~4,800 pages and ~17,000 commits. If we get reports of others + // hitting ENOBUFS errors here in the future, we may want to switch to streaming the git log + // with `spawn` instead. + // See https://github.com/withastro/starlight/issues/3154 + maxBuffer: 10 * 1024 * 1024, } ); - if (result.exitCode !== 0) { - throw new Error( - `Failed to retrieve the git history for file "${file}" with exit code ${result.exitCode}: ${result.stderr}` - ); + + if (gitLog.error) { + return []; } - let regex = /^(?<timestamp>\d+)$/; - const output = result.stdout.trim(); + let runningDate = Date.now(); + const latestDates = new Map<string, number>(); - if (!output) { - throw new FileNotTrackedError( - `Failed to retrieve the git history for file "${file}" because the file is not tracked by git.` - ); - } + for (const logLine of gitLog.stdout.split('\n')) { + if (logLine.startsWith('t:')) { + // t:<seconds since epoch> + runningDate = Number.parseInt(logLine.slice(2)) * 1000; + } - const match = output.match(regex); + // - Added files take the format `A\t<file>` + // - Modified files take the format `M\t<file>` + // - Deleted files take the format `D\t<file>` + // - Renamed files take the format `R<count>\t<old>\t<new>` + // - Copied files take the format `C<count>\t<old>\t<new>` + // The name of the file as of the commit being processed is always + // the last part of the log line. + const tabSplit = logLine.lastIndexOf('\t'); + if (tabSplit === -1) continue; + const fileName = logLine.slice(tabSplit + 1); - if (!match) { - throw new Error( - `Failed to retrieve the git history for file "${file}" with unexpected output: ${output}` - ); + const currentLatest = latestDates.get(fileName) || 0; + latestDates.set(fileName, Math.max(currentLatest, runningDate)); } - const timestamp = Number(match.groups!.timestamp); - const date = new Date(timestamp * 1000); + return Array.from(latestDates.entries()).map(([file, date]) => { + const fileFullPath = resolve(repoRoot, file); + let fileInDirectory = relative(rootPath, fileFullPath); + // Format path to unix style path. + fileInDirectory = fileInDirectory?.replace(/\\/g, '/'); - return { date, timestamp }; + return [fileInDirectory, date]; + }); } diff --git a/packages/starlight/utils/gitInlined.ts b/packages/starlight/utils/gitInlined.ts new file mode 100644 index 00000000000..387e67ad789 --- /dev/null +++ b/packages/starlight/utils/gitInlined.ts @@ -0,0 +1,20 @@ +/** + * Git module to be used on production build results. + * The API is based on inlined git information. + */ + +import type { GitAPI, getAllNewestCommitDate } from './git'; + +type InlinedData = ReturnType<typeof getAllNewestCommitDate>; + +export const makeAPI = (data: InlinedData): GitAPI => { + const trackedDocsFiles = new Map(data); + + return { + getNewestCommitDate: (file) => { + const timestamp = trackedDocsFiles.get(file); + if (!timestamp) throw new Error(`Failed to retrieve the git history for file "${file}"`); + return new Date(timestamp); + }, + }; +}; diff --git a/packages/starlight/utils/head.ts b/packages/starlight/utils/head.ts index 25a20917e8f..46d2efd9fb1 100644 --- a/packages/starlight/utils/head.ts +++ b/packages/starlight/utils/head.ts @@ -1,9 +1,126 @@ +import config from 'virtual:starlight/user-config'; +import project from 'virtual:starlight/project-context'; +import { version } from '../package.json'; import { type HeadConfig, HeadConfigSchema, type HeadUserConfig } from '../schemas/head'; +import type { PageProps, RouteDataContext } from './routing/data'; +import { fileWithBase } from './base'; +import { formatCanonical } from './canonical'; +import { localizedUrl } from './localizedUrl'; +import { isAbsoluteUrl } from './url'; -const HeadSchema = HeadConfigSchema(); +const HeadSchema = HeadConfigSchema({ source: 'content' }); + +/** Get the head for the current page. */ +export function getHead( + { entry, lang }: PageProps, + context: RouteDataContext, + siteTitle: string +): HeadConfig { + const { data } = entry; + + const canonical = context.site ? new URL(context.url.pathname, context.site) : undefined; + const canonicalHref = canonical?.href + ? formatCanonical(canonical.href, { + format: project.build.format, + trailingSlash: project.trailingSlash, + }) + : undefined; + const description = data.description || config.description; + + const headDefaults: HeadUserConfig = [ + { tag: 'meta', attrs: { charset: 'utf-8' } }, + { + tag: 'meta', + attrs: { name: 'viewport', content: 'width=device-width, initial-scale=1' }, + }, + { tag: 'title', content: `${data.title} ${config.titleDelimiter} ${siteTitle}` }, + ...(canonicalHref !== undefined + ? ([{ tag: 'link', attrs: { rel: 'canonical', href: canonicalHref } }] as const) + : []), + { tag: 'meta', attrs: { name: 'generator', content: context.generator } }, + { + tag: 'meta', + attrs: { name: 'generator', content: `Starlight v${version}` }, + }, + // Favicon + { + tag: 'link', + attrs: { + rel: 'shortcut icon', + href: isAbsoluteUrl(config.favicon.href) + ? config.favicon.href + : fileWithBase(config.favicon.href), + type: config.favicon.type, + }, + }, + // OpenGraph Tags + { tag: 'meta', attrs: { property: 'og:title', content: data.title } }, + { tag: 'meta', attrs: { property: 'og:type', content: 'article' } }, + ...(canonicalHref !== undefined + ? ([{ tag: 'meta', attrs: { property: 'og:url', content: canonicalHref } }] as const) + : []), + { tag: 'meta', attrs: { property: 'og:locale', content: lang } }, + ...(description !== undefined + ? ([{ tag: 'meta', attrs: { property: 'og:description', content: description } }] as const) + : []), + { tag: 'meta', attrs: { property: 'og:site_name', content: siteTitle } }, + // Twitter Tags + { + tag: 'meta', + attrs: { name: 'twitter:card', content: 'summary_large_image' }, + }, + ]; + + if (description) + headDefaults.push({ + tag: 'meta', + attrs: { name: 'description', content: description }, + }); + + // Link to language alternates. + if (canonical && config.isMultilingual) { + for (const locale in config.locales) { + const localeOpts = config.locales[locale]; + if (!localeOpts) continue; + headDefaults.push({ + tag: 'link', + attrs: { + rel: 'alternate', + hreflang: localeOpts.lang, + href: localizedUrl(canonical, locale, project.trailingSlash).href, + }, + }); + } + } + + // Link to sitemap, but only when `site` is set. + if (context.site) { + headDefaults.push({ + tag: 'link', + attrs: { + rel: 'sitemap', + href: fileWithBase('/sitemap-index.xml'), + }, + }); + } + + // Link to Twitter account if set in Starlight config. + const twitterLink = config.social?.find(({ icon }) => icon === 'twitter' || icon === 'x.com'); + if (twitterLink) { + headDefaults.push({ + tag: 'meta', + attrs: { + name: 'twitter:site', + content: new URL(twitterLink.href).pathname.replace('/', '@'), + }, + }); + } + + return createHead(headDefaults, config.head, data.head); +} /** Create a fully parsed, merged, and sorted head entry array from multiple sources. */ -export function createHead(defaults: HeadUserConfig, ...heads: HeadConfig[]) { +function createHead(defaults: HeadUserConfig, ...heads: HeadConfig[]) { let head = HeadSchema.parse(defaults); for (const next of heads) { head = mergeHead(head, next); @@ -12,7 +129,8 @@ export function createHead(defaults: HeadUserConfig, ...heads: HeadConfig[]) { } /** - * Test if a head config object contains a matching `<title>` or `<meta>` tag. + * Test if a head config object contains a matching `<title>`, `<meta>`, `<link rel="canonical">` + * or `<link rel="sitemap">` tag. * * For example, will return true if `head` already contains * `<meta name="description" content="A">` and the passed `tag` @@ -25,6 +143,12 @@ function hasTag(head: HeadConfig, entry: HeadConfig[number]): boolean { return head.some(({ tag }) => tag === 'title'); case 'meta': return hasOneOf(head, entry, ['name', 'property', 'http-equiv']); + case 'link': + return head.some( + ({ attrs }) => + (entry.attrs?.rel === 'canonical' && attrs?.rel === 'canonical') || + (entry.attrs?.rel === 'sitemap' && attrs?.rel === 'sitemap') + ); default: return false; } @@ -38,7 +162,7 @@ function hasOneOf(head: HeadConfig, entry: HeadConfig[number], keys: string[]): const attr = getAttr(keys, entry); if (!attr) return false; const [key, val] = attr; - return head.some(({ tag, attrs }) => tag === entry.tag && attrs[key] === val); + return head.some(({ tag, attrs }) => tag === entry.tag && attrs?.[key] === val); } /** Find the first matching key–value pair in a head entry’s attributes. */ @@ -48,7 +172,7 @@ function getAttr( ): [key: string, value: string | boolean] | undefined { let attr: [string, string | boolean] | undefined; for (const key of keys) { - const val = entry.attrs[key]; + const val = entry.attrs?.[key]; if (val) { attr = [key, val]; break; @@ -76,6 +200,7 @@ function getImportance(entry: HeadConfig[number]) { // 1. Important meta tags. if ( entry.tag === 'meta' && + entry.attrs && ('charset' in entry.attrs || 'http-equiv' in entry.attrs || entry.attrs.name === 'viewport') ) { return 100; @@ -87,7 +212,12 @@ function getImportance(entry: HeadConfig[number]) { // The default favicon should be below any extra icons that the user may have set // because if several icons are equally appropriate, the last one is used and we // want to use the SVG icon when supported. - if (entry.tag === 'link' && 'rel' in entry.attrs && entry.attrs.rel === 'shortcut icon') { + if ( + entry.tag === 'link' && + entry.attrs && + 'rel' in entry.attrs && + entry.attrs.rel === 'shortcut icon' + ) { return 70; } return 80; diff --git a/packages/starlight/utils/i18n.ts b/packages/starlight/utils/i18n.ts index e00dfc66c27..016947b84c1 100644 --- a/packages/starlight/utils/i18n.ts +++ b/packages/starlight/utils/i18n.ts @@ -1,3 +1,201 @@ +import type { AstroConfig } from 'astro'; +import { AstroError } from 'astro/errors'; +import type { StarlightConfig } from './user-config'; + +/** + * A list of well-known right-to-left languages used as a fallback when determining the text + * direction of a locale is not supported by the `Intl.Locale` API in the current environment. + * + * @see getLocaleDir() + * @see https://en.wikipedia.org/wiki/IETF_language_tag#List_of_common_primary_language_subtags + */ +const wellKnownRTL = ['ar', 'fa', 'he', 'prs', 'ps', 'syc', 'ug', 'ur']; + +/** Information about the built-in default locale used as a fallback when no locales are defined. */ +export const BuiltInDefaultLocale = { ...getLocaleInfo('en'), lang: 'en' }; + +/** + * Processes the Astro and Starlight i18n configurations to generate/update them accordingly: + * + * - If no Astro and Starlight i18n configurations are provided, the built-in default locale is + * used in Starlight and the generated Astro i18n configuration will match it. + * - If only a Starlight i18n configuration is provided, an equivalent Astro i18n configuration is + * generated. + * - If only an Astro i18n configuration is provided, an equivalent Starlight i18n configuration is + * used. + * - If both an Astro and Starlight i18n configurations are provided, an error is thrown. + */ +export function processI18nConfig( + starlightConfig: StarlightConfig, + astroI18nConfig: AstroConfig['i18n'] +) { + // We don't know what to do if both an Astro and Starlight i18n configuration are provided. + if (astroI18nConfig && !starlightConfig.isUsingBuiltInDefaultLocale) { + throw new AstroError( + 'Cannot provide both an Astro `i18n` configuration and a Starlight `locales` configuration.', + 'Remove one of the two configurations.\nSee more at https://starlight.astro.build/guides/i18n/' + ); + } else if (astroI18nConfig) { + // If a Starlight compatible Astro i18n configuration is provided, we generate the matching + // Starlight configuration. + return { + astroI18nConfig, + starlightConfig: { + ...starlightConfig, + ...getStarlightI18nConfig(astroI18nConfig), + } as StarlightConfig, + }; + } + // Otherwise, we generate the Astro i18n configuration based on the Starlight configuration. + return { astroI18nConfig: getAstroI18nConfig(starlightConfig), starlightConfig: starlightConfig }; +} + +/** Generate an Astro i18n configuration based on a Starlight configuration. */ +function getAstroI18nConfig(config: StarlightConfig): NonNullable<AstroConfig['i18n']> { + return { + // When using custom locale `path`s, the default locale must match one of these paths. + // In Starlight, this matches the `locale` property if defined, and we fallback to the `lang` + // property if not (which would be set to the language’s directory name by default). + defaultLocale: + // If the default locale is explicitly set to `root`, we use the `lang` property instead. + (config.defaultLocale.locale === 'root' + ? config.defaultLocale.lang + : (config.defaultLocale.locale ?? config.defaultLocale.lang)) ?? BuiltInDefaultLocale.lang, + locales: config.locales + ? Object.entries(config.locales).map(([locale, localeConfig]) => { + return { + codes: [localeConfig?.lang ?? locale], + path: locale === 'root' ? (localeConfig?.lang ?? BuiltInDefaultLocale.lang) : locale, + }; + }) + : [config.defaultLocale.lang], + routing: { + prefixDefaultLocale: + // Sites with multiple languages without a root locale. + (config.isMultilingual && config.locales?.root === undefined) || + // Sites with a single non-root language different from the built-in default locale. + (!config.isMultilingual && config.locales !== undefined), + redirectToDefaultLocale: false, + fallbackType: 'redirect', + }, + }; +} + +/** Generate a Starlight i18n configuration based on an Astro configuration. */ +function getStarlightI18nConfig( + astroI18nConfig: NonNullable<AstroConfig['i18n']> +): Pick<StarlightConfig, 'isMultilingual' | 'locales' | 'defaultLocale'> { + if (astroI18nConfig.routing === 'manual') { + throw new AstroError( + 'Starlight is not compatible with the `manual` routing option in the Astro i18n configuration.' + ); + } + + const prefixDefaultLocale = astroI18nConfig.routing.prefixDefaultLocale; + const isMultilingual = astroI18nConfig.locales.length > 1; + const isMonolingualWithRootLocale = !isMultilingual && !prefixDefaultLocale; + + const locales = isMonolingualWithRootLocale + ? undefined + : Object.fromEntries( + astroI18nConfig.locales.map((locale) => [ + isDefaultAstroLocale(astroI18nConfig, locale) && !prefixDefaultLocale + ? 'root' + : isAstroLocaleExtendedConfig(locale) + ? locale.path + : locale, + inferStarlightLocaleFromAstroLocale(locale), + ]) + ); + + const defaultAstroLocale = astroI18nConfig.locales.find((locale) => + isDefaultAstroLocale(astroI18nConfig, locale) + ); + + // This should never happen as Astro validation should prevent this case. + if (!defaultAstroLocale) { + throw new AstroError( + 'Astro default locale not found.', + 'This should never happen. Please open a new issue: https://github.com/withastro/starlight/issues/new?template=---01-bug-report.yml' + ); + } + + return { + isMultilingual, + locales, + defaultLocale: { + ...inferStarlightLocaleFromAstroLocale(defaultAstroLocale), + locale: + isMonolingualWithRootLocale || (isMultilingual && !prefixDefaultLocale) + ? undefined + : isAstroLocaleExtendedConfig(defaultAstroLocale) + ? defaultAstroLocale.codes[0] + : defaultAstroLocale, + }, + }; +} + +/** Infer Starlight locale information based on a locale from an Astro i18n configuration. */ +function inferStarlightLocaleFromAstroLocale(astroLocale: AstroLocale) { + const lang = isAstroLocaleExtendedConfig(astroLocale) ? astroLocale.codes[0] : astroLocale; + return { ...getLocaleInfo(lang), lang }; +} + +/** Check if the passed locale is the default locale in an Astro i18n configuration. */ +function isDefaultAstroLocale( + astroI18nConfig: NonNullable<AstroConfig['i18n']>, + locale: AstroLocale +) { + return ( + (isAstroLocaleExtendedConfig(locale) ? locale.path : locale) === astroI18nConfig.defaultLocale + ); +} + +/** + * Check if the passed Astro locale is using the object variant. + * @see AstroLocaleExtendedConfig + */ +function isAstroLocaleExtendedConfig(locale: AstroLocale): locale is AstroLocaleExtendedConfig { + return typeof locale !== 'string'; +} + +/** Returns the locale information such as a label and a direction based on a BCP-47 tag. */ +function getLocaleInfo(lang: string) { + try { + const locale = new Intl.Locale(lang); + const label = new Intl.DisplayNames(locale, { type: 'language' }).of(lang); + if (!label || lang === label) throw new Error('Label not found.'); + return { + label: label[0]?.toLocaleUpperCase(locale) + label.slice(1), + dir: getLocaleDir(locale), + }; + } catch { + throw new AstroError( + `Failed to get locale information for the '${lang}' locale.`, + 'Make sure to provide a valid BCP-47 tags (e.g. en, ar, or zh-CN).' + ); + } +} + +/** + * Returns the direction of the passed locale. + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getTextInfo + */ +function getLocaleDir(locale: Intl.Locale): 'ltr' | 'rtl' { + if ('textInfo' in locale) { + // @ts-expect-error - `textInfo` is not typed but is available in v8 based environments. + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return locale.textInfo.direction; + } else if ('getTextInfo' in locale) { + // @ts-expect-error - `getTextInfo` is not typed but is available in some non-v8 based environments. + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access + return locale.getTextInfo().direction; + } + // Firefox does not support `textInfo` or `getTextInfo` yet so we fallback to a well-known list + // of right-to-left languages. + return wellKnownRTL.includes(locale.language) ? 'rtl' : 'ltr'; +} + /** * Get the string for the passed language from a dictionary object. * @@ -14,3 +212,6 @@ export function pickLang<T extends Record<string, string>>( ): string | undefined { return dictionary[lang]; } + +type AstroLocale = NonNullable<AstroConfig['i18n']>['locales'][number]; +type AstroLocaleExtendedConfig = Exclude<AstroLocale, string>; diff --git a/packages/starlight/utils/localizedUrl.ts b/packages/starlight/utils/localizedUrl.ts index c7e35255830..5b9debee66b 100644 --- a/packages/starlight/utils/localizedUrl.ts +++ b/packages/starlight/utils/localizedUrl.ts @@ -1,9 +1,15 @@ import config from 'virtual:starlight/user-config'; +import { stripTrailingSlash } from './path'; +import type { AstroConfig } from 'astro'; /** * Get the equivalent of the passed URL for the passed locale. */ -export function localizedUrl(url: URL, locale: string | undefined): URL { +export function localizedUrl( + url: URL, + locale: string | undefined, + trailingSlash: AstroConfig['trailingSlash'] +): URL { // Create a new URL object to void mutating the global. url = new URL(url); if (!config.locales) { @@ -12,21 +18,34 @@ export function localizedUrl(url: URL, locale: string | undefined): URL { } if (locale === 'root') locale = ''; /** Base URL with trailing `/` stripped. */ - const base = import.meta.env.BASE_URL.replace(/\/$/, ''); + const base = stripTrailingSlash(import.meta.env.BASE_URL); const hasBase = url.pathname.startsWith(base); // Temporarily remove base to simplify if (hasBase) url.pathname = url.pathname.replace(base, ''); const [_leadingSlash, baseSegment] = url.pathname.split('/'); - if (baseSegment && baseSegment in config.locales) { + // Strip .html extension to handle file output builds where URL might be e.g. `/en.html` + const htmlExt = '.html'; + const isRootHtml = baseSegment?.endsWith(htmlExt); + const baseSlug = isRootHtml ? baseSegment?.slice(0, -1 * htmlExt.length) : baseSegment; + if (baseSlug && baseSlug in config.locales) { // We’re in a localized route, substitute the new locale (or strip for root lang). - url.pathname = locale - ? url.pathname.replace(baseSegment, locale) - : url.pathname.replace('/' + baseSegment, ''); + if (locale) { + url.pathname = url.pathname.replace(baseSlug, locale); + } else if (isRootHtml) { + url.pathname = '/index.html'; + } else { + url.pathname = url.pathname.replace('/' + baseSlug, ''); + } } else if (locale) { // We’re in the root language. Inject the new locale if we have one. - url.pathname = '/' + locale + url.pathname; + if (baseSegment === 'index.html') { + url.pathname = '/' + locale + '.html'; + } else { + url.pathname = '/' + locale + url.pathname; + } } // Restore base if (hasBase) url.pathname = base + url.pathname; + if (trailingSlash === 'never') url.pathname = stripTrailingSlash(url.pathname); return url; } diff --git a/packages/starlight/utils/navigation.ts b/packages/starlight/utils/navigation.ts index 88d9e3e1e66..079663cc1c8 100644 --- a/packages/starlight/utils/navigation.ts +++ b/packages/starlight/utils/navigation.ts @@ -1,32 +1,43 @@ -import { basename, dirname } from 'node:path'; +import { AstroError } from 'astro/errors'; +import project from 'virtual:starlight/project-context'; import config from 'virtual:starlight/user-config'; +import type { Badge, I18nBadge, I18nBadgeConfig } from '../schemas/badge'; import type { PrevNextLinkConfig } from '../schemas/prevNextLink'; -import { pathWithBase } from './base'; -import { pickLang } from './i18n'; -import { getLocaleRoutes, type Route } from './routing'; -import { localeToLang, slugToPathname } from './slugs'; -import type { AutoSidebarGroup, SidebarItem, SidebarLinkItem } from './user-config'; -import { ensureLeadingAndTrailingSlashes, ensureTrailingSlash } from './path'; -import type { Badge } from '../schemas/badge'; +import type { + AutoSidebarGroup, + InternalSidebarLinkItem, + LinkHTMLAttributes, + SidebarItem, + SidebarLinkItem, +} from '../schemas/sidebar'; +import { getCollectionPathFromRoot } from './collection'; +import { createPathFormatter } from './createPathFormatter'; +import { formatPath } from './format-path'; +import { BuiltInDefaultLocale, pickLang } from './i18n'; +import { + ensureLeadingSlash, + ensureTrailingSlash, + stripExtension, + stripLeadingAndTrailingSlashes, +} from './path'; +import { getLocaleRoutes, routes } from './routing'; +import type { + SidebarGroup, + SidebarLink, + PaginationLinks, + Route, + SidebarEntry, +} from './routing/types'; +import { localeToLang, localizedId, slugToPathname } from './slugs'; +import { isAbsoluteUrl } from './url'; +import type { StarlightConfig } from './user-config'; const DirKey = Symbol('DirKey'); +const SlugKey = Symbol('SlugKey'); -export interface Link { - type: 'link'; - label: string; - href: string; - isCurrent: boolean; - badge: Badge | undefined; -} +const neverPathFormatter = createPathFormatter({ trailingSlash: 'never' }); -interface Group { - type: 'group'; - label: string; - entries: (Link | Group)[]; - collapsed: boolean; -} - -export type SidebarEntry = Link | Group; +const docsCollectionPathFromRoot = getCollectionPathFromRoot('docs', project); /** * A representation of the route structure. For each object entry: @@ -36,14 +47,16 @@ export type SidebarEntry = Link | Group; */ interface Dir { [DirKey]: undefined; + [SlugKey]: string; [item: string]: Dir | Route; } /** Create a new directory object. */ -function makeDir(): Dir { +function makeDir(slug: string): Dir { const dir = {} as Dir; - // Add DirKey as a non-enumerable property so that `Object.entries(dir)` ignores it. + // Add DirKey and SlugKey as non-enumerable properties so that `Object.entries(dir)` ignores them. Object.defineProperty(dir, DirKey, { enumerable: false }); + Object.defineProperty(dir, SlugKey, { value: slug, enumerable: false }); return dir; } @@ -60,15 +73,19 @@ function configItemToEntry( routes: Route[] ): SidebarEntry { if ('link' in item) { - return linkFromConfig(item, locale, currentPathname); + return linkFromSidebarLinkItem(item, locale); } else if ('autogenerate' in item) { return groupFromAutogenerateConfig(item, locale, routes, currentPathname); + } else if ('slug' in item) { + return linkFromInternalSidebarLinkItem(item, locale); } else { + const label = pickLang(item.translations, localeToLang(locale)) || item.label; return { type: 'group', - label: pickLang(item.translations, localeToLang(locale)) || item.label, + label, entries: item.items.map((i) => configItemToEntry(i, currentPathname, locale, routes)), collapsed: item.collapsed, + badge: getSidebarBadge(item.badge, locale, label), }; } } @@ -79,49 +96,117 @@ function groupFromAutogenerateConfig( locale: string | undefined, routes: Route[], currentPathname: string -): Group { - const { collapsed: subgroupCollapsed, directory } = item.autogenerate; +): SidebarGroup { + const { attrs, collapsed: subgroupCollapsed, directory } = item.autogenerate; const localeDir = locale ? locale + '/' + directory : directory; - const dirDocs = routes.filter( - (doc) => + const dirDocs = routes.filter((doc) => { + const filePathFromContentDir = getRoutePathRelativeToCollectionRoot(doc, locale); + return ( // Match against `foo.md` or `foo/index.md`. - stripExtension(doc.id) === localeDir || + stripExtension(filePathFromContentDir) === localeDir || // Match against `foo/anything/else.md`. - doc.id.startsWith(localeDir + '/') - ); - const tree = treeify(dirDocs, localeDir); + filePathFromContentDir.startsWith(localeDir + '/') + ); + }); + const tree = treeify(dirDocs, locale, localeDir); + const label = pickLang(item.translations, localeToLang(locale)) || item.label; return { type: 'group', - label: pickLang(item.translations, localeToLang(locale)) || item.label, - entries: sidebarFromDir(tree, currentPathname, locale, subgroupCollapsed ?? item.collapsed), + label, + entries: sidebarFromDir( + tree, + currentPathname, + locale, + subgroupCollapsed ?? item.collapsed, + attrs + ), collapsed: item.collapsed, + badge: getSidebarBadge(item.badge, locale, label), }; } -/** Check if a string starts with one of `http://` or `https://`. */ -const isAbsolute = (link: string) => /^https?:\/\//.test(link); - -/** Create a link entry from a user config object. */ -function linkFromConfig( - item: SidebarLinkItem, - locale: string | undefined, - currentPathname: string -) { +/** Create a link entry from a manual link item in user config. */ +function linkFromSidebarLinkItem(item: SidebarLinkItem, locale: string | undefined) { let href = item.link; - if (!isAbsolute(href)) { - href = ensureLeadingAndTrailingSlashes(href); + if (!isAbsoluteUrl(href)) { + href = ensureLeadingSlash(href); // Inject current locale into link. if (locale) href = '/' + locale + href; } const label = pickLang(item.translations, localeToLang(locale)) || item.label; - return makeLink(href, label, currentPathname, item.badge); + return makeSidebarLink(href, label, getSidebarBadge(item.badge, locale, label), item.attrs); +} + +/** Create a link entry from an automatic internal link item in user config. */ +function linkFromInternalSidebarLinkItem( + item: InternalSidebarLinkItem, + locale: string | undefined +) { + // Astro passes root `index.[md|mdx]` entries with a slug of `index` + const slug = item.slug === 'index' ? '' : item.slug; + const localizedSlug = locale ? (slug ? locale + '/' + slug : locale) : slug; + const route = routes.find((entry) => localizedSlug === entry.slug); + if (!route) { + const hasExternalSlashes = item.slug.at(0) === '/' || item.slug.at(-1) === '/'; + if (hasExternalSlashes) { + throw new AstroError( + `The slug \`"${item.slug}"\` specified in the Starlight sidebar config must not start or end with a slash.`, + `Please try updating \`"${item.slug}"\` to \`"${stripLeadingAndTrailingSlashes(item.slug)}"\`.` + ); + } else { + throw new AstroError( + `The slug \`"${item.slug}"\` specified in the Starlight sidebar config does not exist.`, + 'Update the Starlight config to reference a valid entry slug in the docs content collection.\n' + + 'Learn more about Astro content collection slugs at https://docs.astro.build/en/reference/modules/astro-content/#getentry' + ); + } + } + const frontmatter = route.entry.data; + const label = + pickLang(item.translations, localeToLang(locale)) || + item.label || + frontmatter.sidebar?.label || + frontmatter.title; + const badge = item.badge ?? frontmatter.sidebar?.badge; + const attrs = { ...frontmatter.sidebar?.attrs, ...item.attrs }; + return makeSidebarLink( + slugToPathname(route.slug), + label, + getSidebarBadge(badge, locale, label), + attrs + ); } -/** Create a link entry. */ -function makeLink(href: string, label: string, currentPathname: string, badge?: Badge): Link { - if (!isAbsolute(href)) href = pathWithBase(href); - const isCurrent = href === ensureTrailingSlash(currentPathname); - return { type: 'link', label, href, isCurrent, badge }; +/** Process sidebar link options to create a link entry. */ +function makeSidebarLink( + href: string, + label: string, + badge?: Badge, + attrs?: LinkHTMLAttributes +): SidebarLink { + if (!isAbsoluteUrl(href)) { + href = formatPath(href); + } + return makeLink({ label, href, badge, attrs }); +} + +/** Create a link entry */ +function makeLink({ + attrs = {}, + badge = undefined, + ...opts +}: { + label: string; + href: string; + badge?: Badge | undefined; + attrs?: LinkHTMLAttributes | undefined; +}): SidebarLink { + return { type: 'link', ...opts, badge, isCurrent: false, attrs }; +} + +/** Test if two paths are equivalent even if formatted differently. */ +function pathsMatch(pathA: string, pathB: string) { + return neverPathFormatter(pathA) === neverPathFormatter(pathB); } /** Get the segments leading to a page. */ @@ -131,47 +216,68 @@ function getBreadcrumbs(path: string, baseDir: string): string[] { // Index paths will match `baseDir` and don’t include breadcrumbs. if (pathWithoutExt === baseDir) return []; // Ensure base directory ends in a trailing slash. - if (!baseDir.endsWith('/')) baseDir += '/'; + baseDir = ensureTrailingSlash(baseDir); // Strip base directory from path if present. const relativePath = pathWithoutExt.startsWith(baseDir) ? pathWithoutExt.replace(baseDir, '') : pathWithoutExt; - let dir = dirname(relativePath); - // Return no breadcrumbs for items in the root directory. - if (dir === '.') return []; - return dir.split('/'); + + return relativePath.split('/'); +} + +/** Return the path of a route relative to the root of the collection, which is equivalent to legacy IDs. */ +function getRoutePathRelativeToCollectionRoot(route: Route, locale: string | undefined) { + return project.legacyCollections + ? route.id + : // For collections with a loader, use a localized filePath relative to the collection + localizedId(route.entry.filePath.replace(`${docsCollectionPathFromRoot}/`, ''), locale); } /** Turn a flat array of routes into a tree structure. */ -function treeify(routes: Route[], baseDir: string): Dir { - const treeRoot: Dir = makeDir(); +function treeify(routes: Route[], locale: string | undefined, baseDir: string): Dir { + const treeRoot: Dir = makeDir(baseDir); routes // Remove any entries that should be hidden .filter((doc) => !doc.entry.data.sidebar.hidden) - .forEach((doc) => { - const breadcrumbs = getBreadcrumbs(doc.id, baseDir); - - // Walk down the route’s path to generate the tree. - let currentDir = treeRoot; - breadcrumbs.forEach((dir) => { - // Create new folder if needed. - if (typeof currentDir[dir] === 'undefined') currentDir[dir] = makeDir(); - // Go into the subdirectory. - currentDir = currentDir[dir] as Dir; + // Compute the path of each entry from the root of the collection ahead of time. + .map((doc) => [getRoutePathRelativeToCollectionRoot(doc, locale), doc] as const) + // Sort by depth, to build the tree depth first. + .sort(([a], [b]) => b.split('/').length - a.split('/').length) + // Build the tree + .forEach(([filePathFromContentDir, doc]) => { + const parts = getBreadcrumbs(filePathFromContentDir, baseDir); + let currentNode = treeRoot; + + parts.forEach((part, index) => { + const isLeaf = index === parts.length - 1; + + // Handle directory index pages by renaming them to `index` + if (isLeaf && Object.hasOwn(currentNode, part)) { + currentNode = currentNode[part] as Dir; + part = 'index'; + } + + // Recurse down the tree if this isn’t the leaf node. + if (!isLeaf) { + const path = currentNode[SlugKey]; + currentNode[part] ||= makeDir(stripLeadingAndTrailingSlashes(path + '/' + part)); + currentNode = currentNode[part] as Dir; + } else { + currentNode[part] = doc; + } }); - // We’ve walked through the path. Register the route in this directory. - currentDir[basename(doc.slug)] = doc; }); + return treeRoot; } /** Create a link entry for a given content collection entry. */ -function linkFromRoute(route: Route, currentPathname: string): Link { - return makeLink( +function linkFromRoute(route: Route, attrs?: LinkHTMLAttributes): SidebarLink { + return makeSidebarLink( slugToPathname(route.slug), route.entry.data.sidebar.label || route.entry.data.title, - currentPathname, - route.entry.data.sidebar.badge + route.entry.data.sidebar.badge, + { ...attrs, ...route.entry.data.sidebar.attrs } ); } @@ -183,21 +289,18 @@ function getOrder(routeOrDir: Route | Dir): number { return isDir(routeOrDir) ? Math.min(...Object.values(routeOrDir).flatMap(getOrder)) : // If no order value is found, set it to the largest number possible. - routeOrDir.entry.data.sidebar.order ?? Number.MAX_VALUE; + (routeOrDir.entry.data.sidebar.order ?? Number.MAX_VALUE); } /** Sort a directory’s entries by user-specified order or alphabetically if no order specified. */ -function sortDirEntries( - dir: [string, Dir | Route][], - locale: string | undefined -): [string, Dir | Route][] { - const collator = new Intl.Collator(localeToLang(locale)); - return dir.sort(([keyA, a], [keyB, b]) => { +function sortDirEntries(dir: [string, Dir | Route][]): [string, Dir | Route][] { + const collator = new Intl.Collator(localeToLang(undefined)); + return dir.sort(([_keyA, a], [_keyB, b]) => { const [aOrder, bOrder] = [getOrder(a), getOrder(b)]; // Pages are sorted by order in ascending order. if (aOrder !== bOrder) return aOrder < bOrder ? -1 : 1; // If two pages have the same order value they will be sorted by their slug. - return collator.compare(isDir(a) ? keyA : a.slug, isDir(b) ? keyB : b.slug); + return collator.compare(isDir(a) ? a[SlugKey] : a.slug, isDir(b) ? b[SlugKey] : b.slug); }); } @@ -208,16 +311,18 @@ function groupFromDir( dirName: string, currentPathname: string, locale: string | undefined, - collapsed: boolean -): Group { - const entries = sortDirEntries(Object.entries(dir), locale).map(([key, dirOrRoute]) => - dirToItem(dirOrRoute, `${fullPath}/${key}`, key, currentPathname, locale, collapsed) + collapsed: boolean, + attrs?: LinkHTMLAttributes +): SidebarGroup { + const entries = sortDirEntries(Object.entries(dir)).map(([key, dirOrRoute]) => + dirToItem(dirOrRoute, `${fullPath}/${key}`, key, currentPathname, locale, collapsed, attrs) ); return { type: 'group', label: dirName, entries, collapsed, + badge: undefined, }; } @@ -228,11 +333,12 @@ function dirToItem( dirName: string, currentPathname: string, locale: string | undefined, - collapsed: boolean + collapsed: boolean, + attrs?: LinkHTMLAttributes ): SidebarEntry { return isDir(dirOrRoute) - ? groupFromDir(dirOrRoute, fullPath, dirName, currentPathname, locale, collapsed) - : linkFromRoute(dirOrRoute, currentPathname); + ? groupFromDir(dirOrRoute, fullPath, dirName, currentPathname, locale, collapsed, attrs) + : linkFromRoute(dirOrRoute, attrs); } /** Create a sidebar entry for a given content directory. */ @@ -240,26 +346,112 @@ function sidebarFromDir( tree: Dir, currentPathname: string, locale: string | undefined, - collapsed: boolean + collapsed: boolean, + attrs?: LinkHTMLAttributes ) { - return sortDirEntries(Object.entries(tree), locale).map(([key, dirOrRoute]) => - dirToItem(dirOrRoute, key, key, currentPathname, locale, collapsed) + return sortDirEntries(Object.entries(tree)).map(([key, dirOrRoute]) => + dirToItem(dirOrRoute, key, key, currentPathname, locale, collapsed, attrs) ); } -/** Get the sidebar for the current page. */ +/** + * Intermediate sidebar represents sidebar entries generated from the user config for a specific + * locale and do not contain any information about the current page. + * These representations are cached per locale to avoid regenerating them for each page. + * When generating the final sidebar for a page, the intermediate sidebar is cloned and the current + * page is marked as such. + * + * @see getSidebarFromIntermediateSidebar + */ +const intermediateSidebars = new Map<string | undefined, SidebarEntry[]>(); + +/** Get the sidebar for the current page using the global config. */ export function getSidebar(pathname: string, locale: string | undefined): SidebarEntry[] { + let intermediateSidebar = intermediateSidebars.get(locale); + if (!intermediateSidebar) { + intermediateSidebar = getIntermediateSidebarFromConfig(config.sidebar, pathname, locale); + intermediateSidebars.set(locale, intermediateSidebar); + } + return getSidebarFromIntermediateSidebar(intermediateSidebar, pathname); +} + +/** Get the sidebar for the current page using the specified sidebar config. */ +export function getSidebarFromConfig( + sidebarConfig: StarlightConfig['sidebar'], + pathname: string, + locale: string | undefined +): SidebarEntry[] { + const intermediateSidebar = getIntermediateSidebarFromConfig(sidebarConfig, pathname, locale); + return getSidebarFromIntermediateSidebar(intermediateSidebar, pathname); +} + +/** Get the intermediate sidebar for the current page using the specified sidebar config. */ +function getIntermediateSidebarFromConfig( + sidebarConfig: StarlightConfig['sidebar'], + pathname: string, + locale: string | undefined +): SidebarEntry[] { const routes = getLocaleRoutes(locale); - if (config.sidebar) { - return config.sidebar.map((group) => configItemToEntry(group, pathname, locale, routes)); + if (sidebarConfig) { + return sidebarConfig.map((group) => configItemToEntry(group, pathname, locale, routes)); } else { - const tree = treeify(routes, locale || ''); + const tree = treeify(routes, locale, locale || ''); return sidebarFromDir(tree, pathname, locale, false); } } +/** Transform an intermediate sidebar into a sidebar for the current page. */ +function getSidebarFromIntermediateSidebar( + intermediateSidebar: SidebarEntry[], + pathname: string +): SidebarEntry[] { + const sidebar = structuredClone(intermediateSidebar); + setIntermediateSidebarCurrentEntry(sidebar, pathname); + return sidebar; +} + +/** Marks the current page as such in an intermediate sidebar. */ +function setIntermediateSidebarCurrentEntry( + intermediateSidebar: SidebarEntry[], + pathname: string +): boolean { + for (const entry of intermediateSidebar) { + if (entry.type === 'link' && pathsMatch(encodeURI(entry.href), pathname)) { + entry.isCurrent = true; + return true; + } + + if (entry.type === 'group' && setIntermediateSidebarCurrentEntry(entry.entries, pathname)) { + return true; + } + } + return false; +} + +/** Generates a deterministic string based on the content of the passed sidebar. */ +export function getSidebarHash(sidebar: SidebarEntry[]): string { + let hash = 0; + const sidebarIdentity = recursivelyBuildSidebarIdentity(sidebar); + for (let i = 0; i < sidebarIdentity.length; i++) { + const char = sidebarIdentity.charCodeAt(i); + hash = (hash << 5) - hash + char; + } + return (hash >>> 0).toString(36).padStart(7, '0'); +} + +/** Recurses through a sidebar tree to generate a string concatenating labels and link hrefs. */ +function recursivelyBuildSidebarIdentity(sidebar: SidebarEntry[]): string { + return sidebar + .flatMap((entry) => + entry.type === 'group' + ? entry.label + recursivelyBuildSidebarIdentity(entry.entries) + : entry.label + entry.href + ) + .join(''); +} + /** Turn the nested tree structure of a sidebar into a flat list of all the links. */ -export function flattenSidebar(sidebar: SidebarEntry[]): Link[] { +export function flattenSidebar(sidebar: SidebarEntry[]): SidebarLink[] { return sidebar.flatMap((entry) => entry.type === 'group' ? flattenSidebar(entry.entries) : entry ); @@ -273,10 +465,7 @@ export function getPrevNextLinks( prev?: PrevNextLinkConfig; next?: PrevNextLinkConfig; } -): { - prev: Link | undefined; - next: Link | undefined; -} { +): PaginationLinks { const entries = flattenSidebar(sidebar); const currentIndex = entries.findIndex((entry) => entry.isCurrent); const prev = applyPrevNextLinkConfig(entries[currentIndex - 1], paginationEnabled, config.prev); @@ -290,10 +479,10 @@ export function getPrevNextLinks( /** Apply a prev/next link config to a navigation link. */ function applyPrevNextLinkConfig( - link: Link | undefined, + link: SidebarLink | undefined, paginationEnabled: boolean, config: PrevNextLinkConfig | undefined -): Link | undefined { +): SidebarLink | undefined { // Explicitly remove the link. if (config === false) return undefined; // Use the generated link if any. @@ -308,16 +497,50 @@ function applyPrevNextLinkConfig( ...link, label: config.label ?? link.label, href: config.link ?? link.href, + // Explicitly remove sidebar link attributes for prev/next links. + attrs: {}, }; } else if (config.link && config.label) { // If there is no link and the frontmatter contains both a URL and a label, // create a new link. - return makeLink(config.link, config.label, config.link); + return makeLink({ href: config.link, label: config.label }); } } // Otherwise, if the global config is enabled, return the generated link if any. return paginationEnabled ? link : undefined; } -/** Remove the extension from a path. */ -const stripExtension = (path: string) => path.replace(/\.\w+$/, ''); +/** Get a sidebar badge for a given item. */ +function getSidebarBadge( + config: I18nBadgeConfig, + locale: string | undefined, + itemLabel: string +): Badge | undefined { + if (!config) return; + if (typeof config === 'string') { + return { variant: 'default', text: config }; + } + return { ...config, text: getSidebarBadgeText(config.text, locale, itemLabel) }; +} + +/** Get the badge text for a sidebar item. */ +function getSidebarBadgeText( + text: I18nBadge['text'], + locale: string | undefined, + itemLabel: string +): string { + if (typeof text === 'string') return text; + const defaultLang = + config.defaultLocale?.lang || config.defaultLocale?.locale || BuiltInDefaultLocale.lang; + const defaultText = text[defaultLang]; + + if (!defaultText) { + throw new AstroError( + `The badge text for "${itemLabel}" must have a key for the default language "${defaultLang}".`, + 'Update the Starlight config to include a badge text for the default language.\n' + + 'Learn more about sidebar badges internationalization at https://starlight.astro.build/guides/sidebar/#internationalization-with-badges' + ); + } + + return pickLang(text, localeToLang(locale)) || defaultText; +} diff --git a/packages/starlight/utils/path.ts b/packages/starlight/utils/path.ts index a4fe8b245e9..cf30d0385f9 100644 --- a/packages/starlight/utils/path.ts +++ b/packages/starlight/utils/path.ts @@ -35,3 +35,24 @@ export function stripLeadingAndTrailingSlashes(href: string): string { href = stripTrailingSlash(href); return href; } + +/** Remove the extension from a path. */ +export function stripHtmlExtension(path: string) { + const pathWithoutTrailingSlash = stripTrailingSlash(path); + return pathWithoutTrailingSlash.endsWith('.html') ? pathWithoutTrailingSlash.slice(0, -5) : path; +} + +/** Add '.html' extension to a path. */ +export function ensureHtmlExtension(path: string) { + path = stripLeadingAndTrailingSlashes(path); + if (!path.endsWith('.html')) { + path = path ? path + '.html' : '/index.html'; + } + return ensureLeadingSlash(path); +} + +/** Remove the extension from a path. */ +export function stripExtension(path: string) { + const periodIndex = path.lastIndexOf('.'); + return path.slice(0, periodIndex > -1 ? periodIndex : undefined); +} diff --git a/packages/starlight/utils/plugins.ts b/packages/starlight/utils/plugins.ts new file mode 100644 index 00000000000..d51663e1929 --- /dev/null +++ b/packages/starlight/utils/plugins.ts @@ -0,0 +1,461 @@ +import type { AstroIntegration, HookParameters as AstroHookParameters } from 'astro'; +import { AstroError } from 'astro/errors'; +import { z } from 'astro/zod'; +import { parseWithFriendlyErrors } from '../utils/error-map'; +import { + StarlightConfigSchema, + type StarlightConfig, + type StarlightUserConfig, +} from '../utils/user-config'; +import type { UserI18nSchema } from './translations'; +import { createTranslationSystemFromFs } from './translations-fs'; +import { absolutePathToLang as getAbsolutePathFromLang } from '../integrations/shared/absolutePathToLang'; +import { getCollectionPosixPath } from './collection-fs'; + +/** + * Runs Starlight plugins in the order that they are configured after validating the user-provided + * configuration and returns the final validated user config that may have been updated by the + * plugins and a list of any integrations added by the plugins. + */ +export async function runPlugins( + starlightUserConfig: StarlightUserConfig, + pluginsUserConfig: StarlightPluginsUserConfig, + context: StarlightPluginContext +) { + // Validate the user-provided configuration. + let userConfig = starlightUserConfig; + + let starlightConfig = parseWithFriendlyErrors( + StarlightConfigSchema, + userConfig, + 'Invalid config passed to starlight integration' + ); + + // Validate the user-provided plugins configuration. + const pluginsConfig = parseWithFriendlyErrors( + starlightPluginsConfigSchema, + pluginsUserConfig, + 'Invalid plugins config passed to starlight integration' + ); + + // A list of translations injected by the various plugins keyed by locale. + const pluginTranslations: PluginTranslations = {}; + // A list of route middleware added by the various plugins. + const routeMiddlewareConfigs: Array<z.output<typeof routeMiddlewareConfigSchema>> = []; + + for (const { + hooks: { 'i18n:setup': i18nSetup }, + } of pluginsConfig) { + if (i18nSetup) { + await i18nSetup({ + injectTranslations(translations) { + // Merge the translations injected by the plugin. + for (const [locale, localeTranslations] of Object.entries(translations)) { + pluginTranslations[locale] ??= {}; + Object.assign(pluginTranslations[locale], localeTranslations); + } + }, + }); + } + } + + const useTranslations = await createTranslationSystemFromFs( + starlightConfig, + context.config, + pluginTranslations + ); + + function absolutePathToLang(path: string) { + return getAbsolutePathFromLang(path, { + docsPath: getCollectionPosixPath('docs', context.config.srcDir), + starlightConfig, + }); + } + + // A list of Astro integrations added by the various plugins. + const integrations: AstroIntegration[] = []; + + for (const { + name, + hooks: { 'config:setup': configSetup, setup: deprecatedSetup }, + } of pluginsConfig) { + // A refinement in the schema ensures that at least one of the two hooks is defined. + const setup = (configSetup ?? deprecatedSetup)!; + + await setup({ + config: pluginsUserConfig ? { ...userConfig, plugins: pluginsUserConfig } : userConfig, + updateConfig(newConfig) { + // Ensure that plugins do not update the `plugins` config key. + if ('plugins' in newConfig) { + throw new AstroError( + `The \`${name}\` plugin tried to update the \`plugins\` config key which is not supported.` + ); + } + if ('routeMiddleware' in newConfig) { + throw new AstroError( + `The \`${name}\` plugin tried to update the \`routeMiddleware\` config key which is not supported.`, + 'Use the `addRouteMiddleware()` utility instead.\n' + + 'See https://starlight.astro.build/reference/plugins/#addroutemiddleware for more details.' + ); + } + + // If the plugin is updating the user config, re-validate it. + const mergedUserConfig = { ...userConfig, ...newConfig }; + const mergedConfig = parseWithFriendlyErrors( + StarlightConfigSchema, + mergedUserConfig, + `Invalid config update provided by the '${name}' plugin` + ); + + // If the updated config is valid, keep track of both the user config and parsed config. + userConfig = mergedUserConfig; + starlightConfig = mergedConfig; + }, + addIntegration(integration) { + // Collect any Astro integrations added by the plugin. + integrations.push(integration); + }, + addRouteMiddleware(middlewareConfig) { + routeMiddlewareConfigs.push(middlewareConfig); + }, + astroConfig: { + ...context.config, + integrations: [...context.config.integrations, ...integrations], + }, + command: context.command, + isRestart: context.isRestart, + logger: context.logger.fork(name), + useTranslations, + absolutePathToLang, + }); + } + + applyPluginMiddleware(routeMiddlewareConfigs, starlightConfig); + + return { integrations, starlightConfig, pluginTranslations, useTranslations, absolutePathToLang }; +} + +/** Updates `routeMiddleware` in the Starlight config to add plugin middlewares in the correct order. */ +function applyPluginMiddleware( + routeMiddlewareConfigs: { entrypoint: string; order: 'default' | 'pre' | 'post' }[], + starlightConfig: StarlightConfig +) { + const middlewareBuckets = routeMiddlewareConfigs.reduce< + Record<'pre' | 'default' | 'post', string[]> + >( + (buckets, { entrypoint, order = 'default' }) => { + buckets[order].push(entrypoint); + return buckets; + }, + { pre: [], default: [], post: [] } + ); + starlightConfig.routeMiddleware.unshift(...middlewareBuckets.pre); + starlightConfig.routeMiddleware.push(...middlewareBuckets.default, ...middlewareBuckets.post); +} + +export function injectPluginTranslationsTypes( + translations: PluginTranslations, + injectTypes: AstroHookParameters<'astro:config:done'>['injectTypes'] +) { + const allKeys = new Set<string>(); + + for (const localeTranslations of Object.values(translations)) { + for (const key of Object.keys(localeTranslations)) { + allKeys.add(key); + } + } + + // If there are no translations to inject, we don't need to generate any types or cleanup + // previous ones as they will not be referenced anymore. + if (allKeys.size === 0) return; + + injectTypes({ + filename: 'i18n-plugins.d.ts', + content: `declare namespace StarlightApp { + type PluginUIStringKeys = { + ${[...allKeys].map((key) => `'${key}': string;`).join('\n\t\t')} + }; + interface I18n extends PluginUIStringKeys {} +}`, + }); +} + +// https://github.com/withastro/astro/blob/910eb00fe0b70ca80bd09520ae100e8c78b675b5/packages/astro/src/core/config/schema.ts#L113 +const astroIntegrationSchema = z.object({ + name: z.string(), + hooks: z.object({}).passthrough().default({}), +}) as z.Schema<AstroIntegration>; + +const routeMiddlewareConfigSchema = z.object({ + entrypoint: z.string(), + order: z.enum(['pre', 'post', 'default']).default('default'), +}); + +const baseStarlightPluginSchema = z.object({ + /** Name of the Starlight plugin. */ + name: z.string(), +}); + +const configSetupHookSchema = z + .function( + z.tuple([ + z.object({ + /** + * A read-only copy of the user-supplied Starlight configuration. + * + * Note that this configuration may have been updated by other plugins configured + * before this one. + */ + config: z.any() as z.Schema< + // The configuration passed to plugins should contains the list of plugins. + StarlightUserConfig & { plugins?: z.input<typeof baseStarlightPluginSchema>[] } + >, + /** + * A callback function to update the user-supplied Starlight configuration. + * + * You only need to provide the configuration values that you want to update but no deep + * merge is performed. + * + * @example + * { + * name: 'My Starlight Plugin', + * hooks: { + * 'config:setup'({ updateConfig }) { + * updateConfig({ + * description: 'Custom description', + * }); + * } + * } + * } + */ + updateConfig: z.function( + z.tuple([ + z.record(z.any()) as z.Schema<Partial<Omit<StarlightUserConfig, 'routeMiddleware'>>>, + ]), + z.void() + ), + /** + * A callback function to add an Astro integration required by this plugin. + * + * @see https://docs.astro.build/en/reference/integrations-reference/ + * + * @example + * { + * name: 'My Starlight Plugin', + * hooks: { + * 'config:setup'({ addIntegration }) { + * addIntegration({ + * name: 'My Plugin Astro Integration', + * hooks: { + * 'astro:config:setup': () => { + * // … + * }, + * }, + * }); + * } + * } + * } + */ + addIntegration: z.function(z.tuple([astroIntegrationSchema]), z.void()), + /** + * A callback function to register additional route middleware handlers. + * + * If the order of execution is important, a plugin can use the `order` option to enforce + * running first or last. + * + * @example + * { + * name: 'My Starlight Plugin', + * hooks: { + * setup({ addRouteMiddleware }) { + * addRouteMiddleware({ entrypoint: '@me/my-plugin/route-middleware' }); + * }, + * }, + * } + */ + addRouteMiddleware: z.function(z.tuple([routeMiddlewareConfigSchema]), z.void()), + /** + * A read-only copy of the user-supplied Astro configuration. + * + * Note that this configuration is resolved before any other integrations have run. + * + * @see https://docs.astro.build/en/reference/integrations-reference/#config-option + */ + astroConfig: z.any() as z.Schema<StarlightPluginContext['config']>, + /** + * The command used to run Starlight. + * + * @see https://docs.astro.build/en/reference/integrations-reference/#command-option + */ + command: z.any() as z.Schema<StarlightPluginContext['command']>, + /** + * `false` when the dev server starts, `true` when a reload is triggered. + * + * @see https://docs.astro.build/en/reference/integrations-reference/#isrestart-option + */ + isRestart: z.any() as z.Schema<StarlightPluginContext['isRestart']>, + /** + * An instance of the Astro integration logger with all logged messages prefixed with the + * plugin name. + * + * @see https://docs.astro.build/en/reference/integrations-reference/#astrointegrationlogger + */ + logger: z.any() as z.Schema<StarlightPluginContext['logger']>, + /** + * A callback function to generate a utility function to access UI strings for a given + * language. + * + * @see https://starlight.astro.build/guides/i18n/#using-ui-translations + * + * @example + * { + * name: 'My Starlight Plugin', + * hooks: { + * 'config:setup'({ useTranslations, logger }) { + * const t = useTranslations('en'); + * logger.info(t('builtWithStarlight.label')); + * // ^ Logs 'Built with Starlight' to the console. + * } + * } + * } + */ + useTranslations: z.any() as z.Schema< + Awaited<ReturnType<typeof createTranslationSystemFromFs>> + >, + /** + * A callback function to get the language for a given absolute file path. The returned + * language can be used with the `useTranslations` helper to get UI strings for that + * language. + * + * This can be particularly useful in remark or rehype plugins to get the language for + * the current file being processed and use it to get the appropriate UI strings for that + * language. + * + * @example + * { + * name: 'My Starlight Plugin', + * hooks: { + * 'config:setup'({ absolutePathToLang, useTranslations, logger }) { + * const lang = absolutePathToLang('/absolute/path/to/project/src/content/docs/fr/index.mdx'); + * const t = useTranslations(lang); + * logger.info(t('aside.tip')); + * // ^ Logs 'Astuce' to the console. + * } + * } + * } + */ + absolutePathToLang: z.function(z.tuple([z.string()]), z.string()), + }), + ]), + z.union([z.void(), z.promise(z.void())]) + ) + .optional(); + +/** + * A plugin `config` and `updateConfig` argument are purposely not validated using the Starlight + * user config schema but properly typed for user convenience because we do not want to run any of + * the Zod `transform`s used in the user config schema when running plugins. + */ +const starlightPluginSchema = baseStarlightPluginSchema + .extend({ + /** The different hooks available to the plugin. */ + hooks: z.object({ + /** + * Plugin internationalization setup function allowing to inject translations strings for the + * plugin in various locales. These translations will be available in the `config:setup` hook + * and plugin UI. + */ + 'i18n:setup': z + .function( + z.tuple([ + z.object({ + /** + * A callback function to add or update translations strings. + * + * @see https://starlight.astro.build/guides/i18n/#extend-translation-schema + * + * @example + * { + * name: 'My Starlight Plugin', + * hooks: { + * 'i18n:setup'({ injectTranslations }) { + * injectTranslations({ + * en: { + * 'myPlugin.doThing': 'Do the thing', + * }, + * fr: { + * 'myPlugin.doThing': 'Faire le truc', + * }, + * }); + * } + * } + * } + */ + injectTranslations: z.function( + z.tuple([z.record(z.string(), z.record(z.string(), z.string()))]), + z.void() + ), + }), + ]), + z.union([z.void(), z.promise(z.void())]) + ) + .optional(), + /** + * Plugin configuration setup function called with an object containing various values that + * can be used by the plugin to interact with Starlight. + */ + 'config:setup': configSetupHookSchema, + /** + * @deprecated Use the `config:setup` hook instead as `setup` will be removed in a future + * version. + */ + setup: configSetupHookSchema, + }), + }) + .superRefine((plugin, ctx) => { + if (!plugin.hooks['config:setup'] && !plugin.hooks.setup) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'A plugin must define at least a `config:setup` hook.', + }); + } else if (plugin.hooks['config:setup'] && plugin.hooks.setup) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + 'A plugin cannot define both a `config:setup` and `setup` hook. ' + + 'As `setup` is deprecated and will be removed in a future version, ' + + 'consider using `config:setup` instead.', + }); + } + }); + +const starlightPluginsConfigSchema = z.array(starlightPluginSchema).default([]); + +type StarlightPluginsUserConfig = z.input<typeof starlightPluginsConfigSchema>; + +export type StarlightPlugin = z.input<typeof starlightPluginSchema>; + +export type HookParameters< + Hook extends keyof StarlightPlugin['hooks'], + HookFn = StarlightPlugin['hooks'][Hook], +> = HookFn extends (...args: any[]) => unknown ? Parameters<HookFn>[0] : never; + +export type StarlightUserConfigWithPlugins = StarlightUserConfig & { + /** + * A list of plugins to extend Starlight with. + * + * @example + * // Add Starlight Algolia plugin. + * starlight({ + * plugins: [starlightAlgolia({ … })], + * }) + */ + plugins?: StarlightPluginsUserConfig; +}; + +export type StarlightPluginContext = Pick< + AstroHookParameters<'astro:config:setup'>, + 'command' | 'config' | 'isRestart' | 'logger' +>; + +export type PluginTranslations = Record<string, UserI18nSchema & Record<string, string>>; diff --git a/packages/starlight/utils/routing/data.ts b/packages/starlight/utils/routing/data.ts new file mode 100644 index 00000000000..f968de58da0 --- /dev/null +++ b/packages/starlight/utils/routing/data.ts @@ -0,0 +1,160 @@ +import type { APIContext, MarkdownHeading } from 'astro'; +import project from 'virtual:starlight/project-context'; +import config from 'virtual:starlight/user-config'; +import { generateToC } from '../generateToC'; +import { getNewestCommitDate } from 'virtual:starlight/git-info'; +import { getPrevNextLinks, getSidebar } from '../navigation'; +import { ensureTrailingSlash } from '../path'; +import { getRouteBySlugParam, normalizeCollectionEntry } from '../routing'; +import type { + Route, + StarlightDocsCollectionEntry, + StarlightDocsEntry, + StarlightRouteData, +} from './types'; +import { formatPath } from '../format-path'; +import { useTranslations } from '../translations'; +import { BuiltInDefaultLocale } from '../i18n'; +import { getEntry, type RenderResult } from 'astro:content'; +import { getCollectionPathFromRoot } from '../collection'; +import { getHead } from '../head'; + +export interface PageProps extends Route { + headings: MarkdownHeading[]; +} + +export type RouteDataContext = Pick<APIContext, 'generator' | 'site' | 'url'>; + +export async function getRoute(context: APIContext): Promise<Route> { + return ( + ('slug' in context.params && getRouteBySlugParam(context.params.slug)) || + (await get404Route(context.locals)) + ); +} + +export function useRouteData( + context: APIContext, + route: Route, + { Content, headings }: RenderResult +): StarlightRouteData { + const routeData = generateRouteData({ props: { ...route, headings }, context }); + return { ...routeData, Content }; +} + +export function generateRouteData({ + props, + context, +}: { + props: PageProps; + context: RouteDataContext; +}): StarlightRouteData { + const { entry, locale, lang } = props; + const sidebar = getSidebar(context.url.pathname, locale); + const siteTitle = getSiteTitle(lang); + return { + ...props, + siteTitle, + siteTitleHref: getSiteTitleHref(locale), + sidebar, + hasSidebar: entry.data.template !== 'splash', + pagination: getPrevNextLinks(sidebar, config.pagination, entry.data), + toc: getToC(props), + lastUpdated: getLastUpdated(props), + editUrl: getEditUrl(props), + head: getHead(props, context, siteTitle), + }; +} + +export function getToC({ entry, lang, headings }: PageProps) { + const tocConfig = + entry.data.template === 'splash' + ? false + : entry.data.tableOfContents !== undefined + ? entry.data.tableOfContents + : config.tableOfContents; + if (!tocConfig) return; + const t = useTranslations(lang); + return { + ...tocConfig, + items: generateToC(headings, { ...tocConfig, title: t('tableOfContents.overview') }), + }; +} + +function getLastUpdated({ entry }: PageProps): Date | undefined { + const { lastUpdated: frontmatterLastUpdated } = entry.data; + const { lastUpdated: configLastUpdated } = config; + + if (frontmatterLastUpdated ?? configLastUpdated) { + try { + return frontmatterLastUpdated instanceof Date + ? frontmatterLastUpdated + : getNewestCommitDate(entry.filePath); + } catch { + // If the git command fails, ignore the error. + return undefined; + } + } + + return undefined; +} + +function getEditUrl({ entry }: PageProps): URL | undefined { + const { editUrl } = entry.data; + // If frontmatter value is false, editing is disabled for this page. + if (editUrl === false) return; + + let url: string | undefined; + if (typeof editUrl === 'string') { + // If a URL was provided in frontmatter, use that. + url = editUrl; + } else if (config.editLink.baseUrl) { + // If a base URL was added in Starlight config, synthesize the edit URL from it. + url = ensureTrailingSlash(config.editLink.baseUrl) + entry.filePath; + } + return url ? new URL(url) : undefined; +} + +/** Get the site title for a given language. **/ +export function getSiteTitle(lang: string): string { + const defaultLang = config.defaultLocale.lang as string; + if (lang && config.title[lang]) { + return config.title[lang]; + } + return config.title[defaultLang] as string; +} + +export function getSiteTitleHref(locale: string | undefined): string { + return formatPath(locale || '/'); +} + +/** Generate a route object for Starlight’s 404 page. */ +async function get404Route(locals: App.Locals): Promise<Route> { + const { lang = BuiltInDefaultLocale.lang, dir = BuiltInDefaultLocale.dir } = + config.defaultLocale || {}; + let locale = config.defaultLocale?.locale; + if (locale === 'root') locale = undefined; + + const entryMeta = { dir, lang, locale }; + + const fallbackEntry: StarlightDocsEntry = { + slug: '404', + id: '404', + body: '', + collection: 'docs', + data: { + title: '404', + template: 'splash', + editUrl: false, + head: [], + hero: { tagline: locals.t('404.text'), actions: [] }, + pagefind: false, + sidebar: { hidden: false, attrs: {} }, + draft: false, + }, + filePath: `${getCollectionPathFromRoot('docs', project)}/404.md`, + }; + + const userEntry = (await getEntry('docs', '404')) as StarlightDocsCollectionEntry; + const entry = userEntry ? normalizeCollectionEntry(userEntry) : fallbackEntry; + return { ...entryMeta, entryMeta, entry, id: entry.id, slug: entry.slug }; +} diff --git a/packages/starlight/utils/routing.ts b/packages/starlight/utils/routing/index.ts similarity index 60% rename from packages/starlight/utils/routing.ts rename to packages/starlight/utils/routing/index.ts index 496578ce204..460d15a778f 100644 --- a/packages/starlight/utils/routing.ts +++ b/packages/starlight/utils/routing/index.ts @@ -1,26 +1,16 @@ import type { GetStaticPathsItem } from 'astro'; -import { type CollectionEntry, getCollection } from 'astro:content'; +import { getCollection } from 'astro:content'; import config from 'virtual:starlight/user-config'; -import { - type LocaleData, - localizedId, - localizedSlug, - slugToLocaleData, - slugToParam, -} from './slugs'; +import project from 'virtual:starlight/project-context'; +import { getCollectionPathFromRoot } from '../collection'; +import { localizedId, localizedSlug, slugToLocaleData, slugToParam } from '../slugs'; +import { validateLogoImports } from '../validateLogoImports'; +import { BuiltInDefaultLocale } from '../i18n'; +import type { Route, StarlightDocsCollectionEntry, StarlightDocsEntry } from './types'; -export type StarlightDocsEntry = Omit<CollectionEntry<'docs'>, 'slug'> & { - slug: string; -}; - -export interface Route extends LocaleData { - entry: StarlightDocsEntry; - entryMeta: LocaleData; - slug: string; - id: string; - isFallback?: true; - [key: string]: unknown; -} +// Validate any user-provided logos imported correctly. +// We do this here so all pages trigger it and at the top level so it runs just once. +validateLogoImports(); interface Path extends GetStaticPathsItem { params: { slug: string | undefined }; @@ -34,13 +24,27 @@ interface Path extends GetStaticPathsItem { */ const normalizeIndexSlug = (slug: string) => (slug === 'index' ? '' : slug); -/** All entries in the docs content collection. */ -const docs: StarlightDocsEntry[] = ((await getCollection('docs')) ?? []).map( - ({ slug, ...entry }) => ({ +/** Normalize the different collection entry we can get from a legacy collection or a loader. */ +export function normalizeCollectionEntry(entry: StarlightDocsCollectionEntry): StarlightDocsEntry { + const slug = normalizeIndexSlug(entry.slug ?? entry.id); + return { ...entry, - slug: normalizeIndexSlug(slug), - }) -); + // In a collection with a loader, the `id` is a slug and should be normalized. + id: entry.slug ? entry.id : slug, + // In a legacy collection, the `filePath` property doesn't exist. + filePath: entry.filePath ?? `${getCollectionPathFromRoot('docs', project)}/${entry.id}`, + // In a collection with a loader, the `slug` property is replaced by the `id`. + slug: normalizeIndexSlug(entry.slug ?? entry.id), + }; +} + +/** All entries in the docs content collection. */ +const docs: StarlightDocsEntry[] = ( + (await getCollection('docs', ({ data }) => { + // In production, filter out drafts. + return import.meta.env.MODE !== 'production' || data.draft === false; + })) ?? [] +).map(normalizeCollectionEntry); function getRoutes(): Route[] { const routes: Route[] = docs.map((entry) => ({ @@ -65,7 +69,7 @@ function getRoutes(): Route[] { const localeDocs = getLocaleDocs(locale); for (const fallback of defaultLocaleDocs) { const slug = localizedSlug(fallback.slug, locale); - const id = localizedId(fallback.id, locale); + const id = project.legacyCollections ? localizedId(fallback.id, locale) : slug; const doesNotNeedFallback = localeDocs.some((doc) => doc.slug === slug); if (doesNotNeedFallback) continue; routes.push({ @@ -73,7 +77,7 @@ function getRoutes(): Route[] { slug, id, isFallback: true, - lang: localeConfig.lang || 'en', + lang: localeConfig.lang || BuiltInDefaultLocale.lang, locale, dir: localeConfig.dir, entryMeta: slugToLocaleData(fallback.slug), @@ -86,6 +90,19 @@ function getRoutes(): Route[] { } export const routes = getRoutes(); +function getParamRouteMapping(): ReadonlyMap<string | undefined, Route> { + const map = new Map<string | undefined, Route>(); + for (const route of routes) { + map.set(slugToParam(route.slug), route); + } + return map; +} +const routesBySlugParam = getParamRouteMapping(); + +export function getRouteBySlugParam(slugParam: string | undefined): Route | undefined { + return routesBySlugParam.get(slugParam?.replace(/\/$/, '') || undefined); +} + function getPaths(): Path[] { return routes.map((route) => ({ params: { slug: slugToParam(route.slug) }, diff --git a/packages/starlight/utils/routing/middleware.ts b/packages/starlight/utils/routing/middleware.ts new file mode 100644 index 00000000000..9aa09a55e00 --- /dev/null +++ b/packages/starlight/utils/routing/middleware.ts @@ -0,0 +1,81 @@ +import type { APIContext } from 'astro'; +import { klona } from 'klona/lite'; +import { routeMiddleware } from 'virtual:starlight/route-middleware'; +import type { StarlightRouteData } from './types'; + +/** + * Adds a deep clone of the passed `routeData` object to locals and then runs middleware. + * @param context Astro context object + * @param routeData Initial route data object to attach. + */ +export async function attachRouteDataAndRunMiddleware( + context: APIContext, + routeData: StarlightRouteData +) { + context.locals.starlightRoute = klona(routeData); + const runner = new MiddlewareRunner(context, routeMiddleware); + await runner.run(); +} + +type MiddlewareHandler<T> = (context: T, next: () => Promise<void>) => void | Promise<void>; + +/** + * A middleware function wrapper that only allows a single execution of the wrapped function. + * Subsequent calls to `run()` are no-ops. + */ +class MiddlewareRunnerStep<T> { + #callback: MiddlewareHandler<T> | null; + constructor(callback: MiddlewareHandler<T>) { + this.#callback = callback; + } + async run(context: T, next: () => Promise<void>): Promise<void> { + if (this.#callback) { + await this.#callback(context, next); + this.#callback = null; + } + } +} + +/** + * Class that runs a stack of middleware handlers with an initial context object. + * Middleware functions can mutate properties of the `context` object, but cannot replace it. + * + * @example + * const context = { value: 10 }; + * const timesTwo = async (ctx, next) => { + * await next(); + * ctx.value *= 2; + * }; + * const addFive = async (ctx) => { + * ctx.value += 5; + * } + * const runner = new MiddlewareRunner(context, [timesTwo, addFive]); + * runner.run(); + * console.log(context); // { value: 30 } + */ +class MiddlewareRunner<T> { + #context: T; + #steps: Array<MiddlewareRunnerStep<T>>; + + constructor( + /** Context object passed as the first argument to each middleware function. */ + context: T, + /** Array of middleware functions to run in sequence. */ + stack: Array<MiddlewareHandler<T>> = [] + ) { + this.#context = context; + this.#steps = stack.map((callback) => new MiddlewareRunnerStep(callback)); + } + + async #stepThrough(steps: Array<MiddlewareRunnerStep<T>>) { + let currentStep: MiddlewareRunnerStep<T>; + while (steps.length > 0) { + [currentStep, ...steps] = steps as [MiddlewareRunnerStep<T>, ...MiddlewareRunnerStep<T>[]]; + await currentStep.run(this.#context, async () => this.#stepThrough(steps)); + } + } + + async run() { + await this.#stepThrough(this.#steps); + } +} diff --git a/packages/starlight/utils/routing/types.ts b/packages/starlight/utils/routing/types.ts new file mode 100644 index 00000000000..7a307359571 --- /dev/null +++ b/packages/starlight/utils/routing/types.ts @@ -0,0 +1,99 @@ +import type { MarkdownHeading } from 'astro'; +import type { CollectionEntry, RenderResult } from 'astro:content'; +import type { TocItem } from '../generateToC'; +import type { LinkHTMLAttributes } from '../../schemas/sidebar'; +import type { Badge } from '../../schemas/badge'; +import type { HeadConfig } from '../../schemas/head'; + +export interface LocaleData { + /** Writing direction. */ + dir: 'ltr' | 'rtl'; + /** BCP-47 language tag. */ + lang: string; + /** The base path at which a language is served. `undefined` for root locale slugs. */ + locale: string | undefined; +} + +export interface SidebarLink { + type: 'link'; + label: string; + href: string; + isCurrent: boolean; + badge: Badge | undefined; + attrs: LinkHTMLAttributes; +} + +export interface SidebarGroup { + type: 'group'; + label: string; + entries: (SidebarLink | SidebarGroup)[]; + collapsed: boolean; + badge: Badge | undefined; +} + +export type SidebarEntry = SidebarLink | SidebarGroup; + +export interface PaginationLinks { + /** Link to previous page in the sidebar. */ + prev: SidebarLink | undefined; + /** Link to next page in the sidebar. */ + next: SidebarLink | undefined; +} + +// The type returned from `CollectionEntry` is different for legacy collections and collections +// using a loader. This type is a common subset of both types. +export type StarlightDocsCollectionEntry = Omit< + CollectionEntry<'docs'>, + 'id' | 'filePath' | 'render' | 'slug' +> & { + // Update the `id` property to be a string like in the loader type. + id: string; + // Add the `filePath` property which is only present in the loader type. + filePath?: string; + // Add the `slug` property which is only present in the legacy type. + slug?: string; +}; + +export type StarlightDocsEntry = StarlightDocsCollectionEntry & { + filePath: string; + slug: string; +}; + +export interface Route extends LocaleData { + /** Content collection entry for the current page. Includes frontmatter at `data`. */ + entry: StarlightDocsEntry; + /** Locale metadata for the page content. Can be different from top-level locale values when a page is using fallback content. */ + entryMeta: LocaleData; + /** @deprecated Migrate to the new Content Layer API and use `id` instead. */ + slug: string; + /** The slug or unique ID if using the `legacy.collections` flag. */ + id: string; + /** Whether this page is untranslated in the current language and using fallback content from the default locale. */ + isFallback?: boolean; + [key: string]: unknown; +} + +export interface StarlightRouteData extends Route { + /** Title of the site. */ + siteTitle: string; + /** URL or path used as the link when clicking on the site title. */ + siteTitleHref: string; + /** Array of Markdown headings extracted from the current page. */ + headings: MarkdownHeading[]; + /** Site navigation sidebar entries for this page. */ + sidebar: SidebarEntry[]; + /** Whether or not the sidebar should be displayed on this page. */ + hasSidebar: boolean; + /** Links to the previous and next page in the sidebar if enabled. */ + pagination: PaginationLinks; + /** Table of contents for this page if enabled. */ + toc: { minHeadingLevel: number; maxHeadingLevel: number; items: TocItem[] } | undefined; + /** JS Date object representing when this page was last updated if enabled. */ + lastUpdated: Date | undefined; + /** URL object for the address where this page can be edited if enabled. */ + editUrl: URL | undefined; + /** An Astro component to render the current page’s content if this route is a Markdown page. */ + Content?: RenderResult['Content']; + /** Array of tags to include in the `<head>` of the current page. */ + head: HeadConfig; +} diff --git a/packages/starlight/utils/slugs.ts b/packages/starlight/utils/slugs.ts index 2b45fd8d741..fb8c4bd27b3 100644 --- a/packages/starlight/utils/slugs.ts +++ b/packages/starlight/utils/slugs.ts @@ -1,13 +1,8 @@ import config from 'virtual:starlight/user-config'; - -export interface LocaleData { - /** Writing direction. */ - dir: 'ltr' | 'rtl'; - /** BCP-47 language tag. */ - lang: string; - /** The base path at which a language is served. `undefined` for root locale slugs. */ - locale: string | undefined; -} +import { slugToLocale as getLocaleFromSlug } from '../integrations/shared/slugToLocale'; +import { BuiltInDefaultLocale } from './i18n'; +import { stripTrailingSlash } from './path'; +import type { LocaleData } from './routing/types'; /** * Get the “locale” of a slug. This is the base path at which a language is served. @@ -16,10 +11,7 @@ export interface LocaleData { * @param slug A collection entry slug */ function slugToLocale(slug: string): string | undefined { - const locales = Object.keys(config.locales || {}); - const baseSegment = slug.split('/')[0]; - if (baseSegment && locales.includes(baseSegment)) return baseSegment; - return undefined; + return getLocaleFromSlug(slug, config); } /** Get locale information for a given slug. */ @@ -35,7 +27,7 @@ export function slugToLocaleData(slug: string): LocaleData { export function localeToLang(locale: string | undefined): string { const lang = locale ? config.locales?.[locale]?.lang : config.locales?.root?.lang; const defaultLang = config.defaultLocale?.lang || config.defaultLocale?.locale; - return lang || defaultLang || 'en'; + return lang || defaultLang || BuiltInDefaultLocale.lang; } /** @@ -47,12 +39,18 @@ function localeToDir(locale: string | undefined): 'ltr' | 'rtl' { return dir || config.defaultLocale.dir; } +/** + * Convert a content collection slug to a param as expected by Astro’s router. + * This utility handles stripping `index` from file names and matches + * [Astro’s param sanitization logic](https://github.com/withastro/astro/blob/687d25365a41ff8a9e6da155d3527f841abb70dd/packages/astro/src/core/routing/manifest/generator.ts#L4-L18) + * by normalizing strings to their canonical representations. + * @param slug Content collection slug + * @returns Param compatible with Astro’s router + */ export function slugToParam(slug: string): string | undefined { - return slug === 'index' || slug === '' + return slug === 'index' || slug === '' || slug === '/' ? undefined - : slug.endsWith('/index') - ? slug.replace(/\/index$/, '') - : slug; + : (slug.endsWith('/index') ? slug.slice(0, -6) : slug).normalize(); } export function slugToPathname(slug: string): string { @@ -76,13 +74,14 @@ export function localizedSlug(slug: string, locale: string | undefined): string locale = locale || ''; if (slugLocale === slug) return locale; if (slugLocale) { - return slug.replace(slugLocale + '/', locale ? locale + '/' : '').replace(/\/$/, ''); + return stripTrailingSlash(slug.replace(slugLocale + '/', locale ? locale + '/' : '')); } return slug ? locale + '/' + slug : locale; } /** - * Convert a collection entry ID to a different locale. + * Convert a legacy collection entry ID or filePath relative to the collection root to a different + * locale. * For example, passing an ID of `en/home.md` and a locale of `fr` results in `fr/home.md`. * An undefined locale is treated as the root locale, resulting in `home.md`. * @param id A collection entry ID @@ -101,3 +100,21 @@ export function localizedId(id: string, locale: string | undefined): string { return id; } } + +/** Extract the slug from a URL. */ +export function urlToSlug(url: URL): string { + let pathname = url.pathname; + const base = stripTrailingSlash(import.meta.env.BASE_URL); + if (pathname.startsWith(base)) pathname = pathname.replace(base, ''); + const segments = pathname.split('/'); + const htmlExt = '.html'; + if (segments.at(-1) === 'index.html') { + // Remove trailing `index.html`. + segments.pop(); + } else if (segments.at(-1)?.endsWith(htmlExt)) { + // Remove trailing `.html`. + const last = segments.pop(); + if (last) segments.push(last.slice(0, -1 * htmlExt.length)); + } + return segments.filter(Boolean).join('/'); +} diff --git a/packages/starlight/utils/starlight-page.ts b/packages/starlight/utils/starlight-page.ts new file mode 100644 index 00000000000..5b8b4c6202f --- /dev/null +++ b/packages/starlight/utils/starlight-page.ts @@ -0,0 +1,215 @@ +import { z } from 'astro/zod'; +import { type ContentConfig, type ImageFunction, type SchemaContext } from 'astro:content'; +import project from 'virtual:starlight/project-context'; +import config from 'virtual:starlight/user-config'; +import { getCollectionPathFromRoot } from './collection'; +import { parseWithFriendlyErrors, parseAsyncWithFriendlyErrors } from './error-map'; +import { stripLeadingAndTrailingSlashes } from './path'; +import { + getSiteTitle, + getSiteTitleHref, + getToC, + type PageProps, + type RouteDataContext, +} from './routing/data'; +import type { StarlightDocsEntry, StarlightRouteData } from './routing/types'; +import { slugToLocaleData, urlToSlug } from './slugs'; +import { getPrevNextLinks, getSidebar, getSidebarFromConfig } from './navigation'; +import { docsSchema } from '../schema'; +import type { Prettify, RemoveIndexSignature } from './types'; +import { SidebarItemSchema } from '../schemas/sidebar'; +import type { StarlightConfig, StarlightUserConfig } from './user-config'; +import { getHead } from './head'; + +/** + * The frontmatter schema for Starlight pages derived from the default schema for Starlight’s + * `docs` content collection. + * The frontmatter schema for Starlight pages cannot include some properties which will be omitted + * and some others needs to be refined to a stricter type. + */ +const StarlightPageFrontmatterSchema = async (context: SchemaContext) => { + const userDocsSchema = await getUserDocsSchema(); + const schema = typeof userDocsSchema === 'function' ? userDocsSchema(context) : userDocsSchema; + + return schema.transform((frontmatter) => { + /** + * Starlight pages can only be edited if an edit URL is explicitly provided. + * The `sidebar` frontmatter prop only works for pages in an autogenerated links group. + * Starlight pages edit links cannot be autogenerated. + * + * These changes to the schema are done using a transformer and not using the usual `omit` + * method because when the frontmatter schema is extended by the user, an intersection between + * the default schema and the user schema is created using the `and` method. Intersections in + * Zod returns a `ZodIntersection` object which does not have some methods like `omit` or + * `pick`. + * + * This transformer only sets the `editUrl` default value and removes the `sidebar` property + * from the validated output but does not apply any changes to the input schema type itself so + * this needs to be done manually. + * + * @see StarlightPageFrontmatter + * @see https://github.com/colinhacks/zod#intersections + */ + const { editUrl, sidebar, ...others } = frontmatter; + const pageEditUrl = editUrl === undefined || editUrl === true ? false : editUrl; + return { ...others, editUrl: pageEditUrl }; + }); +}; + +/** + * Type of Starlight pages frontmatter schema. + * We manually refines the `editUrl` type and omit the `sidebar` property as it's not possible to + * do that on the schema itself using Zod but the proper validation is still using a transformer. + * @see StarlightPageFrontmatterSchema + */ +type StarlightPageFrontmatter = Omit< + z.input<Awaited<ReturnType<typeof StarlightPageFrontmatterSchema>>>, + 'editUrl' | 'sidebar' +> & { editUrl?: string | false }; + +/** Parse sidebar prop to ensure it's valid. */ +const validateSidebarProp = ( + sidebarProp: StarlightUserConfig['sidebar'] +): StarlightConfig['sidebar'] => { + return parseWithFriendlyErrors( + SidebarItemSchema.array().optional(), + sidebarProp, + 'Invalid sidebar prop passed to the `<StarlightPage/>` component.' + ); +}; + +/** + * The props accepted by the `<StarlightPage/>` component. + */ +export type StarlightPageProps = Prettify< + // Remove the index signature from `Route`, omit undesired properties and make the rest optional. + Partial<Omit<RemoveIndexSignature<PageProps>, 'entry' | 'entryMeta' | 'id' | 'locale' | 'slug'>> & + // Add the sidebar definitions for a Starlight page. + Partial<Pick<StarlightRouteData, 'hasSidebar'>> & { + sidebar?: StarlightUserConfig['sidebar']; + // And finally add the Starlight page frontmatter properties in a `frontmatter` property. + frontmatter: StarlightPageFrontmatter; + } +>; + +/** + * A docs entry used for Starlight pages meant to be rendered by plugins and which is safe to cast + * to a `StarlightDocsEntry`. + * A Starlight page docs entry cannot be rendered like a content collection entry. + */ +type StarlightPageDocsEntry = Omit<StarlightDocsEntry, 'id' | 'render'> & { + /** + * The unique ID if using the `legacy.collections` for this Starlight page which cannot be + * inferred from codegen like content collection entries or the slug. + */ + id: string; +}; + +export async function generateStarlightPageRouteData({ + props, + context, +}: { + props: StarlightPageProps; + context: RouteDataContext; +}): Promise<StarlightRouteData> { + const { frontmatter, ...routeProps } = props; + const { url } = context; + const slug = urlToSlug(url); + const pageFrontmatter = await getStarlightPageFrontmatter(frontmatter); + const id = project.legacyCollections ? `${stripLeadingAndTrailingSlashes(slug)}.md` : slug; + const localeData = slugToLocaleData(slug); + const sidebar = props.sidebar + ? getSidebarFromConfig(validateSidebarProp(props.sidebar), url.pathname, localeData.locale) + : getSidebar(url.pathname, localeData.locale); + const headings = props.headings ?? []; + const pageDocsEntry: StarlightPageDocsEntry = { + id, + slug, + body: '', + collection: 'docs', + filePath: `${getCollectionPathFromRoot('docs', project)}/${stripLeadingAndTrailingSlashes(slug)}.md`, + data: { + ...pageFrontmatter, + sidebar: { + attrs: {}, + hidden: false, + }, + }, + }; + const entry = pageDocsEntry as StarlightDocsEntry; + const entryMeta: StarlightRouteData['entryMeta'] = { + dir: props.dir ?? localeData.dir, + lang: props.lang ?? localeData.lang, + locale: localeData.locale, + }; + const editUrl = pageFrontmatter.editUrl ? new URL(pageFrontmatter.editUrl) : undefined; + const lastUpdated = + pageFrontmatter.lastUpdated instanceof Date ? pageFrontmatter.lastUpdated : undefined; + const pageProps: PageProps = { + ...routeProps, + ...localeData, + entry, + entryMeta, + headings, + id, + locale: localeData.locale, + slug, + }; + const siteTitle = getSiteTitle(localeData.lang); + const routeData: StarlightRouteData = { + ...routeProps, + ...localeData, + id, + editUrl, + entry, + entryMeta, + hasSidebar: props.hasSidebar ?? entry.data.template !== 'splash', + head: getHead(pageProps, context, siteTitle), + headings, + lastUpdated, + pagination: getPrevNextLinks(sidebar, config.pagination, entry.data), + sidebar, + siteTitle, + siteTitleHref: getSiteTitleHref(localeData.locale), + slug, + toc: getToC(pageProps), + }; + return routeData; +} + +/** Validates the Starlight page frontmatter properties from the props received by a Starlight page. */ +async function getStarlightPageFrontmatter(frontmatter: StarlightPageFrontmatter) { + const schema = await StarlightPageFrontmatterSchema({ + image: (() => + // Mock validator for ImageMetadata. + // https://github.com/withastro/astro/blob/cf993bc263b58502096f00d383266cd179f331af/packages/astro/src/assets/types.ts#L32 + // It uses a custom validation approach because imported SVGs have a type of `function` as + // well as containing the metadata properties and this ensures we handle those correctly. + z.custom( + (value) => + (value && + (typeof value === 'function' || typeof value === 'object') && + 'src' in value && + 'width' in value && + 'height' in value && + 'format' in value) as ReturnType<ImageFunction>, + 'Invalid image passed to `<StarlightPage>` component. Expected imported `ImageMetadata` object.' + )) as ImageFunction, + }); + + // Starting with Astro 4.14.0, a frontmatter schema that contains collection references will + // contain an async transform. + return parseAsyncWithFriendlyErrors( + schema, + frontmatter, + 'Invalid frontmatter props passed to the `<StarlightPage/>` component.' + ); +} + +/** Returns the user docs schema and falls back to the default schema if needed. */ +async function getUserDocsSchema(): Promise< + NonNullable<ContentConfig['collections']['docs']['schema']> +> { + const userCollections = (await import('virtual:starlight/collection-config')).collections; + return userCollections?.docs?.schema ?? docsSchema(); +} diff --git a/packages/starlight/utils/translations-fs.ts b/packages/starlight/utils/translations-fs.ts new file mode 100644 index 00000000000..6838f6ac79c --- /dev/null +++ b/packages/starlight/utils/translations-fs.ts @@ -0,0 +1,54 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import yaml from 'js-yaml'; +import type { i18nSchemaOutput } from '../schemas/i18n'; +import { createTranslationSystem } from './createTranslationSystem'; +import type { StarlightConfig } from './user-config'; +import type { AstroConfig } from 'astro'; + +const contentCollectionFileExtensions = ['.json', '.yaml', '.yml']; + +/** + * Loads and creates a translation system from the file system. + * Only for use in integration code. + * In modules loaded by Vite/Astro, import [`useTranslations`](./translations.ts) instead. + * + * @see [`./translations.ts`](./translations.ts) + */ +export async function createTranslationSystemFromFs<T extends i18nSchemaOutput>( + opts: Pick<StarlightConfig, 'defaultLocale' | 'locales'>, + { srcDir }: Pick<AstroConfig, 'srcDir'>, + pluginTranslations: Record<string, T> = {} +) { + /** All translation data from the i18n collection, keyed by `id`, which matches locale. */ + const userTranslations: Record<string, i18nSchemaOutput> = {}; + try { + const i18nDir = new URL('content/i18n/', srcDir); + // Load the user’s i18n directory + const files = fs.readdirSync(i18nDir, 'utf-8'); + // Load the user’s i18n collection and ignore the error if it doesn’t exist. + for (const file of files) { + const filePath = path.parse(file); + if (!contentCollectionFileExtensions.includes(filePath.ext)) continue; + const id = filePath.name; + const url = new URL(filePath.base, i18nDir); + const content = fs.readFileSync(new URL(file, i18nDir), 'utf-8'); + const data = ( + filePath.ext === '.json' + ? JSON.parse(content) + : yaml.load(content, { filename: fileURLToPath(url) }) + ) as i18nSchemaOutput; + userTranslations[id] = data; + } + } catch (e: unknown) { + if (e instanceof Error && 'code' in e && e.code === 'ENOENT') { + // i18nDir doesn’t exist, so we ignore the error. + } else { + // Other errors may be meaningful, e.g. JSON syntax errors, so should be thrown. + throw e; + } + } + + return createTranslationSystem(opts, userTranslations, pluginTranslations); +} diff --git a/packages/starlight/utils/translations.ts b/packages/starlight/utils/translations.ts index b4c6da4b645..12040d65efb 100644 --- a/packages/starlight/utils/translations.ts +++ b/packages/starlight/utils/translations.ts @@ -1,70 +1,58 @@ -import { type CollectionEntry, getCollection } from 'astro:content'; +import { getCollection, type CollectionEntry, type DataCollectionKey } from 'astro:content'; import config from 'virtual:starlight/user-config'; -import builtinTranslations from '../translations'; -import { localeToLang } from './slugs'; +import project from 'virtual:starlight/project-context'; +import pluginTranslations from 'virtual:starlight/plugin-translations'; +import type { i18nSchemaOutput } from '../schemas/i18n'; +import { createTranslationSystem } from './createTranslationSystem'; +import type { RemoveIndexSignature } from './types'; +import { getCollectionPathFromRoot } from './collection'; +import { stripExtension, stripLeadingSlash } from './path'; -/** User-configured default locale. */ -const defaultLocale = config.defaultLocale?.locale || 'root'; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore - This may be a type error in projects without an i18n collection and running +// `tsc --noEmit` in their project. Note that it is not possible to inline this type in +// `UserI18nSchema` because this would break types for users having multiple data collections. +type i18nCollection = CollectionEntry<'i18n'>; -/** All translation data from the i18n collection, keyed by `id`, which matches locale. */ -let userTranslations: Record<string, CollectionEntry<'i18n'>['data']> = {}; -try { - // Load the user’s i18n collection and ignore the error if it doesn’t exist. - userTranslations = Object.fromEntries( - (await getCollection('i18n')).map(({ id, data }) => [id, data] as const) - ); -} catch {} +const i18nCollectionPathFromRoot = getCollectionPathFromRoot('i18n', project); -/** Default map of UI strings based on Starlight and user-configured defaults. */ -const defaults = buildDictionary( - builtinTranslations.en!, - userTranslations.en, - builtinTranslations[defaultLocale] || builtinTranslations[stripLangRegion(defaultLocale)], - userTranslations[defaultLocale] -); +export type UserI18nSchema = 'i18n' extends DataCollectionKey + ? i18nCollection extends { data: infer T } + ? i18nSchemaOutput & T + : i18nSchemaOutput + : i18nSchemaOutput; +export type UserI18nKeys = keyof RemoveIndexSignature<UserI18nSchema>; -/** - * Strips the region subtag from a BCP-47 lang string. - * @param {string} [lang] - * @example - * const lang = stripLangRegion('en-GB'); // => 'en' - */ -export function stripLangRegion(lang: string) { - return lang.replace(/-[a-zA-Z]{2}/, ''); +/** Get all translation data from the i18n collection, keyed by `lang`, which are BCP-47 language tags. */ +async function loadTranslations() { + // Briefly override `console.warn()` to silence logging when a project has no i18n collection. + const warn = console.warn; + console.warn = () => {}; + const userTranslations: Record<string, UserI18nSchema> = Object.fromEntries( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore — may be a type error in projects without an i18n collection + (await getCollection('i18n')).map(({ id, data, filePath }) => { + const lang = + project.legacyCollections || !filePath + ? id + : stripExtension(stripLeadingSlash(filePath.replace(i18nCollectionPathFromRoot, ''))); + return [lang, data] as const; + }) + ); + // Restore the original warn implementation. + console.warn = warn; + return userTranslations; } /** - * Generate a utility function that returns UI strings for the given `locale`. - * @param {string | undefined} [locale] + * Generate a utility function that returns UI strings for the given language. + * @param {string | undefined} [lang] * @example * const t = useTranslations('en'); * const label = t('search.label'); // => 'Search' */ -export function useTranslations(locale: string | undefined) { - const lang = localeToLang(locale); - const dictionary = buildDictionary( - defaults, - builtinTranslations[lang] || builtinTranslations[stripLangRegion(lang)], - userTranslations[lang] - ); - const t = <K extends keyof typeof dictionary>(key: K) => dictionary[key]; - t.pick = (startOfKey: string) => - Object.fromEntries(Object.entries(dictionary).filter(([k]) => k.startsWith(startOfKey))); - return t; -} - -/** Build a dictionary by layering preferred translation sources. */ -function buildDictionary( - base: (typeof builtinTranslations)[string], - ...dictionaries: (CollectionEntry<'i18n'>['data'] | undefined)[] -) { - const dictionary = { ...base }; - // Iterate over alternate dictionaries to avoid overwriting preceding values with `undefined`. - for (const dict of dictionaries) { - for (const key in dict) { - const value = dict[key as keyof typeof dict]; - if (value) dictionary[key as keyof typeof dict] = value; - } - } - return dictionary; -} +export const useTranslations = await createTranslationSystem( + config, + await loadTranslations(), + pluginTranslations +); diff --git a/packages/starlight/utils/types.ts b/packages/starlight/utils/types.ts new file mode 100644 index 00000000000..46ac4814396 --- /dev/null +++ b/packages/starlight/utils/types.ts @@ -0,0 +1,15 @@ +// https://stackoverflow.com/a/66252656/1945960 +export type RemoveIndexSignature<T> = { + [K in keyof T as string extends K + ? never + : number extends K + ? never + : symbol extends K + ? never + : K]: T[K]; +}; + +// https://www.totaltypescript.com/concepts/the-prettify-helper +export type Prettify<T> = { + [K in keyof T]: T[K]; +} & {}; diff --git a/packages/starlight/utils/url.ts b/packages/starlight/utils/url.ts new file mode 100644 index 00000000000..2313493f177 --- /dev/null +++ b/packages/starlight/utils/url.ts @@ -0,0 +1,4 @@ +const HTTPProtocolRegEx = /^https?:\/\//; + +/** Check if a string starts with one of `http://` or `https://`. */ +export const isAbsoluteUrl = (link: string) => HTTPProtocolRegEx.test(link); diff --git a/packages/starlight/utils/user-config.ts b/packages/starlight/utils/user-config.ts index dcc69ee4398..2f8e20fa48e 100644 --- a/packages/starlight/utils/user-config.ts +++ b/packages/starlight/utils/user-config.ts @@ -1,10 +1,16 @@ import { z } from 'astro/zod'; import { parse as bcpParse, stringify as bcpStringify } from 'bcp-47'; +import { ComponentConfigSchema } from '../schemas/components'; +import { ExpressiveCodeSchema } from '../schemas/expressiveCode'; +import { FaviconSchema } from '../schemas/favicon'; import { HeadConfigSchema } from '../schemas/head'; import { LogoConfigSchema } from '../schemas/logo'; +import { PagefindConfigDefaults, PagefindConfigSchema } from '../schemas/pagefind'; +import { SidebarItemSchema } from '../schemas/sidebar'; +import { TitleConfigSchema, TitleTransformConfigSchema } from '../schemas/site-title'; +import { SocialLinksSchema } from '../schemas/social'; import { TableOfContentsSchema } from '../schemas/tableOfContents'; -import { FaviconSchema } from '../schemas/favicon'; -import { BadgeConfigSchema } from '../schemas/badge'; +import { BuiltInDefaultLocale } from './i18n'; const LocaleSchema = z.object({ /** The label for this language to show in UI, e.g. `"English"`, `"العربية"`, or `"简体中文"`. */ @@ -28,84 +34,9 @@ const LocaleSchema = z.object({ ), }); -const SidebarBaseSchema = z.object({ - /** The visible label for this item in the sidebar. */ - label: z.string(), - /** Translations of the `label` for each supported language. */ - translations: z.record(z.string()).default({}), -}); - -const SidebarGroupSchema = SidebarBaseSchema.extend({ - /** Whether this item should be collapsed by default. */ - collapsed: z.boolean().default(false), -}); - -const SidebarLinkItemSchema = SidebarBaseSchema.extend({ - /** The link to this item’s content. Can be a relative link to local files or the full URL of an external page. */ - link: z.string(), - /** Adds a badge to the link item */ - badge: BadgeConfigSchema(), -}); -export type SidebarLinkItem = z.infer<typeof SidebarLinkItemSchema>; - -const AutoSidebarGroupSchema = SidebarGroupSchema.extend({ - /** Enable autogenerating a sidebar category from a specific docs directory. */ - autogenerate: z.object({ - /** The directory to generate sidebar items for. */ - directory: z.string(), - /** - * Whether the autogenerated subgroups should be collapsed by default. - * Defaults to the `AutoSidebarGroup` `collapsed` value. - */ - collapsed: z.boolean().optional(), - // TODO: not supported by Docusaurus but would be good to have - /** How many directories deep to include from this directory in the sidebar. Default: `Infinity`. */ - // depth: z.number().optional(), - }), -}); -export type AutoSidebarGroup = z.infer<typeof AutoSidebarGroupSchema>; - -type ManualSidebarGroupInput = z.input<typeof SidebarGroupSchema> & { - /** Array of links and subcategories to display in this category. */ - items: Array< - | z.input<typeof SidebarLinkItemSchema> - | z.input<typeof AutoSidebarGroupSchema> - | ManualSidebarGroupInput - >; -}; - -type ManualSidebarGroupOutput = z.output<typeof SidebarGroupSchema> & { - /** Array of links and subcategories to display in this category. */ - items: Array< - | z.output<typeof SidebarLinkItemSchema> - | z.output<typeof AutoSidebarGroupSchema> - | ManualSidebarGroupOutput - >; -}; - -const ManualSidebarGroupSchema: z.ZodType< - ManualSidebarGroupOutput, - z.ZodTypeDef, - ManualSidebarGroupInput -> = SidebarGroupSchema.extend({ - /** Array of links and subcategories to display in this category. */ - items: z.lazy(() => - z.union([SidebarLinkItemSchema, ManualSidebarGroupSchema, AutoSidebarGroupSchema]).array() - ), -}); - -const SidebarItemSchema = z.union([ - SidebarLinkItemSchema, - ManualSidebarGroupSchema, - AutoSidebarGroupSchema, -]); -export type SidebarItem = z.infer<typeof SidebarItemSchema>; - const UserConfigSchema = z.object({ /** Title for your website. Will be used in metadata and as browser tab title. */ - title: z - .string() - .describe('Title for your website. Will be used in metadata and as browser tab title.'), + title: TitleConfigSchema(), /** Description metadata for your website. Can be used in page metadata. */ description: z @@ -120,43 +51,15 @@ const UserConfigSchema = z.object({ * Optional details about the social media accounts for this site. * * @example - * social: { - * codeberg: 'https://codeberg.org/knut/examples', - * discord: 'https://astro.build/chat', - * github: 'https://github.com/withastro/starlight', - * gitlab: 'https://gitlab.com/delucis', - * linkedin: 'https://www.linkedin.com/company/astroinc', - * mastodon: 'https://m.webtoo.ls/@astro', - * threads: 'https://www.threads.net/@nmoodev', - * twitch: 'https://www.twitch.tv/bholmesdev', - * twitter: 'https://twitter.com/astrodotbuild', - * youtube: 'https://youtube.com/@astrodotbuild', - * } + * social: [ + * { icon: 'codeberg', label: 'Codeberg', href: 'https://codeberg.org/knut' }, + * { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' }, + * { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro' }, + * { icon: 'gitlab', label: 'GitLab', href: 'https://gitlab.com/delucis' }, + * { icon: 'mastodon', label: 'Mastodon', href: 'https://m.webtoo.ls/@astro' }, + * ] */ - social: z - .record( - z.enum([ - 'twitter', - 'mastodon', - 'github', - 'gitlab', - 'bitbucket', - 'discord', - 'gitter', - 'codeberg', - 'codePen', - 'youtube', - 'threads', - 'linkedin', - 'twitch', - 'microsoftTeams', - 'instagram', - 'stackOverflow', - ]), - // Link to the respective social profile for this site - z.string().url() - ) - .optional(), + social: SocialLinksSchema(), /** The tagline for your website. */ tagline: z.string().optional().describe('The tagline for your website.'), @@ -246,7 +149,7 @@ const UserConfigSchema = z.object({ * ], * }) */ - head: HeadConfigSchema(), + head: HeadConfigSchema({ source: 'config' }), /** * Provide CSS files to customize the look and feel of your Starlight site. @@ -260,7 +163,24 @@ const UserConfigSchema = z.object({ * customCss: ['/src/custom-styles.css', '@fontsource/roboto'], * }) */ - customCss: z.string().array().optional().default([]), + customCss: z + .string() + .array() + .optional() + .default([]) + .superRefine((paths, ctx) => { + const invalidPathRegex = /^\.?\/public\/.+$/; + const invalidPaths = paths.filter((path) => invalidPathRegex.test(path)); + if (invalidPaths.length > 0) { + ctx.addIssue({ + code: 'custom', + message: + `These paths in your Starlight \`customCss\` config are invalid: ${invalidPaths.map((path) => `\`"${path}"\``).join(', ')}\n\n` + + `CSS files specified in \`customCss\` should be in the \`src/\` directory, not the \`public/\` directory.\n\n` + + `You should move these CSS files into the \`src/\` directory and update the path in \`customCss\` to match.`, + }); + } + }), /** Define if the last update date should be visible in the page footer. */ lastUpdated: z @@ -276,20 +196,131 @@ const UserConfigSchema = z.object({ /** The default favicon for your site which should be a path to an image in the `public/` directory. */ favicon: FaviconSchema(), + + /** + * Define how code blocks are rendered by passing options to Expressive Code, + * or disable the integration by passing `false`. + */ + expressiveCode: ExpressiveCodeSchema(), + + /** + * Configure Starlight’s default site search provider Pagefind. Set to `false` to disable indexing + * your site with Pagefind, which will also hide the default search UI if in use. + */ + pagefind: z + .boolean() + // Transform `true` to our default config object. + .transform((val) => val && PagefindConfigDefaults()) + .or(PagefindConfigSchema()) + .optional(), + + /** Specify paths to components that should override Starlight’s default components */ + components: ComponentConfigSchema(), + + /** Will be used as title delimiter in the generated `<title>` tag. */ + titleDelimiter: z + .string() + .default('|') + .describe('Will be used as title delimiter in the generated `<title>` tag.'), + + /** Disable Starlight's default 404 page. */ + disable404Route: z.boolean().default(false).describe("Disable Starlight's default 404 page."), + + /** + * Define whether Starlight pages should be prerendered or not. + * Defaults to always prerender Starlight pages, even when the project is + * set to "server" output mode. + */ + prerender: z.boolean().default(true), + + /** Enable displaying a “Built with Starlight” link in your site’s footer. */ + credits: z + .boolean() + .default(false) + .describe('Enable displaying a “Built with Starlight” link in your site’s footer.'), + + /** Add middleware to process Starlight’s route data for each page. */ + routeMiddleware: z + .string() + .transform((string) => [string]) + .or(z.string().array()) + .default([]) + .superRefine((middlewares, ctx) => { + // Regex pattern to match invalid middleware paths: https://regex101.com/r/kQH7xm/2 + const invalidPathRegex = /^\.?\/src\/middleware(?:\/index)?\.[jt]s$/; + const invalidPaths = middlewares.filter((middleware) => invalidPathRegex.test(middleware)); + for (const invalidPath of invalidPaths) { + ctx.addIssue({ + code: 'custom', + message: + `The \`"${invalidPath}"\` path in your Starlight \`routeMiddleware\` config conflicts with Astro’s middleware locations.\n\n` + + `You should rename \`${invalidPath}\` to something else like \`./src/starlightRouteData.ts\` and update the \`routeMiddleware\` file path to match.\n\n` + + '- More about Starlight route middleware: https://starlight.astro.build/guides/route-data/#how-to-customize-route-data\n' + + '- More about Astro middleware: https://docs.astro.build/en/guides/middleware/', + }); + } + }) + .describe('Add middleware to process Starlight’s route data for each page.'), + + /** Configure features that impact Starlight’s Markdown processing. */ + markdown: z + .object({ + /** Define whether headings in content should be rendered with clickable anchor links. Default: `true`. */ + headingLinks: z + .boolean() + .default(true) + .describe( + 'Define whether headings in content should be rendered with clickable anchor links. Default: `true`.' + ), + /** + * Define additional directories where files should be processed by Starlight’s Markdown pipeline. + * + * Supports local directories relative to the root of your project, e.g. './src/data/comments/'. + * Content of the `docs` content collection is always processed by Starlight’s Markdown pipeline. + */ + processedDirs: z + .string() + .array() + .default([]) + .describe( + 'Define additional directories where files should be processed by Starlight’s Markdown pipeline. Default: `[]`.' + ), + }) + .default({}) + .describe('Configure features that impact Starlight’s Markdown processing.'), }); -export const StarlightConfigSchema = UserConfigSchema.strict().transform( - ({ locales, defaultLocale, ...config }, ctx) => { - if (locales !== undefined && Object.keys(locales).length > 1) { - // This is a multilingual site (more than one locale configured). +export const StarlightConfigSchema = UserConfigSchema.strict() + .transform((config) => ({ + ...config, + // Pagefind only defaults to true if prerender is also true. + pagefind: + typeof config.pagefind === 'undefined' + ? config.prerender && PagefindConfigDefaults() + : config.pagefind, + })) + .refine((config) => !(!config.prerender && config.pagefind), { + message: 'Pagefind search is not supported with prerendering disabled.', + }) + .transform(({ title, locales, defaultLocale, ...config }, ctx) => { + const configuredLocales = Object.keys(locales ?? {}); + + // This is a multilingual site (more than one locale configured) or a monolingual site with + // only one locale configured (not a root locale). + // Monolingual sites with only one non-root locale needs their configuration to be defined in + // `config.locales` so that slugs can be correctly generated by taking into consideration the + // base path at which a language is served which is the key of the `config.locales` object. + if ( + locales !== undefined && + (configuredLocales.length > 1 || + (configuredLocales.length === 1 && locales.root === undefined)) + ) { // Make sure we can find the default locale and if not, help the user set it. // We treat the root locale as the default if present and no explicit default is set. const defaultLocaleConfig = locales[defaultLocale || 'root']; if (!defaultLocaleConfig) { - const availableLocales = Object.keys(locales) - .map((l) => `"${l}"`) - .join(', '); + const availableLocales = configuredLocales.map((l) => `"${l}"`).join(', '); ctx.addIssue({ code: 'custom', message: @@ -300,33 +331,47 @@ export const StarlightConfigSchema = UserConfigSchema.strict().transform( return z.NEVER; } + // Transform the title + const TitleSchema = TitleTransformConfigSchema(defaultLocaleConfig.lang as string); + const parsedTitle = TitleSchema.parse(title); + return { ...config, + title: parsedTitle, /** Flag indicating if this site has multiple locales set up. */ - isMultilingual: true, + isMultilingual: configuredLocales.length > 1, + /** Flag indicating if the Starlight built-in default locale is used. */ + isUsingBuiltInDefaultLocale: false, /** Full locale object for this site’s default language. */ defaultLocale: { ...defaultLocaleConfig, locale: defaultLocale }, locales, } as const; } - // This is a monolingual site, so things are pretty simple. + // This is a monolingual site with no locales configured or only a root locale, so things are + // pretty simple. + /** Full locale object for this site’s default language. */ + const defaultLocaleConfig = { + label: BuiltInDefaultLocale.label, + lang: BuiltInDefaultLocale.lang, + dir: BuiltInDefaultLocale.dir, + locale: undefined, + ...locales?.root, + }; + /** Transform the title */ + const TitleSchema = TitleTransformConfigSchema(defaultLocaleConfig.lang); + const parsedTitle = TitleSchema.parse(title); return { ...config, + title: parsedTitle, /** Flag indicating if this site has multiple locales set up. */ isMultilingual: false, - /** Full locale object for this site’s default language. */ - defaultLocale: { - label: 'English', - lang: 'en', - dir: 'ltr', - locale: undefined, - ...locales?.root, - }, + /** Flag indicating if the Starlight built-in default locale is used. */ + isUsingBuiltInDefaultLocale: locales?.root === undefined, + defaultLocale: defaultLocaleConfig, locales: undefined, } as const; - } -); + }); export type StarlightConfig = z.infer<typeof StarlightConfigSchema>; export type StarlightUserConfig = z.input<typeof StarlightConfigSchema>; diff --git a/packages/starlight/utils/validateLogoImports.ts b/packages/starlight/utils/validateLogoImports.ts new file mode 100644 index 00000000000..773fae9812d --- /dev/null +++ b/packages/starlight/utils/validateLogoImports.ts @@ -0,0 +1,21 @@ +import config from 'virtual:starlight/user-config'; +import { logos } from 'virtual:starlight/user-images'; + +/** Check user-imported logo images have resolved correctly. */ +export function validateLogoImports(): void { + if (config.logo) { + let err: string | undefined; + if ('src' in config.logo) { + if (!logos.dark || !logos.light) { + err = `Could not resolve logo import for "${config.logo.src}" (logo.src)`; + } + } else { + if (!logos.dark) { + err = `Could not resolve logo import for "${config.logo.dark}" (logo.dark)`; + } else if (!logos.light) { + err = `Could not resolve logo import for "${config.logo.light}" (logo.light)`; + } + } + if (err) throw new Error(err); + } +} diff --git a/packages/starlight/virtual-internal.d.ts b/packages/starlight/virtual-internal.d.ts new file mode 100644 index 00000000000..3002b4519e4 --- /dev/null +++ b/packages/starlight/virtual-internal.d.ts @@ -0,0 +1,149 @@ +declare module 'virtual:starlight/git-info' { + export function getNewestCommitDate(file: string): Date; +} + +declare module 'virtual:starlight/user-css' {} + +declare module 'virtual:starlight/optional-css' {} + +declare module 'virtual:starlight/user-images' { + type ImageMetadata = import('astro').ImageMetadata; + export const logos: { + dark?: ImageMetadata; + light?: ImageMetadata; + }; +} + +declare module 'virtual:starlight/collection-config' { + export const collections: import('astro:content').ContentConfig['collections'] | undefined; +} + +declare module 'virtual:starlight/route-middleware' { + export const routeMiddleware: Array<import('./route-data').RouteMiddlewareHandler>; +} + +declare module 'virtual:starlight/pagefind-config' { + export const pagefindUserConfig: Partial< + Extract<import('./types').StarlightConfig['pagefind'], object> + >; +} + +declare module 'virtual:starlight/components/Banner' { + const Banner: typeof import('./components/Banner.astro').default; + export default Banner; +} +declare module 'virtual:starlight/components/ContentPanel' { + const ContentPanel: typeof import('./components/ContentPanel.astro').default; + export default ContentPanel; +} +declare module 'virtual:starlight/components/PageTitle' { + const PageTitle: typeof import('./components/PageTitle.astro').default; + export default PageTitle; +} +declare module 'virtual:starlight/components/FallbackContentNotice' { + const FallbackContentNotice: typeof import('./components/FallbackContentNotice.astro').default; + export default FallbackContentNotice; +} +declare module 'virtual:starlight/components/DraftContentNotice' { + const DraftContentNotice: typeof import('./components/DraftContentNotice.astro').default; + export default DraftContentNotice; +} + +declare module 'virtual:starlight/components/Footer' { + const Footer: typeof import('./components/Footer.astro').default; + export default Footer; +} +declare module 'virtual:starlight/components/LastUpdated' { + const LastUpdated: typeof import('./components/LastUpdated.astro').default; + export default LastUpdated; +} +declare module 'virtual:starlight/components/Pagination' { + const Pagination: typeof import('./components/Pagination.astro').default; + export default Pagination; +} +declare module 'virtual:starlight/components/EditLink' { + const EditLink: typeof import('./components/EditLink.astro').default; + export default EditLink; +} + +declare module 'virtual:starlight/components/Header' { + const Header: typeof import('./components/Header.astro').default; + export default Header; +} +declare module 'virtual:starlight/components/LanguageSelect' { + const LanguageSelect: typeof import('./components/LanguageSelect.astro').default; + export default LanguageSelect; +} +declare module 'virtual:starlight/components/Search' { + const Search: typeof import('./components/Search.astro').default; + export default Search; +} +declare module 'virtual:starlight/components/SiteTitle' { + const SiteTitle: typeof import('./components/SiteTitle.astro').default; + export default SiteTitle; +} +declare module 'virtual:starlight/components/SocialIcons' { + const SocialIcons: typeof import('./components/SocialIcons.astro').default; + export default SocialIcons; +} +declare module 'virtual:starlight/components/ThemeSelect' { + const ThemeSelect: typeof import('./components/ThemeSelect.astro').default; + export default ThemeSelect; +} + +declare module 'virtual:starlight/components/Head' { + const Head: typeof import('./components/Head.astro').default; + export default Head; +} +declare module 'virtual:starlight/components/Hero' { + const Hero: typeof import('./components/Hero.astro').default; + export default Hero; +} +declare module 'virtual:starlight/components/MarkdownContent' { + const MarkdownContent: typeof import('./components/MarkdownContent.astro').default; + export default MarkdownContent; +} + +declare module 'virtual:starlight/components/PageSidebar' { + const PageSidebar: typeof import('./components/PageSidebar.astro').default; + export default PageSidebar; +} +declare module 'virtual:starlight/components/TableOfContents' { + const TableOfContents: typeof import('./components/TableOfContents.astro').default; + export default TableOfContents; +} +declare module 'virtual:starlight/components/MobileTableOfContents' { + const MobileTableOfContents: typeof import('./components/MobileTableOfContents.astro').default; + export default MobileTableOfContents; +} + +declare module 'virtual:starlight/components/Sidebar' { + const Sidebar: typeof import('./components/Sidebar.astro').default; + export default Sidebar; +} +declare module 'virtual:starlight/components/SkipLink' { + const SkipLink: typeof import('./components/SkipLink.astro').default; + export default SkipLink; +} +declare module 'virtual:starlight/components/ThemeProvider' { + const ThemeProvider: typeof import('./components/ThemeProvider.astro').default; + export default ThemeProvider; +} + +declare module 'virtual:starlight/components/PageFrame' { + const PageFrame: typeof import('./components/PageFrame.astro').default; + export default PageFrame; +} +declare module 'virtual:starlight/components/MobileMenuToggle' { + const MobileMenuToggle: typeof import('./components/MobileMenuToggle.astro').default; + export default MobileMenuToggle; +} +declare module 'virtual:starlight/components/MobileMenuFooter' { + const MobileMenuFooter: typeof import('./components/MobileMenuFooter.astro').default; + export default MobileMenuFooter; +} + +declare module 'virtual:starlight/components/TwoColumnContent' { + const TwoColumnContent: typeof import('./components/TwoColumnContent.astro').default; + export default TwoColumnContent; +} diff --git a/packages/starlight/virtual.d.ts b/packages/starlight/virtual.d.ts index 1230c460534..5ff0c53c55d 100644 --- a/packages/starlight/virtual.d.ts +++ b/packages/starlight/virtual.d.ts @@ -2,16 +2,23 @@ declare module 'virtual:starlight/user-config' { const Config: import('./types').StarlightConfig; export default Config; } -declare module 'virtual:starlight/project-context' { - export default { root: string, srcDir: string }; -} -declare module 'virtual:starlight/user-css' {} +declare module 'virtual:starlight/plugin-translations' { + const PluginTranslations: import('./utils/plugins').PluginTranslations; + export default PluginTranslations; +} -declare module 'virtual:starlight/user-images' { - type ImageMetadata = import('astro').ImageMetadata; - export const logos: { - dark?: ImageMetadata; - light?: ImageMetadata; +// TODO: Move back to `virtual-internal.d.ts` when possible. For example, when dropping support for +// legacy collections, `utils/translations.ts` would no longer need to import project context. +declare module 'virtual:starlight/project-context' { + const ProjectContext: { + root: string; + srcDir: string; + trailingSlash: import('astro').AstroConfig['trailingSlash']; + build: { + format: import('astro').AstroConfig['build']['format']; + }; + legacyCollections: boolean; }; + export default ProjectContext; } diff --git a/packages/starlight/vitest.config.ts b/packages/starlight/vitest.config.ts index b80690ddb63..d9a80406d62 100644 --- a/packages/starlight/vitest.config.ts +++ b/packages/starlight/vitest.config.ts @@ -1,31 +1,32 @@ -import { defineConfig } from 'vitest/config'; - -// Copy of https://github.com/vitest-dev/vitest/blob/8693449b412743f20a63fd9bfa1a9054aa74613f/packages/vitest/src/defaults.ts#L13C1-L26C1 -const defaultCoverageExcludes = [ - 'coverage/**', - 'dist/**', - 'packages/*/test?(s)/**', - '**/*.d.ts', - 'cypress/**', - 'test?(s)/**', - 'test?(-*).?(c|m)[jt]s?(x)', - '**/*{.,-}{test,spec}.?(c|m)[jt]s?(x)', - '**/__tests__/**', - '**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*', - '**/.{eslint,mocha,prettier}rc.{?(c|m)js,yml}', -]; +import { coverageConfigDefaults, defineConfig } from 'vitest/config'; export default defineConfig({ test: { coverage: { all: true, reportsDirectory: './__coverage__', - exclude: [...defaultCoverageExcludes, '**/vitest.*', 'components.ts', 'types.ts'], - thresholdAutoUpdate: true, - lines: 66.57, - functions: 88.46, - branches: 90.14, - statements: 66.57, + exclude: [ + ...coverageConfigDefaults.exclude, + '**/__e2e__/**', + 'playwright.config.*', + '**/vitest.*', + 'components.ts', + 'types.ts', + // We use this to set up test environments so it isn‘t picked up, but we are testing it downstream. + 'integrations/virtual-user-config.ts', + // Types-only export. + 'props.ts', + // Main integration entrypoint — don’t think we’re able to test this directly currently. + 'index.ts', + // Since Vitest 2.1.2, coverage is collected for `*.astro` files. + '**/*.astro', + ], + thresholds: { + lines: 87, + functions: 90, + branches: 90, + statements: 87, + }, }, }, }); diff --git a/packages/starlight/vitest.workspace.ts b/packages/starlight/vitest.workspace.ts index 4cfafe822e9..5fd9db05ef0 100644 --- a/packages/starlight/vitest.workspace.ts +++ b/packages/starlight/vitest.workspace.ts @@ -1 +1 @@ -export default ['__tests__/*']; +export default ['__tests__/*/vitest.config.ts']; diff --git a/packages/tailwind/CHANGELOG.md b/packages/tailwind/CHANGELOG.md index bf0340e35be..0ba7890f796 100644 --- a/packages/tailwind/CHANGELOG.md +++ b/packages/tailwind/CHANGELOG.md @@ -1,5 +1,204 @@ # @astrojs/starlight-tailwind +## 4.0.2 + +### Patch Changes + +- [#3500](https://github.com/withastro/starlight/pull/3500) [`7700456`](https://github.com/withastro/starlight/commit/770045663c8ca3cc44983dd0d444955eba441243) Thanks [@delucis](https://github.com/delucis)! - This is the first release published with OIDC trusted publishing. + +## 4.0.1 + +### Patch Changes + +- [#3132](https://github.com/withastro/starlight/pull/3132) [`5959919`](https://github.com/withastro/starlight/commit/595991952be1a76cdf54f457c6e4d23b3f2ffec7) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fixes an issue where all border styles were not reset by the Starlight’s Tailwind compatibility package like in [Tailwind base styles](https://tailwindcss.com/docs/preflight#border-styles-are-reset). + +## 4.0.0 + +### Major Changes + +- [#2322](https://github.com/withastro/starlight/pull/2322) [`f14eb0c`](https://github.com/withastro/starlight/commit/f14eb0cd7baa0391d6124379f6c5df4b9ab7cc44) Thanks [@HiDeoo](https://github.com/HiDeoo)! - ⚠️ **BREAKING CHANGE:** The minimum supported version of Starlight is now 0.34.0 + + Please use the `@astrojs/upgrade` command to upgrade your project: + + ```sh + npx @astrojs/upgrade + ``` + +- [#2322](https://github.com/withastro/starlight/pull/2322) [`f14eb0c`](https://github.com/withastro/starlight/commit/f14eb0cd7baa0391d6124379f6c5df4b9ab7cc44) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Adds support for Tailwind v4, drops support for Tailwind v3. + + ⚠️ **BREAKING CHANGE:** Tailwind v3 is no longer supported. Tailwind v4 support in Astro is now provided using a Vite plugin and the Astro Tailwind integration is no longer required. + + 1. **Remove the Astro Tailwind integration.** The Astro Tailwind integration is no longer required with Tailwind v4. + + ```diff + // astro.config.mjs + import { defineConfig } from "astro/config"; + import starlight from "@astrojs/starlight"; + -import tailwind from "@astrojs/tailwind"; + + export default defineConfig({ + integrations: [ + starlight({ + title: "Docs with Tailwind", + customCss: ["./src/tailwind.css"], + }), + - tailwind({ applyBaseStyles: false }), + ], + }); + ``` + + 1. **Install Tailwind v4.** Install the latest version of the `tailwindcss` and `@tailwindcss/vite` packages. + + Use the `astro add tailwind` command to install and configure both packages: + + ```sh + npx astro add tailwind + ``` + + 1. **Update Tailwind base styles.** Tailwind CSS base styles needs to be updated for Tailwind v4 and also to use Starlight Tailwind CSS. + + ```diff + /* src/tailwind.css */ + -@tailwind base; + -@tailwind components; + -@tailwind utilities; + +@layer base, starlight, theme, components, utilities; + + + +@import '@astrojs/starlight-tailwind'; + +@import 'tailwindcss/theme.css' layer(theme); + +@import 'tailwindcss/utilities.css' layer(utilities); + + + +@theme { + + /* + + Configure your Tailwind theme that will be used by Starlight. + + https://starlight.astro.build/guides/css-and-tailwind/#styling-starlight-with-tailwind + + */ + +} + + + +/* + +Add additional Tailwind styles to this file: + +https://tailwindcss.com/docs/adding-custom-styles#using-custom-css + +*/ + ``` + + 1. **Update Tailwind customizations.** If you previously [customized your Tailwind theme configuration](https://starlight.astro.build/guides/css-and-tailwind/#styling-starlight-with-tailwind) in the `tailwind.config.mjs` file, such customizations are now defined through CSS using the `@theme` block in your Tailwind base styles. + + 1. Locate existing customizations in your `tailwind.config.mjs` file. The following example defines customizations for the accent colors, gray scale, and font families used by Starlight: + + ```js + // tailwind.config.mjs + import starlightPlugin from '@astrojs/starlight-tailwind'; + import colors from 'tailwindcss/colors'; + + /** @type {import('tailwindcss').Config} */ + export default { + content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], + theme: { + extend: { + colors: { + // Custom accent colors. + accent: colors.fuchsia, + // Custom gray scale. + gray: colors.slate, + }, + fontFamily: { + // Custom text font. + sans: ['"Atkinson Hyperlegible"'], + // Custom code font. + mono: ['"IBM Plex Mono"'], + }, + }, + }, + plugins: [starlightPlugin()], + }; + ``` + + 1. The above customizations can be migrated to the new `@theme` block in the file containing your Tailwind base styles as follows: + + ```css + /* src/tailwind.css */ + @layer base, starlight, theme, components, utilities; + + @import '@astrojs/starlight-tailwind'; + @import 'tailwindcss/theme.css' layer(theme); + @import 'tailwindcss/utilities.css' layer(utilities); + + @theme { + /* Custom accent colors. */ + --color-accent-50: var(--color-fuchsia-50); + --color-accent-100: var(--color-fuchsia-100); + --color-accent-200: var(--color-fuchsia-200); + --color-accent-300: var(--color-fuchsia-300); + --color-accent-400: var(--color-fuchsia-400); + --color-accent-500: var(--color-fuchsia-500); + --color-accent-600: var(--color-fuchsia-600); + --color-accent-700: var(--color-fuchsia-700); + --color-accent-800: var(--color-fuchsia-800); + --color-accent-900: var(--color-fuchsia-900); + --color-accent-950: var(--color-fuchsia-950); + /* Custom gray scale. */ + --color-gray-50: var(--color-slate-50); + --color-gray-100: var(--color-slate-100); + --color-gray-200: var(--color-slate-200); + --color-gray-300: var(--color-slate-300); + --color-gray-400: var(--color-slate-400); + --color-gray-500: var(--color-slate-500); + --color-gray-600: var(--color-slate-600); + --color-gray-700: var(--color-slate-700); + --color-gray-800: var(--color-slate-800); + --color-gray-900: var(--color-slate-900); + --color-gray-950: var(--color-slate-950); + /* Custom text font. */ + --font-sans: 'Atkinson Hyperlegible'; + /* Custom code font. */ + --font-mono: 'IBM Plex Mono'; + } + ``` + + We recommend checking your site’s appearance when upgrading to make sure there are no style regressions caused by this change. + + For full details about upgrading from Tailwind v3 to v4, see the [official upgrade guide](https://tailwindcss.com/docs/upgrade-guide). + +## 3.0.1 + +### Patch Changes + +- [#2991](https://github.com/withastro/starlight/pull/2991) [`b8a4800`](https://github.com/withastro/starlight/commit/b8a480054aba2b39414ef7942db1a6110b800540) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Adds support for `@astrojs/tailwind` v6 + +## 3.0.0 + +### Major Changes + +- [#2612](https://github.com/withastro/starlight/pull/2612) [`8d5a4e8`](https://github.com/withastro/starlight/commit/8d5a4e8000d9e3a4bb9ca8178767cf3d8bc48773) Thanks [@HiDeoo](https://github.com/HiDeoo)! - ⚠️ **BREAKING CHANGE:** The minimum supported version of Starlight is now 0.30.0 + + Please use the `@astrojs/upgrade` command to upgrade your project: + + ```sh + npx @astrojs/upgrade + ``` + +### Patch Changes + +- [#2664](https://github.com/withastro/starlight/pull/2664) [`62ff007`](https://github.com/withastro/starlight/commit/62ff0074d9a3f82e46f5c62db85c04d87ff5e931) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Publishes provenance containing verifiable data to link a package back to its source repository and the specific build instructions used to publish it. + +## 2.0.3 + +### Patch Changes + +- [#1906](https://github.com/withastro/starlight/pull/1906) [`b079ae11`](https://github.com/withastro/starlight/commit/b079ae114c49bf0570a142b94997bcc0828c47e0) Thanks [@delucis](https://github.com/delucis)! - Fixes default `font-family` in non-Starlight pages when using Tailwind plugin + +## 2.0.2 + +### Patch Changes + +- [#1726](https://github.com/withastro/starlight/pull/1726) [`1aae51ac`](https://github.com/withastro/starlight/commit/1aae51ac512df8de088c7529236e196be42077e8) Thanks [@delucis](https://github.com/delucis)! - Adds warning log if a user tries to set `colors.white` in their Tailwind theme config with an object instead of a string. + +## 2.0.1 + +### Patch Changes + +- [#903](https://github.com/withastro/starlight/pull/903) [`232f512`](https://github.com/withastro/starlight/commit/232f51207fe97880760fba25351cdc65b20f4c67) Thanks [@torn4dom4n](https://github.com/torn4dom4n)! - Show `tailwind.config.mjs` file in docs + ## 2.0.0 ### Major Changes diff --git a/packages/tailwind/__tests__/tailwind.test.ts b/packages/tailwind/__tests__/tailwind.test.ts index d351bcdb166..2d1ca37f01b 100644 --- a/packages/tailwind/__tests__/tailwind.test.ts +++ b/packages/tailwind/__tests__/tailwind.test.ts @@ -1,265 +1,263 @@ -import tailwindcss, { Config } from 'tailwindcss'; -import colors from 'tailwindcss/colors'; -import postcss from 'postcss'; -import { test, expect, describe, vi } from 'vitest'; -import StarlightTailwindPlugin from '..'; +import { compile } from 'tailwindcss'; +import { transform } from 'lightningcss'; +import { test, expect, describe } from 'vitest'; +import starlightTailwindCss from '../tailwind.css?raw'; -/** Generate a CSS string based on the passed CSS and HTML content. */ -const generatePluginCss = ({ - css = '@tailwind base;', - html = '', - config = {}, -}: { css?: string; html?: string; config?: Partial<Config> } = {}): Promise<string> => { - return postcss( - tailwindcss({ - // Enable Starlight plugin. - plugins: [StarlightTailwindPlugin()], - // Provide content for Tailwind to scan for class names. - content: [{ raw: html, extension: 'html' }], - // Spread in any custom Tailwind config. - ...config, - }) - ) - .process(css, { from: '' }) - .then((result) => result.css); -}; +const css = String.raw; -describe('@tailwind base;', async () => { - // Generate base CSS with no core Tailwind plugins running to see just Starlight’s output. - const base = await generatePluginCss({ config: { corePlugins: [] } }); +test('generates base and utilities CSS layers and defines default theme values', async () => { + const output = await render(); - test('generates Starlight base CSS', async () => { - expect(base).toMatchInlineSnapshot(` - "*, ::before, ::after { - border-width: 0; - border-style: solid; - border-color: #e5e7eb; + // The first line includes Tailwind version so we skip it. + const outputWithoutVersion = output.split('\n').slice(1).join('\n'); + expect(outputWithoutVersion).toMatchInlineSnapshot(` + "@layer theme; + + @layer base { + *, :after, :before { + border: 0 solid; + } + + html, :host { + font-family: var(--font-sans); + } + + code, kbd, samp, pre { + font-family: var(--font-mono); + } } - ::before, ::after { - --tw-content: ; + + @layer components; + + @layer utilities { + :root { + --sl-font: var(--font-sans); + --sl-font-mono: var(--font-mono); + --sl-color-white: var(--color-white); + --sl-color-gray-1: var(--color-gray-200); + --sl-color-gray-2: var(--color-gray-300); + --sl-color-gray-3: var(--color-gray-400); + --sl-color-gray-4: var(--color-gray-600); + --sl-color-gray-5: var(--color-gray-700); + --sl-color-gray-6: var(--color-gray-800); + --sl-color-black: var(--color-gray-900); + --sl-color-accent-low: var(--color-accent-950, var(--color-accent-900, #1e1b4b)); + --sl-color-accent: var(--color-accent-600, #4f46e5); + --sl-color-accent-high: var(--color-accent-200, #c7d2fe); + + &[data-theme="light"] { + --sl-color-white: var(--color-gray-900); + --sl-color-gray-1: var(--color-gray-800); + --sl-color-gray-2: var(--color-gray-700); + --sl-color-gray-3: var(--color-gray-500); + --sl-color-gray-4: var(--color-gray-400); + --sl-color-gray-5: var(--color-gray-300); + --sl-color-gray-6: var(--color-gray-200); + --sl-color-gray-7: var(--color-gray-100); + --sl-color-black: var(--color-white); + --sl-color-accent-low: var(--color-accent-200, #c7d2fe); + --sl-color-accent: var(--color-accent-600, #4f46e5); + --sl-color-accent-high: var(--color-accent-900, #312e81); + } + } } - :root { - --sl-font: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \\"Segoe UI\\", Roboto, \\"Helvetica Neue\\", Arial, \\"Noto Sans\\", sans-serif, \\"Apple Color Emoji\\", \\"Segoe UI Emoji\\", \\"Segoe UI Symbol\\", \\"Noto Color Emoji\\"; - --sl-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \\"Liberation Mono\\", \\"Courier New\\", monospace; - --sl-color-white: #fff; - --sl-color-gray-1: #e5e7eb; - --sl-color-gray-2: #d1d5db; - --sl-color-gray-3: #9ca3af; - --sl-color-gray-4: #4b5563; - --sl-color-gray-5: #374151; - --sl-color-gray-6: #1f2937; - --sl-color-black: #111827; - --sl-color-accent-low: #1e1b4b; - --sl-color-accent: #4f46e5; - --sl-color-accent-high: #c7d2fe; + + :root, :host { + --color-accent-200: var(--color-indigo-200); + --color-accent-600: var(--color-indigo-600); + --color-accent-900: var(--color-indigo-900); + --color-accent-950: var(--color-indigo-950); + --color-gray-100: var(--color-zinc-100); + --color-gray-200: var(--color-zinc-200); + --color-gray-300: var(--color-zinc-300); + --color-gray-400: var(--color-zinc-400); + --color-gray-500: var(--color-zinc-500); + --color-gray-600: var(--color-zinc-600); + --color-gray-700: var(--color-zinc-700); + --color-gray-800: var(--color-zinc-800); + --color-gray-900: var(--color-zinc-900); } - :root[data-theme=\\"light\\"] { - --sl-color-white: #111827; - --sl-color-gray-1: #1f2937; - --sl-color-gray-2: #374151; - --sl-color-gray-3: #6b7280; - --sl-color-gray-4: #9ca3af; - --sl-color-gray-5: #d1d5db; - --sl-color-gray-6: #e5e7eb; - --sl-color-gray-7: #f3f4f6; - --sl-color-black: #fff; - --sl-color-accent-low: #c7d2fe; - --sl-color-accent: #4f46e5; - --sl-color-accent-high: #312e81; - }" + " `); - }); +}); - test('configures `--sl-color-*` variables', () => { - expect(base).includes('--sl-color-gray-1: #e5e7eb;'); - expect(base).includes('--sl-color-accent: #4f46e5;'); +describe('@theme', () => { + function getRootVariables(output: string) { + return output.match(/:root, :host {(.*?)}\n*$/s)?.[1]; + } + + test('defines Tailwind variables with Starlight defaults', async () => { + const output = await render(); + const rootVariables = getRootVariables(output); + + expect(rootVariables).toMatchInlineSnapshot(` + " + --color-accent-200: var(--color-indigo-200); + --color-accent-600: var(--color-indigo-600); + --color-accent-900: var(--color-indigo-900); + --color-accent-950: var(--color-indigo-950); + --color-gray-100: var(--color-zinc-100); + --color-gray-200: var(--color-zinc-200); + --color-gray-300: var(--color-zinc-300); + --color-gray-400: var(--color-zinc-400); + --color-gray-500: var(--color-zinc-500); + --color-gray-600: var(--color-zinc-600); + --color-gray-700: var(--color-zinc-700); + --color-gray-800: var(--color-zinc-800); + --color-gray-900: var(--color-zinc-900); + " + `); }); - describe('with user theme config', async () => { - const baseWithConfig = await generatePluginCss({ - config: { - corePlugins: [], - theme: { extend: { colors: { accent: colors.amber, gray: colors.slate } } }, - }, - }); + test('defines Tailwind variables with custom values', async () => { + // const output = await render(); + const output = await render( + ['dark:bg-black'], + css` + @theme { + /* Custom accent color. */ + --color-accent-50: var(--color-orange-50); + --color-accent-100: var(--color-orange-100); + --color-accent-200: var(--color-orange-200); + --color-accent-300: var(--color-orange-300); + --color-accent-400: var(--color-orange-400); + --color-accent-500: var(--color-orange-500); + --color-accent-600: var(--color-orange-600); + --color-accent-700: var(--color-orange-700); + --color-accent-800: var(--color-orange-800); + --color-accent-900: var(--color-orange-900); + --color-accent-950: var(--color-orange-950); + /* Custom gray scale. */ + --color-gray-50: var(--color-violet-50); + --color-gray-100: var(--color-violet-100); + --color-gray-200: var(--color-violet-200); + --color-gray-300: var(--color-violet-300); + --color-gray-400: var(--color-violet-400); + --color-gray-500: var(--color-violet-500); + --color-gray-600: var(--color-violet-600); + --color-gray-700: var(--color-violet-700); + --color-gray-800: var(--color-violet-800); + --color-gray-900: var(--color-violet-900); + --color-gray-950: var(--color-violet-950); + /* Custom text font. */ + --font-sans: 'Atkinson Hyperlegible'; + /* Custom code font. */ + --font-mono: 'IBM Plex Mono'; + } + ` + ); + const rootVariables = getRootVariables(output); + + expect(rootVariables).toMatchInlineSnapshot(` + " + --color-accent-200: var(--color-orange-200); + --color-accent-600: var(--color-orange-600); + --color-accent-900: var(--color-orange-900); + --color-accent-950: var(--color-orange-950); + --color-gray-100: var(--color-violet-100); + --color-gray-200: var(--color-violet-200); + --color-gray-300: var(--color-violet-300); + --color-gray-400: var(--color-violet-400); + --color-gray-500: var(--color-violet-500); + --color-gray-600: var(--color-violet-600); + --color-gray-700: var(--color-violet-700); + --color-gray-800: var(--color-violet-800); + --color-gray-900: var(--color-violet-900); + --font-sans: "Atkinson Hyperlegible"; + --font-mono: "IBM Plex Mono"; + " + `); + }); +}); - test('generates different CSS from base without user config', () => { - expect(baseWithConfig).not.toEqual(base); - }); +describe('@layer base', async () => { + const output = await render(); + const baseLayer = output.match(/@layer base {(.*?)}[\s\n]*@layer/s)?.[1]; - test('uses theme values for Starlight colours', () => { - expect(baseWithConfig).includes('--sl-color-gray-1: #e2e8f0;'); - expect(baseWithConfig).includes('--sl-color-accent: #d97706;'); - }); + test('restores some styles from Tailwind Preflight in the base layer', () => { + expect(baseLayer).toMatch(/html, :host {[\s\n]+font-family: var\(--font-sans\);[\s\n]+}/); + expect(baseLayer).toMatch( + /code, kbd, samp, pre {[\s\n]+font-family: var\(--font-mono\);[\s\n]+}/ + ); }); +}); - test('disables Tailwind preflight', async () => { - const baseWithDefaultPlugins = await generatePluginCss(); - expect(baseWithDefaultPlugins).not.includes('line-height: 1.5;'); - expect(baseWithDefaultPlugins).includes('--tw-'); - expect(baseWithDefaultPlugins).toMatchInlineSnapshot(` - "*, ::before, ::after { - border-width: 0; - border-style: solid; - border-color: #e5e7eb; - } - ::before, ::after { - --tw-content: ; - } - :root { - --sl-font: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \\"Segoe UI\\", Roboto, \\"Helvetica Neue\\", Arial, \\"Noto Sans\\", sans-serif, \\"Apple Color Emoji\\", \\"Segoe UI Emoji\\", \\"Segoe UI Symbol\\", \\"Noto Color Emoji\\"; - --sl-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \\"Liberation Mono\\", \\"Courier New\\", monospace; - --sl-color-white: #fff; - --sl-color-gray-1: #e5e7eb; - --sl-color-gray-2: #d1d5db; - --sl-color-gray-3: #9ca3af; - --sl-color-gray-4: #4b5563; - --sl-color-gray-5: #374151; - --sl-color-gray-6: #1f2937; - --sl-color-black: #111827; - --sl-color-accent-low: #1e1b4b; - --sl-color-accent: #4f46e5; - --sl-color-accent-high: #c7d2fe; - } - :root[data-theme=\\"light\\"] { - --sl-color-white: #111827; - --sl-color-gray-1: #1f2937; - --sl-color-gray-2: #374151; - --sl-color-gray-3: #6b7280; - --sl-color-gray-4: #9ca3af; - --sl-color-gray-5: #d1d5db; - --sl-color-gray-6: #e5e7eb; - --sl-color-gray-7: #f3f4f6; - --sl-color-black: #fff; - --sl-color-accent-low: #c7d2fe; - --sl-color-accent: #4f46e5; - --sl-color-accent-high: #312e81; - } - *, ::before, ::after { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; +describe('@layer utilities', async () => { + const output = await render( + ['dark:bg-black'], + css` + @theme { + --color-black: #000; } - ::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - }" - `); + ` + ); + const utilitiesLayer = output.match(/@layer utilities {(.*?)}[\s\n]*:root, :host/s)?.[1]; + + test('configures `--sl-color-*` variables', () => { + expect(utilitiesLayer).includes('--sl-color-gray-1: var(--color-gray-200);'); + expect(utilitiesLayer).includes('--sl-color-accent: var(--color-accent-600, #4f46e5);'); }); -}); -describe('@tailwind utilities;', () => { - test('uses [data-theme="dark"] for dark: utility classes', async () => { - const utils = await generatePluginCss({ - css: '@tailwind utilities;', - html: '<div class="dark:text-red-50"></div>', - }); - expect(utils).includes('[data-theme="dark"] .dark'); - expect(utils).toMatchInlineSnapshot(` - ":is([data-theme=\\"dark\\"] .dark\\\\:text-red-50) { - --tw-text-opacity: 1; - color: rgb(254 242 242 / var(--tw-text-opacity)) - }" + test('uses [data-theme="dark"] for dark: utility classes', () => { + expect(utilitiesLayer).toMatchInlineSnapshot(` + " + .dark\\:bg-black { + &:where([data-theme="dark"], [data-theme="dark"] *) { + background-color: var(--color-black); + } + } + + :root { + --sl-font: var(--font-sans); + --sl-font-mono: var(--font-mono); + --sl-color-white: var(--color-white); + --sl-color-gray-1: var(--color-gray-200); + --sl-color-gray-2: var(--color-gray-300); + --sl-color-gray-3: var(--color-gray-400); + --sl-color-gray-4: var(--color-gray-600); + --sl-color-gray-5: var(--color-gray-700); + --sl-color-gray-6: var(--color-gray-800); + --sl-color-black: var(--color-gray-900); + --sl-color-accent-low: var(--color-accent-950, var(--color-accent-900, #1e1b4b)); + --sl-color-accent: var(--color-accent-600, #4f46e5); + --sl-color-accent-high: var(--color-accent-200, #c7d2fe); + + &[data-theme="light"] { + --sl-color-white: var(--color-gray-900); + --sl-color-gray-1: var(--color-gray-800); + --sl-color-gray-2: var(--color-gray-700); + --sl-color-gray-3: var(--color-gray-500); + --sl-color-gray-4: var(--color-gray-400); + --sl-color-gray-5: var(--color-gray-300); + --sl-color-gray-6: var(--color-gray-200); + --sl-color-gray-7: var(--color-gray-100); + --sl-color-black: var(--color-white); + --sl-color-accent-low: var(--color-accent-200, #c7d2fe); + --sl-color-accent: var(--color-accent-600, #4f46e5); + --sl-color-accent-high: var(--color-accent-900, #312e81); + } + } + " `); }); }); -test('warns when a prefix of "sl-" is set', async () => { - const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}); - await generatePluginCss({ config: { prefix: 'sl-' } }); - expect(warn).toBeCalledTimes(1); - expect(warn.mock.lastCall?.[0]).toMatchInlineSnapshot(` - "A Tailwind prefix of \\"sl-\\" will clash with Starlight’s built-in styles. - Please set a different prefix in your Tailwind config file." +// https://github.com/tailwindlabs/tailwindcss/blob/61af484ff4f34464b317895598c49966c132b410/packages/tailwindcss/src/test-utils/run.ts +async function render(candidates: string[] = [], theme: string = '') { + const { build } = await compile(css` + @layer theme, base, components, utilities; + + @layer utilities { + @tailwind utilities; + } + + ${starlightTailwindCss} + + ${theme} `); - warn.mockRestore(); -}); + + return transform({ + code: Uint8Array.from(Buffer.from(build(candidates))), + filename: 'test.css', + }).code.toString(); +} diff --git a/packages/tailwind/index.ts b/packages/tailwind/index.ts deleted file mode 100644 index b35b3390260..00000000000 --- a/packages/tailwind/index.ts +++ /dev/null @@ -1,107 +0,0 @@ -import plugin from 'tailwindcss/plugin'; - -/** - * Starlight Tailwind Plugin - * - * - Disables Tailwind Preflight. - * - Configures `dark:` variants for Starlight dark mode. - * - Links Starlight’s colors to `gray` and `accent` in Tailwind theme settings. - * - Links Starlight’s fonts to `sans` and `mono` in Tailwind theme settings. - * - * @example - * // tailwind.config.cjs - * const colors = require('tailwindcss/colors'); - * const starlightPlugin = require('@astrojs/starlight/tailwind'); - * - * module.exports = { - * plugins: [ - * // Add Starlight’s Tailwind plugin - * starlightPlugin(), - * ], - * theme: { - * extend: { - * colors: { - * // Set an accent color for Astro to use. Indigo is closest to Astro’s defaults. - * accent: colors.yellow, - * // Configure your preferred gray scale. Zinc is closest to Astro’s defaults. - * gray: colors.zinc, - * }, - * }, - * }, - * } - */ -const StarlightTailwindPlugin = () => - plugin( - ({ addBase, theme, config }) => { - if (config<string>('prefix') === 'sl-') { - console.warn( - 'A Tailwind prefix of "sl-" will clash with Starlight’s built-in styles.\n' + - 'Please set a different prefix in your Tailwind config file.' - ); - } - - /** Utility to apply accent colors based on a user’s theme config. */ - const themeAccent = ( - shade: 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950, - fallback: string - ) => - shade === 950 - ? theme(`colors.accent.${shade}`, theme(`colors.accent.900`, fallback)) - : theme(`colors.accent.${shade}`, fallback); - - addBase({ - // Restore crucial styles from Tailwind Preflight: https://tailwindcss.com/docs/preflight - // Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) - '*, ::before, ::after': { - borderWidth: '0', - borderStyle: 'solid', - borderColor: theme('borderColor.DEFAULT', 'currentColor'), - }, - '::before, ::after': { '--tw-content': '' }, - - // Wire up Starlight theme to use Tailwind config. - ':root': { - // Use Tailwind-configured font families. - '--sl-font': theme('fontFamily.sans'), - '--sl-font-mono': theme('fontFamily.mono'), - // Dark mode Starlight theme variables. - '--sl-color-white': theme('colors.white'), - '--sl-color-gray-1': theme('colors.gray.200'), - '--sl-color-gray-2': theme('colors.gray.300'), - '--sl-color-gray-3': theme('colors.gray.400'), - '--sl-color-gray-4': theme('colors.gray.600'), - '--sl-color-gray-5': theme('colors.gray.700'), - '--sl-color-gray-6': theme('colors.gray.800'), - '--sl-color-black': theme('colors.gray.900'), - '--sl-color-accent-low': themeAccent(950, '#1e1b4b'), - '--sl-color-accent': themeAccent(600, '#4f46e5'), - '--sl-color-accent-high': themeAccent(200, '#c7d2fe'), - // Light mode Starlight theme variables - '&[data-theme="light"]': { - '--sl-color-white': theme('colors.gray.900'), - '--sl-color-gray-1': theme('colors.gray.800'), - '--sl-color-gray-2': theme('colors.gray.700'), - '--sl-color-gray-3': theme('colors.gray.500'), - '--sl-color-gray-4': theme('colors.gray.400'), - '--sl-color-gray-5': theme('colors.gray.300'), - '--sl-color-gray-6': theme('colors.gray.200'), - '--sl-color-gray-7': theme('colors.gray.100'), - '--sl-color-black': theme('colors.white'), - '--sl-color-accent-low': themeAccent(200, '#c7d2fe'), - '--sl-color-accent': themeAccent(600, '#4f46e5'), - '--sl-color-accent-high': themeAccent(900, '#312e81'), - }, - }, - }); - }, - { - // Starlight uses a `data-theme` attribute to power its dark mode. - darkMode: ['class', '[data-theme="dark"]'], - corePlugins: { - // Disable Tailwind’s default reset styles which conflict with Starlight. - preflight: false, - }, - } - ); - -export default StarlightTailwindPlugin; diff --git a/packages/tailwind/package.json b/packages/tailwind/package.json index d7496c524e0..c577c02519c 100644 --- a/packages/tailwind/package.json +++ b/packages/tailwind/package.json @@ -1,6 +1,6 @@ { "name": "@astrojs/starlight-tailwind", - "version": "2.0.0", + "version": "4.0.2", "description": "Tailwind CSS plugin for the Starlight documentation theme for Astro", "author": "Chris Swithinbank <swithinbank@gmail.com>", "license": "MIT", @@ -13,23 +13,25 @@ "homepage": "https://starlight.astro.build", "type": "module", "files": [ - "index.ts" + "tailwind.css" ], "exports": { - ".": "./index.ts" + ".": "./tailwind.css" }, "scripts": { "test": "vitest", - "test:coverage": "vitest run --coverage" + "test:coverage": "pnpm test" }, "devDependencies": { - "@vitest/coverage-v8": "^0.33.0", - "postcss": "^8.4.27", - "vitest": "^0.33.0" + "lightningcss": "^1.29.1", + "tailwindcss": "^4.0.7", + "vitest": "^3.0.5" }, "peerDependencies": { - "@astrojs/starlight": ">=0.9.0", - "@astrojs/tailwind": "^5.0.0", - "tailwindcss": "^3.3.3" + "@astrojs/starlight": ">=0.34.0", + "tailwindcss": "^4.0.0" + }, + "publishConfig": { + "provenance": true } } diff --git a/packages/tailwind/tailwind.css b/packages/tailwind/tailwind.css new file mode 100644 index 00000000000..aeb3a1349ae --- /dev/null +++ b/packages/tailwind/tailwind.css @@ -0,0 +1,85 @@ +@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *)); + +@theme { + /* Default accent color. Indigo is closest to Starlight’s defaults. */ + --color-accent-50: var(--color-indigo-50); + --color-accent-100: var(--color-indigo-100); + --color-accent-200: var(--color-indigo-200); + --color-accent-300: var(--color-indigo-300); + --color-accent-400: var(--color-indigo-400); + --color-accent-500: var(--color-indigo-500); + --color-accent-600: var(--color-indigo-600); + --color-accent-700: var(--color-indigo-700); + --color-accent-800: var(--color-indigo-800); + --color-accent-900: var(--color-indigo-900); + --color-accent-950: var(--color-indigo-950); + /* Default gray scale. Zinc is closest to Starlight’s defaults. */ + --color-gray-50: var(--color-zinc-50); + --color-gray-100: var(--color-zinc-100); + --color-gray-200: var(--color-zinc-200); + --color-gray-300: var(--color-zinc-300); + --color-gray-400: var(--color-zinc-400); + --color-gray-500: var(--color-zinc-500); + --color-gray-600: var(--color-zinc-600); + --color-gray-700: var(--color-zinc-700); + --color-gray-800: var(--color-zinc-800); + --color-gray-900: var(--color-zinc-900); + --color-gray-950: var(--color-zinc-950); +} + +@layer base { + /* Restore crucial styles from Tailwind Preflight: https://tailwindcss.com/docs/preflight */ + /* Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) */ + *, + ::after, + ::before { + border: 0 solid; + } + /* Keep base font-family styles even in non-Starlight pages. */ + html, + :host { + font-family: var(--font-sans); + } + code, + kbd, + samp, + pre { + font-family: var(--font-mono); + } +} + +@layer utilities { + /* Wire up Starlight theme to use Tailwind config. */ + :root { + /* Use Tailwind-configured font families. */ + --sl-font: var(--font-sans); + --sl-font-mono: var(--font-mono); + /* Dark mode Starlight theme variables. */ + --sl-color-white: var(--color-white); + --sl-color-gray-1: var(--color-gray-200); + --sl-color-gray-2: var(--color-gray-300); + --sl-color-gray-3: var(--color-gray-400); + --sl-color-gray-4: var(--color-gray-600); + --sl-color-gray-5: var(--color-gray-700); + --sl-color-gray-6: var(--color-gray-800); + --sl-color-black: var(--color-gray-900); + --sl-color-accent-low: var(--color-accent-950, var(--color-accent-900, #1e1b4b)); + --sl-color-accent: var(--color-accent-600, #4f46e5); + --sl-color-accent-high: var(--color-accent-200, #c7d2fe); + /* Light mode Starlight theme variables. */ + &[data-theme='light'] { + --sl-color-white: var(--color-gray-900); + --sl-color-gray-1: var(--color-gray-800); + --sl-color-gray-2: var(--color-gray-700); + --sl-color-gray-3: var(--color-gray-500); + --sl-color-gray-4: var(--color-gray-400); + --sl-color-gray-5: var(--color-gray-300); + --sl-color-gray-6: var(--color-gray-200); + --sl-color-gray-7: var(--color-gray-100); + --sl-color-black: var(--color-white); + --sl-color-accent-low: var(--color-accent-200, #c7d2fe); + --sl-color-accent: var(--color-accent-600, #4f46e5); + --sl-color-accent-high: var(--color-accent-900, #312e81); + } + } +} diff --git a/packages/tailwind/vitest.config.ts b/packages/tailwind/vitest.config.ts index b29e52cd64b..e32dbf9ae85 100644 --- a/packages/tailwind/vitest.config.ts +++ b/packages/tailwind/vitest.config.ts @@ -2,13 +2,15 @@ import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { + css: true, coverage: { reportsDirectory: './__coverage__', - thresholdAutoUpdate: true, - lines: 100, - functions: 100, - branches: 100, - statements: 100, + thresholds: { + lines: 91, + functions: 100, + branches: 85, + statements: 91, + }, }, }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 54132f2d4e3..20b43fd7cb4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4946 +1,7779 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: - autoInstallPeers: true + autoInstallPeers: false excludeLinksFromLockfile: false importers: .: devDependencies: + '@astrojs/check': + specifier: ^0.9.4 + version: 0.9.4(prettier-plugin-astro@0.14.1)(prettier@3.3.3)(typescript@5.6.3) '@changesets/changelog-github': - specifier: ^0.4.8 - version: 0.4.8 + specifier: ^0.5.0 + version: 0.5.0 '@changesets/cli': - specifier: ^2.26.1 - version: 2.26.1 + specifier: ^2.27.9 + version: 2.27.9 + '@eslint/js': + specifier: ^9.33.0 + version: 9.33.0 '@size-limit/file': - specifier: ^8.2.4 - version: 8.2.4(size-limit@8.2.4) + specifier: ^11.1.6 + version: 11.1.6(size-limit@11.1.6) astro: - specifier: ^3.2.1 - version: 3.2.1(@types/node@18.16.19) + specifier: ^5.6.1 + version: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) + eslint: + specifier: ^9.33.0 + version: 9.33.0(jiti@2.4.2) + eslint-config-prettier: + specifier: ^10.1.8 + version: 10.1.8(eslint@9.33.0(jiti@2.4.2)) + globals: + specifier: ^16.3.0 + version: 16.3.0 prettier: - specifier: ^3.0.0 - version: 3.0.0 + specifier: ^3.3.3 + version: 3.3.3 prettier-plugin-astro: - specifier: ^0.11.0 - version: 0.11.0 + specifier: ^0.14.1 + version: 0.14.1 size-limit: - specifier: ^8.2.4 - version: 8.2.4 + specifier: ^11.1.6 + version: 11.1.6 + typescript: + specifier: ^5.6.3 + version: 5.6.3 + typescript-eslint: + specifier: ^8.39.1 + version: 8.39.1(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3) docs: dependencies: + '@astro-community/astro-embed-youtube': + specifier: ^0.5.6 + version: 0.5.6(astro@5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1)) '@astrojs/starlight': specifier: workspace:* version: link:../packages/starlight + '@lunariajs/core': + specifier: ^0.1.1 + version: 0.1.1 '@types/culori': - specifier: ^2.0.0 - version: 2.0.0 + specifier: ^2.1.1 + version: 2.1.1 astro: - specifier: ^3.2.1 - version: 3.2.1(@types/node@18.16.19) + specifier: ^5.6.1 + version: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) culori: - specifier: ^3.2.0 - version: 3.2.0 + specifier: ^4.0.1 + version: 4.0.1 sharp: - specifier: ^0.32.5 - version: 0.32.5 - devDependencies: - hast-util-from-html: - specifier: ^1.0.2 - version: 1.0.2 - hast-util-to-string: - specifier: ^2.0.0 - version: 2.0.0 - hastscript: - specifier: ^7.2.0 - version: 7.2.0 - pa11y-ci: - specifier: ^3.0.1 - version: 3.0.1 - rehype: - specifier: ^12.0.1 - version: 12.0.1 - start-server-and-test: - specifier: ^2.0.0 - version: 2.0.0 - unist-util-visit: - specifier: ^4.1.2 - version: 4.1.2 - - docs-i18n-tracker: + specifier: ^0.34.2 + version: 0.34.2 devDependencies: - '@types/html-escaper': - specifier: ^3.0.0 - version: 3.0.0 - dedent-js: - specifier: ^1.0.1 - version: 1.0.1 - fast-glob: + '@playwright/test': + specifier: ^1.45.0 + version: 1.45.0 + axe-playwright: + specifier: ^2.0.3 + version: 2.0.3(playwright@1.45.0) + sitemapper: specifier: ^3.2.12 - version: 3.3.1 - html-escaper: - specifier: ^3.0.3 - version: 3.0.3 - kleur: - specifier: ^4.1.5 - version: 4.1.5 - node-fetch: - specifier: ^3.3.1 - version: 3.3.1 - p-retry: - specifier: ^5.1.2 - version: 5.1.2 - simple-git: - specifier: ^3.19.0 - version: 3.19.0 - tsm: - specifier: ^2.3.0 - version: 2.3.0 + version: 3.2.12 + starlight-links-validator: + specifier: ^0.14.0 + version: 0.14.0(@astrojs/starlight@packages+starlight) examples/basics: dependencies: '@astrojs/starlight': - specifier: ^0.10.3 + specifier: ^0.37.6 + version: link:../../packages/starlight + astro: + specifier: ^5.6.1 + version: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) + sharp: + specifier: ^0.34.2 + version: 0.34.2 + + examples/markdoc: + dependencies: + '@astrojs/markdoc': + specifier: ^0.13.3 + version: 0.13.4(astro@5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1)) + '@astrojs/starlight': + specifier: ^0.37.6 version: link:../../packages/starlight + '@astrojs/starlight-markdoc': + specifier: ^0.5.1 + version: link:../../packages/markdoc astro: - specifier: ^3.2.1 - version: 3.2.1(@types/node@18.16.19) + specifier: ^5.6.1 + version: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) sharp: - specifier: ^0.32.5 - version: 0.32.5 + specifier: ^0.34.2 + version: 0.34.2 examples/tailwind: dependencies: '@astrojs/starlight': - specifier: ^0.10.3 + specifier: ^0.37.6 version: link:../../packages/starlight '@astrojs/starlight-tailwind': - specifier: ^2.0.0 + specifier: ^4.0.2 version: link:../../packages/tailwind - '@astrojs/tailwind': - specifier: ^5.0.0 - version: 5.0.0(astro@3.2.1)(tailwindcss@3.3.3) + '@tailwindcss/vite': + specifier: ^4.0.7 + version: 4.0.15(vite@6.2.6(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1)) astro: - specifier: ^3.2.1 - version: 3.2.1(@types/node@18.16.19) + specifier: ^5.6.1 + version: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) sharp: - specifier: ^0.32.5 - version: 0.32.5 + specifier: ^0.34.2 + version: 0.34.2 tailwindcss: - specifier: ^3.3.3 - version: 3.3.3 + specifier: ^4.0.7 + version: 4.0.15 + + packages/docsearch: + dependencies: + '@docsearch/css': + specifier: ^3.6.0 + version: 3.6.0 + '@docsearch/js': + specifier: ^3.6.0 + version: 3.6.0(@algolia/client-search@4.20.0) + devDependencies: + '@astrojs/starlight': + specifier: workspace:* + version: link:../starlight + + packages/file-icons-generator: + dependencies: + opentype.js: + specifier: ^1.3.4 + version: 1.3.4 + tsx: + specifier: ^4.15.2 + version: 4.15.2 + devDependencies: + '@types/opentype.js': + specifier: ^1.3.8 + version: 1.3.8 + + packages/markdoc: + devDependencies: + '@astrojs/markdoc': + specifier: ^0.13.3 + version: 0.13.4(astro@5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1)) + '@astrojs/starlight': + specifier: workspace:* + version: link:../starlight + vitest: + specifier: ^3.0.5 + version: 3.1.1(@types/debug@4.1.12)(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1) packages/starlight: dependencies: + '@astrojs/markdown-remark': + specifier: ^6.3.1 + version: 6.3.1 '@astrojs/mdx': - specifier: ^1.1.0 - version: 1.1.0(astro@3.2.1) + specifier: ^4.2.3 + version: 4.2.4(astro@5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1)) '@astrojs/sitemap': - specifier: ^3.0.0 - version: 3.0.0 + specifier: ^3.3.0 + version: 3.3.0 '@pagefind/default-ui': - specifier: ^1.0.3 - version: 1.0.3 + specifier: ^1.3.0 + version: 1.3.0 + '@types/hast': + specifier: ^3.0.4 + version: 3.0.4 + '@types/js-yaml': + specifier: ^4.0.9 + version: 4.0.9 '@types/mdast': - specifier: ^3.0.11 - version: 3.0.11 + specifier: ^4.0.4 + version: 4.0.4 + astro-expressive-code: + specifier: ^0.41.1 + version: 0.41.1(astro@5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1)) bcp-47: specifier: ^2.1.0 version: 2.1.0 - execa: - specifier: ^7.1.1 - version: 7.1.1 + hast-util-from-html: + specifier: ^2.0.1 + version: 2.0.3 hast-util-select: - specifier: ^5.0.5 - version: 5.0.5 + specifier: ^6.0.2 + version: 6.0.2 + hast-util-to-string: + specifier: ^3.0.0 + version: 3.0.0 hastscript: - specifier: ^7.2.0 - version: 7.2.0 + specifier: ^9.0.0 + version: 9.0.0 + i18next: + specifier: ^23.11.5 + version: 23.11.5 + js-yaml: + specifier: ^4.1.0 + version: 4.1.0 + klona: + specifier: ^2.0.6 + version: 2.0.6 + magic-string: + specifier: ^0.30.17 + version: 0.30.17 + mdast-util-directive: + specifier: ^3.0.0 + version: 3.0.0 + mdast-util-to-markdown: + specifier: ^2.1.0 + version: 2.1.0 + mdast-util-to-string: + specifier: ^4.0.0 + version: 4.0.0 pagefind: - specifier: ^1.0.3 - version: 1.0.3 + specifier: ^1.3.0 + version: 1.3.0 rehype: - specifier: ^12.0.1 - version: 12.0.1 + specifier: ^13.0.1 + version: 13.0.2 + rehype-format: + specifier: ^5.0.0 + version: 5.0.0 remark-directive: - specifier: ^2.0.1 - version: 2.0.1 + specifier: ^3.0.0 + version: 3.0.0 + ultrahtml: + specifier: ^1.6.0 + version: 1.6.0 unified: - specifier: ^10.1.2 - version: 10.1.2 - unist-util-remove: - specifier: ^3.1.1 - version: 3.1.1 + specifier: ^11.0.5 + version: 11.0.5 unist-util-visit: - specifier: ^4.1.2 - version: 4.1.2 + specifier: ^5.0.0 + version: 5.0.0 vfile: - specifier: ^5.3.7 - version: 5.3.7 + specifier: ^6.0.2 + version: 6.0.3 devDependencies: + '@playwright/test': + specifier: ^1.45.0 + version: 1.45.0 '@types/node': specifier: ^18.16.19 version: 18.16.19 '@vitest/coverage-v8': - specifier: ^0.33.0 - version: 0.33.0(vitest@0.33.0) + specifier: ^3.0.5 + version: 3.0.5(vitest@3.1.1(@types/debug@4.1.12)(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1)) astro: - specifier: ^3.2.1 - version: 3.2.1(@types/node@18.16.19) + specifier: ^5.6.1 + version: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) + linkedom: + specifier: ^0.18.4 + version: 0.18.4 vitest: - specifier: ^0.33.0 - version: 0.33.0 + specifier: ^3.0.5 + version: 3.1.1(@types/debug@4.1.12)(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1) - packages/tailwind: + packages/starlight/__e2e__/fixtures/basics: dependencies: '@astrojs/starlight': - specifier: '>=0.9.0' - version: link:../starlight - '@astrojs/tailwind': - specifier: ^5.0.0 - version: 5.0.0(astro@3.2.1)(tailwindcss@3.3.3) - tailwindcss: - specifier: ^3.3.3 - version: 3.3.3 - devDependencies: - '@vitest/coverage-v8': - specifier: ^0.33.0 - version: 0.33.0(vitest@0.33.0) - postcss: - specifier: ^8.4.27 - version: 8.4.29 - vitest: - specifier: ^0.33.0 - version: 0.33.0 - -packages: - - /@alloc/quick-lru@5.2.0: - resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} - engines: {node: '>=10'} - dev: false + specifier: workspace:* + version: link:../../.. + astro: + specifier: ^5.6.1 + version: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) - /@ampproject/remapping@2.2.1: - resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} - engines: {node: '>=6.0.0'} + packages/starlight/__e2e__/fixtures/custom src-dir: dependencies: - '@jridgewell/gen-mapping': 0.3.2 - '@jridgewell/trace-mapping': 0.3.18 + '@astrojs/starlight': + specifier: workspace:* + version: link:../../.. + astro: + specifier: ^5.6.1 + version: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) - /@astrojs/compiler@1.8.0: - resolution: {integrity: sha512-E0TI/uyO8n+IPSZ4Fvl9Lne8JKEasR6ZMGvE2G096oTWOXSsPAhRs2LomV3z+/VRepo2h+t/SdVo54wox4eJwA==} - dev: true + packages/starlight/__e2e__/fixtures/git: + dependencies: + '@astrojs/starlight': + specifier: workspace:* + version: link:../../.. + astro: + specifier: ^5.6.1 + version: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) - /@astrojs/compiler@2.1.0: - resolution: {integrity: sha512-Mp+qrNhly+27bL/Zq8lGeUY+YrdoU0eDfIlAeGIPrzt0PnI/jGpvPUdCaugv4zbCrDkOUScFfcbeEiYumrdJnw==} + packages/starlight/__e2e__/fixtures/legacy-collection-config-file: + dependencies: + '@astrojs/starlight': + specifier: workspace:* + version: link:../../.. + astro: + specifier: ^5.6.1 + version: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) - /@astrojs/internal-helpers@0.2.0: - resolution: {integrity: sha512-NQ4ppp1CM0HNkKbJNM4saVSfmUYzGlRalF6wx7F6T/MYHYSWGuojY89/oFTy4t8VlOGUCUijlsVNNeziWaUo5g==} + packages/starlight/__e2e__/fixtures/no-node-builtins: + dependencies: + '@astrojs/starlight': + specifier: workspace:* + version: link:../../.. + astro: + specifier: ^5.6.1 + version: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) - /@astrojs/markdown-remark@3.2.0(astro@3.2.1): - resolution: {integrity: sha512-jigyLfefUZPKgVmmraCkVpdUuFH1R3SrpgQO13axsgwLDBgkggaQpNR5Ag4O9PDualeBtbdt30aYSfvnBKx9Hg==} - peerDependencies: - astro: ^3.1.0 + packages/starlight/__e2e__/fixtures/ssr: dependencies: - '@astrojs/prism': 3.0.0 - astro: 3.2.1(@types/node@18.16.19) - github-slugger: 2.0.0 - import-meta-resolve: 3.0.0 - mdast-util-definitions: 6.0.0 - rehype-raw: 6.1.1 - rehype-stringify: 9.0.4 - remark-gfm: 3.0.1 - remark-parse: 10.0.2 - remark-rehype: 10.1.0 - remark-smartypants: 2.0.0 - shiki: 0.14.3 - unified: 10.1.2 - unist-util-visit: 4.1.2 - vfile: 5.3.7 - transitivePeerDependencies: - - supports-color + '@astrojs/node': + specifier: ^9.0.0 + version: 9.1.3(astro@5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1)) + '@astrojs/starlight': + specifier: workspace:* + version: link:../../.. + astro: + specifier: ^5.6.1 + version: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) - /@astrojs/mdx@1.1.0(astro@3.2.1): - resolution: {integrity: sha512-rmLZBw3CUCkp+5blBJloV2EqJGRaJTraJygWMfCvrLcCA3vzhwzACnVQKdUDlts8EEr6V6+HXYVqi46AVEfobg==} - engines: {node: '>=18.14.1'} - peerDependencies: - astro: ^3.1.0 - dependencies: - '@astrojs/markdown-remark': 3.2.0(astro@3.2.1) - '@mdx-js/mdx': 2.3.0 - acorn: 8.10.0 - astro: 3.2.1(@types/node@18.16.19) - es-module-lexer: 1.3.0 - estree-util-visit: 1.2.1 - github-slugger: 2.0.0 - gray-matter: 4.0.3 - hast-util-to-html: 8.0.4 - kleur: 4.1.5 - rehype-raw: 6.1.1 - remark-gfm: 3.0.1 - remark-smartypants: 2.0.0 - source-map: 0.7.4 - unist-util-visit: 4.1.2 - vfile: 5.3.7 - transitivePeerDependencies: - - supports-color - dev: false + packages/tailwind: + devDependencies: + lightningcss: + specifier: ^1.29.1 + version: 1.29.3 + tailwindcss: + specifier: ^4.0.7 + version: 4.0.15 + vitest: + specifier: ^3.0.5 + version: 3.1.1(@types/debug@4.1.12)(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1) - /@astrojs/prism@3.0.0: - resolution: {integrity: sha512-g61lZupWq1bYbcBnYZqdjndShr/J3l/oFobBKPA3+qMat146zce3nz2kdO4giGbhYDt4gYdhmoBz0vZJ4sIurQ==} - engines: {node: '>=18.14.1'} - dependencies: - prismjs: 1.29.0 +packages: - /@astrojs/sitemap@3.0.0: - resolution: {integrity: sha512-qm7npHuUW4q3OOmulqhJ1g69jEQu0Sdc6P8NbOzqIoosj/L+3v4i8dtKBnp6n1UQ4Sx8H8Vdi3Z/On7i9/ZJhw==} - dependencies: - sitemap: 7.1.1 - zod: 3.21.1 - dev: false + '@algolia/autocomplete-core@1.9.3': + resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==} - /@astrojs/tailwind@5.0.0(astro@3.2.1)(tailwindcss@3.3.3): - resolution: {integrity: sha512-bMZZNNm/SW+ijUKMQDhdiuNWDdR3CubEKUHb2Ran4Arx1ikWn/kKIkFDXUV+MUnsLa7s19x9VMRlARRyKbqMkQ==} + '@algolia/autocomplete-plugin-algolia-insights@1.9.3': + resolution: {integrity: sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==} peerDependencies: - astro: ^3.0.0 - tailwindcss: ^3.0.24 - dependencies: - astro: 3.2.1(@types/node@18.16.19) - autoprefixer: 10.4.15(postcss@8.4.29) - postcss: 8.4.29 - postcss-load-config: 4.0.1(postcss@8.4.29) - tailwindcss: 3.3.3 - transitivePeerDependencies: - - ts-node - dev: false + search-insights: '>= 1 < 3' - /@astrojs/telemetry@3.0.2: - resolution: {integrity: sha512-ef+jqCkqopCzjGfsMsr+8p56Nj6F9ZzouWcWZt+dKsqbRccI3c8K3jfkLcdq4AyfFZtKBDB6N4ZuI68g33oiOg==} - engines: {node: '>=18.14.1'} - dependencies: - ci-info: 3.8.0 - debug: 4.3.4 - dlv: 1.1.3 - dset: 3.1.2 - is-docker: 3.0.0 - is-wsl: 3.0.0 - undici: 5.23.0 - which-pm-runs: 1.1.0 - transitivePeerDependencies: - - supports-color + '@algolia/autocomplete-preset-algolia@1.9.3': + resolution: {integrity: sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==} + peerDependencies: + '@algolia/client-search': '>= 4.9.1 < 6' + algoliasearch: '>= 4.9.1 < 6' - /@babel/code-frame@7.22.13: - resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.22.13 - chalk: 2.4.2 + '@algolia/autocomplete-shared@1.9.3': + resolution: {integrity: sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==} + peerDependencies: + '@algolia/client-search': '>= 4.9.1 < 6' + algoliasearch: '>= 4.9.1 < 6' - /@babel/compat-data@7.22.9: - resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==} - engines: {node: '>=6.9.0'} + '@algolia/cache-browser-local-storage@4.20.0': + resolution: {integrity: sha512-uujahcBt4DxduBTvYdwO3sBfHuJvJokiC3BP1+O70fglmE1ShkH8lpXqZBac1rrU3FnNYSUs4pL9lBdTKeRPOQ==} - /@babel/core@7.22.11: - resolution: {integrity: sha512-lh7RJrtPdhibbxndr6/xx0w8+CVlY5FJZiaSz908Fpy+G0xkBFTvwLcKJFF4PJxVfGhVWNebikpWGnOoC71juQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.22.13 - '@babel/generator': 7.22.10 - '@babel/helper-compilation-targets': 7.22.10 - '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.11) - '@babel/helpers': 7.22.11 - '@babel/parser': 7.22.14 - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.11 - '@babel/types': 7.22.11 - convert-source-map: 1.9.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color + '@algolia/cache-common@4.20.0': + resolution: {integrity: sha512-vCfxauaZutL3NImzB2G9LjLt36vKAckc6DhMp05An14kVo8F1Yofb6SIl6U3SaEz8pG2QOB9ptwM5c+zGevwIQ==} - /@babel/generator@7.22.10: - resolution: {integrity: sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.11 - '@jridgewell/gen-mapping': 0.3.2 - '@jridgewell/trace-mapping': 0.3.18 - jsesc: 2.5.2 + '@algolia/cache-in-memory@4.20.0': + resolution: {integrity: sha512-Wm9ak/IaacAZXS4mB3+qF/KCoVSBV6aLgIGFEtQtJwjv64g4ePMapORGmCyulCFwfePaRAtcaTbMcJF+voc/bg==} - /@babel/helper-annotate-as-pure@7.22.5: - resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.11 + '@algolia/client-account@4.20.0': + resolution: {integrity: sha512-GGToLQvrwo7am4zVkZTnKa72pheQeez/16sURDWm7Seyz+HUxKi3BM6fthVVPUEBhtJ0reyVtuK9ArmnaKl10Q==} - /@babel/helper-compilation-targets@7.22.10: - resolution: {integrity: sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.22.9 - '@babel/helper-validator-option': 7.22.5 - browserslist: 4.21.10 - lru-cache: 5.1.1 - semver: 6.3.1 + '@algolia/client-analytics@4.20.0': + resolution: {integrity: sha512-EIr+PdFMOallRdBTHHdKI3CstslgLORQG7844Mq84ib5oVFRVASuuPmG4bXBgiDbcsMLUeOC6zRVJhv1KWI0ug==} - /@babel/helper-environment-visitor@7.22.5: - resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==} - engines: {node: '>=6.9.0'} + '@algolia/client-common@4.20.0': + resolution: {integrity: sha512-P3WgMdEss915p+knMMSd/fwiHRHKvDu4DYRrCRaBrsfFw7EQHon+EbRSm4QisS9NYdxbS04kcvNoavVGthyfqQ==} - /@babel/helper-function-name@7.22.5: - resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.5 - '@babel/types': 7.22.11 + '@algolia/client-personalization@4.20.0': + resolution: {integrity: sha512-N9+zx0tWOQsLc3K4PVRDV8GUeOLAY0i445En79Pr3zWB+m67V+n/8w4Kw1C5LlbHDDJcyhMMIlqezh6BEk7xAQ==} - /@babel/helper-hoist-variables@7.22.5: - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.11 + '@algolia/client-search@4.20.0': + resolution: {integrity: sha512-zgwqnMvhWLdpzKTpd3sGmMlr4c+iS7eyyLGiaO51zDZWGMkpgoNVmltkzdBwxOVXz0RsFMznIxB9zuarUv4TZg==} - /@babel/helper-module-imports@7.22.5: - resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.11 + '@algolia/logger-common@4.20.0': + resolution: {integrity: sha512-xouigCMB5WJYEwvoWW5XDv7Z9f0A8VoXJc3VKwlHJw/je+3p2RcDXfksLI4G4lIVncFUYMZx30tP/rsdlvvzHQ==} - /@babel/helper-module-transforms@7.22.9(@babel/core@7.22.11): - resolution: {integrity: sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-module-imports': 7.22.5 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.5 + '@algolia/logger-console@4.20.0': + resolution: {integrity: sha512-THlIGG1g/FS63z0StQqDhT6bprUczBI8wnLT3JWvfAQDZX5P6fCg7dG+pIrUBpDIHGszgkqYEqECaKKsdNKOUA==} - /@babel/helper-plugin-utils@7.22.5: - resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} - engines: {node: '>=6.9.0'} + '@algolia/requester-browser-xhr@4.20.0': + resolution: {integrity: sha512-HbzoSjcjuUmYOkcHECkVTwAelmvTlgs48N6Owt4FnTOQdwn0b8pdht9eMgishvk8+F8bal354nhx/xOoTfwiAw==} - /@babel/helper-simple-access@7.22.5: - resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.11 + '@algolia/requester-common@4.20.0': + resolution: {integrity: sha512-9h6ye6RY/BkfmeJp7Z8gyyeMrmmWsMOCRBXQDs4mZKKsyVlfIVICpcSibbeYcuUdurLhIlrOUkH3rQEgZzonng==} - /@babel/helper-split-export-declaration@7.22.6: - resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.11 + '@algolia/requester-node-http@4.20.0': + resolution: {integrity: sha512-ocJ66L60ABSSTRFnCHIEZpNHv6qTxsBwJEPfYaSBsLQodm0F9ptvalFkHMpvj5DfE22oZrcrLbOYM2bdPJRHng==} - /@babel/helper-string-parser@7.22.5: - resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} - engines: {node: '>=6.9.0'} + '@algolia/transporter@4.20.0': + resolution: {integrity: sha512-Lsii1pGWOAISbzeyuf+r/GPhvHMPHSPrTDWNcIzOE1SG1inlJHICaVe2ikuoRjcpgxZNU54Jl+if15SUCsaTUg==} - /@babel/helper-validator-identifier@7.22.5: - resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==} - engines: {node: '>=6.9.0'} + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} - /@babel/helper-validator-option@7.22.5: - resolution: {integrity: sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==} - engines: {node: '>=6.9.0'} + '@astro-community/astro-embed-youtube@0.5.6': + resolution: {integrity: sha512-/mRfCl/eTBUz0kmjD1psOy0qoDDBorVp0QumUacjFcIkBullYtbeFQ2ZGZ+3N/tA6cR/OIyzr2QA4dQXlY6USg==} + peerDependencies: + astro: ^2.0.0 || ^3.0.0-beta || ^4.0.0-beta || ^5.0.0-beta - /@babel/helpers@7.22.11: - resolution: {integrity: sha512-vyOXC8PBWaGc5h7GMsNx68OH33cypkEDJCHvYVVgVbbxJDROYVtexSk0gK5iCF1xNjRIN2s8ai7hwkWDq5szWg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.11 - '@babel/types': 7.22.11 - transitivePeerDependencies: - - supports-color + '@astrojs/check@0.9.4': + resolution: {integrity: sha512-IOheHwCtpUfvogHHsvu0AbeRZEnjJg3MopdLddkJE70mULItS/Vh37BHcI00mcOJcH1vhD3odbpvWokpxam7xA==} + hasBin: true + peerDependencies: + typescript: ^5.0.0 - /@babel/highlight@7.22.13: - resolution: {integrity: sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.5 - chalk: 2.4.2 - js-tokens: 4.0.0 + '@astrojs/compiler@2.11.0': + resolution: {integrity: sha512-zZOO7i+JhojO8qmlyR/URui6LyfHJY6m+L9nwyX5GiKD78YoRaZ5tzz6X0fkl+5bD3uwlDHayf6Oe8Fu36RKNg==} - /@babel/parser@7.22.14: - resolution: {integrity: sha512-1KucTHgOvaw/LzCVrEOAyXkr9rQlp0A1HiHRYnSUE9dmb8PvPW7o5sscg+5169r54n3vGlbx6GevTE/Iw/P3AQ==} - engines: {node: '>=6.0.0'} + '@astrojs/internal-helpers@0.6.1': + resolution: {integrity: sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A==} + + '@astrojs/language-server@2.15.4': + resolution: {integrity: sha512-JivzASqTPR2bao9BWsSc/woPHH7OGSGc9aMxXL4U6egVTqBycB3ZHdBJPuOCVtcGLrzdWTosAqVPz1BVoxE0+A==} hasBin: true - dependencies: - '@babel/types': 7.22.11 + peerDependencies: + prettier: ^3.0.0 + prettier-plugin-astro: '>=0.11.0' + peerDependenciesMeta: + prettier: + optional: true + prettier-plugin-astro: + optional: true - /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.11): - resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} - engines: {node: '>=6.9.0'} + '@astrojs/markdoc@0.13.4': + resolution: {integrity: sha512-vAfC50/vnqimJknU89uTW2gdPv5bnvxvK1pc9dPQGUk4PE3En4Qg1hK1iyLFZE5Q5SmHiCXLvL3G6oExsB2vHQ==} + engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + astro: ^5.0.0 - /@babel/plugin-transform-react-jsx@7.22.5(@babel/core@7.22.11): - resolution: {integrity: sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==} - engines: {node: '>=6.9.0'} + '@astrojs/markdown-remark@6.3.1': + resolution: {integrity: sha512-c5F5gGrkczUaTVgmMW9g1YMJGzOtRvjjhw6IfGuxarM6ct09MpwysP10US729dy07gg8y+ofVifezvP3BNsWZg==} + + '@astrojs/mdx@4.2.4': + resolution: {integrity: sha512-c832AWpiMCcuPY8j+yr5T+hOf8n5RlKLFHlNTt15xxkOk3zjFJP81TIYKrMrbhD5rMzJ09Ixi+xM0m68w2Q0DQ==} + engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-module-imports': 7.22.5 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.11) - '@babel/types': 7.22.11 + astro: ^5.0.0 + + '@astrojs/node@9.1.3': + resolution: {integrity: sha512-YcVxEmeZU8khNdrPYNPN3j//4tYPM+Pw6CthAJ6VE/bw65qEX7ErMRApalY2tibc3YhCeHMmsO9rXGhyW0NNyA==} + peerDependencies: + astro: ^5.3.0 + + '@astrojs/prism@3.2.0': + resolution: {integrity: sha512-GilTHKGCW6HMq7y3BUv9Ac7GMe/MO9gi9GW62GzKtth0SwukCu/qp2wLiGpEujhY+VVhaG9v7kv/5vFzvf4NYw==} + engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} - /@babel/runtime@7.21.5: - resolution: {integrity: sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==} + '@astrojs/sitemap@3.3.0': + resolution: {integrity: sha512-nYE4lKQtk+Kbrw/w0G0TTgT724co0jUsU4tPlHY9au5HmTBKbwiCLwO/15b1/y13aZ4Kr9ZbMeMHlXuwn0ty4Q==} + + '@astrojs/telemetry@3.2.0': + resolution: {integrity: sha512-wxhSKRfKugLwLlr4OFfcqovk+LIFtKwLyGPqMsv+9/ibqqnW3Gv7tBhtKEb0gAyUAC4G9BTVQeQahqnQAhd6IQ==} + engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} + + '@astrojs/yaml2ts@0.2.2': + resolution: {integrity: sha512-GOfvSr5Nqy2z5XiwqTouBBpy5FyI6DEe+/g/Mk5am9SjILN1S5fOEvYK0GuWHg98yS/dobP4m8qyqw/URW35fQ==} + + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.13.11 - dev: true - /@babel/template@7.22.5: - resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.13 - '@babel/parser': 7.22.14 - '@babel/types': 7.22.11 - /@babel/traverse@7.22.11: - resolution: {integrity: sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==} + '@babel/parser@7.26.2': + resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/runtime@7.24.7': + resolution: {integrity: sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.13 - '@babel/generator': 7.22.10 - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-function-name': 7.22.5 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.22.14 - '@babel/types': 7.22.11 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - /@babel/types@7.22.11: - resolution: {integrity: sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==} + '@babel/types@7.26.0': + resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.22.5 - '@babel/helper-validator-identifier': 7.22.5 - to-fast-properties: 2.0.0 - /@bcoe/v8-coverage@0.2.3: - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - dev: true + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} - /@changesets/apply-release-plan@6.1.3: - resolution: {integrity: sha512-ECDNeoc3nfeAe1jqJb5aFQX7CqzQhD2klXRez2JDb/aVpGUbX673HgKrnrgJRuQR/9f2TtLoYIzrGB9qwD77mg==} - dependencies: - '@babel/runtime': 7.21.5 - '@changesets/config': 2.3.0 - '@changesets/get-version-range-type': 0.3.2 - '@changesets/git': 2.0.0 - '@changesets/types': 5.2.1 - '@manypkg/get-packages': 1.1.3 - detect-indent: 6.1.0 - fs-extra: 7.0.1 - lodash.startcase: 4.4.0 - outdent: 0.5.0 - prettier: 2.8.8 - resolve-from: 5.0.0 - semver: 5.7.1 - dev: true + '@changesets/apply-release-plan@7.0.5': + resolution: {integrity: sha512-1cWCk+ZshEkSVEZrm2fSj1Gz8sYvxgUL4Q78+1ZZqeqfuevPTPk033/yUZ3df8BKMohkqqHfzj0HOOrG0KtXTw==} - /@changesets/assemble-release-plan@5.2.3: - resolution: {integrity: sha512-g7EVZCmnWz3zMBAdrcKhid4hkHT+Ft1n0mLussFMcB1dE2zCuwcvGoy9ec3yOgPGF4hoMtgHaMIk3T3TBdvU9g==} - dependencies: - '@babel/runtime': 7.21.5 - '@changesets/errors': 0.1.4 - '@changesets/get-dependents-graph': 1.3.5 - '@changesets/types': 5.2.1 - '@manypkg/get-packages': 1.1.3 - semver: 5.7.1 - dev: true + '@changesets/assemble-release-plan@6.0.4': + resolution: {integrity: sha512-nqICnvmrwWj4w2x0fOhVj2QEGdlUuwVAwESrUo5HLzWMI1rE5SWfsr9ln+rDqWB6RQ2ZyaMZHUcU7/IRaUJS+Q==} - /@changesets/changelog-git@0.1.14: - resolution: {integrity: sha512-+vRfnKtXVWsDDxGctOfzJsPhaCdXRYoe+KyWYoq5X/GqoISREiat0l3L8B0a453B2B4dfHGcZaGyowHbp9BSaA==} - dependencies: - '@changesets/types': 5.2.1 - dev: true + '@changesets/changelog-git@0.2.0': + resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} - /@changesets/changelog-github@0.4.8: - resolution: {integrity: sha512-jR1DHibkMAb5v/8ym77E4AMNWZKB5NPzw5a5Wtqm1JepAuIF+hrKp2u04NKM14oBZhHglkCfrla9uq8ORnK/dw==} - dependencies: - '@changesets/get-github-info': 0.5.2 - '@changesets/types': 5.2.1 - dotenv: 8.6.0 - transitivePeerDependencies: - - encoding - dev: true + '@changesets/changelog-github@0.5.0': + resolution: {integrity: sha512-zoeq2LJJVcPJcIotHRJEEA2qCqX0AQIeFE+L21L8sRLPVqDhSXY8ZWAt2sohtBpFZkBwu+LUwMSKRr2lMy3LJA==} - /@changesets/cli@2.26.1: - resolution: {integrity: sha512-XnTa+b51vt057fyAudvDKGB0Sh72xutQZNAdXkCqPBKO2zvs2yYZx5hFZj1u9cbtpwM6Sxtcr02/FQJfZOzemQ==} + '@changesets/cli@2.27.9': + resolution: {integrity: sha512-q42a/ZbDnxPpCb5Wkm6tMVIxgeI9C/bexntzTeCFBrQEdpisQqk8kCHllYZMDjYtEc1ZzumbMJAG8H0Z4rdvjg==} hasBin: true - dependencies: - '@babel/runtime': 7.21.5 - '@changesets/apply-release-plan': 6.1.3 - '@changesets/assemble-release-plan': 5.2.3 - '@changesets/changelog-git': 0.1.14 - '@changesets/config': 2.3.0 - '@changesets/errors': 0.1.4 - '@changesets/get-dependents-graph': 1.3.5 - '@changesets/get-release-plan': 3.0.16 - '@changesets/git': 2.0.0 - '@changesets/logger': 0.0.5 - '@changesets/pre': 1.0.14 - '@changesets/read': 0.5.9 - '@changesets/types': 5.2.1 - '@changesets/write': 0.2.3 - '@manypkg/get-packages': 1.1.3 - '@types/is-ci': 3.0.0 - '@types/semver': 6.2.3 - ansi-colors: 4.1.3 - chalk: 2.4.2 - enquirer: 2.3.6 - external-editor: 3.1.0 - fs-extra: 7.0.1 - human-id: 1.0.2 - is-ci: 3.0.1 - meow: 6.1.1 - outdent: 0.5.0 - p-limit: 2.3.0 - preferred-pm: 3.1.2 - resolve-from: 5.0.0 - semver: 5.7.1 - spawndamnit: 2.0.0 - term-size: 2.2.1 - tty-table: 4.2.1 - dev: true - /@changesets/config@2.3.0: - resolution: {integrity: sha512-EgP/px6mhCx8QeaMAvWtRrgyxW08k/Bx2tpGT+M84jEdX37v3VKfh4Cz1BkwrYKuMV2HZKeHOh8sHvja/HcXfQ==} - dependencies: - '@changesets/errors': 0.1.4 - '@changesets/get-dependents-graph': 1.3.5 - '@changesets/logger': 0.0.5 - '@changesets/types': 5.2.1 - '@manypkg/get-packages': 1.1.3 - fs-extra: 7.0.1 - micromatch: 4.0.5 - dev: true + '@changesets/config@3.0.3': + resolution: {integrity: sha512-vqgQZMyIcuIpw9nqFIpTSNyc/wgm/Lu1zKN5vECy74u95Qx/Wa9g27HdgO4NkVAaq+BGA8wUc/qvbvVNs93n6A==} - /@changesets/errors@0.1.4: - resolution: {integrity: sha512-HAcqPF7snsUJ/QzkWoKfRfXushHTu+K5KZLJWPb34s4eCZShIf8BFO3fwq6KU8+G7L5KdtN2BzQAXOSXEyiY9Q==} - dependencies: - extendable-error: 0.1.7 - dev: true + '@changesets/errors@0.2.0': + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} - /@changesets/get-dependents-graph@1.3.5: - resolution: {integrity: sha512-w1eEvnWlbVDIY8mWXqWuYE9oKhvIaBhzqzo4ITSJY9hgoqQ3RoBqwlcAzg11qHxv/b8ReDWnMrpjpKrW6m1ZTA==} - dependencies: - '@changesets/types': 5.2.1 - '@manypkg/get-packages': 1.1.3 - chalk: 2.4.2 - fs-extra: 7.0.1 - semver: 5.7.1 - dev: true + '@changesets/get-dependents-graph@2.1.2': + resolution: {integrity: sha512-sgcHRkiBY9i4zWYBwlVyAjEM9sAzs4wYVwJUdnbDLnVG3QwAaia1Mk5P8M7kraTOZN+vBET7n8KyB0YXCbFRLQ==} - /@changesets/get-github-info@0.5.2: - resolution: {integrity: sha512-JppheLu7S114aEs157fOZDjFqUDpm7eHdq5E8SSR0gUBTEK0cNSHsrSR5a66xs0z3RWuo46QvA3vawp8BxDHvg==} - dependencies: - dataloader: 1.4.0 - node-fetch: 2.6.10 - transitivePeerDependencies: - - encoding - dev: true + '@changesets/get-github-info@0.6.0': + resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} - /@changesets/get-release-plan@3.0.16: - resolution: {integrity: sha512-OpP9QILpBp1bY2YNIKFzwigKh7Qe9KizRsZomzLe6pK8IUo8onkAAVUD8+JRKSr8R7d4+JRuQrfSSNlEwKyPYg==} - dependencies: - '@babel/runtime': 7.21.5 - '@changesets/assemble-release-plan': 5.2.3 - '@changesets/config': 2.3.0 - '@changesets/pre': 1.0.14 - '@changesets/read': 0.5.9 - '@changesets/types': 5.2.1 - '@manypkg/get-packages': 1.1.3 - dev: true + '@changesets/get-release-plan@4.0.4': + resolution: {integrity: sha512-SicG/S67JmPTrdcc9Vpu0wSQt7IiuN0dc8iR5VScnnTVPfIaLvKmEGRvIaF0kcn8u5ZqLbormZNTO77bCEvyWw==} - /@changesets/get-version-range-type@0.3.2: - resolution: {integrity: sha512-SVqwYs5pULYjYT4op21F2pVbcrca4qA/bAA3FmFXKMN7Y+HcO8sbZUTx3TAy2VXulP2FACd1aC7f2nTuqSPbqg==} - dev: true + '@changesets/get-version-range-type@0.4.0': + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} - /@changesets/git@2.0.0: - resolution: {integrity: sha512-enUVEWbiqUTxqSnmesyJGWfzd51PY4H7mH9yUw0hPVpZBJ6tQZFMU3F3mT/t9OJ/GjyiM4770i+sehAn6ymx6A==} - dependencies: - '@babel/runtime': 7.21.5 - '@changesets/errors': 0.1.4 - '@changesets/types': 5.2.1 - '@manypkg/get-packages': 1.1.3 - is-subdir: 1.2.0 - micromatch: 4.0.5 - spawndamnit: 2.0.0 - dev: true + '@changesets/git@3.0.1': + resolution: {integrity: sha512-pdgHcYBLCPcLd82aRcuO0kxCDbw/yISlOtkmwmE8Odo1L6hSiZrBOsRl84eYG7DRCab/iHnOkWqExqc4wxk2LQ==} - /@changesets/logger@0.0.5: - resolution: {integrity: sha512-gJyZHomu8nASHpaANzc6bkQMO9gU/ib20lqew1rVx753FOxffnCrJlGIeQVxNWCqM+o6OOleCo/ivL8UAO5iFw==} - dependencies: - chalk: 2.4.2 - dev: true + '@changesets/logger@0.1.1': + resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} - /@changesets/parse@0.3.16: - resolution: {integrity: sha512-127JKNd167ayAuBjUggZBkmDS5fIKsthnr9jr6bdnuUljroiERW7FBTDNnNVyJ4l69PzR57pk6mXQdtJyBCJKg==} - dependencies: - '@changesets/types': 5.2.1 - js-yaml: 3.14.1 - dev: true + '@changesets/parse@0.4.0': + resolution: {integrity: sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==} - /@changesets/pre@1.0.14: - resolution: {integrity: sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==} - dependencies: - '@babel/runtime': 7.21.5 - '@changesets/errors': 0.1.4 - '@changesets/types': 5.2.1 - '@manypkg/get-packages': 1.1.3 - fs-extra: 7.0.1 - dev: true + '@changesets/pre@2.0.1': + resolution: {integrity: sha512-vvBJ/If4jKM4tPz9JdY2kGOgWmCowUYOi5Ycv8dyLnEE8FgpYYUo1mgJZxcdtGGP3aG8rAQulGLyyXGSLkIMTQ==} - /@changesets/read@0.5.9: - resolution: {integrity: sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==} - dependencies: - '@babel/runtime': 7.21.5 - '@changesets/git': 2.0.0 - '@changesets/logger': 0.0.5 - '@changesets/parse': 0.3.16 - '@changesets/types': 5.2.1 - chalk: 2.4.2 - fs-extra: 7.0.1 - p-filter: 2.1.0 - dev: true + '@changesets/read@0.6.1': + resolution: {integrity: sha512-jYMbyXQk3nwP25nRzQQGa1nKLY0KfoOV7VLgwucI0bUO8t8ZLCr6LZmgjXsiKuRDc+5A6doKPr9w2d+FEJ55zQ==} + + '@changesets/should-skip-package@0.1.1': + resolution: {integrity: sha512-H9LjLbF6mMHLtJIc/eHR9Na+MifJ3VxtgP/Y+XLn4BF7tDTEN1HNYtH6QMcjP1uxp9sjaFYmW8xqloaCi/ckTg==} - /@changesets/types@4.1.0: + '@changesets/types@4.1.0': resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} - dev: true - /@changesets/types@5.2.1: - resolution: {integrity: sha512-myLfHbVOqaq9UtUKqR/nZA/OY7xFjQMdfgfqeZIBK4d0hA6pgxArvdv8M+6NUzzBsjWLOtvApv8YHr4qM+Kpfg==} - dev: true + '@changesets/types@6.0.0': + resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} - /@changesets/write@0.2.3: - resolution: {integrity: sha512-Dbamr7AIMvslKnNYsLFafaVORx4H0pvCA2MHqgtNCySMe1blImEyAEOzDmcgKAkgz4+uwoLz7demIrX+JBr/Xw==} - dependencies: - '@babel/runtime': 7.21.5 - '@changesets/types': 5.2.1 - fs-extra: 7.0.1 - human-id: 1.0.2 - prettier: 2.8.8 - dev: true + '@changesets/write@0.3.2': + resolution: {integrity: sha512-kDxDrPNpUgsjDbWBvUo27PzKX4gqeKOlhibaOXDJA6kuBisGqNHv/HwGJrAu8U/dSf8ZEFIeHIPtvSlZI1kULw==} - /@esbuild/android-arm64@0.18.17: - resolution: {integrity: sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true + '@clack/core@0.3.4': + resolution: {integrity: sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==} - /@esbuild/android-arm64@0.19.2: - resolution: {integrity: sha512-lsB65vAbe90I/Qe10OjkmrdxSX4UJDjosDgb8sZUKcg3oefEuW2OT2Vozz8ef7wrJbMcmhvCC+hciF8jY/uAkw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true + '@ctrl/tinycolor@4.1.0': + resolution: {integrity: sha512-WyOx8cJQ+FQus4Mm4uPIZA64gbk3Wxh0so5Lcii0aJifqwoVOlfFtorjLE0Hen4OYyHZMXDWqMmaQemBhgxFRQ==} + engines: {node: '>=14'} + + '@docsearch/css@3.6.0': + resolution: {integrity: sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==} + + '@docsearch/js@3.6.0': + resolution: {integrity: sha512-QujhqINEElrkIfKwyyyTfbsfMAYCkylInLYMRqHy7PHc8xTBQCow73tlo/Kc7oIwBrCLf0P3YhjlOeV4v8hevQ==} + + '@docsearch/react@3.6.0': + resolution: {integrity: sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==} + peerDependencies: + '@types/react': '>= 16.8.0 < 19.0.0' + react: '>= 16.8.0 < 19.0.0' + react-dom: '>= 16.8.0 < 19.0.0' + search-insights: '>= 1 < 3' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + react-dom: + optional: true + search-insights: + optional: true + + '@emmetio/abbreviation@2.3.3': + resolution: {integrity: sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==} + + '@emmetio/css-abbreviation@2.1.8': + resolution: {integrity: sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==} + + '@emmetio/css-parser@0.4.0': + resolution: {integrity: sha512-z7wkxRSZgrQHXVzObGkXG+Vmj3uRlpM11oCZ9pbaz0nFejvCDmAiNDpY75+wgXOcffKpj4rzGtwGaZxfJKsJxw==} + + '@emmetio/html-matcher@1.3.0': + resolution: {integrity: sha512-NTbsvppE5eVyBMuyGfVu2CRrLvo7J4YHb6t9sBFLyY03WYhXET37qA4zOYUjBWFCRHO7pS1B9khERtY0f5JXPQ==} + + '@emmetio/scanner@1.0.4': + resolution: {integrity: sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==} + + '@emmetio/stream-reader-utils@0.1.0': + resolution: {integrity: sha512-ZsZ2I9Vzso3Ho/pjZFsmmZ++FWeEd/txqybHTm4OgaZzdS8V9V/YYWQwg5TC38Z7uLWUV1vavpLLbjJtKubR1A==} - /@esbuild/android-arm@0.15.18: - resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==} + '@emmetio/stream-reader@2.2.0': + resolution: {integrity: sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==} + + '@emnapi/runtime@1.4.3': + resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} - cpu: [arm] + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.25.1': + resolution: {integrity: sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.25.1': + resolution: {integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==} + engines: {node: '>=18'} + cpu: [arm64] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm@0.18.17: - resolution: {integrity: sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==} + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} cpu: [arm] os: [android] - requiresBuild: true - optional: true - /@esbuild/android-arm@0.19.2: - resolution: {integrity: sha512-tM8yLeYVe7pRyAu9VMi/Q7aunpLwD139EY1S99xbQkT4/q2qa6eA4ige/WJQYdJ8GBL1K33pPFhPfPdJ/WzT8Q==} - engines: {node: '>=12'} + '@esbuild/android-arm@0.25.1': + resolution: {integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==} + engines: {node: '>=18'} cpu: [arm] os: [android] - requiresBuild: true - optional: true - /@esbuild/android-x64@0.18.17: - resolution: {integrity: sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==} + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} cpu: [x64] os: [android] - requiresBuild: true - optional: true - /@esbuild/android-x64@0.19.2: - resolution: {integrity: sha512-qK/TpmHt2M/Hg82WXHRc/W/2SGo/l1thtDHZWqFq7oi24AjZ4O/CpPSu6ZuYKFkEgmZlFoa7CooAyYmuvnaG8w==} - engines: {node: '>=12'} + '@esbuild/android-x64@0.25.1': + resolution: {integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==} + engines: {node: '>=18'} cpu: [x64] os: [android] - requiresBuild: true - optional: true - /@esbuild/darwin-arm64@0.18.17: - resolution: {integrity: sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==} + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] - requiresBuild: true - optional: true - /@esbuild/darwin-arm64@0.19.2: - resolution: {integrity: sha512-Ora8JokrvrzEPEpZO18ZYXkH4asCdc1DLdcVy8TGf5eWtPO1Ie4WroEJzwI52ZGtpODy3+m0a2yEX9l+KUn0tA==} - engines: {node: '>=12'} + '@esbuild/darwin-arm64@0.25.1': + resolution: {integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] - requiresBuild: true - optional: true - /@esbuild/darwin-x64@0.18.17: - resolution: {integrity: sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==} + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] - requiresBuild: true - optional: true - /@esbuild/darwin-x64@0.19.2: - resolution: {integrity: sha512-tP+B5UuIbbFMj2hQaUr6EALlHOIOmlLM2FK7jeFBobPy2ERdohI4Ka6ZFjZ1ZYsrHE/hZimGuU90jusRE0pwDw==} - engines: {node: '>=12'} + '@esbuild/darwin-x64@0.25.1': + resolution: {integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] - requiresBuild: true - optional: true - /@esbuild/freebsd-arm64@0.18.17: - resolution: {integrity: sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==} + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] - requiresBuild: true - optional: true - /@esbuild/freebsd-arm64@0.19.2: - resolution: {integrity: sha512-YbPY2kc0acfzL1VPVK6EnAlig4f+l8xmq36OZkU0jzBVHcOTyQDhnKQaLzZudNJQyymd9OqQezeaBgkTGdTGeQ==} - engines: {node: '>=12'} + '@esbuild/freebsd-arm64@0.25.1': + resolution: {integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - requiresBuild: true - optional: true - /@esbuild/freebsd-x64@0.18.17: - resolution: {integrity: sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==} + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] - requiresBuild: true - optional: true - /@esbuild/freebsd-x64@0.19.2: - resolution: {integrity: sha512-nSO5uZT2clM6hosjWHAsS15hLrwCvIWx+b2e3lZ3MwbYSaXwvfO528OF+dLjas1g3bZonciivI8qKR/Hm7IWGw==} - engines: {node: '>=12'} + '@esbuild/freebsd-x64@0.25.1': + resolution: {integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] - requiresBuild: true - optional: true - /@esbuild/linux-arm64@0.18.17: - resolution: {integrity: sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==} + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} cpu: [arm64] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-arm64@0.19.2: - resolution: {integrity: sha512-ig2P7GeG//zWlU0AggA3pV1h5gdix0MA3wgB+NsnBXViwiGgY77fuN9Wr5uoCrs2YzaYfogXgsWZbm+HGr09xg==} - engines: {node: '>=12'} + '@esbuild/linux-arm64@0.25.1': + resolution: {integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-arm@0.18.17: - resolution: {integrity: sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==} + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} cpu: [arm] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-arm@0.19.2: - resolution: {integrity: sha512-Odalh8hICg7SOD7XCj0YLpYCEc+6mkoq63UnExDCiRA2wXEmGlK5JVrW50vZR9Qz4qkvqnHcpH+OFEggO3PgTg==} - engines: {node: '>=12'} + '@esbuild/linux-arm@0.25.1': + resolution: {integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==} + engines: {node: '>=18'} cpu: [arm] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-ia32@0.18.17: - resolution: {integrity: sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==} + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-ia32@0.19.2: - resolution: {integrity: sha512-mLfp0ziRPOLSTek0Gd9T5B8AtzKAkoZE70fneiiyPlSnUKKI4lp+mGEnQXcQEHLJAcIYDPSyBvsUbKUG2ri/XQ==} - engines: {node: '>=12'} + '@esbuild/linux-ia32@0.25.1': + resolution: {integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-loong64@0.15.18: - resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-loong64@0.18.17: - resolution: {integrity: sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==} + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-loong64@0.19.2: - resolution: {integrity: sha512-hn28+JNDTxxCpnYjdDYVMNTR3SKavyLlCHHkufHV91fkewpIyQchS1d8wSbmXhs1fiYDpNww8KTFlJ1dHsxeSw==} - engines: {node: '>=12'} + '@esbuild/linux-loong64@0.25.1': + resolution: {integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-mips64el@0.18.17: - resolution: {integrity: sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==} + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-mips64el@0.19.2: - resolution: {integrity: sha512-KbXaC0Sejt7vD2fEgPoIKb6nxkfYW9OmFUK9XQE4//PvGIxNIfPk1NmlHmMg6f25x57rpmEFrn1OotASYIAaTg==} - engines: {node: '>=12'} + '@esbuild/linux-mips64el@0.25.1': + resolution: {integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-ppc64@0.18.17: - resolution: {integrity: sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==} + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-ppc64@0.19.2: - resolution: {integrity: sha512-dJ0kE8KTqbiHtA3Fc/zn7lCd7pqVr4JcT0JqOnbj4LLzYnp+7h8Qi4yjfq42ZlHfhOCM42rBh0EwHYLL6LEzcw==} - engines: {node: '>=12'} + '@esbuild/linux-ppc64@0.25.1': + resolution: {integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-riscv64@0.18.17: - resolution: {integrity: sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==} + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-riscv64@0.19.2: - resolution: {integrity: sha512-7Z/jKNFufZ/bbu4INqqCN6DDlrmOTmdw6D0gH+6Y7auok2r02Ur661qPuXidPOJ+FSgbEeQnnAGgsVynfLuOEw==} - engines: {node: '>=12'} + '@esbuild/linux-riscv64@0.25.1': + resolution: {integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-s390x@0.18.17: - resolution: {integrity: sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==} + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} cpu: [s390x] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-s390x@0.19.2: - resolution: {integrity: sha512-U+RinR6aXXABFCcAY4gSlv4CL1oOVvSSCdseQmGO66H+XyuQGZIUdhG56SZaDJQcLmrSfRmx5XZOWyCJPRqS7g==} - engines: {node: '>=12'} + '@esbuild/linux-s390x@0.25.1': + resolution: {integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-x64@0.18.17: - resolution: {integrity: sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==} + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.25.1': + resolution: {integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.1': + resolution: {integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.1': + resolution: {integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.1': + resolution: {integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.1': + resolution: {integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.25.1': + resolution: {integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.25.1': + resolution: {integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.25.1': + resolution: {integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.25.1': + resolution: {integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.7.0': + resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.0': + resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.3.1': + resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.15.2': + resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.33.0': + resolution: {integrity: sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.3.5': + resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@expressive-code/core@0.41.1': + resolution: {integrity: sha512-mG2IrN4t/NGPmEeeswmttsW7W7c96sz3ASjo1psQnOqU5QWAF61HpnBu3lPxHI8iQJyZI8wfAroo9FFpwlkvAQ==} + + '@expressive-code/plugin-frames@0.41.1': + resolution: {integrity: sha512-cwUUWMr2jNpKpgiepEzM9BGnU60WepE5/Ar3H2aOn8IzcDa4Eeuk0JqQB1Vvpo0bu+VRIxaTA2njoAIeQuMN5w==} + + '@expressive-code/plugin-shiki@0.41.1': + resolution: {integrity: sha512-xJHk89ECxQpvf7ftTmtEfAKoApYYr5Um7d6fiE6GuY7+WuXN02+ZHH8r5pSJpxlQMfAmavqbNPd3dEJ9v/zHnQ==} + + '@expressive-code/plugin-text-markers@0.41.1': + resolution: {integrity: sha512-PFvk91yY+H8KVEcyZSrktLoWzBgLVpowvMxOJooFn74roGxnU4TEBJpWcRnJFtMEwTLzWNnk10MSOApOccvSKg==} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@img/sharp-darwin-arm64@0.33.3': + resolution: {integrity: sha512-FaNiGX1MrOuJ3hxuNzWgsT/mg5OHG/Izh59WW2mk1UwYHUwtfbhk5QNKYZgxf0pLOhx9ctGiGa2OykD71vOnSw==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-arm64@0.34.2': + resolution: {integrity: sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.33.3': + resolution: {integrity: sha512-2QeSl7QDK9ru//YBT4sQkoq7L0EAJZA3rtV+v9p8xTKl4U1bUqTIaCnoC7Ctx2kCjQgwFXDasOtPTCT8eCTXvw==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.2': + resolution: {integrity: sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.0.2': + resolution: {integrity: sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==} + engines: {macos: '>=11', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.1.0': + resolution: {integrity: sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.0.2': + resolution: {integrity: sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==} + engines: {macos: '>=10.13', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.1.0': + resolution: {integrity: sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.0.2': + resolution: {integrity: sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==} + engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm64@1.1.0': + resolution: {integrity: sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.0.2': + resolution: {integrity: sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==} + engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.1.0': + resolution: {integrity: sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-ppc64@1.1.0': + resolution: {integrity: sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==} + cpu: [ppc64] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.0.2': + resolution: {integrity: sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==} + engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.1.0': + resolution: {integrity: sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.0.2': + resolution: {integrity: sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ==} + engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.1.0': + resolution: {integrity: sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.0.2': + resolution: {integrity: sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ==} + engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.1.0': + resolution: {integrity: sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.0.2': + resolution: {integrity: sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw==} + engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.1.0': + resolution: {integrity: sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.33.3': + resolution: {integrity: sha512-Zf+sF1jHZJKA6Gor9hoYG2ljr4wo9cY4twaxgFDvlG0Xz9V7sinsPp8pFd1XtlhTzYo0IhDbl3rK7P6MzHpnYA==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm64@0.34.2': + resolution: {integrity: sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.33.3': + resolution: {integrity: sha512-Q7Ee3fFSC9P7vUSqVEF0zccJsZ8GiiCJYGWDdhEjdlOeS9/jdkyJ6sUSPj+bL8VuOYFSbofrW0t/86ceVhx32w==} + engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-arm@0.34.2': + resolution: {integrity: sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-s390x@0.33.3': + resolution: {integrity: sha512-vFk441DKRFepjhTEH20oBlFrHcLjPfI8B0pMIxGm3+yilKyYeHEVvrZhYFdqIseSclIqbQ3SnZMwEMWonY5XFA==} + engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-s390x@0.34.2': + resolution: {integrity: sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.33.3': + resolution: {integrity: sha512-Q4I++herIJxJi+qmbySd072oDPRkCg/SClLEIDh5IL9h1zjhqjv82H0Seupd+q2m0yOfD+/fJnjSoDFtKiHu2g==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-x64@0.34.2': + resolution: {integrity: sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.33.3': + resolution: {integrity: sha512-qnDccehRDXadhM9PM5hLvcPRYqyFCBN31kq+ErBSZtZlsAc1U4Z85xf/RXv1qolkdu+ibw64fUDaRdktxTNP9A==} + engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.34.2': + resolution: {integrity: sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.33.3': + resolution: {integrity: sha512-Jhchim8kHWIU/GZ+9poHMWRcefeaxFIs9EBqf9KtcC14Ojk6qua7ghKiPs0sbeLbLj/2IGBtDcxHyjCdYWkk2w==} + engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.34.2': + resolution: {integrity: sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] os: [linux] - requiresBuild: true + + '@img/sharp-wasm32@0.33.3': + resolution: {integrity: sha512-68zivsdJ0koE96stdUfM+gmyaK/NcoSZK5dV5CAjES0FUXS9lchYt8LAB5rTbM7nlWtxaU/2GON0HVN6/ZYJAQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [wasm32] + + '@img/sharp-wasm32@0.34.2': + resolution: {integrity: sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.2': + resolution: {integrity: sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.33.3': + resolution: {integrity: sha512-CyimAduT2whQD8ER4Ux7exKrtfoaUiVr7HG0zZvO0XTFn2idUWljjxv58GxNTkFb8/J9Ub9AqITGkJD6ZginxQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-ia32@0.34.2': + resolution: {integrity: sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.33.3': + resolution: {integrity: sha512-viT4fUIDKnli3IfOephGnolMzhz5VaTvDRkYqtZxOMIoMQ4MrAziO7pT1nVnOt2FAm7qW5aa+CCc13aEY6Le0g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [win32] + + '@img/sharp-win32-x64@0.34.2': + resolution: {integrity: sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.1': + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@kwsites/file-exists@1.1.1': + resolution: {integrity: sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==} + + '@kwsites/promise-deferred@1.1.1': + resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} + + '@lunariajs/core@0.1.1': + resolution: {integrity: sha512-sAqM9+DVsLe3xHM9wu2pEnKGYMs/bWS9qpR+CGHol3RihOELnOQTzHddXbdB1MtgesbI8dnQuG64Ocd8KkWsng==} + engines: {node: '>=18.17.0'} + hasBin: true + + '@manypkg/find-root@1.1.0': + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + + '@manypkg/get-packages@1.1.3': + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + + '@markdoc/markdoc@0.5.1': + resolution: {integrity: sha512-W2apYOglq0hOnvWbhE70yl6V9++FG+YPFKNHmgiSjv0HTmdJaMLt+NA1LMqoH5LasSiTI7R0yVc5ofjaFh39Pg==} + engines: {node: '>=14.7.0'} + peerDependencies: + '@types/react': '*' + react: '*' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + + '@mdx-js/mdx@3.1.0': + resolution: {integrity: sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@oslojs/encoding@1.1.0': + resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + + '@pagefind/darwin-arm64@1.3.0': + resolution: {integrity: sha512-365BEGl6ChOsauRjyVpBjXybflXAOvoMROw3TucAROHIcdBvXk9/2AmEvGFU0r75+vdQI4LJdJdpH4Y6Yqaj4A==} + cpu: [arm64] + os: [darwin] + + '@pagefind/darwin-x64@1.3.0': + resolution: {integrity: sha512-zlGHA23uuXmS8z3XxEGmbHpWDxXfPZ47QS06tGUq0HDcZjXjXHeLG+cboOy828QIV5FXsm9MjfkP5e4ZNbOkow==} + cpu: [x64] + os: [darwin] + + '@pagefind/default-ui@1.3.0': + resolution: {integrity: sha512-CGKT9ccd3+oRK6STXGgfH+m0DbOKayX6QGlq38TfE1ZfUcPc5+ulTuzDbZUnMo+bubsEOIypm4Pl2iEyzZ1cNg==} + + '@pagefind/linux-arm64@1.3.0': + resolution: {integrity: sha512-8lsxNAiBRUk72JvetSBXs4WRpYrQrVJXjlRRnOL6UCdBN9Nlsz0t7hWstRk36+JqHpGWOKYiuHLzGYqYAqoOnQ==} + cpu: [arm64] + os: [linux] + + '@pagefind/linux-x64@1.3.0': + resolution: {integrity: sha512-hAvqdPJv7A20Ucb6FQGE6jhjqy+vZ6pf+s2tFMNtMBG+fzcdc91uTw7aP/1Vo5plD0dAOHwdxfkyw0ugal4kcQ==} + cpu: [x64] + os: [linux] + + '@pagefind/windows-x64@1.3.0': + resolution: {integrity: sha512-BR1bIRWOMqkf8IoU576YDhij1Wd/Zf2kX/kCI0b2qzCKC8wcc2GQJaaRMCpzvCCrmliO4vtJ6RITp/AnoYUUmQ==} + cpu: [x64] + os: [win32] + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@playwright/test@1.45.0': + resolution: {integrity: sha512-TVYsfMlGAaxeUllNkywbwek67Ncf8FRGn8ZlRdO291OL3NjG9oMbfVhyP82HQF0CZLMrYsvesqoUekxdWuF9Qw==} + engines: {node: '>=18'} + hasBin: true + + '@rollup/pluginutils@5.1.4': + resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.36.0': + resolution: {integrity: sha512-jgrXjjcEwN6XpZXL0HUeOVGfjXhPyxAbbhD0BlXUB+abTOpbPiN5Wb3kOT7yb+uEtATNYF5x5gIfwutmuBA26w==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.36.0': + resolution: {integrity: sha512-NyfuLvdPdNUfUNeYKUwPwKsE5SXa2J6bCt2LdB/N+AxShnkpiczi3tcLJrm5mA+eqpy0HmaIY9F6XCa32N5yzg==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.36.0': + resolution: {integrity: sha512-JQ1Jk5G4bGrD4pWJQzWsD8I1n1mgPXq33+/vP4sk8j/z/C2siRuxZtaUA7yMTf71TCZTZl/4e1bfzwUmFb3+rw==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.36.0': + resolution: {integrity: sha512-6c6wMZa1lrtiRsbDziCmjE53YbTkxMYhhnWnSW8R/yqsM7a6mSJ3uAVT0t8Y/DGt7gxUWYuFM4bwWk9XCJrFKA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.36.0': + resolution: {integrity: sha512-KXVsijKeJXOl8QzXTsA+sHVDsFOmMCdBRgFmBb+mfEb/7geR7+C8ypAml4fquUt14ZyVXaw2o1FWhqAfOvA4sg==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.36.0': + resolution: {integrity: sha512-dVeWq1ebbvByI+ndz4IJcD4a09RJgRYmLccwlQ8bPd4olz3Y213uf1iwvc7ZaxNn2ab7bjc08PrtBgMu6nb4pQ==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.36.0': + resolution: {integrity: sha512-bvXVU42mOVcF4le6XSjscdXjqx8okv4n5vmwgzcmtvFdifQ5U4dXFYaCB87namDRKlUL9ybVtLQ9ztnawaSzvg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.36.0': + resolution: {integrity: sha512-JFIQrDJYrxOnyDQGYkqnNBtjDwTgbasdbUiQvcU8JmGDfValfH1lNpng+4FWlhaVIR4KPkeddYjsVVbmJYvDcg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.36.0': + resolution: {integrity: sha512-KqjYVh3oM1bj//5X7k79PSCZ6CvaVzb7Qs7VMWS+SlWB5M8p3FqufLP9VNp4CazJ0CsPDLwVD9r3vX7Ci4J56A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.36.0': + resolution: {integrity: sha512-QiGnhScND+mAAtfHqeT+cB1S9yFnNQ/EwCg5yE3MzoaZZnIV0RV9O5alJAoJKX/sBONVKeZdMfO8QSaWEygMhw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.36.0': + resolution: {integrity: sha512-1ZPyEDWF8phd4FQtTzMh8FQwqzvIjLsl6/84gzUxnMNFBtExBtpL51H67mV9xipuxl1AEAerRBgBwFNpkw8+Lg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.36.0': + resolution: {integrity: sha512-VMPMEIUpPFKpPI9GZMhJrtu8rxnp6mJR3ZzQPykq4xc2GmdHj3Q4cA+7avMyegXy4n1v+Qynr9fR88BmyO74tg==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.36.0': + resolution: {integrity: sha512-ttE6ayb/kHwNRJGYLpuAvB7SMtOeQnVXEIpMtAvx3kepFQeowVED0n1K9nAdraHUPJ5hydEMxBpIR7o4nrm8uA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.36.0': + resolution: {integrity: sha512-4a5gf2jpS0AIe7uBjxDeUMNcFmaRTbNv7NxI5xOCs4lhzsVyGR/0qBXduPnoWf6dGC365saTiwag8hP1imTgag==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.36.0': + resolution: {integrity: sha512-5KtoW8UWmwFKQ96aQL3LlRXX16IMwyzMq/jSSVIIyAANiE1doaQsx/KRyhAvpHlPjPiSU/AYX/8m+lQ9VToxFQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.36.0': + resolution: {integrity: sha512-sycrYZPrv2ag4OCvaN5js+f01eoZ2U+RmT5as8vhxiFz+kxwlHrsxOwKPSA8WyS+Wc6Epid9QeI/IkQ9NkgYyQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.36.0': + resolution: {integrity: sha512-qbqt4N7tokFwwSVlWDsjfoHgviS3n/vZ8LK0h1uLG9TYIRuUTJC88E1xb3LM2iqZ/WTqNQjYrtmtGmrmmawB6A==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.36.0': + resolution: {integrity: sha512-t+RY0JuRamIocMuQcfwYSOkmdX9dtkr1PbhKW42AMvaDQa+jOdpUYysroTF/nuPpAaQMWp7ye+ndlmmthieJrQ==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.36.0': + resolution: {integrity: sha512-aRXd7tRZkWLqGbChgcMMDEHjOKudo1kChb1Jt1IfR8cY/KIpgNviLeJy5FUb9IpSuQj8dU2fAYNMPW/hLKOSTw==} + cpu: [x64] + os: [win32] + + '@shikijs/core@3.2.2': + resolution: {integrity: sha512-yvlSKVMLjddAGBa2Yu+vUZxuu3sClOWW1AG+UtJkvejYuGM5BVL35s6Ijiwb75O9QdEx6IkMxinHZSi8ZyrBaA==} + + '@shikijs/engine-javascript@3.2.2': + resolution: {integrity: sha512-tlDKfhWpF4jKLUyVAnmL+ggIC+0VyteNsUpBzh1iwWLZu4i+PelIRr0TNur6pRRo5UZIv3ss/PLMuwahg9S2hg==} + + '@shikijs/engine-oniguruma@3.2.2': + resolution: {integrity: sha512-vyXRnWVCSvokwbaUD/8uPn6Gqsf5Hv7XwcW4AgiU4Z2qwy19sdr6VGzMdheKKN58tJOOe5MIKiNb901bgcUXYQ==} + + '@shikijs/langs@3.2.2': + resolution: {integrity: sha512-NY0Urg2dV9ETt3JIOWoMPuoDNwte3geLZ4M1nrPHbkDS8dWMpKcEwlqiEIGqtwZNmt5gKyWpR26ln2Bg2ecPgw==} + + '@shikijs/themes@3.2.2': + resolution: {integrity: sha512-Zuq4lgAxVKkb0FFdhHSdDkALuRpsj1so1JdihjKNQfgM78EHxV2JhO10qPsMrm01FkE3mDRTdF68wfmsqjt6HA==} + + '@shikijs/types@3.2.2': + resolution: {integrity: sha512-a5TiHk7EH5Lso8sHcLHbVNNhWKP0Wi3yVnXnu73g86n3WoDgEra7n3KszyeCGuyoagspQ2fzvy4cpSc8pKhb0A==} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + + '@sindresorhus/is@4.6.0': + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} + + '@size-limit/file@11.1.6': + resolution: {integrity: sha512-ojzzJMrTfcSECRnaTjGy0wNIolTCRdyqZTSWG9sG5XEoXG6PNgHXDDS6gf6YNxnqb+rWfCfVe93u6aKi3wEocQ==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + size-limit: 11.1.6 + + '@szmarczak/http-timer@4.0.6': + resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} + engines: {node: '>=10'} + + '@tailwindcss/node@4.0.15': + resolution: {integrity: sha512-IODaJjNmiasfZX3IoS+4Em3iu0fD2HS0/tgrnkYfW4hyUor01Smnr5eY3jc4rRgaTDrJlDmBTHbFO0ETTDaxWA==} + + '@tailwindcss/oxide-android-arm64@4.0.15': + resolution: {integrity: sha512-EBuyfSKkom7N+CB3A+7c0m4+qzKuiN0WCvzPvj5ZoRu4NlQadg/mthc1tl5k9b5ffRGsbDvP4k21azU4VwVk3Q==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.0.15': + resolution: {integrity: sha512-ObVAnEpLepMhV9VoO0JSit66jiN5C4YCqW3TflsE9boo2Z7FIjV80RFbgeL2opBhtxbaNEDa6D0/hq/EP03kgQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.0.15': + resolution: {integrity: sha512-IElwoFhUinOr9MyKmGTPNi1Rwdh68JReFgYWibPWTGuevkHkLWKEflZc2jtI5lWZ5U9JjUnUfnY43I4fEXrc4g==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.0.15': + resolution: {integrity: sha512-6BLLqyx7SIYRBOnTZ8wgfXANLJV5TQd3PevRJZp0vn42eO58A2LykRKdvL1qyPfdpmEVtF+uVOEZ4QTMqDRAWA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.15': + resolution: {integrity: sha512-Zy63EVqO9241Pfg6G0IlRIWyY5vNcWrL5dd2WAKVJZRQVeolXEf1KfjkyeAAlErDj72cnyXObEZjMoPEKHpdNw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.0.15': + resolution: {integrity: sha512-2NemGQeaTbtIp1Z2wyerbVEJZTkAWhMDOhhR5z/zJ75yMNf8yLnE+sAlyf6yGDNr+1RqvWrRhhCFt7i0CIxe4Q==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.0.15': + resolution: {integrity: sha512-342GVnhH/6PkVgKtEzvNVuQ4D+Q7B7qplvuH20Cfz9qEtydG6IQczTZ5IT4JPlh931MG1NUCVxg+CIorr1WJyw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.0.15': + resolution: {integrity: sha512-g76GxlKH124RuGqacCEFc2nbzRl7bBrlC8qDQMiUABkiifDRHOIUjgKbLNG4RuR9hQAD/MKsqZ7A8L08zsoBrw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.0.15': + resolution: {integrity: sha512-Gg/Y1XrKEvKpq6WeNt2h8rMIKOBj/W3mNa5NMvkQgMC7iO0+UNLrYmt6zgZufht66HozNpn+tJMbbkZ5a3LczA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-win32-arm64-msvc@4.0.15': + resolution: {integrity: sha512-7QtSSJwYZ7ZK1phVgcNZpuf7c7gaCj8Wb0xjliligT5qCGCp79OV2n3SJummVZdw4fbTNKUOYMO7m1GinppZyA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.0.15': + resolution: {integrity: sha512-JQ5H+5MLhOjpgNp6KomouE0ZuKmk3hO5h7/ClMNAQ8gZI2zkli3IH8ZqLbd2DVfXDbdxN2xvooIEeIlkIoSCqw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.0.15': + resolution: {integrity: sha512-e0uHrKfPu7JJGMfjwVNyt5M0u+OP8kUmhACwIRlM+JNBuReDVQ63yAD1NWe5DwJtdaHjugNBil76j+ks3zlk6g==} + engines: {node: '>= 10'} + + '@tailwindcss/vite@4.0.15': + resolution: {integrity: sha512-JRexava80NijI8cTcLXNM3nQL5A0ptTHI8oJLLe8z1MpNB6p5J4WCdJJP8RoyHu8/eB1JzEdbpH86eGfbuaezQ==} + peerDependencies: + vite: ^5.2.0 || ^6 + + '@types/acorn@4.0.6': + resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} + + '@types/cacheable-request@6.0.3': + resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} + + '@types/culori@2.1.1': + resolution: {integrity: sha512-NzLYD0vNHLxTdPp8+RlvGbR2NfOZkwxcYGFwxNtm+WH2NuUNV8785zv1h0sulFQ5aFQ9n/jNDUuJeo3Bh7+oFA==} + + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + + '@types/estree-jsx@1.0.5': + resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/http-cache-semantics@4.0.4': + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + + '@types/js-yaml@4.0.9': + resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/junit-report-builder@3.0.2': + resolution: {integrity: sha512-R5M+SYhMbwBeQcNXYWNCZkl09vkVfAtcPIaCGdzIkkbeaTrVbGQ7HVgi4s+EmM/M1K4ZuWQH0jGcvMvNePfxYA==} + + '@types/keyv@3.1.4': + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + + '@types/linkify-it@3.0.5': + resolution: {integrity: sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==} + + '@types/markdown-it@12.2.3': + resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + + '@types/ms@0.7.34': + resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + + '@types/nlcst@2.0.3': + resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} + + '@types/node@12.20.55': + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + + '@types/node@17.0.45': + resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} + + '@types/node@18.16.19': + resolution: {integrity: sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==} + + '@types/opentype.js@1.3.8': + resolution: {integrity: sha512-H6qeTp03jrknklSn4bpT1/9+1xCAEIU2CnjcWPkicJy8A1SKuthanbvoHYMiv79/2W3Xn1XE4gfSJFzt2U3JSw==} + + '@types/picomatch@3.0.1': + resolution: {integrity: sha512-1MRgzpzY0hOp9pW/kLRxeQhUWwil6gnrUYd3oEpeYBqp/FexhaCPv3F8LsYr47gtUU45fO2cm1dbwkSrHEo8Uw==} + + '@types/responselike@1.0.3': + resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + + '@types/sax@1.2.4': + resolution: {integrity: sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==} + + '@types/unist@2.0.10': + resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} + + '@types/unist@3.0.0': + resolution: {integrity: sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==} + + '@typescript-eslint/eslint-plugin@8.39.1': + resolution: {integrity: sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.39.1 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.39.1': + resolution: {integrity: sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.39.1': + resolution: {integrity: sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.39.1': + resolution: {integrity: sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.39.1': + resolution: {integrity: sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.39.1': + resolution: {integrity: sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@8.39.1': + resolution: {integrity: sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.39.1': + resolution: {integrity: sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@8.39.1': + resolution: {integrity: sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.39.1': + resolution: {integrity: sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + '@vitest/coverage-v8@3.0.5': + resolution: {integrity: sha512-zOOWIsj5fHh3jjGwQg+P+J1FW3s4jBu1Zqga0qW60yutsBtqEqNEJKWYh7cYn1yGD+1bdPsPdC/eL4eVK56xMg==} + peerDependencies: + '@vitest/browser': 3.0.5 + vitest: 3.0.5 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@3.1.1': + resolution: {integrity: sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==} + + '@vitest/mocker@3.1.1': + resolution: {integrity: sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.1.1': + resolution: {integrity: sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==} + + '@vitest/runner@3.1.1': + resolution: {integrity: sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==} + + '@vitest/snapshot@3.1.1': + resolution: {integrity: sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==} + + '@vitest/spy@3.1.1': + resolution: {integrity: sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==} + + '@vitest/utils@3.1.1': + resolution: {integrity: sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==} + + '@volar/kit@2.4.10': + resolution: {integrity: sha512-ul+rLeO9RlFDgkY/FhPWMnpFqAsjvjkKz8VZeOY5YCJMwTblmmSBlNJtFNxSBx9t/k1q80nEthLyxiJ50ZbIAg==} + peerDependencies: + typescript: '*' + + '@volar/language-core@2.4.10': + resolution: {integrity: sha512-hG3Z13+nJmGaT+fnQzAkS0hjJRa2FCeqZt6Bd+oGNhUkQ+mTFsDETg5rqUTxyzIh5pSOGY7FHCWUS8G82AzLCA==} + + '@volar/language-server@2.4.10': + resolution: {integrity: sha512-odQsgrJh8hOXfxkSj/BSnpjThb2/KDhbxZnG/XAEx6E3QGDQv4hAOz9GWuKoNs0tkjgwphQGIwDMT1JYaTgRJw==} + + '@volar/language-service@2.4.10': + resolution: {integrity: sha512-VxUiWS11rnRzakkqw5x1LPhsz+RBfD0CrrFarLGW2/voliYXEdCuSOM3r8JyNRvMvP4uwhD38ccAdTcULQEAIQ==} + + '@volar/source-map@2.4.10': + resolution: {integrity: sha512-OCV+b5ihV0RF3A7vEvNyHPi4G4kFa6ukPmyVocmqm5QzOd8r5yAtiNvaPEjl8dNvgC/lj4JPryeeHLdXd62rWA==} + + '@volar/typescript@2.4.10': + resolution: {integrity: sha512-F8ZtBMhSXyYKuBfGpYwqA5rsONnOwAVvjyE7KPYJ7wgZqo2roASqNWUnianOomJX5u1cxeRooHV59N0PhvEOgw==} + + '@vscode/emmet-helper@2.9.3': + resolution: {integrity: sha512-rB39LHWWPQYYlYfpv9qCoZOVioPCftKXXqrsyqN1mTWZM6dTnONT63Db+03vgrBbHzJN45IrgS/AGxw9iiqfEw==} + + '@vscode/l10n@0.0.18': + resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + algoliasearch@4.20.0: + resolution: {integrity: sha512-y+UHEjnOItoNy0bYO+WWmLWBlPwDjKHW6mNHrPi0NkuhpQOOEbrkwQH/wgKFDLh7qlKjzoKeiRtlpewDPDG23g==} + + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-iterate@2.0.1: + resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + astring@1.9.0: + resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} + hasBin: true + + astro-expressive-code@0.41.1: + resolution: {integrity: sha512-za6HlekMOczwlkuYuQQTd6LkKFwsnfAjwjIprCzOqsjp9vkYrAcriXM5cIG7V1Zxx88sVXF6iGnyNl4J0DL2Mg==} + peerDependencies: + astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0 + + astro@5.6.2: + resolution: {integrity: sha512-Ds4x3Au2s+YfBKLXY2HCHird+73ff4wTds+cuAGqaHmY4GR+Gc+sCAP54Mq6blkpuFqXwqjPUAcmxvAwovJPGQ==} + engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} + hasBin: true + + axe-core@4.10.1: + resolution: {integrity: sha512-qPC9o+kD8Tir0lzNGLeghbOrWMr3ZJpaRlCIb6Uobt/7N4FiEDvqUMnxzCHRHmg8vOg14kr5gVNyScRmbMaJ9g==} + engines: {node: '>=4'} + + axe-html-reporter@2.2.11: + resolution: {integrity: sha512-WlF+xlNVgNVWiM6IdVrsh+N0Cw7qupe5HT9N6Uyi+aN7f6SSi92RDomiP1noW8OWIV85V6x404m5oKMeqRV3tQ==} + engines: {node: '>=8.9.0'} + peerDependencies: + axe-core: '>=3' + + axe-playwright@2.0.3: + resolution: {integrity: sha512-s7iI2okyHHsD3XZK4RMJtTy2UASkNWLQtnzLuaHiK3AWkERf+cqZJqkxb7O4b56fnbib9YnZVRByTl92ME3o6g==} + peerDependencies: + playwright: '>1.0.0' + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base-64@1.0.0: + resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} + + bcp-47-match@2.0.3: + resolution: {integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==} + + bcp-47@2.1.0: + resolution: {integrity: sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==} + + better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + boxen@8.0.1: + resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} + engines: {node: '>=18'} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + bytes-iec@3.1.1: + resolution: {integrity: sha512-fey6+4jDK7TFtFg/klGSvNKJctyU7n2aQdnM+CO0ruLPbqqMOM8Tio0Pc+deqUeVKX1tL5DQep1zQ7+37aTAsA==} + engines: {node: '>= 0.8'} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + cacheable-lookup@5.0.4: + resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} + engines: {node: '>=10.6.0'} + + cacheable-request@7.0.4: + resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} + engines: {node: '>=8'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} + engines: {node: '>=12'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + character-reference-invalid@2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + ci-info@4.2.0: + resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} + engines: {node: '>=8'} + + cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone-response@1.0.3: + resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + collapse-white-space@2.1.0: + resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + common-ancestor-path@1.0.1: + resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + cookie-es@1.2.2: + resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==} + + cookie@1.0.2: + resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + engines: {node: '>=18'} + + cross-spawn@5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + + cross-spawn@7.0.5: + resolution: {integrity: sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==} + engines: {node: '>= 8'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crossws@0.3.4: + resolution: {integrity: sha512-uj0O1ETYX1Bh6uSgktfPvwDiPYGQ3aI4qVsaC/LWpkIzGj1nUYm5FK3K+t11oOlpN01lGbprFCH4wBlKdJjVgw==} + + css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + + css-selector-parser@3.0.2: + resolution: {integrity: sha512-eA5pvYwgtffuxQlDk0gJRApDUKgfwlsQBMAH6uawKuuilTLfxKIOtzyV63Y3IC0LWnDCeTJ/I1qYmlfYvvMzDg==} + + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + cssom@0.5.0: + resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} + + culori@4.0.1: + resolution: {integrity: sha512-LSnjA6HuIUOlkfKVbzi2OlToZE8OjFi667JWN9qNymXVXzGDmvuP60SSgC+e92sd7B7158f7Fy3Mb6rXS5EDPw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + dataloader@1.4.0: + resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-named-character-reference@1.0.2: + resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + destr@2.0.3: + resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + detect-libc@2.0.4: + resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} + engines: {node: '>=8'} + + deterministic-object-hash@2.0.2: + resolution: {integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==} + engines: {node: '>=18'} + + devalue@5.1.1: + resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + direction@2.0.1: + resolution: {integrity: sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==} + hasBin: true + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dotenv@8.6.0: + resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} + engines: {node: '>=10'} + + dset@3.1.4: + resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} + engines: {node: '>=4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + emmet@2.4.7: + resolution: {integrity: sha512-O5O5QNqtdlnQM2bmKHtJgyChcrFMgQuulI+WdiOw2NArzprUqqxUW6bgYtKvzKgrsYpuLWalOkdhNP+1jluhCA==} + + emoji-regex-xs@1.0.0: + resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} + + emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + engines: {node: '>=10.13.0'} + + enquirer@2.3.6: + resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} + engines: {node: '>=8.6'} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + entities@6.0.0: + resolution: {integrity: sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==} + engines: {node: '>=0.12'} + + es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} + + esast-util-from-estree@2.0.0: + resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} + + esast-util-from-js@2.0.1: + resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.25.1: + resolution: {integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + eslint-config-prettier@10.1.8: + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.33.0: + resolution: {integrity: sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-util-attach-comments@3.0.0: + resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==} + + estree-util-build-jsx@3.0.1: + resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==} + + estree-util-is-identifier-name@3.0.0: + resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + + estree-util-scope@1.0.0: + resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==} + + estree-util-to-js@2.0.0: + resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==} + + estree-util-visit@2.0.0: + resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + expect-type@1.2.1: + resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} + engines: {node: '>=12.0.0'} + + expressive-code@0.41.1: + resolution: {integrity: sha512-O3+bDWGw+y7b0L3Y3xc7LbPgRTvFy2tqXzYY24TBbDwnHbIwb0OFdS4v+1PpX6NEsF7XsVv9sqY5xo22yWe7Hw==} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + extendable-error@0.1.7: + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} + + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-uri@3.0.3: + resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fdir@6.4.3: + resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + flattie@1.1.1: + resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==} + engines: {node: '>=8'} + + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + + get-port@7.1.0: + resolution: {integrity: sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==} + engines: {node: '>=16'} + + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + + get-tsconfig@4.7.5: + resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==} + + github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@16.3.0: + resolution: {integrity: sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==} + engines: {node: '>=18'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + got@11.8.6: + resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} + engines: {node: '>=10.19.0'} + + graceful-fs@4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + h3@1.15.1: + resolution: {integrity: sha512-+ORaOBttdUm1E2Uu/obAyCguiI7MbBvsLTndc3gyK3zU+SYLoZXlyCP9Xgy0gikkGufFLTZXCXD6+4BsufnmHA==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hast-util-embedded@3.0.0: + resolution: {integrity: sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==} + + hast-util-from-html@2.0.3: + resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} + + hast-util-from-parse5@8.0.1: + resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} + + hast-util-has-property@3.0.0: + resolution: {integrity: sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==} + + hast-util-is-body-ok-link@3.0.0: + resolution: {integrity: sha512-VFHY5bo2nY8HiV6nir2ynmEB1XkxzuUffhEGeVx7orbu/B1KaGyeGgMZldvMVx5xWrDlLLG/kQ6YkJAMkBEx0w==} + + hast-util-is-element@3.0.0: + resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} + + hast-util-parse-selector@4.0.0: + resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + + hast-util-phrasing@3.0.1: + resolution: {integrity: sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==} + + hast-util-raw@9.0.1: + resolution: {integrity: sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==} + + hast-util-select@6.0.2: + resolution: {integrity: sha512-hT/SD/d/Meu+iobvgkffo1QecV8WeKWxwsNMzcTJsKw1cKTQKSR/7ArJeURLNJF9HDjp9nVoORyNNJxrvBye8Q==} + + hast-util-to-estree@3.1.0: + resolution: {integrity: sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==} + + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-to-jsx-runtime@2.3.2: + resolution: {integrity: sha512-1ngXYb+V9UT5h+PxNRa1O1FYguZK/XL+gkeqvp7EdHlB9oHUG0eYRo/vY5inBdcqo3RkPMC58/H94HvkbfGdyg==} + + hast-util-to-parse5@8.0.0: + resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} + + hast-util-to-string@3.0.0: + resolution: {integrity: sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==} + + hast-util-to-text@4.0.2: + resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + hastscript@8.0.0: + resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} + + hastscript@9.0.0: + resolution: {integrity: sha512-jzaLBGavEDKHrc5EfFImKN7nZKKBdSLIdGvCwDZ9TfzbF2ffXiov8CKE445L2Z1Ek2t/m4SKQ2j6Ipv7NyUolw==} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + html-escaper@3.0.3: + resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + html-whitespace-sensitive-tag-names@3.0.0: + resolution: {integrity: sha512-KlClZ3/Qy5UgvpvVvDomGhnQhNWH5INE8GwvSIQ9CWt1K0zbbXrl7eN5bWaafOZgtmO3jMPwUqmrmEwinhPq1w==} + + htmlparser2@10.0.0: + resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} + + htmlparser2@9.1.0: + resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} + + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http2-wrapper@1.0.3: + resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} + engines: {node: '>=10.19.0'} + + human-id@1.0.2: + resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} + + i18next@23.11.5: + resolution: {integrity: sha512-41pvpVbW9rhZPk5xjCX2TPJi2861LEig/YRhUkY+1FQ2IQPS0bKUDYnEqY8XPPbB48h1uIwLnP9iiEfuSl20CA==} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + inline-style-parser@0.1.1: + resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} + + inline-style-parser@0.2.4: + resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} + + iron-webcrypto@1.2.1: + resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + + is-absolute-url@4.0.1: + resolution: {integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-alphabetical@2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + + is-alphanumerical@2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + + is-decimal@2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-gzip@2.0.0: + resolution: {integrity: sha512-jtO4Njg6q58zDo/Pu4027beSZ0VdsZlt8/5Moco6yAg+DIxb5BK/xUYqYG2+MD4+piKldXJNHxRkhEYI2fvrxA==} + engines: {node: '>=4'} + + is-hexadecimal@2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + hasBin: true + + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + jsonc-parser@2.3.1: + resolution: {integrity: sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==} + + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + junit-report-builder@5.1.1: + resolution: {integrity: sha512-ZNOIIGMzqCGcHQEA2Q4rIQQ3Df6gSIfne+X9Rly9Bc2y55KxAZu8iGv+n2pP0bLf0XAOctJZgeloC54hWzCahQ==} + engines: {node: '>=16'} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + klona@2.0.6: + resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} + engines: {node: '>= 8'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lightningcss-darwin-arm64@1.29.2: + resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-arm64@1.29.3: + resolution: {integrity: sha512-fb7raKO3pXtlNbQbiMeEu8RbBVHnpyqAoxTyTRMEWFQWmscGC2wZxoHzZ+YKAepUuKT9uIW5vL2QbFivTgprZg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.29.2: + resolution: {integrity: sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-darwin-x64@1.29.3: + resolution: {integrity: sha512-KF2XZ4ZdmDGGtEYmx5wpzn6u8vg7AdBHaEOvDKu8GOs7xDL/vcU2vMKtTeNe1d4dogkDdi3B9zC77jkatWBwEQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.29.2: + resolution: {integrity: sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-freebsd-x64@1.29.3: + resolution: {integrity: sha512-VUWeVf+V1UM54jv9M4wen9vMlIAyT69Krl9XjI8SsRxz4tdNV/7QEPlW6JASev/pYdiynUCW0pwaFquDRYdxMw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.29.2: + resolution: {integrity: sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm-gnueabihf@1.29.3: + resolution: {integrity: sha512-UhgZ/XVNfXQVEJrMIWeK1Laj8KbhjbIz7F4znUk7G4zeGw7TRoJxhb66uWrEsonn1+O45w//0i0Fu0wIovYdYg==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.29.2: + resolution: {integrity: sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-gnu@1.29.3: + resolution: {integrity: sha512-Pqau7jtgJNmQ/esugfmAT1aCFy/Gxc92FOxI+3n+LbMHBheBnk41xHDhc0HeYlx9G0xP5tK4t0Koy3QGGNqypw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.29.2: + resolution: {integrity: sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.29.3: + resolution: {integrity: sha512-dxakOk66pf7KLS7VRYFO7B8WOJLecE5OPL2YOk52eriFd/yeyxt2Km5H0BjLfElokIaR+qWi33gB8MQLrdAY3A==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.29.2: + resolution: {integrity: sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-gnu@1.29.3: + resolution: {integrity: sha512-ySZTNCpbfbK8rqpKJeJR2S0g/8UqqV3QnzcuWvpI60LWxnFN91nxpSSwCbzfOXkzKfar9j5eOuOplf+klKtINg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.29.2: + resolution: {integrity: sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.29.3: + resolution: {integrity: sha512-3pVZhIzW09nzi10usAXfIGTTSTYQ141dk88vGFNCgawIzayiIzZQxEcxVtIkdvlEq2YuFsL9Wcj/h61JHHzuFQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.29.2: + resolution: {integrity: sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-arm64-msvc@1.29.3: + resolution: {integrity: sha512-VRnkAvtIkeWuoBJeGOTrZxsNp4HogXtcaaLm8agmbYtLDOhQdpgxW6NjZZjDXbvGF+eOehGulXZ3C1TiwHY4QQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.29.2: + resolution: {integrity: sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss-win32-x64-msvc@1.29.3: + resolution: {integrity: sha512-IszwRPu2cPnDQsZpd7/EAr0x2W7jkaWqQ1SwCVIZ/tSbZVXPLt6k8s6FkcyBjViCzvB5CW0We0QbbP7zp2aBjQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.29.2: + resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==} + engines: {node: '>= 12.0.0'} + + lightningcss@1.29.3: + resolution: {integrity: sha512-GlOJwTIP6TMIlrTFsxTerwC0W6OpQpCGuX1ECRLBUVRh6fpJH3xTqjCjRgQHTb4ZXexH9rtHou1Lf03GKzmhhQ==} + engines: {node: '>= 12.0.0'} + + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + + linkedom@0.18.4: + resolution: {integrity: sha512-JhLErxMIEOKByMi3fURXgI1fYOzR87L1Cn0+MI9GlMckFrqFZpV1SUGox1jcKtsKN3y6JgclcQf0FzZT//BuGw==} + + lite-youtube-embed@0.3.3: + resolution: {integrity: sha512-gFfVVnj6NRjxVfJKo3qoLtpi0v5mn3AcR4eKD45wrxQuxzveFJUb+7Cr6uV6n+DjO8X3p0UzPPquhGt0H/y+NA==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + loupe@3.1.2: + resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} + + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + + lowercase-keys@2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + + make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + markdown-extensions@2.0.0: + resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==} + engines: {node: '>=16'} + + markdown-table@3.0.3: + resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + + mdast-util-definitions@6.0.0: + resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==} + + mdast-util-directive@3.0.0: + resolution: {integrity: sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==} + + mdast-util-find-and-replace@3.0.1: + resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} + + mdast-util-from-markdown@2.0.0: + resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} + + mdast-util-gfm-autolink-literal@2.0.0: + resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==} + + mdast-util-gfm-footnote@2.0.0: + resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} + + mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + + mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + + mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + + mdast-util-gfm@3.0.0: + resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} + + mdast-util-mdx-expression@2.0.1: + resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} + + mdast-util-mdx-jsx@3.1.3: + resolution: {integrity: sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==} + + mdast-util-mdx@3.0.0: + resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==} + + mdast-util-mdxjs-esm@2.0.1: + resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} + + mdast-util-phrasing@4.0.0: + resolution: {integrity: sha512-xadSsJayQIucJ9n053dfQwVu1kuXg7jCTdYsMK8rqzKZh52nLfSH/k0sAxE0u+pj/zKZX+o5wB+ML5mRayOxFA==} + + mdast-util-to-hast@13.0.2: + resolution: {integrity: sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==} + + mdast-util-to-markdown@2.1.0: + resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromark-core-commonmark@2.0.0: + resolution: {integrity: sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==} + + micromark-extension-directive@3.0.0: + resolution: {integrity: sha512-61OI07qpQrERc+0wEysLHMvoiO3s2R56x5u7glHq2Yqq6EHbH4dW25G9GfDdGCDYqA21KE6DWgNSzxSwHc2hSg==} + + micromark-extension-gfm-autolink-literal@2.0.0: + resolution: {integrity: sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==} + + micromark-extension-gfm-footnote@2.0.0: + resolution: {integrity: sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==} + + micromark-extension-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==} + + micromark-extension-gfm-table@2.0.0: + resolution: {integrity: sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==} + + micromark-extension-gfm-tagfilter@2.0.0: + resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + + micromark-extension-gfm-task-list-item@2.0.1: + resolution: {integrity: sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==} + + micromark-extension-gfm@3.0.0: + resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + + micromark-extension-mdx-expression@3.0.0: + resolution: {integrity: sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==} + + micromark-extension-mdx-jsx@3.0.1: + resolution: {integrity: sha512-vNuFb9czP8QCtAQcEJn0UJQJZA8Dk6DXKBqx+bg/w0WGuSxDxNr7hErW89tHUY31dUW4NqEOWwmEUNhjTFmHkg==} + + micromark-extension-mdx-md@2.0.0: + resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} + + micromark-extension-mdxjs-esm@3.0.0: + resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==} + + micromark-extension-mdxjs@3.0.0: + resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==} + + micromark-factory-destination@2.0.0: + resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} + + micromark-factory-label@2.0.0: + resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} + + micromark-factory-mdx-expression@2.0.2: + resolution: {integrity: sha512-5E5I2pFzJyg2CtemqAbcyCktpHXuJbABnsb32wX2U8IQKhhVFBqkcZR5LRm1WVoFqa4kTueZK4abep7wdo9nrw==} + + micromark-factory-space@2.0.0: + resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} + + micromark-factory-title@2.0.0: + resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==} + + micromark-factory-whitespace@2.0.0: + resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} + + micromark-util-character@2.0.1: + resolution: {integrity: sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==} + + micromark-util-chunked@2.0.0: + resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} + + micromark-util-classify-character@2.0.0: + resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==} + + micromark-util-combine-extensions@2.0.0: + resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==} + + micromark-util-decode-numeric-character-reference@2.0.1: + resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==} + + micromark-util-decode-string@2.0.0: + resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==} + + micromark-util-encode@2.0.0: + resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + + micromark-util-events-to-acorn@2.0.2: + resolution: {integrity: sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==} + + micromark-util-html-tag-name@2.0.0: + resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} + + micromark-util-normalize-identifier@2.0.0: + resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==} + + micromark-util-resolve-all@2.0.0: + resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==} + + micromark-util-sanitize-uri@2.0.0: + resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + + micromark-util-subtokenize@2.0.0: + resolution: {integrity: sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==} + + micromark-util-symbol@2.0.0: + resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + + micromark-util-types@2.0.0: + resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + + micromark@4.0.0: + resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mimic-response@1.0.1: + resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} + engines: {node: '>=4'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + mustache@4.2.0: + resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} + hasBin: true + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanospinner@1.1.0: + resolution: {integrity: sha512-yFvNYMig4AthKYfHFl1sLj7B2nkHL4lzdig4osvl9/LdGbXwrdFRoqBS98gsEsOakr0yH+r5NZ/1Y9gdVB8trA==} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + neotraverse@0.6.18: + resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} + engines: {node: '>= 10'} + + nlcst-to-string@4.0.0: + resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==} + + node-fetch-native@1.6.6: + resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==} + + node-fetch@2.6.10: + resolution: {integrity: sha512-5YytjUVbwzjE/BX4N62vnPPkGNxlJPwdA9/ArUc4pcM6cYS4Hinuv4VazzwjMGgnWuiQqcemOanib/5PpcsGug==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-mock-http@1.0.0: + resolution: {integrity: sha512-0uGYQ1WQL1M5kKvGRXWQ3uZCHtLTO8hln3oBjIusM75WoesZ909uQJs/Hb946i2SS+Gsrhkaa6iAO17jRIv6DQ==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + + not@0.1.0: + resolution: {integrity: sha512-5PDmaAsVfnWUgTUbJ3ERwn7u79Z0dYxN9ErxCpVJJqe2RK0PJ3z+iFUxuqjwtlDDegXvtWoxD/3Fzxox7tFGWA==} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + ofetch@1.4.1: + resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + oniguruma-parser@0.11.1: + resolution: {integrity: sha512-fX6SirDOsTUNqSUOnL3fDtD3R7PCXNWGA3WWPvv9egEfTWkNXzRLO/9CC1WkDusP6HyWRZig06kHeYPcw3mlqQ==} + + oniguruma-to-es@4.2.0: + resolution: {integrity: sha512-MDPs6KSOLS0tKQ7joqg44dRIRZUyotfTy0r+7oEEs6VwWWP0+E2PPDYWMFN0aqOjRyWHBYq7RfKw9GQk2S2z5g==} + + opentype.js@1.3.4: + resolution: {integrity: sha512-d2JE9RP/6uagpQAVtJoF0pJJA/fgai89Cc50Yp0EJHk+eLp6QQ7gBoblsnubRULNY132I0J1QKMJ+JTbMqz4sw==} + engines: {node: '>= 8.0.0'} + hasBin: true + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + outdent@0.5.0: + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + + p-cancelable@2.1.1: + resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} + engines: {node: '>=8'} + + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-limit@6.2.0: + resolution: {integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==} + engines: {node: '>=18'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-queue@8.1.0: + resolution: {integrity: sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==} + engines: {node: '>=18'} + + p-timeout@6.1.2: + resolution: {integrity: sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==} + engines: {node: '>=14.16'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + package-manager-detector@0.2.2: + resolution: {integrity: sha512-VgXbyrSNsml4eHWIvxxG/nTL4wgybMTXCV2Un/+yEc3aDKKU6nQBZjbeP3Pl3qm9Qg92X/1ng4ffvCeD/zwHgg==} + + package-manager-detector@1.1.0: + resolution: {integrity: sha512-Y8f9qUlBzW8qauJjd/eu6jlpJZsuPJm2ZAV0cDVd420o4EdpH5RPdoCv+60/TdJflGatr4sDfpAL6ArWZbM5tA==} + + pagefind@1.3.0: + resolution: {integrity: sha512-8KPLGT5g9s+olKMRTU9LFekLizkVIu9tes90O1/aigJ0T5LmyPqTzGJrETnSw3meSYg58YH7JTzhTTW/3z6VAw==} + hasBin: true + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-entities@4.0.1: + resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} + + parse-latin@7.0.0: + resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==} + + parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-to-regexp@6.2.2: + resolution: {integrity: sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + playwright-core@1.45.0: + resolution: {integrity: sha512-lZmHlFQ0VYSpAs43dRq1/nJ9G/6SiTI7VPqidld9TDefL9tX87bTKExWZZUF5PeRyqtXqd8fQi2qmfIedkwsNQ==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.45.0: + resolution: {integrity: sha512-4z3ac3plDfYzGB6r0Q3LF8POPR20Z8D0aXcxbJvmfMgSSq1hkcgvFRXJk9rUq5H/MJ0Ktal869hhOdI/zUTeLA==} + engines: {node: '>=18'} + hasBin: true + + postcss-nested@6.0.1: + resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.0.13: + resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} + engines: {node: '>=4'} + + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} + + preact@10.18.2: + resolution: {integrity: sha512-X/K43vocUHDg0XhWVmTTMbec4LT/iBMh+csCEqJk+pJqegaXsvjdqN80ZZ3L+93azWCnWCZ+WGwYb8SplxeNjA==} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-plugin-astro@0.14.1: + resolution: {integrity: sha512-RiBETaaP9veVstE4vUwSIcdATj6dKmXljouXc/DDNwBSPTp8FRkLGDSGFClKsAFeeg+13SB0Z1JZvbD76bigJw==} + engines: {node: ^14.15.0 || >=16.0.0} + + prettier@2.8.7: + resolution: {integrity: sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==} + engines: {node: '>=10.13.0'} + hasBin: true + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} + engines: {node: '>=14'} + hasBin: true + + prismjs@1.29.0: + resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} + engines: {node: '>=6'} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + property-information@6.2.0: + resolution: {integrity: sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==} + + property-information@7.0.0: + resolution: {integrity: sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg==} + + pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + + pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + + radix3@1.1.2: + resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + read-yaml-file@1.1.0: + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} + engines: {node: '>=6'} + + readdirp@4.0.2: + resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} + engines: {node: '>= 14.16.0'} + + recma-build-jsx@1.0.0: + resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} + + recma-jsx@1.0.0: + resolution: {integrity: sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==} + + recma-parse@1.0.0: + resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==} + + recma-stringify@1.0.0: + resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@6.0.1: + resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==} + + rehype-expressive-code@0.41.1: + resolution: {integrity: sha512-QApC3js5/AwrF6VqWfGsNY9Y1qLC0LQDWcqOHEAhbl3CB4e5GMor2SpWaGOWBW+mmrkVCEymayLPCPIbx0tcQQ==} + + rehype-format@5.0.0: + resolution: {integrity: sha512-kM4II8krCHmUhxrlvzFSptvaWh280Fr7UGNJU5DCMuvmAwGCNmGfi9CvFAQK6JDjsNoRMWQStglK3zKJH685Wg==} + + rehype-minify-whitespace@6.0.0: + resolution: {integrity: sha512-i9It4YHR0Sf3GsnlR5jFUKXRr9oayvEk9GKQUkwZv6hs70OH9q3OCZrq9PpLvIGKt3W+JxBOxCidNVpH/6rWdA==} + + rehype-parse@9.0.0: + resolution: {integrity: sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==} + + rehype-raw@7.0.0: + resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} + + rehype-recma@1.0.0: + resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==} + + rehype-stringify@10.0.1: + resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==} + + rehype@13.0.2: + resolution: {integrity: sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==} + + remark-directive@3.0.0: + resolution: {integrity: sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA==} + + remark-gfm@4.0.1: + resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} + + remark-mdx@3.1.0: + resolution: {integrity: sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==} + + remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + + remark-rehype@11.1.1: + resolution: {integrity: sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==} + + remark-smartypants@3.0.2: + resolution: {integrity: sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==} + engines: {node: '>=16.0.0'} + + remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + + request-light@0.5.8: + resolution: {integrity: sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==} + + request-light@0.7.0: + resolution: {integrity: sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + responselike@2.0.1: + resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + + retext-latin@4.0.0: + resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==} + + retext-smartypants@6.1.0: + resolution: {integrity: sha512-LDPXg95346bqFZnDMHo0S7Rq5p64+B+N8Vz733+wPMDtwb9rCOs9LIdIEhrUOU+TAywX9St+ocQWJt8wrzivcQ==} + + retext-stringify@4.0.0: + resolution: {integrity: sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==} + + retext@9.0.0: + resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup@4.36.0: + resolution: {integrity: sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + s.color@0.0.15: + resolution: {integrity: sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sass-formatter@0.7.6: + resolution: {integrity: sha512-hXdxU6PCkiV3XAiSnX+XLqz2ohHoEnVUlrd8LEVMAI80uB1+OTScIkH9n6qQwImZpTye1r1WG1rbGUteHNhoHg==} + + sax@1.2.4: + resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + send@1.1.0: + resolution: {integrity: sha512-v67WcEouB5GxbTWL/4NeToqcZiAWEq90N888fczVArY8A79J0L4FD7vj5hm3eUMua5EpoQ59wa/oovY6TLvRUA==} + engines: {node: '>= 18'} + + server-destroy@1.0.1: + resolution: {integrity: sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + sharp@0.33.3: + resolution: {integrity: sha512-vHUeXJU1UvlO/BNwTpT0x/r53WkLUVxrmb5JTgW92fdFCFk0ispLMAeu/jPO2vjkXM1fYUi3K7/qcLF47pwM1A==} + engines: {libvips: '>=8.15.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + sharp@0.34.2: + resolution: {integrity: sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shiki@3.2.2: + resolution: {integrity: sha512-0qWBkM2t/0NXPRcVgtLhtHv6Ak3Q5yI4K/ggMqcgLRKm4+pCs3namgZlhlat/7u2CuqNtlShNs9lENOG6n7UaQ==} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-git@3.21.0: + resolution: {integrity: sha512-oTzw9248AF5bDTMk9MrxsRzEzivMlY+DWH0yWS4VYpMhNLhDWnN06pCtaUyPnqv/FpsdeNmRqmZugMABHRPdDA==} + + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + sitemap@8.0.0: + resolution: {integrity: sha512-+AbdxhM9kJsHtruUF39bwS/B0Fytw6Fr1o4ZAIAEqA6cke2xcoO2GleBw9Zw7nRzILVEgz7zBM5GiTJjie1G9A==} + engines: {node: '>=14.0.0', npm: '>=6.0.0'} + hasBin: true + + sitemapper@3.2.12: + resolution: {integrity: sha512-nbc6mJ4zqG3VSrat95b+9gedzkf31P7BBtGHWtkVNbs7ObV7qcvKEiTK0B5Fiqe4HKV1lljkNTlA6vYpn7cJfg==} + engines: {node: '>= 10.0.0'} + + size-limit@11.1.6: + resolution: {integrity: sha512-S5ux2IB8rU26xwVgMskmknGMFkieaIAqDLuwgKiypk6oa4lFsie8yFPrzRFV+yrLDY2GddjXuCaVk5PveVOHiQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + smol-toml@1.3.1: + resolution: {integrity: sha512-tEYNll18pPKHroYSmLLrksq233j021G0giwW7P3D24jC54pQ5W5BXMsQ/Mvw1OJCmEYDgY+lrzT+3nNUtoNfXQ==} + engines: {node: '>= 18'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + spawndamnit@2.0.0: + resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + starlight-links-validator@0.14.0: + resolution: {integrity: sha512-mxaNtlSl+BR32PoBkFPymhNNttrozGLQan2Nkki7mzQw2Z+li5o3c1ltds+EnbIh/RuVm3xHUxZz8THQW6Xgbw==} + engines: {node: '>=18.17.1'} + peerDependencies: + '@astrojs/starlight': '>=0.15.0' + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + std-env@3.8.0: + resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} + + std-env@3.9.0: + resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + + stream-replace-string@2.0.0: + resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string.prototype.codepointat@0.2.1: + resolution: {integrity: sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==} + + stringify-entities@4.0.3: + resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + style-to-object@0.4.4: + resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} + + style-to-object@1.0.8: + resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==} + + suf-log@2.5.3: + resolution: {integrity: sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + tailwindcss@4.0.15: + resolution: {integrity: sha512-6ZMg+hHdMJpjpeCCFasX7K+U615U9D+7k5/cDK/iRwl6GptF24+I/AbKgOnXhVKePzrEyIXutLv36n4cRsq3Sg==} + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + term-size@2.2.1: + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} + engines: {node: '>=8'} + + test-exclude@7.0.1: + resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} + engines: {node: '>=18'} + + tiny-inflate@1.0.3: + resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.12: + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + engines: {node: '>=12.0.0'} + + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.1.0: + resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} + + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + tsconfck@3.1.5: + resolution: {integrity: sha512-CLDfGgUp7XPswWnezWwsCRxNmgQjhYq3VXHM0/XIRxhVrKw0M1if9agzryh1QS3nxjCROvV+xWxoJO1YctzzWg==} + engines: {node: ^18 || >=20} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + tslib@2.5.0: + resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} + + tsx@4.15.2: + resolution: {integrity: sha512-kIZTOCmR37nEw0qxQks2dR+eZWSXydhTGmz7yx94vEiJtJGBTkUl0D/jt/5fey+CNdm6i3Cp+29WKRay9ScQUw==} + engines: {node: '>=18.0.0'} + hasBin: true + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@4.26.1: + resolution: {integrity: sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==} + engines: {node: '>=16'} + + typesafe-path@0.2.2: + resolution: {integrity: sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==} + + typescript-auto-import-cache@0.3.5: + resolution: {integrity: sha512-fAIveQKsoYj55CozUiBoj4b/7WpN0i4o74wiGY5JVUEoD0XiqDk1tJqTEjgzL2/AizKQrXxyRosSebyDzBZKjw==} + + typescript-eslint@8.39.1: + resolution: {integrity: sha512-GDUv6/NDYngUlNvwaHM1RamYftxf782IyEDbdj3SeaIHHv8fNQVRC++fITT7kUJV/5rIA/tkoRSSskt6osEfqg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + typescript@5.6.3: + resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + + uhyphen@0.2.0: + resolution: {integrity: sha512-qz3o9CHXmJJPGBdqzab7qAYuW8kQGKNEuoHFYrBwV6hWIMcpAmxDLXojcHfFr9US1Pe6zUswEIJIbLI610fuqA==} + + ultrahtml@1.6.0: + resolution: {integrity: sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==} + + ultramatter@0.0.4: + resolution: {integrity: sha512-1f/hO3mR+/Hgue4eInOF/Qm/wzDqwhYha4DxM0hre9YIUyso3fE2XtrAU6B4njLqTC8CM49EZaYgsVSa+dXHGw==} + + uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unist-util-find-after@5.0.0: + resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} + + unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + + unist-util-modify-children@4.0.0: + resolution: {integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==} + + unist-util-position-from-estree@2.0.0: + resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-children@3.0.0: + resolution: {integrity: sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==} + + unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + + unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + unstorage@1.15.0: + resolution: {integrity: sha512-m40eHdGY/gA6xAPqo8eaxqXgBuzQTlAKfmB1iF7oCKXE1HfwHwzDJBywK+qQGn52dta+bPlZluPF7++yR3p/bg==} + peerDependencies: + '@azure/app-configuration': ^1.8.0 + '@azure/cosmos': ^4.2.0 + '@azure/data-tables': ^13.3.0 + '@azure/identity': ^4.6.0 + '@azure/keyvault-secrets': ^4.9.0 + '@azure/storage-blob': ^12.26.0 + '@capacitor/preferences': ^6.0.3 + '@deno/kv': '>=0.9.0' + '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 + '@planetscale/database': ^1.19.0 + '@upstash/redis': ^1.34.3 + '@vercel/blob': '>=0.27.1' + '@vercel/kv': ^1.0.1 + aws4fetch: ^1.0.20 + db0: '>=0.2.1' + idb-keyval: ^6.2.1 + ioredis: ^5.4.2 + uploadthing: ^7.4.4 + peerDependenciesMeta: + '@azure/app-configuration': + optional: true + '@azure/cosmos': + optional: true + '@azure/data-tables': + optional: true + '@azure/identity': + optional: true + '@azure/keyvault-secrets': + optional: true + '@azure/storage-blob': + optional: true + '@capacitor/preferences': + optional: true + '@deno/kv': + optional: true + '@netlify/blobs': + optional: true + '@planetscale/database': + optional: true + '@upstash/redis': + optional: true + '@vercel/blob': + optional: true + '@vercel/kv': + optional: true + aws4fetch: + optional: true + db0: + optional: true + idb-keyval: + optional: true + ioredis: + optional: true + uploadthing: + optional: true + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vfile-location@5.0.2: + resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} + + vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + vite-node@3.1.1: + resolution: {integrity: sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite@6.2.6: + resolution: {integrity: sha512-9xpjNl3kR4rVDZgPNdTL0/c6ao4km69a/2ihNQbcANz8RuCOK3hQBmLSJf3bRKVQjVMda+YvizNE8AwvogcPbw==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitefu@1.0.6: + resolution: {integrity: sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + vite: + optional: true + + vitest@3.1.1: + resolution: {integrity: sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.1.1 + '@vitest/ui': 3.1.1 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + volar-service-css@0.0.62: + resolution: {integrity: sha512-JwNyKsH3F8PuzZYuqPf+2e+4CTU8YoyUHEHVnoXNlrLe7wy9U3biomZ56llN69Ris7TTy/+DEX41yVxQpM4qvg==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-emmet@0.0.62: + resolution: {integrity: sha512-U4dxWDBWz7Pi4plpbXf4J4Z/ss6kBO3TYrACxWNsE29abu75QzVS0paxDDhI6bhqpbDFXlpsDhZ9aXVFpnfGRQ==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-html@0.0.62: + resolution: {integrity: sha512-Zw01aJsZRh4GTGUjveyfEzEqpULQUdQH79KNEiKVYHZyuGtdBRYCHlrus1sueSNMxwwkuF5WnOHfvBzafs8yyQ==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-prettier@0.0.62: + resolution: {integrity: sha512-h2yk1RqRTE+vkYZaI9KYuwpDfOQRrTEMvoHol0yW4GFKc75wWQRrb5n/5abDrzMPrkQbSip8JH2AXbvrRtYh4w==} + peerDependencies: + '@volar/language-service': ~2.4.0 + prettier: ^2.2 || ^3.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + prettier: + optional: true + + volar-service-typescript-twoslash-queries@0.0.62: + resolution: {integrity: sha512-KxFt4zydyJYYI0kFAcWPTh4u0Ha36TASPZkAnNY784GtgajerUqM80nX/W1d0wVhmcOFfAxkVsf/Ed+tiYU7ng==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-typescript@0.0.62: + resolution: {integrity: sha512-p7MPi71q7KOsH0eAbZwPBiKPp9B2+qrdHAd6VY5oTo9BUXatsOAdakTm9Yf0DUj6uWBAaOT01BSeVOPwucMV1g==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-yaml@0.0.62: + resolution: {integrity: sha512-k7gvv7sk3wa+nGll3MaSKyjwQsJjIGCHFjVkl3wjaSP2nouKyn9aokGmqjrl39mi88Oy49giog2GkZH526wjig==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + vscode-css-languageservice@6.3.2: + resolution: {integrity: sha512-GEpPxrUTAeXWdZWHev1OJU9lz2Q2/PPBxQ2TIRmLGvQiH3WZbqaNoute0n0ewxlgtjzTW3AKZT+NHySk5Rf4Eg==} + + vscode-html-languageservice@5.3.1: + resolution: {integrity: sha512-ysUh4hFeW/WOWz/TO9gm08xigiSsV/FOAZ+DolgJfeLftna54YdmZ4A+lIn46RbdO3/Qv5QHTn1ZGqmrXQhZyA==} + + vscode-json-languageservice@4.1.8: + resolution: {integrity: sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==} + engines: {npm: '>=7.0.0'} + + vscode-jsonrpc@6.0.0: + resolution: {integrity: sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==} + engines: {node: '>=8.0.0 || >=10.0.0'} + + vscode-jsonrpc@8.2.0: + resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} + engines: {node: '>=14.0.0'} + + vscode-languageserver-protocol@3.16.0: + resolution: {integrity: sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==} + + vscode-languageserver-protocol@3.17.5: + resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} + + vscode-languageserver-textdocument@1.0.12: + resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} + + vscode-languageserver-types@3.16.0: + resolution: {integrity: sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==} + + vscode-languageserver-types@3.17.5: + resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} + + vscode-languageserver@7.0.0: + resolution: {integrity: sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==} + hasBin: true + + vscode-languageserver@9.0.1: + resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} + hasBin: true + + vscode-nls@5.2.0: + resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==} + + vscode-uri@2.1.2: + resolution: {integrity: sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==} + + vscode-uri@3.0.8: + resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + + web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which-pm-runs@1.1.0: + resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} + engines: {node: '>=4'} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + widest-line@5.0.0: + resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} + engines: {node: '>=18'} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + xml2js@0.5.0: + resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} + engines: {node: '>=4.0.0'} + + xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + + xmlbuilder@15.1.1: + resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} + engines: {node: '>=8.0'} + + xxhash-wasm@1.1.0: + resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + + yaml-language-server@1.15.0: + resolution: {integrity: sha512-N47AqBDCMQmh6mBLmI6oqxryHRzi33aPFPsJhYy3VTUGCdLHYjGh4FZzpUjRlphaADBBkDmnkM/++KNIOHi5Rw==} + hasBin: true + + yaml@2.2.2: + resolution: {integrity: sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==} + engines: {node: '>= 14'} + + yaml@2.6.1: + resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yocto-queue@1.1.1: + resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} + engines: {node: '>=12.20'} + + yocto-spinner@0.2.1: + resolution: {integrity: sha512-lHHxjh0bXaLgdJy3cNnVb/F9myx3CkhrvSOEVTkaUgNMXnYFa2xYPVhtGnqhh3jErY2gParBOHallCbc7NrlZQ==} + engines: {node: '>=18.19'} + + yoctocolors@2.1.1: + resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} + engines: {node: '>=18'} + + zod-to-json-schema@3.24.5: + resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==} + peerDependencies: + zod: ^3.24.1 + + zod-to-ts@1.2.0: + resolution: {integrity: sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==} + peerDependencies: + typescript: ^4.9.4 || ^5.0.2 + zod: ^3 + + zod@3.24.2: + resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)': + dependencies: + '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) + '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + - search-insights + + '@algolia/autocomplete-plugin-algolia-insights@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)': + dependencies: + '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + + '@algolia/autocomplete-preset-algolia@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)': + dependencies: + '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) + '@algolia/client-search': 4.20.0 + algoliasearch: 4.20.0 + + '@algolia/autocomplete-shared@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)': + dependencies: + '@algolia/client-search': 4.20.0 + algoliasearch: 4.20.0 + + '@algolia/cache-browser-local-storage@4.20.0': + dependencies: + '@algolia/cache-common': 4.20.0 + + '@algolia/cache-common@4.20.0': {} + + '@algolia/cache-in-memory@4.20.0': + dependencies: + '@algolia/cache-common': 4.20.0 + + '@algolia/client-account@4.20.0': + dependencies: + '@algolia/client-common': 4.20.0 + '@algolia/client-search': 4.20.0 + '@algolia/transporter': 4.20.0 + + '@algolia/client-analytics@4.20.0': + dependencies: + '@algolia/client-common': 4.20.0 + '@algolia/client-search': 4.20.0 + '@algolia/requester-common': 4.20.0 + '@algolia/transporter': 4.20.0 + + '@algolia/client-common@4.20.0': + dependencies: + '@algolia/requester-common': 4.20.0 + '@algolia/transporter': 4.20.0 + + '@algolia/client-personalization@4.20.0': + dependencies: + '@algolia/client-common': 4.20.0 + '@algolia/requester-common': 4.20.0 + '@algolia/transporter': 4.20.0 + + '@algolia/client-search@4.20.0': + dependencies: + '@algolia/client-common': 4.20.0 + '@algolia/requester-common': 4.20.0 + '@algolia/transporter': 4.20.0 + + '@algolia/logger-common@4.20.0': {} + + '@algolia/logger-console@4.20.0': + dependencies: + '@algolia/logger-common': 4.20.0 + + '@algolia/requester-browser-xhr@4.20.0': + dependencies: + '@algolia/requester-common': 4.20.0 + + '@algolia/requester-common@4.20.0': {} + + '@algolia/requester-node-http@4.20.0': + dependencies: + '@algolia/requester-common': 4.20.0 + + '@algolia/transporter@4.20.0': + dependencies: + '@algolia/cache-common': 4.20.0 + '@algolia/logger-common': 4.20.0 + '@algolia/requester-common': 4.20.0 + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@astro-community/astro-embed-youtube@0.5.6(astro@5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1))': + dependencies: + astro: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) + lite-youtube-embed: 0.3.3 + + '@astrojs/check@0.9.4(prettier-plugin-astro@0.14.1)(prettier@3.3.3)(typescript@5.6.3)': + dependencies: + '@astrojs/language-server': 2.15.4(prettier-plugin-astro@0.14.1)(prettier@3.3.3)(typescript@5.6.3) + chokidar: 4.0.3 + kleur: 4.1.5 + typescript: 5.6.3 + yargs: 17.7.2 + transitivePeerDependencies: + - prettier + - prettier-plugin-astro + + '@astrojs/compiler@2.11.0': {} + + '@astrojs/internal-helpers@0.6.1': {} + + '@astrojs/language-server@2.15.4(prettier-plugin-astro@0.14.1)(prettier@3.3.3)(typescript@5.6.3)': + dependencies: + '@astrojs/compiler': 2.11.0 + '@astrojs/yaml2ts': 0.2.2 + '@jridgewell/sourcemap-codec': 1.5.0 + '@volar/kit': 2.4.10(typescript@5.6.3) + '@volar/language-core': 2.4.10 + '@volar/language-server': 2.4.10 + '@volar/language-service': 2.4.10 + fast-glob: 3.3.2 + muggle-string: 0.4.1 + volar-service-css: 0.0.62(@volar/language-service@2.4.10) + volar-service-emmet: 0.0.62(@volar/language-service@2.4.10) + volar-service-html: 0.0.62(@volar/language-service@2.4.10) + volar-service-prettier: 0.0.62(@volar/language-service@2.4.10)(prettier@3.3.3) + volar-service-typescript: 0.0.62(@volar/language-service@2.4.10) + volar-service-typescript-twoslash-queries: 0.0.62(@volar/language-service@2.4.10) + volar-service-yaml: 0.0.62(@volar/language-service@2.4.10) + vscode-html-languageservice: 5.3.1 + vscode-uri: 3.0.8 + optionalDependencies: + prettier: 3.3.3 + prettier-plugin-astro: 0.14.1 + transitivePeerDependencies: + - typescript + + '@astrojs/markdoc@0.13.4(astro@5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1))': + dependencies: + '@astrojs/internal-helpers': 0.6.1 + '@astrojs/markdown-remark': 6.3.1 + '@astrojs/prism': 3.2.0 + '@markdoc/markdoc': 0.5.1 + astro: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) + esbuild: 0.25.1 + github-slugger: 2.0.0 + htmlparser2: 10.0.0 + transitivePeerDependencies: + - '@types/react' + - react + - supports-color + + '@astrojs/markdown-remark@6.3.1': + dependencies: + '@astrojs/internal-helpers': 0.6.1 + '@astrojs/prism': 3.2.0 + github-slugger: 2.0.0 + hast-util-from-html: 2.0.3 + hast-util-to-text: 4.0.2 + import-meta-resolve: 4.1.0 + js-yaml: 4.1.0 + mdast-util-definitions: 6.0.0 + rehype-raw: 7.0.0 + rehype-stringify: 10.0.1 + remark-gfm: 4.0.1 + remark-parse: 11.0.0 + remark-rehype: 11.1.1 + remark-smartypants: 3.0.2 + shiki: 3.2.2 + smol-toml: 1.3.1 + unified: 11.0.5 + unist-util-remove-position: 5.0.0 + unist-util-visit: 5.0.0 + unist-util-visit-parents: 6.0.1 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@astrojs/mdx@4.2.4(astro@5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1))': + dependencies: + '@astrojs/markdown-remark': 6.3.1 + '@mdx-js/mdx': 3.1.0(acorn@8.14.1) + acorn: 8.14.1 + astro: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) + es-module-lexer: 1.6.0 + estree-util-visit: 2.0.0 + hast-util-to-html: 9.0.5 + kleur: 4.1.5 + rehype-raw: 7.0.0 + remark-gfm: 4.0.1 + remark-smartypants: 3.0.2 + source-map: 0.7.4 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@astrojs/node@9.1.3(astro@5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1))': + dependencies: + '@astrojs/internal-helpers': 0.6.1 + astro: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) + send: 1.1.0 + server-destroy: 1.0.1 + transitivePeerDependencies: + - supports-color + + '@astrojs/prism@3.2.0': + dependencies: + prismjs: 1.29.0 + + '@astrojs/sitemap@3.3.0': + dependencies: + sitemap: 8.0.0 + stream-replace-string: 2.0.0 + zod: 3.24.2 + + '@astrojs/telemetry@3.2.0': + dependencies: + ci-info: 4.2.0 + debug: 4.4.0 + dlv: 1.1.3 + dset: 3.1.4 + is-docker: 3.0.0 + is-wsl: 3.1.0 + which-pm-runs: 1.1.0 + transitivePeerDependencies: + - supports-color + + '@astrojs/yaml2ts@0.2.2': + dependencies: + yaml: 2.6.1 + + '@babel/helper-string-parser@7.25.9': {} + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/parser@7.26.2': + dependencies: + '@babel/types': 7.26.0 + + '@babel/runtime@7.24.7': + dependencies: + regenerator-runtime: 0.14.1 + + '@babel/types@7.26.0': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + + '@bcoe/v8-coverage@1.0.2': {} + + '@changesets/apply-release-plan@7.0.5': + dependencies: + '@changesets/config': 3.0.3 + '@changesets/get-version-range-type': 0.4.0 + '@changesets/git': 3.0.1 + '@changesets/should-skip-package': 0.1.1 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + detect-indent: 6.1.0 + fs-extra: 7.0.1 + lodash.startcase: 4.4.0 + outdent: 0.5.0 + prettier: 2.8.8 + resolve-from: 5.0.0 + semver: 7.7.1 + + '@changesets/assemble-release-plan@6.0.4': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.2 + '@changesets/should-skip-package': 0.1.1 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + semver: 7.7.1 + + '@changesets/changelog-git@0.2.0': + dependencies: + '@changesets/types': 6.0.0 + + '@changesets/changelog-github@0.5.0': + dependencies: + '@changesets/get-github-info': 0.6.0 + '@changesets/types': 6.0.0 + dotenv: 8.6.0 + transitivePeerDependencies: + - encoding + + '@changesets/cli@2.27.9': + dependencies: + '@changesets/apply-release-plan': 7.0.5 + '@changesets/assemble-release-plan': 6.0.4 + '@changesets/changelog-git': 0.2.0 + '@changesets/config': 3.0.3 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.2 + '@changesets/get-release-plan': 4.0.4 + '@changesets/git': 3.0.1 + '@changesets/logger': 0.1.1 + '@changesets/pre': 2.0.1 + '@changesets/read': 0.6.1 + '@changesets/should-skip-package': 0.1.1 + '@changesets/types': 6.0.0 + '@changesets/write': 0.3.2 + '@manypkg/get-packages': 1.1.3 + ansi-colors: 4.1.3 + ci-info: 3.9.0 + enquirer: 2.3.6 + external-editor: 3.1.0 + fs-extra: 7.0.1 + mri: 1.2.0 + p-limit: 2.3.0 + package-manager-detector: 0.2.2 + picocolors: 1.1.1 + resolve-from: 5.0.0 + semver: 7.7.1 + spawndamnit: 2.0.0 + term-size: 2.2.1 + + '@changesets/config@3.0.3': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.2 + '@changesets/logger': 0.1.1 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + micromatch: 4.0.8 + + '@changesets/errors@0.2.0': + dependencies: + extendable-error: 0.1.7 + + '@changesets/get-dependents-graph@2.1.2': + dependencies: + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + picocolors: 1.1.1 + semver: 7.7.1 + + '@changesets/get-github-info@0.6.0': + dependencies: + dataloader: 1.4.0 + node-fetch: 2.6.10 + transitivePeerDependencies: + - encoding + + '@changesets/get-release-plan@4.0.4': + dependencies: + '@changesets/assemble-release-plan': 6.0.4 + '@changesets/config': 3.0.3 + '@changesets/pre': 2.0.1 + '@changesets/read': 0.6.1 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/get-version-range-type@0.4.0': {} + + '@changesets/git@3.0.1': + dependencies: + '@changesets/errors': 0.2.0 + '@manypkg/get-packages': 1.1.3 + is-subdir: 1.2.0 + micromatch: 4.0.8 + spawndamnit: 2.0.0 + + '@changesets/logger@0.1.1': + dependencies: + picocolors: 1.1.1 + + '@changesets/parse@0.4.0': + dependencies: + '@changesets/types': 6.0.0 + js-yaml: 3.14.1 + + '@changesets/pre@2.0.1': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + + '@changesets/read@0.6.1': + dependencies: + '@changesets/git': 3.0.1 + '@changesets/logger': 0.1.1 + '@changesets/parse': 0.4.0 + '@changesets/types': 6.0.0 + fs-extra: 7.0.1 + p-filter: 2.1.0 + picocolors: 1.1.1 + + '@changesets/should-skip-package@0.1.1': + dependencies: + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/types@4.1.0': {} + + '@changesets/types@6.0.0': {} + + '@changesets/write@0.3.2': + dependencies: + '@changesets/types': 6.0.0 + fs-extra: 7.0.1 + human-id: 1.0.2 + prettier: 2.8.8 + + '@clack/core@0.3.4': + dependencies: + picocolors: 1.1.1 + sisteransi: 1.0.5 + + '@ctrl/tinycolor@4.1.0': {} + + '@docsearch/css@3.6.0': {} + + '@docsearch/js@3.6.0(@algolia/client-search@4.20.0)': + dependencies: + '@docsearch/react': 3.6.0(@algolia/client-search@4.20.0) + preact: 10.18.2 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/react' + - react + - react-dom + - search-insights + + '@docsearch/react@3.6.0(@algolia/client-search@4.20.0)': + dependencies: + '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) + '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) + '@docsearch/css': 3.6.0 + algoliasearch: 4.20.0 + transitivePeerDependencies: + - '@algolia/client-search' + + '@emmetio/abbreviation@2.3.3': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/css-abbreviation@2.1.8': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/css-parser@0.4.0': + dependencies: + '@emmetio/stream-reader': 2.2.0 + '@emmetio/stream-reader-utils': 0.1.0 + + '@emmetio/html-matcher@1.3.0': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/scanner@1.0.4': {} + + '@emmetio/stream-reader-utils@0.1.0': {} + + '@emmetio/stream-reader@2.2.0': {} + + '@emnapi/runtime@1.4.3': + dependencies: + tslib: 2.5.0 + optional: true + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/aix-ppc64@0.25.1': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.25.1': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-arm@0.25.1': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/android-x64@0.25.1': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.25.1': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.25.1': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.25.1': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.25.1': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.25.1': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-arm@0.25.1': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.25.1': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.25.1': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.25.1': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.25.1': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.25.1': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.25.1': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/linux-x64@0.25.1': + optional: true + + '@esbuild/netbsd-arm64@0.25.1': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.25.1': + optional: true + + '@esbuild/openbsd-arm64@0.25.1': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.25.1': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.25.1': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.25.1': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.25.1': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@esbuild/win32-x64@0.25.1': + optional: true + + '@eslint-community/eslint-utils@4.7.0(eslint@9.33.0(jiti@2.4.2))': + dependencies: + eslint: 9.33.0(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.21.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.0 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.3.1': {} + + '@eslint/core@0.15.2': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.0 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.2.4 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.33.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.3.5': + dependencies: + '@eslint/core': 0.15.2 + levn: 0.4.1 + + '@expressive-code/core@0.41.1': + dependencies: + '@ctrl/tinycolor': 4.1.0 + hast-util-select: 6.0.2 + hast-util-to-html: 9.0.5 + hast-util-to-text: 4.0.2 + hastscript: 9.0.0 + postcss: 8.5.3 + postcss-nested: 6.0.1(postcss@8.5.3) + unist-util-visit: 5.0.0 + unist-util-visit-parents: 6.0.1 + + '@expressive-code/plugin-frames@0.41.1': + dependencies: + '@expressive-code/core': 0.41.1 + + '@expressive-code/plugin-shiki@0.41.1': + dependencies: + '@expressive-code/core': 0.41.1 + shiki: 3.2.2 + + '@expressive-code/plugin-text-markers@0.41.1': + dependencies: + '@expressive-code/core': 0.41.1 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@img/sharp-darwin-arm64@0.33.3': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.2 + optional: true + + '@img/sharp-darwin-arm64@0.34.2': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.1.0 + optional: true + + '@img/sharp-darwin-x64@0.33.3': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.2 + optional: true + + '@img/sharp-darwin-x64@0.34.2': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.1.0 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.0.2': + optional: true + + '@img/sharp-libvips-darwin-arm64@1.1.0': + optional: true + + '@img/sharp-libvips-darwin-x64@1.0.2': + optional: true + + '@img/sharp-libvips-darwin-x64@1.1.0': + optional: true + + '@img/sharp-libvips-linux-arm64@1.0.2': + optional: true + + '@img/sharp-libvips-linux-arm64@1.1.0': + optional: true + + '@img/sharp-libvips-linux-arm@1.0.2': + optional: true + + '@img/sharp-libvips-linux-arm@1.1.0': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.1.0': + optional: true + + '@img/sharp-libvips-linux-s390x@1.0.2': + optional: true + + '@img/sharp-libvips-linux-s390x@1.1.0': + optional: true + + '@img/sharp-libvips-linux-x64@1.0.2': + optional: true + + '@img/sharp-libvips-linux-x64@1.1.0': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.0.2': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.1.0': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.0.2': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.1.0': + optional: true + + '@img/sharp-linux-arm64@0.33.3': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.2 + optional: true + + '@img/sharp-linux-arm64@0.34.2': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.1.0 + optional: true + + '@img/sharp-linux-arm@0.33.3': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.2 + optional: true + + '@img/sharp-linux-arm@0.34.2': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.1.0 + optional: true + + '@img/sharp-linux-s390x@0.33.3': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.2 optional: true - /@esbuild/linux-x64@0.19.2: - resolution: {integrity: sha512-oxzHTEv6VPm3XXNaHPyUTTte+3wGv7qVQtqaZCrgstI16gCuhNOtBXLEBkBREP57YTd68P0VgDgG73jSD8bwXQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true + '@img/sharp-linux-s390x@0.34.2': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.1.0 optional: true - /@esbuild/netbsd-x64@0.18.17: - resolution: {integrity: sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true + '@img/sharp-linux-x64@0.33.3': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.2 optional: true - /@esbuild/netbsd-x64@0.19.2: - resolution: {integrity: sha512-WNa5zZk1XpTTwMDompZmvQLHszDDDN7lYjEHCUmAGB83Bgs20EMs7ICD+oKeT6xt4phV4NDdSi/8OfjPbSbZfQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true + '@img/sharp-linux-x64@0.34.2': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.1.0 optional: true - /@esbuild/openbsd-x64@0.18.17: - resolution: {integrity: sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true + '@img/sharp-linuxmusl-arm64@0.33.3': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 optional: true - /@esbuild/openbsd-x64@0.19.2: - resolution: {integrity: sha512-S6kI1aT3S++Dedb7vxIuUOb3oAxqxk2Rh5rOXOTYnzN8JzW1VzBd+IqPiSpgitu45042SYD3HCoEyhLKQcDFDw==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true + '@img/sharp-linuxmusl-arm64@0.34.2': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.1.0 optional: true - /@esbuild/sunos-x64@0.18.17: - resolution: {integrity: sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true + '@img/sharp-linuxmusl-x64@0.33.3': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.2 optional: true - /@esbuild/sunos-x64@0.19.2: - resolution: {integrity: sha512-VXSSMsmb+Z8LbsQGcBMiM+fYObDNRm8p7tkUDMPG/g4fhFX5DEFmjxIEa3N8Zr96SjsJ1woAhF0DUnS3MF3ARw==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true + '@img/sharp-linuxmusl-x64@0.34.2': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.1.0 optional: true - /@esbuild/win32-arm64@0.18.17: - resolution: {integrity: sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true + '@img/sharp-wasm32@0.33.3': + dependencies: + '@emnapi/runtime': 1.4.3 optional: true - /@esbuild/win32-arm64@0.19.2: - resolution: {integrity: sha512-5NayUlSAyb5PQYFAU9x3bHdsqB88RC3aM9lKDAz4X1mo/EchMIT1Q+pSeBXNgkfNmRecLXA0O8xP+x8V+g/LKg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true + '@img/sharp-wasm32@0.34.2': + dependencies: + '@emnapi/runtime': 1.4.3 optional: true - /@esbuild/win32-ia32@0.18.17: - resolution: {integrity: sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true + '@img/sharp-win32-arm64@0.34.2': optional: true - /@esbuild/win32-ia32@0.19.2: - resolution: {integrity: sha512-47gL/ek1v36iN0wL9L4Q2MFdujR0poLZMJwhO2/N3gA89jgHp4MR8DKCmwYtGNksbfJb9JoTtbkoe6sDhg2QTA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true + '@img/sharp-win32-ia32@0.33.3': optional: true - /@esbuild/win32-x64@0.18.17: - resolution: {integrity: sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true + '@img/sharp-win32-ia32@0.34.2': optional: true - /@esbuild/win32-x64@0.19.2: - resolution: {integrity: sha512-tcuhV7ncXBqbt/Ybf0IyrMcwVOAPDckMK9rXNHtF17UTK18OKLpg08glminN06pt2WCoALhXdLfSPbVvK/6fxw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true + '@img/sharp-win32-x64@0.33.3': optional: true - /@hapi/hoek@9.3.0: - resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} - dev: true + '@img/sharp-win32-x64@0.34.2': + optional: true - /@hapi/topo@5.1.0: - resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + '@isaacs/cliui@8.0.2': dependencies: - '@hapi/hoek': 9.3.0 - dev: true - - /@istanbuljs/schema@0.1.3: - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - dev: true + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 - /@jest/schemas@29.6.0: - resolution: {integrity: sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@sinclair/typebox': 0.27.8 - dev: true + '@istanbuljs/schema@0.1.3': {} - /@jridgewell/gen-mapping@0.3.2: - resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} - engines: {node: '>=6.0.0'} + '@jridgewell/gen-mapping@0.3.5': dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.18 - - /@jridgewell/resolve-uri@3.1.0: - resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} - engines: {node: '>=6.0.0'} + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 - /@jridgewell/set-array@1.1.2: - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} - engines: {node: '>=6.0.0'} + '@jridgewell/resolve-uri@3.1.1': {} - /@jridgewell/sourcemap-codec@1.4.14: - resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} + '@jridgewell/set-array@1.2.1': {} - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + '@jridgewell/sourcemap-codec@1.5.0': {} - /@jridgewell/trace-mapping@0.3.18: - resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} + '@jridgewell/trace-mapping@0.3.25': dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.5.0 - /@kwsites/file-exists@1.1.1: - resolution: {integrity: sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==} + '@kwsites/file-exists@1.1.1': dependencies: - debug: 4.3.4 + debug: 4.4.0 transitivePeerDependencies: - supports-color - dev: true - /@kwsites/promise-deferred@1.1.1: - resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} - dev: true + '@kwsites/promise-deferred@1.1.1': {} - /@manypkg/find-root@1.1.0: - resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + '@lunariajs/core@0.1.1': dependencies: - '@babel/runtime': 7.21.5 + '@clack/core': 0.3.4 + fast-glob: 3.3.2 + get-port: 7.1.0 + jiti: 1.21.0 + micromatch: 4.0.8 + path-to-regexp: 6.2.2 + picocolors: 1.1.1 + simple-git: 3.21.0 + ultramatter: 0.0.4 + zod: 3.24.2 + transitivePeerDependencies: + - supports-color + + '@manypkg/find-root@1.1.0': + dependencies: + '@babel/runtime': 7.24.7 '@types/node': 12.20.55 find-up: 4.1.0 fs-extra: 8.1.0 - dev: true - /@manypkg/get-packages@1.1.3: - resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + '@manypkg/get-packages@1.1.3': dependencies: - '@babel/runtime': 7.21.5 + '@babel/runtime': 7.24.7 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 globby: 11.1.0 read-yaml-file: 1.1.0 - dev: true - /@mdx-js/mdx@2.3.0: - resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==} - dependencies: - '@types/estree-jsx': 1.0.0 - '@types/mdx': 2.0.5 - estree-util-build-jsx: 2.2.2 - estree-util-is-identifier-name: 2.1.0 - estree-util-to-js: 1.2.0 + '@markdoc/markdoc@0.5.1': + optionalDependencies: + '@types/linkify-it': 3.0.5 + '@types/markdown-it': 12.2.3 + + '@mdx-js/mdx@3.1.0(acorn@8.14.1)': + dependencies: + '@types/estree': 1.0.6 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdx': 2.0.13 + collapse-white-space: 2.1.0 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + estree-util-scope: 1.0.0 estree-walker: 3.0.3 - hast-util-to-estree: 2.3.2 - markdown-extensions: 1.1.1 - periscopic: 3.1.0 - remark-mdx: 2.3.0 - remark-parse: 10.0.2 - remark-rehype: 10.1.0 - unified: 10.1.2 - unist-util-position-from-estree: 1.1.2 - unist-util-stringify-position: 3.0.3 - unist-util-visit: 4.1.2 - vfile: 5.3.7 + hast-util-to-jsx-runtime: 2.3.2 + markdown-extensions: 2.0.0 + recma-build-jsx: 1.0.0 + recma-jsx: 1.0.0(acorn@8.14.1) + recma-stringify: 1.0.0 + rehype-recma: 1.0.0 + remark-mdx: 3.1.0 + remark-parse: 11.0.0 + remark-rehype: 11.1.1 + source-map: 0.7.4 + unified: 11.0.5 + unist-util-position-from-estree: 2.0.0 + unist-util-stringify-position: 4.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 transitivePeerDependencies: + - acorn - supports-color - dev: false - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} + '@nodelib/fs.stat@2.0.5': {} - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} + '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.15.0 + fastq: 1.17.1 - /@pagefind/darwin-arm64@1.0.3: - resolution: {integrity: sha512-vsHDtvao3W4iFCxVc4S0BVhpj3E2MAoIVM7RmuQfGp1Ng22nGLRaMP6FguLO8TMabRJdvp4SVr227hL4WGKOHA==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false + '@oslojs/encoding@1.1.0': {} + + '@pagefind/darwin-arm64@1.3.0': optional: true - /@pagefind/darwin-x64@1.0.3: - resolution: {integrity: sha512-NhEXHHYmB/hT6lx5rCcmnVTxH+uIkMAd43bzEqMwHQosqTZEIQfwihmV39H+m8yo7jFvz3zRbJNzhAh7G4PiwA==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false + '@pagefind/darwin-x64@1.3.0': optional: true - /@pagefind/default-ui@1.0.3: - resolution: {integrity: sha512-WieFJXvezyvjZh49I8j7a7Kz3LsXYY2Uep3IWvG5NG05mmiurURXjXc+KyrpIp/iAycSnjrC1TDJ8CdES/ee3A==} - dev: false + '@pagefind/default-ui@1.3.0': {} - /@pagefind/linux-arm64@1.0.3: - resolution: {integrity: sha512-RGsMt4AmGT8WxCSeP09arU7Za6Vf/We4TWHVSbY7vDMuwWql9Ngoib/q1cP9dIAIMdkXh9ePG/S3mGnJYsdzuQ==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false + '@pagefind/linux-arm64@1.3.0': optional: true - /@pagefind/linux-x64@1.0.3: - resolution: {integrity: sha512-o+VCKaqImL42scSH1n5gUfppYSNyu3BuGTvtKKgWHmycbL+A3fkFH+ZOFbaLeN7LVTvJqJIOYbk4j2yaq9784Q==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false + '@pagefind/linux-x64@1.3.0': optional: true - /@pagefind/windows-x64@1.0.3: - resolution: {integrity: sha512-S+Yq4FyvXJm4F+iN/wRiLvEEF8Xs9lTKGtQGaRHXJslQyl65dytDDPIULXJXIadrDbnMrnTt4C2YHmEUIyUIHg==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false + '@pagefind/windows-x64@1.3.0': + optional: true + + '@pkgjs/parseargs@0.11.0': optional: true - /@sideway/address@4.1.4: - resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==} + '@playwright/test@1.45.0': dependencies: - '@hapi/hoek': 9.3.0 - dev: true + playwright: 1.45.0 + + '@rollup/pluginutils@5.1.4(rollup@4.36.0)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.36.0 + + '@rollup/rollup-android-arm-eabi@4.36.0': + optional: true + + '@rollup/rollup-android-arm64@4.36.0': + optional: true - /@sideway/formula@3.0.1: - resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} - dev: true + '@rollup/rollup-darwin-arm64@4.36.0': + optional: true - /@sideway/pinpoint@2.0.0: - resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} - dev: true + '@rollup/rollup-darwin-x64@4.36.0': + optional: true - /@sinclair/typebox@0.27.8: - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - dev: true + '@rollup/rollup-freebsd-arm64@4.36.0': + optional: true - /@size-limit/file@8.2.4(size-limit@8.2.4): - resolution: {integrity: sha512-xLuF97W7m7lxrRJvqXRlxO/4t7cpXtfxOnjml/t4aRVUCMXLdyvebRr9OM4jjoK8Fmiz8jomCbETUCI3jVhLzA==} - engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0} - peerDependencies: - size-limit: 8.2.4 + '@rollup/rollup-freebsd-x64@4.36.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.36.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.36.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.36.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.36.0': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.36.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.36.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.36.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.36.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.36.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.36.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.36.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.36.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.36.0': + optional: true + + '@shikijs/core@3.2.2': dependencies: - semver: 7.3.8 - size-limit: 8.2.4 - dev: true + '@shikijs/types': 3.2.2 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 - /@types/acorn@4.0.6: - resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} + '@shikijs/engine-javascript@3.2.2': + dependencies: + '@shikijs/types': 3.2.2 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 4.2.0 + + '@shikijs/engine-oniguruma@3.2.2': + dependencies: + '@shikijs/types': 3.2.2 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/langs@3.2.2': dependencies: - '@types/estree': 1.0.0 - dev: false + '@shikijs/types': 3.2.2 - /@types/babel__core@7.20.1: - resolution: {integrity: sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==} + '@shikijs/themes@3.2.2': dependencies: - '@babel/parser': 7.22.14 - '@babel/types': 7.22.11 - '@types/babel__generator': 7.6.4 - '@types/babel__template': 7.4.1 - '@types/babel__traverse': 7.18.3 + '@shikijs/types': 3.2.2 - /@types/babel__generator@7.6.4: - resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} + '@shikijs/types@3.2.2': dependencies: - '@babel/types': 7.22.11 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 - /@types/babel__template@7.4.1: - resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} + '@shikijs/vscode-textmate@10.0.2': {} + + '@sindresorhus/is@4.6.0': {} + + '@size-limit/file@11.1.6(size-limit@11.1.6)': dependencies: - '@babel/parser': 7.22.14 - '@babel/types': 7.22.11 + size-limit: 11.1.6 - /@types/babel__traverse@7.18.3: - resolution: {integrity: sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==} + '@szmarczak/http-timer@4.0.6': dependencies: - '@babel/types': 7.22.11 + defer-to-connect: 2.0.1 - /@types/chai-subset@1.3.3: - resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} + '@tailwindcss/node@4.0.15': dependencies: - '@types/chai': 4.3.5 - dev: true + enhanced-resolve: 5.18.1 + jiti: 2.4.2 + tailwindcss: 4.0.15 + + '@tailwindcss/oxide-android-arm64@4.0.15': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.0.15': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.0.15': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.0.15': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.15': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.0.15': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.0.15': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.0.15': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.0.15': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.0.15': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.0.15': + optional: true - /@types/chai@4.3.5: - resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==} - dev: true + '@tailwindcss/oxide@4.0.15': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.0.15 + '@tailwindcss/oxide-darwin-arm64': 4.0.15 + '@tailwindcss/oxide-darwin-x64': 4.0.15 + '@tailwindcss/oxide-freebsd-x64': 4.0.15 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.15 + '@tailwindcss/oxide-linux-arm64-gnu': 4.0.15 + '@tailwindcss/oxide-linux-arm64-musl': 4.0.15 + '@tailwindcss/oxide-linux-x64-gnu': 4.0.15 + '@tailwindcss/oxide-linux-x64-musl': 4.0.15 + '@tailwindcss/oxide-win32-arm64-msvc': 4.0.15 + '@tailwindcss/oxide-win32-x64-msvc': 4.0.15 + + '@tailwindcss/vite@4.0.15(vite@6.2.6(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1))': + dependencies: + '@tailwindcss/node': 4.0.15 + '@tailwindcss/oxide': 4.0.15 + lightningcss: 1.29.2 + tailwindcss: 4.0.15 + vite: 6.2.6(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1) + + '@types/acorn@4.0.6': + dependencies: + '@types/estree': 1.0.6 + + '@types/cacheable-request@6.0.3': + dependencies: + '@types/http-cache-semantics': 4.0.4 + '@types/keyv': 3.1.4 + '@types/node': 18.16.19 + '@types/responselike': 1.0.3 - /@types/culori@2.0.0: - resolution: {integrity: sha512-bKpEra39sQS9UZ+1JoWhuGJEzwKS0dUkNCohVYmn6CAEBkqyIXimKiPDRZWtiOB7sKgkWMaTUpHFimygRoGIlg==} - dev: false + '@types/culori@2.1.1': {} - /@types/debug@4.1.7: - resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} + '@types/debug@4.1.12': dependencies: - '@types/ms': 0.7.31 + '@types/ms': 0.7.34 - /@types/estree-jsx@1.0.0: - resolution: {integrity: sha512-3qvGd0z8F2ENTGr/GG1yViqfiKmRfrXVx5sJyHGFu3z7m5g5utCQtGp/g29JnjflhtQJBv1WDQukHiT58xPcYQ==} + '@types/estree-jsx@1.0.5': dependencies: - '@types/estree': 1.0.0 - dev: false + '@types/estree': 1.0.6 - /@types/estree@1.0.0: - resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} + '@types/estree@1.0.6': {} - /@types/hast@2.3.4: - resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==} + '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.0 - /@types/html-escaper@3.0.0: - resolution: {integrity: sha512-OcJcvP3Yk8mjYwf/IdXZtTE1tb/u0WF0qa29ER07ZHCYUBZXSN29Z1mBS+/96+kNMGTFUAbSz9X+pHmHpZrTCw==} - dev: true + '@types/http-cache-semantics@4.0.4': {} + + '@types/js-yaml@4.0.9': {} + + '@types/json-schema@7.0.15': {} - /@types/is-ci@3.0.0: - resolution: {integrity: sha512-Q0Op0hdWbYd1iahB+IFNQcWXFq4O0Q5MwQP7uN0souuQ4rPg1vEYcnIOfr1gY+M+6rc8FGoRaBO1mOOvL29sEQ==} + '@types/junit-report-builder@3.0.2': {} + + '@types/keyv@3.1.4': dependencies: - ci-info: 3.8.0 - dev: true + '@types/node': 18.16.19 - /@types/istanbul-lib-coverage@2.0.4: - resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} - dev: true + '@types/linkify-it@3.0.5': + optional: true - /@types/json5@0.0.30: - resolution: {integrity: sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA==} + '@types/markdown-it@12.2.3': + dependencies: + '@types/linkify-it': 3.0.5 + '@types/mdurl': 2.0.0 + optional: true - /@types/mdast@3.0.11: - resolution: {integrity: sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==} + '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.0 - /@types/mdast@4.0.1: - resolution: {integrity: sha512-IlKct1rUTJ1T81d8OHzyop15kGv9A/ff7Gz7IJgrk6jDb4Udw77pCJ+vq8oxZf4Ghpm+616+i1s/LNg/Vh7d+g==} + '@types/mdurl@2.0.0': + optional: true + + '@types/mdx@2.0.13': {} + + '@types/ms@0.7.34': {} + + '@types/nlcst@2.0.3': dependencies: '@types/unist': 3.0.0 - /@types/mdx@2.0.5: - resolution: {integrity: sha512-76CqzuD6Q7LC+AtbPqrvD9AqsN0k8bsYo2bM2J8pmNldP1aIPAbzUQ7QbobyXL4eLr1wK5x8FZFe8eF/ubRuBg==} - dev: false + '@types/node@12.20.55': {} + + '@types/node@17.0.45': {} - /@types/minimist@1.2.2: - resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} - dev: true + '@types/node@18.16.19': {} - /@types/ms@0.7.31: - resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} + '@types/opentype.js@1.3.8': {} - /@types/nlcst@1.0.0: - resolution: {integrity: sha512-3TGCfOcy8R8mMQ4CNSNOe3PG66HttvjcLzCoOpvXvDtfWOTi+uT/rxeOKm/qEwbM4SNe1O/PjdiBK2YcTjU4OQ==} + '@types/picomatch@3.0.1': {} + + '@types/responselike@1.0.3': dependencies: - '@types/unist': 3.0.0 + '@types/node': 18.16.19 - /@types/node@12.20.55: - resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - dev: true + '@types/sax@1.2.4': + dependencies: + '@types/node': 18.16.19 - /@types/node@17.0.45: - resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} - dev: false + '@types/unist@2.0.10': {} - /@types/node@18.16.19: - resolution: {integrity: sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==} + '@types/unist@3.0.0': {} + + '@typescript-eslint/eslint-plugin@8.39.1(@typescript-eslint/parser@8.39.1(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3))(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.39.1(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.39.1 + '@typescript-eslint/type-utils': 8.39.1(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3) + '@typescript-eslint/utils': 8.39.1(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.39.1 + eslint: 9.33.0(jiti@2.4.2) + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.6.3) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color - /@types/normalize-package-data@2.4.1: - resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} - dev: true + '@typescript-eslint/parser@8.39.1(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.39.1 + '@typescript-eslint/types': 8.39.1 + '@typescript-eslint/typescript-estree': 8.39.1(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.39.1 + debug: 4.4.0 + eslint: 9.33.0(jiti@2.4.2) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color - /@types/parse5@6.0.3: - resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} + '@typescript-eslint/project-service@8.39.1(typescript@5.6.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.39.1(typescript@5.6.3) + '@typescript-eslint/types': 8.39.1 + debug: 4.4.0 + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color - /@types/resolve@1.20.2: - resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + '@typescript-eslint/scope-manager@8.39.1': + dependencies: + '@typescript-eslint/types': 8.39.1 + '@typescript-eslint/visitor-keys': 8.39.1 - /@types/retry@0.12.1: - resolution: {integrity: sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==} - dev: true + '@typescript-eslint/tsconfig-utils@8.39.1(typescript@5.6.3)': + dependencies: + typescript: 5.6.3 - /@types/sax@1.2.4: - resolution: {integrity: sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==} + '@typescript-eslint/type-utils@8.39.1(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3)': dependencies: - '@types/node': 18.16.19 - dev: false + '@typescript-eslint/types': 8.39.1 + '@typescript-eslint/typescript-estree': 8.39.1(typescript@5.6.3) + '@typescript-eslint/utils': 8.39.1(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3) + debug: 4.4.0 + eslint: 9.33.0(jiti@2.4.2) + ts-api-utils: 2.1.0(typescript@5.6.3) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color - /@types/semver@6.2.3: - resolution: {integrity: sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A==} - dev: true + '@typescript-eslint/types@8.39.1': {} - /@types/unist@2.0.6: - resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} + '@typescript-eslint/typescript-estree@8.39.1(typescript@5.6.3)': + dependencies: + '@typescript-eslint/project-service': 8.39.1(typescript@5.6.3) + '@typescript-eslint/tsconfig-utils': 8.39.1(typescript@5.6.3) + '@typescript-eslint/types': 8.39.1 + '@typescript-eslint/visitor-keys': 8.39.1 + debug: 4.4.0 + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.6.3) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color - /@types/unist@3.0.0: - resolution: {integrity: sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==} + '@typescript-eslint/utils@8.39.1(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.39.1 + '@typescript-eslint/types': 8.39.1 + '@typescript-eslint/typescript-estree': 8.39.1(typescript@5.6.3) + eslint: 9.33.0(jiti@2.4.2) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color - /@types/yauzl@2.10.0: - resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} - requiresBuild: true + '@typescript-eslint/visitor-keys@8.39.1': dependencies: - '@types/node': 18.16.19 - dev: true - optional: true + '@typescript-eslint/types': 8.39.1 + eslint-visitor-keys: 4.2.1 - /@vitest/coverage-v8@0.33.0(vitest@0.33.0): - resolution: {integrity: sha512-Rj5IzoLF7FLj6yR7TmqsfRDSeaFki6NAJ/cQexqhbWkHEV2htlVGrmuOde3xzvFsCbLCagf4omhcIaVmfU8Okg==} - peerDependencies: - vitest: '>=0.32.0 <1' - dependencies: - '@ampproject/remapping': 2.2.1 - '@bcoe/v8-coverage': 0.2.3 - istanbul-lib-coverage: 3.2.0 - istanbul-lib-report: 3.0.0 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.5 - magic-string: 0.30.3 - picocolors: 1.0.0 - std-env: 3.3.3 - test-exclude: 6.0.0 - v8-to-istanbul: 9.1.0 - vitest: 0.33.0 + '@ungap/structured-clone@1.2.0': {} + + '@vitest/coverage-v8@3.0.5(vitest@3.1.1(@types/debug@4.1.12)(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 1.0.2 + debug: 4.4.0 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.1.7 + magic-string: 0.30.17 + magicast: 0.3.5 + std-env: 3.8.0 + test-exclude: 7.0.1 + tinyrainbow: 2.0.0 + vitest: 3.1.1(@types/debug@4.1.12)(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1) transitivePeerDependencies: - supports-color - dev: true - /@vitest/expect@0.33.0: - resolution: {integrity: sha512-sVNf+Gla3mhTCxNJx+wJLDPp/WcstOe0Ksqz4Vec51MmgMth/ia0MGFEkIZmVGeTL5HtjYR4Wl/ZxBxBXZJTzQ==} + '@vitest/expect@3.1.1': dependencies: - '@vitest/spy': 0.33.0 - '@vitest/utils': 0.33.0 - chai: 4.3.7 - dev: true + '@vitest/spy': 3.1.1 + '@vitest/utils': 3.1.1 + chai: 5.2.0 + tinyrainbow: 2.0.0 - /@vitest/runner@0.33.0: - resolution: {integrity: sha512-UPfACnmCB6HKRHTlcgCoBh6ppl6fDn+J/xR8dTufWiKt/74Y9bHci5CKB8tESSV82zKYtkBJo9whU3mNvfaisg==} + '@vitest/mocker@3.1.1(vite@6.2.6(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1))': dependencies: - '@vitest/utils': 0.33.0 - p-limit: 4.0.0 - pathe: 1.1.1 - dev: true + '@vitest/spy': 3.1.1 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 6.2.6(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1) - /@vitest/snapshot@0.33.0: - resolution: {integrity: sha512-tJjrl//qAHbyHajpFvr8Wsk8DIOODEebTu7pgBrP07iOepR5jYkLFiqLq2Ltxv+r0uptUb4izv1J8XBOwKkVYA==} + '@vitest/pretty-format@3.1.1': dependencies: - magic-string: 0.30.3 - pathe: 1.1.1 - pretty-format: 29.6.1 - dev: true + tinyrainbow: 2.0.0 - /@vitest/spy@0.33.0: - resolution: {integrity: sha512-Kv+yZ4hnH1WdiAkPUQTpRxW8kGtH8VRTnus7ZTGovFYM1ZezJpvGtb9nPIjPnptHbsyIAxYZsEpVPYgtpjGnrg==} + '@vitest/runner@3.1.1': dependencies: - tinyspy: 2.1.1 - dev: true + '@vitest/utils': 3.1.1 + pathe: 2.0.3 - /@vitest/utils@0.33.0: - resolution: {integrity: sha512-pF1w22ic965sv+EN6uoePkAOTkAPWM03Ri/jXNyMIKBb/XHLDPfhLvf/Fa9g0YECevAIz56oVYXhodLvLQ/awA==} + '@vitest/snapshot@3.1.1': dependencies: - diff-sequences: 29.4.3 - loupe: 2.3.6 - pretty-format: 29.6.1 - dev: true + '@vitest/pretty-format': 3.1.1 + magic-string: 0.30.17 + pathe: 2.0.3 - /abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - dev: true + '@vitest/spy@3.1.1': + dependencies: + tinyspy: 3.0.2 - /acorn-jsx@5.3.2(acorn@8.10.0): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + '@vitest/utils@3.1.1': dependencies: - acorn: 8.10.0 - dev: false + '@vitest/pretty-format': 3.1.1 + loupe: 3.1.3 + tinyrainbow: 2.0.0 - /acorn-walk@8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} - engines: {node: '>=0.4.0'} - dev: true + '@volar/kit@2.4.10(typescript@5.6.3)': + dependencies: + '@volar/language-service': 2.4.10 + '@volar/typescript': 2.4.10 + typesafe-path: 0.2.2 + typescript: 5.6.3 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 - /acorn@8.10.0: - resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} - engines: {node: '>=0.4.0'} - hasBin: true + '@volar/language-core@2.4.10': + dependencies: + '@volar/source-map': 2.4.10 - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} + '@volar/language-server@2.4.10': dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true + '@volar/language-core': 2.4.10 + '@volar/language-service': 2.4.10 + '@volar/typescript': 2.4.10 + path-browserify: 1.0.1 + request-light: 0.7.0 + vscode-languageserver: 9.0.1 + vscode-languageserver-protocol: 3.17.5 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 - /ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + '@volar/language-service@2.4.10': dependencies: - string-width: 4.2.3 + '@volar/language-core': 2.4.10 + vscode-languageserver-protocol: 3.17.5 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 - /ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - dev: true + '@volar/source-map@2.4.10': {} - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} + '@volar/typescript@2.4.10': + dependencies: + '@volar/language-core': 2.4.10 + path-browserify: 1.0.1 + vscode-uri: 3.0.8 - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} + '@vscode/emmet-helper@2.9.3': + dependencies: + emmet: 2.4.7 + jsonc-parser: 2.3.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-uri: 2.1.2 - /ansi-sequence-parser@1.1.0: - resolution: {integrity: sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==} + '@vscode/l10n@0.0.18': {} - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} + acorn-jsx@5.3.2(acorn@8.14.1): dependencies: - color-convert: 1.9.3 + acorn: 8.14.1 - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: - color-convert: 2.0.1 - dev: true + acorn: 8.15.0 - /ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - dev: true + acorn@8.14.1: {} - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} + acorn@8.15.0: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + algoliasearch@4.20.0: + dependencies: + '@algolia/cache-browser-local-storage': 4.20.0 + '@algolia/cache-common': 4.20.0 + '@algolia/cache-in-memory': 4.20.0 + '@algolia/client-account': 4.20.0 + '@algolia/client-analytics': 4.20.0 + '@algolia/client-common': 4.20.0 + '@algolia/client-personalization': 4.20.0 + '@algolia/client-search': 4.20.0 + '@algolia/logger-common': 4.20.0 + '@algolia/logger-console': 4.20.0 + '@algolia/requester-browser-xhr': 4.20.0 + '@algolia/requester-common': 4.20.0 + '@algolia/requester-node-http': 4.20.0 + '@algolia/transporter': 4.20.0 + + ansi-align@3.0.1: + dependencies: + string-width: 4.2.3 + + ansi-colors@4.1.3: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 - /any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - dev: false + ansi-styles@6.2.1: {} - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - /arg@5.0.2: - resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + arg@5.0.2: {} - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + argparse@2.0.1: {} - /array-buffer-byte-length@1.0.0: - resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} - dependencies: - call-bind: 1.0.2 - is-array-buffer: 3.0.2 - dev: true + aria-query@5.3.2: {} - /array-iterate@2.0.1: - resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} + array-iterate@2.0.1: {} - /array-union@1.0.2: - resolution: {integrity: sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==} - engines: {node: '>=0.10.0'} - dependencies: - array-uniq: 1.0.3 - dev: true + array-union@2.1.0: {} - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true + assertion-error@2.0.1: {} - /array-uniq@1.0.3: - resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} - engines: {node: '>=0.10.0'} - dev: true + astring@1.9.0: {} - /array.prototype.flat@1.3.1: - resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} - engines: {node: '>= 0.4'} + astro-expressive-code@0.41.1(astro@5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1)): dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - es-shim-unscopables: 1.0.0 - dev: true - - /arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - dev: true - - /assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - dev: true + astro: 5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1) + rehype-expressive-code: 0.41.1 - /astring@1.8.4: - resolution: {integrity: sha512-97a+l2LBU3Op3bBQEff79i/E4jMD2ZLFD8rHx9B6mXyB2uQwhJQYfiDqUwtfjF4QA1F2qs//N6Cw8LetMbQjcw==} - hasBin: true - dev: false - - /astro@3.2.1(@types/node@18.16.19): - resolution: {integrity: sha512-idPwpMSdFg8wuS9HVkefDcbRdKpCkQzZGeKw3XO6enLcCv6ZvACRdWgl9xhM/N3RO4AOzrnJPAk1cbYcP3FdNQ==} - engines: {node: '>=18.14.1', npm: '>=6.14.0'} - hasBin: true + astro@5.6.2(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(rollup@4.36.0)(tsx@4.15.2)(typescript@5.6.3)(yaml@2.6.1): dependencies: - '@astrojs/compiler': 2.1.0 - '@astrojs/internal-helpers': 0.2.0 - '@astrojs/markdown-remark': 3.2.0(astro@3.2.1) - '@astrojs/telemetry': 3.0.2 - '@babel/core': 7.22.11 - '@babel/generator': 7.22.10 - '@babel/parser': 7.22.14 - '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.11) - '@babel/traverse': 7.22.11 - '@babel/types': 7.22.11 - '@types/babel__core': 7.20.1 - acorn: 8.10.0 - boxen: 7.1.1 - chokidar: 3.5.3 - ci-info: 3.8.0 - clsx: 2.0.0 + '@astrojs/compiler': 2.11.0 + '@astrojs/internal-helpers': 0.6.1 + '@astrojs/markdown-remark': 6.3.1 + '@astrojs/telemetry': 3.2.0 + '@oslojs/encoding': 1.1.0 + '@rollup/pluginutils': 5.1.4(rollup@4.36.0) + acorn: 8.14.1 + aria-query: 5.3.2 + axobject-query: 4.1.0 + boxen: 8.0.1 + ci-info: 4.2.0 + clsx: 2.1.1 common-ancestor-path: 1.0.1 - cookie: 0.5.0 - debug: 4.3.4 - devalue: 4.3.2 - diff: 5.1.0 - es-module-lexer: 1.3.0 - esbuild: 0.19.2 + cookie: 1.0.2 + cssesc: 3.0.0 + debug: 4.4.0 + deterministic-object-hash: 2.0.2 + devalue: 5.1.1 + diff: 5.2.0 + dlv: 1.1.3 + dset: 3.1.4 + es-module-lexer: 1.6.0 + esbuild: 0.25.1 estree-walker: 3.0.3 - execa: 8.0.1 - fast-glob: 3.3.1 + flattie: 1.1.1 github-slugger: 2.0.0 - gray-matter: 4.0.3 html-escaper: 3.0.3 http-cache-semantics: 4.1.1 js-yaml: 4.1.0 kleur: 4.1.5 - magic-string: 0.30.3 - mime: 3.0.0 - ora: 7.0.1 - p-limit: 4.0.0 - path-to-regexp: 6.2.1 - preferred-pm: 3.1.2 - probe-image-size: 7.2.3 + magic-string: 0.30.17 + magicast: 0.3.5 + mrmime: 2.0.1 + neotraverse: 0.6.18 + p-limit: 6.2.0 + p-queue: 8.1.0 + package-manager-detector: 1.1.0 + picomatch: 4.0.2 prompts: 2.4.2 - rehype: 12.0.1 - resolve: 1.22.4 - semver: 7.5.4 - server-destroy: 1.0.1 - shiki: 0.14.3 - string-width: 6.1.0 - strip-ansi: 7.1.0 - tsconfig-resolver: 3.0.1 - undici: 5.23.0 - unist-util-visit: 4.1.2 - vfile: 5.3.7 - vite: 4.4.9(@types/node@18.16.19) - vitefu: 0.2.4(vite@4.4.9) - which-pm: 2.1.1 + rehype: 13.0.2 + semver: 7.7.2 + shiki: 3.2.2 + tinyexec: 0.3.2 + tinyglobby: 0.2.12 + tsconfck: 3.1.5(typescript@5.6.3) + ultrahtml: 1.6.0 + unist-util-visit: 5.0.0 + unstorage: 1.15.0 + vfile: 6.0.3 + vite: 6.2.6(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1) + vitefu: 1.0.6(vite@6.2.6(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1)) + xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 - zod: 3.21.1 + yocto-spinner: 0.2.1 + zod: 3.24.2 + zod-to-json-schema: 3.24.5(zod@3.24.2) + zod-to-ts: 1.2.0(typescript@5.6.3)(zod@3.24.2) optionalDependencies: - sharp: 0.32.5 + sharp: 0.33.3 transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' - '@types/node' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - db0 + - idb-keyval + - ioredis + - jiti - less - lightningcss + - rollup - sass + - sass-embedded - stylus - sugarss - supports-color - terser + - tsx + - typescript + - uploadthing + - yaml - /async@2.6.4: - resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} - dependencies: - lodash: 4.17.21 - dev: true - - /asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true - - /autoprefixer@10.4.15(postcss@8.4.29): - resolution: {integrity: sha512-KCuPB8ZCIqFdA4HwKXsvz7j6gvSDNhDP7WnUjBleRkKjPdvCmHFuQ77ocavI8FT6NdvlBnE2UFr2H4Mycn8Vew==} - engines: {node: ^10 || ^12 || >=14} - hasBin: true - peerDependencies: - postcss: ^8.1.0 - dependencies: - browserslist: 4.21.10 - caniuse-lite: 1.0.30001524 - fraction.js: 4.2.0 - normalize-range: 0.1.2 - picocolors: 1.0.0 - postcss: 8.4.29 - postcss-value-parser: 4.2.0 - dev: false - - /available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} - engines: {node: '>= 0.4'} - dev: true + axe-core@4.10.1: {} - /axe-core@4.7.0: - resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} - engines: {node: '>=4'} - dev: true + axe-html-reporter@2.2.11(axe-core@4.10.1): + dependencies: + axe-core: 4.10.1 + mustache: 4.2.0 - /axios@0.27.2(debug@4.3.4): - resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} + axe-playwright@2.0.3(playwright@1.45.0): dependencies: - follow-redirects: 1.15.2(debug@4.3.4) - form-data: 4.0.0 - transitivePeerDependencies: - - debug - dev: true + '@types/junit-report-builder': 3.0.2 + axe-core: 4.10.1 + axe-html-reporter: 2.2.11(axe-core@4.10.1) + junit-report-builder: 5.1.1 + picocolors: 1.1.1 + playwright: 1.45.0 - /b4a@1.6.4: - resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==} + axobject-query@4.1.0: {} - /bail@2.0.2: - resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + bail@2.0.2: {} - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@1.0.2: {} - /base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + base-64@1.0.0: {} - /bcp-47-match@2.0.3: - resolution: {integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==} - dev: false + bcp-47-match@2.0.3: {} - /bcp-47@2.1.0: - resolution: {integrity: sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==} + bcp-47@2.1.0: dependencies: is-alphabetical: 2.0.1 is-alphanumerical: 2.0.1 is-decimal: 2.0.1 - dev: false - /better-path-resolve@1.0.0: - resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} - engines: {node: '>=4'} + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 - dev: true - - /bfj@7.0.2: - resolution: {integrity: sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw==} - engines: {node: '>= 8.0.0'} - dependencies: - bluebird: 3.7.2 - check-types: 11.2.2 - hoopy: 0.1.4 - tryer: 1.0.1 - dev: true - - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - - /bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - - /bl@5.1.0: - resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} - dependencies: - buffer: 6.0.3 - inherits: 2.0.4 - readable-stream: 3.6.2 - /bluebird@3.7.2: - resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} - dev: true + boolbase@1.0.0: {} - /boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - - /boxen@7.1.1: - resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} - engines: {node: '>=14.16'} + boxen@8.0.1: dependencies: ansi-align: 3.0.1 - camelcase: 7.0.1 + camelcase: 8.0.0 chalk: 5.3.0 cli-boxes: 3.0.0 - string-width: 5.1.2 - type-fest: 2.19.0 - widest-line: 4.0.1 - wrap-ansi: 8.1.0 + string-width: 7.2.0 + type-fest: 4.26.1 + widest-line: 5.0.0 + wrap-ansi: 9.0.0 - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - - /breakword@1.0.5: - resolution: {integrity: sha512-ex5W9DoOQ/LUEU3PMdLs9ua/CYZl1678NUkKOdUSi8Aw5F1idieaiRURCBFJCwVcrD1J8Iy3vfWSloaMwO2qFg==} - dependencies: - wcwidth: 1.0.1 - dev: true - - /browserslist@4.21.10: - resolution: {integrity: sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001524 - electron-to-chromium: 1.4.505 - node-releases: 2.0.13 - update-browserslist-db: 1.0.11(browserslist@4.21.10) - - /buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - dev: true - - /buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - /buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + brace-expansion@2.0.1: dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 + balanced-match: 1.0.2 - /busboy@1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} + braces@3.0.3: dependencies: - streamsearch: 1.1.0 - - /bytes-iec@3.1.1: - resolution: {integrity: sha512-fey6+4jDK7TFtFg/klGSvNKJctyU7n2aQdnM+CO0ruLPbqqMOM8Tio0Pc+deqUeVKX1tL5DQep1zQ7+37aTAsA==} - engines: {node: '>= 0.8'} - dev: true + fill-range: 7.1.1 - /cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - dev: true + bytes-iec@3.1.1: {} - /call-bind@1.0.2: - resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} - dependencies: - function-bind: 1.1.1 - get-intrinsic: 1.2.0 - dev: true + cac@6.7.14: {} - /camelcase-css@2.0.1: - resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} - engines: {node: '>= 6'} - dev: false + cacheable-lookup@5.0.4: {} - /camelcase-keys@6.2.2: - resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} - engines: {node: '>=8'} + cacheable-request@7.0.4: dependencies: - camelcase: 5.3.1 - map-obj: 4.3.0 - quick-lru: 4.0.1 - dev: true - - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true + clone-response: 1.0.3 + get-stream: 5.2.0 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + lowercase-keys: 2.0.0 + normalize-url: 6.1.0 + responselike: 2.0.1 - /camelcase@7.0.1: - resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} - engines: {node: '>=14.16'} + callsites@3.1.0: {} - /caniuse-lite@1.0.30001524: - resolution: {integrity: sha512-Jj917pJtYg9HSJBF95HVX3Cdr89JUyLT4IZ8SvM5aDRni95swKgYi3TgYLH5hnGfPE/U1dg6IfZ50UsIlLkwSA==} + camelcase@8.0.0: {} - /ccount@2.0.1: - resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + ccount@2.0.1: {} - /chai@4.3.7: - resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==} - engines: {node: '>=4'} + chai@5.2.0: dependencies: - assertion-error: 1.1.0 - check-error: 1.0.2 - deep-eql: 4.1.3 - get-func-name: 2.0.0 - loupe: 2.3.6 - pathval: 1.1.1 - type-detect: 4.0.8 - dev: true - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.2 + pathval: 2.0.0 - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - dev: true - - /chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - - /character-entities-html4@2.1.0: - resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} - - /character-entities-legacy@3.0.0: - resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} - - /character-entities@2.0.2: - resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - /character-reference-invalid@2.0.1: - resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} - dev: false + chalk@5.3.0: {} - /chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - dev: true + character-entities-html4@2.1.0: {} - /check-error@1.0.2: - resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} - dev: true + character-entities-legacy@3.0.0: {} - /check-more-types@2.24.0: - resolution: {integrity: sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==} - engines: {node: '>= 0.8.0'} - dev: true + character-entities@2.0.2: {} - /check-types@11.2.2: - resolution: {integrity: sha512-HBiYvXvn9Z70Z88XKjz3AEKd4HJhBXsa3j7xFnITAzoS8+q6eIGi8qDB8FKPBAjtuxjI/zFpwuiCb8oDtKOYrA==} - dev: true + character-reference-invalid@2.0.1: {} - /cheerio-select@2.1.0: - resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} - dependencies: - boolbase: 1.0.0 - css-select: 5.1.0 - css-what: 6.1.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.1.0 - dev: true + chardet@0.7.0: {} - /cheerio@1.0.0-rc.12: - resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==} - engines: {node: '>= 6'} - dependencies: - cheerio-select: 2.1.0 - dom-serializer: 2.0.0 - domhandler: 5.0.3 - domutils: 3.1.0 - htmlparser2: 8.0.2 - parse5: 7.1.2 - parse5-htmlparser2-tree-adapter: 7.0.0 - dev: true + check-error@2.1.1: {} - /chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} + chokidar@4.0.3: dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.2 - - /chownr@1.1.4: - resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - - /ci-info@3.8.0: - resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} - engines: {node: '>=8'} + readdirp: 4.0.2 - /cli-boxes@3.0.0: - resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} - engines: {node: '>=10'} - - /cli-cursor@4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - restore-cursor: 4.0.0 + ci-info@3.9.0: {} - /cli-spinners@2.9.0: - resolution: {integrity: sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==} - engines: {node: '>=6'} + ci-info@4.2.0: {} - /cliui@6.0.0: - resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - dev: true + cli-boxes@3.0.0: {} - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} + cliui@8.0.1: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: true - /clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: true + clone-response@1.0.3: + dependencies: + mimic-response: 1.0.1 - /clsx@2.0.0: - resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} - engines: {node: '>=6'} + clsx@2.1.1: {} - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 + collapse-white-space@2.1.0: {} - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + color-convert@2.0.1: dependencies: color-name: 1.1.4 - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + color-name@1.1.4: {} - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - /color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + color-string@1.9.1: dependencies: color-name: 1.1.4 simple-swizzle: 0.2.2 - /color@4.2.3: - resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} - engines: {node: '>=12.5.0'} + color@4.2.3: dependencies: color-convert: 2.0.1 color-string: 1.9.1 - /combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - dev: true - - /comma-separated-tokens@2.0.3: - resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - - /commander@4.1.1: - resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} - engines: {node: '>= 6'} - dev: false - - /commander@6.2.1: - resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} - engines: {node: '>= 6'} - dev: true - - /commander@8.0.0: - resolution: {integrity: sha512-Xvf85aAtu6v22+E5hfVoLHqyul/jyxh91zvqk/ioJTQuJR7Z78n7H558vMPKanPSRgIEeZemT92I2g9Y8LPbSQ==} - engines: {node: '>= 12'} - dev: true + comma-separated-tokens@2.0.3: {} - /common-ancestor-path@1.0.1: - resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} + common-ancestor-path@1.0.1: {} - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + concat-map@0.0.1: {} - /convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + cookie-es@1.2.2: {} - /cookie@0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} - engines: {node: '>= 0.6'} + cookie@1.0.2: {} - /cross-spawn@5.1.0: - resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + cross-spawn@5.1.0: dependencies: lru-cache: 4.1.5 shebang-command: 1.2.0 which: 1.3.1 - dev: true - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} + cross-spawn@7.0.5: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - /css-select@5.1.0: - resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 5.0.3 - domutils: 3.1.0 - nth-check: 2.1.1 - dev: true - - /css-selector-parser@1.4.1: - resolution: {integrity: sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g==} - dev: false - - /css-what@6.1.0: - resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} - engines: {node: '>= 6'} - dev: true - - /cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - dev: false - - /csv-generate@3.4.3: - resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} - dev: true - - /csv-parse@4.16.3: - resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} - dev: true - - /csv-stringify@5.6.5: - resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} - dev: true - - /csv@5.5.3: - resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} - engines: {node: '>= 0.1.90'} - dependencies: - csv-generate: 3.4.3 - csv-parse: 4.16.3 - csv-stringify: 5.6.5 - stream-transform: 2.1.3 - dev: true - - /culori@3.2.0: - resolution: {integrity: sha512-HIEbTSP7vs1mPq/2P9In6QyFE0Tkpevh0k9a+FkjhD+cwsYm9WRSbn4uMdW9O0yXlNYC3ppxL3gWWPOcvEl57w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: false - - /data-uri-to-buffer@4.0.1: - resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} - engines: {node: '>= 12'} - dev: true - - /dataloader@1.4.0: - resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} - dev: true - - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - - /debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - - /decamelize-keys@1.1.1: - resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} - engines: {node: '>=0.10.0'} - dependencies: - decamelize: 1.2.0 - map-obj: 1.0.1 - dev: true - - /decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} - dev: true - - /decode-named-character-reference@1.0.2: - resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} - dependencies: - character-entities: 2.0.2 - - /decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} - dependencies: - mimic-response: 3.1.0 - - /dedent-js@1.0.1: - resolution: {integrity: sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==} - dev: true - - /deep-eql@4.1.3: - resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} - engines: {node: '>=6'} + cross-spawn@7.0.6: dependencies: - type-detect: 4.0.8 - dev: true - - /deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + crossws@0.3.4: dependencies: - clone: 1.0.4 - dev: true + uncrypto: 0.1.3 - /define-properties@1.2.0: - resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} - engines: {node: '>= 0.4'} + css-select@5.1.0: dependencies: - has-property-descriptors: 1.0.0 - object-keys: 1.1.1 - dev: true - - /delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dev: true - - /dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - - /detect-indent@6.1.0: - resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} - engines: {node: '>=8'} - dev: true - - /detect-libc@2.0.2: - resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} - engines: {node: '>=8'} - - /devalue@4.3.2: - resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==} - - /devtools-protocol@0.0.869402: - resolution: {integrity: sha512-VvlVYY+VDJe639yHs5PHISzdWTLL3Aw8rO4cvUtwvoxFd6FHbE4OpHHcde52M6096uYYazAmd4l0o5VuFRO2WA==} - dev: true - - /didyoumean@1.2.2: - resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - dev: false - - /diff-sequences@29.4.3: - resolution: {integrity: sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 - /diff@5.1.0: - resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} - engines: {node: '>=0.3.1'} + css-selector-parser@3.0.2: {} - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true + css-what@6.1.0: {} - /direction@2.0.1: - resolution: {integrity: sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==} - hasBin: true - dev: false + cssesc@3.0.0: {} - /dlv@1.1.3: - resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + cssom@0.5.0: {} - /dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - dev: true + culori@4.0.1: {} - /domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - dev: true + dataloader@1.4.0: {} - /domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} + debug@4.4.0: dependencies: - domelementtype: 2.3.0 - dev: true + ms: 2.1.3 - /domutils@3.1.0: - resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + decode-named-character-reference@1.0.2: dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - dev: true + character-entities: 2.0.2 - /dotenv@8.6.0: - resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} - engines: {node: '>=10'} - dev: true + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 - /dset@3.1.2: - resolution: {integrity: sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==} - engines: {node: '>=4'} + deep-eql@5.0.2: {} - /duplexer@0.1.2: - resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} - dev: true + deep-is@0.1.4: {} - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + defer-to-connect@2.0.1: {} - /electron-to-chromium@1.4.505: - resolution: {integrity: sha512-0A50eL5BCCKdxig2SsCXhpuztnB9PfUgRMojj5tMvt8O54lbwz3t6wNgnpiTRosw5QjlJB7ixhVyeg8daLQwSQ==} + defu@6.1.4: {} - /emoji-regex@10.2.1: - resolution: {integrity: sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==} + depd@2.0.0: {} - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dequal@2.0.3: {} - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + destr@2.0.3: {} - /end-of-stream@1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - dependencies: - once: 1.4.0 + destroy@1.2.0: {} - /enquirer@2.3.6: - resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} - engines: {node: '>=8.6'} - dependencies: - ansi-colors: 4.1.3 - dev: true + detect-indent@6.1.0: {} - /entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - dev: true + detect-libc@2.0.3: {} - /envinfo@7.8.1: - resolution: {integrity: sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==} - engines: {node: '>=4'} - hasBin: true - dev: true + detect-libc@2.0.4: {} - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + deterministic-object-hash@2.0.2: dependencies: - is-arrayish: 0.2.1 - dev: true + base-64: 1.0.0 - /es-abstract@1.21.2: - resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.0 - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - es-set-tostringtag: 2.0.1 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.5 - get-intrinsic: 1.2.0 - get-symbol-description: 1.0.0 - globalthis: 1.0.3 - gopd: 1.0.1 - has: 1.0.3 - has-property-descriptors: 1.0.0 - has-proto: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.5 - is-array-buffer: 3.0.2 - is-callable: 1.2.7 - is-negative-zero: 2.0.2 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - is-string: 1.0.7 - is-typed-array: 1.1.10 - is-weakref: 1.0.2 - object-inspect: 1.12.3 - object-keys: 1.1.1 - object.assign: 4.1.4 - regexp.prototype.flags: 1.5.0 - safe-regex-test: 1.0.0 - string.prototype.trim: 1.2.7 - string.prototype.trimend: 1.0.6 - string.prototype.trimstart: 1.0.6 - typed-array-length: 1.0.4 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.9 - dev: true - - /es-module-lexer@1.3.0: - resolution: {integrity: sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==} - - /es-set-tostringtag@2.0.1: - resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} - engines: {node: '>= 0.4'} + devalue@5.1.1: {} + + devlop@1.1.0: dependencies: - get-intrinsic: 1.2.0 - has: 1.0.3 - has-tostringtag: 1.0.0 - dev: true + dequal: 2.0.3 + + diff@5.2.0: {} - /es-shim-unscopables@1.0.0: - resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} + dir-glob@3.0.1: dependencies: - has: 1.0.3 - dev: true + path-type: 4.0.0 - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} + direction@2.0.1: {} + + dlv@1.1.3: {} + + dom-serializer@2.0.0: dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: true + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 - /esbuild-android-64@0.15.18: - resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true + domelementtype@2.3.0: {} - /esbuild-android-arm64@0.15.18: - resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 - /esbuild-darwin-64@0.15.18: - resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 - /esbuild-darwin-arm64@0.15.18: - resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true + dotenv@8.6.0: {} - /esbuild-freebsd-64@0.15.18: - resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true + dset@3.1.4: {} - /esbuild-freebsd-arm64@0.15.18: - resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true + eastasianwidth@0.2.0: {} - /esbuild-linux-32@0.15.18: - resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true + ee-first@1.1.1: {} - /esbuild-linux-64@0.15.18: - resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true + emmet@2.4.7: + dependencies: + '@emmetio/abbreviation': 2.3.3 + '@emmetio/css-abbreviation': 2.1.8 - /esbuild-linux-arm64@0.15.18: - resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true + emoji-regex-xs@1.0.0: {} - /esbuild-linux-arm@0.15.18: - resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true + emoji-regex@10.3.0: {} - /esbuild-linux-mips64le@0.15.18: - resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true + emoji-regex@8.0.0: {} - /esbuild-linux-ppc64le@0.15.18: - resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true + emoji-regex@9.2.2: {} - /esbuild-linux-riscv64@0.15.18: - resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true + encodeurl@2.0.0: {} - /esbuild-linux-s390x@0.15.18: - resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 - /esbuild-netbsd-64@0.15.18: - resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true + enhanced-resolve@5.18.1: + dependencies: + graceful-fs: 4.2.10 + tapable: 2.2.1 - /esbuild-openbsd-64@0.15.18: - resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true + enquirer@2.3.6: + dependencies: + ansi-colors: 4.1.3 - /esbuild-sunos-64@0.15.18: - resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true + entities@4.5.0: {} - /esbuild-windows-32@0.15.18: - resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true + entities@6.0.0: {} - /esbuild-windows-64@0.15.18: - resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true + es-module-lexer@1.6.0: {} - /esbuild-windows-arm64@0.15.18: - resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true + esast-util-from-estree@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + unist-util-position-from-estree: 2.0.0 - /esbuild@0.15.18: - resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true + esast-util-from-js@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + acorn: 8.14.1 + esast-util-from-estree: 2.0.0 + vfile-message: 4.0.2 + + esbuild@0.21.5: optionalDependencies: - '@esbuild/android-arm': 0.15.18 - '@esbuild/linux-loong64': 0.15.18 - esbuild-android-64: 0.15.18 - esbuild-android-arm64: 0.15.18 - esbuild-darwin-64: 0.15.18 - esbuild-darwin-arm64: 0.15.18 - esbuild-freebsd-64: 0.15.18 - esbuild-freebsd-arm64: 0.15.18 - esbuild-linux-32: 0.15.18 - esbuild-linux-64: 0.15.18 - esbuild-linux-arm: 0.15.18 - esbuild-linux-arm64: 0.15.18 - esbuild-linux-mips64le: 0.15.18 - esbuild-linux-ppc64le: 0.15.18 - esbuild-linux-riscv64: 0.15.18 - esbuild-linux-s390x: 0.15.18 - esbuild-netbsd-64: 0.15.18 - esbuild-openbsd-64: 0.15.18 - esbuild-sunos-64: 0.15.18 - esbuild-windows-32: 0.15.18 - esbuild-windows-64: 0.15.18 - esbuild-windows-arm64: 0.15.18 - dev: true - - /esbuild@0.18.17: - resolution: {integrity: sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + esbuild@0.25.1: optionalDependencies: - '@esbuild/android-arm': 0.18.17 - '@esbuild/android-arm64': 0.18.17 - '@esbuild/android-x64': 0.18.17 - '@esbuild/darwin-arm64': 0.18.17 - '@esbuild/darwin-x64': 0.18.17 - '@esbuild/freebsd-arm64': 0.18.17 - '@esbuild/freebsd-x64': 0.18.17 - '@esbuild/linux-arm': 0.18.17 - '@esbuild/linux-arm64': 0.18.17 - '@esbuild/linux-ia32': 0.18.17 - '@esbuild/linux-loong64': 0.18.17 - '@esbuild/linux-mips64el': 0.18.17 - '@esbuild/linux-ppc64': 0.18.17 - '@esbuild/linux-riscv64': 0.18.17 - '@esbuild/linux-s390x': 0.18.17 - '@esbuild/linux-x64': 0.18.17 - '@esbuild/netbsd-x64': 0.18.17 - '@esbuild/openbsd-x64': 0.18.17 - '@esbuild/sunos-x64': 0.18.17 - '@esbuild/win32-arm64': 0.18.17 - '@esbuild/win32-ia32': 0.18.17 - '@esbuild/win32-x64': 0.18.17 - - /esbuild@0.19.2: - resolution: {integrity: sha512-G6hPax8UbFakEj3hWO0Vs52LQ8k3lnBhxZWomUJDxfz3rZTLqF5k/FCzuNdLx2RbpBiQQF9H9onlDDH1lZsnjg==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true + '@esbuild/aix-ppc64': 0.25.1 + '@esbuild/android-arm': 0.25.1 + '@esbuild/android-arm64': 0.25.1 + '@esbuild/android-x64': 0.25.1 + '@esbuild/darwin-arm64': 0.25.1 + '@esbuild/darwin-x64': 0.25.1 + '@esbuild/freebsd-arm64': 0.25.1 + '@esbuild/freebsd-x64': 0.25.1 + '@esbuild/linux-arm': 0.25.1 + '@esbuild/linux-arm64': 0.25.1 + '@esbuild/linux-ia32': 0.25.1 + '@esbuild/linux-loong64': 0.25.1 + '@esbuild/linux-mips64el': 0.25.1 + '@esbuild/linux-ppc64': 0.25.1 + '@esbuild/linux-riscv64': 0.25.1 + '@esbuild/linux-s390x': 0.25.1 + '@esbuild/linux-x64': 0.25.1 + '@esbuild/netbsd-arm64': 0.25.1 + '@esbuild/netbsd-x64': 0.25.1 + '@esbuild/openbsd-arm64': 0.25.1 + '@esbuild/openbsd-x64': 0.25.1 + '@esbuild/sunos-x64': 0.25.1 + '@esbuild/win32-arm64': 0.25.1 + '@esbuild/win32-ia32': 0.25.1 + '@esbuild/win32-x64': 0.25.1 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@4.0.0: {} + + escape-string-regexp@5.0.0: {} + + eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.4.2)): + dependencies: + eslint: 9.33.0(jiti@2.4.2) + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.33.0(jiti@2.4.2): + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.1 + '@eslint/core': 0.15.2 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.33.0 + '@eslint/plugin-kit': 0.3.5 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.0 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.2.4 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 optionalDependencies: - '@esbuild/android-arm': 0.19.2 - '@esbuild/android-arm64': 0.19.2 - '@esbuild/android-x64': 0.19.2 - '@esbuild/darwin-arm64': 0.19.2 - '@esbuild/darwin-x64': 0.19.2 - '@esbuild/freebsd-arm64': 0.19.2 - '@esbuild/freebsd-x64': 0.19.2 - '@esbuild/linux-arm': 0.19.2 - '@esbuild/linux-arm64': 0.19.2 - '@esbuild/linux-ia32': 0.19.2 - '@esbuild/linux-loong64': 0.19.2 - '@esbuild/linux-mips64el': 0.19.2 - '@esbuild/linux-ppc64': 0.19.2 - '@esbuild/linux-riscv64': 0.19.2 - '@esbuild/linux-s390x': 0.19.2 - '@esbuild/linux-x64': 0.19.2 - '@esbuild/netbsd-x64': 0.19.2 - '@esbuild/openbsd-x64': 0.19.2 - '@esbuild/sunos-x64': 0.19.2 - '@esbuild/win32-arm64': 0.19.2 - '@esbuild/win32-ia32': 0.19.2 - '@esbuild/win32-x64': 0.19.2 - - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} + jiti: 2.4.2 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} + esprima@4.0.1: {} - /escape-string-regexp@5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 - /estree-util-attach-comments@2.1.1: - resolution: {integrity: sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w==} + estraverse@5.3.0: {} + + estree-util-attach-comments@3.0.0: dependencies: - '@types/estree': 1.0.0 - dev: false + '@types/estree': 1.0.6 - /estree-util-build-jsx@2.2.2: - resolution: {integrity: sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg==} + estree-util-build-jsx@3.0.1: dependencies: - '@types/estree-jsx': 1.0.0 - estree-util-is-identifier-name: 2.1.0 + '@types/estree-jsx': 1.0.5 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 estree-walker: 3.0.3 - dev: false - /estree-util-is-identifier-name@2.1.0: - resolution: {integrity: sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==} - dev: false + estree-util-is-identifier-name@3.0.0: {} - /estree-util-to-js@1.2.0: - resolution: {integrity: sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==} + estree-util-scope@1.0.0: dependencies: - '@types/estree-jsx': 1.0.0 - astring: 1.8.4 - source-map: 0.7.4 - dev: false + '@types/estree': 1.0.6 + devlop: 1.1.0 - /estree-util-visit@1.2.1: - resolution: {integrity: sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==} + estree-util-to-js@2.0.0: dependencies: - '@types/estree-jsx': 1.0.0 - '@types/unist': 2.0.6 - dev: false + '@types/estree-jsx': 1.0.5 + astring: 1.9.0 + source-map: 0.7.4 - /estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + estree-util-visit@2.0.0: dependencies: - '@types/estree': 1.0.0 + '@types/estree-jsx': 1.0.5 + '@types/unist': 3.0.0 - /event-stream@3.3.4: - resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} - dependencies: - duplexer: 0.1.2 - from: 0.1.7 - map-stream: 0.1.0 - pause-stream: 0.0.11 - split: 0.3.3 - stream-combiner: 0.0.4 - through: 2.3.8 - dev: true + estree-walker@2.0.2: {} - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} + estree-walker@3.0.3: dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /execa@7.1.1: - resolution: {integrity: sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==} - engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 4.3.1 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.1.0 - onetime: 6.0.0 - signal-exit: 3.0.7 - strip-final-newline: 3.0.0 - dev: false - - /execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.1.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 + '@types/estree': 1.0.6 - /expand-template@2.0.3: - resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} - engines: {node: '>=6'} + esutils@2.0.3: {} - /extend-shallow@2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} + etag@1.8.1: {} + + eventemitter3@5.0.1: {} + + expect-type@1.2.1: {} + + expressive-code@0.41.1: dependencies: - is-extendable: 0.1.1 + '@expressive-code/core': 0.41.1 + '@expressive-code/plugin-frames': 0.41.1 + '@expressive-code/plugin-shiki': 0.41.1 + '@expressive-code/plugin-text-markers': 0.41.1 - /extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + extend@3.0.2: {} - /extendable-error@0.1.7: - resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} - dev: true + extendable-error@0.1.7: {} - /external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} + external-editor@3.1.0: dependencies: chardet: 0.7.0 iconv-lite: 0.4.24 tmp: 0.0.33 - dev: true - - /extract-zip@2.0.1: - resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} - engines: {node: '>= 10.17.0'} - hasBin: true - dependencies: - debug: 4.3.4 - get-stream: 5.2.0 - yauzl: 2.10.0 - optionalDependencies: - '@types/yauzl': 2.10.0 - transitivePeerDependencies: - - supports-color - dev: true - /fast-fifo@1.3.0: - resolution: {integrity: sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw==} + fast-deep-equal@3.1.3: {} - /fast-glob@3.3.1: - resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} - engines: {node: '>=8.6.0'} + fast-glob@3.3.2: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} - /fastq@1.15.0: - resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + fast-levenshtein@2.0.6: {} + + fast-uri@3.0.3: {} + + fastq@1.17.1: dependencies: reusify: 1.0.4 - /fd-slicer@1.1.0: - resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} - dependencies: - pend: 1.2.0 - dev: true + fdir@6.4.3(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 - /fetch-blob@3.2.0: - resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} - engines: {node: ^12.20 || >= 14.13} + file-entry-cache@8.0.0: dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 3.2.1 - dev: true + flat-cache: 4.0.1 - /file-url@3.0.0: - resolution: {integrity: sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==} - engines: {node: '>=8'} - dev: true - - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} + find-up@4.1.0: dependencies: locate-path: 5.0.0 path-exists: 4.0.0 - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} + find-up@5.0.0: dependencies: locate-path: 6.0.0 path-exists: 4.0.0 - /find-yarn-workspace-root2@1.2.16: - resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} - dependencies: - micromatch: 4.0.5 - pkg-dir: 4.2.0 - - /follow-redirects@1.15.2(debug@4.3.4): - resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true + flat-cache@4.0.1: dependencies: - debug: 4.3.4 - dev: true + flatted: 3.3.3 + keyv: 4.5.4 - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.7 - dev: true + flatted@3.3.3: {} - /form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: true + flattie@1.1.1: {} - /formdata-polyfill@4.0.10: - resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} - engines: {node: '>=12.20.0'} + foreground-child@3.3.0: dependencies: - fetch-blob: 3.2.0 - dev: true - - /fraction.js@4.2.0: - resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} - dev: false - - /from@0.1.7: - resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} - dev: true + cross-spawn: 7.0.5 + signal-exit: 4.1.0 - /fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fresh@0.5.2: {} - /fs-extra@7.0.1: - resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} - engines: {node: '>=6 <7 || >=8'} + fs-extra@7.0.1: dependencies: graceful-fs: 4.2.10 jsonfile: 4.0.0 universalify: 0.1.2 - dev: true - /fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} + fs-extra@8.1.0: dependencies: graceful-fs: 4.2.10 jsonfile: 4.0.0 universalify: 0.1.2 - dev: true - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - /fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true + fsevents@2.3.2: optional: true - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - - /function.prototype.name@1.1.5: - resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - functions-have-names: 1.2.3 - dev: true - - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} + fsevents@2.3.3: + optional: true - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true + get-caller-file@2.0.5: {} - /get-func-name@2.0.0: - resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} - dev: true + get-east-asian-width@1.2.0: {} - /get-intrinsic@1.2.0: - resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} - dependencies: - function-bind: 1.1.1 - has: 1.0.3 - has-symbols: 1.0.3 - dev: true + get-port@7.1.0: {} - /get-stream@5.2.0: - resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} - engines: {node: '>=8'} + get-stream@5.2.0: dependencies: pump: 3.0.0 - dev: true - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - - /get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - - /get-symbol-description@1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} - engines: {node: '>= 0.4'} + get-tsconfig@4.7.5: dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.0 - dev: true - - /github-from-package@0.0.0: - resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + resolve-pkg-maps: 1.0.0 - /github-slugger@2.0.0: - resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + github-slugger@2.0.0: {} - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} + glob-parent@6.0.2: dependencies: is-glob: 4.0.3 - dev: false - - /glob@7.1.6: - resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: false - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + glob@10.4.5: dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} + globals@14.0.0: {} - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.0 - dev: true + globals@16.3.0: {} - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} + globby@11.1.0: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 - fast-glob: 3.3.1 + fast-glob: 3.3.2 ignore: 5.2.4 merge2: 1.4.1 slash: 3.0.0 - dev: true - /globby@6.1.0: - resolution: {integrity: sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==} - engines: {node: '>=0.10.0'} - dependencies: - array-union: 1.0.2 - glob: 7.2.3 - object-assign: 4.1.1 - pify: 2.3.0 - pinkie-promise: 2.0.1 - dev: true - - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + got@11.8.6: dependencies: - get-intrinsic: 1.2.0 - dev: true + '@sindresorhus/is': 4.6.0 + '@szmarczak/http-timer': 4.0.6 + '@types/cacheable-request': 6.0.3 + '@types/responselike': 1.0.3 + cacheable-lookup: 5.0.4 + cacheable-request: 7.0.4 + decompress-response: 6.0.0 + http2-wrapper: 1.0.3 + lowercase-keys: 2.0.0 + p-cancelable: 2.1.1 + responselike: 2.0.1 - /graceful-fs@4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + graceful-fs@4.2.10: {} - /grapheme-splitter@1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - dev: true + graphemer@1.4.0: {} - /gray-matter@4.0.3: - resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} - engines: {node: '>=6.0'} + h3@1.15.1: dependencies: - js-yaml: 3.14.1 - kind-of: 6.0.3 - section-matter: 1.0.0 - strip-bom-string: 1.0.0 - - /hard-rejection@2.1.0: - resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} - engines: {node: '>=6'} - dev: true - - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} + cookie-es: 1.2.2 + crossws: 0.3.4 + defu: 6.1.4 + destr: 2.0.3 + iron-webcrypto: 1.2.1 + node-mock-http: 1.0.0 + radix3: 1.1.2 + ufo: 1.5.4 + uncrypto: 0.1.3 - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true + has-flag@4.0.0: {} - /has-property-descriptors@1.0.0: - resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + hast-util-embedded@3.0.0: dependencies: - get-intrinsic: 1.2.0 - dev: true - - /has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} - engines: {node: '>= 0.4'} - dev: true + '@types/hast': 3.0.4 + hast-util-is-element: 3.0.0 - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: true + hast-util-from-html@2.0.3: + dependencies: + '@types/hast': 3.0.4 + devlop: 1.1.0 + hast-util-from-parse5: 8.0.1 + parse5: 7.1.2 + vfile: 6.0.3 + vfile-message: 4.0.2 - /has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} + hast-util-from-parse5@8.0.1: dependencies: - has-symbols: 1.0.3 - dev: true + '@types/hast': 3.0.4 + '@types/unist': 3.0.0 + devlop: 1.1.0 + hastscript: 8.0.0 + property-information: 6.2.0 + vfile: 6.0.3 + vfile-location: 5.0.2 + web-namespaces: 2.0.1 - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} + hast-util-has-property@3.0.0: dependencies: - function-bind: 1.1.1 + '@types/hast': 3.0.4 - /hast-util-from-html@1.0.2: - resolution: {integrity: sha512-LhrTA2gfCbLOGJq2u/asp4kwuG0y6NhWTXiPKP+n0qNukKy7hc10whqqCFfyvIA1Q5U5d0sp9HhNim9gglEH4A==} + hast-util-is-body-ok-link@3.0.0: dependencies: - '@types/hast': 2.3.4 - hast-util-from-parse5: 7.1.2 - parse5: 7.1.2 - vfile: 5.3.7 - vfile-message: 3.1.4 - dev: true + '@types/hast': 3.0.4 - /hast-util-from-parse5@7.1.2: - resolution: {integrity: sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==} + hast-util-is-element@3.0.0: dependencies: - '@types/hast': 2.3.4 - '@types/unist': 2.0.6 - hastscript: 7.2.0 - property-information: 6.2.0 - vfile: 5.3.7 - vfile-location: 4.1.0 - web-namespaces: 2.0.1 + '@types/hast': 3.0.4 - /hast-util-has-property@2.0.1: - resolution: {integrity: sha512-X2+RwZIMTMKpXUzlotatPzWj8bspCymtXH3cfG3iQKV+wPF53Vgaqxi/eLqGck0wKq1kS9nvoB1wchbCPEL8sg==} - dev: false + hast-util-parse-selector@4.0.0: + dependencies: + '@types/hast': 3.0.4 - /hast-util-parse-selector@3.1.1: - resolution: {integrity: sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==} + hast-util-phrasing@3.0.1: dependencies: - '@types/hast': 2.3.4 + '@types/hast': 3.0.4 + 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 - /hast-util-raw@7.2.3: - resolution: {integrity: sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==} + hast-util-raw@9.0.1: dependencies: - '@types/hast': 2.3.4 - '@types/parse5': 6.0.3 - hast-util-from-parse5: 7.1.2 - hast-util-to-parse5: 7.1.0 - html-void-elements: 2.0.1 - parse5: 6.0.1 - unist-util-position: 4.0.4 - unist-util-visit: 4.1.2 - vfile: 5.3.7 + '@types/hast': 3.0.4 + '@types/unist': 3.0.0 + '@ungap/structured-clone': 1.2.0 + hast-util-from-parse5: 8.0.1 + hast-util-to-parse5: 8.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.0.2 + parse5: 7.1.2 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 web-namespaces: 2.0.1 zwitch: 2.0.4 - /hast-util-select@5.0.5: - resolution: {integrity: sha512-QQhWMhgTFRhCaQdgTKzZ5g31GLQ9qRb1hZtDPMqQaOhpLBziWcshUS0uCR5IJ0U1jrK/mxg35fmcq+Dp/Cy2Aw==} + hast-util-select@6.0.2: dependencies: - '@types/hast': 2.3.4 - '@types/unist': 2.0.6 + '@types/hast': 3.0.4 + '@types/unist': 3.0.0 bcp-47-match: 2.0.3 comma-separated-tokens: 2.0.3 - css-selector-parser: 1.4.1 + css-selector-parser: 3.0.2 + devlop: 1.1.0 direction: 2.0.1 - hast-util-has-property: 2.0.1 - hast-util-to-string: 2.0.0 - hast-util-whitespace: 2.0.1 + hast-util-has-property: 3.0.0 + hast-util-to-string: 3.0.0 + hast-util-whitespace: 3.0.0 not: 0.1.0 nth-check: 2.1.1 property-information: 6.2.0 space-separated-tokens: 2.0.2 - unist-util-visit: 4.1.2 + unist-util-visit: 5.0.0 zwitch: 2.0.4 - dev: false - /hast-util-to-estree@2.3.2: - resolution: {integrity: sha512-YYDwATNdnvZi3Qi84iatPIl1lWpXba1MeNrNbDfJfVzEBZL8uUmtR7mt7bxKBC8kuAuvb0bkojXYZzsNHyHCLg==} + hast-util-to-estree@3.1.0: dependencies: - '@types/estree': 1.0.0 - '@types/estree-jsx': 1.0.0 - '@types/hast': 2.3.4 - '@types/unist': 2.0.6 + '@types/estree': 1.0.6 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 - estree-util-attach-comments: 2.1.1 - estree-util-is-identifier-name: 2.1.0 - hast-util-whitespace: 2.0.1 - mdast-util-mdx-expression: 1.3.2 - mdast-util-mdxjs-esm: 1.3.1 + devlop: 1.1.0 + estree-util-attach-comments: 3.0.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.1.3 + mdast-util-mdxjs-esm: 2.0.1 property-information: 6.2.0 space-separated-tokens: 2.0.2 - style-to-object: 0.4.1 - unist-util-position: 4.0.4 + style-to-object: 0.4.4 + unist-util-position: 5.0.0 zwitch: 2.0.4 transitivePeerDependencies: - supports-color - dev: false - /hast-util-to-html@8.0.4: - resolution: {integrity: sha512-4tpQTUOr9BMjtYyNlt0P50mH7xj0Ks2xpo8M943Vykljf99HW6EzulIoJP1N3eKOSScEHzyzi9dm7/cn0RfGwA==} + hast-util-to-html@9.0.5: dependencies: - '@types/hast': 2.3.4 - '@types/unist': 2.0.6 + '@types/hast': 3.0.4 + '@types/unist': 3.0.0 ccount: 2.0.1 comma-separated-tokens: 2.0.3 - hast-util-raw: 7.2.3 - hast-util-whitespace: 2.0.1 - html-void-elements: 2.0.1 - property-information: 6.2.0 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.0.2 + property-information: 7.0.0 space-separated-tokens: 2.0.2 stringify-entities: 4.0.3 zwitch: 2.0.4 - /hast-util-to-parse5@7.1.0: - resolution: {integrity: sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==} + hast-util-to-jsx-runtime@2.3.2: + dependencies: + '@types/estree': 1.0.6 + '@types/hast': 3.0.4 + '@types/unist': 3.0.0 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.1.3 + mdast-util-mdxjs-esm: 2.0.1 + property-information: 6.2.0 + space-separated-tokens: 2.0.2 + style-to-object: 1.0.8 + unist-util-position: 5.0.0 + vfile-message: 4.0.2 + transitivePeerDependencies: + - supports-color + + hast-util-to-parse5@8.0.0: dependencies: - '@types/hast': 2.3.4 + '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 + devlop: 1.1.0 property-information: 6.2.0 space-separated-tokens: 2.0.2 web-namespaces: 2.0.1 zwitch: 2.0.4 - /hast-util-to-string@2.0.0: - resolution: {integrity: sha512-02AQ3vLhuH3FisaMM+i/9sm4OXGSq1UhOOCpTLLQtHdL3tZt7qil69r8M8iDkZYyC0HCFylcYoP+8IO7ddta1A==} + hast-util-to-string@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-to-text@4.0.2: dependencies: - '@types/hast': 2.3.4 + '@types/hast': 3.0.4 + '@types/unist': 3.0.0 + hast-util-is-element: 3.0.0 + unist-util-find-after: 5.0.0 - /hast-util-whitespace@2.0.1: - resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 - /hastscript@7.2.0: - resolution: {integrity: sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==} + hastscript@8.0.0: dependencies: - '@types/hast': 2.3.4 + '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 - hast-util-parse-selector: 3.1.1 + hast-util-parse-selector: 4.0.0 property-information: 6.2.0 space-separated-tokens: 2.0.2 - /hogan.js@3.0.2: - resolution: {integrity: sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==} - hasBin: true + hastscript@9.0.0: dependencies: - mkdirp: 0.3.0 - nopt: 1.0.10 - dev: true - - /hoopy@0.1.4: - resolution: {integrity: sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==} - engines: {node: '>= 6.0.0'} - dev: true + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 4.0.0 + property-information: 6.2.0 + space-separated-tokens: 2.0.2 - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true + html-escaper@2.0.2: {} - /html-escaper@2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - dev: true + html-escaper@3.0.3: {} - /html-escaper@3.0.3: - resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + html-void-elements@3.0.0: {} - /html-void-elements@2.0.1: - resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==} + html-whitespace-sensitive-tag-names@3.0.0: {} - /html_codesniffer@2.5.1: - resolution: {integrity: sha512-vcz0yAaX/OaV6sdNHuT9alBOKkSxYb8h5Yq26dUqgi7XmCgGUSa7U9PiY1PBXQFMjKv1wVPs5/QzHlGuxPDUGg==} - engines: {node: '>=6'} - dev: true + htmlparser2@10.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 6.0.0 - /htmlparser2@8.0.2: - resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} + htmlparser2@9.1.0: dependencies: domelementtype: 2.3.0 domhandler: 5.0.3 - domutils: 3.1.0 + domutils: 3.2.2 entities: 4.5.0 - dev: true - /http-cache-semantics@4.1.1: - resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + http-cache-semantics@4.1.1: {} - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} + http-errors@2.0.0: dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /human-id@1.0.2: - resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} - dev: true + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: true + http2-wrapper@1.0.3: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 - /human-signals@4.3.1: - resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} - engines: {node: '>=14.18.0'} - dev: false + human-id@1.0.2: {} - /human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} + i18next@23.11.5: + dependencies: + '@babel/runtime': 7.24.7 - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@5.2.4: {} - /ignore@5.2.4: - resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} - engines: {node: '>= 4'} - dev: true + ignore@7.0.5: {} - /import-meta-resolve@3.0.0: - resolution: {integrity: sha512-4IwhLhNNA8yy445rPjD/lWh++7hMDOml2eHtd58eG7h+qK3EryMuuRbsHGPikCoAgIkkDnckKfWSk2iDla/ejg==} + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true + import-meta-resolve@4.1.0: {} - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 + imurmurhash@0.1.4: {} - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + inherits@2.0.4: {} - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + inline-style-parser@0.1.1: {} - /inline-style-parser@0.1.1: - resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} - dev: false + inline-style-parser@0.2.4: {} - /internal-slot@1.0.5: - resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.0 - has: 1.0.3 - side-channel: 1.0.4 - dev: true + iron-webcrypto@1.2.1: {} - /is-alphabetical@2.0.1: - resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} - dev: false + is-absolute-url@4.0.1: {} - /is-alphanumerical@2.0.1: - resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + is-alphabetical@2.0.1: {} + + is-alphanumerical@2.0.1: dependencies: is-alphabetical: 2.0.1 is-decimal: 2.0.1 - dev: false - /is-array-buffer@3.0.2: - resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.0 - is-typed-array: 1.1.10 - dev: true + is-arrayish@0.3.2: {} - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true + is-decimal@2.0.1: {} - /is-arrayish@0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-docker@3.0.0: {} - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - dev: true + is-extglob@2.1.1: {} - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.2.0 + is-fullwidth-code-point@3.0.0: {} - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} + is-glob@4.0.3: dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: true + is-extglob: 2.1.1 - /is-buffer@2.0.5: - resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} - engines: {node: '>=4'} + is-gzip@2.0.0: {} - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: true + is-hexadecimal@2.0.1: {} - /is-ci@3.0.1: - resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} - hasBin: true + is-inside-container@1.0.0: dependencies: - ci-info: 3.8.0 - dev: true + is-docker: 3.0.0 - /is-core-module@2.13.0: - resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} - dependencies: - has: 1.0.3 + is-number@7.0.0: {} - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true + is-plain-obj@4.1.0: {} - /is-decimal@2.0.1: - resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - dev: false + is-subdir@1.2.0: + dependencies: + better-path-resolve: 1.0.0 - /is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true + is-windows@1.0.2: {} - /is-extendable@0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} + isexe@2.0.0: {} - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} + istanbul-lib-coverage@3.2.2: {} - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + istanbul-lib-report@3.0.1: dependencies: - is-extglob: 2.1.1 - - /is-hexadecimal@2.0.1: - resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} - dev: false - - /is-interactive@2.0.0: - resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} - engines: {node: '>=12'} + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 - /is-negative-zero@2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} - engines: {node: '>= 0.4'} - dev: true + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + debug: 4.4.0 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} + istanbul-reports@3.1.7: dependencies: - has-tostringtag: 1.0.0 - dev: true + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 - /is-plain-obj@1.1.0: - resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} - engines: {node: '>=0.10.0'} - dev: true + jiti@1.21.0: {} - /is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} + jiti@2.4.2: {} - /is-reference@3.0.1: - resolution: {integrity: sha512-baJJdQLiYaJdvFbJqXrcGv3WU3QCzBlUcI5QhbesIm6/xPsvmO+2CDoi/GMOFBQEQm+PXkwOPrp9KK5ozZsp2w==} + js-yaml@3.14.1: dependencies: - '@types/estree': 1.0.0 - dev: false + argparse: 1.0.10 + esprima: 4.0.1 - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} + js-yaml@4.1.0: dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: true + argparse: 2.0.1 - /is-shared-array-buffer@1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} - dependencies: - call-bind: 1.0.2 - dev: true + json-buffer@3.0.1: {} - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true + json-schema-traverse@0.4.1: {} - /is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + json-schema-traverse@1.0.0: {} - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true + json-stable-stringify-without-jsonify@1.0.1: {} - /is-subdir@1.2.0: - resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} - engines: {node: '>=4'} - dependencies: - better-path-resolve: 1.0.0 - dev: true + jsonc-parser@2.3.1: {} - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} + jsonc-parser@3.3.1: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.10 + + junit-report-builder@5.1.1: dependencies: - has-symbols: 1.0.3 - dev: true + lodash: 4.17.21 + make-dir: 3.1.0 + xmlbuilder: 15.1.1 - /is-typed-array@1.1.10: - resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} - engines: {node: '>= 0.4'} + keyv@4.5.4: dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - dev: true + json-buffer: 3.0.1 - /is-unicode-supported@1.3.0: - resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} - engines: {node: '>=12'} + kleur@3.0.3: {} - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.2 - dev: true + kleur@4.1.5: {} - /is-windows@1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - dev: true + klona@2.0.6: {} - /is-wsl@3.0.0: - resolution: {integrity: sha512-TQ7xXW/fTBaz/HhGSV779AC99ocpvb9qJPuPwyIea+F+Z+htcQ1wouAA0xEQaa4saVqyP8mwkoYp5efeM/4Gbg==} - engines: {node: '>=16'} + levn@0.4.1: dependencies: - is-docker: 3.0.0 + prelude-ls: 1.2.1 + type-check: 0.4.0 - /is@3.3.0: - resolution: {integrity: sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==} - dev: true + lightningcss-darwin-arm64@1.29.2: + optional: true - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + lightningcss-darwin-arm64@1.29.3: + optional: true - /istanbul-lib-coverage@3.2.0: - resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} - engines: {node: '>=8'} - dev: true + lightningcss-darwin-x64@1.29.2: + optional: true - /istanbul-lib-report@3.0.0: - resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} - engines: {node: '>=8'} - dependencies: - istanbul-lib-coverage: 3.2.0 - make-dir: 3.1.0 - supports-color: 7.2.0 - dev: true + lightningcss-darwin-x64@1.29.3: + optional: true - /istanbul-lib-source-maps@4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} - engines: {node: '>=10'} - dependencies: - debug: 4.3.4 - istanbul-lib-coverage: 3.2.0 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - dev: true + lightningcss-freebsd-x64@1.29.2: + optional: true - /istanbul-reports@3.1.5: - resolution: {integrity: sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==} - engines: {node: '>=8'} - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.0 - dev: true + lightningcss-freebsd-x64@1.29.3: + optional: true - /jiti@1.19.1: - resolution: {integrity: sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==} - hasBin: true - dev: false + lightningcss-linux-arm-gnueabihf@1.29.2: + optional: true - /joi@17.9.2: - resolution: {integrity: sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==} - dependencies: - '@hapi/hoek': 9.3.0 - '@hapi/topo': 5.1.0 - '@sideway/address': 4.1.4 - '@sideway/formula': 3.0.1 - '@sideway/pinpoint': 2.0.0 - dev: true + lightningcss-linux-arm-gnueabihf@1.29.3: + optional: true - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + lightningcss-linux-arm64-gnu@1.29.2: + optional: true - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 + lightningcss-linux-arm64-gnu@1.29.3: + optional: true - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 + lightningcss-linux-arm64-musl@1.29.2: + optional: true - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true + lightningcss-linux-arm64-musl@1.29.3: + optional: true - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true + lightningcss-linux-x64-gnu@1.29.2: + optional: true - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true + lightningcss-linux-x64-gnu@1.29.3: + optional: true - /jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + lightningcss-linux-x64-musl@1.29.2: + optional: true - /jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - optionalDependencies: - graceful-fs: 4.2.10 - dev: true + lightningcss-linux-x64-musl@1.29.3: + optional: true - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} + lightningcss-win32-arm64-msvc@1.29.2: + optional: true - /kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} + lightningcss-win32-arm64-msvc@1.29.3: + optional: true - /kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} + lightningcss-win32-x64-msvc@1.29.2: + optional: true - /lazy-ass@1.6.0: - resolution: {integrity: sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==} - engines: {node: '> 0.8'} - dev: true + lightningcss-win32-x64-msvc@1.29.3: + optional: true - /lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} + lightningcss@1.29.2: + dependencies: + detect-libc: 2.0.3 + optionalDependencies: + lightningcss-darwin-arm64: 1.29.2 + lightningcss-darwin-x64: 1.29.2 + lightningcss-freebsd-x64: 1.29.2 + lightningcss-linux-arm-gnueabihf: 1.29.2 + lightningcss-linux-arm64-gnu: 1.29.2 + lightningcss-linux-arm64-musl: 1.29.2 + lightningcss-linux-x64-gnu: 1.29.2 + lightningcss-linux-x64-musl: 1.29.2 + lightningcss-win32-arm64-msvc: 1.29.2 + lightningcss-win32-x64-msvc: 1.29.2 + + lightningcss@1.29.3: + dependencies: + detect-libc: 2.0.3 + optionalDependencies: + lightningcss-darwin-arm64: 1.29.3 + lightningcss-darwin-x64: 1.29.3 + lightningcss-freebsd-x64: 1.29.3 + lightningcss-linux-arm-gnueabihf: 1.29.3 + lightningcss-linux-arm64-gnu: 1.29.3 + lightningcss-linux-arm64-musl: 1.29.3 + lightningcss-linux-x64-gnu: 1.29.3 + lightningcss-linux-x64-musl: 1.29.3 + lightningcss-win32-arm64-msvc: 1.29.3 + lightningcss-win32-x64-msvc: 1.29.3 - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + lilconfig@3.1.2: {} - /load-yaml-file@0.2.0: - resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} - engines: {node: '>=6'} + linkedom@0.18.4: dependencies: - graceful-fs: 4.2.10 - js-yaml: 3.14.1 - pify: 4.0.1 - strip-bom: 3.0.0 + css-select: 5.1.0 + cssom: 0.5.0 + html-escaper: 3.0.3 + htmlparser2: 9.1.0 + uhyphen: 0.2.0 - /local-pkg@0.4.3: - resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} - engines: {node: '>=14'} - dev: true + lite-youtube-embed@0.3.3: {} - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} + locate-path@5.0.0: dependencies: p-locate: 4.1.0 - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - - /lodash.startcase@4.4.0: - resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true + lodash.merge@4.6.2: {} - /log-symbols@5.1.0: - resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} - engines: {node: '>=12'} - dependencies: - chalk: 5.3.0 - is-unicode-supported: 1.3.0 + lodash.startcase@4.4.0: {} - /longest-streak@3.1.0: - resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + lodash@4.17.21: {} - /loupe@2.3.6: - resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} - dependencies: - get-func-name: 2.0.0 - dev: true + longest-streak@3.1.0: {} - /lru-cache@4.1.5: - resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} - dependencies: - pseudomap: 1.0.2 - yallist: 2.1.2 - dev: true + loupe@3.1.2: {} - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 + loupe@3.1.3: {} - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 + lowercase-keys@2.0.0: {} - /magic-string@0.30.3: - resolution: {integrity: sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 + lru-cache@10.4.3: {} - /make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} + lru-cache@4.1.5: dependencies: - semver: 6.3.1 - dev: true - - /map-obj@1.0.1: - resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} - engines: {node: '>=0.10.0'} - dev: true - - /map-obj@4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} - engines: {node: '>=8'} - dev: true + pseudomap: 1.0.2 + yallist: 2.1.2 - /map-stream@0.1.0: - resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} - dev: true + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 - /markdown-extensions@1.1.1: - resolution: {integrity: sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==} - engines: {node: '>=0.10.0'} - dev: false + magicast@0.3.5: + dependencies: + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 + source-map-js: 1.2.1 - /markdown-table@3.0.3: - resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + make-dir@3.1.0: + dependencies: + semver: 6.3.1 - /mdast-util-definitions@5.1.2: - resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==} + make-dir@4.0.0: dependencies: - '@types/mdast': 3.0.11 - '@types/unist': 2.0.6 - unist-util-visit: 4.1.2 + semver: 7.7.1 - /mdast-util-definitions@6.0.0: - resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==} + markdown-extensions@2.0.0: {} + + markdown-table@3.0.3: {} + + mdast-util-definitions@6.0.0: dependencies: - '@types/mdast': 4.0.1 + '@types/mdast': 4.0.4 '@types/unist': 3.0.0 unist-util-visit: 5.0.0 - /mdast-util-directive@2.2.4: - resolution: {integrity: sha512-sK3ojFP+jpj1n7Zo5ZKvoxP1MvLyzVG63+gm40Z/qI00avzdPCYxt7RBMgofwAva9gBjbDBWVRB/i+UD+fUCzQ==} + mdast-util-directive@3.0.0: dependencies: - '@types/mdast': 3.0.11 - '@types/unist': 2.0.6 - mdast-util-from-markdown: 1.3.0 - mdast-util-to-markdown: 1.5.0 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.0 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 parse-entities: 4.0.1 stringify-entities: 4.0.3 - unist-util-visit-parents: 5.1.3 + unist-util-visit-parents: 6.0.1 transitivePeerDependencies: - supports-color - dev: false - /mdast-util-find-and-replace@2.2.2: - resolution: {integrity: sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==} + mdast-util-find-and-replace@3.0.1: dependencies: - '@types/mdast': 3.0.11 + '@types/mdast': 4.0.4 escape-string-regexp: 5.0.0 - unist-util-is: 5.2.1 - unist-util-visit-parents: 5.1.3 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 - /mdast-util-from-markdown@1.3.0: - resolution: {integrity: sha512-HN3W1gRIuN/ZW295c7zi7g9lVBllMgZE40RxCX37wrTPWXCWtpvOZdfnuK+1WNpvZje6XuJeI3Wnb4TJEUem+g==} + mdast-util-from-markdown@2.0.0: dependencies: - '@types/mdast': 3.0.11 - '@types/unist': 2.0.6 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.0 decode-named-character-reference: 1.0.2 - mdast-util-to-string: 3.1.1 - micromark: 3.1.0 - micromark-util-decode-numeric-character-reference: 1.0.0 - micromark-util-decode-string: 1.0.2 - micromark-util-normalize-identifier: 1.0.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - unist-util-stringify-position: 3.0.3 - uvu: 0.5.6 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-decode-string: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-stringify-position: 4.0.0 transitivePeerDependencies: - supports-color - /mdast-util-gfm-autolink-literal@1.0.3: - resolution: {integrity: sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==} + mdast-util-gfm-autolink-literal@2.0.0: dependencies: - '@types/mdast': 3.0.11 + '@types/mdast': 4.0.4 ccount: 2.0.1 - mdast-util-find-and-replace: 2.2.2 - micromark-util-character: 1.1.0 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.1 + micromark-util-character: 2.0.1 - /mdast-util-gfm-footnote@1.0.2: - resolution: {integrity: sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==} + mdast-util-gfm-footnote@2.0.0: dependencies: - '@types/mdast': 3.0.11 - mdast-util-to-markdown: 1.5.0 - micromark-util-normalize-identifier: 1.0.0 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + micromark-util-normalize-identifier: 2.0.0 + transitivePeerDependencies: + - supports-color - /mdast-util-gfm-strikethrough@1.0.3: - resolution: {integrity: sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==} + mdast-util-gfm-strikethrough@2.0.0: dependencies: - '@types/mdast': 3.0.11 - mdast-util-to-markdown: 1.5.0 + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color - /mdast-util-gfm-table@1.0.7: - resolution: {integrity: sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==} + mdast-util-gfm-table@2.0.0: dependencies: - '@types/mdast': 3.0.11 + '@types/mdast': 4.0.4 + devlop: 1.1.0 markdown-table: 3.0.3 - mdast-util-from-markdown: 1.3.0 - mdast-util-to-markdown: 1.5.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - /mdast-util-gfm-task-list-item@1.0.2: - resolution: {integrity: sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==} + mdast-util-gfm-task-list-item@2.0.0: dependencies: - '@types/mdast': 3.0.11 - mdast-util-to-markdown: 1.5.0 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color - /mdast-util-gfm@2.0.2: - resolution: {integrity: sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==} + mdast-util-gfm@3.0.0: dependencies: - mdast-util-from-markdown: 1.3.0 - mdast-util-gfm-autolink-literal: 1.0.3 - mdast-util-gfm-footnote: 1.0.2 - mdast-util-gfm-strikethrough: 1.0.3 - mdast-util-gfm-table: 1.0.7 - mdast-util-gfm-task-list-item: 1.0.2 - mdast-util-to-markdown: 1.5.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-gfm-autolink-literal: 2.0.0 + mdast-util-gfm-footnote: 2.0.0 + mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - /mdast-util-mdx-expression@1.3.2: - resolution: {integrity: sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==} + mdast-util-mdx-expression@2.0.1: dependencies: - '@types/estree-jsx': 1.0.0 - '@types/hast': 2.3.4 - '@types/mdast': 3.0.11 - mdast-util-from-markdown: 1.3.0 - mdast-util-to-markdown: 1.5.0 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - dev: false - /mdast-util-mdx-jsx@2.1.2: - resolution: {integrity: sha512-o9vBCYQK5ZLGEj3tCGISJGjvafyHRVJlZmfJzSE7xjiogSzIeph/Z4zMY65q4WGRMezQBeAwPlrdymDYYYx0tA==} + mdast-util-mdx-jsx@3.1.3: dependencies: - '@types/estree-jsx': 1.0.0 - '@types/hast': 2.3.4 - '@types/mdast': 3.0.11 - '@types/unist': 2.0.6 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.0 ccount: 2.0.1 - mdast-util-from-markdown: 1.3.0 - mdast-util-to-markdown: 1.5.0 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 parse-entities: 4.0.1 stringify-entities: 4.0.3 - unist-util-remove-position: 4.0.2 - unist-util-stringify-position: 3.0.3 - vfile-message: 3.1.4 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.2 transitivePeerDependencies: - supports-color - dev: false - /mdast-util-mdx@2.0.1: - resolution: {integrity: sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw==} + mdast-util-mdx@3.0.0: dependencies: - mdast-util-from-markdown: 1.3.0 - mdast-util-mdx-expression: 1.3.2 - mdast-util-mdx-jsx: 2.1.2 - mdast-util-mdxjs-esm: 1.3.1 - mdast-util-to-markdown: 1.5.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.1.3 + mdast-util-mdxjs-esm: 2.0.1 + mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - dev: false - /mdast-util-mdxjs-esm@1.3.1: - resolution: {integrity: sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w==} + mdast-util-mdxjs-esm@2.0.1: dependencies: - '@types/estree-jsx': 1.0.0 - '@types/hast': 2.3.4 - '@types/mdast': 3.0.11 - mdast-util-from-markdown: 1.3.0 - mdast-util-to-markdown: 1.5.0 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - dev: false - /mdast-util-phrasing@3.0.1: - resolution: {integrity: sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==} + mdast-util-phrasing@4.0.0: dependencies: - '@types/mdast': 3.0.11 - unist-util-is: 5.2.1 + '@types/mdast': 4.0.4 + unist-util-is: 6.0.0 - /mdast-util-to-hast@12.3.0: - resolution: {integrity: sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==} + mdast-util-to-hast@13.0.2: dependencies: - '@types/hast': 2.3.4 - '@types/mdast': 3.0.11 - mdast-util-definitions: 5.1.2 - micromark-util-sanitize-uri: 1.1.0 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.2.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.0 trim-lines: 3.0.1 - unist-util-generated: 2.0.1 - unist-util-position: 4.0.4 - unist-util-visit: 4.1.2 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 - /mdast-util-to-markdown@1.5.0: - resolution: {integrity: sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==} + mdast-util-to-markdown@2.1.0: dependencies: - '@types/mdast': 3.0.11 - '@types/unist': 2.0.6 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.0 longest-streak: 3.1.0 - mdast-util-phrasing: 3.0.1 - mdast-util-to-string: 3.1.1 - micromark-util-decode-string: 1.0.2 - unist-util-visit: 4.1.2 + mdast-util-phrasing: 4.0.0 + mdast-util-to-string: 4.0.0 + micromark-util-decode-string: 2.0.0 + unist-util-visit: 5.0.0 zwitch: 2.0.4 - /mdast-util-to-string@3.1.1: - resolution: {integrity: sha512-tGvhT94e+cVnQt8JWE9/b3cUQZWS732TJxXHktvP+BYo62PpYD53Ls/6cC60rW21dW+txxiM4zMdc6abASvZKA==} + mdast-util-to-string@4.0.0: dependencies: - '@types/mdast': 3.0.11 + '@types/mdast': 4.0.4 - /meow@6.1.1: - resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} - engines: {node: '>=8'} - dependencies: - '@types/minimist': 1.2.2 - camelcase-keys: 6.2.2 - decamelize-keys: 1.1.1 - hard-rejection: 2.1.0 - minimist-options: 4.1.0 - normalize-package-data: 2.5.0 - read-pkg-up: 7.0.1 - redent: 3.0.0 - trim-newlines: 3.0.1 - type-fest: 0.13.1 - yargs-parser: 18.1.3 - dev: true - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} + merge2@1.4.1: {} - /micromark-core-commonmark@1.0.6: - resolution: {integrity: sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA==} + micromark-core-commonmark@2.0.0: dependencies: decode-named-character-reference: 1.0.2 - micromark-factory-destination: 1.0.0 - micromark-factory-label: 1.0.2 - micromark-factory-space: 1.0.0 - micromark-factory-title: 1.0.2 - micromark-factory-whitespace: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-chunked: 1.0.0 - micromark-util-classify-character: 1.0.0 - micromark-util-html-tag-name: 1.1.0 - micromark-util-normalize-identifier: 1.0.0 - micromark-util-resolve-all: 1.0.0 - micromark-util-subtokenize: 1.0.2 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - - /micromark-extension-directive@2.1.2: - resolution: {integrity: sha512-brqLEztt14/73snVXYsq9Cv6ng67O+Sy69ZuM0s8ZhN/GFI9rnyXyj0Y0DaCwi648vCImv7/U1H5TzR7wMv5jw==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-factory-whitespace: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 + devlop: 1.1.0 + micromark-factory-destination: 2.0.0 + micromark-factory-label: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-factory-title: 2.0.0 + micromark-factory-whitespace: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-chunked: 2.0.0 + micromark-util-classify-character: 2.0.0 + micromark-util-html-tag-name: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-subtokenize: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-extension-directive@3.0.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-factory-whitespace: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 parse-entities: 4.0.1 - uvu: 0.5.6 - dev: false - - /micromark-extension-gfm-autolink-literal@1.0.3: - resolution: {integrity: sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-sanitize-uri: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - - /micromark-extension-gfm-footnote@1.0.4: - resolution: {integrity: sha512-E/fmPmDqLiMUP8mLJ8NbJWJ4bTw6tS+FEQS8CcuDtZpILuOb2kjLqPEeAePF1djXROHXChM/wPJw0iS4kHCcIg==} - dependencies: - micromark-core-commonmark: 1.0.6 - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-normalize-identifier: 1.0.0 - micromark-util-sanitize-uri: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - - /micromark-extension-gfm-strikethrough@1.0.4: - resolution: {integrity: sha512-/vjHU/lalmjZCT5xt7CcHVJGq8sYRm80z24qAKXzaHzem/xsDYb2yLL+NNVbYvmpLx3O7SYPuGL5pzusL9CLIQ==} - dependencies: - micromark-util-chunked: 1.0.0 - micromark-util-classify-character: 1.0.0 - micromark-util-resolve-all: 1.0.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - - /micromark-extension-gfm-table@1.0.5: - resolution: {integrity: sha512-xAZ8J1X9W9K3JTJTUL7G6wSKhp2ZYHrFk5qJgY/4B33scJzE2kpfRL6oiw/veJTbt7jiM/1rngLlOKPWr1G+vg==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - - /micromark-extension-gfm-tagfilter@1.0.1: - resolution: {integrity: sha512-Ty6psLAcAjboRa/UKUbbUcwjVAv5plxmpUTy2XC/3nJFL37eHej8jrHrRzkqcpipJliuBH30DTs7+3wqNcQUVA==} - dependencies: - micromark-util-types: 1.0.2 - - /micromark-extension-gfm-task-list-item@1.0.3: - resolution: {integrity: sha512-PpysK2S1Q/5VXi72IIapbi/jliaiOFzv7THH4amwXeYXLq3l1uo8/2Be0Ac1rEwK20MQEsGH2ltAZLNY2KI/0Q==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - - /micromark-extension-gfm@2.0.1: - resolution: {integrity: sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA==} - dependencies: - micromark-extension-gfm-autolink-literal: 1.0.3 - micromark-extension-gfm-footnote: 1.0.4 - micromark-extension-gfm-strikethrough: 1.0.4 - micromark-extension-gfm-table: 1.0.5 - micromark-extension-gfm-tagfilter: 1.0.1 - micromark-extension-gfm-task-list-item: 1.0.3 - micromark-util-combine-extensions: 1.0.0 - micromark-util-types: 1.0.2 - - /micromark-extension-mdx-expression@1.0.4: - resolution: {integrity: sha512-TCgLxqW6ReQ3AJgtj1P0P+8ZThBTloLbeb7jNaqr6mCOLDpxUiBFE/9STgooMZttEwOQu5iEcCCa3ZSDhY9FGw==} - dependencies: - micromark-factory-mdx-expression: 1.0.7 - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-events-to-acorn: 1.2.1 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-mdx-jsx@1.0.3: - resolution: {integrity: sha512-VfA369RdqUISF0qGgv2FfV7gGjHDfn9+Qfiv5hEwpyr1xscRj/CiVRkU7rywGFCO7JwJ5L0e7CJz60lY52+qOA==} - dependencies: - '@types/acorn': 4.0.6 - estree-util-is-identifier-name: 2.1.0 - micromark-factory-mdx-expression: 1.0.7 - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - vfile-message: 3.1.4 - dev: false - - /micromark-extension-mdx-md@1.0.0: - resolution: {integrity: sha512-xaRAMoSkKdqZXDAoSgp20Azm0aRQKGOl0RrS81yGu8Hr/JhMsBmfs4wR7m9kgVUIO36cMUQjNyiyDKPrsv8gOw==} - dependencies: - micromark-util-types: 1.0.2 - dev: false - - /micromark-extension-mdxjs-esm@1.0.3: - resolution: {integrity: sha512-2N13ol4KMoxb85rdDwTAC6uzs8lMX0zeqpcyx7FhS7PxXomOnLactu8WI8iBNXW8AVyea3KIJd/1CKnUmwrK9A==} - dependencies: - micromark-core-commonmark: 1.0.6 - micromark-util-character: 1.1.0 - micromark-util-events-to-acorn: 1.2.1 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - unist-util-position-from-estree: 1.1.2 - uvu: 0.5.6 - vfile-message: 3.1.4 - dev: false - - /micromark-extension-mdxjs@1.0.0: - resolution: {integrity: sha512-TZZRZgeHvtgm+IhtgC2+uDMR7h8eTKF0QUX9YsgoL9+bADBpBY6SiLvWqnBlLbCEevITmTqmEuY3FoxMKVs1rQ==} - dependencies: - acorn: 8.10.0 - acorn-jsx: 5.3.2(acorn@8.10.0) - micromark-extension-mdx-expression: 1.0.4 - micromark-extension-mdx-jsx: 1.0.3 - micromark-extension-mdx-md: 1.0.0 - micromark-extension-mdxjs-esm: 1.0.3 - micromark-util-combine-extensions: 1.0.0 - micromark-util-types: 1.0.2 - dev: false - - /micromark-factory-destination@1.0.0: - resolution: {integrity: sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - - /micromark-factory-label@1.0.2: - resolution: {integrity: sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - - /micromark-factory-mdx-expression@1.0.7: - resolution: {integrity: sha512-QAdFbkQagTZ/eKb8zDGqmjvgevgJH3+aQpvvKrXWxNJp3o8/l2cAbbrBd0E04r0Gx6nssPpqWIjnbHFvZu5qsQ==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-events-to-acorn: 1.2.1 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - unist-util-position-from-estree: 1.1.2 - uvu: 0.5.6 - vfile-message: 3.1.4 - dev: false - - /micromark-factory-space@1.0.0: - resolution: {integrity: sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-types: 1.0.2 - - /micromark-factory-title@1.0.2: - resolution: {integrity: sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - - /micromark-factory-whitespace@1.0.0: - resolution: {integrity: sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - - /micromark-util-character@1.1.0: - resolution: {integrity: sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==} - dependencies: - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - - /micromark-util-chunked@1.0.0: - resolution: {integrity: sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==} - dependencies: - micromark-util-symbol: 1.0.1 - /micromark-util-classify-character@1.0.0: - resolution: {integrity: sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==} + micromark-extension-gfm-autolink-literal@2.0.0: dependencies: - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 + micromark-util-character: 2.0.1 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - /micromark-util-combine-extensions@1.0.0: - resolution: {integrity: sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==} + micromark-extension-gfm-footnote@2.0.0: dependencies: - micromark-util-chunked: 1.0.0 - micromark-util-types: 1.0.2 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - /micromark-util-decode-numeric-character-reference@1.0.0: - resolution: {integrity: sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==} + micromark-extension-gfm-strikethrough@2.0.0: dependencies: - micromark-util-symbol: 1.0.1 + devlop: 1.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-classify-character: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - /micromark-util-decode-string@1.0.2: - resolution: {integrity: sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q==} + micromark-extension-gfm-table@2.0.0: dependencies: - decode-named-character-reference: 1.0.2 - micromark-util-character: 1.1.0 - micromark-util-decode-numeric-character-reference: 1.0.0 - micromark-util-symbol: 1.0.1 + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - /micromark-util-encode@1.0.1: - resolution: {integrity: sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA==} - - /micromark-util-events-to-acorn@1.2.1: - resolution: {integrity: sha512-mkg3BaWlw6ZTkQORrKVBW4o9ICXPxLtGz51vml5mQpKFdo9vqIX68CAx5JhTOdjQyAHH7JFmm4rh8toSPQZUmg==} + micromark-extension-gfm-tagfilter@2.0.0: dependencies: - '@types/acorn': 4.0.6 - '@types/estree': 1.0.0 - estree-util-visit: 1.2.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - vfile-location: 4.1.0 - vfile-message: 3.1.4 - dev: false + micromark-util-types: 2.0.0 - /micromark-util-html-tag-name@1.1.0: - resolution: {integrity: sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA==} - - /micromark-util-normalize-identifier@1.0.0: - resolution: {integrity: sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==} + micromark-extension-gfm-task-list-item@2.0.1: dependencies: - micromark-util-symbol: 1.0.1 + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - /micromark-util-resolve-all@1.0.0: - resolution: {integrity: sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==} + micromark-extension-gfm@3.0.0: dependencies: - micromark-util-types: 1.0.2 + micromark-extension-gfm-autolink-literal: 2.0.0 + micromark-extension-gfm-footnote: 2.0.0 + micromark-extension-gfm-strikethrough: 2.0.0 + micromark-extension-gfm-table: 2.0.0 + micromark-extension-gfm-tagfilter: 2.0.0 + micromark-extension-gfm-task-list-item: 2.0.1 + micromark-util-combine-extensions: 2.0.0 + micromark-util-types: 2.0.0 - /micromark-util-sanitize-uri@1.1.0: - resolution: {integrity: sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg==} + micromark-extension-mdx-expression@3.0.0: dependencies: - micromark-util-character: 1.1.0 - micromark-util-encode: 1.0.1 - micromark-util-symbol: 1.0.1 + '@types/estree': 1.0.6 + devlop: 1.1.0 + micromark-factory-mdx-expression: 2.0.2 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - /micromark-util-subtokenize@1.0.2: - resolution: {integrity: sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==} + micromark-extension-mdx-jsx@3.0.1: dependencies: - micromark-util-chunked: 1.0.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - - /micromark-util-symbol@1.0.1: - resolution: {integrity: sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ==} + '@types/acorn': 4.0.6 + '@types/estree': 1.0.6 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + micromark-factory-mdx-expression: 2.0.2 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + vfile-message: 4.0.2 - /micromark-util-types@1.0.2: - resolution: {integrity: sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w==} + micromark-extension-mdx-md@2.0.0: + dependencies: + micromark-util-types: 2.0.0 - /micromark@3.1.0: - resolution: {integrity: sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA==} + micromark-extension-mdxjs-esm@3.0.0: dependencies: - '@types/debug': 4.1.7 - debug: 4.3.4 - decode-named-character-reference: 1.0.2 - micromark-core-commonmark: 1.0.6 - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-chunked: 1.0.0 - micromark-util-combine-extensions: 1.0.0 - micromark-util-decode-numeric-character-reference: 1.0.0 - micromark-util-encode: 1.0.1 - micromark-util-normalize-identifier: 1.0.0 - micromark-util-resolve-all: 1.0.0 - micromark-util-sanitize-uri: 1.1.0 - micromark-util-subtokenize: 1.0.2 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - transitivePeerDependencies: - - supports-color + '@types/estree': 1.0.6 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.2 - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} + micromark-extension-mdxjs@3.0.0: dependencies: - braces: 3.0.2 - picomatch: 2.3.1 + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + micromark-extension-mdx-expression: 3.0.0 + micromark-extension-mdx-jsx: 3.0.1 + micromark-extension-mdx-md: 2.0.0 + micromark-extension-mdxjs-esm: 3.0.0 + micromark-util-combine-extensions: 2.0.0 + micromark-util-types: 2.0.0 - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: true + micromark-factory-destination@2.0.0: + dependencies: + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} + micromark-factory-label@2.0.0: dependencies: - mime-db: 1.52.0 - dev: true + devlop: 1.1.0 + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - /mime@3.0.0: - resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} - engines: {node: '>=10.0.0'} - hasBin: true + micromark-factory-mdx-expression@2.0.2: + dependencies: + '@types/estree': 1.0.6 + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.2 - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} + micromark-factory-space@2.0.0: + dependencies: + micromark-util-character: 2.0.1 + micromark-util-types: 2.0.0 - /mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} + micromark-factory-title@2.0.0: + dependencies: + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - /mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} + micromark-factory-whitespace@2.0.0: + dependencies: + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - /min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: true + micromark-util-character@2.0.1: + dependencies: + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + micromark-util-chunked@2.0.0: dependencies: - brace-expansion: 1.1.11 + micromark-util-symbol: 2.0.0 - /minimist-options@4.1.0: - resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} - engines: {node: '>= 6'} + micromark-util-classify-character@2.0.0: dependencies: - arrify: 1.0.1 - is-plain-obj: 1.1.0 - kind-of: 6.0.3 - dev: true + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + micromark-util-combine-extensions@2.0.0: + dependencies: + micromark-util-chunked: 2.0.0 + micromark-util-types: 2.0.0 - /mixme@0.5.9: - resolution: {integrity: sha512-VC5fg6ySUscaWUpI4gxCBTQMH2RdUpNrk+MsbpCYtIvf9SBJdiUey4qE7BXviJsJR4nDQxCZ+3yaYNW3guz/Pw==} - engines: {node: '>= 8.0.0'} - dev: true + micromark-util-decode-numeric-character-reference@2.0.1: + dependencies: + micromark-util-symbol: 2.0.0 - /mkdirp-classic@0.5.3: - resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + micromark-util-decode-string@2.0.0: + dependencies: + decode-named-character-reference: 1.0.2 + micromark-util-character: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-symbol: 2.0.0 - /mkdirp@0.3.0: - resolution: {integrity: sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==} - deprecated: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.) - dev: true + micromark-util-encode@2.0.0: {} - /mlly@1.4.0: - resolution: {integrity: sha512-ua8PAThnTwpprIaU47EPeZ/bPUVp2QYBbWMphUQpVdBI3Lgqzm5KZQ45Agm3YJedHXaIHl6pBGabaLSUPPSptg==} + micromark-util-events-to-acorn@2.0.2: dependencies: - acorn: 8.10.0 - pathe: 1.1.1 - pkg-types: 1.0.3 - ufo: 1.1.2 - dev: true - - /mri@1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} + '@types/acorn': 4.0.6 + '@types/estree': 1.0.6 + '@types/unist': 3.0.0 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + vfile-message: 4.0.2 - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + micromark-util-html-tag-name@2.0.0: {} - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + micromark-util-normalize-identifier@2.0.0: + dependencies: + micromark-util-symbol: 2.0.0 - /mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + micromark-util-resolve-all@2.0.0: dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - dev: false + micromark-util-types: 2.0.0 - /nanoid@3.3.6: - resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true + micromark-util-sanitize-uri@2.0.0: + dependencies: + micromark-util-character: 2.0.1 + micromark-util-encode: 2.0.0 + micromark-util-symbol: 2.0.0 - /nanospinner@1.1.0: - resolution: {integrity: sha512-yFvNYMig4AthKYfHFl1sLj7B2nkHL4lzdig4osvl9/LdGbXwrdFRoqBS98gsEsOakr0yH+r5NZ/1Y9gdVB8trA==} + micromark-util-subtokenize@2.0.0: dependencies: - picocolors: 1.0.0 - dev: true + devlop: 1.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - /napi-build-utils@1.0.2: - resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + micromark-util-symbol@2.0.0: {} - /needle@2.9.1: - resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==} - engines: {node: '>= 4.4.x'} - hasBin: true + micromark-util-types@2.0.0: {} + + micromark@4.0.0: dependencies: - debug: 3.2.7 - iconv-lite: 0.4.24 - sax: 1.2.4 + '@types/debug': 4.1.12 + debug: 4.4.0 + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-chunked: 2.0.0 + micromark-util-combine-extensions: 2.0.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-encode: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-subtokenize: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 transitivePeerDependencies: - supports-color - /nlcst-to-string@3.1.1: - resolution: {integrity: sha512-63mVyqaqt0cmn2VcI2aH6kxe1rLAmSROqHMA0i4qqg1tidkfExgpb0FGMikMCn86mw5dFtBtEANfmSSK7TjNHw==} + micromatch@4.0.8: dependencies: - '@types/nlcst': 1.0.0 + braces: 3.0.3 + picomatch: 2.3.1 - /node-abi@3.45.0: - resolution: {integrity: sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==} - engines: {node: '>=10'} + mime-db@1.52.0: {} + + mime-types@2.1.35: dependencies: - semver: 7.5.4 + mime-db: 1.52.0 - /node-addon-api@6.1.0: - resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} + mimic-response@1.0.1: {} - /node-domexception@1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} - dev: true + mimic-response@3.1.0: {} - /node-fetch@2.6.10: - resolution: {integrity: sha512-5YytjUVbwzjE/BX4N62vnPPkGNxlJPwdA9/ArUc4pcM6cYS4Hinuv4VazzwjMGgnWuiQqcemOanib/5PpcsGug==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true + minimatch@3.1.2: dependencies: - whatwg-url: 5.0.0 - dev: true + brace-expansion: 1.1.12 - /node-fetch@3.3.1: - resolution: {integrity: sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + minimatch@9.0.5: dependencies: - data-uri-to-buffer: 4.0.1 - fetch-blob: 3.2.0 - formdata-polyfill: 4.0.10 - dev: true + brace-expansion: 2.0.1 - /node-releases@2.0.13: - resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} + minipass@7.1.2: {} - /node.extend@2.0.2: - resolution: {integrity: sha512-pDT4Dchl94/+kkgdwyS2PauDFjZG0Hk0IcHIB+LkW27HLDtdoeMxHTxZh39DYbPP8UflWXWj9JcdDozF+YDOpQ==} - engines: {node: '>=0.4.0'} - dependencies: - has: 1.0.3 - is: 3.3.0 - dev: true + mri@1.2.0: {} - /nopt@1.0.10: - resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} - hasBin: true - dependencies: - abbrev: 1.1.1 - dev: true + mrmime@2.0.1: {} - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.4 - semver: 5.7.1 - validate-npm-package-license: 3.0.4 - dev: true + ms@2.1.3: {} - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} + muggle-string@0.4.1: {} - /normalize-range@0.1.2: - resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} - engines: {node: '>=0.10.0'} - dev: false + mustache@4.2.0: {} - /not@0.1.0: - resolution: {integrity: sha512-5PDmaAsVfnWUgTUbJ3ERwn7u79Z0dYxN9ErxCpVJJqe2RK0PJ3z+iFUxuqjwtlDDegXvtWoxD/3Fzxox7tFGWA==} - dev: false + nanoid@3.3.11: {} - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} + nanospinner@1.1.0: dependencies: - path-key: 3.1.1 - dev: true + picocolors: 1.1.1 - /npm-run-path@5.1.0: - resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + natural-compare@1.4.0: {} + + neotraverse@0.6.18: {} + + nlcst-to-string@4.0.0: dependencies: - path-key: 4.0.0 + '@types/nlcst': 2.0.3 - /nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + node-fetch-native@1.6.6: {} + + node-fetch@2.6.10: dependencies: - boolbase: 1.0.0 + whatwg-url: 5.0.0 - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} + node-mock-http@1.0.0: {} - /object-hash@3.0.0: - resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} - engines: {node: '>= 6'} - dev: false + normalize-path@3.0.0: {} - /object-inspect@1.12.3: - resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} - dev: true + normalize-url@6.1.0: {} - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true + not@0.1.0: {} - /object.assign@4.1.4: - resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} - engines: {node: '>= 0.4'} + nth-check@2.1.1: dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: true + boolbase: 1.0.0 - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + ofetch@1.4.1: + dependencies: + destr: 2.0.3 + node-fetch-native: 1.6.6 + ufo: 1.5.4 + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: dependencies: wrappy: 1.0.2 - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} + oniguruma-parser@0.11.1: {} + + oniguruma-to-es@4.2.0: dependencies: - mimic-fn: 2.1.0 + emoji-regex-xs: 1.0.0 + oniguruma-parser: 0.11.1 + regex: 6.0.1 + regex-recursion: 6.0.2 - /onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} + opentype.js@1.3.4: dependencies: - mimic-fn: 4.0.0 + string.prototype.codepointat: 0.2.1 + tiny-inflate: 1.0.3 - /ora@7.0.1: - resolution: {integrity: sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==} - engines: {node: '>=16'} + optionator@0.9.4: dependencies: - chalk: 5.3.0 - cli-cursor: 4.0.0 - cli-spinners: 2.9.0 - is-interactive: 2.0.0 - is-unicode-supported: 1.3.0 - log-symbols: 5.1.0 - stdin-discarder: 0.1.0 - string-width: 6.1.0 - strip-ansi: 7.1.0 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 - /os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: true + os-tmpdir@1.0.2: {} - /outdent@0.5.0: - resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} - dev: true + outdent@0.5.0: {} - /p-filter@2.1.0: - resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} - engines: {node: '>=8'} + p-cancelable@2.1.1: {} + + p-filter@2.1.0: dependencies: p-map: 2.1.0 - dev: true - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} + p-limit@2.3.0: dependencies: p-try: 2.2.0 - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 - /p-limit@4.0.0: - resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + p-limit@6.2.0: dependencies: - yocto-queue: 1.0.0 + yocto-queue: 1.1.1 - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} + p-locate@4.1.0: dependencies: p-limit: 2.3.0 - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} + p-locate@5.0.0: dependencies: p-limit: 3.1.0 - /p-map@2.1.0: - resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} - engines: {node: '>=6'} - dev: true + p-map@2.1.0: {} - /p-retry@5.1.2: - resolution: {integrity: sha512-couX95waDu98NfNZV+i/iLt+fdVxmI7CbrrdC2uDWfPdUAApyxT4wmDlyOtR5KtTDmkDO0zDScDjDou9YHhd9g==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + p-queue@8.1.0: dependencies: - '@types/retry': 0.12.1 - retry: 0.13.1 - dev: true + eventemitter3: 5.0.1 + p-timeout: 6.1.2 - /p-timeout@4.1.0: - resolution: {integrity: sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==} - engines: {node: '>=10'} - dev: true + p-timeout@6.1.2: {} - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} + p-try@2.2.0: {} - /pa11y-ci@3.0.1: - resolution: {integrity: sha512-DUtEIhEG3Ofds7qRuplq0DdCb9doILRlzcRctFNzo4QUNmVy4iZfM3u51A9cqoPo2irCJZoo5BzfiFrcriY2IQ==} - engines: {node: '>=12'} - hasBin: true - dependencies: - async: 2.6.4 - cheerio: 1.0.0-rc.12 - commander: 6.2.1 - globby: 6.1.0 - kleur: 4.1.5 - lodash: 4.17.21 - node-fetch: 2.6.10 - pa11y: 6.1.1 - protocolify: 3.0.0 - puppeteer: 9.1.1 - wordwrap: 1.0.0 - transitivePeerDependencies: - - bufferutil - - encoding - - supports-color - - utf-8-validate - dev: true + package-json-from-dist@1.0.1: {} - /pa11y@6.1.1: - resolution: {integrity: sha512-2NzqA3D9CUlDWj8WuOI4fM2P0qM1d/IUxsRRpzCOfDT5eMR1oEgmUwW2TAk+f90ff/GVck0BewdYT4et4BANew==} - engines: {node: '>=12'} - hasBin: true - dependencies: - axe-core: 4.7.0 - bfj: 7.0.2 - commander: 8.0.0 - envinfo: 7.8.1 - hogan.js: 3.0.2 - html_codesniffer: 2.5.1 - kleur: 4.1.5 - node.extend: 2.0.2 - p-timeout: 4.1.0 - puppeteer: 9.1.1 - semver: 7.3.8 - transitivePeerDependencies: - - bufferutil - - encoding - - supports-color - - utf-8-validate - dev: true + package-manager-detector@0.2.2: {} - /pagefind@1.0.3: - resolution: {integrity: sha512-ws7kmMxW6OuxzsOjj3YAx6TYq/54MiE3wfyBM3J5CInbZyBBvM2Z8c8IYvnMkBcb5v2EoB9DewXEekOEiDRu5g==} - hasBin: true + package-manager-detector@1.1.0: {} + + pagefind@1.3.0: optionalDependencies: - '@pagefind/darwin-arm64': 1.0.3 - '@pagefind/darwin-x64': 1.0.3 - '@pagefind/linux-arm64': 1.0.3 - '@pagefind/linux-x64': 1.0.3 - '@pagefind/windows-x64': 1.0.3 - dev: false - - /parse-entities@4.0.1: - resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} + '@pagefind/darwin-arm64': 1.3.0 + '@pagefind/darwin-x64': 1.3.0 + '@pagefind/linux-arm64': 1.3.0 + '@pagefind/linux-x64': 1.3.0 + '@pagefind/windows-x64': 1.3.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-entities@4.0.1: dependencies: - '@types/unist': 2.0.6 + '@types/unist': 2.0.10 character-entities: 2.0.2 character-entities-legacy: 3.0.0 character-reference-invalid: 2.0.1 @@ -4948,1883 +7781,1100 @@ packages: is-alphanumerical: 2.0.1 is-decimal: 2.0.1 is-hexadecimal: 2.0.1 - dev: false - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.22.13 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /parse-latin@5.0.1: - resolution: {integrity: sha512-b/K8ExXaWC9t34kKeDV8kGXBkXZ1HCSAZRYE7HR14eA1GlXX5L8iWhs8USJNhQU9q5ci413jCKF0gOyovvyRBg==} - dependencies: - nlcst-to-string: 3.1.1 - unist-util-modify-children: 3.1.1 - unist-util-visit-children: 2.0.2 - /parse5-htmlparser2-tree-adapter@7.0.0: - resolution: {integrity: sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==} + parse-latin@7.0.0: dependencies: - domhandler: 5.0.3 - parse5: 7.1.2 - dev: true - - /parse5@6.0.1: - resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + '@types/nlcst': 2.0.3 + '@types/unist': 3.0.0 + nlcst-to-string: 4.0.0 + unist-util-modify-children: 4.0.0 + unist-util-visit-children: 3.0.0 + vfile: 6.0.3 - /parse5@7.1.2: - resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + parse5@7.1.2: dependencies: entities: 4.5.0 - dev: true - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - /path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-browserify@1.0.1: {} - /path-to-regexp@6.2.1: - resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} + path-exists@4.0.0: {} - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true - - /pathe@1.1.1: - resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} - dev: true - - /pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - dev: true + path-key@3.1.1: {} - /pause-stream@0.0.11: - resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} + path-scurry@1.11.1: dependencies: - through: 2.3.8 - dev: true - - /pend@1.2.0: - resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - dev: true - - /periscopic@3.1.0: - resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} - dependencies: - '@types/estree': 1.0.0 - estree-walker: 3.0.3 - is-reference: 3.0.1 - dev: false + lru-cache: 10.4.3 + minipass: 7.1.2 - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + path-to-regexp@6.2.2: {} - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - /pify@2.3.0: - resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} - engines: {node: '>=0.10.0'} + path-type@4.0.0: {} - /pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - - /pinkie-promise@2.0.1: - resolution: {integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==} - engines: {node: '>=0.10.0'} - dependencies: - pinkie: 2.0.4 - dev: true + pathe@2.0.3: {} - /pinkie@2.0.4: - resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==} - engines: {node: '>=0.10.0'} - dev: true + pathval@2.0.0: {} - /pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} - engines: {node: '>= 6'} - dev: false + picocolors@1.1.1: {} - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 + picomatch@2.3.1: {} - /pkg-types@1.0.3: - resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} - dependencies: - jsonc-parser: 3.2.0 - mlly: 1.4.0 - pathe: 1.1.1 - dev: true + picomatch@4.0.2: {} - /postcss-import@15.1.0(postcss@8.4.29): - resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} - engines: {node: '>=14.0.0'} - peerDependencies: - postcss: ^8.0.0 - dependencies: - postcss: 8.4.29 - postcss-value-parser: 4.2.0 - read-cache: 1.0.0 - resolve: 1.22.4 - dev: false + pify@4.0.1: {} - /postcss-js@4.0.1(postcss@8.4.29): - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} - engines: {node: ^12 || ^14 || >= 16} - peerDependencies: - postcss: ^8.4.21 - dependencies: - camelcase-css: 2.0.1 - postcss: 8.4.29 - dev: false + playwright-core@1.45.0: {} - /postcss-load-config@4.0.1(postcss@8.4.29): - resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} - engines: {node: '>= 14'} - peerDependencies: - postcss: '>=8.0.9' - ts-node: '>=9.0.0' - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true + playwright@1.45.0: dependencies: - lilconfig: 2.1.0 - postcss: 8.4.29 - yaml: 2.3.1 - dev: false + playwright-core: 1.45.0 + optionalDependencies: + fsevents: 2.3.2 - /postcss-nested@6.0.1(postcss@8.4.29): - resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.2.14 + postcss-nested@6.0.1(postcss@8.5.3): dependencies: - postcss: 8.4.29 + postcss: 8.5.3 postcss-selector-parser: 6.0.13 - dev: false - /postcss-selector-parser@6.0.13: - resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} - engines: {node: '>=4'} + postcss-selector-parser@6.0.13: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - dev: false - - /postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: false - - /postcss@8.4.29: - resolution: {integrity: sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.6 - picocolors: 1.0.0 - source-map-js: 1.0.2 - /prebuild-install@7.1.1: - resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} - engines: {node: '>=10'} - hasBin: true + postcss@8.5.3: dependencies: - detect-libc: 2.0.2 - expand-template: 2.0.3 - github-from-package: 0.0.0 - minimist: 1.2.8 - mkdirp-classic: 0.5.3 - napi-build-utils: 1.0.2 - node-abi: 3.45.0 - pump: 3.0.0 - rc: 1.2.8 - simple-get: 4.0.1 - tar-fs: 2.1.1 - tunnel-agent: 0.6.0 + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 - /preferred-pm@3.1.2: - resolution: {integrity: sha512-nk7dKrcW8hfCZ4H6klWcdRknBOXWzNQByJ0oJyX97BOupsYD+FzLS4hflgEu/uPUEHZCuRfMxzCBsuWd7OzT8Q==} - engines: {node: '>=10'} - dependencies: - find-up: 5.0.0 - find-yarn-workspace-root2: 1.2.16 - path-exists: 4.0.0 - which-pm: 2.0.0 + preact@10.18.2: {} - /prepend-http@3.0.1: - resolution: {integrity: sha512-BLxfZh+m6UiAiCPZFJ4+vYoL7NrRs5XgCTRrjseATAggXhdZKKxn+JUNmuVYWY23bDHgaEHodxw8mnmtVEDtHw==} - engines: {node: '>=8'} - dev: true + prelude-ls@1.2.1: {} - /prettier-plugin-astro@0.11.0: - resolution: {integrity: sha512-rl2hJ4Kty/aEfGjk3i4JS+bpng9MjgvwqLRNzeb9NqYhqKoWNwOR39cIJXFjU1vR3zYOPnwWNRMelKb0orunYA==} - engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'} + prettier-plugin-astro@0.14.1: dependencies: - '@astrojs/compiler': 1.8.0 - prettier: 3.0.0 + '@astrojs/compiler': 2.11.0 + prettier: 3.3.3 sass-formatter: 0.7.6 - dev: true - - /prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: true - - /prettier@3.0.0: - resolution: {integrity: sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==} - engines: {node: '>=14'} - hasBin: true - dev: true - /pretty-format@29.6.1: - resolution: {integrity: sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.6.0 - ansi-styles: 5.2.0 - react-is: 18.2.0 - dev: true + prettier@2.8.7: + optional: true - /prismjs@1.29.0: - resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} - engines: {node: '>=6'} + prettier@2.8.8: {} - /probe-image-size@7.2.3: - resolution: {integrity: sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==} - dependencies: - lodash.merge: 4.6.2 - needle: 2.9.1 - stream-parser: 0.3.1 - transitivePeerDependencies: - - supports-color + prettier@3.3.3: {} - /progress@2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} - dev: true + prismjs@1.29.0: {} - /prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} + prompts@2.4.2: dependencies: kleur: 3.0.3 sisteransi: 1.0.5 - /property-information@6.2.0: - resolution: {integrity: sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==} - - /protocolify@3.0.0: - resolution: {integrity: sha512-PuvDJOkKJMVQx8jSNf8E5g0bJw/UTKm30mTjFHg4N30c8sefgA5Qr/f8INKqYBKfvP/MUSJrj+z1Smjbq4/3rQ==} - engines: {node: '>=8'} - dependencies: - file-url: 3.0.0 - prepend-http: 3.0.1 - dev: true - - /proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: true + property-information@6.2.0: {} - /ps-tree@1.2.0: - resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==} - engines: {node: '>= 0.10'} - hasBin: true - dependencies: - event-stream: 3.3.4 - dev: true + property-information@7.0.0: {} - /pseudomap@1.0.2: - resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} - dev: true + pseudomap@1.0.2: {} - /pump@3.0.0: - resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + pump@3.0.0: dependencies: end-of-stream: 1.4.4 once: 1.4.0 - /puppeteer@9.1.1: - resolution: {integrity: sha512-W+nOulP2tYd/ZG99WuZC/I5ljjQQ7EUw/jQGcIb9eu8mDlZxNY2SgcJXTLG9h5gRvqA3uJOe4hZXYsd3EqioMw==} - engines: {node: '>=10.18.1'} - deprecated: < 19.4.0 is no longer supported - requiresBuild: true - dependencies: - debug: 4.3.4 - devtools-protocol: 0.0.869402 - extract-zip: 2.0.1 - https-proxy-agent: 5.0.1 - node-fetch: 2.6.10 - pkg-dir: 4.2.0 - progress: 2.0.3 - proxy-from-env: 1.1.0 - rimraf: 3.0.2 - tar-fs: 2.1.1 - unbzip2-stream: 1.4.3 - ws: 7.5.9 - transitivePeerDependencies: - - bufferutil - - encoding - - supports-color - - utf-8-validate - dev: true + punycode@2.3.1: {} - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + queue-microtask@1.2.3: {} - /queue-tick@1.0.1: - resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + quick-lru@5.1.1: {} - /quick-lru@4.0.1: - resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} - engines: {node: '>=8'} - dev: true + radix3@1.1.2: {} - /rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true + range-parser@1.2.1: {} + + read-yaml-file@1.1.0: dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 + graceful-fs: 4.2.10 + js-yaml: 3.14.1 + pify: 4.0.1 + strip-bom: 3.0.0 - /react-is@18.2.0: - resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} - dev: true + readdirp@4.0.2: {} - /read-cache@1.0.0: - resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + recma-build-jsx@1.0.0: dependencies: - pify: 2.3.0 - dev: false + '@types/estree': 1.0.6 + estree-util-build-jsx: 3.0.1 + vfile: 6.0.3 - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} + recma-jsx@1.0.0(acorn@8.14.1): dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - dev: true + acorn-jsx: 5.3.2(acorn@8.14.1) + estree-util-to-js: 2.0.0 + recma-parse: 1.0.0 + recma-stringify: 1.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - acorn - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} + recma-parse@1.0.0: dependencies: - '@types/normalize-package-data': 2.4.1 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - dev: true + '@types/estree': 1.0.6 + esast-util-from-js: 2.0.1 + unified: 11.0.5 + vfile: 6.0.3 - /read-yaml-file@1.1.0: - resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} - engines: {node: '>=6'} + recma-stringify@1.0.0: dependencies: - graceful-fs: 4.2.10 - js-yaml: 3.14.1 - pify: 4.0.1 - strip-bom: 3.0.0 - dev: true + '@types/estree': 1.0.6 + estree-util-to-js: 2.0.0 + unified: 11.0.5 + vfile: 6.0.3 - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} + regenerator-runtime@0.14.1: {} + + regex-recursion@6.0.2: dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} + regex@6.0.1: dependencies: - picomatch: 2.3.1 + regex-utilities: 2.3.0 - /redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} + rehype-expressive-code@0.41.1: + dependencies: + expressive-code: 0.41.1 + + rehype-format@5.0.0: dependencies: - indent-string: 4.0.0 - strip-indent: 3.0.0 - dev: true + '@types/hast': 3.0.4 + 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 - /regenerator-runtime@0.13.11: - resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} - dev: true + rehype-minify-whitespace@6.0.0: + dependencies: + '@types/hast': 3.0.4 + 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 - /regexp.prototype.flags@1.5.0: - resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} - engines: {node: '>= 0.4'} + rehype-parse@9.0.0: dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - functions-have-names: 1.2.3 - dev: true + '@types/hast': 3.0.4 + hast-util-from-html: 2.0.3 + unified: 11.0.5 - /rehype-parse@8.0.4: - resolution: {integrity: sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg==} + rehype-raw@7.0.0: dependencies: - '@types/hast': 2.3.4 - hast-util-from-parse5: 7.1.2 - parse5: 6.0.1 - unified: 10.1.2 + '@types/hast': 3.0.4 + hast-util-raw: 9.0.1 + vfile: 6.0.3 - /rehype-raw@6.1.1: - resolution: {integrity: sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==} + rehype-recma@1.0.0: dependencies: - '@types/hast': 2.3.4 - hast-util-raw: 7.2.3 - unified: 10.1.2 + '@types/estree': 1.0.6 + '@types/hast': 3.0.4 + hast-util-to-estree: 3.1.0 + transitivePeerDependencies: + - supports-color - /rehype-stringify@9.0.4: - resolution: {integrity: sha512-Uk5xu1YKdqobe5XpSskwPvo1XeHUUucWEQSl8hTrXt5selvca1e8K1EZ37E6YoZ4BT8BCqCdVfQW7OfHfthtVQ==} + rehype-stringify@10.0.1: dependencies: - '@types/hast': 2.3.4 - hast-util-to-html: 8.0.4 - unified: 10.1.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + unified: 11.0.5 - /rehype@12.0.1: - resolution: {integrity: sha512-ey6kAqwLM3X6QnMDILJthGvG1m1ULROS9NT4uG9IDCuv08SFyLlreSuvOa//DgEvbXx62DS6elGVqusWhRUbgw==} + rehype@13.0.2: dependencies: - '@types/hast': 2.3.4 - rehype-parse: 8.0.4 - rehype-stringify: 9.0.4 - unified: 10.1.2 + '@types/hast': 3.0.4 + rehype-parse: 9.0.0 + rehype-stringify: 10.0.1 + unified: 11.0.5 - /remark-directive@2.0.1: - resolution: {integrity: sha512-oosbsUAkU/qmUE78anLaJePnPis4ihsE7Agp0T/oqTzvTea8pOiaYEtfInU/+xMOVTS9PN5AhGOiaIVe4GD8gw==} + remark-directive@3.0.0: dependencies: - '@types/mdast': 3.0.11 - mdast-util-directive: 2.2.4 - micromark-extension-directive: 2.1.2 - unified: 10.1.2 + '@types/mdast': 4.0.4 + mdast-util-directive: 3.0.0 + micromark-extension-directive: 3.0.0 + unified: 11.0.5 transitivePeerDependencies: - supports-color - dev: false - /remark-gfm@3.0.1: - resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==} + remark-gfm@4.0.1: dependencies: - '@types/mdast': 3.0.11 - mdast-util-gfm: 2.0.2 - micromark-extension-gfm: 2.0.1 - unified: 10.1.2 + '@types/mdast': 4.0.4 + mdast-util-gfm: 3.0.0 + micromark-extension-gfm: 3.0.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.5 transitivePeerDependencies: - supports-color - /remark-mdx@2.3.0: - resolution: {integrity: sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==} + remark-mdx@3.1.0: dependencies: - mdast-util-mdx: 2.0.1 - micromark-extension-mdxjs: 1.0.0 + mdast-util-mdx: 3.0.0 + micromark-extension-mdxjs: 3.0.0 transitivePeerDependencies: - supports-color - dev: false - /remark-parse@10.0.2: - resolution: {integrity: sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==} + remark-parse@11.0.0: dependencies: - '@types/mdast': 3.0.11 - mdast-util-from-markdown: 1.3.0 - unified: 10.1.2 + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.0 + micromark-util-types: 2.0.0 + unified: 11.0.5 transitivePeerDependencies: - supports-color - /remark-rehype@10.1.0: - resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==} + remark-rehype@11.1.1: dependencies: - '@types/hast': 2.3.4 - '@types/mdast': 3.0.11 - mdast-util-to-hast: 12.3.0 - unified: 10.1.2 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + mdast-util-to-hast: 13.0.2 + unified: 11.0.5 + vfile: 6.0.3 - /remark-smartypants@2.0.0: - resolution: {integrity: sha512-Rc0VDmr/yhnMQIz8n2ACYXlfw/P/XZev884QU1I5u+5DgJls32o97Vc1RbK3pfumLsJomS2yy8eT4Fxj/2MDVA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + remark-smartypants@3.0.2: dependencies: - retext: 8.1.0 - retext-smartypants: 5.2.0 - unist-util-visit: 4.1.2 - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true - - /require-main-filename@2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - dev: true - - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true + retext: 9.0.0 + retext-smartypants: 6.1.0 + unified: 11.0.5 + unist-util-visit: 5.0.0 - /resolve@1.22.4: - resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} - hasBin: true + remark-stringify@11.0.0: dependencies: - is-core-module: 2.13.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 + '@types/mdast': 4.0.4 + mdast-util-to-markdown: 2.1.0 + unified: 11.0.5 - /restore-cursor@4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 + request-light@0.5.8: {} - /retext-latin@3.1.0: - resolution: {integrity: sha512-5MrD1tuebzO8ppsja5eEu+ZbBeUNCjoEarn70tkXOS7Bdsdf6tNahsv2bY0Z8VooFF6cw7/6S+d3yI/TMlMVVQ==} - dependencies: - '@types/nlcst': 1.0.0 - parse-latin: 5.0.1 - unherit: 3.0.1 - unified: 10.1.2 + request-light@0.7.0: {} - /retext-smartypants@5.2.0: - resolution: {integrity: sha512-Do8oM+SsjrbzT2UNIKgheP0hgUQTDDQYyZaIY3kfq0pdFzoPk+ZClYJ+OERNXveog4xf1pZL4PfRxNoVL7a/jw==} - dependencies: - '@types/nlcst': 1.0.0 - nlcst-to-string: 3.1.1 - unified: 10.1.2 - unist-util-visit: 4.1.2 + require-directory@2.1.1: {} - /retext-stringify@3.1.0: - resolution: {integrity: sha512-767TLOaoXFXyOnjx/EggXlb37ZD2u4P1n0GJqVdpipqACsQP+20W+BNpMYrlJkq7hxffnFk+jc6mAK9qrbuB8w==} - dependencies: - '@types/nlcst': 1.0.0 - nlcst-to-string: 3.1.1 - unified: 10.1.2 + require-from-string@2.0.2: {} - /retext@8.1.0: - resolution: {integrity: sha512-N9/Kq7YTn6ZpzfiGW45WfEGJqFf1IM1q8OsRa1CGzIebCJBNCANDRmOrholiDRGKo/We7ofKR4SEvcGAWEMD3Q==} - dependencies: - '@types/nlcst': 1.0.0 - retext-latin: 3.1.0 - retext-stringify: 3.1.0 - unified: 10.1.2 + resolve-alpn@1.2.1: {} - /retry@0.13.1: - resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} - engines: {node: '>= 4'} - dev: true + resolve-from@4.0.0: {} - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + resolve-from@5.0.0: {} - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true + resolve-pkg-maps@1.0.0: {} - /rollup@3.28.1: - resolution: {integrity: sha512-R9OMQmIHJm9znrU3m3cpE8uhN0fGdXiawME7aZIpQqvpS/85+Vt1Hq1/yVIcYfOmaQiHjvXkQAoJukvLpau6Yw==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} - hasBin: true - optionalDependencies: - fsevents: 2.3.2 + responselike@2.0.1: + dependencies: + lowercase-keys: 2.0.0 - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + retext-latin@4.0.0: dependencies: - queue-microtask: 1.2.3 + '@types/nlcst': 2.0.3 + parse-latin: 7.0.0 + unified: 11.0.5 - /rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + retext-smartypants@6.1.0: dependencies: - tslib: 2.5.0 - dev: true + '@types/nlcst': 2.0.3 + nlcst-to-string: 4.0.0 + unist-util-visit: 5.0.0 - /s.color@0.0.15: - resolution: {integrity: sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA==} - dev: true + retext-stringify@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + nlcst-to-string: 4.0.0 + unified: 11.0.5 - /sade@1.8.1: - resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} - engines: {node: '>=6'} + retext@9.0.0: dependencies: - mri: 1.2.0 + '@types/nlcst': 2.0.3 + retext-latin: 4.0.0 + retext-stringify: 4.0.0 + unified: 11.0.5 - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + reusify@1.0.4: {} - /safe-regex-test@1.0.0: - resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + rollup@4.36.0: dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.0 - is-regex: 1.1.4 - dev: true + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.36.0 + '@rollup/rollup-android-arm64': 4.36.0 + '@rollup/rollup-darwin-arm64': 4.36.0 + '@rollup/rollup-darwin-x64': 4.36.0 + '@rollup/rollup-freebsd-arm64': 4.36.0 + '@rollup/rollup-freebsd-x64': 4.36.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.36.0 + '@rollup/rollup-linux-arm-musleabihf': 4.36.0 + '@rollup/rollup-linux-arm64-gnu': 4.36.0 + '@rollup/rollup-linux-arm64-musl': 4.36.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.36.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.36.0 + '@rollup/rollup-linux-riscv64-gnu': 4.36.0 + '@rollup/rollup-linux-s390x-gnu': 4.36.0 + '@rollup/rollup-linux-x64-gnu': 4.36.0 + '@rollup/rollup-linux-x64-musl': 4.36.0 + '@rollup/rollup-win32-arm64-msvc': 4.36.0 + '@rollup/rollup-win32-ia32-msvc': 4.36.0 + '@rollup/rollup-win32-x64-msvc': 4.36.0 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + s.color@0.0.15: {} - /sass-formatter@0.7.6: - resolution: {integrity: sha512-hXdxU6PCkiV3XAiSnX+XLqz2ohHoEnVUlrd8LEVMAI80uB1+OTScIkH9n6qQwImZpTye1r1WG1rbGUteHNhoHg==} + safer-buffer@2.1.2: {} + + sass-formatter@0.7.6: dependencies: suf-log: 2.5.3 - dev: true - /sax@1.2.4: - resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + sax@1.2.4: {} - /section-matter@1.0.0: - resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} - engines: {node: '>=4'} - dependencies: - extend-shallow: 2.0.1 - kind-of: 6.0.3 + semver@6.3.1: {} - /semver@5.7.1: - resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} - hasBin: true - dev: true + semver@7.7.1: {} - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true + semver@7.7.2: {} - /semver@7.3.8: - resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} - engines: {node: '>=10'} - hasBin: true + send@1.1.0: dependencies: - lru-cache: 6.0.0 - dev: true + debug: 4.4.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime-types: 2.1.35 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color - /semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 + server-destroy@1.0.1: {} - /server-destroy@1.0.1: - resolution: {integrity: sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==} + setprototypeof@1.2.0: {} - /set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: true + sharp@0.33.3: + dependencies: + color: 4.2.3 + detect-libc: 2.0.4 + semver: 7.7.2 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.3 + '@img/sharp-darwin-x64': 0.33.3 + '@img/sharp-libvips-darwin-arm64': 1.0.2 + '@img/sharp-libvips-darwin-x64': 1.0.2 + '@img/sharp-libvips-linux-arm': 1.0.2 + '@img/sharp-libvips-linux-arm64': 1.0.2 + '@img/sharp-libvips-linux-s390x': 1.0.2 + '@img/sharp-libvips-linux-x64': 1.0.2 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 + '@img/sharp-libvips-linuxmusl-x64': 1.0.2 + '@img/sharp-linux-arm': 0.33.3 + '@img/sharp-linux-arm64': 0.33.3 + '@img/sharp-linux-s390x': 0.33.3 + '@img/sharp-linux-x64': 0.33.3 + '@img/sharp-linuxmusl-arm64': 0.33.3 + '@img/sharp-linuxmusl-x64': 0.33.3 + '@img/sharp-wasm32': 0.33.3 + '@img/sharp-win32-ia32': 0.33.3 + '@img/sharp-win32-x64': 0.33.3 + optional: true - /sharp@0.32.5: - resolution: {integrity: sha512-0dap3iysgDkNaPOaOL4X/0akdu0ma62GcdC2NBQ+93eqpePdDdr2/LM0sFdDSMmN7yS+odyZtPsb7tx/cYBKnQ==} - engines: {node: '>=14.15.0'} - requiresBuild: true + sharp@0.34.2: dependencies: color: 4.2.3 - detect-libc: 2.0.2 - node-addon-api: 6.1.0 - prebuild-install: 7.1.1 - semver: 7.5.4 - simple-get: 4.0.1 - tar-fs: 3.0.4 - tunnel-agent: 0.6.0 - - /shebang-command@1.2.0: - resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} - engines: {node: '>=0.10.0'} + detect-libc: 2.0.4 + semver: 7.7.2 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.2 + '@img/sharp-darwin-x64': 0.34.2 + '@img/sharp-libvips-darwin-arm64': 1.1.0 + '@img/sharp-libvips-darwin-x64': 1.1.0 + '@img/sharp-libvips-linux-arm': 1.1.0 + '@img/sharp-libvips-linux-arm64': 1.1.0 + '@img/sharp-libvips-linux-ppc64': 1.1.0 + '@img/sharp-libvips-linux-s390x': 1.1.0 + '@img/sharp-libvips-linux-x64': 1.1.0 + '@img/sharp-libvips-linuxmusl-arm64': 1.1.0 + '@img/sharp-libvips-linuxmusl-x64': 1.1.0 + '@img/sharp-linux-arm': 0.34.2 + '@img/sharp-linux-arm64': 0.34.2 + '@img/sharp-linux-s390x': 0.34.2 + '@img/sharp-linux-x64': 0.34.2 + '@img/sharp-linuxmusl-arm64': 0.34.2 + '@img/sharp-linuxmusl-x64': 0.34.2 + '@img/sharp-wasm32': 0.34.2 + '@img/sharp-win32-arm64': 0.34.2 + '@img/sharp-win32-ia32': 0.34.2 + '@img/sharp-win32-x64': 0.34.2 + + shebang-command@1.2.0: dependencies: shebang-regex: 1.0.0 - dev: true - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - /shebang-regex@1.0.0: - resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} - engines: {node: '>=0.10.0'} - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} + shebang-regex@1.0.0: {} - /shiki@0.14.3: - resolution: {integrity: sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==} - dependencies: - ansi-sequence-parser: 1.1.0 - jsonc-parser: 3.2.0 - vscode-oniguruma: 1.7.0 - vscode-textmate: 8.0.0 + shebang-regex@3.0.0: {} - /side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + shiki@3.2.2: dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.0 - object-inspect: 1.12.3 - dev: true - - /siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - dev: true - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + '@shikijs/core': 3.2.2 + '@shikijs/engine-javascript': 3.2.2 + '@shikijs/engine-oniguruma': 3.2.2 + '@shikijs/langs': 3.2.2 + '@shikijs/themes': 3.2.2 + '@shikijs/types': 3.2.2 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} + siginfo@2.0.0: {} - /simple-concat@1.0.1: - resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + signal-exit@3.0.7: {} - /simple-get@4.0.1: - resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} - dependencies: - decompress-response: 6.0.0 - once: 1.4.0 - simple-concat: 1.0.1 + signal-exit@4.1.0: {} - /simple-git@3.19.0: - resolution: {integrity: sha512-hyH2p9Ptxjf/xPuL7HfXbpYt9gKhC1yWDh3KYIAYJJePAKV7AEjLN4xhp7lozOdNiaJ9jlVvAbBymVlcS2jRiA==} + simple-git@3.21.0: dependencies: '@kwsites/file-exists': 1.1.1 '@kwsites/promise-deferred': 1.1.1 - debug: 4.3.4 + debug: 4.4.0 transitivePeerDependencies: - supports-color - dev: true - /simple-swizzle@0.2.2: - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + simple-swizzle@0.2.2: dependencies: is-arrayish: 0.3.2 - /sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + sisteransi@1.0.5: {} - /sitemap@7.1.1: - resolution: {integrity: sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==} - engines: {node: '>=12.0.0', npm: '>=5.6.0'} - hasBin: true + sitemap@8.0.0: dependencies: '@types/node': 17.0.45 '@types/sax': 1.2.4 arg: 5.0.2 sax: 1.2.4 - dev: false - /size-limit@8.2.4: - resolution: {integrity: sha512-Un16nSreD1v2CYwSorattiJcHuAWqXvg4TsGgzpjnoByqQwsSfCIEQHuaD14HNStzredR8cdsO9oGH91ibypTA==} - engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0} - hasBin: true + sitemapper@3.2.12: + dependencies: + got: 11.8.6 + is-gzip: 2.0.0 + p-limit: 3.1.0 + xml2js: 0.5.0 + + size-limit@11.1.6: dependencies: bytes-iec: 3.1.1 - chokidar: 3.5.3 - globby: 11.1.0 - lilconfig: 2.1.0 + chokidar: 4.0.3 + jiti: 2.4.2 + lilconfig: 3.1.2 nanospinner: 1.1.0 - picocolors: 1.0.0 - dev: true - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true + picocolors: 1.1.1 + tinyglobby: 0.2.12 - /smartwrap@2.0.2: - resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} - engines: {node: '>=6'} - hasBin: true - dependencies: - array.prototype.flat: 1.3.1 - breakword: 1.0.5 - grapheme-splitter: 1.0.4 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - yargs: 15.4.1 - dev: true + slash@3.0.0: {} - /source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} + smol-toml@1.3.1: {} - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true + source-map-js@1.2.1: {} - /source-map@0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} - dev: false + source-map@0.7.4: {} - /space-separated-tokens@2.0.2: - resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + space-separated-tokens@2.0.2: {} - /spawndamnit@2.0.0: - resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} + spawndamnit@2.0.0: dependencies: cross-spawn: 5.1.0 signal-exit: 3.0.7 - dev: true - - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.13 - dev: true - - /spdx-exceptions@2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - dev: true - - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.13 - dev: true - - /spdx-license-ids@3.0.13: - resolution: {integrity: sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==} - dev: true - /split@0.3.3: - resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} - dependencies: - through: 2.3.8 - dev: true - - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - - /stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - dev: true - - /start-server-and-test@2.0.0: - resolution: {integrity: sha512-UqKLw0mJbfrsG1jcRLTUlvuRi9sjNuUiDOLI42r7R5fA9dsFoywAy9DoLXNYys9B886E4RCKb+qM1Gzu96h7DQ==} - engines: {node: '>=6'} - hasBin: true - dependencies: - arg: 5.0.2 - bluebird: 3.7.2 - check-more-types: 2.24.0 - debug: 4.3.4 - execa: 5.1.1 - lazy-ass: 1.6.0 - ps-tree: 1.2.0 - wait-on: 7.0.1(debug@4.3.4) - transitivePeerDependencies: - - supports-color - dev: true + sprintf-js@1.0.3: {} - /std-env@3.3.3: - resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==} - dev: true + stackback@0.0.2: {} - /stdin-discarder@0.1.0: - resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - bl: 5.1.0 - - /stream-combiner@0.0.4: - resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} + starlight-links-validator@0.14.0(@astrojs/starlight@packages+starlight): dependencies: - duplexer: 0.1.2 - dev: true + '@astrojs/starlight': link:packages/starlight + '@types/picomatch': 3.0.1 + github-slugger: 2.0.0 + hast-util-from-html: 2.0.3 + hast-util-has-property: 3.0.0 + is-absolute-url: 4.0.1 + kleur: 4.1.5 + mdast-util-to-string: 4.0.0 + picomatch: 4.0.2 + unist-util-visit: 5.0.0 - /stream-parser@0.3.1: - resolution: {integrity: sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==} - dependencies: - debug: 2.6.9 - transitivePeerDependencies: - - supports-color + statuses@2.0.1: {} - /stream-transform@2.1.3: - resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} - dependencies: - mixme: 0.5.9 - dev: true + std-env@3.8.0: {} - /streamsearch@1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} + std-env@3.9.0: {} - /streamx@2.15.0: - resolution: {integrity: sha512-HcxY6ncGjjklGs1xsP1aR71INYcsXFJet5CU1CHqihQ2J5nOsbd4OjgjHO42w/4QNv9gZb3BueV+Vxok5pLEXg==} - dependencies: - fast-fifo: 1.3.0 - queue-tick: 1.0.1 + stream-replace-string@2.0.0: {} - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} + string-width@5.1.2: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 - /string-width@6.1.0: - resolution: {integrity: sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==} - engines: {node: '>=16'} + string-width@7.2.0: dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 10.2.1 + emoji-regex: 10.3.0 + get-east-asian-width: 1.2.0 strip-ansi: 7.1.0 - /string.prototype.trim@1.2.7: - resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - dev: true - - /string.prototype.trimend@1.0.6: - resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - dev: true - - /string.prototype.trimstart@1.0.6: - resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - dev: true - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 + string.prototype.codepointat@0.2.1: {} - /stringify-entities@4.0.3: - resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==} + stringify-entities@4.0.3: dependencies: character-entities-html4: 2.1.0 character-entities-legacy: 3.0.0 - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - - /strip-bom-string@1.0.0: - resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} - engines: {node: '>=0.10.0'} - - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - - /strip-bom@4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true - - /strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - dependencies: - min-indent: 1.0.1 - dev: true - - /strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - - /strip-literal@1.0.1: - resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==} + strip-ansi@6.0.1: dependencies: - acorn: 8.10.0 - dev: true - - /style-to-object@0.4.1: - resolution: {integrity: sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw==} - dependencies: - inline-style-parser: 0.1.1 - dev: false - - /sucrase@3.34.0: - resolution: {integrity: sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==} - engines: {node: '>=8'} - hasBin: true - dependencies: - '@jridgewell/gen-mapping': 0.3.2 - commander: 4.1.1 - glob: 7.1.6 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.6 - ts-interface-checker: 0.1.13 - dev: false - - /suf-log@2.5.3: - resolution: {integrity: sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==} - dependencies: - s.color: 0.0.15 - dev: true - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - /tailwindcss@3.3.3: - resolution: {integrity: sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==} - engines: {node: '>=14.0.0'} - hasBin: true - dependencies: - '@alloc/quick-lru': 5.2.0 - arg: 5.0.2 - chokidar: 3.5.3 - didyoumean: 1.2.2 - dlv: 1.1.3 - fast-glob: 3.3.1 - glob-parent: 6.0.2 - is-glob: 4.0.3 - jiti: 1.19.1 - lilconfig: 2.1.0 - micromatch: 4.0.5 - normalize-path: 3.0.0 - object-hash: 3.0.0 - picocolors: 1.0.0 - postcss: 8.4.29 - postcss-import: 15.1.0(postcss@8.4.29) - postcss-js: 4.0.1(postcss@8.4.29) - postcss-load-config: 4.0.1(postcss@8.4.29) - postcss-nested: 6.0.1(postcss@8.4.29) - postcss-selector-parser: 6.0.13 - resolve: 1.22.4 - sucrase: 3.34.0 - transitivePeerDependencies: - - ts-node - dev: false + ansi-regex: 5.0.1 - /tar-fs@2.1.1: - resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + strip-ansi@7.1.0: dependencies: - chownr: 1.1.4 - mkdirp-classic: 0.5.3 - pump: 3.0.0 - tar-stream: 2.2.0 + ansi-regex: 6.0.1 + + strip-bom@3.0.0: {} - /tar-fs@3.0.4: - resolution: {integrity: sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==} + strip-json-comments@3.1.1: {} + + style-to-object@0.4.4: dependencies: - mkdirp-classic: 0.5.3 - pump: 3.0.0 - tar-stream: 3.1.6 + inline-style-parser: 0.1.1 - /tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} + style-to-object@1.0.8: dependencies: - bl: 4.1.0 - end-of-stream: 1.4.4 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 + inline-style-parser: 0.2.4 - /tar-stream@3.1.6: - resolution: {integrity: sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==} + suf-log@2.5.3: dependencies: - b4a: 1.6.4 - fast-fifo: 1.3.0 - streamx: 2.15.0 + s.color: 0.0.15 - /term-size@2.2.1: - resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} - engines: {node: '>=8'} - dev: true + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 - /test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} + tailwindcss@4.0.15: {} + + tapable@2.2.1: {} + + term-size@2.2.1: {} + + test-exclude@7.0.1: dependencies: '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 - dev: true + glob: 10.4.5 + minimatch: 9.0.5 - /thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} - dependencies: - thenify: 3.3.1 - dev: false + tiny-inflate@1.0.3: {} - /thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - dependencies: - any-promise: 1.3.0 - dev: false + tinybench@2.9.0: {} - /through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: true + tinyexec@0.3.2: {} - /tinybench@2.5.0: - resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==} - dev: true + tinyglobby@0.2.12: + dependencies: + fdir: 6.4.3(picomatch@4.0.2) + picomatch: 4.0.2 - /tinypool@0.6.0: - resolution: {integrity: sha512-FdswUUo5SxRizcBc6b1GSuLpLjisa8N8qMyYoP3rl+bym+QauhtJP5bvZY1ytt8krKGmMLYIRl36HBZfeAoqhQ==} - engines: {node: '>=14.0.0'} - dev: true + tinypool@1.0.2: {} - /tinyspy@2.1.1: - resolution: {integrity: sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==} - engines: {node: '>=14.0.0'} - dev: true + tinyrainbow@2.0.0: {} - /tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} + tinyspy@3.0.2: {} + + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 - dev: true - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - /tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true - - /trim-lines@3.0.1: - resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} - - /trim-newlines@3.0.1: - resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} - engines: {node: '>=8'} - dev: true + toidentifier@1.0.1: {} - /trough@2.1.0: - resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} + tr46@0.0.3: {} - /tryer@1.0.1: - resolution: {integrity: sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==} - dev: true + trim-lines@3.0.1: {} - /ts-interface-checker@0.1.13: - resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - dev: false + trough@2.1.0: {} - /tsconfig-resolver@3.0.1: - resolution: {integrity: sha512-ZHqlstlQF449v8glscGRXzL6l2dZvASPCdXJRWG4gHEZlUVx2Jtmr+a2zeVG4LCsKhDXKRj5R3h0C/98UcVAQg==} + ts-api-utils@2.1.0(typescript@5.6.3): dependencies: - '@types/json5': 0.0.30 - '@types/resolve': 1.20.2 - json5: 2.2.3 - resolve: 1.22.4 - strip-bom: 4.0.0 - type-fest: 0.13.1 + typescript: 5.6.3 - /tslib@2.5.0: - resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} - dev: true + tsconfck@3.1.5(typescript@5.6.3): + optionalDependencies: + typescript: 5.6.3 - /tsm@2.3.0: - resolution: {integrity: sha512-++0HFnmmR+gMpDtKTnW3XJ4yv9kVGi20n+NfyQWB9qwJvTaIWY9kBmzek2YUQK5APTQ/1DTrXmm4QtFPmW9Rzw==} - engines: {node: '>=12'} - hasBin: true - dependencies: - esbuild: 0.15.18 - dev: true + tslib@2.5.0: + optional: true - /tty-table@4.2.1: - resolution: {integrity: sha512-xz0uKo+KakCQ+Dxj1D/tKn2FSyreSYWzdkL/BYhgN6oMW808g8QRMuh1atAV9fjTPbWBjfbkKQpI/5rEcnAc7g==} - engines: {node: '>=8.0.0'} - hasBin: true + tsx@4.15.2: dependencies: - chalk: 4.1.2 - csv: 5.5.3 - kleur: 4.1.5 - smartwrap: 2.0.2 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - yargs: 17.7.2 - dev: true + esbuild: 0.21.5 + get-tsconfig: 4.7.5 + optionalDependencies: + fsevents: 2.3.3 - /tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + type-check@0.4.0: dependencies: - safe-buffer: 5.2.1 - - /type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - dev: true + prelude-ls: 1.2.1 - /type-fest@0.13.1: - resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} - engines: {node: '>=10'} - - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true + type-fest@4.26.1: {} - /type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true + typesafe-path@0.2.2: {} - /type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} + typescript-auto-import-cache@0.3.5: + dependencies: + semver: 7.7.2 - /typed-array-length@1.0.4: - resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + typescript-eslint@8.39.1(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3): dependencies: - call-bind: 1.0.2 - for-each: 0.3.3 - is-typed-array: 1.1.10 - dev: true + '@typescript-eslint/eslint-plugin': 8.39.1(@typescript-eslint/parser@8.39.1(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3))(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3) + '@typescript-eslint/parser': 8.39.1(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3) + '@typescript-eslint/typescript-estree': 8.39.1(typescript@5.6.3) + '@typescript-eslint/utils': 8.39.1(eslint@9.33.0(jiti@2.4.2))(typescript@5.6.3) + eslint: 9.33.0(jiti@2.4.2) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color - /ufo@1.1.2: - resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==} - dev: true + typescript@5.6.3: {} - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - dependencies: - call-bind: 1.0.2 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: true + ufo@1.5.4: {} - /unbzip2-stream@1.4.3: - resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} - dependencies: - buffer: 5.7.1 - through: 2.3.8 - dev: true + uhyphen@0.2.0: {} - /undici@5.23.0: - resolution: {integrity: sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg==} - engines: {node: '>=14.0'} - dependencies: - busboy: 1.6.0 + ultrahtml@1.6.0: {} + + ultramatter@0.0.4: {} - /unherit@3.0.1: - resolution: {integrity: sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==} + uncrypto@0.1.3: {} - /unified@10.1.2: - resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} + unified@11.0.5: dependencies: - '@types/unist': 2.0.6 + '@types/unist': 3.0.0 bail: 2.0.2 + devlop: 1.1.0 extend: 3.0.2 - is-buffer: 2.0.5 is-plain-obj: 4.1.0 trough: 2.1.0 - vfile: 5.3.7 - - /unist-util-generated@2.0.1: - resolution: {integrity: sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==} + vfile: 6.0.3 - /unist-util-is@5.2.1: - resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==} + unist-util-find-after@5.0.0: dependencies: - '@types/unist': 2.0.6 + '@types/unist': 3.0.0 + unist-util-is: 6.0.0 - /unist-util-is@6.0.0: - resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + unist-util-is@6.0.0: dependencies: '@types/unist': 3.0.0 - /unist-util-modify-children@3.1.1: - resolution: {integrity: sha512-yXi4Lm+TG5VG+qvokP6tpnk+r1EPwyYL04JWDxLvgvPV40jANh7nm3udk65OOWquvbMDe+PL9+LmkxDpTv/7BA==} + unist-util-modify-children@4.0.0: dependencies: - '@types/unist': 2.0.6 + '@types/unist': 3.0.0 array-iterate: 2.0.1 - /unist-util-position-from-estree@1.1.2: - resolution: {integrity: sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /unist-util-position@4.0.4: - resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==} + unist-util-position-from-estree@2.0.0: dependencies: - '@types/unist': 2.0.6 - - /unist-util-remove-position@4.0.2: - resolution: {integrity: sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ==} - dependencies: - '@types/unist': 2.0.6 - unist-util-visit: 4.1.2 - dev: false + '@types/unist': 3.0.0 - /unist-util-remove@3.1.1: - resolution: {integrity: sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw==} + unist-util-position@5.0.0: dependencies: - '@types/unist': 2.0.6 - unist-util-is: 5.2.1 - unist-util-visit-parents: 5.1.3 - dev: false + '@types/unist': 3.0.0 - /unist-util-stringify-position@3.0.3: - resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==} + unist-util-remove-position@5.0.0: dependencies: - '@types/unist': 2.0.6 + '@types/unist': 3.0.0 + unist-util-visit: 5.0.0 - /unist-util-visit-children@2.0.2: - resolution: {integrity: sha512-+LWpMFqyUwLGpsQxpumsQ9o9DG2VGLFrpz+rpVXYIEdPy57GSy5HioC0g3bg/8WP9oCLlapQtklOzQ8uLS496Q==} + unist-util-stringify-position@4.0.0: dependencies: - '@types/unist': 2.0.6 + '@types/unist': 3.0.0 - /unist-util-visit-parents@5.1.3: - resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==} + unist-util-visit-children@3.0.0: dependencies: - '@types/unist': 2.0.6 - unist-util-is: 5.2.1 + '@types/unist': 3.0.0 - /unist-util-visit-parents@6.0.1: - resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + unist-util-visit-parents@6.0.1: dependencies: '@types/unist': 3.0.0 unist-util-is: 6.0.0 - /unist-util-visit@4.1.2: - resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==} - dependencies: - '@types/unist': 2.0.6 - unist-util-is: 5.2.1 - unist-util-visit-parents: 5.1.3 - - /unist-util-visit@5.0.0: - resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + unist-util-visit@5.0.0: dependencies: '@types/unist': 3.0.0 unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 - /universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - dev: true - - /update-browserslist-db@1.0.11(browserslist@4.21.10): - resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.21.10 - escalade: 3.1.1 - picocolors: 1.0.0 - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + universalify@0.1.2: {} - /uvu@0.5.6: - resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} - engines: {node: '>=8'} - hasBin: true + unstorage@1.15.0: dependencies: - dequal: 2.0.3 - diff: 5.1.0 - kleur: 4.1.5 - sade: 1.8.1 + anymatch: 3.1.3 + chokidar: 4.0.3 + destr: 2.0.3 + h3: 1.15.1 + lru-cache: 10.4.3 + node-fetch-native: 1.6.6 + ofetch: 1.4.1 + ufo: 1.5.4 - /v8-to-istanbul@9.1.0: - resolution: {integrity: sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==} - engines: {node: '>=10.12.0'} + uri-js@4.4.1: dependencies: - '@jridgewell/trace-mapping': 0.3.18 - '@types/istanbul-lib-coverage': 2.0.4 - convert-source-map: 1.9.0 - dev: true + punycode: 2.3.1 - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - dev: true + util-deprecate@1.0.2: {} - /vfile-location@4.1.0: - resolution: {integrity: sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==} + vfile-location@5.0.2: dependencies: - '@types/unist': 2.0.6 - vfile: 5.3.7 + '@types/unist': 3.0.0 + vfile: 6.0.3 - /vfile-message@3.1.4: - resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==} + vfile-message@4.0.2: dependencies: - '@types/unist': 2.0.6 - unist-util-stringify-position: 3.0.3 + '@types/unist': 3.0.0 + unist-util-stringify-position: 4.0.0 - /vfile@5.3.7: - resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==} + vfile@6.0.3: dependencies: - '@types/unist': 2.0.6 - is-buffer: 2.0.5 - unist-util-stringify-position: 3.0.3 - vfile-message: 3.1.4 + '@types/unist': 3.0.0 + vfile-message: 4.0.2 - /vite-node@0.33.0(@types/node@18.16.19): - resolution: {integrity: sha512-19FpHYbwWWxDr73ruNahC+vtEdza52kA90Qb3La98yZ0xULqV8A5JLNPUff0f5zID4984tW7l3DH2przTJUZSw==} - engines: {node: '>=v14.18.0'} - hasBin: true + vite-node@3.1.1(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1): dependencies: cac: 6.7.14 - debug: 4.3.4 - mlly: 1.4.0 - pathe: 1.1.1 - picocolors: 1.0.0 - vite: 4.4.9(@types/node@18.16.19) + debug: 4.4.0 + es-module-lexer: 1.6.0 + pathe: 2.0.3 + vite: 6.2.6(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1) transitivePeerDependencies: - '@types/node' + - jiti - less - lightningcss - sass + - sass-embedded - stylus - sugarss - supports-color - terser - dev: true + - tsx + - yaml - /vite@4.4.9(@types/node@18.16.19): - resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==} - engines: {node: ^14.18.0 || >=16.0.0} - hasBin: true - peerDependencies: - '@types/node': '>= 14' - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true + vite@6.2.6(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1): dependencies: - '@types/node': 18.16.19 - esbuild: 0.18.17 - postcss: 8.4.29 - rollup: 3.28.1 + esbuild: 0.25.1 + postcss: 8.5.3 + rollup: 4.36.0 optionalDependencies: - fsevents: 2.3.2 - - /vitefu@0.2.4(vite@4.4.9): - resolution: {integrity: sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==} - peerDependencies: - vite: ^3.0.0 || ^4.0.0 - peerDependenciesMeta: - vite: - optional: true - dependencies: - vite: 4.4.9(@types/node@18.16.19) + '@types/node': 18.16.19 + fsevents: 2.3.3 + jiti: 2.4.2 + lightningcss: 1.29.3 + tsx: 4.15.2 + yaml: 2.6.1 - /vitest@0.33.0: - resolution: {integrity: sha512-1CxaugJ50xskkQ0e969R/hW47za4YXDUfWJDxip1hwbnhUjYolpfUn2AMOulqG/Dtd9WYAtkHmM/m3yKVrEejQ==} - engines: {node: '>=v14.18.0'} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@vitest/browser': '*' - '@vitest/ui': '*' - happy-dom: '*' - jsdom: '*' - playwright: '*' - safaridriver: '*' - webdriverio: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - playwright: - optional: true - safaridriver: - optional: true - webdriverio: - optional: true - dependencies: - '@types/chai': 4.3.5 - '@types/chai-subset': 1.3.3 + vitefu@1.0.6(vite@6.2.6(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1)): + optionalDependencies: + vite: 6.2.6(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1) + + vitest@3.1.1(@types/debug@4.1.12)(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1): + dependencies: + '@vitest/expect': 3.1.1 + '@vitest/mocker': 3.1.1(vite@6.2.6(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1)) + '@vitest/pretty-format': 3.1.1 + '@vitest/runner': 3.1.1 + '@vitest/snapshot': 3.1.1 + '@vitest/spy': 3.1.1 + '@vitest/utils': 3.1.1 + chai: 5.2.0 + debug: 4.4.0 + expect-type: 1.2.1 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 6.2.6(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1) + vite-node: 3.1.1(@types/node@18.16.19)(jiti@2.4.2)(lightningcss@1.29.3)(tsx@4.15.2)(yaml@2.6.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/debug': 4.1.12 '@types/node': 18.16.19 - '@vitest/expect': 0.33.0 - '@vitest/runner': 0.33.0 - '@vitest/snapshot': 0.33.0 - '@vitest/spy': 0.33.0 - '@vitest/utils': 0.33.0 - acorn: 8.10.0 - acorn-walk: 8.2.0 - cac: 6.7.14 - chai: 4.3.7 - debug: 4.3.4 - local-pkg: 0.4.3 - magic-string: 0.30.3 - pathe: 1.1.1 - picocolors: 1.0.0 - std-env: 3.3.3 - strip-literal: 1.0.1 - tinybench: 2.5.0 - tinypool: 0.6.0 - vite: 4.4.9(@types/node@18.16.19) - vite-node: 0.33.0(@types/node@18.16.19) - why-is-node-running: 2.2.2 transitivePeerDependencies: + - jiti - less - lightningcss + - msw - sass + - sass-embedded - stylus - sugarss - supports-color - terser - dev: true + - tsx + - yaml - /vscode-oniguruma@1.7.0: - resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} + volar-service-css@0.0.62(@volar/language-service@2.4.10): + dependencies: + vscode-css-languageservice: 6.3.2 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 + optionalDependencies: + '@volar/language-service': 2.4.10 + + volar-service-emmet@0.0.62(@volar/language-service@2.4.10): + dependencies: + '@emmetio/css-parser': 0.4.0 + '@emmetio/html-matcher': 1.3.0 + '@vscode/emmet-helper': 2.9.3 + vscode-uri: 3.0.8 + optionalDependencies: + '@volar/language-service': 2.4.10 - /vscode-textmate@8.0.0: - resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} + volar-service-html@0.0.62(@volar/language-service@2.4.10): + dependencies: + vscode-html-languageservice: 5.3.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 + optionalDependencies: + '@volar/language-service': 2.4.10 - /wait-on@7.0.1(debug@4.3.4): - resolution: {integrity: sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog==} - engines: {node: '>=12.0.0'} - hasBin: true + volar-service-prettier@0.0.62(@volar/language-service@2.4.10)(prettier@3.3.3): dependencies: - axios: 0.27.2(debug@4.3.4) - joi: 17.9.2 - lodash: 4.17.21 - minimist: 1.2.8 - rxjs: 7.8.1 - transitivePeerDependencies: - - debug - dev: true + vscode-uri: 3.0.8 + optionalDependencies: + '@volar/language-service': 2.4.10 + prettier: 3.3.3 - /wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + volar-service-typescript-twoslash-queries@0.0.62(@volar/language-service@2.4.10): dependencies: - defaults: 1.0.4 - dev: true + vscode-uri: 3.0.8 + optionalDependencies: + '@volar/language-service': 2.4.10 - /web-namespaces@2.0.1: - resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + volar-service-typescript@0.0.62(@volar/language-service@2.4.10): + dependencies: + path-browserify: 1.0.1 + semver: 7.7.1 + typescript-auto-import-cache: 0.3.5 + vscode-languageserver-textdocument: 1.0.12 + vscode-nls: 5.2.0 + vscode-uri: 3.0.8 + optionalDependencies: + '@volar/language-service': 2.4.10 - /web-streams-polyfill@3.2.1: - resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} - engines: {node: '>= 8'} - dev: true + volar-service-yaml@0.0.62(@volar/language-service@2.4.10): + dependencies: + vscode-uri: 3.0.8 + yaml-language-server: 1.15.0 + optionalDependencies: + '@volar/language-service': 2.4.10 - /webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true + vscode-css-languageservice@6.3.2: + dependencies: + '@vscode/l10n': 0.0.18 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.0.8 - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + vscode-html-languageservice@5.3.1: dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - dev: true + '@vscode/l10n': 0.0.18 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.0.8 - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + vscode-json-languageservice@4.1.8: dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: true + jsonc-parser: 3.3.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-nls: 5.2.0 + vscode-uri: 3.0.8 - /which-module@2.0.1: - resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - dev: true + vscode-jsonrpc@6.0.0: {} - /which-pm-runs@1.1.0: - resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} - engines: {node: '>=4'} + vscode-jsonrpc@8.2.0: {} - /which-pm@2.0.0: - resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} - engines: {node: '>=8.15'} + vscode-languageserver-protocol@3.16.0: dependencies: - load-yaml-file: 0.2.0 - path-exists: 4.0.0 + vscode-jsonrpc: 6.0.0 + vscode-languageserver-types: 3.16.0 - /which-pm@2.1.1: - resolution: {integrity: sha512-xzzxNw2wMaoCWXiGE8IJ9wuPMU+EYhFksjHxrRT8kMT5SnocBPRg69YAMtyV4D12fP582RA+k3P8H9J5EMdIxQ==} - engines: {node: '>=8.15'} + vscode-languageserver-protocol@3.17.5: dependencies: - load-yaml-file: 0.2.0 - path-exists: 4.0.0 + vscode-jsonrpc: 8.2.0 + vscode-languageserver-types: 3.17.5 - /which-typed-array@1.1.9: - resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} - engines: {node: '>= 0.4'} + vscode-languageserver-textdocument@1.0.12: {} + + vscode-languageserver-types@3.16.0: {} + + vscode-languageserver-types@3.17.5: {} + + vscode-languageserver@7.0.0: dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - is-typed-array: 1.1.10 - dev: true + vscode-languageserver-protocol: 3.16.0 - /which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true + vscode-languageserver@9.0.1: + dependencies: + vscode-languageserver-protocol: 3.17.5 + + vscode-nls@5.2.0: {} + + vscode-uri@2.1.2: {} + + vscode-uri@3.0.8: {} + + web-namespaces@2.0.1: {} + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which-pm-runs@1.1.0: {} + + which@1.3.1: dependencies: isexe: 2.0.0 - dev: true - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + which@2.0.2: dependencies: isexe: 2.0.0 - /why-is-node-running@2.2.2: - resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} - engines: {node: '>=8'} - hasBin: true + why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 stackback: 0.0.2 - dev: true - /widest-line@4.0.1: - resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} - engines: {node: '>=12'} + widest-line@5.0.0: dependencies: - string-width: 5.1.2 - - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: true + string-width: 7.2.0 - /wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true + word-wrap@1.2.5: {} - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} + wrap-ansi@8.1.0: dependencies: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 - /ws@7.5.9: - resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true + wrappy@1.0.2: {} - /y18n@4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - dev: true + xml2js@0.5.0: + dependencies: + sax: 1.2.4 + xmlbuilder: 11.0.1 - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true + xmlbuilder@11.0.1: {} - /yallist@2.1.2: - resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} - dev: true + xmlbuilder@15.1.1: {} - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + xxhash-wasm@1.1.0: {} - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + y18n@5.0.8: {} - /yaml@2.3.1: - resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==} - engines: {node: '>= 14'} - dev: false + yallist@2.1.2: {} - /yargs-parser@18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} + yaml-language-server@1.15.0: dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 - dev: true + ajv: 8.17.1 + lodash: 4.17.21 + request-light: 0.5.8 + vscode-json-languageservice: 4.1.8 + vscode-languageserver: 7.0.0 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-nls: 5.2.0 + vscode-uri: 3.0.8 + yaml: 2.2.2 + optionalDependencies: + prettier: 2.8.7 - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} + yaml@2.2.2: {} - /yargs@15.4.1: - resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} - engines: {node: '>=8'} - dependencies: - cliui: 6.0.0 - decamelize: 1.2.0 - find-up: 4.1.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 4.2.3 - which-module: 2.0.1 - y18n: 4.0.3 - yargs-parser: 18.1.3 - dev: true + yaml@2.6.1: {} - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} + yargs-parser@21.1.1: {} + + yargs@17.7.2: dependencies: cliui: 8.0.1 - escalade: 3.1.1 + escalade: 3.2.0 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: true - /yauzl@2.10.0: - resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yocto-queue@0.1.0: {} + + yocto-queue@1.1.1: {} + + yocto-spinner@0.2.1: dependencies: - buffer-crc32: 0.2.13 - fd-slicer: 1.1.0 - dev: true + yoctocolors: 2.1.1 - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} + yoctocolors@2.1.1: {} - /yocto-queue@1.0.0: - resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} - engines: {node: '>=12.20'} + zod-to-json-schema@3.24.5(zod@3.24.2): + dependencies: + zod: 3.24.2 + + zod-to-ts@1.2.0(typescript@5.6.3)(zod@3.24.2): + dependencies: + typescript: 5.6.3 + zod: 3.24.2 - /zod@3.21.1: - resolution: {integrity: sha512-+dTu2m6gmCbO9Ahm4ZBDapx2O6ZY9QSPXst2WXjcznPMwf2YNpn3RevLx4KkZp1OPW/ouFcoBtBzFz/LeY69oA==} + zod@3.24.2: {} - /zwitch@2.0.4: - resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + zwitch@2.0.4: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 2822c8d75c0..bf7d3781696 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,4 +2,3 @@ packages: - 'packages/**/*' - 'examples/**/*' - 'docs' - - 'docs-i18n-tracker' diff --git a/tsconfig.json b/tsconfig.json index c4e44da17a2..a05a719d52c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "astro/tsconfigs/strictest", + "include": ["docs/.astro/types.d.ts", "**/*"], + "exclude": ["**/dist/**", "**/__coverage__/**", "**/build/**"], "compilerOptions": { - "allowJs": true, + "jsx": "preserve", "checkJs": true } }