Skip to content

Commit 610ce03

Browse files
JayantJayant
authored andcommitted
Added option to specify initial number of lines in pyodide fence editors
1 parent 2aced22 commit 610ce03

File tree

3 files changed

+92
-4
lines changed

3 files changed

+92
-4
lines changed

src/markdown_exec/_internal/formatters/pyodide.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from __future__ import annotations
44

5+
import json
56
from typing import TYPE_CHECKING, Any
67

78
if TYPE_CHECKING:
@@ -37,17 +38,64 @@
3738
3839
<script>
3940
document.addEventListener('DOMContentLoaded', (event) => {
40-
setupPyodide('%(id_prefix)s', install=%(install)s, themeLight='%(theme_light)s', themeDark='%(theme_dark)s', session='%(session)s');
41+
setupPyodide('%(id_prefix)s', install=%(install)s, themeLight='%(theme_light)s', themeDark='%(theme_dark)s', session='%(session)s', heightConfig=%(height_config)s);
4142
});
4243
</script>
4344
"""
4445

4546
_counter = 0
4647

4748

49+
def _calculate_height_config(code: str, extra: dict) -> dict:
50+
"""Calculate height configuration for the Pyodide editor."""
51+
# Get per-block options with defaults
52+
height = extra.pop("height", "auto")
53+
min_height = extra.pop("min_height", 5)
54+
max_height = extra.pop("max_height", 30)
55+
resize = extra.pop("resize", True)
56+
57+
# Validate and convert types
58+
if isinstance(height, str) and height != "auto":
59+
try:
60+
height = int(height)
61+
except ValueError:
62+
height = "auto"
63+
64+
if height != "auto" and isinstance(height, int) and height <= 0:
65+
height = "auto"
66+
67+
try:
68+
min_height = max(1, int(min_height))
69+
max_height = max(min_height, int(max_height))
70+
except ValueError:
71+
min_height, max_height = 5, 30
72+
73+
try:
74+
resize = str(resize).lower() in ("true", "1", "yes", "on")
75+
except (ValueError, AttributeError):
76+
resize = True
77+
78+
# Calculate actual height if "auto"
79+
if height == "auto":
80+
# Count lines in the code, with a reasonable default
81+
lines = len(code.strip().split("\n")) if code.strip() else 5
82+
height = max(min_height, min(lines, max_height))
83+
84+
return {
85+
"height": height,
86+
"minLines": min_height,
87+
"maxLines": max_height,
88+
"resize": resize,
89+
}
90+
91+
4892
def _format_pyodide(code: str, md: Markdown, session: str, extra: dict, **options: Any) -> str: # noqa: ARG001
4993
global _counter # noqa: PLW0603
5094
_counter += 1
95+
96+
# Calculate height configuration for this specific code block
97+
height_config = _calculate_height_config(code, extra)
98+
5199
version = extra.pop("version", "0.26.4").lstrip("v")
52100
install = extra.pop("install", "")
53101
install = install.split(",") if install else []
@@ -57,6 +105,9 @@ def _format_pyodide(code: str, md: Markdown, session: str, extra: dict, **option
57105
theme = f"{theme},{theme}"
58106
theme_light, theme_dark = theme.split(",")
59107

108+
# Convert height_config to JSON string for JavaScript
109+
height_config_json = json.dumps(height_config)
110+
60111
data = {
61112
"id_prefix": f"exec-{_counter}--",
62113
"initial_code": code,
@@ -66,6 +117,7 @@ def _format_pyodide(code: str, md: Markdown, session: str, extra: dict, **option
66117
"session": session or "default",
67118
"play_emoji": _play_emoji,
68119
"clear_emoji": _clear_emoji,
120+
"height_config": height_config_json,
69121
}
70122
rendered = _template % data
71123
if exclude_assets:

src/markdown_exec/assets/pyodide.css

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ html[data-theme="dark"] {
1313

1414
.pyodide-editor {
1515
width: 100%;
16-
min-height: 200px;
17-
max-height: 400px;
1816
font-size: .85em;
1917
}
2018

src/markdown_exec/assets/pyodide.js

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ function updateTheme(editor, light, dark) {
7777
});
7878
}
7979

80-
async function setupPyodide(idPrefix, install = null, themeLight = 'tomorrow', themeDark = 'tomorrow_night', session = null) {
80+
async function setupPyodide(idPrefix, install = null, themeLight = 'tomorrow', themeDark = 'tomorrow_night', session = null, heightConfig = null) {
8181
const editor = ace.edit(idPrefix + "editor");
8282
const run = document.getElementById(idPrefix + "run");
8383
const clear = document.getElementById(idPrefix + "clear");
@@ -88,6 +88,44 @@ async function setupPyodide(idPrefix, install = null, themeLight = 'tomorrow', t
8888
editor.session.setMode("ace/mode/python");
8989
setTheme(editor, getTheme(), themeLight, themeDark);
9090

91+
// Apply height configuration using Ace editor options
92+
if (heightConfig) {
93+
// Set initial height/lines
94+
if (heightConfig.height && typeof heightConfig.height === 'number') {
95+
editor.setOption("minLines", heightConfig.height);
96+
if (!heightConfig.resize) {
97+
editor.setOption("maxLines", heightConfig.height);
98+
}
99+
}
100+
101+
// Set min/max lines
102+
if (heightConfig.minLines) {
103+
editor.setOption("minLines", Math.max(editor.getOption("minLines") || 1, heightConfig.minLines));
104+
}
105+
if (heightConfig.maxLines) {
106+
editor.setOption("maxLines", heightConfig.maxLines);
107+
}
108+
109+
// Configure resize behavior
110+
if (heightConfig.resize === false) {
111+
// Fixed height - set both min and max to the same value
112+
const fixedLines = heightConfig.height || heightConfig.minLines || 5;
113+
editor.setOption("minLines", fixedLines);
114+
editor.setOption("maxLines", fixedLines);
115+
} else {
116+
// Allow resizing within bounds
117+
editor.setOption("minLines", heightConfig.minLines || 5);
118+
editor.setOption("maxLines", heightConfig.maxLines || 30);
119+
}
120+
} else {
121+
// Default behavior - keep existing fallback
122+
editor.setOption("minLines", 5);
123+
editor.setOption("maxLines", 30);
124+
}
125+
126+
// Force editor to resize after setting options
127+
editor.resize();
128+
91129
writeOutput(output, "Initializing...");
92130
let pyodide = await pyodidePromise;
93131
if (install && install.length) {

0 commit comments

Comments
 (0)