Code Block Rendering System
Code Block Rendering System
Overview
This technical specification documents the implementation of a flexible, component-based code block rendering system for the Astro site. The system supports custom language rendering, syntax highlighting, and interactive features like copy-to-clipboard functionality.
Architecture
The code block rendering system consists of several interconnected components:
- Astro Configuration: Configures Shiki for syntax highlighting and registers custom languages
- Remark Plugin: Transforms markdown code blocks into component-based renderers
- Base Component: Provides core rendering and copy functionality
- Language-Specific Components: Extend the base component with language-specific styling and features
- Global CSS: Enhances styling for all code blocks
Components
1. Astro Configuration (astro.config.mjs
)
The Astro configuration sets up Shiki for syntax highlighting and registers custom languages like
litegal
and dataview
. It also configures the markdown processing pipeline to use our custom remark plugin. javascript
// Register custom languages for syntax highlighting
shikiConfig: {
theme: 'github-dark',
langs: [
{
id: 'litegal',
scopeName: 'source.litegal',
grammar: {
patterns: [
// Language-specific patterns
]
}
},
// Other custom languages
]
}
2. Remark Plugin (remark-codeblocks.ts
)
This plugin transforms markdown code blocks into component-based renderers based on the language specified.
typescript
visit(tree, 'code', (node: Code, index: number, parent: Parent | null) => {
if (!parent) return;
const lang = node.lang || 'text';
// Determine which component to use based on language
let componentName = 'BaseCodeblock';
if (lang === 'litegal') {
componentName = 'LitegalCodeblockDisplay';
} else if (lang === 'dataview') {
componentName = 'DataviewCodeblockDisplay';
}
// Create an MDX component node
const mdxNode: MdxJsxFlowElement = {
// Component configuration
};
// Replace the original code node with our custom component
parent.children[index] = mdxNode as any;
});
3. Base Component (BaseCodeblock.astro
)
The base component provides core rendering and copy functionality for all code blocks.
astro
<div class="codeblock-container">
<div class="codeblock-header">
<span class="codeblock-language">{lang}</span>
<button class="copy-button" aria-label="Copy code to clipboard">
<!-- Copy icon SVG -->
</button>
</div>
<pre class="codeblock" data-language={lang}>
<code>
{code}
</code>
</pre>
</div>
<script>
// Copy-to-clipboard functionality
</script>
4. Language-Specific Components
Language-specific components extend the base component with custom styling and features.
Example:
LitegalCodeblockDisplay.astro
astro
<BaseCodeblock code={code} lang={lang}>
<style>
/* Add litegal-specific styles here */
.codeblock--litegal {
background-color: #f4f4f4;
border-left: 4px solid #4a9eff;
}
</style>
</BaseCodeblock>
5. Global CSS (codeblocks.css
)
Provides consistent styling for all code blocks, including those rendered directly by Shiki.
css
/* Base code block styling */
pre {
padding: 1.25rem;
margin: 1.5rem 0;
border-radius: 0.5rem;
/* Additional styling */
}
/* Language-specific styling */
pre[data-language="typescript"] {
border-left: 4px solid var(--clr-lossless-accent--brightest, #4a9eff);
}
/* Additional styles for our component-based approach */
.codeblock-container {
margin: 1.5rem 0;
}
Features
- Syntax Highlighting: Uses Shiki for high-quality syntax highlighting
- Custom Language Support: Supports custom languages like
litegal
anddataview
- Copy-to-Clipboard: Provides a button to copy code to clipboard with visual feedback
- Language Indicator: Shows the language of the code block
- Language-Specific Styling: Different styling based on the language
Implementation Details
Copy-to-Clipboard Functionality
The copy-to-clipboard functionality is implemented using the Clipboard API:
javascript
navigator.clipboard.writeText(code)
.then(() => {
// Visual feedback on successful copy
copyButton.classList.add('copied');
// Change icon to checkmark
// Reset after 2 seconds
})
.catch((error) => {
// Error handling
});
Custom Language Registration
Custom languages are registered with Shiki by defining a grammar with patterns for different syntax elements:
javascript
{
id: 'litegal',
scopeName: 'source.litegal',
grammar: {
patterns: [
{ match: '\\b(function|return|if|else|for|while)\\b', name: 'keyword.control.litegal' },
// Other patterns
]
}
}
Integration with Markdown Processing Pipeline
The code block rendering system integrates with Astro's markdown processing pipeline through the remark plugin system:
javascript
markdown: {
remarkPlugins: [
// Other plugins
remarkCodeblocks // Transform code blocks
],
// Other configuration
}
Future Enhancements
- Line Highlighting: Add support for highlighting specific lines in code blocks
- Line Numbers: Add line numbers to code blocks
- Code Folding: Allow collapsing sections of code
- Interactive Examples: Add support for runnable code examples
- More Custom Languages: Add support for additional custom languages
Conclusion
The code block rendering system provides a flexible, component-based approach to rendering code blocks in markdown content. It leverages Astro's built-in capabilities while adding custom features like copy-to-clipboard functionality and language-specific styling.