Line numbers in Markdown code blocks transform simple code examples into professional, navigable documentation that enhances readability and enables precise reference communication. While standard Markdown doesn’t include built-in line numbering, various platforms, extensions, and custom solutions provide sophisticated approaches to adding numbered lines that improve code comprehension and collaborative development workflows.

Why Use Line Numbers in Code Blocks?

Line numbers provide significant advantages for technical documentation and code sharing:

  • Precise Reference: Enable exact line references in discussions and code reviews
  • Enhanced Navigation: Help readers locate specific sections in lengthy code examples
  • Professional Presentation: Create publication-quality code documentation
  • Improved Debugging: Facilitate error reporting and troubleshooting discussions
  • Educational Value: Support step-by-step code explanations and tutorials

Platform-Specific Line Number Implementations

GitHub Flavored Markdown

GitHub supports line number highlighting through URL anchors:

## JavaScript Authentication Example

```javascript
// Complete authentication system with error handling
class AuthenticationManager {
    constructor(config) {
        this.config = {
            tokenExpiry: config.tokenExpiry || 3600000, // 1 hour default
            maxLoginAttempts: config.maxAttempts || 5,
            lockoutDuration: config.lockoutDuration || 300000, // 5 minutes
            secretKey: config.secretKey || process.env.JWT_SECRET
        };
        this.loginAttempts = new Map(); // Track failed attempts
        this.lockedAccounts = new Map(); // Track account lockouts
    }
    
    async authenticate(email, password) {
        // Check if account is currently locked
        if (this.isAccountLocked(email)) {
            throw new Error('Account temporarily locked due to multiple failed attempts');
        }
        
        try {
            // Validate input parameters
            if (!this.isValidEmail(email) || !password) {
                this.recordFailedAttempt(email);
                throw new Error('Invalid email or password format');
            }
            
            // Attempt user authentication
            const user = await this.validateCredentials(email, password);
            if (!user) {
                this.recordFailedAttempt(email);
                throw new Error('Authentication failed: Invalid credentials');
            }
            
            // Generate access token for authenticated user
            const token = this.generateToken(user);
            this.clearFailedAttempts(email); // Reset failed attempts on success
            
            return {
                success: true,
                token: token,
                user: this.sanitizeUser(user),
                expiresAt: new Date(Date.now() + this.config.tokenExpiry)
            };
            
        } catch (error) {
            console.error('Authentication error:', error.message);
            throw error;
        }
    }
}
```

**Reference specific lines in discussions:**
- Line 15: Account lockout check prevents brute force attacks
- Lines 25-28: Input validation with attempt tracking
- Lines 35-42: Token generation and success response

GitLab Markdown Extensions

GitLab provides enhanced code block features with line number support:

## Python Data Processing Pipeline

```python
# Advanced data processing pipeline with error handling and logging
import pandas as pd
import numpy as np
import logging
from typing import Dict, List, Optional, Tuple
from pathlib import Path
import json

class DataProcessor:
    """
    Comprehensive data processing pipeline for CSV and JSON data sources.
    Includes validation, transformation, and export capabilities.
    """
    
    def __init__(self, config_path: str = "config.json"):
        self.logger = self._setup_logging()
        self.config = self._load_config(config_path)
        self.processed_data: Optional[pd.DataFrame] = None
        self.processing_stats: Dict = {}
        
    def _setup_logging(self) -> logging.Logger:
        """Configure logging for data processing operations"""
        logger = logging.getLogger('DataProcessor')
        logger.setLevel(logging.INFO)
        
        if not logger.handlers:
            handler = logging.StreamHandler()
            formatter = logging.Formatter(
                '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
            )
            handler.setFormatter(formatter)
            logger.addHandler(handler)
            
        return logger
    
    def _load_config(self, config_path: str) -> Dict:
        """Load processing configuration from JSON file"""
        try:
            with open(config_path, 'r') as file:
                config = json.load(file)
            self.logger.info(f"Configuration loaded from {config_path}")
            return config
        except FileNotFoundError:
            self.logger.warning(f"Config file not found: {config_path}, using defaults")
            return self._get_default_config()
        except json.JSONDecodeError as e:
            self.logger.error(f"Invalid JSON in config file: {e}")
            raise ValueError(f"Configuration file contains invalid JSON: {e}")
    
    def process_csv_data(self, file_path: str, delimiter: str = ',') -> pd.DataFrame:
        """
        Process CSV data with comprehensive validation and cleaning.
        
        Args:
            file_path: Path to CSV file
            delimiter: CSV delimiter character
            
        Returns:
            Processed DataFrame with cleaned and validated data
        """
        try:
            # Load CSV data with error handling
            self.logger.info(f"Loading CSV data from {file_path}")
            raw_data = pd.read_csv(file_path, delimiter=delimiter)
            
            # Record initial data statistics
            initial_rows = len(raw_data)
            self.processing_stats['initial_rows'] = initial_rows
            self.logger.info(f"Loaded {initial_rows} rows from CSV")
            
            # Data validation and cleaning pipeline
            cleaned_data = self._validate_data_types(raw_data)
            cleaned_data = self._handle_missing_values(cleaned_data)
            cleaned_data = self._remove_duplicates(cleaned_data)
            cleaned_data = self._apply_transformations(cleaned_data)
            
            # Record final statistics
            final_rows = len(cleaned_data)
            self.processing_stats['final_rows'] = final_rows
            self.processing_stats['rows_removed'] = initial_rows - final_rows
            self.processing_stats['data_quality_score'] = self._calculate_quality_score(cleaned_data)
            
            self.processed_data = cleaned_data
            self.logger.info(f"Processing complete: {final_rows} clean rows")
            
            return cleaned_data
            
        except Exception as e:
            self.logger.error(f"CSV processing failed: {e}")
            raise RuntimeError(f"Failed to process CSV data: {e}")
```

**Line-specific documentation:**
- Lines 15-19: Constructor initializes core components and statistics tracking
- Lines 21-33: Logging setup with proper formatting and level configuration  
- Lines 50-78: CSV processing pipeline with comprehensive error handling
- Lines 65-69: Data cleaning operations applied sequentially

