コンテンツにスキップ

実行可能セル

実行可能セルは、先頭に metadata comment を持つ通常の MDX code block です。Oxiquill は生成時にその block を抽出し、runtime UI に置き換えます。

Rust セルは build 時に WebAssembly に compile されます。Python セルは browser の Pyodide worker で動きます。Haskell セルは build 時に WASI WebAssembly module に compile されます。3つの言語は同じ input metadata と run mode model を使います。

再実行中も最後に成功した出力を保持し、失敗時にはエラーと再試行操作を併記します。キャンセルや入力不正でも出力を消しません。互換性のあるグラフは同じ canvas を更新し、既定で180msの遷移を使います。OS の動作軽減設定を優先します。style の型・制限と Rust overload は リッチ出力 を参照してください。動的な出力の並びには明示的な artifact ID を推奨します。

interactive fence は rustpythonhaskell(Markdown の {.rust} form を含む)を使い、legal backtick/tilde fence と indentation に対応します。metadata は fence 先頭の一つの contiguous な language-specific option-comment block です。Rust は //|////|、Python は #|、Haskell は --| を使います。最初の source line より後にある option 風 comment は source code のままです。

許可される top-level field は次だけで、unknown field は error です。

FieldType と ruleDefault
id必須の lowercase kebab-case ^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$。page 内と route scope 後で unique。
titlecell header に表示する non-empty string。明示した値は前後の空白を除去。id
runbuttonreactiveautorunbutton
inputs^[a-z][a-z0-9_]*$ に一致する lowercase cross-language identifier から input spec への mapping。autorun では禁止。{}
packagesunique non-empty Pyodide package name。Python 専用。[]
cratescratesDir 直下の helper package name の unique non-empty list。Rust 専用。[]
timeoutMs1 以上 2147483647 以下の integer millisecond。30000
showSourceinitial source visibility を指定する boolean。true

source には metadata 以外の code が必要です。malformed YAML、wrong scalar/collection type、duplicate normalized ID/binding/function、unknown package/crate、language-mismatched dependency field は output を書く前に失敗します。diagnostic は page path、fence start line、可能なら cell ID、正確な field path を含みます。

Haskell cell は standard-library code のみで packages/crates を受け付けません。helper 不要の Rust example では crates: [] を明示します。package/crate list は strict validation 後に deduplicate/sort されます。

  • button: input と Run button を表示し、mount 時は実行しません。
  • reactive: input を表示して Run button を隠し、mount 時に一度実行します。その後は 150 ms trailing debounce を使い、active execution 一つと最新 replacement 一つだけを保持します。
  • autorun: input/Run button を表示せず、各 cell.id + runtimeVersion + source について正確に一度だけ実行します。開発中は runtime-version の更新が先に届いた場合も、source の更新によって前回の実行結果を無効化します。

次の button cell は、input を変更しても明示的に実行するまで待機します。

Rust + Wasm

Explicit button execution

Cell actions
Cell inputs

Choose an integer from 1 through 10.

println!("button value = {value}");

Run the cell to show its output.

次の autorun cell には実行 control がなく、現在の生成 runtime に対して1回だけ実行されます。

Rust + Wasm

One-time autorun execution

Cell actions
println!("autorun ready");

Waiting for the runtime to start.

reactive run が supersede されると、その worker request を active に cancel し、worker recycle の影響を受ける全 request を reject して timer を除去します。debounce 後は最新の complete value だけを実行します。cancellation は execution error として表示されず、stale result は新しい state を上書きしません。timeout/worker fault も同じ deterministic recycle boundary で回復します。unmount は pending/active work を cancel します。

各 input が受け取るのは type に関係する field だけです。共通 field は typelabeldescriptionvalue。numeric input は minmaxstepintegerselect/radiooptions も使います。

TypeValue と constraint
range, numberfinite number。step > 0min <= max、default が bound 内かつ step grid 上。
integer-2147483648 以上 2147483647 以下の signed 32-bit integer。bound/step も同じ domain。
text, textareastring value。
checkboxboolean value。
select, radionon-empty unique string option または { label, value } object。default は option value と一致。

type の default は textlabel の default は input name です。description は control と assistive technology 向けに関連付ける optional non-empty string です。default value は checkbox が false、numeric input が 0、text input が空 string です。numeric 専用 field は non-numeric control で拒否され、optionsselect/radio 以外では使えません。

