# Markdown Viewer Read-only Markdown renderer — fetches a `.md` file by URL (public web or SGApps `fs://`), renders it inline with navigation on in-page links to other `.md` files and a "Go Home" bar. Internally this is the **Code Editor** webapp launched with a chrome-less preset: no sidebar, no top toolbars, no tab bar, light theme, and the markdown tab type pre-selected (not Monaco source — the rendered HTML view). For an **editable** Markdown surface with WYSIWYG, DOCX/ODF import/export, and both source and preview modes, use [Writer](/apps/writer.md) instead. ## Live Demo ## Embed ```html ``` ### Open with a Markdown URL Encode the Markdown URL in base64 and append it as `/url/`: ```js var mdUrl = "https://sgapps.io/webapp-docs/README.md"; var src = "https://sgapps.io/online/webapp/markdown-browser/url/" + btoa(mdUrl); ``` Default (no arg) opens the Code Editor welcome page. ## Navigation Links inside the rendered Markdown behave contextually: - Links to `.md` / `.markdown` files are rewritten and opened in the same viewer (full navigation stack with a "Go Home" button to return to the originally loaded doc). - `http(s)://` and `ftp(s)://` links and in-page anchors (`#section`) open as normal external links (new tab). - Other relative paths open through [xdg-open](https://sgapps.io/online/webapp/xdg-open) — routed to the matching registered app for that mimetype. Relative image / asset URLs are resolved against the current `.md` file's folder. ## API Events Markdown Viewer inherits the full [Code Editor](/apps/code-editor.md) API. The active tab is a markdown-render tab (not a Monaco text buffer), so these behave specifically: - `active-file:codeEditor:value`, `:syntax`, `:markers` → return "No active editor" (no Monaco for this tab type). - `files:open`, `files:list`, `files:active:set`, `files:close:all` → work normally. - `fs:*` (read, write, exists, stats, …) → work normally through the shared fs instance. ### `files:open` -- Open a `.md` File in a New Tab ```js socket.fire("webapp::instance::request", "files:open", "/files/README.md", "markdown", function (err, tabId) { /* ... */ } ); ``` ### `fs:write` + `files:open` -- Render In-Memory Markdown ```js var md = "# Hello\n\nThis Markdown was written from the embedder."; socket.fire("webapp::instance::request", "fs:write", "input://memory/doc.md", md, function (err) { if (err) return console.error(err); socket.fire("webapp::instance::request", "files:open", "input://memory/doc.md", "markdown"); } ); ``` ### `files:list` -- List Open Tabs ```js socket.fire("webapp::instance::request", "files:list", function (err, tabs) { console.log(tabs); } ); ``` ## Window Chrome Controls Fullscreen (hide header + footer): ```js socket.fire("webapp::instance::embed-mode", true); ``` Granular controls — see [Embedding](/embedding.md). ## Supported Mime Types Registered for: `text/x-markdown`, `text/markdown`. Opens from the SGApps window manager when a `.md` is double-clicked in File Manager. Also auto-selected for directory paths matching `/public/documentation/`, `/public/share/*/`, `/apps/*/public/` via the `readme-preview` handler (renders the folder's `README.md` as the entry point). ## Features - Inline Markdown rendering (not Monaco source view) with navigation - Click-through on `.md` / `.markdown` links keeps you inside the viewer - Relative images resolve against the current file's folder - "Go Home" bar on secondary files to return to the first-loaded doc - Default welcome content when no URL is passed - Full inherited `files:*` and `fs:*` API from Code Editor - For **editing**: use [Writer](/apps/writer.md) (WYSIWYG + markdown source + DOCX/ODF import)