feat(cheddar): Implement highlighting of CL and bug shortlinks
Implements highlighting of shortlinks like cl/123, or b/123. Highlighting works by replacing the input Markdown using a simple regular expression replacement. We also considered parsing and replacing these links in the Markdown AST, but it would have been significantly more complex (due to arena allocation) for little upside and no obvious performance benefit. Change-Id: I53f03fb17491046d89d0b7f605929571c11ee9a8 Reviewed-on: https://cl.tvl.fyi/c/depot/+/3082 Tested-by: BuildkiteCI Reviewed-by: eta <eta@theta.eu.org>
This commit is contained in:
parent
57502cfc46
commit
a9902dadcf
4 changed files with 51 additions and 1 deletions
1
tools/cheddar/Cargo.lock
generated
1
tools/cheddar/Cargo.lock
generated
|
@ -196,6 +196,7 @@ dependencies = [
|
|||
"clap",
|
||||
"comrak",
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"rouille",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
|
@ -11,6 +11,7 @@ lazy_static = "1.4"
|
|||
rouille = "3.0"
|
||||
syntect = "4.5.0"
|
||||
serde_json = "1.0"
|
||||
regex = "1.4"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
|
|
|
@ -5,6 +5,7 @@ use comrak::arena_tree::Node;
|
|||
use comrak::nodes::{Ast, AstNode, NodeCodeBlock, NodeHtmlBlock, NodeValue};
|
||||
use comrak::{format_html, parse_document, Arena, ComrakOptions};
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
|
@ -68,6 +69,13 @@ lazy_static! {
|
|||
map.insert("rules.pl", "Prolog");
|
||||
map
|
||||
};
|
||||
|
||||
// Supported shortlinks in Markdown files.
|
||||
//
|
||||
// Currently only bug links (e.g. b/123) and CL links (e.g.
|
||||
// cl/345) are supported. Coincidentally these have the same
|
||||
// format, which makes the initial implementation easy.
|
||||
static ref SHORTLINK: Regex = Regex::new("\\b(?P<type>b|cl)/(?P<dest>\\d+)\\b").unwrap();
|
||||
}
|
||||
|
||||
// HTML fragment used when rendering inline blocks in Markdown documents.
|
||||
|
@ -172,6 +180,12 @@ fn has_callout<'a>(node: &Node<'a, RefCell<Ast>>) -> Option<Callout> {
|
|||
}
|
||||
}
|
||||
|
||||
// Replace instances of known shortlinks in the input document with
|
||||
// Markdown syntax for a highlighted link.
|
||||
fn linkify_shortlinks<'a>(input: &'a str) -> std::borrow::Cow<'a, str> {
|
||||
SHORTLINK.replace_all(input, "[$type/$dest](https://$type.tvl.fyi/$dest)")
|
||||
}
|
||||
|
||||
fn format_callout_paragraph(callout: Callout) -> NodeValue {
|
||||
let class = match callout {
|
||||
Callout::Todo => "cheddar-todo",
|
||||
|
@ -195,7 +209,7 @@ pub fn format_markdown<R: BufRead, W: Write>(reader: &mut R, writer: &mut W) {
|
|||
};
|
||||
|
||||
let arena = Arena::new();
|
||||
let root = parse_document(&arena, &document, &MD_OPTS);
|
||||
let root = parse_document(&arena, &linkify_shortlinks(&document), &MD_OPTS);
|
||||
|
||||
// This node must exist with a lifetime greater than that of the parsed AST
|
||||
// in case that callouts are encountered (otherwise insertion into the tree
|
||||
|
|
|
@ -61,3 +61,37 @@ toString 42
|
|||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn highlights_bug_link() {
|
||||
expect_markdown(
|
||||
"Please look at b/123.",
|
||||
"<p>Please look at <a href=\"https://b.tvl.fyi/123\">b/123</a>.</p>",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn highlights_cl_link() {
|
||||
expect_markdown(
|
||||
"Please look at cl/420.",
|
||||
"<p>Please look at <a href=\"https://cl.tvl.fyi/420\">cl/420</a>.</p>",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn highlights_multiple_shortlinks() {
|
||||
expect_markdown(
|
||||
"Please look at cl/420, b/123.",
|
||||
"<p>Please look at <a href=\"https://cl.tvl.fyi/420\">cl/420</a>, <a href=\"https://b.tvl.fyi/123\">b/123</a>.</p>",
|
||||
);
|
||||
|
||||
expect_markdown(
|
||||
"b/213/cl/213 are different things",
|
||||
"<p><a href=\"https://b.tvl.fyi/213\">b/213</a>/<a href=\"https://cl.tvl.fyi/213\">cl/213</a> are different things</p>",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignores_invalid_shortlinks() {
|
||||
expect_markdown("b/abc is not a real bug", "<p>b/abc is not a real bug</p>");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue