Skip to content
Closed
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
56 changes: 56 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: CI

on:
push:
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
test-and-package:
name: Test and package plugin
runs-on: ubuntu-latest
timeout-minutes: 20

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: |
package-lock.json
packages/description-renderer/package-lock.json
packages/mcp-server/package-lock.json

- name: Install root dependencies
run: npm ci

- name: Install description renderer dependencies
run: npm ci --prefix packages/description-renderer

- name: Install MCP server dependencies
run: npm ci --prefix packages/mcp-server

- name: Run tests
run: npm test

- name: Build VSIX artifact
run: npm run package

- name: Upload VSIX artifact
uses: actions/upload-artifact@v4
with:
name: codetour-linux-x64-${{ github.sha }}
path: codetour-linux-x64-*.vsix
if-no-files-found: error
retention-days: 14
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules
.vscode-test/
*.vsix
.DS_Store
.agents/
54 changes: 54 additions & 0 deletions .tours/changes.tour
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"$schema": "https://aka.ms/codetour-schema",
"title": "Descriptions de tour cliquables dans un webview",
"description": "Cette branche ajoute une vue agrandie pour lire la description de l'étape CodeTour active. Depuis la barre d'actions du commentaire, l'utilisateur ouvre un panneau latéral qui rend le Markdown, conserve les liens CodeTour et protège le webview contre le HTML ou les URI dangereux.\n\nElle complète aussi les consignes du serveur MCP afin que les tours générés restent lisibles et utilisent Mermaid lorsqu'un diagramme apporte une vraie vue d'ensemble.\n\nGenerated from `feature/mermaid-tour-support` (`ba7f55f65b262af892aca94fb8cb2582c0757f9b`) to `feature/clickable-tour-description-webview` (`591effd`). Les modifications locales non commitées sont exclues.",
"ref": "591effd",
"steps": [
{
"title": "Point d'entrée dans l'interface",
"description": "La nouvelle commande `codetour.showStepDescription` est déclarée dans le manifeste et ajoutée à la barre d'actions du commentaire CodeTour. L'icône d'aperçu apparaît en première position, tandis que les commandes de navigation et de fin de tour conservent leurs rôles.\n\nLa commande est également disponible dans la palette et dans les menus associés au contexte de lecture.",
"file": "package.json",
"pattern": "codetour.showStepDescription"
},
{
"title": "Enregistrement de la commande",
"description": "Le player relie la contribution du manifeste à `showStepDescription`. Cette petite couture garde le manifeste déclaratif et délègue toute la logique de présentation au module du webview.",
"file": "src/player/commands.ts",
"pattern": "showStepDescription"
},
{
"title": "Ouverture de la description active",
"description": "`showStepDescription` récupère le tour et l'étape actifs, ignore proprement les cas sans description, puis passe le contenu dans le pipeline de prévisualisation existant. Les liens de fichiers, références de tours, commandes et images Mermaid bénéficient ainsi des mêmes transformations que les autres surfaces de lecture.\n\nUn seul panneau est réutilisé au fil des étapes. Son titre et son contenu sont actualisés, et les références globales sont nettoyées à sa fermeture.",
"file": "src/player/descriptionWebview.ts",
"pattern": "export async function showStepDescription"
},
{
"title": "Liens réellement cliquables",
"description": "Le webview renvoie les clics au processus de l'extension. Les commandes sont limitées à `codetour.*` et `vscode.open`, les liens HTTP, HTTPS et mailto sont ouverts à l'extérieur, et les chemins relatifs sont résolus dans le workspace.\n\nLes objets URI encodés dans les arguments de commande sont reconstruits avant l'appel à VS Code, ce qui permet aux liens enrichis produits par CodeTour de continuer à fonctionner.",
"file": "src/player/descriptionWebview.ts",
"pattern": "async function openLink"
},
{
"title": "Rendu Markdown centralisé et sécurisé",
"description": "Le nouveau module convertit le Markdown avec `markdown-it`, puis nettoie systématiquement le HTML avec `sanitize-html`. L'allowlist conserve le balisage de présentation, les liens, le code et les images nécessaires au renderer Mermaid, tout en supprimant scripts, attributs et protocoles non autorisés.\n\nLe document final ajoute une Content Security Policy avec nonce, reprend les couleurs du thème VS Code et intercepte les liens non locaux pour les transmettre à l'extension.\n\n**Diagram — Flux d'une description jusqu'à l'action utilisateur**\n```mermaid\nflowchart LR\n A[Description de l'étape] --> B[Pipeline CodeTour]\n B --> C[Markdown-it]\n C --> D[Sanitization HTML]\n D --> E[Webview sécurisé]\n E -->|clic| F[Validation du lien]\n F --> G[Commande VS Code ou navigateur]\n```",
"file": "src/player/markdown.ts",
"pattern": "export function renderMarkdownToHtml"
},
{
"title": "Décision d'architecture",
"description": "L'ADR formalise la séparation entre les surfaces natives de VS Code, qui continuent de recevoir du Markdown préparé, et les surfaces HTML possédées par l'extension, qui doivent toutes passer par le renderer et le sanitizer partagés.\n\n`markdown-it` et `sanitize-html` deviennent donc des dépendances directes: leur version et leur politique de sécurité font partie du contrat de CodeTour au lieu de dépendre d'une dépendance transitive.",
"file": "docs/adr/0009-centralize-markdown-rendering-and-sanitization.md"
},
{
"title": "Couverture du comportement et de la sécurité",
"description": "Les tests du webview vérifient le rendu d'un titre Markdown, la transmission des clics, la Content Security Policy, l'échappement du titre du panneau et la suppression des scripts ou liens `javascript:`.\n\nUn test séparé contrôle la contribution de menu pour garantir que le nouveau bouton ne remplace pas l'action `End Tour`.",
"file": "src/player/descriptionWebview.test.ts"
},
{
"title": "Des tours MCP plus lisibles",
"description": "Le second commit enrichit les instructions exposées par `create_project_tour` et `create_changes_tour`. Les descriptions doivent utiliser des paragraphes courts séparés par des lignes vides, des listes lorsque cela clarifie une collection ou une séquence, et éviter les gros blocs de texte.\n\nLes tours d'architecture, de workflow, de cycle de vie ou multi-modules sont désormais encouragés à inclure un diagramme Mermaid quand il synthétise des relations réparties sur plusieurs étapes. Le schéma d'entrée et les tests d'intégration rendent ces attentes visibles et vérifiables.",
"file": "packages/mcp-server/src/server.ts",
"pattern": "MARKDOWN_WRITING_GUIDANCE"
}
]
}
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"typescript.tsc.autoDetect": "off",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
"source.organizeImports": "explicit"
}
}
7 changes: 6 additions & 1 deletion .vscodeignore
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
.tours/**
.vscode/**
node_modules/**
packages/**
src/**
scripts/**
docs/**
.gitignore
.space
package.lock.json
tsconfig.json
webpack.config.js
dist/test/**
dist/extension-web.js*
**/*.vsix
.git/**
.github/**
**/*.svg
**/*.svg
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
## Upcoming

- Added a bundled, workspace-confined MCP server for generating Project Tours
and Changes Tours from VS Code and GitHub Copilot.
- Added secure, theme-aware Mermaid diagrams to Tour descriptions and MCP
validation.

- Automatically updating a tour file as the associated code changes
- Automatically set the "pattern" record mode when you create a new tour, and select `None` for the git ref
- Added support for opening a `*.tour` file in the VS Code notebook editor (Insiders only)
Expand Down
21 changes: 21 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# CodeTour

CodeTour guides a reader through selected places in a codebase using an ordered sequence of contextual explanations.

## Language

**Tour**:
An ordered walkthrough of a codebase composed of Tour Steps.
_Avoid_: Guide, presentation

**Tour Step**:
One contextual stop in a Tour, anchored to a code location or content surface and carrying a description.
_Avoid_: Comment, slide

**Mermaid Diagram**:
A diagram whose source belongs to a Tour description and whose rendered form remains part of that description during playback.
_Avoid_: Screenshot, generated attachment

**Playback Surface**:
A user-visible place where a Tour or Tour Step description is presented while reading a Tour.
_Avoid_: Component, container
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# CodeTour 🗺️

## AI-generated tours

The desktop extension includes a local MCP server for generating a Project
Tour or a Changes Tour. VS Code and GitHub Copilot discover one server per
workspace folder automatically. The server is bundled with the extension,
runs over stdio, remains confined to its workspace, and does not access the
network.

Tour descriptions can include captioned Mermaid diagrams. CodeTour validates
generated diagrams before saving them and renders them as static,
theme-aware images during playback without writing generated image files.

CodeTour is a Visual Studio Code extension, which allows you to record and play back guided walkthroughs of your codebases. It's like a table of contents, that can make it easier to onboard (or re-board!) to a new project/feature area, visualize bug reports, or understand the context of a code review/PR change. A "code tour" is simply a series of interactive steps, each of which are associated with a specific directory, or file/line, and include a description of the respective code. This allows developers to clone a repo, and then immediately start **learning it**, without needing to refer to a `CONTRIBUTING.md` file and/or rely on help from others. Tours can either be checked into a repo, to enable sharing with other contributors, or [exported](#exporting-tours) to a "tour file", which allows anyone to replay the same tour, without having to clone any code to do it!

<img width="800px" src="https://user-images.githubusercontent.com/116461/76165260-c6c00500-6112-11ea-9cda-0a6cb9b72e8f.gif" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Distribute and discover the MCP server with the extension

The desktop extension bundles the compiled stdio MCP server and registers one
server definition per workspace folder. This allows VS Code and GitHub Copilot
to discover the tools without a workspace-specific MCP configuration file.

Each server receives one explicit workspace root and remains confined to it.
The web extension does not register or start the Node.js server.

The MCP server definition API requires VS Code 1.101, so the extension's
minimum VS Code version moves to 1.101.
19 changes: 19 additions & 0 deletions docs/adr/0007-render-mermaid-diagrams-within-codetour.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Render Mermaid diagrams within CodeTour

CodeTour stores Mermaid source in fenced `mermaid` blocks inside a Tour's existing Markdown descriptions and renders diagrams itself, without requiring another VS Code extension or committing generated images. The Tour Generator's MCP tools validate Mermaid before writing a generated Tour, using the same exact, locked Mermaid version and diagram rules as playback. During playback, CodeTour renders with strict security, disables interactive links and HTML, and adapts the result to the active theme: Mermaid produces a theme-aware SVG internally, which CodeTour sanitizes as defense in depth and rasterizes in memory. Native comments transport the diagram as a `data:image/png;base64` image in the final Markdown, because SVG data URIs and in-memory filesystem URIs did not display as images in native comments. A rendering failure shows a compact warning and the diagram's alternative text without exposing its source, and no generated SVG or PNG file is ever written.

A Mermaid Diagram is introduced by a visible Markdown caption of the form `**Diagram — …**`, which also provides its alternative text. The first version accepts `flowchart`, `sequenceDiagram`, `stateDiagram-v2`, `classDiagram`, and `erDiagram`. A single Markdown description may contain at most three diagrams, and each Mermaid source may contain at most 20 KB. Changing the active VS Code theme invalidates the render cache, immediately refreshes the visible Tour step and Tour tree, and leaves other diagrams to be regenerated on demand. Diagrams in the same description render independently, so one failure does not hide successful diagrams. Mermaid fences are excluded from CodeTour's existing `Insert Code` transformation.

Packaging accounts for the rasterizer's native code by producing one VSIX per
supported platform. The build externalizes `@resvg/resvg-js`, stages only the
matching native binary, and verifies the staged runtime before publication.

```mermaid
flowchart LR
Generator[Tour Generator] -->|proposes Mermaid source| MCP[CodeTour MCP tools]
MCP -->|validates with the locked Mermaid| Tour[Tour file]
Tour -->|reads the fenced Mermaid block| Renderer[CodeTour Mermaid renderer]
Renderer -->|strict, theme-aware SVG| Cache[In-memory cache]
Cache -->|in-memory PNG as a data URI image| Surface[Markdown description surfaces]
Renderer -->|rendering failure| Fallback[Warning and alternative text]
```
5 changes: 5 additions & 0 deletions docs/adr/0008-drop-vscode-web-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Drop VS Code Web support

CodeTour targets the Node-based VS Code extension host and no longer builds or publishes a browser extension. The manifest exposes only the Node `main` entry point, the build emits the Node extension and the bundled MCP server with no Web Worker bundle, and the Web-specific desktop-integration shim and the `os-browserify`/`path-browserify` fallbacks are deleted. Packaging and CI verify that no web artifact reaches the VSIX.

Desktop VS Code remains supported locally and through remote Node extension hosts such as SSH, Dev Containers, and Codespaces; `extensionKind: ["workspace"]` is unchanged. The `isWeb` property of a tour's `when` expression context is retained and now always evaluates to `false`.
19 changes: 19 additions & 0 deletions docs/adr/0009-centralize-markdown-rendering-and-sanitization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
status: proposed
---

# Centralize Markdown rendering and sanitization

CodeTour uses one shared description pipeline for every Playback Surface. That pipeline prepares CodeTour-specific links and references, renders Mermaid diagrams, and produces the same Markdown regardless of its destination. Native VS Code surfaces continue to receive this prepared Markdown because VS Code owns their rendering; extension-owned HTML surfaces, including the Expanded Description View for the active Tour Step, convert it through a directly declared Markdown engine and an explicit HTML sanitizer before display.

The Markdown engine and sanitizer are direct application dependencies rather than incidental transitive dependencies of Mermaid or packaging tools. This keeps rendering behavior versioned and testable at the CodeTour boundary, prevents a dependency update elsewhere from silently changing descriptions, and gives every extension-owned HTML surface the same allowlist for markup, attributes, URI schemes, and images.

## Considered options

- Relying on a Markdown engine brought transitively by another package was rejected because its presence and version are not part of CodeTour's dependency contract.
- Letting each webview choose and configure its own renderer was rejected because rendering and security rules would drift between Playback Surfaces.
- Replacing native VS Code Markdown rendering with generated HTML was rejected because native comments, hovers, tooltips, and notebook cells own their rendering lifecycle and capabilities.

## Consequences

All extension-owned HTML rendering must go through the shared renderer and sanitizer; a Playback Surface must not instantiate its own Markdown engine. Changes to rendering or the sanitizer allowlist are cross-surface behavior changes and require tests. Native surfaces may still differ visually where VS Code intentionally controls presentation, but they consume the same prepared Markdown semantics.
Loading