Technical Specification - Custom Code Block Rendering in Astro

Custom Code Block Rendering in Astro

Executive Summary

Problem Statement

Our markdown content includes code blocks with custom languages (litegal and dataview) that require specialized rendering. While Astro's default syntax highlighter (Shiki) doesn't recognize these languages, we need a way to handle them gracefully without breaking the build process.

Solution Overview

Implement a component-based approach using MDX that:
  1. Creates specialized components for each custom code block type
  2. Registers custom languages with Shiki to prevent build warnings
  3. Maintains a flexible, composable architecture for future custom languages

Technical Details

Component Architecture

  1. Base Component (BaseCodeblock.astro)
    • Provides foundational styling and structure
    • Renders code content with minimal styling
    • Acts as a fallback for unknown languages
  2. Specialized Components
    • LitegalCodeblockDisplay.astro: Handles Litegal syntax
    • DataviewCodeblockDisplay.astro: Handles Dataview syntax
    • Both extend BaseCodeblock with language-specific styling

Integration Points

  1. MDX Configuration
    typescript
    // astro.config.mjs
    markdown: {
      syntaxHighlight: false, // Disable Shiki's syntax highlighting
      shikiConfig: {
        theme: 'github-dark',
        langs: [
          {
            id: 'litegal',
            scopeName: 'source.litegal',
            grammar: {
              patterns: [{ match: '.*', name: 'text.litegal' }]
            }
          },
          {
            id: 'dataview',
            scopeName: 'source.dataview',
            grammar: {
              patterns: [{ match: '.*', name: 'text.dataview' }]
            }
          }
        ]
      }
    }
  2. Content Collection Configuration
    typescript
    // content.config.ts
    const pagesCollection = defineCollection({
      type: 'content',
      schema: z.object({
        title: z.string()
      }).catchall(z.any()) // Flexible schema for AI-generated content
    });

Usage Example

mdx
---
title: 'Testing MDX Integration'
---
import BaseCodeblock from '../../components/codeblocks/BaseCodeblock.astro';
import LitegalCodeblock from '../../components/codeblocks/LitegalCodeblockDisplay.astro';
import DataviewCodeblock from '../../components/codeblocks/DataviewCodeblockDisplay.astro';

<LitegalCodeblock code={`function test() {
  console.log("Hello from litegal!");
}`} />

<DataviewCodeblock code={`dataview
table file.name, tags
from "content"
where file.name = this.file.name`} />

Implementation Status

Completed

  • Basic component structure
  • Shiki language registration
  • MDX integration
  • Content collection configuration

Pending

  • Enhanced syntax highlighting
  • Language-specific features
  • Error boundary implementation
  • Documentation for adding new languages

Design Decisions

  1. Component Composition over Configuration
    • Each language gets its own component
    • Makes it easy to add new languages
    • Allows for language-specific features
  2. Minimal Schema Validation
    • Following project rules for AI-generated content
    • Only validate structural requirements (arrays vs objects)
    • Use .catchall() for maximum flexibility
  3. Custom Language Registration
    • Register with Shiki to prevent build warnings
    • Simple grammar patterns for now
    • Can be enhanced later for proper syntax highlighting

Future Considerations

  1. Performance Optimization
    • Lazy loading of language-specific components
    • Caching of rendered code blocks
  2. Enhanced Features
    • Line highlighting
    • Code copying
    • Interactive elements
  3. Documentation
    • Guide for adding new languages
    • Component API reference
    • Usage examples