diff options
-rw-r--r-- | tools/cheddar/Cargo.lock | 1 | ||||
-rw-r--r-- | tools/cheddar/Cargo.toml | 1 | ||||
-rw-r--r-- | tools/cheddar/src/lib.rs | 16 | ||||
-rw-r--r-- | tools/cheddar/src/tests.rs | 34 |
4 files changed, 51 insertions, 1 deletions
diff --git a/tools/cheddar/Cargo.lock b/tools/cheddar/Cargo.lock index 09b9ff6e85d8..bc6af6ff4b82 100644 --- a/tools/cheddar/Cargo.lock +++ b/tools/cheddar/Cargo.lock @@ -196,6 +196,7 @@ dependencies = [ "clap", "comrak", "lazy_static", + "regex", "rouille", "serde", "serde_json", diff --git a/tools/cheddar/Cargo.toml b/tools/cheddar/Cargo.toml index ae33197cacdc..6cc8163c730a 100644 --- a/tools/cheddar/Cargo.toml +++ b/tools/cheddar/Cargo.toml @@ -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" diff --git a/tools/cheddar/src/lib.rs b/tools/cheddar/src/lib.rs index 5e88aaaf61f8..441af1f6e95d 100644 --- a/tools/cheddar/src/lib.rs +++ b/tools/cheddar/src/lib.rs @@ -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 diff --git a/tools/cheddar/src/tests.rs b/tools/cheddar/src/tests.rs index 8b8219b22d7c..5b7b1cc52a95 100644 --- a/tools/cheddar/src/tests.rs +++ b/tools/cheddar/src/tests.rs @@ -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>"); +} |