This commit is contained in:
Philippe Torrel
2026-07-03 15:30:26 +02:00
parent f0e8aaa79c
commit 1b7f884cc6
837 changed files with 122510 additions and 11 deletions

View File

@@ -0,0 +1,17 @@
---
import BaseLayout from '@layouts/BaseLayout.astro'
---
<BaseLayout
overrides={{
body: { class: 'd-flex flex-column min-vh-100' },
main: { class: 'my-auto p-5', id: 'content' }
}}
robots="noindex,follow"
title="404 - File not found"
>
<div class="text-center py-5">
<h1 class="display-1">404</h1>
<h2>File not found</h2>
</div>
</BaseLayout>

View File

@@ -0,0 +1,56 @@
---
import type { InferGetStaticPropsType } from 'astro'
import RedirectLayout from '@layouts/RedirectLayout.astro'
import { getVersionedDocsPath } from '@libs/path'
import { trimLeadingAndTrailingSlashes } from '@libs/utils'
import { replaceConfigInText } from '@libs/remark'
import { aliasedDocsPages } from '@libs/content'
import { getAliasedExamplesPages, getExampleNameFromPagePath } from '@libs/examples'
export async function getStaticPaths() {
function normalizeAliases(aliases: string | string[] | undefined): string[] {
return aliases ? (Array.isArray(aliases) ? aliases : [aliases]) : []
}
function getAliasStaticPath(alias: string, path: string) {
return { params: { alias: trimLeadingAndTrailingSlashes(replaceConfigInText(alias)) }, props: { path } }
}
const staticPaths = []
const examplesPageModules = import.meta.glob('../assets/examples/**/*.astro', { eager: true })
const examplesPages = Object.entries(examplesPageModules).map(([file, module]) => {
return {
file,
...module
}
})
const aliasedExamplesPages = getAliasedExamplesPages(examplesPages)
// Generate static paths for all examples pages with aliases.
for (const aliasedExamplesPage of aliasedExamplesPages) {
const aliases = normalizeAliases(aliasedExamplesPage.aliases)
for (const alias of aliases) {
staticPaths.push(getAliasStaticPath(alias, `/examples/${getExampleNameFromPagePath(aliasedExamplesPage.file)}`))
}
}
// Generate static paths for all docs pages with aliases.
for (const aliasedDocsPage of aliasedDocsPages) {
const aliases = normalizeAliases(aliasedDocsPage.data.aliases)
for (const alias of aliases) {
staticPaths.push(getAliasStaticPath(alias, aliasedDocsPage.slug))
}
}
return staticPaths.flat()
}
type Props = InferGetStaticPropsType<typeof getStaticPaths>
const { path } = Astro.props
---
<RedirectLayout path={getVersionedDocsPath(path)} />

View File

@@ -0,0 +1,25 @@
---
import type { InferGetStaticPropsType } from 'astro'
import DocsLayout from '@layouts/DocsLayout.astro'
import { getConfig } from '@libs/config'
import { docsPages } from '@libs/content'
import Code from '@shortcodes/Code.astro'
export async function getStaticPaths() {
return docsPages.map((docsPage) => {
return {
params: { slug: docsPage.slug, version: getConfig().docs_version },
props: docsPage
}
})
}
type Props = InferGetStaticPropsType<typeof getStaticPaths>
const { id, data, render } = Astro.props
const { Content, headings, remarkPluginFrontmatter } = await render()
---
<DocsLayout frontmatter={remarkPluginFrontmatter as typeof data} headings={headings} id={id}>
<Content components={{ pre: Code }} />
</DocsLayout>

View File

@@ -0,0 +1,32 @@
import fs from 'node:fs'
import path from 'node:path'
import type { APIRoute } from 'astro'
import mime from 'mime'
import { getConfig } from '@libs/config'
import { getExamplesAssets } from '@libs/examples'
import { getDocsFsPath } from '@libs/path'
export function getStaticPaths() {
const examplesAssets = getExamplesAssets()
return examplesAssets.map((examplesAsset) => {
return {
params: { asset: examplesAsset, version: getConfig().docs_version }
}
})
}
export const GET: APIRoute = ({ params }) => {
const asset = params.asset
if (!asset) {
throw new Error('Missing asset parameter while generating an example asset.')
}
const assetPath = path.join(getDocsFsPath(), 'src/assets/examples', asset)
const buffer = fs.readFileSync(assetPath)
const mimetype = mime.getType(assetPath)
const headers: ResponseInit['headers'] = typeof mimetype === 'string' ? { 'Content-Type': mimetype } : {}
return new Response(buffer, { headers })
}

View File

@@ -0,0 +1,40 @@
---
import ExamplesLayout from '@layouts/ExamplesLayout.astro'
import { getConfig } from '@libs/config'
import { exampleFrontmatterSchema, getExampleNameFromPagePath, type ExampleFrontmatter } from '@libs/examples'
export async function getStaticPaths() {
const examplesPageModules = import.meta.glob('../../../../assets/examples/**/*.astro', { eager: true })
const examplesPages = Object.entries(examplesPageModules).map(([file, module]) => {
return {
file,
...module
}
})
return examplesPages.map((examplesPage) => {
const { default: Content, file, url, ...props } = examplesPage
const example = getExampleNameFromPagePath(examplesPage.file)
let frontmatter: ExampleFrontmatter
try {
frontmatter = exampleFrontmatterSchema.parse(props)
} catch (error) {
throw new Error(`Invalid frontmatter for the '${example}' example.`, { cause: error })
}
return {
params: { example, version: getConfig().docs_version },
props: { ...frontmatter, Content }
}
})
}
type Props = ExampleFrontmatter
const { Content, ...props } = Astro.props
---
<ExamplesLayout {...props}>
<Content />
</ExamplesLayout>