signed 32-bit integer domain は JavaScript で正確に表現でき、Rust i32、Haskell Int、Python int に同じ値として渡されます。domain 外の integer valueminmaxstep は authoring 時に拒否されます。browser control と worker request も、integer: true の numeric input を含めて同じ domain を適用します。

numeric default は browser control と同じ step grid に揃える必要があります。effective step は step があればその値、なければ 1 です。grid の base は min があればその値、なければ明示または default の numeric value です。Oxiquill は不一致の default を丸めたり clamp したりせず、authoring 時に拒否します。

number/integer control は raw edit text と committed runtime value を分離します。空、入力途中、non-finite、range 外、step 不一致の text は表示を保ちますが cell input を更新しません。どれか一つでも invalid なら Run button は disabled になり、reactive execution は validity が戻った後に最新の complete value set を一度だけ実行します。range label の表示精度は step から決まります。

visible label が control の accessible name で、input key は generated language binding にだけ使います。normalization で二つの Rust/Haskell binding が衝突してはなりません。label、description、current value、validation message、grouped control は stable ID で関連付けられ、keyboard focus を表示し、run/error status は focus を奪わず announce されます。

この Rust セルは helper crate を使い、slider が変わるたびに plot を再描画します。

Rust + Wasm

Calculate the logistic map with Rust

Cell actions
Cell inputs
3.20
0.20
let steps = u32::try_from(steps).map_err(|_| "steps must be non-negative".to_owned())?;
let points = doc_rust::logistic_series(r, x0, steps).map_err(|error| error.to_string())?;

for point in points.iter().take(5) {
    println!("n={} x={:.6}", point.n, point.x);
}

emit_line_plot!(&points, "n", "x");

Waiting for the runtime to start.

crates: [] のセルは helper crate に依存しません。この例では checkbox、select、radio input を使います。

Rust + Wasm

Rust input UI

Cell actions
Cell inputs
style
let base_score = match operation.as_str() {
    "triple" => 21_i32,
    "double" => 14_i32,
    _ => 7_i32,
};
let score = if include_bonus {
    base_score + 5
} else {
    base_score
};

println!("style = {style}");
println!("score = {score}");

Waiting for the runtime to start.

各 Rust セルは必要な helper crate を宣言します。名前は crates/* 配下の Cargo package name と一致させます。

Rust + Wasm

Rust cell with multiple crates

Cell actions
Cell inputs
style
let points = doc_rust::logistic_series(3.2, 0.2, 8).map_err(|error| error.to_string())?;
let final_point = points.last().ok_or_else(|| "series is empty".to_owned())?;

println!("{}", doc_rust_text::labeled_value("final step", final_point.n));
println!("{}", doc_rust_text::labeled_value("final x", format!("{:.6}", final_point.x)));
println!("{}", doc_rust_text::style_note(style.as_str()));

Waiting for the runtime to start.

Python セルも同じ input metadata を使います。input value は Python 変数として使えます。

Python + Pyodide

Python input UI

Cell actions
Cell inputs
style
values = [1, 2, 3, 4]

if method == "sum":
    result = sum(values) * scale
elif method == "max":
    result = max(values) * scale
else:
    result = sum(values) / len(values) * scale

name = label.upper() if enabled else label
print(f"{name}: {method} = {result}")
print(f"style = {style}")

Waiting for the runtime to start.

Haskell セルは --| metadata comment を使います。input value は Haskell 変数になり、putStrLnprint の text output が結果 panel に表示されます。

Haskell + WASI

Haskell input UI

Cell actions
Cell inputs
{- Imports may use normal multiline Haskell layout. -}
import Data.List
  ( intercalate
  , sort
  )

let base = [1 .. 4 :: Int]
let scaled = map (* factor) base
let displayed = sort (if include_squares then map (\value -> value * value) scaled else scaled)

putStrLn (label ++ ": " ++ intercalate ", " (map show displayed))
putStrLn ("total = " ++ show (sum displayed))

Waiting for the runtime to start.

Python の初期化と package 読み込み中は「Python を準備中…」、執筆した code の実行中は「実行中…」と表示します。python.preload による page 単位の先読みは Python runtime asset を参照してください。