Skip to content

Commit c64eff1

Browse files
committed
feat(templs): default api sidebar
1 parent 4c2e51a commit c64eff1

File tree

8 files changed

+202
-36
lines changed

8 files changed

+202
-36
lines changed

crates/rari-doc/src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ pub enum DocError {
9393
MustHaveAtRule,
9494
#[error("Invalid slug for templ/sidebar: {0}")]
9595
InvalidSlugForX(String),
96+
#[error("Invalid group for templ/sidebar: {0}")]
97+
InvalidGroupForX(String),
9698
}
9799

98100
impl<T> From<PoisonError<T>> for DocError {

crates/rari-doc/src/helpers/json_data.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ pub struct GroupData {
3636
pub properties: Vec<String>,
3737
#[serde(default)]
3838
pub events: Vec<String>,
39+
#[serde(default)]
40+
pub tutorial: Vec<String>,
3941
}
4042

4143
pub static JSON_DATA_GROUP: OnceCell<HashMap<String, GroupData>> = OnceCell::new();

crates/rari-doc/src/html/links.rs

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::borrow::Cow;
22

33
use rari_types::fm_types::FeatureStatus;
44
use rari_types::locale::Locale;
5+
use tracing::warn;
56

67
use crate::docs::page::{Page, PageLike};
78
use crate::error::DocError;
@@ -79,39 +80,49 @@ pub fn render_link_via_page(
7980
} else {
8081
Cow::Borrowed(link)
8182
};
82-
let page = RariApi::get_page(&url)?;
83-
let url = page.url();
84-
let content = content.unwrap_or(page.short_title().unwrap_or(page.title()));
85-
render_internal_link(
86-
out,
87-
url,
88-
content,
89-
title,
90-
&LinkModifier {
91-
badges: if with_badges { page.status() } else { &[] },
92-
badge_locale: locale.unwrap_or(page.locale()),
93-
code,
94-
only_en_us: page.locale() != locale.unwrap_or_default(),
95-
},
96-
)?;
97-
} else {
98-
out.push_str("<a href=\"");
99-
let url = link;
100-
let content = html_escape::encode_safe(content.unwrap_or(link));
101-
out.push_str(url);
102-
if let Some(title) = title {
103-
out.push_str("\" title=\"");
104-
out.push_str(title);
105-
}
106-
out.push_str("\">");
107-
if code {
108-
out.push_str("<code>");
109-
}
110-
out.push_str(&content);
111-
if code {
112-
out.push_str("</code>");
83+
match RariApi::get_page(&url) {
84+
Ok(page) => {
85+
let url = page.url();
86+
let content = content.unwrap_or(page.short_title().unwrap_or(page.title()));
87+
return render_internal_link(
88+
out,
89+
url,
90+
content,
91+
title,
92+
&LinkModifier {
93+
badges: if with_badges { page.status() } else { &[] },
94+
badge_locale: locale.unwrap_or(page.locale()),
95+
code,
96+
only_en_us: page.locale() != locale.unwrap_or_default(),
97+
},
98+
);
99+
}
100+
Err(e) => {
101+
warn!("Link via page not found for {url}: {e}",)
102+
}
113103
}
114-
out.push_str("</a>");
115104
}
105+
106+
out.push_str("<a href=\"");
107+
let url = link;
108+
let content = if link.starts_with('/') {
109+
&link[link.rfind('/').unwrap_or(0)..]
110+
} else {
111+
&html_escape::encode_safe(content.unwrap_or(link))
112+
};
113+
out.push_str(url);
114+
if let Some(title) = title {
115+
out.push_str("\" title=\"");
116+
out.push_str(title);
117+
}
118+
out.push_str("\">");
119+
if code {
120+
out.push_str("<code>");
121+
}
122+
out.push_str(content);
123+
if code {
124+
out.push_str("</code>");
125+
}
126+
out.push_str("</a>");
116127
Ok(())
117128
}

crates/rari-doc/src/sidebars/apiref.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub fn sidebar(slug: &str, group: Option<&str>, locale: Locale) -> Result<MetaSi
8686

8787
let mut entries = vec![];
8888

