Skip to content

Commit 3c44331

Browse files
committed
Added mod-relative link support
1 parent eff0fdc commit 3c44331

File tree

5 files changed

+115
-41
lines changed

5 files changed

+115
-41
lines changed

src/libcollections/btree/set.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ use Bound;
3535
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
3636
///
3737
/// [`BTreeMap`]: struct.BTreeMap.html
38-
/// [`Ord`]: /std/cmp/trait.Ord.html
39-
/// [`Cell`]: /std/cell/struct.Cell.html
40-
/// [`RefCell`]: /std/cell/struct.RefCell.html
38+
/// [`Ord`]: ::/std/cmp/trait.Ord.html
39+
/// [`Cell`]: ::/std/cell/struct.Cell.html
40+
/// [`RefCell`]: ::/std/cell/struct.RefCell.html
4141
///
4242
/// # Examples
4343
///

src/libcollections/str.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
//! Unicode string slices.
1212
//!
13-
//! *[See also the `str` primitive type](../../std/primitive.str.html).*
13+
//! *[See also the `str` primitive type](::/std/primitive.str.html).*
1414
1515

1616
#![stable(feature = "rust1", since = "1.0.0")]
@@ -715,7 +715,7 @@ impl str {
715715
/// a character matches.
716716
///
717717
/// [`char`]: primitive.char.html
718-
/// [`None`]: /std/option/enum.Option.html#variant.None
718+
/// [`None`]: ::/std/option/enum.Option.html#variant.None
719719
///
720720
/// # Examples
721721
///
@@ -760,7 +760,7 @@ impl str {
760760
/// a character matches.
761761
///
762762
/// [`char`]: primitive.char.html
763-
/// [`None`]: /std/option/enum.Option.html#variant.None
763+
/// [`None`]: ::/std/option/enum.Option.html#variant.None
764764
///
765765
/// # Examples
766766
///
@@ -809,7 +809,7 @@ impl str {
809809
/// allows a reverse search and forward/reverse search yields the same
810810
/// elements. This is true for, eg, [`char`] but not for `&str`.
811811
///
812-
/// [`DoubleEndedIterator`]: /std/iter/trait.DoubleEndedIterator.html
812+
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
813813
///
814814
/// If the pattern allows a reverse search but its results might differ
815815
/// from a forward search, the [`rsplit()`] method can be used.
@@ -922,7 +922,7 @@ impl str {
922922
/// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
923923
/// search yields the same elements.
924924
///
925-
/// [`DoubleEndedIterator`]: /std/iter/trait.DoubleEndedIterator.html
925+
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
926926
///
927927
/// For iterating from the front, the [`split()`] method can be used.
928928
///
@@ -979,7 +979,7 @@ impl str {
979979
/// allows a reverse search and forward/reverse search yields the same
980980
/// elements. This is true for, eg, [`char`] but not for `&str`.
981981
///
982-
/// [`DoubleEndedIterator`]: /std/iter/trait.DoubleEndedIterator.html
982+
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
983983
/// [`char`]: primitive.char.html
984984
///
985985
/// If the pattern allows a reverse search but its results might differ
@@ -1161,7 +1161,7 @@ impl str {
11611161
/// allows a reverse search and forward/reverse search yields the same
11621162
/// elements. This is true for, eg, [`char`] but not for `&str`.
11631163
///
1164-
/// [`DoubleEndedIterator`]: /std/iter/trait.DoubleEndedIterator.html
1164+
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
11651165
/// [`char`]: primitive.char.html
11661166
///
11671167
/// If the pattern allows a reverse search but its results might differ
@@ -1199,7 +1199,7 @@ impl str {
11991199
/// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
12001200
/// search yields the same elements.
12011201
///
1202-
/// [`DoubleEndedIterator`]: /std/iter/trait.DoubleEndedIterator.html
1202+
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
12031203
///
12041204
/// For iterating from the front, the [`matches()`] method can be used.
12051205
///
@@ -1240,7 +1240,7 @@ impl str {
12401240
/// allows a reverse search and forward/reverse search yields the same
12411241
/// elements. This is true for, eg, [`char`] but not for `&str`.
12421242
///
1243-
/// [`DoubleEndedIterator`]: /std/iter/trait.DoubleEndedIterator.html
1243+
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
12441244
///
12451245
/// If the pattern allows a reverse search but its results might differ
12461246
/// from a forward search, the [`rmatch_indices()`] method can be used.
@@ -1283,7 +1283,7 @@ impl str {
12831283
/// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
12841284
/// search yields the same elements.
12851285
///
1286-
/// [`DoubleEndedIterator`]: /std/iter/trait.DoubleEndedIterator.html
1286+
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
12871287
///
12881288
/// For iterating from the front, the [`match_indices()`] method can be used.
12891289
///
@@ -1513,14 +1513,14 @@ impl str {
15131513
///
15141514
/// `parse()` can parse any type that implements the [`FromStr`] trait.
15151515
///
1516-
/// [`FromStr`]: /std/str/trait.FromStr.html
1516+
/// [`FromStr`]: ::/std/str/trait.FromStr.html
15171517
///
15181518
/// # Errors
15191519
///
15201520
/// Will return [`Err`] if it's not possible to parse this string slice into
15211521
/// the desired type.
15221522
///
1523-
/// [`Err`]: /std/str/trait.FromStr.html#associatedtype.Err
1523+
/// [`Err`]: ::/std/str/trait.FromStr.html#associatedtype.Err
15241524
///
15251525
/// # Example
15261526
///
@@ -1559,7 +1559,7 @@ impl str {
15591559
/// While doing so, it attempts to find matches of a pattern. If it finds any, it
15601560
/// replaces them with the replacement string slice.
15611561
///
1562-
/// [`String`]: /std/string/struct.String.html
1562+
/// [`String`]: ::/std/string/struct.String.html
15631563
///
15641564
/// # Examples
15651565
///
@@ -1595,7 +1595,7 @@ impl str {
15951595
/// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property
15961596
/// `Lowercase`.
15971597
///
1598-
/// [`String`]: /std/string/struct.String.html
1598+
/// [`String`]: ::/std/string/struct.String.html
15991599
///
16001600
/// # Examples
16011601
///
@@ -1671,7 +1671,7 @@ impl str {
16711671
/// 'Uppercase' is defined according to the terms of the Unicode Derived Core Property
16721672
/// `Uppercase`.
16731673
///
1674-
/// [`String`]: /std/string/struct.String.html
1674+
/// [`String`]: ::/std/string/struct.String.html
16751675
///
16761676
/// # Examples
16771677
///
@@ -1715,7 +1715,7 @@ impl str {
17151715

17161716
/// Converts a `Box<str>` into a [`String`] without copying or allocating.
17171717
///
1718-
/// [`String`]: /std/string/struct.String.html
1718+
/// [`String`]: ::/std/string/struct.String.html
17191719
///
17201720
/// # Examples
17211721
///

src/librustdoc/html/markdown.rs

+77-7
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,12 @@ use test;
4747
/// formatted, this struct will emit the HTML corresponding to the rendered
4848
/// version of the contained markdown string.
4949
pub struct Markdown<'a>(pub &'a str);
50-
/// A unit struct like `Markdown`, that renders the markdown with a
50+
/// A unit struct like `Markdown`, that can expand '::/...' links
51+
/// using the root prefix provided in the second string.
52+
pub struct MarkdownRelative<'a>(pub &'a str, pub &'a str);
53+
/// A unit struct like `MarkdownRelative`, that renders the markdown with a
5154
/// table of contents.
52-
pub struct MarkdownWithToc<'a>(pub &'a str);
55+
pub struct MarkdownWithToc<'a>(pub &'a str, pub &'a str);
5356

5457
const DEF_OUNIT: libc::size_t = 64;
5558
const HOEDOWN_EXT_NO_INTRA_EMPHASIS: libc::c_uint = 1 << 11;
@@ -143,9 +146,13 @@ struct html_toc_data {
143146
nesting_level: libc::c_int,
144147
}
145148

146-
struct MyOpaque {
149+
struct MyOpaque<'a> {
147150
dfltblk: extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
148151
*const hoedown_buffer, *const hoedown_renderer_data),
152+
dfltlink: extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
153+
*const hoedown_buffer, *const hoedown_buffer,
154+
*const hoedown_renderer_data) -> libc::c_int,
155+
root_path: &'a str,
149156
toc_builder: Option<TocBuilder>,
150157
}
151158

@@ -219,7 +226,7 @@ thread_local!(pub static PLAYGROUND_KRATE: RefCell<Option<Option<String>>> = {
219226
RefCell::new(None)
220227
});
221228

222-
pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
229+
pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool, root_path: &str) -> fmt::Result {
223230
extern fn block(ob: *mut hoedown_buffer, orig_text: *const hoedown_buffer,
224231
lang: *const hoedown_buffer, data: *const hoedown_renderer_data) {
225232
unsafe {
@@ -349,18 +356,58 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
349356
1
350357
}
351358

359+
// Intercept the default link logic to process mod-relative links starting with '::/'
360+
extern fn link(
361+
ob: *mut hoedown_buffer,
362+
content: *const hoedown_buffer,
363+
link: *const hoedown_buffer,
364+
title: *const hoedown_buffer,
365+
data: *const hoedown_renderer_data,
366+
) -> libc::c_int {
367+
368+
let my_opaque : &MyOpaque = unsafe {
369+
let opaque = (*data).opaque as *mut hoedown_html_renderer_state;
370+
&*((*opaque).opaque as *const MyOpaque)
371+
};
372+
373+
if link.is_null() {
374+
return (my_opaque.dfltlink)(ob, content, link, title, data);
375+
}
376+
377+
let bytes = unsafe { (*link).as_bytes() };
378+
let link_str = str::from_utf8(bytes).unwrap().to_owned();
379+
380+
if !link_str.starts_with("::/") {
381+
return (my_opaque.dfltlink)(ob, content, link, title, data);
382+
}
383+
384+
let new_link = my_opaque.root_path.to_owned() + &link_str[3..];
385+
let new_link = CString::new(new_link).unwrap();
386+
387+
unsafe {
388+
let link_buffer = hoedown_buffer_new(DEF_OUNIT);
389+
hoedown_buffer_puts(link_buffer, new_link.as_ptr());
390+
let result = (my_opaque.dfltlink)(ob, content, link_buffer, title, data);
391+
hoedown_buffer_free(link_buffer);
392+
result
393+
}
394+
}
395+
352396
unsafe {
353397
let ob = hoedown_buffer_new(DEF_OUNIT);
354398
let renderer = hoedown_html_renderer_new(0, 0);
355399
let mut opaque = MyOpaque {
356400
dfltblk: (*renderer).blockcode.unwrap(),
401+
dfltlink: (*renderer).link.unwrap(),
402+
root_path: root_path,
357403
toc_builder: if print_toc {Some(TocBuilder::new())} else {None}
358404
};
359405
(*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
360406
= &mut opaque as *mut _ as *mut libc::c_void;
361407
(*renderer).blockcode = Some(block);
362408
(*renderer).header = Some(header);
363409
(*renderer).codespan = Some(codespan);
410+
(*renderer).link = Some(link);
364411

365412
let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
366413
hoedown_document_render(document, ob, s.as_ptr(),
@@ -524,14 +571,23 @@ impl<'a> fmt::Display for Markdown<'a> {
524571
let Markdown(md) = *self;
525572
// This is actually common enough to special-case
526573
if md.is_empty() { return Ok(()) }
527-
render(fmt, md, false)
574+
render(fmt, md, false, "")
575+
}
576+
}
577+
578+
impl<'a> fmt::Display for MarkdownRelative<'a> {
579+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
580+
let MarkdownRelative(md, root_path) = *self;
581+
// This is actually common enough to special-case
582+
if md.is_empty() { return Ok(()) }
583+
render(fmt, md, false, root_path)
528584
}
529585
}
530586

531587
impl<'a> fmt::Display for MarkdownWithToc<'a> {
532588
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
533-
let MarkdownWithToc(md) = *self;
534-
render(fmt, md, true)
589+
let MarkdownWithToc(md, root_path) = *self;
590+
render(fmt, md, true, root_path)
535591
}
536592
}
537593

@@ -690,4 +746,18 @@ mod tests {
690746
t("# top header", "top header");
691747
t("## header", "header");
692748
}
749+
750+
#[test]
751+
fn test_root_relative_links() {
752+
fn t(input: &str, root: &str, expect: &str) {
753+
let output = format!("{}", MarkdownRelative(input, root));
754+
assert_eq!(output, format!("<p><a href=\"{}\">Link</a></p>\n", expect));
755+
}
756+
757+
t("[Link](::/path/file.html)", "", "path/file.html");
758+
t("[Link](::/path/file.html)", "../", "../path/file.html");
759+
t("[Link](::/path/file.html)", "../../", "../../path/file.html");
760+
t("[Link]\n[Link]: ::/path/file.html", "../", "../path/file.html");
761+
}
762+
693763
}

0 commit comments

Comments
 (0)