//! Renders a bit of code as HTML. use ra_db::SourceDatabase; use ra_syntax::{AstNode, TextUnit}; use crate::{FileId, RootDatabase}; use super::highlight; pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: bool) -> String { let parse = db.parse(file_id); fn rainbowify(seed: u64) -> String { use rand::prelude::*; let mut rng = SmallRng::seed_from_u64(seed); format!( "hsl({h},{s}%,{l}%)", h = rng.gen_range::(0, 361), s = rng.gen_range::(42, 99), l = rng.gen_range::(40, 91), ) } let ranges = highlight(db, file_id, None); let text = parse.tree().syntax().to_string(); let mut prev_pos = TextUnit::from(0); let mut buf = String::new(); buf.push_str(&STYLE); buf.push_str("
");
    for range in &ranges {
        if range.range.start() > prev_pos {
            let curr = &text[prev_pos.to_usize()..range.range.start().to_usize()];
            let text = html_escape(curr);
            buf.push_str(&text);
        }
        let curr = &text[range.range.start().to_usize()..range.range.end().to_usize()];

        let class = range.highlight.to_string().replace('.', " ");
        let color = match (rainbow, range.binding_hash) {
            (true, Some(hash)) => {
                format!(" data-binding-hash=\"{}\" style=\"color: {};\"", hash, rainbowify(hash))
            }
            _ => "".into(),
        };
        buf.push_str(&format!("{}", class, color, html_escape(curr)));

        prev_pos = range.range.end();
    }
    // Add the remaining (non-highlighted) text
    let curr = &text[prev_pos.to_usize()..];
    let text = html_escape(curr);
    buf.push_str(&text);
    buf.push_str("
"); buf } //FIXME: like, real html escaping fn html_escape(text: &str) -> String { text.replace("<", "<").replace(">", ">") } const STYLE: &str = " ";