Prism.js Line Number Plugin

Enable client-side line numbering with Prism.js:

<!-- Prism.js setup with line numbers -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Code Documentation with Line Numbers</title>
    
    <!-- Prism.js core CSS -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" rel="stylesheet" />
    
    <!-- Line numbers plugin CSS -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/line-numbers/prism-line-numbers.min.css" rel="stylesheet" />
    
    <!-- Line highlight plugin CSS -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/line-highlight/prism-line-highlight.min.css" rel="stylesheet" />
</head>
<body>
    <!-- Code block with line numbers and highlighting -->
    <pre class="line-numbers" data-line="5-8,12,15-17"><code class="language-javascript">
// React component with hooks and state management
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { debounce } from 'lodash';

// Custom hook for API data fetching with caching
function useAPIData(endpoint, options = {}) {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState(null);
    const [cache, setCache] = useState(new Map());
    
    // Memoized fetch function with caching logic
    const fetchData = useCallback(async (url, fetchOptions) => {
        const cacheKey = `${url}_${JSON.stringify(fetchOptions)}`;
        
        // Check cache first to avoid unnecessary requests
        if (cache.has(cacheKey)) {
            const cachedData = cache.get(cacheKey);
            if (Date.now() - cachedData.timestamp < 300000) { // 5 minute cache
                setData(cachedData.data);
                return cachedData.data;
            }
        }
        
        setLoading(true);
        setError(null);
        
        try {
            const response = await fetch(url, fetchOptions);
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const result = await response.json();
            
            // Update cache with timestamp
            setCache(prev => new Map(prev.set(cacheKey, {
                data: result,
                timestamp: Date.now()
            })));
            
            setData(result);
            return result;
            
        } catch (err) {
            setError(err.message);
            throw err;
        } finally {
            setLoading(false);
        }
    }, [cache]);
    
    // Debounced API call to prevent excessive requests
    const debouncedFetch = useMemo(
        () => debounce(fetchData, 300),
        [fetchData]
    );
    
    // Effect for initial data loading
    useEffect(() => {
        if (endpoint) {
            fetchData(endpoint, options);
        }
    }, [endpoint, fetchData, options]);
    
    return {
        data,
        loading,
        error,
        refetch: () => fetchData(endpoint, options),
        debouncedRefetch: () => debouncedFetch(endpoint, options)
    };
}
    </code></pre>
    
    <!-- Prism.js core JavaScript -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
    
    <!-- Line numbers plugin -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/line-numbers/prism-line-numbers.min.js"></script>
    
    <!-- Line highlight plugin -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/line-highlight/prism-line-highlight.min.js"></script>
</body>
</html>

CSS-Based Line Number Solutions

Pure CSS Implementation

Create line numbers using CSS counters and pseudo-elements:

/* CSS-only line numbers for code blocks */
.code-with-lines {
    position: relative;
    background-color: #f8f8f8;
    border: 1px solid #e1e1e1;
    border-radius: 6px;
    padding: 0;
    margin: 1.5rem 0;
    overflow-x: auto;
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    font-size: 14px;
    line-height: 1.4;
}

.code-with-lines pre {
    margin: 0;
    padding: 1rem 1rem 1rem 3.5rem;
    counter-reset: line-counter;
    white-space: pre;
    overflow: visible;
}

.code-with-lines code {
    display: block;
    counter-increment: line-counter;
    position: relative;
}

.code-with-lines code::before {
    content: counter(line-counter);
    position: absolute;
    left: -3rem;
    width: 2.5rem;
    text-align: right;
    color: #666;
    font-size: 12px;
    line-height: inherit;
    padding-right: 0.5rem;
    border-right: 1px solid #ddd;
    background-color: #f0f0f0;
    user-select: none;
}

/* Syntax highlighting integration */
.code-with-lines .token.comment {
    color: #6a9955;
    font-style: italic;
}

.code-with-lines .token.string {
    color: #ce9178;
}

.code-with-lines .token.keyword {
    color: #569cd6;
    font-weight: bold;
}

.code-with-lines .token.function {
    color: #dcdcaa;
}

.code-with-lines .token.number {
    color: #b5cea8;
}

/* Dark theme support */
@media (prefers-color-scheme: dark) {
    .code-with-lines {
        background-color: #1e1e1e;
        border-color: #404040;
        color: #d4d4d4;
    }
    
    .code-with-lines code::before {
        background-color: #2d2d2d;
        color: #858585;
        border-right-color: #404040;
    }
    
    .code-with-lines .token.comment {
        color: #6a9955;
    }
    
    .code-with-lines .token.string {
        color: #ce9178;
    }
    
    .code-with-lines .token.keyword {
        color: #569cd6;
    }
}

/* Responsive adjustments */
@media (max-width: 768px) {
    .code-with-lines {
        font-size: 12px;
    }
    
    .code-with-lines pre {
        padding-left: 2.5rem;
    }
    
    .code-with-lines code::before {
        left: -2.5rem;
        width: 2rem;
        font-size: 10px;
    }
}

Advanced Styling with Highlighting

Create sophisticated line number displays with highlighting capabilities:

/* Advanced line numbers with highlighting and selection */
.advanced-code-block {
    position: relative;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border-radius: 10px;
    padding: 2px;
    margin: 2rem 0;
    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
}

.code-container {
    background-color: #1e1e1e;
    border-radius: 8px;
    position: relative;
    overflow: hidden;
}

