Help us shape the future of Go! Take the 2026 Go Developer Survey

engine

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2026 License: BSD-3-Clause Imports: 22 Imported by: 0

Documentation

Overview

Package engine runs a Go notebook in an interpreter: the playground's core, the same in the browser (compiled to WebAssembly) and in tests.

A notebook is a Markdown document whose ```go blocks are cells, as github.com/go-notebook/notebook/format reads it. The cells run in document order, in one yaegi interpreter, so that what a cell defines is visible to the cells after it. The packages a cell may import are those of github.com/go-notebook/playground/symbols; their code is compiled, not interpreted, so a call into go-statistics or go-plot runs at native (or WebAssembly) speed and only the notebook's own code is interpreted.

The conventions are go-notebook's: a cell's final expression is shown; a final call returning (value, error) shows the value, or fails the cell with the error; a value that draws itself as SVG — a go-plot figure — is shown as a figure.

Index

Constants

View Source
const JuliaSupported = true

JuliaSupported reports whether this build checks Julia cells.

View Source
const MaxNotebook = 1 << 20

MaxNotebook is the largest notebook the page opens or edits, in bytes.

View Source
const RubySupported = true

RubySupported reports whether this build runs Ruby cells. The page's default WebAssembly core does not: it is built without them, and a notebook with a Ruby cell loads the core built with the tag ruby instead, so that a visitor who runs only Go never downloads the Ruby. Native builds have it wherever rbgo compiles, which since v0.8.3 is every GOOS/GOARCH but plan9 (go-embedded-ruby/ruby#832). wasip1 has no page to load a core into, so it stays with Go cells, as does plan9.

Variables

View Source
var Langs = []string{"go", "ruby", "julia"}

Langs are the languages a code cell may be in, as its fence names them (a Julia cell is parsed and checked, not run).

Functions

func Bundle

func Bundle(v any) map[string]string

Bundle returns the MIME bundle of a value. A figure is drawn as SVG only (Display would also rasterise it to PNG, which the page does not need); a displayer gives its own bundle, PNG in base64; anything else is its text. text/plain is always there.

func SanitizeSVG added in v0.2.0

func SanitizeSVG(in string) (out string, err error)

SanitizeSVG rewrites a figure keeping only what draws: an allowlist of SVG elements and attributes, written back by this code, so that nothing a cell shows can run code in the page or fetch anything. A cell's figure is data, even when the notebook came from someone else, and a Go value's SaveSVG or a Ruby cell can write any text at all.

What goes, by class:

  • scripts and anything that can hold them or HTML: script, style, foreignObject, iframe, and every element outside the allowlist, with its content (an <a> alone is unwrapped: its content stays);
  • event handlers and every attribute outside the allowlist;
  • animation (set, animate, animateMotion, animateTransform), which can change an attribute after this check;
  • external references: an href that is not a "#fragment" (or, on an <image>, an embedded PNG, JPEG or GIF), a url() that is not url(#…), and style properties outside the presentation allowlist;
  • comments, processing instructions and DOCTYPEs (entities).

The allowlist follows DOMPurify's SVG lists (src/tags.ts), narrower: <use> and <style>, which DOMPurify also refuses or rewrites, are dropped. A document that is not well-formed XML, too large or too deep, or whose root is not <svg>, is refused whole, with an error. Only the first root element is kept.

Types

type Cell

type Cell struct {
	// Kind is "prose" (Markdown) or "code".
	Kind string `json:"kind"`
	// Lang is a code cell's language: "go", "ruby" or "julia".
	Lang string `json:"lang,omitempty"`
	// Source is the cell's text, without the fences of a code cell.
	Source string `json:"source"`
}

Cell is a cell of a notebook, as the page shows it.

func Cells

func Cells(markdown string) []Cell

Cells splits a notebook into its cells, as go-notebook does.

type Edited added in v0.6.0

type Edited struct {
	Markdown string `json:"markdown"`
	Cells    []Cell `json:"cells"`
	// Focus is the cell the last operation leaves the reader on: the edited
	// or inserted cell, as the document now splits (a prose cell inserted
	// next to prose joins it), or the one after a deleted cell.
	Focus int `json:"focus"`
}

Edited is a notebook after edits.

func Edit added in v0.6.0

func Edit(markdown string, ops []Op) (Edited, error)

Edit applies ops, in order, to the cells of markdown as it parses, and writes the notebook back. The indices of every op refer to those cells: a prose edit that makes a new code fence splits the document only when it is parsed again, after the last op.

type Op added in v0.6.0

type Op struct {
	// Op is "source" (set Source), "lang" (set Lang: a language, or
	// "markdown" to make the cell prose), "insert" (a new cell before Index,
	// or at the end when Index is the number of cells), "delete", or "move"
	// (to the position To).
	Op     string `json:"op"`
	Index  int    `json:"index"`
	Source string `json:"source,omitempty"`
	Lang   string `json:"lang,omitempty"`
	To     int    `json:"to,omitempty"`
}

Op is one edit. Index counts every cell, prose included, as Cells returns them.

type Result

type Result struct {
	// Cell is the cell's index among the notebook's code cells.
	Cell int `json:"cell"`
	// Line is the line of the document where the cell's code starts.
	Line int `json:"line"`
	// Output is what the cell printed.
	Output string `json:"output,omitempty"`
	// Display holds what the cell showed, each value as a MIME bundle:
	// "text/plain", and "image/svg+xml" or "text/html" when the value has
	// that representation ("image/png" is base64).
	Display []map[string]string `json:"display,omitempty"`
	// Error is why the cell failed, with the line in the cell.
	Error string `json:"error,omitempty"`
	// Skipped reports a cell that did not run because one before it
	// failed.
	Skipped bool `json:"skipped,omitempty"`
	// Millis is how long the cell ran.
	Millis float64 `json:"ms"`
}

Result is what one code cell did.

func Run

func Run(markdown string) []Result

Run runs every code cell of a notebook in order and returns what each one did. A cell that fails stops the run: the cells after it are skipped, as their inputs may not be there.

func RunUpTo added in v0.6.0

func RunUpTo(markdown string, last int, started func(cell int)) []Result

RunUpTo runs the code cells of a notebook in order, up to the code cell last (counted among code cells, from 0) or every one when last is negative, and returns what each of those did. The playground keeps no values between runs and has no dependency graph to run a cell's dependents alone, so running one cell runs the cells above it first. started, when not nil, is called with each code cell's index as it starts: the page's time limit counts from there.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL