chore: documentation added and adapted to RuDS

This commit is contained in:
2026-07-20 13:02:34 +02:00
parent c82b790b82
commit 7887d02e0b
15 changed files with 507 additions and 20 deletions

View File

@@ -969,6 +969,8 @@ pub struct BdsApp {
duplicates_state: DuplicatesState,
guide_documentation: DocumentationState,
api_documentation: DocumentationState,
cli_documentation: DocumentationState,
mcp_documentation: DocumentationState,
metadata_diff_state: MetadataDiffState,
menu_editor_state: MenuEditorState,
translation_validation_state: crate::views::translation_validation::TranslationValidationState,
@@ -1144,6 +1146,8 @@ impl BdsApp {
duplicates_state: DuplicatesState::default(),
guide_documentation: DocumentationState::new(DocumentationKind::Guide),
api_documentation: DocumentationState::new(DocumentationKind::Api),
cli_documentation: DocumentationState::new(DocumentationKind::Cli),
mcp_documentation: DocumentationState::new(DocumentationKind::Mcp),
metadata_diff_state: MetadataDiffState::default(),
menu_editor_state: MenuEditorState::default(),
translation_validation_state: Default::default(),
@@ -1232,6 +1236,8 @@ impl BdsApp {
duplicates_state: DuplicatesState::default(),
guide_documentation: DocumentationState::new(DocumentationKind::Guide),
api_documentation: DocumentationState::new(DocumentationKind::Api),
cli_documentation: DocumentationState::new(DocumentationKind::Cli),
mcp_documentation: DocumentationState::new(DocumentationKind::Mcp),
metadata_diff_state: MetadataDiffState::default(),
menu_editor_state: MenuEditorState::default(),
translation_validation_state: Default::default(),
@@ -3127,6 +3133,8 @@ impl BdsApp {
match kind {
DocumentationKind::Guide => &self.guide_documentation,
DocumentationKind::Api => &self.api_documentation,
DocumentationKind::Cli => &self.cli_documentation,
DocumentationKind::Mcp => &self.mcp_documentation,
}
}
@@ -3134,6 +3142,8 @@ impl BdsApp {
match kind {
DocumentationKind::Guide => &mut self.guide_documentation,
DocumentationKind::Api => &mut self.api_documentation,
DocumentationKind::Cli => &mut self.cli_documentation,
DocumentationKind::Mcp => &mut self.mcp_documentation,
}
}
@@ -3144,6 +3154,8 @@ impl BdsApp {
tokio::task::spawn_blocking(move || match kind {
DocumentationKind::Guide => crate::views::documentation::load_user_guide(),
DocumentationKind::Api => crate::views::documentation::load_api_document(),
DocumentationKind::Cli => crate::views::documentation::load_cli_guide(),
DocumentationKind::Mcp => crate::views::documentation::load_mcp_guide(),
})
.await
.unwrap_or_else(|error| DocumentLoad::Malformed {
@@ -3160,6 +3172,8 @@ impl BdsApp {
for (tab_type, kind) in [
(TabType::Documentation, DocumentationKind::Guide),
(TabType::ApiDocumentation, DocumentationKind::Api),
(TabType::CliDocumentation, DocumentationKind::Cli),
(TabType::McpDocumentation, DocumentationKind::Mcp),
] {
if !self.tabs.iter().any(|tab| tab.tab_type == tab_type) {
continue;
@@ -3413,6 +3427,8 @@ impl BdsApp {
&self.duplicates_state,
&self.guide_documentation,
&self.api_documentation,
&self.cli_documentation,
&self.mcp_documentation,
&self.metadata_diff_state,
&self.menu_editor_state,
&self.translation_validation_state,
@@ -4349,6 +4365,14 @@ impl BdsApp {
self.open_singleton_tab(TabType::ApiDocumentation, "tabBar.apiDocumentation");
self.start_documentation_load(DocumentationKind::Api)
}
MenuAction::OpenCliDocumentation => {
self.open_singleton_tab(TabType::CliDocumentation, "tabBar.cliDocumentation");
self.start_documentation_load(DocumentationKind::Cli)
}
MenuAction::OpenMcpDocumentation => {
self.open_singleton_tab(TabType::McpDocumentation, "tabBar.mcpDocumentation");
self.start_documentation_load(DocumentationKind::Mcp)
}
MenuAction::ViewOnGitHub => {
let _ = open::that("https://github.com/nickarumern/bds");
Task::none()
@@ -9164,6 +9188,34 @@ mod tests {
);
}
#[test]
fn help_menu_opens_cli_and_mcp_documentation_tabs() {
let (db, project, temp) = setup();
let mut app = BdsApp::new_for_tests(db, project, temp.path().to_path_buf());
let _ = app.dispatch_menu_action(MenuAction::OpenCliDocumentation);
assert!(
app.tabs
.iter()
.any(|tab| tab.tab_type == TabType::CliDocumentation)
);
assert_eq!(
app.cli_documentation.status,
crate::views::documentation::DocumentStatus::Loading
);
let _ = app.dispatch_menu_action(MenuAction::OpenMcpDocumentation);
assert!(
app.tabs
.iter()
.any(|tab| tab.tab_type == TabType::McpDocumentation)
);
assert_eq!(
app.mcp_documentation.status,
crate::views::documentation::DocumentStatus::Loading
);
}
#[test]
fn project_switch_keeps_global_documentation_loaded() {
let (db, project, temp) = setup();

View File

@@ -57,6 +57,8 @@ pub enum MenuAction {
About,
OpenDocumentation,
OpenApiDocumentation,
OpenCliDocumentation,
OpenMcpDocumentation,
ViewOnGitHub,
ReportIssue,
}
@@ -101,6 +103,8 @@ impl MenuAction {
MenuAction::About,
MenuAction::OpenDocumentation,
MenuAction::OpenApiDocumentation,
MenuAction::OpenCliDocumentation,
MenuAction::OpenMcpDocumentation,
MenuAction::ViewOnGitHub,
MenuAction::ReportIssue,
];
@@ -190,6 +194,8 @@ impl MenuAction {
Self::About => "menu.item.about",
Self::OpenDocumentation => "menu.item.openDocumentation",
Self::OpenApiDocumentation => "menu.item.openApiDocumentation",
Self::OpenCliDocumentation => "menu.item.openCliDocumentation",
Self::OpenMcpDocumentation => "menu.item.openMcpDocumentation",
Self::ViewOnGitHub => "menu.item.viewOnGitHub",
Self::ReportIssue => "menu.item.reportIssue",
}
@@ -562,6 +568,18 @@ pub fn build_menu_bar(locale: UiLocale) -> (Menu, MenuRegistry) {
locale,
None,
));
let _ = help_menu.append(&item(
&mut reg,
MenuAction::OpenCliDocumentation,
locale,
None,
));
let _ = help_menu.append(&item(
&mut reg,
MenuAction::OpenMcpDocumentation,
locale,
None,
));
let _ = help_menu.append(&item(&mut reg, MenuAction::ViewOnGitHub, locale, None));
let _ = help_menu.append(&item(&mut reg, MenuAction::ReportIssue, locale, None));

View File

@@ -17,6 +17,8 @@ pub enum TabType {
Templates,
Documentation,
ApiDocumentation,
CliDocumentation,
McpDocumentation,
SiteValidation,
TranslationValidation,
FindDuplicates,
@@ -25,9 +27,9 @@ pub enum TabType {
impl TabType {
/// Singleton tool tabs per tabs.allium: always one instance, id = type name.
///
/// Singleton types (10): settings, tags, style, menu_editor,
/// documentation, api_documentation, metadata_diff, site_validation,
/// translation_validation, find_duplicates.
/// Singleton types (12): settings, tags, style, menu_editor,
/// documentation, api_documentation, cli_documentation, mcp_documentation,
/// metadata_diff, site_validation, translation_validation, find_duplicates.
///
/// Entity types (keyed by external ID): post, media, scripts (keyed),
/// templates (keyed), chat, import, git_diff.
@@ -41,6 +43,8 @@ impl TabType {
| Self::MetadataDiff
| Self::Documentation
| Self::ApiDocumentation
| Self::CliDocumentation
| Self::McpDocumentation
| Self::SiteValidation
| Self::TranslationValidation
| Self::FindDuplicates
@@ -57,6 +61,8 @@ impl TabType {
Self::MetadataDiff => "metadata_diff",
Self::Documentation => "documentation",
Self::ApiDocumentation => "api_documentation",
Self::CliDocumentation => "cli_documentation",
Self::McpDocumentation => "mcp_documentation",
Self::SiteValidation => "site_validation",
Self::TranslationValidation => "translation_validation",
Self::FindDuplicates => "find_duplicates",
@@ -76,6 +82,8 @@ impl TabType {
Self::MetadataDiff => Some("tabBar.metadataDiff"),
Self::Documentation => Some("tabBar.documentation"),
Self::ApiDocumentation => Some("tabBar.apiDocumentation"),
Self::CliDocumentation => Some("tabBar.cliDocumentation"),
Self::McpDocumentation => Some("tabBar.mcpDocumentation"),
Self::SiteValidation => Some("tabBar.siteValidation"),
Self::TranslationValidation => Some("tabBar.translationValidation"),
Self::FindDuplicates => Some("tabBar.findDuplicates"),

View File

@@ -15,6 +15,8 @@ use crate::i18n::t;
const API_REFERENCE: &str = include_str!("../../../../docs/scripting/API_REFERENCE.md");
const API_TYPES: &str = include_str!("../../../../docs/scripting/TYPES.md");
const USER_GUIDE: &str = include_str!("../../../../DOCUMENTATION.md");
const CLI_GUIDE: &str = include_str!("../../../../CLI.md");
const MCP_GUIDE: &str = include_str!("../../../../MCP.md");
const UTILITY_EXAMPLE: &str = include_str!("../../../../docs/scripting/examples/utility.lua");
const MACRO_EXAMPLE: &str = include_str!("../../../../docs/scripting/examples/macro.lua");
const TRANSFORM_EXAMPLE: &str = include_str!("../../../../docs/scripting/examples/transform.lua");
@@ -24,6 +26,8 @@ pub const API_DOCUMENTATION_URL: &str = "https://ruds.invalid/api-documentation"
pub enum DocumentationKind {
Guide,
Api,
Cli,
Mcp,
}
#[derive(Debug, Clone)]
@@ -136,6 +140,8 @@ pub fn scroll_id(kind: DocumentationKind) -> scrollable::Id {
scrollable::Id::new(match kind {
DocumentationKind::Guide => "user-documentation",
DocumentationKind::Api => "api-documentation",
DocumentationKind::Cli => "cli-documentation",
DocumentationKind::Mcp => "mcp-documentation",
})
}
@@ -143,10 +149,14 @@ pub fn view(state: &DocumentationState, locale: UiLocale) -> Element<'_, Message
let title_key = match state.kind {
DocumentationKind::Guide => "documentation.title",
DocumentationKind::Api => "documentation.apiTitle",
DocumentationKind::Cli => "documentation.cliTitle",
DocumentationKind::Mcp => "documentation.mcpTitle",
};
let subtitle_key = match state.kind {
DocumentationKind::Guide => "documentation.subtitle",
DocumentationKind::Api => "documentation.apiSubtitle",
DocumentationKind::Cli => "documentation.cliSubtitle",
DocumentationKind::Mcp => "documentation.mcpSubtitle",
};
let toolbar = inputs::toolbar(
vec![
@@ -244,10 +254,21 @@ fn table_row<'a>(values: &'a [String], header: bool) -> Element<'a, Message> {
}
pub fn load_user_guide() -> DocumentLoad {
let path = user_guide_path();
match load_document_file(&path) {
load_embedded_document(&user_guide_path(), USER_GUIDE)
}
pub fn load_cli_guide() -> DocumentLoad {
load_embedded_document(&root_document_path("CLI.md"), CLI_GUIDE)
}
pub fn load_mcp_guide() -> DocumentLoad {
load_embedded_document(&root_document_path("MCP.md"), MCP_GUIDE)
}
fn load_embedded_document(path: &Path, embedded: &str) -> DocumentLoad {
match load_document_file(path) {
DocumentLoad::Missing { signature } => DocumentLoad::Ready {
source: USER_GUIDE.to_string(),
source: embedded.to_string(),
signature,
},
load => load,
@@ -308,6 +329,8 @@ pub fn load_api_document() -> DocumentLoad {
pub fn current_signature(kind: DocumentationKind) -> u64 {
match kind {
DocumentationKind::Guide => file_signature(&user_guide_path()),
DocumentationKind::Cli => file_signature(&root_document_path("CLI.md")),
DocumentationKind::Mcp => file_signature(&root_document_path("MCP.md")),
DocumentationKind::Api => {
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../docs/scripting");
paths_signature(
@@ -325,7 +348,11 @@ pub fn current_signature(kind: DocumentationKind) -> u64 {
}
fn user_guide_path() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("../../DOCUMENTATION.md")
root_document_path("DOCUMENTATION.md")
}
fn root_document_path(name: &str) -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("../..").join(name)
}
pub fn parse_document(source: &str) -> ParsedDocument {

View File

@@ -134,6 +134,8 @@ pub fn view<'a>(
duplicates_state: &'a DuplicatesState,
guide_documentation: &'a DocumentationState,
api_documentation: &'a DocumentationState,
cli_documentation: &'a DocumentationState,
mcp_documentation: &'a DocumentationState,
metadata_diff_state: &'a MetadataDiffState,
menu_editor_state: &'a MenuEditorState,
translation_validation_state: &'a TranslationValidationState,
@@ -168,6 +170,8 @@ pub fn view<'a>(
duplicates_state,
guide_documentation,
api_documentation,
cli_documentation,
mcp_documentation,
metadata_diff_state,
menu_editor_state,
translation_validation_state,
@@ -414,6 +418,8 @@ fn route_content_area<'a>(
duplicates_state: &'a DuplicatesState,
guide_documentation: &'a DocumentationState,
api_documentation: &'a DocumentationState,
cli_documentation: &'a DocumentationState,
mcp_documentation: &'a DocumentationState,
metadata_diff_state: &'a MetadataDiffState,
menu_editor_state: &'a MenuEditorState,
translation_validation_state: &'a TranslationValidationState,
@@ -507,6 +513,8 @@ fn route_content_area<'a>(
ContentRoute::FindDuplicates => duplicates::view(duplicates_state, locale),
ContentRoute::Documentation => documentation::view(guide_documentation, locale),
ContentRoute::ApiDocumentation => documentation::view(api_documentation, locale),
ContentRoute::CliDocumentation => documentation::view(cli_documentation, locale),
ContentRoute::McpDocumentation => documentation::view(mcp_documentation, locale),
ContentRoute::MetadataDiff => metadata_diff::view(metadata_diff_state, locale),
ContentRoute::MenuEditor => menu_editor::view(menu_editor_state, locale),
ContentRoute::TranslationValidation => {
@@ -546,6 +554,8 @@ enum ContentRoute<'a> {
FindDuplicates,
Documentation,
ApiDocumentation,
CliDocumentation,
McpDocumentation,
MetadataDiff,
MenuEditor,
TranslationValidation,
@@ -638,6 +648,8 @@ fn route_kind<'a>(
TabType::FindDuplicates => ContentRoute::FindDuplicates,
TabType::Documentation => ContentRoute::Documentation,
TabType::ApiDocumentation => ContentRoute::ApiDocumentation,
TabType::CliDocumentation => ContentRoute::CliDocumentation,
TabType::McpDocumentation => ContentRoute::McpDocumentation,
TabType::MenuEditor => ContentRoute::MenuEditor,
TabType::Style => ContentRoute::Placeholder(&tab.title),
TabType::TranslationValidation => ContentRoute::TranslationValidation,