.code-header {
    background: linear-gradient(90deg, #2d2d2d 0%, #404040 100%);
    padding: 0.75rem 1rem;
    border-bottom: 1px solid #505050;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.code-title {
    color: #ffffff;
    font-weight: 600;
    font-size: 0.9rem;
    margin: 0;
}

.copy-button {
    background: #007acc;
    color: white;
    border: none;
    padding: 0.25rem 0.75rem;
    border-radius: 4px;
    font-size: 0.8rem;
    cursor: pointer;
    transition: background-color 0.2s;
}

.copy-button:hover {
    background: #005a9e;
}

.line-numbers-wrapper {
    display: flex;
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    font-size: 14px;
    line-height: 1.5;
}

.line-numbers {
    background-color: #2d2d2d;
    color: #858585;
    padding: 1rem 0;
    min-width: 3rem;
    text-align: right;
    border-right: 1px solid #505050;
    user-select: none;
    counter-reset: line-counter;
}

.line-numbers .line-number {
    display: block;
    counter-increment: line-counter;
    padding: 0 0.75rem 0 0.5rem;
    position: relative;
}

.line-numbers .line-number::before {
    content: counter(line-counter);
}

/* Highlighted line numbers */
.line-numbers .line-number.highlighted {
    background-color: #3c4043;
    color: #ffffff;
}

.line-numbers .line-number.highlighted::after {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: linear-gradient(45deg, #ff6b6b, #ffd93d);
}

.code-content {
    flex: 1;
    padding: 1rem;
    color: #d4d4d4;
    background-color: #1e1e1e;
    overflow-x: auto;
    white-space: pre;
}

.code-line {
    display: block;
    min-height: 1.5em;
    position: relative;
}

.code-line.highlighted {
    background-color: rgba(255, 255, 0, 0.1);
    margin: 0 -1rem;
    padding: 0 1rem;
}

/* Error line highlighting */
.code-line.error {
    background-color: rgba(255, 107, 107, 0.2);
    border-left: 3px solid #ff6b6b;
    margin: 0 -1rem;
    padding: 0 1rem;
    padding-left: calc(1rem - 3px);
}

/* Warning line highlighting */
.code-line.warning {
    background-color: rgba(255, 193, 7, 0.2);
    border-left: 3px solid #ffc107;
    margin: 0 -1rem;
    padding: 0 1rem;
    padding-left: calc(1rem - 3px);
}

/* Success/added line highlighting */
.code-line.added {
    background-color: rgba(76, 175, 80, 0.2);
    border-left: 3px solid #4caf50;
    margin: 0 -1rem;
    padding: 0 1rem;
    padding-left: calc(1rem - 3px);
}

/* Deleted line highlighting */
.code-line.removed {
    background-color: rgba(244, 67, 54, 0.2);
    border-left: 3px solid #f44336;
    margin: 0 -1rem;
    padding: 0 1rem;
    padding-left: calc(1rem - 3px);
    text-decoration: line-through;
    opacity: 0.7;
}

JavaScript-Enhanced Line Numbers

Dynamic Line Number Generation

Create interactive line numbers with JavaScript:

// Advanced line number system with interactive features
class CodeLineNumbers {
    constructor(options = {}) {
        this.options = {
            startLine: options.startLine || 1,
            highlightedLines: options.highlightedLines || [],
            showCopyButton: options.showCopyButton !== false,
            enableLineSelection: options.enableLineSelection !== false,
            syntaxHighlighting: options.syntaxHighlighting !== false,
            ...options
        };
        
        this.selectedLines = new Set();
        this.observers = new Map();
        
        this.init();
    }
    
    init() {
        // Find all code blocks and enhance them
        const codeBlocks = document.querySelectorAll('pre code, .code-block code');
        codeBlocks.forEach(codeBlock => this.enhanceCodeBlock(codeBlock));
        
        // Set up global event listeners
        this.setupGlobalEventHandlers();
    }
    
    enhanceCodeBlock(codeElement) {
        const preElement = codeElement.closest('pre') || codeElement.parentElement;
        
        // Skip if already enhanced
        if (preElement.classList.contains('enhanced-code-block')) {
            return;
        }
        
        // Create enhanced structure
        const wrapper = this.createWrapper(codeElement);
        const lineNumbers = this.createLineNumbers(codeElement);
        const codeContent = this.createCodeContent(codeElement);
        
        // Add copy functionality
        if (this.options.showCopyButton) {
            const copyButton = this.createCopyButton(codeElement);
            wrapper.appendChild(copyButton);
        }
        
        // Replace original element
        preElement.parentNode.replaceChild(wrapper, preElement);
        
        // Set up line selection if enabled
        if (this.options.enableLineSelection) {
            this.setupLineSelection(wrapper, lineNumbers, codeContent);
        }
        
        // Apply syntax highlighting if enabled
        if (this.options.syntaxHighlighting && window.Prism) {
            Prism.highlightElement(codeContent.querySelector('code'));
        }
        
        // Set up intersection observer for lazy loading
        this.setupIntersectionObserver(wrapper);
    }
    
    createWrapper(codeElement) {
        const wrapper = document.createElement('div');
        wrapper.className = 'enhanced-code-block';
        wrapper.setAttribute('data-language', this.getLanguage(codeElement));
        return wrapper;
    }
    
    createLineNumbers(codeElement) {
        const lines = this.getCodeLines(codeElement);
        const lineNumbersContainer = document.createElement('div');
        lineNumbersContainer.className = 'line-numbers-container';
        
        const lineNumbersList = document.createElement('div');
        lineNumbersList.className = 'line-numbers-list';
        
        lines.forEach((line, index) => {
            const lineNumber = document.createElement('div');
            const actualLineNumber = this.options.startLine + index;
            
            lineNumber.className = 'line-number';
            lineNumber.textContent = actualLineNumber;
            lineNumber.setAttribute('data-line', actualLineNumber);
            
            // Highlight specific lines
            if (this.options.highlightedLines.includes(actualLineNumber)) {
                lineNumber.classList.add('highlighted');
            }
            
            // Add click handler for line selection
            if (this.options.enableLineSelection) {
                lineNumber.addEventListener('click', (e) => {
                    this.toggleLineSelection(actualLineNumber, e.ctrlKey || e.metaKey);
                });
            }
            
            lineNumbersList.appendChild(lineNumber);
        });
        
        lineNumbersContainer.appendChild(lineNumbersList);
        return lineNumbersContainer;
    }
    
    createCodeContent(codeElement) {
        const codeContainer = document.createElement('div');
        codeContainer.className = 'code-content-container';
        
        const codeContent = document.createElement('pre');
        codeContent.className = 'code-content';
        
        const newCodeElement = document.createElement('code');
        newCodeElement.className = codeElement.className;
        newCodeElement.textContent = codeElement.textContent;
        
        codeContent.appendChild(newCodeElement);
        codeContainer.appendChild(codeContent);
        
        return codeContainer;
    }
    
    createCopyButton(codeElement) {
        const copyButton = document.createElement('button');
        copyButton.className = 'copy-code-button';
        copyButton.innerHTML = `
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
                <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
            </svg>
            <span>Copy</span>
        `;
        
        copyButton.addEventListener('click', async () => {
            const selectedText = this.getSelectedLinesText() || codeElement.textContent;
            
            try {
                await navigator.clipboard.writeText(selectedText);
                this.showCopyFeedback(copyButton, 'Copied!');
            } catch (err) {
                console.error('Failed to copy code:', err);
                this.showCopyFeedback(copyButton, 'Error');
            }
        });
        
        return copyButton;
    }
    
    getCodeLines(codeElement) {
        return codeElement.textContent.split('\n').filter(line => line !== '' || line === '\n');
    }
    
    getLanguage(codeElement) {
        const className = codeElement.className;
        const languageMatch = className.match(/language-(\w+)/);
        return languageMatch ? languageMatch[1] : 'text';
    }
    
    setupLineSelection(wrapper, lineNumbers, codeContent) {
        const codeLines = codeContent.querySelectorAll('.code-line');
        
        // Add line selection to both line numbers and code lines
        [...lineNumbers.querySelectorAll('.line-number')].forEach((lineNumber, index) => {
            const codeLine = codeLines[index];
            
            [lineNumber, codeLine].forEach(element => {
                if (element) {
                    element.addEventListener('click', (e) => {
                        const lineNum = parseInt(lineNumber.getAttribute('data-line'));
                        this.toggleLineSelection(lineNum, e.ctrlKey || e.metaKey);
                    });
                }
            });
        });
    }
    
    toggleLineSelection(lineNumber, multiSelect = false) {
        if (!multiSelect) {
            this.selectedLines.clear();
            // Clear all previously selected lines
            document.querySelectorAll('.line-number.selected, .code-line.selected')
                .forEach(el => el.classList.remove('selected'));
        }
        
        const lineElements = document.querySelectorAll(`[data-line="${lineNumber}"]`);
        
        if (this.selectedLines.has(lineNumber)) {
            this.selectedLines.delete(lineNumber);
            lineElements.forEach(el => el.classList.remove('selected'));
        } else {
            this.selectedLines.add(lineNumber);
            lineElements.forEach(el => el.classList.add('selected'));
        }
        
        // Update copy button state
        this.updateCopyButtonState();
    }
    
    getSelectedLinesText() {
        if (this.selectedLines.size === 0) return null;
        
        const sortedLines = Array.from(this.selectedLines).sort((a, b) => a - b);
        const codeContent = document.querySelector('.code-content code');
        const lines = codeContent.textContent.split('\n');
        
        return sortedLines
            .map(lineNum => lines[lineNum - this.options.startLine])
            .join('\n');
    }
    
    updateCopyButtonState() {
        const copyButtons = document.querySelectorAll('.copy-code-button span');
        copyButtons.forEach(span => {
            span.textContent = this.selectedLines.size > 0 
                ? `Copy ${this.selectedLines.size} lines` 
                : 'Copy';
        });
    }
    
    showCopyFeedback(button, message) {
        const span = button.querySelector('span');
        const originalText = span.textContent;
        
        span.textContent = message;
        button.classList.add('copied');
        
        setTimeout(() => {
            span.textContent = originalText;
            button.classList.remove('copied');
        }, 2000);
    }
    
    setupIntersectionObserver(wrapper) {
        const observer = new IntersectionObserver(
            (entries) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        wrapper.classList.add('visible');
                    }
                });
            },
            { threshold: 0.1 }
        );
        
        observer.observe(wrapper);
        this.observers.set(wrapper, observer);
    }
    
    setupGlobalEventHandlers() {
        // Keyboard shortcuts
        document.addEventListener('keydown', (e) => {
            // Ctrl/Cmd + A to select all lines in focused code block
            if ((e.ctrlKey || e.metaKey) && e.key === 'a') {
                const focusedCodeBlock = document.activeElement.closest('.enhanced-code-block');
                if (focusedCodeBlock) {
                    e.preventDefault();
                    this.selectAllLines(focusedCodeBlock);
                }
            }
            
            // Escape to clear selection
            if (e.key === 'Escape') {
                this.clearSelection();
            }
        });
    }
    
    selectAllLines(codeBlock) {
        const lineNumbers = codeBlock.querySelectorAll('.line-number');
        lineNumbers.forEach(lineNumber => {
            const lineNum = parseInt(lineNumber.getAttribute('data-line'));
            this.selectedLines.add(lineNum);
            lineNumber.classList.add('selected');
        });
        this.updateCopyButtonState();
    }
    
    clearSelection() {
        this.selectedLines.clear();
        document.querySelectorAll('.line-number.selected, .code-line.selected')
            .forEach(el => el.classList.remove('selected'));
        this.updateCopyButtonState();
    }
    
    destroy() {
        // Clean up observers and event listeners
        this.observers.forEach(observer => observer.disconnect());
        this.observers.clear();
        this.selectedLines.clear();
    }
}

