Interactive REPL Plugin
The REPL plugin adds interactive C# code execution to your documentation. Readers can run code snippets directly in the browser, making it easy to explore APIs and experiment with your library.
Plugin ID: mokadocs-repl
What It Does
The REPL plugin transforms specially marked code blocks into interactive editors with a Run button. When a reader clicks Run, the C# code is sent to the server, executed via Roslyn, and the console output is displayed in a panel below the code block. This provides a "try it live" experience without readers needing to set up a local development environment.
Markdown Syntax
Use the csharp-repl language identifier on fenced code blocks to mark them as interactive:
```csharp-repl
var x = 42;
Console.WriteLine($"The answer is {x}");
```
Standard csharp code blocks are not affected and will render as normal syntax-highlighted code without the Run button.
How It Works
The REPL plugin integrates at multiple levels of the MokaDocs pipeline:
1. Markdown Extension (ReplExtension)
During markdown parsing, the ReplExtension (a Markdig extension) intercepts code blocks with the csharp-repl language identifier. It wraps the code in a structured HTML container:
<div class="repl-container" data-repl="true">
<pre><code class="language-csharp">var x = 42;
Console.WriteLine($"The answer is {x}");</code></pre>
</div>
The data-repl="true" attribute marks the container for the client-side JavaScript to enhance.
2. Plugin Injection (ReplPlugin)
During the plugin execution phase (order 500), the ReplPlugin injects the necessary CSS and JavaScript into each page that contains REPL containers. This includes:
- A Run button overlaid on the code block
- An output panel below the code block that shows execution results
- A loading indicator displayed while code is executing
- Styling for success and error states
3. Client-Side Execution Request
When the reader clicks the Run button, the injected JavaScript:
- Extracts the code from the code block
- Sends a
POSTrequest to/api/repl/executewith the code as the request body - Displays a loading spinner while waiting for the response
- Renders the output (or error message) in the output panel
4. Server-Side Execution (ReplExecutionService)
The /api/repl/execute endpoint is available in serve mode only. The ReplExecutionService handles execution:
- Receives the C# code string
- Creates a Roslyn
CSharpScriptinstance with configured options - Redirects
Console.Outto aStringWriterto capture output - Executes the script with a 5-second timeout
- Returns the captured console output (or the exception message on failure)
5. Output Display
The output panel renders results in a monospace font. Successful output is shown in the default text color. Errors and exceptions are shown in red with the exception type and message.
Features
Execution Timeout
All REPL executions are subject to a 5-second timeout. If the script does not complete within this window, execution is cancelled and an error message is returned. This prevents infinite loops and long-running operations from blocking the server.
Console Output Capture
The REPL captures output from Console.Write and Console.WriteLine. Both methods are fully supported, including formatted strings and interpolated strings:
```csharp-repl
Console.WriteLine("Hello, World!");
Console.Write("No ");
Console.Write("newline ");
Console.WriteLine("here.");
Console.WriteLine($"2 + 2 = {2 + 2}");
```
Default Namespaces
The following namespaces are imported by default in every REPL execution, so you do not need to add using statements for them:
SystemSystem.LinqSystem.Collections.GenericSystem.Text
You can use types from these namespaces directly:
```csharp-repl
var numbers = new List<int> { 1, 2, 3, 4, 5 };
var even = numbers.Where(n => n % 2 == 0).ToList();
Console.WriteLine(string.Join(", ", even));
```
NuGet Package Loading
You can configure additional NuGet packages to be available in REPL sessions. Packages are specified in the plugin options and are resolved and loaded at initialization time.
plugins:
- name: mokadocs-repl
options:
packages:
- Newtonsoft.Json
- Humanizer@2.14.1
Packages without a version specifier resolve to the latest stable version. Use the @version syntax to pin a specific version.
Once configured, you can use types from those packages in your REPL blocks:
```csharp-repl
using Newtonsoft.Json;
var obj = new { Name = "MokaDocs", Version = "1.0" };
var json = JsonConvert.SerializeObject(obj, Formatting.Indented);
Console.WriteLine(json);
```
Project Assembly Auto-Loading
When you are documenting your own .NET library, the REPL plugin can automatically load your project's compiled assembly. This allows REPL blocks to reference the types and methods from the library you are documenting, providing readers with a true "try the API" experience.
The assembly is resolved from the build output of the project referenced in your MokaDocs configuration. No additional setup is required beyond having a successful build of your library.
Configuration
Basic Configuration
Add the REPL plugin to your mokadocs.yaml:
plugins:
- name: mokadocs-repl
With NuGet Packages
plugins:
- name: mokadocs-repl
options:
packages:
- Newtonsoft.Json
- Humanizer@2.14.1
Full Configuration Example
plugins:
- name: mokadocs-repl
options:
packages:
- Newtonsoft.Json
- Humanizer@2.14.1
- FluentValidation@11.0.0
Configuration Options
| Option | Type | Description |
|---|---|---|
packages |
string[] | List of NuGet packages to make available. Use PackageName or PackageName@Version format. |
Security
The REPL execution environment includes several safety measures:
- AppDomain isolation -- Scripts run in a restricted AppDomain with limited permissions, preventing access to the file system, network, and other system resources outside the sandbox.
- 5-second timeout -- Execution is forcefully cancelled after 5 seconds, protecting against infinite loops,
Thread.Sleepabuse, and other long-running operations. - No persistent state -- Each execution is independent. Variables and state do not carry over between Run clicks, even on the same code block.
These restrictions mean certain operations will fail in the REPL:
- File I/O operations (
File.ReadAllText,StreamWriter, etc.) - Network requests (
HttpClient,WebClient, etc.) - Thread and process creation
- Assembly loading beyond the pre-configured packages
Static Build Behavior
When you run mokadocs build to produce a static site, the REPL API endpoint is not available. In static builds, the REPL containers display a message in place of the Run button:
Run
mokadocs serveto execute code
This informs readers that they need the live dev server to use the interactive features. The code blocks still display with full syntax highlighting so readers can study the code even in the static version of the site.