use crate::doc_parts::*;
use crate::print::{LinkAdjuster, terms::*};
use crate::util::md_tools::md_print::*;
use crate::util::syn_tools::*;
use crate::util::*;
use proc_macro2::TokenStream;
use pulldown_cmark::Event;
use quote::quote;
use std::cell::Ref;
use std::iter;
pub(crate) fn print_doc_chunk_mod(chunk_mod: &DocChunkMod) -> TokenStream {
let head_macro = head_macro(chunk_mod);
let body_macro = body_macro(chunk_mod);
let defs_macro = defs_macro(chunk_mod);
let top_macro = top_macro(chunk_mod);
let subs_macro = subs_macro(chunk_mod);
let all_macro = all_macro(chunk_mod);
let sub_mod = sub_mod(chunk_mod);
let contents = quote! {
#head_macro
#body_macro
#defs_macro
#top_macro
#subs_macro
#all_macro
#sub_mod
};
templates::module(chunk_mod.mod_id(), &contents)
}
fn head_macro(chunk_mod: &DocChunkMod) -> TokenStream {
let chunk = &chunk_mod.chunk().borrow();
let events = adjust_links(chunk, chunk.head_events());
let md = MdPrinter::print(events);
let tokens = &syn_tools::text(&md);
templates::doc_macro(&ids::head(), tokens)
}
fn body_macro(chunk_mod: &DocChunkMod) -> TokenStream {
let chunk = &chunk_mod.chunk().borrow();
let events = adjust_links(chunk, chunk.body_events());
let md = MdPrinter::print(events);
let tokens = &syn_tools::text(&md);
templates::doc_macro(&ids::body(), tokens)
}
fn defs_macro(chunk_mod: &DocChunkMod) -> TokenStream {
if !chunk_mod.is_root() {
return quote! {};
}
let chunk = chunk_mod.chunk().borrow();
let mds = chunk.defs().map(|(key, url)| format!("[{key}]: {url}"));
let md = mds.collect::<Vec<_>>().join("\n");
let tokens = &syn_tools::text(&md);
templates::doc_macro(&ids::defs(), tokens)
}
fn subs_macro(chunk_mod: &DocChunkMod) -> TokenStream {
let path = chunk_mod.mod_path();
let chunk = chunk_mod.chunk().borrow();
let chunks = chunk.chunks();
let sub_ids = chunks.filter_map(|x| x.borrow().rs_id().map(ns::id));
let sub_macros = sub_ids.map(|x| paths::sub_all_macro(&x));
let sub_macros_calls = sub_macros.map(|x| quote! { #path::#x!() });
let concat = &templates::concat(sub_macros_calls);
templates::doc_macro(&ids::subs(), concat)
}
fn top_macro(chunk_mod: &DocChunkMod) -> TokenStream {
let path = chunk_mod.mod_path();
let all_macros = [paths::head_macro(), paths::body_macro()].into_iter();
let all_macros_call = all_macros.map(|x| quote! { #path::#x!() });
let concat = &templates::concat(all_macros_call);
templates::doc_macro(&ids::top(), concat)
}
fn all_macro(chunk_mod: &DocChunkMod) -> TokenStream {
let path = chunk_mod.mod_path();
let top_macros = iter::once(paths::top_macro());
let subs_macros = iter::once(paths::subs_macro());
let defs_macros = chunk_mod.is_root().then_some(paths::defs_macro());
let all_macros = top_macros.chain(subs_macros).chain(defs_macros);
let all_macros_calls = all_macros.map(|x| quote! { #path::#x!() });
let concat = &templates::concat(all_macros_calls);
templates::doc_macro(&ids::all(), concat)
}
fn sub_mod(chunk_mod: &DocChunkMod) -> TokenStream {
let path = &ns::path_with(chunk_mod.mod_path(), [&ids::sub()]);
let chunk = chunk_mod.chunk().borrow();
let sub_items = chunk.chunks().map(|x| sub_item_mod(path, &x));
let sub_items_tokens = "e! { #(#sub_items)* };
templates::module(&ids::sub(), sub_items_tokens)
}
fn sub_item_mod(path: &syn::Path, chunk: &DocChunk) -> TokenStream {
assert!(!chunk.borrow().is_root() && chunk.borrow().rs_id().is_some());
let id = &ns::id(chunk.borrow().rs_id().unwrap());
let path = &ns::path_with(path, [id]);
let chunk_mod = DocChunkMod::new_sub(path, chunk);
print_doc_chunk_mod(&chunk_mod)
}
fn adjust_links<'a>(
chunk: &Ref<DocChunkCore<'a>>,
events: impl Iterator<Item = Event<'a>>,
) -> impl Iterator<Item = Event<'a>> {
let mut la = LinkAdjuster::new()
.with_self_item(chunk.self_item().cloned())
.with_copy_guard(chunk.copy_guard().map(str::to_string));
events.map(move |x| la.adjust(&x))
}