// Initialize enhanced code blocks
document.addEventListener('DOMContentLoaded', () => {
    new CodeLineNumbers({
        startLine: 1,
        highlightedLines: [5, 8, 12, 15],
        showCopyButton: true,
        enableLineSelection: true,
        syntaxHighlighting: true
    });
});

// Export for module usage
if (typeof module !== 'undefined' && module.exports) {
    module.exports = CodeLineNumbers;
}

Hugo Shortcode Implementation

Create reusable shortcodes for consistent line-numbered code blocks:

<!-- layouts/shortcodes/code-with-lines.html -->
{{ $language := .Get "language" | default "text" }}
{{ $title := .Get "title" | default "" }}
{{ $startLine := .Get "start" | default 1 | int }}
{{ $highlightLines := .Get "highlight" | default "" }}
{{ $showCopy := .Get "copy" | default true }}

<div class="code-block-wrapper" data-language="{{ $language }}">
    {{ if $title }}
    <div class="code-block-header">
        <h4 class="code-title">{{ $title }}</h4>
        {{ if $showCopy }}
        <button class="copy-button" onclick="copyCodeBlock(this)">
            <span>Copy</span>
        </button>
        {{ end }}
    </div>
    {{ end }}
    
    <div class="line-numbered-code" 
         data-start="{{ $startLine }}"
         data-highlight="{{ $highlightLines }}">
        <div class="line-numbers" aria-hidden="true"></div>
        <pre class="code-content"><code class="language-{{ $language }}">{{ .Inner | htmlEscape }}</code></pre>
    </div>
