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
litegalanddataview - 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.