rust/src/librustdoc/markdown_index_pass.rs

249 lines
6.3 KiB
Rust
Raw Normal View History

//! Build indexes as appropriate for the markdown pass
2012-03-02 17:17:13 -06:00
2012-09-18 18:48:40 -05:00
use doc::ItemUtils;
2012-11-19 20:48:46 -06:00
pub fn mk_pass(+config: config::Config) -> Pass {
2012-03-02 17:17:13 -06:00
{
name: ~"markdown_index",
2012-11-19 20:48:46 -06:00
f: fn~(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
run(srv, doc, config)
}
2012-03-02 17:17:13 -06:00
}
}
fn run(
2012-09-18 18:48:40 -05:00
_srv: astsrv::Srv,
2012-11-19 20:48:46 -06:00
+doc: doc::Doc,
+config: config::Config
2012-09-18 18:48:40 -05:00
) -> doc::Doc {
let fold = fold::Fold({
fold_mod: fold_mod,
2012-09-04 15:29:32 -05:00
fold_nmod: fold_nmod,
.. *fold::default_any_fold(config)
2012-03-02 17:17:13 -06:00
});
2012-11-19 20:48:46 -06:00
fold.fold_doc(&fold, doc)
2012-03-02 17:17:13 -06:00
}
fn fold_mod(
2012-11-19 20:48:46 -06:00
fold: &fold::Fold<config::Config>,
+doc: doc::ModDoc
2012-09-18 18:48:40 -05:00
) -> doc::ModDoc {
2012-03-02 17:17:13 -06:00
let doc = fold::default_any_fold_mod(fold, doc);
2012-09-18 18:48:40 -05:00
doc::ModDoc_({
2012-09-04 15:29:32 -05:00
index: Some(build_mod_index(doc, fold.ctxt)),
.. *doc
})
2012-03-02 17:17:13 -06:00
}
fn fold_nmod(
2012-11-19 20:48:46 -06:00
fold: &fold::Fold<config::Config>,
+doc: doc::NmodDoc
2012-09-18 18:48:40 -05:00
) -> doc::NmodDoc {
let doc = fold::default_any_fold_nmod(fold, doc);
{
2012-09-04 15:29:32 -05:00
index: Some(build_nmod_index(doc, fold.ctxt)),
.. doc
}
}
fn build_mod_index(
2012-11-21 00:36:32 -06:00
+doc: doc::ModDoc,
+config: config::Config
2012-09-18 18:48:40 -05:00
) -> doc::Index {
2012-03-02 17:17:13 -06:00
{
entries: par::map(doc.items, |doc| {
2012-09-28 19:17:20 -05:00
item_to_entry(*doc, config)
})
}
}
fn build_nmod_index(
2012-11-21 00:36:32 -06:00
+doc: doc::NmodDoc,
+config: config::Config
2012-09-18 18:48:40 -05:00
) -> doc::Index {
{
entries: par::map(doc.fns, |doc| {
2012-09-28 19:17:20 -05:00
item_to_entry(doc::FnTag(*doc), config)
})
2012-03-02 17:17:13 -06:00
}
}
fn item_to_entry(
2012-11-21 00:36:32 -06:00
+doc: doc::ItemTag,
+config: config::Config
2012-09-18 18:48:40 -05:00
) -> doc::IndexEntry {
let link = match doc {
2012-09-18 18:48:40 -05:00
doc::ModTag(_) | doc::NmodTag(_)
if config.output_style == config::DocPerMod => {
markdown_writer::make_filename(config, doc::ItemPage(doc)).to_str()
}
2012-08-03 21:59:04 -05:00
_ => {
~"#" + pandoc_header_id(markdown_pass::header_text(doc))
}
};
2012-03-02 17:17:13 -06:00
{
kind: markdown_pass::header_kind(doc),
name: markdown_pass::header_name(doc),
brief: doc.brief(),
link: link
2012-03-02 17:17:13 -06:00
}
}
2012-11-21 00:36:32 -06:00
fn pandoc_header_id(header: &str) -> ~str {
2012-03-02 17:17:13 -06:00
// http://johnmacfarlane.net/pandoc/README.html#headers
let header = remove_formatting(header);
let header = remove_punctuation(header);
let header = replace_with_hyphens(header);
let header = convert_to_lowercase(header);
let header = remove_up_to_first_letter(header);
let header = maybe_use_section_id(header);
2012-08-01 19:30:05 -05:00
return header;
2012-03-02 17:17:13 -06:00
2012-11-21 00:36:32 -06:00
fn remove_formatting(s: &str) -> ~str {
str::replace(s, ~"`", ~"")
2012-03-02 17:17:13 -06:00
}
2012-11-21 00:36:32 -06:00
fn remove_punctuation(s: &str) -> ~str {
let s = str::replace(s, ~"<", ~"");
let s = str::replace(s, ~">", ~"");
let s = str::replace(s, ~"[", ~"");
let s = str::replace(s, ~"]", ~"");
let s = str::replace(s, ~"(", ~"");
let s = str::replace(s, ~")", ~"");
let s = str::replace(s, ~"@~", ~"");
let s = str::replace(s, ~"~", ~"");
let s = str::replace(s, ~"/", ~"");
let s = str::replace(s, ~":", ~"");
let s = str::replace(s, ~"&", ~"");
let s = str::replace(s, ~"^", ~"");
2012-08-01 19:30:05 -05:00
return s;
}
2012-11-21 00:36:32 -06:00
fn replace_with_hyphens(s: &str) -> ~str {
// Collapse sequences of whitespace to a single dash
// XXX: Hacky implementation here that only covers
// one or two spaces.
let s = str::replace(s, ~" ", ~"-");
let s = str::replace(s, ~" ", ~"-");
return s;
2012-03-02 17:17:13 -06:00
}
2012-11-21 00:36:32 -06:00
fn convert_to_lowercase(s: &str) -> ~str { str::to_lower(s) }
fn remove_up_to_first_letter(s: &str) -> ~str { s.to_str() }
fn maybe_use_section_id(s: &str) -> ~str { s.to_str() }
2012-03-02 17:17:13 -06:00
}
#[test]
fn should_remove_punctuation_from_headers() {
assert pandoc_header_id(~"impl foo of bar<A>") == ~"impl-foo-of-bara";
assert pandoc_header_id(~"fn@(~[~A])") == ~"fna";
assert pandoc_header_id(~"impl of num::num for int")
== ~"impl-of-numnum-for-int";
assert pandoc_header_id(~"impl of num::num for int/&")
== ~"impl-of-numnum-for-int";
assert pandoc_header_id(~"impl of num::num for ^int")
== ~"impl-of-numnum-for-int";
assert pandoc_header_id(~"impl for & condvar")
== ~"impl-for-condvar";
}
2012-03-02 17:17:13 -06:00
#[test]
fn should_index_mod_contents() {
let doc = test::mk_doc(
2012-09-18 18:48:40 -05:00
config::DocPerCrate,
~"mod a { } fn b() { }"
);
2012-09-21 21:37:57 -05:00
assert doc.cratemod().index.get().entries[0] == {
kind: ~"Module",
name: ~"a",
2012-08-20 14:23:37 -05:00
brief: None,
link: ~"#module-a"
};
2012-09-21 21:37:57 -05:00
assert doc.cratemod().index.get().entries[1] == {
kind: ~"Function",
name: ~"b",
2012-08-20 14:23:37 -05:00
brief: None,
link: ~"#function-b"
};
}
#[test]
fn should_index_mod_contents_multi_page() {
let doc = test::mk_doc(
2012-09-18 18:48:40 -05:00
config::DocPerMod,
~"mod a { } fn b() { }"
);
2012-09-21 21:37:57 -05:00
assert doc.cratemod().index.get().entries[0] == {
kind: ~"Module",
name: ~"a",
2012-08-20 14:23:37 -05:00
brief: None,
link: ~"a.html"
2012-03-02 17:17:13 -06:00
};
2012-09-21 21:37:57 -05:00
assert doc.cratemod().index.get().entries[1] == {
kind: ~"Function",
name: ~"b",
2012-08-20 14:23:37 -05:00
brief: None,
link: ~"#function-b"
2012-03-02 17:17:13 -06:00
};
}
#[test]
fn should_index_foreign_mod_pages() {
let doc = test::mk_doc(
2012-09-18 18:48:40 -05:00
config::DocPerMod,
~"extern mod a { }"
);
2012-09-21 21:37:57 -05:00
assert doc.cratemod().index.get().entries[0] == {
kind: ~"Foreign module",
name: ~"a",
2012-08-20 14:23:37 -05:00
brief: None,
link: ~"a.html"
};
}
#[test]
fn should_add_brief_desc_to_index() {
let doc = test::mk_doc(
2012-09-18 18:48:40 -05:00
config::DocPerMod,
~"#[doc = \"test\"] mod a { }"
);
2012-09-21 21:37:57 -05:00
assert doc.cratemod().index.get().entries[0].brief
2012-08-20 14:23:37 -05:00
== Some(~"test");
}
#[test]
fn should_index_foreign_mod_contents() {
let doc = test::mk_doc(
2012-09-18 18:48:40 -05:00
config::DocPerCrate,
~"extern mod a { fn b(); }"
);
2012-09-21 21:37:57 -05:00
assert doc.cratemod().nmods()[0].index.get().entries[0] == {
kind: ~"Function",
name: ~"b",
2012-08-20 14:23:37 -05:00
brief: None,
link: ~"#function-b"
};
}
2012-03-02 17:17:13 -06:00
#[cfg(test)]
mod test {
#[legacy_exports];
2012-11-21 00:36:32 -06:00
fn mk_doc(output_style: config::OutputStyle, +source: ~str) -> doc::Doc {
2012-06-30 18:19:07 -05:00
do astsrv::from_str(source) |srv| {
let config = {
2012-09-04 15:29:32 -05:00
output_style: output_style,
.. config::default_config(&Path("whatever"))
};
let doc = extract::from_srv(srv, ~"");
let doc = attr_pass::mk_pass().f(srv, doc);
2012-03-09 20:12:15 -06:00
let doc = desc_to_brief_pass::mk_pass().f(srv, doc);
2012-03-02 17:17:13 -06:00
let doc = path_pass::mk_pass().f(srv, doc);
run(srv, doc, config)
2012-03-02 17:17:13 -06:00
}
}
}