</div>

<script>
// Initialize line numbers for this code block
(function() {
    const codeBlock = document.currentScript.previousElementSibling;
    const lineNumberContainer = codeBlock.querySelector('.line-numbers');
    const codeContent = codeBlock.querySelector('code');
    const startLine = parseInt(codeBlock.querySelector('.line-numbered-code').dataset.start);
    const highlightLines = codeBlock.querySelector('.line-numbered-code').dataset.highlight.split(',').map(n => parseInt(n.trim())).filter(n => !isNaN(n));
    
    // Generate line numbers
    const lines = codeContent.textContent.split('\n');
    lines.forEach((line, index) => {
        const lineNum = startLine + index;
        const lineElement = document.createElement('div');
        lineElement.className = 'line-number';
        lineElement.textContent = lineNum;
        
        if (highlightLines.includes(lineNum)) {
            lineElement.classList.add('highlighted');
        }
        
        lineNumberContainer.appendChild(lineElement);
    });
    
    // Syntax highlighting
    if (window.Prism) {
        Prism.highlightElement(codeContent);
    }
})();

function copyCodeBlock(button) {
    const codeBlock = button.closest('.code-block-wrapper');
    const codeContent = codeBlock.querySelector('code');
    
    navigator.clipboard.writeText(codeContent.textContent).then(() => {
        const span = button.querySelector('span');
        const originalText = span.textContent;
        span.textContent = 'Copied!';
        setTimeout(() => span.textContent = originalText, 2000);
    }).catch(err => {
        console.error('Failed to copy:', err);
    });
}
</script>

Usage in Hugo content:

## Database Connection Example

{{< code-with-lines language="python" title="Database Manager" start="1" highlight="5,12,18-20" >}}
import psycopg2
from contextlib import contextmanager
import logging

class DatabaseManager:
    def __init__(self, connection_string):
        self.connection_string = connection_string
        self.logger = logging.getLogger(__name__)
    
    @contextmanager
    def get_connection(self):
        conn = None
        try:
            conn = psycopg2.connect(self.connection_string)
            yield conn
        except Exception as e:
            if conn:
                conn.rollback()
            self.logger.error(f"Database error: {e}")
            raise
        finally:
            if conn:
                conn.close()
{{< /code-with-lines >}}

Jekyll Plugin Implementation

Create a Jekyll plugin for automatic line numbering:

# _plugins/line_numbers.rb
module Jekyll
  class LineNumbersTag < Liquid::Block
    def initialize(tag_name, markup, tokens)
      super
      @attributes = parse_attributes(markup)
    end
    
    def render(context)
      site = context.registers[:site]
      converter = site.find_converter_instance(Jekyll::Converters::Markdown)
      
      # Get code content
      code_content = super.strip
      
      # Parse attributes
      language = @attributes['language'] || 'text'
      start_line = (@attributes['start'] || '1').to_i
      title = @attributes['title']
      highlight_lines = parse_highlight_lines(@attributes['highlight'])
      
      # Generate HTML
      generate_line_numbered_html(code_content, language, start_line, title, highlight_lines)
    end
    
    private
    
    def parse_attributes(markup)
      attributes = {}
      markup.scan(/(\w+)=["']([^"']+)["']/) do |key, value|
        attributes[key] = value
      end
      attributes
    end
    
    def parse_highlight_lines(highlight_string)
      return [] unless highlight_string
      
      lines = []
      highlight_string.split(',').each do |part|
        part = part.strip
        if part.include?('-')
          range_start, range_end = part.split('-').map(&:to_i)
          lines.concat((range_start..range_end).to_a)
        else
          lines << part.to_i
        end
      end
      lines
    end
    
    def generate_line_numbered_html(code_content, language, start_line, title, highlight_lines)
      lines = code_content.split("\n")
      
      html = ['<div class="jekyll-line-numbered-code">']
      
      # Add title if provided
      if title
        html << "<div class=\"code-header\">"
        html << "<h4 class=\"code-title\">#{title}</h4>"
        html << "<button class=\"copy-button\" onclick=\"copyJekyllCode(this)\">Copy</button>"
        html << "</div>"
      end
      
      html << '<div class="code-container">'
      html << '<div class="line-numbers">'
      
      # Generate line numbers
      lines.each_with_index do |line, index|
        line_num = start_line + index
        css_classes = ['line-number']
        css_classes << 'highlighted' if highlight_lines.include?(line_num)
        
        html << "<div class=\"#{css_classes.join(' ')}\" data-line=\"#{line_num}\">#{line_num}</div>"
      end
      
      html << '</div>'
      html << "<div class=\"code-content\">"
      html << "<pre><code class=\"language-#{language}\">#{Jekyll::Utils.xml_escape(code_content)}</code></pre>"
      html << "</div>"
      html << '</div>'
      html << '</div>'
      
      # Add JavaScript for copy functionality
      html << generate_copy_script
      
      html.join("\n")
    end
    
    def generate_copy_script
      <<~JAVASCRIPT
      <script>
      function copyJekyllCode(button) {
          const codeBlock = button.closest('.jekyll-line-numbered-code');
          const codeContent = codeBlock.querySelector('code');
          
          navigator.clipboard.writeText(codeContent.textContent).then(() => {
              button.textContent = 'Copied!';
              setTimeout(() => button.textContent = 'Copy', 2000);
          }).catch(err => {
              console.error('Copy failed:', err);
              button.textContent = 'Error';
              setTimeout(() => button.textContent = 'Copy', 2000);
          });
      }
      </script>
      JAVASCRIPT
    end
  end
