astro-gists/package/src/ExpressiveCode/components/Code.astro

81 lines
3.2 KiB
Plaintext

---
import { toHtml } from 'hast-util-to-html'
import { getPageData } from './page-data';
import { engine } from '../index'
// Extract the code and other props from the Astro component
const {
code,
raw_url,
locale,
lang = '',
meta = '',
...props
} = Astro.props
// Get the current block group index from the page data
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
// Get the base and theme styles, and the JS modules from the ExpressiveCode engine
const baseStyles = await engine.getBaseStyles();
const themeStyles = await engine.getThemeStyles();
const jsModules = await engine.getJsModules();
// Render the code using the ExpressiveCode engine
const { renderedGroupAst, styles } = await engine.render({
language: lang, meta, locale, code,
parentDocument: {
positionInDocument: { groupIndex,},
},
props, })
// Convert the rendered group AST to HTML
let htmlContent = toHtml(renderedGroupAst)
// Prepend the base and theme styles to the HTML content
const stylesToPrepend: string[] = []
stylesToPrepend.push(baseStyles, themeStyles, ...styles)
if (stylesToPrepend.length) {
htmlContent = `<style>${[...stylesToPrepend].join('').replace(/\.expressive-code/g, '.gist .expressive-code')}</style>${htmlContent}`
}
// Prepend the JS modules to the HTML content
const scriptsToPrepend: string[] = []
scriptsToPrepend.push(...jsModules)
if (scriptsToPrepend.length) {
htmlContent = `<script type="module">${[...scriptsToPrepend].join('')}</script>${htmlContent}`
}
---
<a class="raw inline not-content" title="GitHub Gist RAW" href={raw_url}><button class="inline not-content">View Gist<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="currentColor" class="not-content inline bi bi-filetype-raw" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M14 4.5V14a2 2 0 0 1-2 2v-1a1 1 0 0 0 1-1V4.5h-2A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v9H2V2a2 2 0 0 1 2-2h5.5zM1.597 11.85H0v3.999h.782v-1.491h.71l.7 1.491h1.651l.313-1.028h1.336l.314 1.028h.84L5.31 11.85h-.925l-1.329 3.96-.783-1.572A1.18 1.18 0 0 0 3 13.116q0-.384-.167-.668a1.1 1.1 0 0 0-.478-.44 1.7 1.7 0 0 0-.758-.158m-.815 1.913v-1.292h.7a.74.74 0 0 1 .507.17q.194.17.194.49 0 .315-.194.474-.19.158-.518.158zm4.063-1.148.489 1.617H4.32l.49-1.617zm4.006.445-.74 2.789h-.73L6.326 11.85h.855l.601 2.903h.038l.706-2.903h.683l.706 2.903h.04l.596-2.903h.858l-1.055 3.999h-.73l-.74-2.789H8.85Z"/> </svg></button></a>
<div class="my-1" />
<div class="gist not-content">
<Fragment set:html={htmlContent} />
</div>
<style>
.my-1 {
line-break: loose;
padding-bottom: 1.5rem;
}
.raw {
float: right;
height: auto;
border-radius: 1px;
background-color: transparent;
background: transparent;
color: black;
padding-inline-end: 1rem;
text-decoration: none;
}
.inline { display: inline-flex; }
.gist {
padding-top: 1rem;
padding-bottom: 1rem;
}
</style>