Components Overview
Eduskript extends markdown with interactive components. This skript is the reference for every built-in component, with full syntax, options, and examples.
How components work
A component is a special block in your markdown — either a fenced code block with a keyword, or a custom HTML element. The renderer transforms it into a React component on the page, often with interactive behavior (run code, query a database, draw on the canvas).
Markdown → AST transformation → Custom HTML element → React hydration → Interactive component
You don't need to know any of this to use components — but it explains why two syntactic conventions exist (markdown and HTML) and why there are some constraints.
The two component syntaxes
Markdown style (preferred for code blocks)
```python editor
print("Hello")
```
Used for code editors and code blocks. Compact, natural to read.
HTML style (for everything else, plus extra options on code editors)
<code-editor data-language="python" data-code="print('Hello')"></code-editor>
Used for components with no clear markdown equivalent (callouts have markdown via > [!type], but quizzes, tabs, plugins, and custom elements use HTML).
HTML rules — strictAll custom HTML must be lowercase tags with lowercase, string-quoted attributes. No PascalCase, no JSX expressions.
- ✅
<question id="q1" type="single">- ❌
<Question id="q1" type="single">(PascalCase tag — won't render)- ❌
<question initialCount={7}>(JSX expression — writeinitialcount="7"instead)
Standard HTML elements (<div>, <span>, <p>, <h1>, etc.) work too — useful for layout and inline styling.
Quick tour of the built-in components
Callout
> [!tip] Pro tip
> Callouts highlight important information.
Pro tipCallouts highlight important information.
Math
Inline: — block:
Code block (read-only)
def greet(name):
return f"Hello, {name}!"
Code editor (runnable)
Auto-graded exercise
A code editor + a python-check block that grades the student's code:
SQL editor
Query a SQLite database in the browser. The example below pulls the five most recently released TV shows from netflix.db — ordered by release_date descending, capped at 5 rows. Try editing the LIMIT or swapping tv_show for movie:
Video

Custom plugin
<plugin src="marie/mod-clock" mod="7"></plugin>
Quiz (single choice)
<question id="q1" type="single">
<p>What is 2 + 2?</p>
<answer>3</answer>
<answer correct>4</answer>
<answer>5</answer>
</question>
Tabs
<tabs-container>
<tab-item label="Python">Python content</tab-item>
<tab-item label="JavaScript">JavaScript content</tab-item>
</tabs-container>
Custom CSS
<style>
.my-class { color: red; }
</style>
Quick reference
| Component | Markdown | HTML |
|---|---|---|
| Callout | > [!type] | — |
| Math (inline / block) | $...$ / $$...$$ | — |
| Code block | ``` | — |
| Code editor | ```python editor | <code-editor data-language="python"> |
| SQL editor | ```sql editor db="..." | <code-editor data-language="sql" data-db="..."> |
| Auto-graded | ```python-check for="..." | — |
| Image |  | <image src="file.png"> |
| Excalidraw |  | — |
| Video |  | <muxvideo src="file.mp4"> |
| Plugin | — | <plugin src="owner/plugin"> |
| Quiz | — | <question type="single">...<answer> |
| Tabs | — | <tabs-container>...<tab-item> |
| Custom CSS | — | <style>.cls { ... }</style> |
The rest of this skript covers each built-in component in detail.