diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index c47eb0b3fad45..e08ff9d524179 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -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 /// diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 55308a46f0ac5..f46cc242d1e0e 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -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")] @@ -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 /// @@ -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 /// @@ -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. @@ -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. /// @@ -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 @@ -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 @@ -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. /// @@ -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. @@ -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. /// @@ -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 /// @@ -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 /// @@ -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 /// @@ -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 /// @@ -1715,7 +1715,7 @@ impl str { /// Converts a `Box` into a [`String`] without copying or allocating. /// - /// [`String`]: string/struct.String.html + /// [`String`]: ::/std/string/struct.String.html /// /// # Examples /// diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 139e1033175ea..8c59f9b989e59 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -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; @@ -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, } @@ -219,7 +226,7 @@ thread_local!(pub static PLAYGROUND_KRATE: RefCell>> = { 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 { @@ -349,11 +356,50 @@ 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 @@ -361,6 +407,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { (*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(), @@ -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) } } @@ -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!("

Link

\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"); + } + } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index f63d37b34032e..dc9324a8b8cf5 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -71,7 +71,7 @@ use html::format::{TyParamBounds, WhereClause, href, AbiSpace}; use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace}; use html::format::fmt_impl_for_trait_page; use html::item_type::ItemType; -use html::markdown::{self, Markdown}; +use html::markdown::{self, MarkdownRelative}; use html::{highlight, layout}; /// A pair of name and its optional document. @@ -1660,11 +1660,12 @@ fn plain_summary_line(s: Option<&str>) -> String { fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result { document_stability(w, cx, item)?; - document_full(w, item)?; + document_full(w, cx, item)?; Ok(()) } -fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLink) -> fmt::Result { +fn document_short(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, link: AssocItemLink) + -> fmt::Result { if let Some(s) = item.doc_value() { let markdown = if s.contains('\n') { format!("{} [Read more]({})", @@ -1672,14 +1673,14 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin } else { format!("{}", &plain_summary_line(Some(s))) }; - write!(w, "
{}
", Markdown(&markdown))?; + write!(w, "
{}
", MarkdownRelative(&markdown, &cx.root_path))?; } Ok(()) } -fn document_full(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result { +fn document_full(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result { if let Some(s) = item.doc_value() { - write!(w, "
{}
", Markdown(s))?; + write!(w, "
{}
", MarkdownRelative(s, &cx.root_path))?; } Ok(()) } @@ -1829,7 +1830,9 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, ", name = *myitem.name.as_ref().unwrap(), stab_docs = stab_docs, - docs = shorter(Some(&Markdown(doc_value).to_string())), + docs = shorter( + Some(&MarkdownRelative(doc_value, &cx.root_path).to_string()) + ), class = shortty(myitem), stab = myitem.stability_class(), href = item_path(shortty(myitem), myitem.name.as_ref().unwrap()), @@ -1859,7 +1862,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) }; @@ -1879,7 +1882,8 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) }; } else if let Some(depr) = item.deprecation.as_ref() { @@ -1894,7 +1898,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) } @@ -2591,7 +2595,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi write!(w, "")?; write!(w, "\n")?; if let Some(ref dox) = i.impl_item.attrs.value("doc") { - write!(w, "
{}
", Markdown(dox))?; + write!(w, "
{}
", MarkdownRelative(dox, &cx.root_path))?; } } @@ -2659,11 +2663,11 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi // because impls can't have a stability. document_stability(w, cx, it)?; if item.doc_value().is_some() { - document_full(w, item)?; + document_full(w, cx, item)?; } else { // In case the item isn't documented, // provide short documentation from the trait. - document_short(w, it, link)?; + document_short(w, cx, it, link)?; } } } else { @@ -2671,7 +2675,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi } } else { document_stability(w, cx, item)?; - document_short(w, item, link)?; + document_short(w, cx, item, link)?; } } Ok(()) diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index d21726dd40f08..c360973c8ad02 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -86,7 +86,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, reset_ids(false); let rendered = if include_toc { - format!("{}", MarkdownWithToc(text)) + format!("{}", MarkdownWithToc(text, "")) } else { format!("{}", Markdown(text)) };