Syntax Highlighting Guide

July 16, 2025 ยท View on GitHub

SwiftMarkdownParser includes professional-grade syntax highlighting for code blocks with support for multiple programming languages, built-in themes, and extensible architecture.

๐ŸŒŸ Features

  • 6 Programming Languages: JavaScript, TypeScript, Swift, Kotlin, Python, Bash
  • 3 Built-in Themes: GitHub, Xcode, VS Code Dark (HTML renderer only)
  • 25+ Token Types: Keywords, strings, comments, operators, types, functions, and more
  • Modern Language Features: ES6+, async/await, generics, coroutines, decorators
  • Performance Optimized: Actor-based engine registry with LRU caching
  • Thread-Safe: Built with Swift 6 concurrency patterns
  • HTML Renderer: Full syntax highlighting with CSS classes and themes
  • SwiftUI Renderer: Basic code blocks with monospace styling (no syntax highlighting)

๐Ÿš€ Quick Start

Basic HTML Rendering with Syntax Highlighting

import SwiftMarkdownParser

let codeMarkdown = """
# Code Example

```swift
@State private var count: Int = 0

func increment() async {
    await MainActor.run {
        count += 1
    }
}

"""

// Configure syntax highlighting let context = RenderContext( styleConfiguration: StyleConfiguration( syntaxHighlighting: SyntaxHighlightingConfig( enabled: true, cssPrefix: "hljs-" // optional; default is "language-" ) ) )

let parser = SwiftMarkdownParser() let ast = try await parser.parseToAST(codeMarkdown)

let renderer = HTMLRenderer(context: context) let highlightedHTML = try await renderer.render(document: ast)


### SwiftUI Integration (Basic Code Blocks Only)

**Note**: SwiftUI renderer does NOT support syntax highlighting. It only renders plain monospace code blocks.

