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