Skip to content

Citation Directive Implementation

This document describes the citation directive feature for highlighting text with source references.

Overview

The citation directive allows you to wrap content with source references and provides hover highlighting functionality. When a user hovers over a source reference, the associated text will be highlighted.

Syntax

Use the text directive syntax from remark-directive:

:cit[my content]{sources=1,2}

Where:

  • :cit is the directive name
  • [my content] is the content to be wrapped
  • {sources=1,2} specifies the source IDs (comma-separated)

Example Usage

Old approach (still supported):

# My Answer

More content [1]

Real-world example:

In South Africa, the socks market in 2025 is expected to generate approximately US$26.62 million with a projected growth to US$32.98 million by 2029, driven by a CAGR of 5.50%, and a per capita expenditure of US$0.41 [1][2].

New approach with citation directive:

# My Answer

:cit[More content]{sources=1}

Multiple sources:
:cit[This data comes from multiple sources]{sources=1,2,3}

Component Architecture

1. remarkCitationPlugin (utils/remark-citation-plugin.ts)

  • Remark plugin that parses :cit[content]{sources=...} directives
  • Converts them to <span class="citation" data-sources="1,2,3">content</span>

2. Citation (components/citation/citation.tsx)

  • React component that wraps content and displays source badges
  • Handles hover highlighting via the HOVER_POPOVER_EVENT system
  • Supports both desktop (Popover) and mobile (BottomSheet) interactions
  • Highlights the entire citation span when any of its sources are hovered

3. MarkdownAnswer (components/markdown-answer/markdown-answer.tsx)

  • Updated to include remarkDirective and remarkCitationPlugin in the plugin chain
  • Custom span renderer that detects citation spans and renders them with the Citation component

Features

  • ✅ Hover highlighting: When hovering over a source badge, the entire citation text is highlighted
  • ✅ Multiple sources: Supports multiple source references per citation
  • ✅ Desktop/Mobile support: Uses Popover on desktop and BottomSheet on mobile
  • ✅ Event system: Integrates with existing HOVER_POPOVER_EVENT for coordinated highlighting
  • ✅ Backward compatible: Old [1] syntax still works via SourceReference component

Technical Details

Dependencies

  • remark-directive: Core directive parsing
  • mdast-util-directive: TypeScript types for directives
  • unist-util-visit: AST traversal utility

Styling

The highlight effect is achieved with:

className={`inline-block transition-all ${
  isAnySourceHovered
    ? "bg-primary-subtle rounded"
    : ""
}`}

Integration with existing code

  • Reuses Source type from source-reference
  • Reuses SourceBadge, Popover, PopoverSourceContent, and BottomSheet components
  • Integrates with existing HOVER_POPOVER_EVENT system for cross-component highlighting

Migration Path

  1. Backend changes: Update answer generation to use citation directive syntax
  2. Frontend changes: Already implemented (this PR)
  3. Gradual rollout: Both old and new syntax work simultaneously
  4. Future: Deprecate old [n] syntax once all answers use directives

Testing

To test:

  1. Use markdown with citation directives in your answer
  2. Hover over source badges to see the text highlight
  3. Test on both desktop and mobile viewports
  4. Verify multiple sources per citation work correctly