```swift
import SwiftUI
import SwiftMarkdownParser

struct CodeExampleView: View {
    let markdown = """
    ```python
    async def fetch_data():
        response = await http.get('/api/data')
        return await response.json()
    ```
    """
    
    var body: some View {
        ScrollView {
            MarkdownView(markdown: markdown)
                .padding()
        }
    }
}

struct MarkdownView: View {
    let markdown: String
    @State private var renderedView: AnyView?
    
    var body: some View {
        Group {
            if let view = renderedView {
                view
            } else {
                ProgressView("Rendering...")
            }
        }
        .task {
            await renderMarkdown()
        }
    }
    
    private func renderMarkdown() async {
        do {
            let parser = SwiftMarkdownParser()
            let ast = try await parser.parseToAST(markdown)
            
            // Use a predefined SwiftUI style - NO syntax highlighting available
            let context = SwiftUIRenderContext(
                styleConfiguration: SwiftUIStyleConfiguration.github
            )
            
            let renderer = SwiftUIRenderer(context: context)
            let view = try await renderer.render(document: ast)
            
            await MainActor.run {
                self.renderedView = view
            }
        } catch {
            await MainActor.run {
                self.renderedView = AnyView(Text("Error: \(error.localizedDescription)"))
            }
        }
    }
}

๐Ÿ“‹ Supported Languages

JavaScript

  • ES6+ Features: Arrow functions, destructuring, template literals
  • Modern Syntax: async/await, classes, modules
  • JSX Support: React component syntax
  • Template Literals: String interpolation with ${}
const fetchUser = async (id) => {
    const response = await fetch(`/api/users/${id}`);
    return await response.json();
};

const UserComponent = ({ user }) => (
    <div className="user-card">
        <h2>{user.name}</h2>
        <p>{user.email}</p>
    </div>
);

TypeScript

  • Type Annotations: Parameters, return types, variables
  • Generics: Type parameters and constraints
  • Interfaces: Object type definitions
  • Decorators: Class and method decorators
  • TSX Support: TypeScript + JSX
interface User {
    id: number;
    name: string;
    email?: string;
}

@Component({
    selector: 'user-list'
})
class UserList<T extends User> {
    users: T[] = [];
    
    async loadUsers(): Promise<void> {
        this.users = await this.userService.getUsers<T>();
    }
}

Swift

  • Swift 6 Syntax: Latest language features
  • Property Wrappers: @State, @Binding, @Published
  • String Interpolation: (expression) syntax
  • Async/Await: Modern concurrency
  • Closures: Including shorthand syntax ($0, $1)
@State private var users: [User] = []
@Published var isLoading = false

func loadUsers() async throws {
    let response = try await URLSession.shared.data(from: url)
    users = try JSONDecoder().decode([User].self, from: response.0)
}

let sorted = users.sorted { \$0.name < \$1.name }

Kotlin

  • Data Classes: Automatic implementations
  • Coroutines: suspend functions, async/await
  • Null Safety: ? and ?: operators
  • Extension Functions: Adding methods to existing types
data class User(val name: String, var age: Int)

suspend fun fetchUser(id: String): User? = withContext(Dispatchers.IO) {
    val response = httpClient.get("/api/users/$id")
    response.body<User>()
}

fun String.isEmail(): Boolean = this.contains('@')

Python

  • Python 3+ Syntax: Modern Python features
  • Async/Await: Asynchronous programming
  • Triple-quoted Strings: Multi-line strings
  • List Comprehensions: Functional programming constructs
  • Type Hints: Optional type annotations
from typing import List, Optional

async def fetch_users() -> List[User]:
    async with aiohttp.ClientSession() as session:
        async with session.get('/api/users') as response:
            return await response.json()

users = [user for user in all_users if user.age >= 18]

Bash

  • Shell Scripts: Complete bash syntax
  • Variables: VARandVAR and {VAR} syntax
  • Control Structures: if/then/fi, for/do/done
  • Built-in Commands: Common shell utilities
  • Shebang: #!/bin/bash detection
#!/bin/bash

USER_COUNT=$(wc -l < users.txt)

if [ $USER_COUNT -gt 100 ]; then
    echo "Many users: $USER_COUNT"
    for user in $(cat users.txt); do
        echo "Processing: $user"
    done
fi

๐ŸŽจ Built-in Themes

Important: Themes are only available for the HTML renderer. The SwiftUI renderer uses basic monospace styling without syntax highlighting.

GitHub Theme

Clean, professional styling matching GitHub's code blocks:

  • Background: Light gray (#f6f8fa)
  • Keywords: Deep red (#d73a49)
  • Strings: Dark blue (#032f62)
  • Comments: Gray (#6a737d)

Xcode Theme

Apple's development environment colors:

  • Background: White
  • Keywords: Purple (#aa0d91)
  • Strings: Red (#c41a16)
  • Comments: Green (#008400)

VS Code Dark Theme

Popular dark theme for developers:

  • Background: Dark gray (#1e1e1e)
  • Keywords: Light blue (#4fc3f7)
  • Strings: Orange (#ce9178)
  • Comments: Green (#6a9955)

๐Ÿ› ๏ธ Configuration

HTML Renderer Configuration

let syntaxConfig = SyntaxHighlightingConfig(
    enabled: true,
    cssPrefix: "hljs-"   // optional; default is "language-"
)

let context = RenderContext(
    styleConfiguration: StyleConfiguration(
        syntaxHighlighting: syntaxConfig
    )
)

SwiftUI Renderer Configuration

Note: SwiftUI renderer does not support syntax highlighting. Only basic styling is available.

let context = SwiftUIRenderContext(
    styleConfiguration: SwiftUIStyleConfiguration(
        // Only basic code styling - no syntax highlighting
        codeFont: .system(.body, design: .monospaced),
        codeTextColor: .primary,
        codeBackgroundColor: Color.gray.opacity(0.1),
        codeCornerRadius: 8.0
    )
)

๐ŸŽจ Custom Themes

Creating Custom Themes (HTML Renderer Only)

// Custom CSS classes for HTML output
let context = RenderContext(
    styleConfiguration: StyleConfiguration(
        syntaxHighlighting: SyntaxHighlightingConfig(
            enabled: true,
            cssPrefix: "custom-"
        ),
        cssClasses: [
            .codeBlock: "my-code-block"
        ]
    )
)

// Then provide your own CSS rules:
// .custom-keyword { color: #0066cc; }
// .custom-string { color: #009900; }
// .custom-comment { color: #888888; }

SwiftUI Basic Styling

// Only basic styling available for SwiftUI
let customStyle = SwiftUIStyleConfiguration(
    codeFont: .system(.footnote, design: .monospaced),
    codeTextColor: Color.blue,
    codeBackgroundColor: Color.gray.opacity(0.05),
    codeCornerRadius: 4.0
)

let context = SwiftUIRenderContext(styleConfiguration: customStyle)

Theme Color Mapping

The syntax highlighting system supports 25+ token types:

Token TypeDescriptionExample
.keywordLanguage keywordsfunc, class, if, async
.stringString literals"Hello", 'world'
.commentComments// comment, /* block */
.numberNumeric literals42, 3.14, 0xFF
.identifierVariable namesuserName, count
.operatorOperators+, -, ==, &&
.punctuationPunctuation(, ), {, }, ;
.typeType namesString, Int, User
.functionFunction namesprint, map, filter
.builtinBuilt-in functionsconsole.log, len, echo
.constantConstantstrue, false, null
.attributeAttributes/decorators@State, @Component
.genericGeneric parameters<T>, <K, V>
.methodMethod callsuser.getName()
.propertyObject propertiesuser.name
.parameterFunction parameters$0, $1
.modifierAccess modifierspublic, private
.templateTemplate literals`Hello ${name}`
.interpolationString interpolation${name}, \(value)
.regexRegular expressions/pattern/flags
.escapeEscape sequences\n, \t, \"

โšก Performance

Caching System

The syntax highlighting system includes an intelligent caching mechanism:

// Access the registry for performance monitoring
let registry = SyntaxHighlightingRegistry()

// Get cache statistics
let cache = SyntaxHighlightingCache()
let stats = await cache.getStatistics()
print("Cache entries: \(stats["entryCount"] ?? 0)")
print("Total hits: \(stats["totalHits"] ?? 0)")

// Clear cache if needed
await cache.clearCache()

Performance Features

  • LRU Cache: Least Recently Used eviction policy
  • Actor-based: Thread-safe concurrent access
  • Lazy Loading: Engines loaded only when needed
  • Efficient Parsing: Single-pass tokenization
  • Memory Efficient: Minimal allocations during highlighting

Benchmarks

Performance characteristics for different code block sizes (HTML renderer):

Lines of CodeHighlighting TimeMemory Usage
10-50 lines< 1ms< 10KB
100-500 lines< 5ms< 50KB
1000+ lines< 20ms< 200KB

Note: SwiftUI renderer performance is simpler as it doesn't perform syntax highlighting.

๐Ÿ”ง Advanced Usage

Direct Engine Access

// Use engines directly for custom processing
let jsEngine = JavaScriptSyntaxEngine()
let tokens = try await jsEngine.highlight(
    "const x = 42;", 
    language: "javascript"
)

// Process tokens for HTML output
for token in tokens {
    print("\(token.content): \(token.tokenType)")
}

Custom Engine Registration

// Register a custom engine
struct MyLanguageEngine: SyntaxHighlightingEngine {
    func highlight(_ code: String, language: String) async throws -> [SyntaxToken] {
        // Custom highlighting logic
        return []
    }
    
    func supportedLanguages() -> Set<String> {
        return ["mylang"]
    }
}

let registry = SyntaxHighlightingRegistry()
await registry.register(engine: MyLanguageEngine(), for: ["mylang"])

Error Handling

do {
    let tokens = try await engine.highlight(code, language: "swift")
    // Process tokens
} catch SyntaxHighlightingError.unsupportedLanguage(let lang) {
    print("Language not supported: \(lang)")
} catch SyntaxHighlightingError.parsingError(let message) {
    print("Parsing error: \(message)")
} catch {
    print("Unknown error: \(error)")
}

๐Ÿงช Testing

Unit Tests

The syntax highlighting system includes comprehensive tests:

# Run all syntax highlighting tests
swift test --filter SyntaxHighlightingEngineTests

# Run specific language tests
swift test --filter test_swiftEngine
swift test --filter test_javascriptEngine

# Run integration tests (HTML renderer)
swift test --filter SyntaxHighlightingIntegrationTests

Test Coverage

  • Engine Tests: Each language engine has dedicated tests
  • Theme Tests: Color theme functionality (HTML only)
  • Registry Tests: Engine registration and caching
  • Performance Tests: Large code block handling
  • Edge Cases: Malformed code, empty blocks, special characters

๐Ÿ“š Examples

Complete HTML Example with Syntax Highlighting

import SwiftMarkdownParser

let multiLanguageMarkdown = """
# Multi-language Code Examples

## Frontend (TypeScript + React)
```typescript
interface User {
    id: number;
    name: string;
    email: string;
}