end

Liquid::Template.register_tag('line_numbers', Jekyll::LineNumbersTag)

Usage in Jekyll posts:

## Authentication System Implementation

{% line_numbers language="typescript" title="User Authentication Service" start="1" highlight="8,15-18,25" %}
interface AuthenticationConfig {
    tokenExpiry: number;
    maxAttempts: number;
    lockoutDuration: number;
    secretKey: string;
}

class AuthService {
    private config: AuthenticationConfig;
    private failedAttempts = new Map<string, number>();
    private lockedAccounts = new Map<string, Date>();
    
    constructor(config: AuthenticationConfig) {
        this.config = config;
        this.validateConfiguration();
    }
    
    async authenticate(email: string, password: string): Promise<AuthResult> {
        // Check account lock status
        if (this.isAccountLocked(email)) {
            throw new Error('Account temporarily locked');
        }
        
        try {
            // Validate credentials
            const user = await this.validateUser(email, password);
            if (!user) {
                this.recordFailedAttempt(email);
                throw new Error('Invalid credentials');
            }
            
            // Generate token and return success
            const token = this.generateToken(user);
            this.clearFailedAttempts(email);
            
            return {
                success: true,
                token,
                user: this.sanitizeUser(user)
            };
            
        } catch (error) {
            this.logger.error('Authentication failed:', error);
            throw error;
        }
    }
}
{% endline_numbers %}

Accessibility and Screen Reader Support

ARIA Labels and Semantic Markup

Ensure line numbers are accessible to all users:

<!-- Accessible line-numbered code block -->
<div class="accessible-code-block" 
     role="region" 
     aria-label="Code example with line numbers">
    
    <div class="code-header" role="banner">
        <h3 id="code-title-1">Python Data Validation Function</h3>
        <button class="copy-button" 
                aria-label="Copy code to clipboard"
                aria-describedby="code-title-1">
            Copy
        </button>
    </div>
    
    <div class="code-container" role="main">
        <!-- Line numbers are decorative and hidden from screen readers -->
        <div class="line-numbers" aria-hidden="true" role="presentation">
            <div class="line-number">1</div>
            <div class="line-number">2</div>
            <div class="line-number">3</div>
            <div class="line-number highlighted" aria-label="Line 4: Important line">4</div>
            <div class="line-number">5</div>
        </div>
        
        <!-- Code content with proper labeling -->
        <pre class="code-content" 
             role="code"
             aria-labelledby="code-title-1"
             tabindex="0"><code class="language-python">def validate_email(email: str) -> bool:
    """Validate email address format and domain"""
    if not email or '@' not in email:
        return False  # Basic format check
    
    username, domain = email.rsplit('@', 1)
    return len(username) > 0 and '.' in domain</code></pre>
    </div>
    
    <!-- Screen reader instructions -->
    <div class="sr-only">
        <p>This code block shows a Python function for email validation. 
           Use arrow keys to navigate through the code. 
           Line 4 contains the main validation logic.</p>
    </div>
</div>

CSS for Screen Reader Support

/* Screen reader and accessibility support */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Focus styles for keyboard navigation */
.accessible-code-block .code-content:focus {
    outline: 2px solid #007acc;
    outline-offset: 2px;
}

.accessible-code-block .copy-button:focus {
    outline: 2px solid #007acc;
    outline-offset: 2px;
    background-color: #005a9e;
}

/* High contrast mode support */
@media (prefers-contrast: high) {
    .line-numbers {
        border-right: 2px solid;
    }
    
    .line-number.highlighted {
        background-color: #ffff00;
        color: #000000;
        font-weight: bold;
    }
    
    .code-content {
        border: 1px solid;
    }
}

/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
    .copy-button,
    .line-number {
        transition: none;
    }
}

/* Font size preferences */
@media (prefers-font-size: large) {
    .accessible-code-block {
        font-size: 1.2em;
    }
}

Performance Optimization Techniques

Lazy Loading for Large Code Blocks

Implement efficient rendering for extensive code examples:

// Performance-optimized line number rendering
class OptimizedLineNumbers {
    constructor(options = {}) {
        this.options = {
            virtualScrollThreshold: options.virtualScrollThreshold || 100,
            renderBuffer: options.renderBuffer || 10,
            debounceDelay: options.debounceDelay || 16,
            ...options
        };
        
        this.intersectionObserver = new IntersectionObserver(
            this.handleIntersection.bind(this),
            { threshold: 0.1 }
        );
        
        this.resizeObserver = new ResizeObserver(
            this.debounce(this.handleResize.bind(this), this.options.debounceDelay)
        );
        
        this.init();
    }
    
    init() {
        // Process existing code blocks
        document.querySelectorAll('pre code').forEach(codeElement => {
            this.processCodeBlock(codeElement);
        });
        
        // Watch for dynamically added code blocks
        this.setupMutationObserver();
    }
    
    processCodeBlock(codeElement) {
        const lines = codeElement.textContent.split('\n');
        
        // Use virtual scrolling for large code blocks
        if (lines.length > this.options.virtualScrollThreshold) {
            this.createVirtualScrollCodeBlock(codeElement, lines);
        } else {
            this.createStaticCodeBlock(codeElement, lines);
        }
    }
    
