This commit is contained in:
@@ -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>
|
||||
@@ -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)} />
|
||||
@@ -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>
|
||||
@@ -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 })
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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/')} />
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
import RedirectLayout from '@layouts/RedirectLayout.astro'
|
||||
import { getVersionedDocsPath } from '@libs/path'
|
||||
---
|
||||
|
||||
<RedirectLayout path={getVersionedDocsPath('/getting-started/introduction/')} />
|
||||
@@ -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>
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
import RedirectLayout from '@layouts/RedirectLayout.astro'
|
||||
import { getVersionedDocsPath } from '@libs/path'
|
||||
---
|
||||
|
||||
<RedirectLayout path={getVersionedDocsPath('examples')} />
|
||||
@@ -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>
|
||||
@@ -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'
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user