const UserCard: React.FC<{ user: User }> = ({ user }) => (
    <div className="user-card">
        <h3>{user.name}</h3>
        <p>{user.email}</p>
    </div>
);

Backend (Swift)

struct User: Codable {
    let id: Int
    let name: String
    let email: String
}

@main
struct App {
    static func main() async throws {
        let users = try await UserService.fetchUsers()
        print("Loaded \(users.count) users")
    }
}

"""

async func generateHighlightedHTML() throws -> String { let parser = SwiftMarkdownParser() let ast = try await parser.parseToAST(multiLanguageMarkdown)

let context = RenderContext(
    styleConfiguration: StyleConfiguration(
        syntaxHighlighting: SyntaxHighlightingConfig(
            enabled: true,
            cssPrefix: "hljs-"
        ),
        cssClasses: [
            .codeBlock: "code-block highlighted",
            .heading: "section-heading"
        ]
    )
)

let renderer = HTMLRenderer(context: context)
return try await renderer.render(document: ast)

}

// Usage let html = try await generateHighlightedHTML() print(html)


### SwiftUI Example (Basic Code Blocks)

```swift
import SwiftUI
import SwiftMarkdownParser

struct SwiftUICodeExample: View {
    let codeMarkdown = """
    ```swift
    let message = "Hello, World!"
    print(message)
    ```
    """
    
    @State private var renderedView: AnyView?
    
    var body: some View {
        VStack {
            if let view = renderedView {
                view
            } else {
                ProgressView("Rendering...")
            }
        }
        .task {
            await renderCode()
        }
    }
    
    private func renderCode() async {
        do {
            let parser = SwiftMarkdownParser()
            let ast = try await parser.parseToAST(codeMarkdown)
            
            // SwiftUI basic styling - no syntax highlighting
            let context = SwiftUIRenderContext(
                styleConfiguration: SwiftUIStyleConfiguration(
                    codeFont: .system(.body, design: .monospaced),
                    codeTextColor: .primary,
                    codeBackgroundColor: Color.gray.opacity(0.1)
                )
            )
            
            let renderer = SwiftUIRenderer(context: context)
            let view = try await renderer.render(document: ast)
            
            await MainActor.run {
                self.renderedView = view
            }
        } catch {
            await MainActor.run {
                self.renderedView = AnyView(Text("Error: \(error.localizedDescription)"))
            }
        }
    }
}

๐Ÿ“‹ Renderer Comparison

FeatureHTML RendererSwiftUI Renderer
Syntax Highlightingโœ… Full supportโŒ Not supported
Themesโœ… 3 built-in themesโŒ Basic styling only
Token-level stylingโœ… 25+ token typesโŒ Plain text only
Custom CSS classesโœ… ConfigurableโŒ N/A
Performanceโœ… Cached highlightingโœ… Simple rendering
Use caseWeb/HTML outputNative iOS/macOS apps

The syntax highlighting system in SwiftMarkdownParser provides professional-grade code block rendering for HTML output with modern language support, beautiful themes, and excellent performance. For SwiftUI applications, basic monospace code blocks are provided without syntax highlighting. ๐ŸŽจโœจ