coreason-meta-engineering 0.1.0

Rust port of the CoReason Agentic Forge & AST Manipulation Layer
Documentation
// Copyright (c) 2026 CoReason, Inc.
// All rights reserved.
// SPDX-License-Identifier: LicenseRef-Prosperity-3.0

//! Forge Scaffolding Extensions — PDF.js citation and Yjs CRDT bindings.
//!
//! Generates configuration scaffolds for:
//! - PDF.js citation highlight overlays
//! - Yjs CRDT bindings for collaborative canvas components

use serde::{Deserialize, Serialize};
use serde_json::{json, Value};

/// A single citation highlight configuration for PDF.js.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CitationHighlight {
    pub page: i64,
    pub x: f64,
    pub y: f64,
    pub width: f64,
    pub height: f64,
    #[serde(default = "default_highlight_color")]
    pub color: String,
    #[serde(default)]
    pub citation_id: String,
    #[serde(default)]
    pub tooltip: String,
}

fn default_highlight_color() -> String {
    "rgba(255, 255, 0, 0.3)".to_string()
}

/// Generate a PDF.js citation highlight configuration.
pub fn generate_pdfjs_citation_config(
    document_urn: &str,
    highlights: &[CitationHighlight],
    viewer_options: Option<Value>,
) -> Value {
    let default_viewer_options = json!({
        "sidebarView": "thumbs",
        "scrollMode": "vertical",
        "spreadMode": "none",
        "enableAnnotations": true,
        "enableHighlights": true,
    });

    let highlights_json: Vec<Value> = highlights
        .iter()
        .map(|h| {
            json!({
                "page": h.page,
                "rect": {
                    "x": h.x,
                    "y": h.y,
                    "width": h.width,
                    "height": h.height,
                },
                "style": {
                    "backgroundColor": h.color,
                    "borderRadius": "2px",
                    "cursor": "pointer",
                },
                "citationId": h.citation_id,
                "tooltip": h.tooltip,
            })
        })
        .collect();

    json!({
        "documentUrn": document_urn,
        "viewerOptions": viewer_options.unwrap_or(default_viewer_options),
        "highlights": highlights_json,
        "onHighlightClick": "handleCitationClick",
        "citationPanelEnabled": true,
    })
}

/// A Yjs CRDT binding configuration for a canvas component.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct YjsCRDTBinding {
    pub component_id: String,
    pub crdt_type: String,
    #[serde(default = "default_sync_provider")]
    pub sync_provider: String,
    #[serde(default = "default_true")]
    pub awareness_enabled: bool,
    #[serde(default)]
    pub initial_value: Value,
}

fn default_sync_provider() -> String {
    "websocket".to_string()
}

fn default_true() -> bool {
    true
}

/// Scaffold Yjs CRDT bindings for a collaborative canvas.
pub fn scaffold_yjs_crdt_bindings(
    canvas_id: &str,
    bindings: &[YjsCRDTBinding],
    websocket_url: Option<&str>,
) -> Value {
    let ws_url = websocket_url.unwrap_or("ws://localhost:1234");

    let bindings_json: Vec<Value> = bindings
        .iter()
        .map(|b| {
            json!({
                "componentId": b.component_id,
                "crdtType": b.crdt_type,
                "path": format!("canvas.{}.{}", canvas_id, b.component_id),
                "syncProvider": b.sync_provider,
                "awarenessEnabled": b.awareness_enabled,
                "initialValue": b.initial_value,
            })
        })
        .collect();

    json!({
        "canvasId": canvas_id,
        "provider": {
            "type": "WebsocketProvider",
            "url": ws_url,
            "roomName": format!("canvas-{}", canvas_id),
            "awareness": true,
        },
        "bindings": bindings_json,
        "undoManager": {
            "enabled": true,
            "trackedOrigins": [format!("canvas-{}", canvas_id)],
        },
    })
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_citation_highlight_defaults() {
        let h = CitationHighlight {
            page: 1,
            x: 10.0,
            y: 20.0,
            width: 100.0,
            height: 50.0,
            color: default_highlight_color(),
            citation_id: String::new(),
            tooltip: String::new(),
        };
        assert_eq!(h.page, 1);
        assert_eq!(h.x, 10.0);
        assert_eq!(h.color, "rgba(255, 255, 0, 0.3)");
    }

    #[test]
    fn test_generate_pdfjs_citation_config() {
        let highlights = vec![CitationHighlight {
            page: 1,
            x: 10.0,
            y: 20.0,
            width: 50.0,
            height: 15.0,
            color: "rgba(255, 255, 0, 0.3)".to_string(),
            citation_id: "c1".to_string(),
            tooltip: "t1".to_string(),
        }];

        let config = generate_pdfjs_citation_config("urn:document:123", &highlights, None);
        assert_eq!(config["documentUrn"], "urn:document:123");
        assert_eq!(config["highlights"][0]["page"], 1);
        assert_eq!(config["highlights"][0]["citationId"], "c1");
        assert_eq!(config["highlights"][0]["tooltip"], "t1");
        assert_eq!(config["highlights"][0]["rect"]["x"], 10.0);
        assert_eq!(config["onHighlightClick"], "handleCitationClick");
        assert_eq!(config["citationPanelEnabled"], true);

        // Default viewer options
        assert_eq!(config["viewerOptions"]["sidebarView"], "thumbs");
        assert_eq!(config["viewerOptions"]["enableAnnotations"], true);

        // Custom viewer options
        let custom = json!({"enableAnnotations": false, "customMode": "special"});
        let config2 = generate_pdfjs_citation_config("urn:doc:2", &highlights, Some(custom.clone()));
        assert_eq!(config2["viewerOptions"], custom);
    }

    #[test]
    fn test_yjs_crdt_binding_defaults() {
        let b = YjsCRDTBinding {
            component_id: "cmp-1".to_string(),
            crdt_type: "Y.Map".to_string(),
            sync_provider: default_sync_provider(),
            awareness_enabled: true,
            initial_value: Value::Null,
        };
        assert_eq!(b.component_id, "cmp-1");
        assert_eq!(b.crdt_type, "Y.Map");
        assert_eq!(b.sync_provider, "websocket");
        assert!(b.awareness_enabled);
    }

    #[test]
    fn test_scaffold_yjs_crdt_bindings() {
        let bindings = vec![YjsCRDTBinding {
            component_id: "editor-1".to_string(),
            crdt_type: "Y.Text".to_string(),
            sync_provider: "websocket".to_string(),
            awareness_enabled: true,
            initial_value: json!("Init text"),
        }];

        let config = scaffold_yjs_crdt_bindings("canvas-99", &bindings, None);
        assert_eq!(config["canvasId"], "canvas-99");
        assert_eq!(config["provider"]["type"], "WebsocketProvider");
        assert_eq!(config["provider"]["url"], "ws://localhost:1234");
        assert_eq!(config["provider"]["roomName"], "canvas-canvas-99");
        assert_eq!(config["bindings"][0]["componentId"], "editor-1");
        assert_eq!(config["bindings"][0]["crdtType"], "Y.Text");
        assert_eq!(config["bindings"][0]["path"], "canvas.canvas-99.editor-1");
        assert_eq!(config["bindings"][0]["initialValue"], "Init text");
        assert_eq!(config["undoManager"]["enabled"], true);
        assert_eq!(config["undoManager"]["trackedOrigins"][0], "canvas-canvas-99");

        // Custom websocket URL
        let config2 = scaffold_yjs_crdt_bindings("canvas-99", &bindings, Some("ws://example.com:4321"));
        assert_eq!(config2["provider"]["url"], "ws://example.com:4321");
    }
}