Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix broken links due to multiple mod paths for the same doc string #34463

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/libcollections/btree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ use Bound;
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
///
/// [`BTreeMap`]: struct.BTreeMap.html
/// [`Ord`]: ../../std/cmp/trait.Ord.html
/// [`Cell`]: ../../std/cell/struct.Cell.html
/// [`RefCell`]: ../../std/cell/struct.RefCell.html
/// [`Ord`]: ::/std/cmp/trait.Ord.html
/// [`Cell`]: ::/std/cell/struct.Cell.html
/// [`RefCell`]: ::/std/cell/struct.RefCell.html
///
/// # Examples
///
Expand Down
32 changes: 16 additions & 16 deletions src/libcollections/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

//! Unicode string slices.
//!
//! *[See also the `str` primitive type](../../std/primitive.str.html).*
//! *[See also the `str` primitive type](::/std/primitive.str.html).*


#![stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -715,7 +715,7 @@ impl str {
/// a character matches.
///
/// [`char`]: primitive.char.html
/// [`None`]: option/enum.Option.html#variant.None
/// [`None`]: ::/std/option/enum.Option.html#variant.None
///
/// # Examples
///
Expand Down Expand Up @@ -760,7 +760,7 @@ impl str {
/// a character matches.
///
/// [`char`]: primitive.char.html
/// [`None`]: option/enum.Option.html#variant.None
/// [`None`]: ::/std/option/enum.Option.html#variant.None
///
/// # Examples
///
Expand Down Expand Up @@ -809,7 +809,7 @@ impl str {
/// allows a reverse search and forward/reverse search yields the same
/// elements. This is true for, eg, [`char`] but not for `&str`.
///
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
///
/// If the pattern allows a reverse search but its results might differ
/// from a forward search, the [`rsplit()`] method can be used.
Expand Down Expand Up @@ -922,7 +922,7 @@ impl str {
/// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
/// search yields the same elements.
///
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
///
/// For iterating from the front, the [`split()`] method can be used.
///
Expand Down Expand Up @@ -979,7 +979,7 @@ impl str {
/// allows a reverse search and forward/reverse search yields the same
/// elements. This is true for, eg, [`char`] but not for `&str`.
///
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
/// [`char`]: primitive.char.html
///
/// If the pattern allows a reverse search but its results might differ
Expand Down Expand Up @@ -1161,7 +1161,7 @@ impl str {
/// allows a reverse search and forward/reverse search yields the same
/// elements. This is true for, eg, [`char`] but not for `&str`.
///
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
/// [`char`]: primitive.char.html
///
/// If the pattern allows a reverse search but its results might differ
Expand Down Expand Up @@ -1199,7 +1199,7 @@ impl str {
/// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
/// search yields the same elements.
///
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
///
/// For iterating from the front, the [`matches()`] method can be used.
///
Expand Down Expand Up @@ -1240,7 +1240,7 @@ impl str {
/// allows a reverse search and forward/reverse search yields the same
/// elements. This is true for, eg, [`char`] but not for `&str`.
///
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
///
/// If the pattern allows a reverse search but its results might differ
/// from a forward search, the [`rmatch_indices()`] method can be used.
Expand Down Expand Up @@ -1283,7 +1283,7 @@ impl str {
/// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
/// search yields the same elements.
///
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
/// [`DoubleEndedIterator`]: ::/std/iter/trait.DoubleEndedIterator.html
///
/// For iterating from the front, the [`match_indices()`] method can be used.
///
Expand Down Expand Up @@ -1513,14 +1513,14 @@ impl str {
///
/// `parse()` can parse any type that implements the [`FromStr`] trait.
///
/// [`FromStr`]: str/trait.FromStr.html
/// [`FromStr`]: ::/std/str/trait.FromStr.html
///
/// # Errors
///
/// Will return [`Err`] if it's not possible to parse this string slice into
/// the desired type.
///
/// [`Err`]: str/trait.FromStr.html#associatedtype.Err
/// [`Err`]: ::/std/str/trait.FromStr.html#associatedtype.Err
///
/// # Example
///
Expand Down Expand Up @@ -1559,7 +1559,7 @@ impl str {
/// While doing so, it attempts to find matches of a pattern. If it finds any, it
/// replaces them with the replacement string slice.
///
/// [`String`]: string/struct.String.html
/// [`String`]: ::/std/string/struct.String.html
///
/// # Examples
///
Expand Down Expand Up @@ -1595,7 +1595,7 @@ impl str {
/// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property
/// `Lowercase`.
///
/// [`String`]: string/struct.String.html
/// [`String`]: ::/std/string/struct.String.html
///
/// # Examples
///
Expand Down Expand Up @@ -1671,7 +1671,7 @@ impl str {
/// 'Uppercase' is defined according to the terms of the Unicode Derived Core Property
/// `Uppercase`.
///
/// [`String`]: string/struct.String.html
/// [`String`]: ::/std/string/struct.String.html
///
/// # Examples
///
Expand Down Expand Up @@ -1715,7 +1715,7 @@ impl str {

/// Converts a `Box<str>` into a [`String`] without copying or allocating.
///
/// [`String`]: string/struct.String.html
/// [`String`]: ::/std/string/struct.String.html
///
/// # Examples
///
Expand Down
84 changes: 77 additions & 7 deletions src/librustdoc/html/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,12 @@ use test;
/// formatted, this struct will emit the HTML corresponding to the rendered
/// version of the contained markdown string.
pub struct Markdown<'a>(pub &'a str);
/// A unit struct like `Markdown`, that renders the markdown with a
/// A unit struct like `Markdown`, that can expand '::/...' links
/// using the root prefix provided in the second string.
pub struct MarkdownRelative<'a>(pub &'a str, pub &'a str);
/// A unit struct like `MarkdownRelative`, that renders the markdown with a
/// table of contents.
pub struct MarkdownWithToc<'a>(pub &'a str);
pub struct MarkdownWithToc<'a>(pub &'a str, pub &'a str);

const DEF_OUNIT: libc::size_t = 64;
const HOEDOWN_EXT_NO_INTRA_EMPHASIS: libc::c_uint = 1 << 11;
Expand Down Expand Up @@ -143,9 +146,13 @@ struct html_toc_data {
nesting_level: libc::c_int,
}

struct MyOpaque {
struct MyOpaque<'a> {
dfltblk: extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
*const hoedown_buffer, *const hoedown_renderer_data),
dfltlink: extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
*const hoedown_buffer, *const hoedown_buffer,
*const hoedown_renderer_data) -> libc::c_int,
root_path: &'a str,
toc_builder: Option<TocBuilder>,
}

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

pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool, root_path: &str) -> fmt::Result {
extern fn block(ob: *mut hoedown_buffer, orig_text: *const hoedown_buffer,
lang: *const hoedown_buffer, data: *const hoedown_renderer_data) {
unsafe {
Expand Down Expand Up @@ -349,18 +356,58 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
1
}

// Intercept the default link logic to process mod-relative links starting with '::/'
extern fn link(
ob: *mut hoedown_buffer,
content: *const hoedown_buffer,
link: *const hoedown_buffer,
title: *const hoedown_buffer,
data: *const hoedown_renderer_data,
) -> libc::c_int {

let my_opaque : &MyOpaque = unsafe {
let opaque = (*data).opaque as *mut hoedown_html_renderer_state;
&*((*opaque).opaque as *const MyOpaque)
};

if link.is_null() {
return (my_opaque.dfltlink)(ob, content, link, title, data);
}

let bytes = unsafe { (*link).as_bytes() };
let link_str = str::from_utf8(bytes).unwrap().to_owned();

if !link_str.starts_with("::/") {
return (my_opaque.dfltlink)(ob, content, link, title, data);
}

let new_link = my_opaque.root_path.to_owned() + &link_str[3..];
let new_link = CString::new(new_link).unwrap();

unsafe {
let link_buffer = hoedown_buffer_new(DEF_OUNIT);
hoedown_buffer_puts(link_buffer, new_link.as_ptr());
let result = (my_opaque.dfltlink)(ob, content, link_buffer, title, data);
hoedown_buffer_free(link_buffer);
result
}
}

unsafe {
let ob = hoedown_buffer_new(DEF_OUNIT);
let renderer = hoedown_html_renderer_new(0, 0);
let mut opaque = MyOpaque {
dfltblk: (*renderer).blockcode.unwrap(),
dfltlink: (*renderer).link.unwrap(),
root_path: root_path,
toc_builder: if print_toc {Some(TocBuilder::new())} else {None}
};
(*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
= &mut opaque as *mut _ as *mut libc::c_void;
(*renderer).blockcode = Some(block);
(*renderer).header = Some(header);
(*renderer).codespan = Some(codespan);
(*renderer).link = Some(link);

let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
hoedown_document_render(document, ob, s.as_ptr(),
Expand Down Expand Up @@ -524,14 +571,23 @@ impl<'a> fmt::Display for Markdown<'a> {
let Markdown(md) = *self;
// This is actually common enough to special-case
if md.is_empty() { return Ok(()) }
render(fmt, md, false)
render(fmt, md, false, "")
}
}

impl<'a> fmt::Display for MarkdownRelative<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let MarkdownRelative(md, root_path) = *self;
// This is actually common enough to special-case
if md.is_empty() { return Ok(()) }
render(fmt, md, false, root_path)
}
}

impl<'a> fmt::Display for MarkdownWithToc<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let MarkdownWithToc(md) = *self;
render(fmt, md, true)
let MarkdownWithToc(md, root_path) = *self;
render(fmt, md, true, root_path)
}
}

Expand Down Expand Up @@ -690,4 +746,18 @@ mod tests {
t("# top header", "top header");
t("## header", "header");
}

#[test]
fn test_root_relative_links() {
fn t(input: &str, root: &str, expect: &str) {
let output = format!("{}", MarkdownRelative(input, root));
assert_eq!(output, format!("<p><a href=\"{}\">Link</a></p>\n", expect));
}

t("[Link](::/path/file.html)", "", "path/file.html");
t("[Link](::/path/file.html)", "../", "../path/file.html");
t("[Link](::/path/file.html)", "../../", "../../path/file.html");
t("[Link]\n[Link]: ::/path/file.html", "../", "../path/file.html");
}

}
Loading