mirror of
https://github.com/sern-handler/website
synced 2026-06-19 06:12:19 +00:00
71 lines
2.0 KiB
Plaintext
71 lines
2.0 KiB
Plaintext
---
|
|
import { addClassName, toHtml } from 'rehype-expressive-code/hast'
|
|
import { getPageData } from './page-data'
|
|
import { getRenderer } from './renderer'
|
|
import type { CodeProps as Props, MarkerValueType } from './types'
|
|
|
|
function formatMessage(...messageParts: string[]) {
|
|
return messageParts.map((part) => part.replace(/\s+/g, ' ')).join('\n\n')
|
|
}
|
|
|
|
async function renderToHtml() {
|
|
const defaultSlotContent = await Astro.slots.render('default')
|
|
if (defaultSlotContent?.trim().length) {
|
|
throw new Error(
|
|
formatMessage(
|
|
`Unsupported child content was found inside the component.
|
|
The code to render must be passed to the \`code\` prop as a string.`,
|
|
`Please remove the following child content:\n${defaultSlotContent}`
|
|
)
|
|
)
|
|
}
|
|
|
|
let { code, lang = '', meta = '', locale, class: className, ...props } = Astro.props
|
|
|
|
if (!code || !code.trim().length) {
|
|
throw new Error('Missing code to render. The `code` prop must be set to a non-empty string.')
|
|
}
|
|
|
|
const pageData = getPageData(Astro.request)
|
|
// Note: It's important to store the incremented index in a local variable immediately,
|
|
// as the `pageData` object is shared between all components on the current page
|
|
// and can be changed by other Code components during the `await` calls below
|
|
const groupIndex = ++pageData.blockGroupIndex
|
|
|
|
const renderer = await getRenderer()
|
|
|
|
const { renderedGroupAst } = await renderer.ec.render({
|
|
code,
|
|
language: lang,
|
|
meta,
|
|
locale,
|
|
parentDocument: {
|
|
positionInDocument: {
|
|
groupIndex,
|
|
},
|
|
},
|
|
props,
|
|
})
|
|
|
|
if (renderedGroupAst?.type === 'element') {
|
|
if (className) {
|
|
const classNames = className.split(' ')
|
|
classNames.forEach((className) => addClassName(renderedGroupAst, className))
|
|
}
|
|
}
|
|
|
|
return toHtml(renderedGroupAst)
|
|
}
|
|
|
|
let html = ''
|
|
try {
|
|
html = await renderToHtml()
|
|
} catch (err) {
|
|
const prefix = `Failed to render a \`<Code>\` component on page ${Astro.request.url}:`
|
|
const error = err instanceof Error ? err : new Error(String(err))
|
|
throw new Error(`${prefix}\n\n${error.message}`, { cause: error })
|
|
}
|
|
---
|
|
|
|
<Fragment set:html={html} />
|