mirror of
https://github.com/tenrok/bootstrap.git
synced 2026-06-14 18:42:30 +03:00
a8ab19955b
Co-authored-by: HiDeoo <494699+HiDeoo@users.noreply.github.com> Co-authored-by: Mark Otto <markdotto@gmail.com>
196 lines
6.5 KiB
TypeScript
196 lines
6.5 KiB
TypeScript
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
import { rehypeHeadingIds } from '@astrojs/markdown-remark'
|
|
import mdx from '@astrojs/mdx'
|
|
import sitemap from '@astrojs/sitemap'
|
|
import type { AstroIntegration } from 'astro'
|
|
import autoImport from 'astro-auto-import'
|
|
import type { Element } from 'hast'
|
|
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
|
|
import { getConfig } from './config'
|
|
import { rehypeBsTable } from './rehype'
|
|
import { remarkBsConfig, remarkBsDocsref } from './remark'
|
|
import { configurePrism } from './prism'
|
|
import {
|
|
docsDirectory,
|
|
getDocsFsPath,
|
|
getDocsPublicFsPath,
|
|
getDocsStaticFsPath,
|
|
validateVersionedDocsPaths
|
|
} from './path'
|
|
|
|
// A list of directories in `src/components` that contains components that will be auto imported in all pages for
|
|
// convenience.
|
|
// Note: adding a new component to one of the existing directories requires a restart of the dev server.
|
|
const autoImportedComponentDirectories = ['shortcodes']
|
|
|
|
// A list of static file paths that will be aliased to a different path.
|
|
const staticFileAliases = {
|
|
'/docs/[version]/assets/img/favicons/apple-touch-icon.png': '/apple-touch-icon.png',
|
|
'/docs/[version]/assets/img/favicons/favicon.ico': '/favicon.ico'
|
|
}
|
|
|
|
// A list of pages that will be excluded from the sitemap.
|
|
const sitemapExcludes = ['/404', '/docs', `/docs/${getConfig().docs_version}`]
|
|
|
|
const headingsRangeRegex = new RegExp(`^h[${getConfig().anchors.min}-${getConfig().anchors.max}]$`)
|
|
|
|
export function bootstrap(): AstroIntegration[] {
|
|
const sitemapExcludedUrls = sitemapExcludes.map((url) => `${getConfig().baseURL}${url}/`)
|
|
|
|
configurePrism()
|
|
|
|
return [
|
|
bootstrap_auto_import(),
|
|
{
|
|
name: 'bootstrap-integration',
|
|
hooks: {
|
|
'astro:config:setup': ({ addWatchFile, updateConfig }) => {
|
|
// Reload the config when the integration is modified.
|
|
addWatchFile(path.join(getDocsFsPath(), 'src/libs/astro.ts'))
|
|
|
|
// Add the remark and rehype plugins.
|
|
updateConfig({
|
|
markdown: {
|
|
rehypePlugins: [
|
|
rehypeHeadingIds,
|
|
[
|
|
rehypeAutolinkHeadings,
|
|
{
|
|
behavior: 'append',
|
|
content: [{ type: 'text', value: ' ' }],
|
|
properties: { class: 'anchor-link' },
|
|
test: (element: Element) => element.tagName.match(headingsRangeRegex)
|
|
}
|
|
],
|
|
rehypeBsTable
|
|
],
|
|
remarkPlugins: [remarkBsConfig, remarkBsDocsref]
|
|
}
|
|
})
|
|
},
|
|
'astro:config:done': () => {
|
|
cleanPublicDirectory()
|
|
copyBootstrap()
|
|
copyStatic()
|
|
aliasStatic()
|
|
},
|
|
'astro:build:done': ({ dir }) => {
|
|
validateVersionedDocsPaths(dir)
|
|
}
|
|
}
|
|
},
|
|
// https://github.com/withastro/astro/issues/6475
|
|
mdx() as AstroIntegration,
|
|
sitemap({
|
|
filter: (page) => sitemapFilter(page, sitemapExcludedUrls)
|
|
})
|
|
]
|
|
}
|
|
|
|
function bootstrap_auto_import() {
|
|
const autoImportedComponents: string[] = []
|
|
const autoImportedComponentDefinitions: string[] = []
|
|
|
|
for (const autoImportedComponentDirectory of autoImportedComponentDirectories) {
|
|
const components = fs.readdirSync(path.join(getDocsFsPath(), 'src/components', autoImportedComponentDirectory), {
|
|
withFileTypes: true
|
|
})
|
|
|
|
for (const component of components) {
|
|
if (component.isFile()) {
|
|
autoImportedComponents.push(
|
|
`./${path.posix.join(docsDirectory, 'src/components', autoImportedComponentDirectory, component.name)}`
|
|
)
|
|
|
|
if (component.name.endsWith('.astro')) {
|
|
autoImportedComponentDefinitions.push(
|
|
`export const ${component.name.replace('.astro', '')}: typeof import('@shortcodes/${
|
|
component.name
|
|
}').default`
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const autoImportedComponentDefinition = `/**
|
|
* DO NOT EDIT THIS FILE MANUALLY.
|
|
*
|
|
* This file is automatically generated by the Boostrap Astro Integration.
|
|
* It contains the type definitions for the components that are auto imported in all pages.
|
|
* @see site/src/libs/astro.ts
|
|
*/
|
|
export declare global {
|
|
${autoImportedComponentDefinitions.join('\n ')}
|
|
}
|
|
`
|
|
|
|
fs.writeFileSync(path.join(getDocsFsPath(), 'src/types/auto-import.d.ts'), autoImportedComponentDefinition)
|
|
|
|
return autoImport({
|
|
imports: autoImportedComponents
|
|
})
|
|
}
|
|
|
|
function cleanPublicDirectory() {
|
|
fs.rmSync(getDocsPublicFsPath(), { force: true, recursive: true })
|
|
}
|
|
|
|
// Copy the `dist` folder from the root of the repo containing the latest version of Bootstrap to make it available from
|
|
// the `/docs/${docs_version}/dist` URL.
|
|
function copyBootstrap() {
|
|
const source = path.join(process.cwd(), 'dist')
|
|
const destination = path.join(getDocsPublicFsPath(), 'docs', getConfig().docs_version, 'dist')
|
|
|
|
fs.mkdirSync(destination, { recursive: true })
|
|
fs.cpSync(source, destination, { recursive: true })
|
|
}
|
|
|
|
// Copy the content as-is of the `static` folder to make it available from the `/` URL.
|
|
// A folder named `[version]` will automatically be renamed to the current version of the docs extracted from the
|
|
// `config.yml` file.
|
|
function copyStatic() {
|
|
const source = getDocsStaticFsPath()
|
|
const destination = path.join(getDocsPublicFsPath())
|
|
|
|
copyStaticRecursively(source, destination)
|
|
}
|
|
|
|
// Alias (copy) some static files to different paths.
|
|
function aliasStatic() {
|
|
const source = getDocsStaticFsPath()
|
|
const destination = path.join(getDocsPublicFsPath())
|
|
|
|
for (const [aliasSource, aliasDestination] of Object.entries(staticFileAliases)) {
|
|
fs.cpSync(path.join(source, aliasSource), path.join(destination, aliasDestination))
|
|
}
|
|
}
|
|
|
|
// See `copyStatic()` for more details.
|
|
function copyStaticRecursively(source: string, destination: string) {
|
|
const entries = fs.readdirSync(source, { withFileTypes: true })
|
|
|
|
for (const entry of entries) {
|
|
if (entry.isFile()) {
|
|
fs.cpSync(path.join(source, entry.name), replacePathVersionPlaceholder(path.join(destination, entry.name)))
|
|
} else if (entry.isDirectory()) {
|
|
fs.mkdirSync(replacePathVersionPlaceholder(path.join(destination, entry.name)), { recursive: true })
|
|
|
|
copyStaticRecursively(path.join(source, entry.name), path.join(destination, entry.name))
|
|
}
|
|
}
|
|
}
|
|
|
|
function replacePathVersionPlaceholder(name: string) {
|
|
return name.replace('[version]', getConfig().docs_version)
|
|
}
|
|
|
|
function sitemapFilter(page: string, excludedUrls: string[]) {
|
|
if (excludedUrls.includes(page)) {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|