mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-25 14:13:38 +00:00
Add LinkReplacer pass for pulldown
This commit is contained in:
parent
dae2e22e81
commit
e8dd5df69b
@ -308,6 +308,11 @@ impl Item {
|
||||
pub fn collapsed_doc_value(&self) -> Option<String> {
|
||||
self.attrs.collapsed_doc_value()
|
||||
}
|
||||
|
||||
pub fn links(&self) -> Vec<(String, String)> {
|
||||
self.attrs.links()
|
||||
}
|
||||
|
||||
pub fn is_crate(&self) -> bool {
|
||||
match self.inner {
|
||||
StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
|
||||
@ -791,6 +796,20 @@ impl Attributes {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Get links as a vector
|
||||
///
|
||||
/// Cache must be populated before call
|
||||
pub fn links(&self) -> Vec<(String, String)> {
|
||||
use html::format::href;
|
||||
self.links.iter().filter_map(|&(ref s, did)| {
|
||||
if let Some((href, ..)) = href(did) {
|
||||
Some((s.clone(), href))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl AttributesExt for Attributes {
|
||||
|
@ -37,7 +37,7 @@ impl ExternalHtml {
|
||||
)
|
||||
.and_then(|(ih, bc)|
|
||||
load_external_files(md_before_content)
|
||||
.map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, render))))
|
||||
.map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, &[], render))))
|
||||
)
|
||||
.and_then(|(ih, bc)|
|
||||
load_external_files(after_content)
|
||||
@ -45,7 +45,7 @@ impl ExternalHtml {
|
||||
)
|
||||
.and_then(|(ih, bc, ac)|
|
||||
load_external_files(md_after_content)
|
||||
.map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, render))))
|
||||
.map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, &[], render))))
|
||||
)
|
||||
.map(|(ih, bc, ac)|
|
||||
ExternalHtml {
|
||||
|
@ -56,15 +56,16 @@ pub enum RenderType {
|
||||
/// A unit struct which has the `fmt::Display` trait implemented. When
|
||||
/// formatted, this struct will emit the HTML corresponding to the rendered
|
||||
/// version of the contained markdown string.
|
||||
// The second parameter is whether we need a shorter version or not.
|
||||
pub struct Markdown<'a>(pub &'a str, pub RenderType);
|
||||
/// The second parameter is a list of link replacements
|
||||
// The third parameter is whether we need a shorter version or not.
|
||||
pub struct Markdown<'a>(pub &'a str, pub &'a [(String, String)], pub RenderType);
|
||||
/// A unit struct like `Markdown`, that renders the markdown with a
|
||||
/// table of contents.
|
||||
pub struct MarkdownWithToc<'a>(pub &'a str, pub RenderType);
|
||||
/// A unit struct like `Markdown`, that renders the markdown escaping HTML tags.
|
||||
pub struct MarkdownHtml<'a>(pub &'a str, pub RenderType);
|
||||
/// A unit struct like `Markdown`, that renders only the first paragraph.
|
||||
pub struct MarkdownSummaryLine<'a>(pub &'a str);
|
||||
pub struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [(String, String)]);
|
||||
|
||||
/// Controls whether a line will be hidden or shown in HTML output.
|
||||
///
|
||||
@ -247,6 +248,38 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Make headings links with anchor ids and build up TOC.
|
||||
struct LinkReplacer<'a, 'b, I: Iterator<Item = Event<'a>>> {
|
||||
inner: I,
|
||||
links: &'b [(String, String)]
|
||||
}
|
||||
|
||||
impl<'a, 'b, I: Iterator<Item = Event<'a>>> LinkReplacer<'a, 'b, I> {
|
||||
fn new(iter: I, links: &'b [(String, String)]) -> Self {
|
||||
LinkReplacer {
|
||||
inner: iter,
|
||||
links
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, 'b, I> {
|
||||
type Item = Event<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let event = self.inner.next();
|
||||
if let Some(Event::Start(Tag::Link(dest, text))) = event {
|
||||
if let Some(&(_, ref replace)) = self.links.into_iter().find(|link| &*link.0 == &*dest) {
|
||||
Some(Event::Start(Tag::Link(replace.to_owned().into(), text)))
|
||||
} else {
|
||||
Some(Event::Start(Tag::Link(dest, text)))
|
||||
}
|
||||
} else {
|
||||
event
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Make headings links with anchor ids and build up TOC.
|
||||
struct HeadingLinks<'a, 'b, I: Iterator<Item = Event<'a>>> {
|
||||
inner: I,
|
||||
@ -996,7 +1029,7 @@ impl LangString {
|
||||
|
||||
impl<'a> fmt::Display for Markdown<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
let Markdown(md, render_type) = *self;
|
||||
let Markdown(md, links, render_type) = *self;
|
||||
|
||||
// This is actually common enough to special-case
|
||||
if md.is_empty() { return Ok(()) }
|
||||
@ -1012,7 +1045,7 @@ impl<'a> fmt::Display for Markdown<'a> {
|
||||
let mut s = String::with_capacity(md.len() * 3 / 2);
|
||||
|
||||
html::push_html(&mut s,
|
||||
Footnotes::new(CodeBlocks::new(HeadingLinks::new(p, None))));
|
||||
Footnotes::new(CodeBlocks::new(LinkReplacer::new(HeadingLinks::new(p, None), links))));
|
||||
|
||||
fmt.write_str(&s)
|
||||
}
|
||||
@ -1079,7 +1112,7 @@ impl<'a> fmt::Display for MarkdownHtml<'a> {
|
||||
|
||||
impl<'a> fmt::Display for MarkdownSummaryLine<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
let MarkdownSummaryLine(md) = *self;
|
||||
let MarkdownSummaryLine(md, links) = *self;
|
||||
// This is actually common enough to special-case
|
||||
if md.is_empty() { return Ok(()) }
|
||||
|
||||
@ -1087,7 +1120,7 @@ impl<'a> fmt::Display for MarkdownSummaryLine<'a> {
|
||||
|
||||
let mut s = String::new();
|
||||
|
||||
html::push_html(&mut s, SummaryLine::new(p));
|
||||
html::push_html(&mut s, LinkReplacer::new(SummaryLine::new(p), links));
|
||||
|
||||
fmt.write_str(&s)
|
||||
}
|
||||
|
@ -1861,12 +1861,13 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re
|
||||
/// rendering between Pulldown and Hoedown.
|
||||
fn render_markdown(w: &mut fmt::Formatter,
|
||||
md_text: &str,
|
||||
links: Vec<(String, String)>,
|
||||
span: Span,
|
||||
render_type: RenderType,
|
||||
prefix: &str,
|
||||
scx: &SharedContext)
|
||||
-> fmt::Result {
|
||||
let (hoedown_output, pulldown_output) = render_text(|ty| format!("{}", Markdown(md_text, ty)));
|
||||
let (hoedown_output, pulldown_output) = render_text(|ty| format!("{}", Markdown(md_text, &links, ty)));
|
||||
let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output);
|
||||
differences.retain(|s| {
|
||||
match *s {
|
||||
@ -1898,7 +1899,7 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin
|
||||
} else {
|
||||
format!("{}", &plain_summary_line(Some(s)))
|
||||
};
|
||||
render_markdown(w, &markdown, item.source.clone(), cx.render_type, prefix, &cx.shared)?;
|
||||
render_markdown(w, &markdown, item.links(), item.source.clone(), cx.render_type, prefix, &cx.shared)?;
|
||||
} else if !prefix.is_empty() {
|
||||
write!(w, "<div class='docblock'>{}</div>", prefix)?;
|
||||
}
|
||||
@ -1924,7 +1925,7 @@ fn document_full(w: &mut fmt::Formatter, item: &clean::Item,
|
||||
cx: &Context, prefix: &str) -> fmt::Result {
|
||||
if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) {
|
||||
debug!("Doc block: =====\n{}\n=====", s);
|
||||
render_markdown(w, &*s, item.source.clone(), cx.render_type, prefix, &cx.shared)?;
|
||||
render_markdown(w, &*s, item.links(), item.source.clone(), cx.render_type, prefix, &cx.shared)?;
|
||||
} else if !prefix.is_empty() {
|
||||
write!(w, "<div class='docblock'>{}</div>", prefix)?;
|
||||
}
|
||||
@ -2146,10 +2147,10 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
|
||||
stab_docs = stab_docs,
|
||||
docs = if cx.render_type == RenderType::Hoedown {
|
||||
format!("{}",
|
||||
shorter(Some(&Markdown(doc_value,
|
||||
shorter(Some(&Markdown(doc_value, &item.links(),
|
||||
RenderType::Hoedown).to_string())))
|
||||
} else {
|
||||
format!("{}", MarkdownSummaryLine(doc_value))
|
||||
format!("{}", MarkdownSummaryLine(doc_value, &item.links()))
|
||||
},
|
||||
class = myitem.type_(),
|
||||
stab = myitem.stability_class().unwrap_or("".to_string()),
|
||||
@ -3338,7 +3339,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
|
||||
write!(w, "</span>")?;
|
||||
write!(w, "</h3>\n")?;
|
||||
if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) {
|
||||
write!(w, "<div class='docblock'>{}</div>", Markdown(&*dox, cx.render_type))?;
|
||||
write!(w, "<div class='docblock'>{}</div>", Markdown(&*dox, &i.impl_item.links(), cx.render_type))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches,
|
||||
} else {
|
||||
// Save the state of USED_ID_MAP so it only gets updated once even
|
||||
// though we're rendering twice.
|
||||
render_text(|ty| format!("{}", Markdown(text, ty)))
|
||||
render_text(|ty| format!("{}", Markdown(text, &[], ty)))
|
||||
};
|
||||
|
||||
let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output);
|
||||
|
Loading…
Reference in New Issue
Block a user