@jxpeng98/vitepress-pyodide
v1.0.1
Published
VitePress plugin and components to run Python (Pyodide) in Markdown with shared page state.
Downloads
2
Maintainers
Readme
vitepress-pyodide
Run Python (Pyodide) inline in VitePress. This package provides:
- Markdown-it plugins to turn code into interactive cells:
- Fenced blocks:
```pyodide→ interactive cell - HTML blocks:
<Pyodide>…</Pyodide>→ interactive cell (dedented, newlines preserved) - Vue components with a shared in‑browser interpreter per page and a tidy VitePress look
- Fenced blocks:
Highlights
- Per‑page shared state: later cells can reuse variables from earlier cells
- Fresh state on new pages (SPA navigation): the first run clears globals
- Editor hidden by default; buttons: Run, Clear, Show/Hide Code
- Dark mode via VitePress tokens — no hardcoded colors
- Adaptive heights: editor/output avoid empty space, but can grow
Table of Contents
- vitepress-pyodide
Installation
pnpm add -D vitepress-pyodideSetup
VitePress Configuration (.vitepress/config.(ts|mts))
import { createPyodideMarkdownPlugin, createPyodideHtmlBlockPlugin } from 'vitepress-pyodide/markdown'
export default {
markdown: {
config(md) {
// Default layout: vertical (output below). Use 'horizontal' for side‑by‑side.
md.use(createPyodideMarkdownPlugin({ layout: 'vertical' }))
md.use(createPyodideHtmlBlockPlugin({ layout: 'vertical' }))
}
}
}VitePress Theme Enhancement (.vitepress/theme/index.(ts|mts))
import { enhanceAppWithPyodide } from 'vitepress-pyodide/client'
export default {
enhanceApp(ctx) {
enhanceAppWithPyodide(ctx)
}
}Usage
Fenced Blocks
Use ```pyodide to create an interactive Python cell.
data = [3, 3, 6, 9, 12]
print(sum(data), len(data))Optional Metadata
Metadata can be added in the info string:
- Title:
title="My Cell"or bare words afterpyodide(e.g.,```pyodide My Cell) - Layout:
layout=horizontal|layout=verticalor shorthand tokens:horizontal/right/vertical - Locale Override:
locale="en"|"zh-CN"
Example:
x = 41
print(f"x = {x}")HTML Form
Use <Pyodide>…</Pyodide> HTML blocks for interactive cells.
<Pyodide title="中文示例" locale="zh-CN" layout="vertical">
print("你好,Pyodide!")
</Pyodide>Loading Python Packages
This plugin can load packages before a cell runs.
Pyodide Package Repository
For most packages in the Pyodide distribution (e.g., numpy, pandas, matplotlib), use the packages attribute:
Fenced Block:
import pandas as pd
import matplotlib.pyplot as pltHTML Form:
<Pyodide packages="pandas, matplotlib">
import pandas as pd
import matplotlib.pyplot as plt
</Pyodide>PyPI Wheels (micropip)
For pure-Python packages compatible with Pyodide (PyPI wheels), use the # micropip: directive at the top of the cell:
# micropip: XlsxWriter openpyxl
import micropip
# After the directive runs, your imports work as usual
import XlsxWriter, openpyxlNotes:
- The directive
# micropip: ...(or# pip: ...) triggers an installation phase before your code executes. It accepts space- or comma‑separated names. - Not all PyPI packages have WebAssembly‑compatible wheels; consult https://pyodide.org.
- The plugin can still auto‑detect and load
matplotlibwhen it seesimport matplotlib.
Plots (matplotlib)
Matplotlib needs a browser‑friendly output path. This plugin auto‑embeds figures after your code runs:
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.show() # optional — figures are auto‑exported as SVG even without explicit show()How it works:
- Before your code runs, the plugin patches
plt.show()to export existing figures. - After your code finishes, it exports any remaining figures.
- Figures are saved as SVG and embedded below the text output — no changes to your code required.
- If you prefer explicit control, you can still save and print a data URL yourself:
import io, base64
import matplotlib.pyplot as plt
plt.plot([1,2,3])
buf = io.BytesIO(); plt.savefig(buf, format='svg', bbox_inches='tight'); buf.seek(0)
print('data:image/svg+xml;base64,' + base64.b64encode(buf.read()).decode())Component API
<Pyodide ...>(wrapper) forwards to<PyodideCell ...>ensuring identical UI to fenced blocks- Props:
layout?:'vertical'|'horizontal'locale?:string(e.g.,'en','zh-CN')title?:stringcode?:string(optional initial code)code64?:string(base64 initial code; used by plugins)
Behavior Notes
- Script semantics: Only printed output appears. Bare expressions won’t display unless printed.
- First run: Downloads Pyodide (~10MB). Subsequent runs reuse the same instance.
- State persistence: Variables persist within the same page; navigating to another page starts fresh state.
Styling
- Adapts to VitePress theme via CSS variables (no hardcoded colors)
- Editor/output heights auto‑fit content; users can drag the editor bigger
Customize
- Default layout per site: Pass
{ layout: 'horizontal' }to the plugins in config - Pyodide version/CDN: Update
packages/vitepress-pyodide/src/runtime.ts
