
| Current Path : /var/www/html/12park/vendor/twbs/bootstrap/site/src/libs/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : /var/www/html/12park/vendor/twbs/bootstrap/site/src/libs/remark.ts |
import type { Root } from 'mdast'
import type { MdxJsxAttribute, MdxJsxExpressionAttribute } from 'mdast-util-mdx-jsx'
import type { Plugin } from 'unified'
import { visit } from 'unist-util-visit'
import { getConfig } from './config'
import { getVersionedDocsPath } from './path'
// [[config:foo]]
// [[config:foo.bar]]
const configRegExp = /\[\[config:(?<name>[\w\.]+)]]/g
// [[docsref:/foo]]
// [[docsref:/foo/bar#baz]]
const docsrefRegExp = /\[\[docsref:(?<path>[\w\.\/#-]+)]]/g
// A remark plugin to replace config values embedded in markdown (or MDX) files.
// For example, [[config:foo]] will be replaced with the value of the `foo` key in the `config.yml` file.
// Nested values are also supported, e.g. [[config:foo.bar]].
// Note: this also works in frontmatter.
// Note: this plugin is meant to facilitate the migration from Hugo to Astro while keeping the differences to a minimum.
// At some point, this plugin should maybe be removed and embrace a more MDX-friendly syntax.
export const remarkBsConfig: Plugin<[], Root> = function () {
return function remarkBsConfigPlugin(ast, file) {
if (containsFrontmatter(file.data.astro)) {
replaceInFrontmatter(file.data.astro.frontmatter, replaceConfigInText)
}
// https://github.com/syntax-tree/mdast#nodes
// https://github.com/syntax-tree/mdast-util-mdx-jsx#nodes
visit(ast, ['code', 'definition', 'image', 'inlineCode', 'link', 'mdxJsxFlowElement', 'text'], (node) => {
switch (node.type) {
case 'code':
case 'inlineCode':
case 'text': {
node.value = replaceConfigInText(node.value)
break
}
case 'image': {
if (node.alt) {
node.alt = replaceConfigInText(node.alt)
}
node.url = replaceConfigInText(node.url)
break
}
case 'definition':
case 'link': {
node.url = replaceConfigInText(node.url)
break
}
case 'mdxJsxFlowElement': {
node.attributes = replaceConfigInAttributes(node.attributes)
break
}
}
})
}
}
// A remark plugin to add versioned docs links in markdown (or MDX) files.
// For example, [[docsref:/foo]] will be replaced with the `/docs/${docs_version}/foo` value with the `docs_version`
// value being read from the `config.yml` file.
// Note: this also works in frontmatter.
// Note: this plugin is meant to facilitate the migration from Hugo to Astro while keeping the differences to a minimum.
// At some point, this plugin should maybe be removed and embrace a more MDX-friendly syntax.
export const remarkBsDocsref: Plugin<[], Root> = function () {
return function remarkBsDocsrefPlugin(ast, file) {
if (containsFrontmatter(file.data.astro)) {
replaceInFrontmatter(file.data.astro.frontmatter, replaceDocsrefInText)
}
// https://github.com/syntax-tree/mdast#nodes
// https://github.com/syntax-tree/mdast-util-mdx-jsx#nodes
visit(ast, ['definition', 'link', 'mdxJsxTextElement'], (node) => {
switch (node.type) {
case 'definition':
case 'link': {
node.url = replaceDocsrefInText(node.url)
break
}
case 'mdxJsxTextElement': {
node.attributes = replaceDocsrefInAttributes(node.attributes)
break
}
}
})
}
}
export function replaceConfigInText(text: string) {
return text.replace(configRegExp, (_match, path) => {
const value = getConfigValueAtPath(path)
if (!value) {
throw new Error(`Failed to find a valid configuration value for '${path}'.`)
}
return value
})
}
function replaceConfigInAttributes(attributes: (MdxJsxAttribute | MdxJsxExpressionAttribute)[]) {
return attributes.map((attribute) => {
if (attribute.type === 'mdxJsxAttribute' && typeof attribute.value === 'string') {
attribute.value = replaceConfigInText(attribute.value)
}
return attribute
})
}
function replaceDocsrefInText(text: string) {
return text.replace(docsrefRegExp, (_match, path) => {
return getVersionedDocsPath(path)
})
}
function replaceDocsrefInAttributes(attributes: (MdxJsxAttribute | MdxJsxExpressionAttribute)[]) {
return attributes.map((attribute) => {
if (attribute.type === 'mdxJsxAttribute' && typeof attribute.value === 'string') {
attribute.value = replaceDocsrefInText(attribute.value)
}
return attribute
})
}
function getConfigValueAtPath(path: string) {
const config = getConfig()
const value = path.split('.').reduce((values, part) => {
if (!values || typeof values !== 'object') {
return undefined
}
return (values as any)?.[part]
}, config as unknown)
return typeof value === 'string' ? value : undefined
}
function replaceInFrontmatter(record: Record<string, unknown>, replacer: (value: string) => string) {
for (const [key, value] of Object.entries(record)) {
if (typeof value === 'string') {
record[key] = replacer(value)
} else if (Array.isArray(value)) {
record[key] = value.map((arrayValue) => {
return typeof arrayValue === 'string'
? replacer(arrayValue)
: typeof arrayValue === 'object'
? replaceInFrontmatter(arrayValue, replacer)
: arrayValue
})
}
}
return record
}
function containsFrontmatter(data: unknown): data is { frontmatter: Record<string, unknown> } {
return data != undefined && typeof data === 'object' && 'frontmatter' in data
}