View File

@@ -0,0 +1,31 @@
---
import SingleLayout from '@layouts/SingleLayout.astro'
import { getConfig } from '@libs/config'
import ExamplesMain from '@layouts/partials/ExamplesMain.astro'
export function getStaticPaths() {
return [
{
params: { version: getConfig().docs_version }
}
]
}
---
<SingleLayout
title="Examples"
description="Quickly get a project started with any of our examples ranging from using parts of the framework to custom components and layouts."
>
<div class="d-flex flex-column flex-md-row gap-3" slot="header-content">
<a
href={getConfig().download.dist_examples}
class="btn btn-lg bd-btn-lg btn-bd-primary d-flex align-items-center justify-content-center fw-semibold"
>
<svg class="bi me-2" aria-hidden="true"><use xlink:href="#box-seam"></use></svg>
Download examples
</a>
<a href={getConfig().download.source} class="btn btn-lg bd-btn-lg btn-outline-secondary"> Download source code</a>
</div>
<Fragment slot="main-content">
<ExamplesMain />
</Fragment>
</SingleLayout>

View File

@@ -0,0 +1,15 @@
---
import RedirectLayout from '@layouts/RedirectLayout.astro'
import { getConfig } from '@libs/config'
import { getVersionedDocsPath } from '@libs/path'
export function getStaticPaths() {
return [
{
params: { version: getConfig().docs_version }
}
]
}
---
<RedirectLayout path={getVersionedDocsPath('/getting-started/introduction/')} />

View File

@@ -0,0 +1,6 @@
---
import RedirectLayout from '@layouts/RedirectLayout.astro'
import { getVersionedDocsPath } from '@libs/path'
---
<RedirectLayout path={getVersionedDocsPath('/getting-started/introduction/')} />

View File

@@ -0,0 +1,53 @@
---
import SingleLayout from '@layouts/SingleLayout.astro'
import { getConfig } from '@libs/config'
import { getData } from '@libs/data'
function getVersionsSortedDesc<TKey extends string, TVersions extends Record<TKey, string>>(
versions: TVersions[],
orderBy: TKey
) {
return [...versions].sort((versionA, versionB) => {
return versionB[orderBy].localeCompare(versionA[orderBy])
})
}
---
<SingleLayout
title="Versions"
description="An appendix of hosted documentation for nearly every release of Bootstrap, from v1 through v5."
>
<div class="row">
{
getVersionsSortedDesc(getData('docs-versions'), 'group').map((docsVersion) => {
return (
<div class="col-md-6 col-lg-4 col-xl mb-4">
<h2>{docsVersion.group}</h2>
<p>{docsVersion.description}</p>
<div class="list-group">
{docsVersion.versions
.slice()
.sort((a, b) => b.localeCompare(a))
.map((version) => {
const isCurrentVersion = version === getConfig().docs_version
return (
<a
class:list={[
'list-group-item list-group-item-action py-2 text-primary',
isCurrentVersion && 'd-flex justify-content-between align-items-center'
]}
href={`${docsVersion.baseurl}/${version}/`}
>
{version}
{isCurrentVersion && <span class="badge text-bg-primary">Latest</span>}
</a>
)
})}
</div>
</div>
)
})
}
</div>
</SingleLayout>

View File

@@ -0,0 +1,6 @@
---
import RedirectLayout from '@layouts/RedirectLayout.astro'
import { getVersionedDocsPath } from '@libs/path'
---
<RedirectLayout path={getVersionedDocsPath('examples')} />

View File

@@ -0,0 +1,22 @@
---
import BaseLayout from '@layouts/BaseLayout.astro'
import GetStarted from '@components/home/GetStarted.astro'
import Customize from '@components/home/Customize.astro'
import CSSVariables from '@components/home/CSSVariables.astro'
import ComponentUtilities from '@components/home/ComponentUtilities.astro'
import MastHead from '@components/home/MastHead.astro'
import Plugins from '@components/home/Plugins.astro'
import Icons from '@components/home/Icons.astro'
---
<BaseLayout>
<MastHead />
<div class="container-xxl bd-gutter masthead-followup">
<GetStarted />
<Customize />
<CSSVariables />
<ComponentUtilities />
<Plugins />
<Icons />
</div>
</BaseLayout>

View File

@@ -0,0 +1,20 @@
import type { APIRoute } from 'astro'
export const GET: APIRoute = function GET({ site }) {
const isProduction = import.meta.env.PROD
const isNetlify = import.meta.env.NETLIFY === 'true'
const allowCrawling = !isNetlify && isProduction
const robotsTxt = `# www.robotstxt.org${allowCrawling ? '\n# Allow crawling of all content' : ''}
User-agent: *
Disallow: ${allowCrawling ? '' : '/'}
Sitemap: ${new URL('sitemap-index.xml', site)}
`
return new Response(robotsTxt, {
headers: {
'Content-Type': 'text/plain'
}
})
}