playground

package
v0.0.0 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: UNKNOWN not legal advice Imports: 0 Imported by: 0

Documentation

Overview

Package playground implements the gnoweb playground feature.

It serves the playground page at /_/play, which opens an editable copy of a package with ?from=<pkgpath> (its source files, one tab each), and the /_/api/eval endpoint the playground and the action page evaluate through.

Index

Constants

View Source
const MaxCopySourceBytes = 1 << 20

MaxCopySourceBytes caps the sources a copy shows, which the page carries as text.

Variables

View Source
var (
	ErrEvalUnavailable = errors.New("the node is unavailable, try again later")
	ErrEvalTimeout     = errors.New("the node did not answer the evaluation in time")
)

The errors a ClientAdapter wraps when an eval failed for a reason that says nothing about the expression. serveEval answers them with a generic message, never the transport detail.

View Source
var (
	ErrPackageNotFound = errors.New("package not found")
	ErrPackageTooLarge = errors.New("package source is too large to open in the playground")
	ErrPackageTimeout  = errors.New("the node did not send the package in time")
)

Errors a PackageFetcher answers with, so the copy page answers as the package's own pages do.

View Source
var PageTemplate = template.Must(template.New("").ParseFS(templateFS, "templates/page.html"))

PageTemplate is the standalone playground page. Pre-parsed at init so a misconfigured template surfaces immediately, not on the first request.

Functions

func CopyURL

func CopyURL(pkgPath, file string) string

CopyURL is the playground URL that opens an editable copy of the package at pkgPath, showing file first when set.

func InCopy

func InCopy(name string) bool

InCopy reports whether a copy opens a package's file: its Gno sources and gnomod.toml, without the filetests, of which a package can hold hundreds.

func NewPageView

func NewPageView(data PlaygroundData) *components.View

NewPageView wraps the playground template.

func ParseFrom

func ParseFrom(domain, from string) *weburl.GnoURL

ParseFrom reads a ?from= value: the bare path of a realm or a pure package, with or without the chain domain. It is nil for anything else, a file, args, a query, a user page or a listing, which no copy opens.

func RelPath

func RelPath(domain, p string) string

RelPath strips the chain domain and slashes from a package path: "gno.land/r/demo/foo", "/r/demo/foo" and "r/demo/foo" all give "r/demo/foo".

Types

type ClientAdapter

type ClientAdapter interface {
	// Eval evaluates expr inside pkgPath through vm/qeval. pkgPath carries
	// no domain: the client adds its own.
	Eval(ctx context.Context, pkgPath, expr string) ([]byte, error)
}

ClientAdapter is the subset of the gnoweb chain-client interface that the playground feature consumes. Declared locally so feature/playground does not import the gnoweb package; gnoweb's adapter maps its client's errors onto ErrEvalTimeout and ErrEvalUnavailable.

type Deps

type Deps struct {
	Client ClientAdapter
	Logger *slog.Logger

	// Packages reads the package a copy opens.
	Packages PackageFetcher

	// Domain is the chain domain (e.g. "gno.land").
	Domain string

	// Limiter bounds the per-client eval rate. Optional; nil disables the
	// check.
	Limiter Limiter

	// Timeout bounds one eval, like the deadline pages render under.
	// Zero means defaultEvalTimeout.
	Timeout time.Duration
}

Deps gathers the dependencies the playground Handler needs.

type File

type File struct {
	Name    string `json:"name"`
	Content string `json:"content"`
}

File is one file of a package, as a copy hands it to the editor.

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler owns the playground feature state.

func New

func New(deps Deps) *Handler

New validates required deps and returns a Handler. If empty Domain defaults to "gno.land" and Logger defaults the standard Go library's logger. It panics if Client or Packages is not specified.

func (*Handler) EvalHandler

func (h *Handler) EvalHandler() http.Handler

EvalHandler returns the http.Handler for POST /_/api/eval.

func (*Handler) GetPlaygroundView

func (h *Handler) GetPlaygroundView(ctx context.Context, u *weburl.GnoURL) (int, *components.View)

GetPlaygroundView serves /_/play: ?from=<pkgpath> opens an editable copy of that package, ?code= a shared snippet, and nothing the default code.

type Limiter

type Limiter interface {
	AllowRequest(r *http.Request) bool
}

Limiter is the admission check applied to each eval request. It takes the request, not an address: which address to trust depends on which proxies to trust, and that rule belongs with the limiter.

type PackageFetcher

type PackageFetcher interface {
	PackageFiles(ctx context.Context, pkgPath string) ([]File, error)
}

PackageFetcher reads the files of a package InCopy selects, up to MaxCopySourceBytes. It answers the ErrPackage errors for what they name.

type PlaygroundData

type PlaygroundData struct {
	// Files is the code the editor opens, one <pre> per file: a package
	// copy (?from=), a shared snippet (?code=) or the default code.
	Files []File

	// From is the copied package's path without its domain (r/demo/foo),
	// empty for anything but a copy.
	From string

	// Domain is the chain domain.
	Domain string

	// DefaultFile is the filename that should be focused on first load.
	DefaultFile string

	// Refused says why the ?code= link was not opened, when it was not:
	// the page shows the default code, and says so.
	Refused string

	// Preview is true when Run shows what the copied realm renders,
	// instead of the commands that run the code locally.
	Preview bool
}

PlaygroundData is the render payload for templates/page.html.

Jump to

Keyboard shortcuts

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