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 ¶
const JuliaSupported = true
JuliaSupported reports whether this build checks Julia cells.
const MaxNotebook = 1 << 20
MaxNotebook is the largest notebook the page opens or edits, in bytes.
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 ¶
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 ¶
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
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.
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.
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 ¶
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
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.