Fixed Slides Directive Rendering in Reader Layout

Summary

Fixed slides directive not rendering in essay reader pages by adding missing remark-directive plugins to CollectionReaderLayout.astro. Both :::slides and :::slideshow directive syntax now work alongside existing custom codeblock syntax for embedding presentations.

Why Care

This fix completes the slides directive implementation, ensuring consistent directive processing across all layout types. Content authors can now use both custom codeblock syntax (`````slides) and directive syntax (:::slideshow`) interchangeably to embed slide presentations in essays and other reader content. The naming flexibility prevents conflicts between language identifiers and directive names.

Implementation

Changes Made

  • Added missing remark-directive plugins to /src/layouts/CollectionReaderLayout.astro
  • Updated directive mapping in /src/utils/markdown/remark-directives.ts to support both 'slides' and 'slideshow' names
  • Enhanced AstroMarkdown.astro to handle both directive variants
  • Added slides route mapping in routeManager.ts for proper backlink resolution

File Tree of Changes

text
site/
├── src/
│   ├── layouts/
│   │   └── CollectionReaderLayout.astro (modified)
│   ├── utils/
│   │   └── markdown/
│   │       └── remark-directives.ts (modified)
│   │   └── routing/
│   │       └── routeManager.ts (modified)
│   └── components/
│       └── markdown/
│           └── AstroMarkdown.astro (modified)

Technical Details

Root Cause Analysis

The issue was layout-specific: while directives worked correctly on market-map pages (using OneArticle layout), they appeared as plain text on essay pages (using CollectionReaderLayout). The CollectionReaderLayout was missing the remark-directive processing plugins in its unified() processor chain.

CollectionReaderLayout Fix

In /src/layouts/CollectionReaderLayout.astro:
typescript
// Added missing imports
import remarkDirective from 'remark-directive';
import { remarkDirectiveToComponent } from '@utils/markdown/remark-directives';

// Updated processor chain
const processor = unified()
  .use(remarkParse)
  .use(remarkGfm)
  .use(remarkDirective)              // Parse directive syntax
  .use(remarkDirectiveToComponent)   // Preserve directives for AstroMarkdown
  .use(remarkImages) 
  .use(remarkBacklinks)
  .use(remarkCitations)
  .use(remarkTableOfContents);

Directive Mapping Enhancement

In /src/utils/markdown/remark-directives.ts:
typescript
export const directiveComponentMap: Record<string, string> = {
  'figma-embed': 'Figma-Object--Display.astro',
  'tool-showcase': 'toolkit/ToolShowcaseIsland.astro',
  'slides': 'direct',      // Handled directly in AstroMarkdown.astro
  'slideshow': 'direct',   // Alternative name to avoid conflict with slides codeblock
};

AstroMarkdown Directive Handling

In /src/components/markdown/AstroMarkdown.astro (around line 1354):
typescript
if (directiveName === 'slides' || directiveName === 'slideshow') {
  // Parse the container content for markdown list items with slide backlinks
  const slides = [];
  const config = node.attributes || {};
  
  // Process nested content to extract slide references
  if (node.children && node.children.length > 0) {
    const listContent = node.children.find(child => child.type === 'list');
    if (listContent && listContent.children) {
      // Extract slide URLs from list items
    }
  }
  
  // Render embedded slideshow iframe
  return (
    <div class="slides-directive-container">
      <iframe src={slidesUrl} width="100%" height="600" />
    </div>
  );
}
In /src/utils/routing/routeManager.ts:
typescript
{
  contentPath: 'slides',
  routePath: 'slides'
},

Integration Points

  • Layout Hierarchy: Essays flow through CollectionReaderLayout → processedHtml → AstroMarkdown → Component rendering
  • Plugin Chain: remarkDirective parses syntax → remarkDirectiveToComponent preserves nodes → AstroMarkdown renders components
  • Naming Strategy: Both 'slides' and 'slideshow' supported to avoid conflicts with existing slides language identifier in custom codeblocks
  • Backlink Resolution: Slides collection properly mapped for [[slides/filename|Title]] syntax

Documentation

  • Usage Example:
    markdown
    :::slideshow
    - [[slides/git-basics|Git Basics for Teams]]
    - [[slides/ai-workflow|AI Workflow Patterns]]
    :::
  • Alternative Syntax: Both :::slides and :::slideshow work identically
  • Backward Compatibility: Existing custom codeblock syntax (`````slides`) continues to work unchanged
  • Error Handling: Unknown directives display debug information in development mode

Testing Verification

  • ✅ Directive renders correctly on /read/through/essays/consistent-go-to-market
  • ✅ Backlinks resolve to proper slide URLs
  • ✅ Both :::slides and :::slideshow syntax work
  • ✅ Custom codeblock syntax continues to work
  • ✅ Directives continue working on market-map pages