Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ OfficeCLI is self-contained. The capabilities below ship inside the binary — *

#### Rendering engine — high-fidelity, built-in

OfficeCLI's keystone: a from-scratch, high-fidelity HTML rendering engine that lets an AI agent *see* the rendered document instead of guessing from the DOM. It covers shapes, charts (trendlines, error bars, waterfall, candlestick, sparklines), equations (OMML → LaTeX, rendered with KaTeX), 3D `.glb` models via Three.js, morph transitions, slide zoom, and shape effects. Per-page PNG screenshots are produced by piping the rendered HTML through a headless browser. Three modes:
OfficeCLI's keystone: a from-scratch, high-fidelity HTML rendering engine that lets an AI agent *see* the rendered document instead of guessing from the DOM. It covers shapes, charts (trendlines, error bars, waterfall, candlestick, sparklines), equations (OMML → LaTeX, rendered with KaTeX), 3D `.glb` models via Three.js, morph transitions, slide zoom, and shape effects. Per-page PNG screenshots are produced by piping the rendered HTML through a headless browser. `diagram --prop render=image` renders with the real mermaid.js in that same browser, caching mermaid.min.js locally on first use (mirror → CDN); set `OFFICECLI_MERMAID_JS=/path/to/mermaid.min.js` to point it at a local copy instead and skip the network entirely (offline / sandboxed hosts). Three modes:

- **`view html`** — standalone HTML file, assets inlined. Open in any browser.
- **`view screenshot`** — per-page PNG, ready for multimodal agents to read.
Expand Down
20 changes: 19 additions & 1 deletion src/officecli/Core/Diagram/MermaidImageRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ namespace OfficeCli.Core.Diagram;
/// <item><b>Chrome-family</b> browser the user already has (via
/// <see cref="HtmlScreenshot"/>): render mermaid.js in a page and screenshot it.
/// Only mermaid.min.js (~3.5 MB) is fetched to a local cache on first use
/// (mirror → CDN); if that fails the page loads mermaid from the CDN live.</item>
/// (mirror → CDN); if that fails the page loads mermaid from the CDN live.
/// <c>OFFICECLI_MERMAID_JS</c> points at a local mermaid.min.js and skips the
/// network entirely, for offline / sandboxed hosts.</item>
/// <item>otherwise the caller falls back to the native synthesizer
/// (<see cref="DiagramCompiler"/>) — zero dependencies, fully editable shapes.</item>
/// </list>
Expand Down Expand Up @@ -180,6 +182,18 @@ private static bool SourceNeedsElk(string source)
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".officecli", "cache");
private static string CachedJsPath => Path.Combine(CacheDir, $"mermaid-{MermaidVersion}.min.js");

/// <summary>Explicit local mermaid.min.js override for offline / sandboxed hosts
/// that cannot reach the mirror or the CDN. Wins over the cache and skips the
/// download + refresh path entirely.</summary>
private static string? MermaidJsOverride
{
get
{
var p = Environment.GetEnvironmentVariable("OFFICECLI_MERMAID_JS");
return !string.IsNullOrWhiteSpace(p) && File.Exists(p) ? p : null;
}
}

/// <summary>True when any image backend is available: mmdc, or a chrome-family browser.</summary>
public static bool IsAvailable() => TryLocateMmdc(out _) || HtmlScreenshot.HasChromeFamily();

Expand All @@ -195,6 +209,7 @@ public static void RefreshCacheIfPresent()
{
try
{
if (MermaidJsOverride != null) return; // explicit local asset — never touch the network
if (!File.Exists(CachedJsPath)) return; // refresh only what the user actually uses
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(20) };
using var req = new HttpRequestMessage(HttpMethod.Get, MirrorUrl);
Expand Down Expand Up @@ -396,6 +411,9 @@ private static string RenderViaChrome(string mermaid, string? background)
/// &lt;script src&gt; (a <c>file://</c> for a cached/downloaded copy, else the CDN).</summary>
private static string ResolveMermaidJsRef()
{
if (MermaidJsOverride is { } overridePath)
return new Uri(Path.GetFullPath(overridePath)).AbsoluteUri;
Comment on lines +414 to +415

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor the local override in the styled ESM path

When a diagram specifies theme, layout, or look, RenderViaChrome selects BuildHtmlEsm and never calls this resolver; that path still imports MermaidEsmUrl and, for ELK, ElkEsmUrl from jsDelivr. Consequently, on the offline or sandboxed hosts this override targets, styled render=image requests still fail—or auto mode falls back to native rendering and loses the requested styling—despite OFFICECLI_MERMAID_JS being set.

Useful? React with 👍 / 👎.


try
{
if (File.Exists(CachedJsPath) && new FileInfo(CachedJsPath).Length > 500_000)
Expand Down