    createVirtualScrollCodeBlock(codeElement, lines) {
        const wrapper = document.createElement('div');
        wrapper.className = 'virtual-scroll-code-block';
        wrapper.style.cssText = `
            height: 400px;
            overflow: auto;
            position: relative;
            border: 1px solid #ddd;
            border-radius: 4px;
        `;
        
        const viewport = document.createElement('div');
        viewport.className = 'virtual-viewport';
        viewport.style.cssText = `
            height: ${lines.length * 20}px;
            position: relative;
        `;
        
        const visibleArea = document.createElement('div');
        visibleArea.className = 'visible-area';
        visibleArea.style.cssText = `
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            display: flex;
        `;
        
        const lineNumbers = document.createElement('div');
        lineNumbers.className = 'virtual-line-numbers';
        lineNumbers.style.cssText = `
            width: 60px;
            background: #f5f5f5;
            border-right: 1px solid #ddd;
            font-family: monospace;
            font-size: 12px;
            text-align: right;
            padding: 0 8px;
        `;
        
        const codeContent = document.createElement('pre');
        codeContent.className = 'virtual-code-content';
        codeContent.style.cssText = `
            flex: 1;
            margin: 0;
            padding: 0 12px;
            font-family: monospace;
            font-size: 14px;
            line-height: 20px;
            background: white;
            overflow: hidden;
        `;
        
        visibleArea.appendChild(lineNumbers);
        visibleArea.appendChild(codeContent);
        viewport.appendChild(visibleArea);
        wrapper.appendChild(viewport);
        
        // Virtual scrolling logic
        let startIndex = 0;
        let visibleLines = Math.ceil(400 / 20) + this.options.renderBuffer;
        
        const updateVisible = () => {
            const scrollTop = wrapper.scrollTop;
            startIndex = Math.max(0, Math.floor(scrollTop / 20) - this.options.renderBuffer);
            const endIndex = Math.min(lines.length, startIndex + visibleLines);
            
            // Update line numbers
            const visibleLineNumbers = [];
            for (let i = startIndex; i < endIndex; i++) {
                visibleLineNumbers.push(`<div style="height: 20px; line-height: 20px;">${i + 1}</div>`);
            }
            lineNumbers.innerHTML = visibleLineNumbers.join('');
            
            // Update code content
            const visibleCode = lines.slice(startIndex, endIndex);
            const codeHTML = visibleCode.map((line, index) => 
                `<div style="height: 20px; line-height: 20px;" data-line="${startIndex + index + 1}">${this.escapeHtml(line)}</div>`
            ).join('');
            codeContent.innerHTML = `<code>${codeHTML}</code>`;
            
            // Position the visible area
            visibleArea.style.transform = `translateY(${startIndex * 20}px)`;
        };
        
        // Throttled scroll handler
        wrapper.addEventListener('scroll', this.throttle(updateVisible, 16));
        
        // Initial render
        updateVisible();
        
        // Replace original code block
        codeElement.closest('pre').parentNode.replaceChild(wrapper, codeElement.closest('pre'));
    }
    
    createStaticCodeBlock(codeElement, lines) {
        // Standard static line numbers for smaller code blocks
        const wrapper = document.createElement('div');
        wrapper.className = 'static-line-numbered-code';
        
        const container = document.createElement('div');
        container.className = 'line-numbered-container';
        container.style.display = 'flex';
        
        const lineNumbers = document.createElement('div');
        lineNumbers.className = 'static-line-numbers';
        lineNumbers.style.cssText = `
            background: #f8f8f8;
            border-right: 1px solid #ddd;
            padding: 1rem 0.5rem;
            text-align: right;
            user-select: none;
            font-family: monospace;
            font-size: 12px;
            line-height: 1.4;
            color: #666;
            min-width: 2.5rem;
        `;
        
        // Generate line numbers efficiently
        const lineNumberHTML = lines.map((_, index) => 
            `<div class="line-num">${index + 1}</div>`
        ).join('');
        lineNumbers.innerHTML = lineNumberHTML;
        
        const codeContainer = document.createElement('div');
        codeContainer.className = 'static-code-content';
        codeContainer.style.cssText = `
            flex: 1;
            overflow-x: auto;
        `;
        
        const pre = document.createElement('pre');
        pre.style.cssText = `
            margin: 0;
            padding: 1rem;
            background: white;
            font-family: monospace;
            font-size: 14px;
            line-height: 1.4;
        `;
        
        const code = document.createElement('code');
        code.className = codeElement.className;
        code.textContent = codeElement.textContent;
        
        pre.appendChild(code);
        codeContainer.appendChild(pre);
        container.appendChild(lineNumbers);
        container.appendChild(codeContainer);
        wrapper.appendChild(container);
        
        // Replace original
        codeElement.closest('pre').parentNode.replaceChild(wrapper, codeElement.closest('pre'));
        
        // Apply syntax highlighting if available
        if (window.Prism && code.className.includes('language-')) {
            Prism.highlightElement(code);
        }
    }
    
    handleIntersection(entries) {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                const codeBlock = entry.target;
                // Lazy load syntax highlighting or other features
                this.enhanceVisibleCodeBlock(codeBlock);
            }
        });
    }
    
    enhanceVisibleCodeBlock(codeBlock) {
        // Add syntax highlighting, copy buttons, etc. only when visible
        const codeElement = codeBlock.querySelector('code');
        if (codeElement && window.Prism && !codeElement.classList.contains('highlighted')) {
            Prism.highlightElement(codeElement);
            codeElement.classList.add('highlighted');
        }
    }
    
    setupMutationObserver() {
        const observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                if (mutation.type === 'childList') {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === Node.ELEMENT_NODE) {
                            const codeElements = node.querySelectorAll('pre code');
                            codeElements.forEach(codeElement => {
                                this.processCodeBlock(codeElement);
                            });
                        }
                    });
                }
            });
        });
        
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }
    
    // Utility functions
    debounce(func, delay) {
        let timeoutId;
        return (...args) => {
            clearTimeout(timeoutId);
            timeoutId = setTimeout(() => func.apply(this, args), delay);
        };
    }
    
    throttle(func, delay) {
        let lastCall = 0;
        return (...args) => {
            const now = Date.now();
            if (now - lastCall >= delay) {
                func.apply(this, args);
                lastCall = now;
            }
        };
    }
    
    escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }
    
    handleResize() {
        // Recalculate virtual scroll parameters on resize
        this.updateVirtualScrollDimensions();
    }
    
    updateVirtualScrollDimensions() {
        const virtualBlocks = document.querySelectorAll('.virtual-scroll-code-block');
        virtualBlocks.forEach(block => {
            // Recalculate visible area and update rendering
            const event = new Event('scroll');
            block.dispatchEvent(event);
        });
    }
    
    destroy() {
        // Cleanup observers
        if (this.intersectionObserver) {
            this.intersectionObserver.disconnect();
        }
        if (this.resizeObserver) {
            this.resizeObserver.disconnect();
        }
    }
}