89-
if let Some([ref overview]) = web_api_groups.map(|group| group.overview.as_slice()) {
89+
if let Some([ref overview, ..]) = web_api_groups.map(|group| group.overview.as_slice()) {
9090
entries.push(SidebarMetaEntry {
9191
section: true,
9292
content: SidebarMetaEntryContent::Page(Doc::page_from_slug(
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
use rari_l10n::l10n_json_data;
2+
use rari_types::locale::Locale;
3+
4+
use crate::docs::doc::Doc;
5+
use crate::error::DocError;
6+
use crate::helpers::json_data::json_data_group;
7+
use crate::html::sidebar::{
8+
Details, MetaChildren, MetaSidebar, SidebarMetaEntry, SidebarMetaEntryContent,
9+
};
10+
11+
pub fn sidebar(group: &str, locale: Locale) -> Result<MetaSidebar, DocError> {
12+
let properties_label = l10n_json_data("Common", "Properties", locale)?;
13+
let methods_label = l10n_json_data("Common", "Methods", locale)?;
14+
let events_label = l10n_json_data("Common", "Events", locale)?;
15+
let interfaces_label = l10n_json_data("Common", "Interfaces", locale)?;
16+
let guides_label = l10n_json_data("Common", "Guides", locale)?;
17+
let tutorial_label = l10n_json_data("Common", "Tutorial", locale)?;
18+
19+
let web_api_groups = json_data_group()
20+
.get(group)
21+
.ok_or(DocError::InvalidSlugForX(group.to_string()))?;
22+
23+
let mut entries = vec![];
24+
25+
if let [ref overview, ..] = web_api_groups.overview.as_slice() {
26+
entries.push(SidebarMetaEntry {
27+
section: true,
28+
content: SidebarMetaEntryContent::Page(Doc::page_from_slug(
29+
&format!("Web/API/{}", overview.replace(' ', "_")),
30+
locale,
31+
)?),
32+
..Default::default()
33+
});
34+
}
35+
36+
build_sublist(&mut entries, &web_api_groups.guides, guides_label);
37+
build_sublist(&mut entries, &web_api_groups.tutorial, tutorial_label);
38+
39+
build_interface_list(
40+
&mut entries,
41+
&web_api_groups.interfaces,
42+
interfaces_label,
43+
APILink::from,
44+
);
45+
build_interface_list(
46+
&mut entries,
47+
&web_api_groups.properties,
48+
properties_label,
49+
APILink::from,
50+
);
51+
build_interface_list(
52+
&mut entries,
53+
&web_api_groups.methods,
54+
methods_label,
55+
APILink::from,
56+
);
57+
build_interface_list(
58+
&mut entries,
59+
&web_api_groups.events,
60+
events_label,
61+
APILink::from_event,
62+
);
63+
64+
Ok(MetaSidebar { entries })
65+
}
66+
67+
struct APILink {
68+
title: Option<String>,
69+
link: String,
70+
}
71+
72+
impl APILink {
73+
pub fn from(s: &str) -> Option<Self> {
74+
Some(Self {
75+
title: Some(s.to_string()),
76+
link: format!("/Web/API/{}", s.replace("()", "").replace('.', "/")),
77+
})
78+
}
79+
80+
pub fn from_event(ev: &str) -> Option<Self> {
81+
ev.split_once(": ").map(|(interface, event)| Self {
82+
link: format!("/Web/API/{interface}/{event}_event"),
83+
title: Some(ev.to_string()),
84+
})
85+
}
86+
}
87+
88+
fn build_sublist(entries: &mut Vec<SidebarMetaEntry>, sub_pages: &[String], label: &str) {
89+
if !sub_pages.is_empty() {
90+
entries.push(SidebarMetaEntry {
91+
details: Details::Open,
92+
content: SidebarMetaEntryContent::Link {
93+
link: None,
94+
title: Some(label.to_string()),
95+
},
96+
children: MetaChildren::Children(
97+
sub_pages
98+
.iter()
99+
.map(|url| SidebarMetaEntry {
100+
content: SidebarMetaEntryContent::Link {
101+
title: None,
102+
link: Some(url.strip_prefix("/docs").unwrap_or(url).to_string()),
103+
},
104+
..Default::default()
105+
})
106+
.collect(),
107+
),
108+
..Default::default()
109+
})
110+
}
111+
}
112+
113+
fn build_interface_list(
114+
entries: &mut Vec<SidebarMetaEntry>,
115+
interfaces: &[String],
116+
label: &str,
117+
convert: fn(&str) -> Option<APILink>,
118+
) {
119+
if !interfaces.is_empty() {
120+
entries.push(SidebarMetaEntry {
121+
details: Details::Open,
122+
content: SidebarMetaEntryContent::Link {
123+
link: None,
124+
title: Some(label.to_string()),
125+
},
126+
children: MetaChildren::Children(
127+
interfaces
128+
.iter()
129+
.filter_map(|s| convert(s))
130+
.map(|APILink { link, title }| SidebarMetaEntry {
131+
code: true,
132+
content: SidebarMetaEntryContent::Link {
133+
title,
134+
link: Some(link),
135+
},
136+
..Default::default()
137+
})
138+
.collect(),
139+
),
140+
..Default::default()
141+
})
142+
}
143+
}

crates/rari-doc/src/sidebars/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod apiref;
2+
pub mod default_api_sidebar;
23
pub mod jsref;
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
use rari_templ_func::rari_f;
22

33
use crate::error::DocError;
4-
use crate::sidebars::apiref;
4+
use crate::sidebars::{apiref, default_api_sidebar};
55

66
#[rari_f]
77
pub fn apiref(group: Option<String>) -> Result<String, DocError> {
88
apiref::sidebar(env.slug, group.as_deref(), env.locale)?.render(env.locale)
99
}
10+
11+
#[rari_f]
12+
pub fn default_api_sidebar(group: String) -> Result<String, DocError> {
13+
default_api_sidebar::sidebar(&group, env.locale)?.render(env.locale)
14+
}

crates/rari-doc/src/templ/templs/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ pub fn invoke(
2828
ident: &str,
2929
args: Vec<Option<Arg>>,
3030
) -> Result<(String, bool), DocError> {
31-
let is_sidebar = matches!(ident.to_lowercase().as_str(), "apiref");
32-
let f = match ident.to_lowercase().as_str() {
31+
let name = ident.to_lowercase();
32+
let is_sidebar = matches!(name.as_str(), "apiref" | "defaultapisidebar");
33+
let f = match name.as_str() {
3334
"compat" => compat::compat_any,
3435
"specifications" => specification::specification_any,
3536
"glossary" => glossary::glossary_any,
@@ -74,6 +75,7 @@ pub fn invoke(
7475

7576
// sidebars
7677
"apiref" => apiref::apiref_any,
78+
"defaultapisidebar" => apiref::default_api_sidebar_any,
7779

7880
// ignore
7981
"cssref" | "glossarysidebar" | "jsref" => return Ok(Default::default()),

0 commit comments

Comments
 (0)