Add LinkReplacer pass for pulldown
This commit is contained in:
@@ -308,6 +308,11 @@ impl Item {
|
|||||||
pub fn collapsed_doc_value(&self) -> Option<String> {
|
pub fn collapsed_doc_value(&self) -> Option<String> {
|
||||||
self.attrs.collapsed_doc_value()
|
self.attrs.collapsed_doc_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn links(&self) -> Vec<(String, String)> {
|
||||||
|
self.attrs.links()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_crate(&self) -> bool {
|
pub fn is_crate(&self) -> bool {
|
||||||
match self.inner {
|
match self.inner {
|
||||||
StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
|
StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
|
||||||
@@ -791,6 +796,20 @@ impl Attributes {
|
|||||||
None
|
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 {
|
impl AttributesExt for Attributes {
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ impl ExternalHtml {
|
|||||||
)
|
)
|
||||||
.and_then(|(ih, bc)|
|
.and_then(|(ih, bc)|
|
||||||
load_external_files(md_before_content)
|
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)|
|
.and_then(|(ih, bc)|
|
||||||
load_external_files(after_content)
|
load_external_files(after_content)
|
||||||
@@ -45,7 +45,7 @@ impl ExternalHtml {
|
|||||||
)
|
)
|
||||||
.and_then(|(ih, bc, ac)|
|
.and_then(|(ih, bc, ac)|
|
||||||
load_external_files(md_after_content)
|
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)|
|
.map(|(ih, bc, ac)|
|
||||||
ExternalHtml {
|
ExternalHtml {
|
||||||
|
|||||||
@@ -56,15 +56,16 @@ pub enum RenderType {
|
|||||||
/// A unit struct which has the `fmt::Display` trait implemented. When
|
/// A unit struct which has the `fmt::Display` trait implemented. When
|
||||||
/// formatted, this struct will emit the HTML corresponding to the rendered
|
/// formatted, this struct will emit the HTML corresponding to the rendered
|
||||||
/// version of the contained markdown string.
|
/// version of the contained markdown string.
|
||||||
// The second parameter is whether we need a shorter version or not.
|
/// The second parameter is a list of link replacements
|
||||||
pub struct Markdown<'a>(pub &'a str, pub RenderType);
|
// 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
|
/// A unit struct like `Markdown`, that renders the markdown with a
|
||||||
/// table of contents.
|
/// table of contents.
|
||||||
pub struct MarkdownWithToc<'a>(pub &'a str, pub RenderType);
|
pub struct MarkdownWithToc<'a>(pub &'a str, pub RenderType);
|
||||||
/// A unit struct like `Markdown`, that renders the markdown escaping HTML tags.
|
/// A unit struct like `Markdown`, that renders the markdown escaping HTML tags.
|
||||||
pub struct MarkdownHtml<'a>(pub &'a str, pub RenderType);
|
pub struct MarkdownHtml<'a>(pub &'a str, pub RenderType);
|
||||||
/// A unit struct like `Markdown`, that renders only the first paragraph.
|
/// 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.
|
/// 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.
|
/// Make headings links with anchor ids and build up TOC.
|
||||||
struct HeadingLinks<'a, 'b, I: Iterator<Item = Event<'a>>> {
|
struct HeadingLinks<'a, 'b, I: Iterator<Item = Event<'a>>> {
|
||||||
inner: I,
|
inner: I,
|
||||||
@@ -996,7 +1029,7 @@ impl LangString {
|
|||||||
|
|
||||||
impl<'a> fmt::Display for Markdown<'a> {
|
impl<'a> fmt::Display for Markdown<'a> {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
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
|
// This is actually common enough to special-case
|
||||||
if md.is_empty() { return Ok(()) }
|
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);
|
let mut s = String::with_capacity(md.len() * 3 / 2);
|
||||||
|
|
||||||
html::push_html(&mut s,
|
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)
|
fmt.write_str(&s)
|
||||||
}
|
}
|
||||||
@@ -1079,7 +1112,7 @@ impl<'a> fmt::Display for MarkdownHtml<'a> {
|
|||||||
|
|
||||||
impl<'a> fmt::Display for MarkdownSummaryLine<'a> {
|
impl<'a> fmt::Display for MarkdownSummaryLine<'a> {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
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
|
// This is actually common enough to special-case
|
||||||
if md.is_empty() { return Ok(()) }
|
if md.is_empty() { return Ok(()) }
|
||||||
|
|
||||||
@@ -1087,7 +1120,7 @@ impl<'a> fmt::Display for MarkdownSummaryLine<'a> {
|
|||||||
|
|
||||||
let mut s = String::new();
|
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)
|
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.
|
/// rendering between Pulldown and Hoedown.
|
||||||
fn render_markdown(w: &mut fmt::Formatter,
|
fn render_markdown(w: &mut fmt::Formatter,
|
||||||
md_text: &str,
|
md_text: &str,
|
||||||
|
links: Vec<(String, String)>,
|
||||||
span: Span,
|
span: Span,
|
||||||
render_type: RenderType,
|
render_type: RenderType,
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
scx: &SharedContext)
|
scx: &SharedContext)
|
||||||
-> fmt::Result {
|
-> 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);
|
let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output);
|
||||||
differences.retain(|s| {
|
differences.retain(|s| {
|
||||||
match *s {
|
match *s {
|
||||||
@@ -1898,7 +1899,7 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin
|
|||||||
} else {
|
} else {
|
||||||
format!("{}", &plain_summary_line(Some(s)))
|
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() {
|
} else if !prefix.is_empty() {
|
||||||
write!(w, "<div class='docblock'>{}</div>", prefix)?;
|
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 {
|
cx: &Context, prefix: &str) -> fmt::Result {
|
||||||
if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) {
|
if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) {
|
||||||
debug!("Doc block: =====\n{}\n=====", s);
|
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() {
|
} else if !prefix.is_empty() {
|
||||||
write!(w, "<div class='docblock'>{}</div>", prefix)?;
|
write!(w, "<div class='docblock'>{}</div>", prefix)?;
|
||||||
}
|
}
|
||||||
@@ -2146,10 +2147,10 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
|
|||||||
stab_docs = stab_docs,
|
stab_docs = stab_docs,
|
||||||
docs = if cx.render_type == RenderType::Hoedown {
|
docs = if cx.render_type == RenderType::Hoedown {
|
||||||
format!("{}",
|
format!("{}",
|
||||||
shorter(Some(&Markdown(doc_value,
|
shorter(Some(&Markdown(doc_value, &item.links(),
|
||||||
RenderType::Hoedown).to_string())))
|
RenderType::Hoedown).to_string())))
|
||||||
} else {
|
} else {
|
||||||
format!("{}", MarkdownSummaryLine(doc_value))
|
format!("{}", MarkdownSummaryLine(doc_value, &item.links()))
|
||||||
},
|
},
|
||||||
class = myitem.type_(),
|
class = myitem.type_(),
|
||||||
stab = myitem.stability_class().unwrap_or("".to_string()),
|
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, "</span>")?;
|
||||||
write!(w, "</h3>\n")?;
|
write!(w, "</h3>\n")?;
|
||||||
if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) {
|
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 {
|
} else {
|
||||||
// Save the state of USED_ID_MAP so it only gets updated once even
|
// Save the state of USED_ID_MAP so it only gets updated once even
|
||||||
// though we're rendering twice.
|
// 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);
|
let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output);
|
||||||
|
|||||||
Reference in New Issue
Block a user