// Initialize optimized line numbers
document.addEventListener('DOMContentLoaded', () => {
    window.optimizedLineNumbers = new OptimizedLineNumbers({
        virtualScrollThreshold: 50,
        renderBuffer: 5,
        debounceDelay: 16
    });
});

Integration with Documentation Workflows

Line numbers in code blocks work seamlessly with other advanced Markdown features to create comprehensive technical documentation. When combined with syntax highlighting, line numbers enable precise code discussions while maintaining beautiful visual presentation of different programming languages.

For complex documentation requiring both detailed code examples and structured explanations, line numbers integrate effectively with custom containers and admonitions to create comprehensive tutorials with clear visual organization and specific line references.

When creating interactive documentation that includes both code examples and user tasks, line numbering complements task lists and checkboxes by enabling readers to reference specific implementation steps while tracking their progress through development workflows.

Troubleshooting Common Issues

Line Number Alignment Problems

Problem: Line numbers don’t align properly with code content

Solutions:

/* Fix alignment issues */
.line-numbers, .code-content {
    font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
    font-size: 14px;
    line-height: 1.5;
    font-feature-settings: normal;
    font-variant-ligatures: none;
}

/* Ensure consistent spacing */
.line-numbers .line-number,
.code-content .code-line {
    height: 1.5em;
    box-sizing: border-box;
}

/* Fix sub-pixel rendering issues */
.line-numbered-code {
    transform: translateZ(0); /* Force hardware acceleration */
}

Performance Issues with Large Files

Problem: Browser becomes sluggish with very long code files

Solutions:

// Implement efficient rendering strategies
const PERFORMANCE_THRESHOLDS = {
    SMALL: 100,    // Lines - full rendering
    MEDIUM: 500,   // Lines - chunked rendering  
    LARGE: 1000    // Lines - virtual scrolling
};

function optimizeCodeBlock(codeElement) {
    const lineCount = codeElement.textContent.split('\n').length;
    
    if (lineCount < PERFORMANCE_THRESHOLDS.SMALL) {
        // Full static rendering
        renderStaticLineNumbers(codeElement);
    } else if (lineCount < PERFORMANCE_THRESHOLDS.MEDIUM) {
        // Chunked rendering with intersection observer
        renderChunkedLineNumbers(codeElement);
    } else {
        // Virtual scrolling for maximum performance
        renderVirtualScrollLineNumbers(codeElement);
    }
}

Cross-Browser Compatibility

Problem: Line numbers display differently across browsers

Solutions:

/* Cross-browser consistent line numbers */
.universal-line-numbers {
    /* Reset browser defaults */
    box-sizing: border-box;
    -webkit-font-feature-settings: "liga" 0;
    font-feature-settings: "liga" 0;
    
    /* Consistent fonts across platforms */
    font-family: 
        'SFMono-Regular',
        'Monaco',
        'Inconsolata',
        'Roboto Mono',
        'Source Code Pro',
        'Menlo',
        'Consolas',
        'DejaVu Sans Mono',
        monospace;
    
    /* Disable text selection and interactions */
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    
    /* Consistent text rendering */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

/* IE11 fallbacks */
@media screen and (-ms-high-contrast: active), 
       screen and (-ms-high-contrast: none) {
    .universal-line-numbers {
        font-family: 'Consolas', monospace;
    }
}

SEO and Content Structure Benefits

Enhanced Code Documentation SEO

Line numbers significantly improve technical content discoverability:

  • Precise Referencing: Enable specific line citations that improve content authority
  • Enhanced Navigation: Help search engines understand code structure and importance
  • Professional Presentation: Demonstrate attention to detail that builds content credibility
  • User Engagement: Longer time-on-page as users can easily navigate complex code examples

Structured Data for Code Examples

<!-- Enhanced markup for code blocks with line numbers -->
<div itemscope itemtype="https://schema.org/SoftwareSourceCode">
    <div class="code-header">
        <h3 itemprop="name">User Authentication Implementation</h3>
        <meta itemprop="programmingLanguage" content="TypeScript">
        <meta itemprop="codeRepository" content="https://github.com/example/auth-system">
    </div>
    
    <div class="line-numbered-code" itemprop="text">
        <div class="line-numbers" role="presentation" aria-hidden="true">
            <!-- Line numbers -->
        </div>
        <pre><code class="language-typescript">
            <!-- Code content with proper indentation -->
        </code></pre>
    </div>
    
    <div itemprop="description">
        Complete authentication system with error handling and token management.
        Key implementation details on lines 15-28 and 35-42.
    </div>
</div>

Conclusion

Markdown line numbers transform code documentation from simple text blocks into professional, navigable technical resources that enhance both reader comprehension and collaborative development workflows. By mastering platform-specific implementations, CSS styling techniques, and JavaScript enhancements, you can create code documentation that not only presents information clearly but actively improves the developer experience.

The key to successful line number implementation lies in choosing appropriate techniques for your content complexity, ensuring accessibility across all users and devices, and optimizing performance for varying code block sizes. Whether you’re creating API documentation, tutorial content, or technical specifications, the techniques covered in this guide provide the foundation for professional code presentation that serves developers effectively.

Remember to test line number implementations across different platforms and devices, consider performance implications for large code examples, and always prioritize accessibility in your styling choices. With proper implementation, line numbers become powerful tools for creating precise, professional technical documentation that enhances code comprehension and facilitates effective technical communication.