diff --git a/crates/rm-handlers/src/common.rs b/crates/rm-handlers/src/common.rs index 8f1a7b8..07b5b93 100644 --- a/crates/rm-handlers/src/common.rs +++ b/crates/rm-handlers/src/common.rs @@ -96,10 +96,29 @@ fn hex_nibble(n: u8) -> char { } } -/// Wrap a fragment in a minimal HTML5 document. G1 (Plan §5 GUI -/// chrome) will replace this with the master `base.askama` template -/// — at that point this fn deletes and every handler uses -/// `askama_axum::Template` directly. +/// Redmine's global `#top-menu` — the persistent bar of cross-app links +/// rendered on every page. The link set is fixed, so it's a `const` the +/// formatter splices in verbatim (no per-request allocation beyond the +/// outer `format!`). Mirrors Redmine's top menu shape (Home + the global +/// resource lists); the `id`/`class` hooks match Redmine so G1's +/// stylesheet drops straight in over this skeleton. +const TOP_MENU: &str = concat!( + r#"
"#, +); + +/// Wrap a fragment in the **master-layout skeleton** — an HTML5 document +/// carrying Redmine's persistent chrome: the global `#top-menu` nav, the +/// `#header` app title, and a `#main` > `#content` wrapper the fragment +/// lands in. G1 (Plan §5 GUI chrome) swaps this Rust-built shell for the +/// real `base.askama` master template + a stylesheet; the markup shape +/// (ids/classes) is already Redmine-compatible so that swap is cosmetic. /// /// The `title` parameter is **HTML-escaped** — handlers pass /// user-controlled strings (issue subjects, project names) and the @@ -109,18 +128,49 @@ fn hex_nibble(n: u8) -> char { /// /// `body` is treated as already-rendered HTML — askama-emitted by /// the kit's `render_list` / `render_detail`, which run their own -/// `escape = "html"` on data-derived strings. +/// `escape = "html"` on data-derived strings — and the handler-built +/// chrome (`render_action_bar`, the filter/sort/pagination strips), +/// which escape their own user-derived inputs. #[must_use] pub fn wrap_in_doc(title: &str, body: &str) -> String { let escaped_title = html_escape(title); format!( "\n\n\ \ + \