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
48 changes: 48 additions & 0 deletions docs/MANAGED-FORK.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Managed fork workflow

This is a **managed fork** of `nicobailon/visual-explainer`. It carries local
customizations (a standard self-contained favicon, house-style notes) on top of
upstream, and stays updatable.

## Philosophy: control over automatic

Updates are **on-demand, not automatic**. Nothing pulls upstream behind your
back — so your local modifications and pinned behavior are never disturbed by a
surprise merge. When you *do* want to update, it's one command, and a pi agent
resolves any conflicts with full repository context.

If a session is already current, everything just loads normally with zero work.

## Remotes

| Remote | Points at | Role |
|------------|------------------------------------|------------------------------|
| `origin` | `zereraz/visual-explainer` | your fork (your commits) |
| `upstream` | `nicobailon/visual-explainer` | the original project |

## Updating

From this clone (`~/Code/Zereraz/visual-explainer`):

```bash
bash scripts/update-fork.sh --check # status only; never modifies
bash scripts/update-fork.sh --apply # fetch + merge upstream + push + pi update
# if conflicts (exit 20): resolve files, then:
bash scripts/update-fork.sh --continue
```

Or, inside pi, just run the command (loaded with this plugin):

```
/update-visual-explainer
```

The command checks first, applies if behind, and if a merge conflict occurs the
agent resolves it — **keeping both** upstream's new behavior and our additive
customizations — then commits, pushes, and refreshes the install.

## Making your own changes

Commit directly on `main` (small tweaks) or via a feature branch + PR to your
own fork. Because our changes are additive, upstream merges are usually clean.
`scripts/update-fork.sh` verifies the favicon customizations survived each update.
24 changes: 24 additions & 0 deletions plugins/visual-explainer/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ Generate self-contained HTML pages that explain systems, code changes, plans, da
- Write files to `~/.agent/diagrams/` or the explicit eval output path. Use descriptive filenames.
- Open generated pages in the browser when running normally. In Pi package installs, use `visual_explainer` with `prepare` for planning/context and `render` only after the complete HTML document exists.
- The final page must be a complete self-contained HTML document, including embedded CSS and any needed JS.
- Always include the standard self-contained data-URI favicon immediately after `</title>` (see "Favicon" below). Never leave a page without a favicon.

## Favicon

Every generated page must include this exact self-contained data-URI favicon, placed immediately after the `</title>` tag. It needs no external file and is a small node-graph glyph that matches the dark/accent palette:

```html
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iNyIgZmlsbD0iIzBmMTcyOSIvPjxjaXJjbGUgY3g9IjkiIGN5PSIxMC41IiByPSIzIiBmaWxsPSIjZDRhNzNhIi8+PGNpcmNsZSBjeD0iMjMiIGN5PSIxMC41IiByPSIzIiBmaWxsPSIjNjBhNWZhIi8+PGNpcmNsZSBjeD0iMTYiIGN5PSIyMi41IiByPSIzIiBmaWxsPSIjNGFkZTgwIi8+PHBhdGggZD0iTTkgMTAuNSBMMTYgMjIuNSBMMjMgMTAuNSIgc3Ryb2tlPSIjZDRhNzNhIiBzdHJva2Utd2lkdGg9IjEuNyIgZmlsbD0ibm9uZSIgb3BhY2l0eT0iMC43NSIvPjwvc3ZnPg==">
```

If math is rendered with KaTeX, escape `<` as `&lt;` inside `$$...$$` (e.g. `y_{&lt;t}`); a bare `<` makes the HTML parser truncate the formula.

## Reference routing

Expand Down Expand Up @@ -83,6 +94,16 @@ Use slides only when explicitly requested or when a command asks for slides. Sli
- Do not drop content to fit a fixed slide count. Add slides instead.
- Use the 10 slide types from `slide-patterns.md`: Title, Section Divider, Content, Split, Diagram, Dashboard, Table, Code, Quote, Full-Bleed.

## Reader-first defaults (pages are made to be read and re-read)

The primary use is a reader consuming the page, often over multiple sittings. Build for that:

- **Navigation**: ship the upgraded `SlideEngine` from `slide-deck.html` — it adds deep-link hashes (`#slide-7`), resume-where-you-left-off (localStorage), reading percent in the counter, an outline overlay (press `O`), and a keyboard help panel (press `?`). Don't ship a stripped engine.
- **Comprehension**: open each section with its one-line takeaway, then expand (TL;DR-first). End a multi-section page with a short "what to remember" recap.
- **Glossary**: wrap domain jargon in `<abbr title="one-line definition">term</abbr>` so a reader can hover/tap for meaning without leaving the page.
- **Don't gate content on motion**: every slide must be fully readable even if its animation never plays; animations enhance, never reveal essential text.
- **Accessibility**: don't rely on color alone (pair with shape/label); respect `prefers-reduced-motion`; keep body text ≥ 16px with generous line-height; ensure keyboard nav reaches everything.

## Optional generated images

