forc_doc/render/item/
components.rs1use crate::{
3 doc::module::ModuleInfo,
4 render::{
5 item::context::ItemContext,
6 search::generate_searchbar,
7 sidebar::{Sidebar, SidebarNav},
8 DocStyle, Renderable, IDENTITY,
9 },
10 RenderPlan, ASSETS_DIR_NAME,
11};
12use anyhow::Result;
13use horrorshow::{box_html, Raw, RenderBox};
14
15use sway_types::BaseIdent;
16
17use super::documentable_type::DocumentableType;
18
19#[derive(Clone, Debug)]
22pub struct ItemHeader {
23 pub module_info: ModuleInfo,
24 pub friendly_name: &'static str,
25 pub item_name: BaseIdent,
26}
27impl Renderable for ItemHeader {
28 fn render(self, _render_plan: RenderPlan) -> Result<Box<dyn RenderBox>> {
30 let ItemHeader {
31 module_info,
32 friendly_name,
33 item_name,
34 } = self;
35
36 let favicon =
37 module_info.to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/sway-logo.svg"));
38 let normalize =
39 module_info.to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/normalize.css"));
40 let swaydoc =
41 module_info.to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/swaydoc.css"));
42 let ayu = module_info.to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/ayu.css"));
43 let ayu_hjs =
44 module_info.to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/ayu.min.css"));
45
46 Ok(box_html! {
47 head {
48 meta(charset="utf-8");
49 meta(name="viewport", content="width=device-width, initial-scale=1.0");
50 meta(name="generator", content="swaydoc");
51 meta(
52 name="description",
53 content=format!(
54 "API documentation for the Sway `{}` {} in `{}`.",
55 item_name.as_str(), friendly_name, module_info.location(),
56 )
57 );
58 meta(name="keywords", content=format!("sway, swaylang, sway-lang, {}", item_name.as_str()));
59 link(rel="icon", href=favicon);
60 title: format!("{} in {} - Sway", item_name.as_str(), module_info.location());
61 link(rel="stylesheet", type="text/css", href=normalize);
62 link(rel="stylesheet", type="text/css", href=swaydoc, id="mainThemeStyle");
63 link(rel="stylesheet", type="text/css", href=ayu);
64 link(rel="stylesheet", href=ayu_hjs);
65 }
67 })
68 }
69}
70
71#[derive(Clone, Debug)]
75pub struct ItemBody {
76 pub module_info: ModuleInfo,
77 pub ty: DocumentableType,
78 pub item_name: BaseIdent,
82 pub code_str: String,
83 pub attrs_opt: Option<String>,
84 pub item_context: ItemContext,
85}
86impl SidebarNav for ItemBody {
87 fn sidebar(&self) -> Sidebar {
88 let style = DocStyle::Item {
89 title: Some(self.ty.as_block_title()),
90 name: Some(self.item_name.clone()),
91 };
92 Sidebar::new(
93 None,
94 style,
95 self.module_info.clone(),
96 self.item_context.to_doclinks(),
97 )
98 }
99}
100impl Renderable for ItemBody {
101 fn render(self, render_plan: RenderPlan) -> Result<Box<dyn RenderBox>> {
103 let sidebar = self.sidebar();
104 let ItemBody {
105 module_info,
106 ty,
107 item_name,
108 code_str,
109 attrs_opt,
110 item_context,
111 } = self;
112
113 let doc_name = ty.doc_name().to_string();
114 let block_title = ty.as_block_title();
115 let sidebar = sidebar.render(render_plan.clone())?;
116 let item_context = (item_context.context_opt.is_some()
117 || item_context.impl_traits.is_some())
118 .then(|| -> Result<Box<dyn RenderBox>> { item_context.render(render_plan.clone()) });
119 let sway_hjs =
120 module_info.to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/highlight.js"));
121 let rendered_module_anchors = module_info.get_anchors()?;
122
123 Ok(box_html! {
124 body(class=format!("swaydoc {doc_name}")) {
125 : sidebar;
126 main {
128 div(class="width-limiter") {
129 : generate_searchbar(&module_info);
130 section(id="main-content", class="content") {
131 div(class="main-heading") {
132 h1(class="fqn") {
133 span(class="in-band") {
134 : format!("{} ", block_title.item_title_str());
135 @ for anchor in rendered_module_anchors {
136 : Raw(anchor);
137 }
138 a(class=&doc_name, href=IDENTITY) {
139 : item_name.as_str();
140 }
141 }
142 }
143 }
144 div(class="docblock item-decl") {
145 pre(class=format!("sway {}", &doc_name)) {
146 code { : code_str; }
147 }
148 }
149 @ if attrs_opt.is_some() {
150 details(class="swaydoc-toggle top-doc", open) {
152 summary(class="hideme") {
153 span { : "Expand description" }
154 }
155 div(class="docblock") {
157 : Raw(attrs_opt.unwrap())
158 }
159 }
160 }
161 @ if item_context.is_some() {
162 : item_context.unwrap();
163 }
164 }
165 section(id="search", class="search-results");
166 }
167 }
168 script(src=sway_hjs);
169 script {
170 : "hljs.highlightAll();";
171 }
172 }
173 })
174 }
175}