If `surf` is available, generated images may be embedded as base64 for hero banners, conceptual illustrations, or educational visuals. Skip images for data-heavy, structural, or Mermaid/CSS-suitable content. Pages must stand on CSS, typography, and diagrams without images.
Expand All @@ -92,6 +113,9 @@ If `surf` is available, generated images may be embedded as base64 for hero bann
Before delivery, verify:

- complete HTML document;
- standard favicon `<link rel="icon">` present immediately after `</title>`;
- decks use the upgraded SlideEngine (outline `O`, help `?`, deep-link + resume, reading %);
- each slide readable with animations disabled; no content depends on motion;
- output written to the requested path;
- no console errors when opened;
- no horizontal overflow at normal desktop width;
Expand Down
28 changes: 28 additions & 0 deletions plugins/visual-explainer/commands/update-visual-explainer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: update-visual-explainer
description: Sync this visual-explainer fork with upstream, preserving local customizations; an agent resolves any merge conflicts.
---

Update the managed `visual-explainer` fork. This is **on-demand** — only run because the user asked.

Managed clone location (try in order; use the first that exists):
- `~/Code/Zereraz/visual-explainer`
- the installed package dir: `~/.pi/agent/git/github.com/zereraz/visual-explainer`

Steps:

1. **Check first.** Run `bash scripts/update-fork.sh --check` from the managed clone.
- Exit `0` → already up to date. Tell the user "already current (fork is N commits ahead with your customizations)" and stop.
- Exit `10` → behind upstream; show the listed upstream commits, then continue.

2. **Apply.** Run `bash scripts/update-fork.sh --apply`.
- Exit `0` → clean merge, pushed to the fork, and `pi update` refreshed the install. Report what upstream commits were merged and confirm the local customizations (favicon / house-style) survived. Done.
- Exit `20` → **merge conflict**. Do NOT abandon. Resolve it:
a. Read each conflicted file (`git diff --name-only --diff-filter=U`).
b. For each conflict, **keep the intent of BOTH sides**: upstream's new behavior AND our customizations (the favicon injection in `extension.ts`, favicon lines in `templates/*.html` and `SKILL.md`, the KaTeX `&lt;` note). Our changes are additive — prefer integrating, not discarding.
c. After resolving every file, run `bash scripts/update-fork.sh --continue` to commit, push, and reinstall.
- Exit `2` → precondition failure (dirty tree / wrong branch). Read the message, fix it (commit/stash local work, or `git checkout main`), then retry.

3. **Verify** after success: confirm `grep -c ensureFavicon plugins/visual-explainer/extension.ts` is non-zero and the 4 templates still contain `rel="icon"`. If a customization was lost in the merge, re-apply it and amend.

Report concisely: what changed upstream, whether conflicts occurred, how they were resolved, and that customizations are intact. $@
39 changes: 38 additions & 1 deletion plugins/visual-explainer/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,41 @@ function outputFilename(input: string) {
return /\.html?$/i.test(raw) ? raw : `${raw}.html`;
}

const STANDARD_FAVICON =
'<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iNyIgZmlsbD0iIzBmMTcyOSIvPjxjaXJjbGUgY3g9IjkiIGN5PSIxMC41IiByPSIzIiBmaWxsPSIjZDRhNzNhIi8+PGNpcmNsZSBjeD0iMjMiIGN5PSIxMC41IiByPSIzIiBmaWxsPSIjNjBhNWZhIi8+PGNpcmNsZSBjeD0iMTYiIGN5PSIyMi41IiByPSIzIiBmaWxsPSIjNGFkZTgwIi8+PHBhdGggZD0iTTkgMTAuNSBMMTYgMjIuNSBMMjMgMTAuNSIgc3Ryb2tlPSIjZDRhNzNhIiBzdHJva2Utd2lkdGg9IjEuNyIgZmlsbD0ibm9uZSIgb3BhY2l0eT0iMC43NSIvPjwvc3ZnPg==">';

// Guarantees the house-style favicon is present, regardless of what the agent emitted.
function ensureFavicon(html: string): string {
if (/<link\b[^>]*rel\s*=\s*["']?(?:shortcut\s+)?icon/i.test(html)) return html;
if (/<\/title>/i.test(html)) return html.replace(/<\/title>/i, `</title>\n${STANDARD_FAVICON}`);
if (/<head[^>]*>/i.test(html)) return html.replace(/<head[^>]*>/i, (m) => `${m}\n${STANDARD_FAVICON}`);
return html;
}

// Reader-safety: inside $$...$$ display math, escape < and > so the HTML
// parser doesn't treat e.g. y_{<t} as a tag and silently truncate the formula.
// KaTeX decodes entities, so this is semantically lossless. Scoped to $$ (very
// unlikely to false-match) and skips already-escaped content.
function fixDisplayMath(html: string): string {
return html.replace(/\$\$([\s\S]*?)\$\$/g, (_m, inner: string) => {
const fixed = inner.replace(/</g, "&lt;").replace(/>/g, "&gt;");
return `$$${fixed}$$`;
});
}

// Reader-safety: a complete, well-formed document for any browser/offline read.
function ensureDocMeta(html: string): string {
let out = html;
if (!/<html[^>]*\blang=/i.test(out)) out = out.replace(/<html\b/i, '<html lang="en"');
if (/<head[^>]*>/i.test(out)) {
if (!/<meta[^>]+name=["']viewport/i.test(out))
out = out.replace(/<head[^>]*>/i, (m) => `${m}\n<meta name="viewport" content="width=device-width, initial-scale=1.0">`);
if (!/<meta[^>]+name=["']theme-color/i.test(out))
out = out.replace(/<head[^>]*>/i, (m) => `${m}\n<meta name="theme-color" content="#0f1729">`);
}
return out;
}

function assertHtmlDocument(html: string) {
const trimmed = html.trim();
if (!trimmed) throw new Error("html is required");
Expand Down Expand Up @@ -276,7 +311,9 @@ async function renderVisualExplanation(params: VisualExplainerParams, signal?: A
}

signal?.throwIfAborted();
writeFileSync(outputPath, params.html, "utf8");
// Reader-safety pipeline: fix truncating math, complete the doc head, guarantee favicon.
const finalHtml = ensureFavicon(ensureDocMeta(fixDisplayMath(params.html)));
writeFileSync(outputPath, finalHtml, "utf8");

signal?.throwIfAborted();

Expand Down
1 change: 1 addition & 0 deletions plugins/visual-explainer/templates/architecture.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Architecture Diagram — Reference Template</title>
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iNyIgZmlsbD0iIzBmMTcyOSIvPjxjaXJjbGUgY3g9IjkiIGN5PSIxMC41IiByPSIzIiBmaWxsPSIjZDRhNzNhIi8+PGNpcmNsZSBjeD0iMjMiIGN5PSIxMC41IiByPSIzIiBmaWxsPSIjNjBhNWZhIi8+PGNpcmNsZSBjeD0iMTYiIGN5PSIyMi41IiByPSIzIiBmaWxsPSIjNGFkZTgwIi8+PHBhdGggZD0iTTkgMTAuNSBMMTYgMjIuNSBMMjMgMTAuNSIgc3Ryb2tlPSIjZDRhNzNhIiBzdHJva2Utd2lkdGg9IjEuNyIgZmlsbD0ibm9uZSIgb3BhY2l0eT0iMC43NSIvPjwvc3ZnPg==">
<!--
Reference template for the visual-explainer skill: CSS Grid architecture layout.
Warm terracotta/sage palette — distinctly different from the teal (mermaid)
Expand Down
1 change: 1 addition & 0 deletions plugins/visual-explainer/templates/data-table.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Requirements Audit — Reference Template</title>
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iNyIgZmlsbD0iIzBmMTcyOSIvPjxjaXJjbGUgY3g9IjkiIGN5PSIxMC41IiByPSIzIiBmaWxsPSIjZDRhNzNhIi8+PGNpcmNsZSBjeD0iMjMiIGN5PSIxMC41IiByPSIzIiBmaWxsPSIjNjBhNWZhIi8+PGNpcmNsZSBjeD0iMTYiIGN5PSIyMi41IiByPSIzIiBmaWxsPSIjNGFkZTgwIi8+PHBhdGggZD0iTTkgMTAuNSBMMTYgMjIuNSBMMjMgMTAuNSIgc3Ryb2tlPSIjZDRhNzNhIiBzdHJva2Utd2lkdGg9IjEuNyIgZmlsbD0ibm9uZSIgb3BhY2l0eT0iMC43NSIvPjwvc3ZnPg==">
<!--
Reference template for the visual-explainer skill: data tables.
Rose/cranberry palette — distinctly different from terracotta (architecture)
Expand Down
1 change: 1 addition & 0 deletions plugins/visual-explainer/templates/mermaid-flowchart.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CI/CD Pipeline — Reference Template</title>
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iNyIgZmlsbD0iIzBmMTcyOSIvPjxjaXJjbGUgY3g9IjkiIGN5PSIxMC41IiByPSIzIiBmaWxsPSIjZDRhNzNhIi8+PGNpcmNsZSBjeD0iMjMiIGN5PSIxMC41IiByPSIzIiBmaWxsPSIjNjBhNWZhIi8+PGNpcmNsZSBjeD0iMTYiIGN5PSIyMi41IiByPSIzIiBmaWxsPSIjNGFkZTgwIi8+PHBhdGggZD0iTTkgMTAuNSBMMTYgMjIuNSBMMjMgMTAuNSIgc3Ryb2tlPSIjZDRhNzNhIiBzdHJva2Utd2lkdGg9IjEuNyIgZmlsbD0ibm9uZSIgb3BhY2l0eT0iMC43NSIvPjwvc3ZnPg==">
<!--
Reference template for the visual-explainer skill: Mermaid diagrams.
Teal/cyan palette — distinctly different from terracotta (architecture)
Expand Down
Loading