vugu: github.com/vugu/vugu Index | Examples | Files | Directories

package vugu

import "github.com/vugu/vugu"

Package vugu provides core functionality including vugu->go codegen and in-browser DOM syncing running in WebAssembly. See http://www.vugu.org/

Since Vugu projects can have both client-side (running in WebAssembly) as well as server-side functionality many of the items in this package are available in both environments. Some however are either only available or only generally useful in one environment.

Common functionality includes the ComponentType interface, and ComponentInst struct corresponding to an instantiated componnet. VGNode and related structs are used to represent a virtual Document Object Model. It is based on golang.org/x/net/html but with additional fields needed for Vugu. Data hashing is performed by ComputeHash() and can be customized by implementing the DataHasher interface.

Client-side code uses JSEnv to maintain a render loop and regenerate virtual DOM and efficiently synchronize it with the browser as needed. DOMEvent is a wrapper around events from the browser and EventEnv is used to synchronize data access when writing event handler code that spawns goroutines. Where appropriate, server-side stubs are available so components can be compiled for both client (WebAssembly) and server (server-side rendering and testing).

Server-side code can use ParserGo and ParserGoPkg to parse .vugu files and code generate a corresponding .go file. StaticHTMLEnv can be used to generate static HTML, similar to the output of JSEnv but can be run on the server. Supported features are approximately the same minus event handling, unapplicable to static output.

Index

Examples

Package Files

build-env.go change-counter.go comp-key.go component.go data-hasher.go doc.go events-component.go events-dom.go mod-check.go parser-compact.go parser-go-pkg.go parser-go.go parser-util.go renderer-js-instructions.go renderer-js-script.go renderer-js.go renderer-static.go renderer.go vgnode.go

Constants

const (
    ErrorNode    = VGNodeType(0)
    TextNode     = VGNodeType(1)
    DocumentNode = VGNodeType(2)
    ElementNode  = VGNodeType(3)
    CommentNode  = VGNodeType(4)
    DoctypeNode  = VGNodeType(5)
)

Available VGNodeTypes.

func ComputeHash Uses

func ComputeHash(i interface{}) uint64

ComputeHash performs data hashing. It walks your data structure and hashes the information as it goes. It uses xxhash internally and returns a uint64. It is intended to be both fast and have good hash distribution to avoid collision-related bugs. Maps are sorted by key and then both keys and values are hashed. Nil values are skipped. Behavior is undefined for circular references via interface or pointer. Will call DataHash() method if present (see DataHasher) on a type. Otherwise will walk the data and find primitive values and hash them byte for byte. No guarantee is made about the exact hash algorithm used or how type information is or is not hashed - only that the same data structure should consistently hash to the same value and changing any value in the data tree should change the hash.

Code:

type D struct {
    A string
}
data1 := &D{A: "test1"}
data2 := &D{A: "test2"}

fmt.Println(ComputeHash(data1) == ComputeHash(data1))
fmt.Println(ComputeHash(data1) == ComputeHash(data2))

Output:

true
false

func MakeCompKeyID Uses

func MakeCompKeyID(t time.Time, data uint32) uint64

MakeCompKeyID forms a value for CompKey.ID from the given time the uint32 you provide for the lower 32 bits.

func MakeCompKeyIDNowRand Uses

func MakeCompKeyIDNowRand() uint64

MakeCompKeyIDNowRand generates a value for CompKey.ID based on the current unix timestamp in seconds for the top 32 bits and the bottom 32 bits populated from crypto/rand

func MakeCompKeyIDTimeHash Uses

func MakeCompKeyIDTimeHash(t time.Time, b []byte) uint64

MakeCompKeyIDTimeHash forms a value for CompKey.ID from the given time and a hash of the bytes you provide.

type BeforeBuilder Uses

type BeforeBuilder interface {
    BeforeBuild()
}

BeforeBuilder can be implemented by components that need a chance to compute internal values after properties have been set but before Build is called.

type BuildEnv Uses

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

BuildEnv is the environment used when building virtual DOM.

func NewBuildEnv Uses

func NewBuildEnv() (*BuildEnv, error)

func (*BuildEnv) CachedComponent Uses

func (e *BuildEnv) CachedComponent(compKey CompKey) Builder

CachedComponent will return the component that corresponds to a given CompKey. The CompKey must contain a unique ID for the instance in question, and an optional IterKey if applicable in the caller. A nil value will be returned if nothing is found. During a single build pass only one component will be returned for a specified key (it is removed from the pool), in order to protect against broken callers that accidentally forget to set IterKey properly and ask for the same component over and over, in whiich case the first call will return a value and subsequent calls will return nil.

func (*BuildEnv) RunBuild Uses

func (e *BuildEnv) RunBuild(builder Builder) *BuildResults

RunBuild performs a bulid on a component, managing the lifecycles of nested components and related concerned. In the map that is output, m[builder] will give the BuildOut for the component in question. Child components can likewise be indexed using the component (which should be a struct pointer) as the key. Callers should not modify the return value as it is reused by subsequent calls.

func (*BuildEnv) UseComponent Uses

func (e *BuildEnv) UseComponent(compKey CompKey, component Builder)

UseComponent indicates the component which was actually used for a specified CompKey during this build pass and stores it for later use. In the next build pass, components which have be provided UseComponent() will be available via CachedComponent().

type BuildIn Uses

type BuildIn struct {
    BuildEnv *BuildEnv
}

BuildIn is the input to a Build call.

type BuildOut Uses

type BuildOut struct {

    // output element(s) - usually just one that is parent to the rest but slots can have multiple
    Out []*VGNode

    // components that need to be built next - corresponding to each VGNode in Out with a Component value set,
    // we make the Builder populate this so BuildEnv doesn't have to traverse Out to gather up each node with a component
    // FIXME: should this be called ChildComponents, NextComponents? something to make it clear that these are pointers to more work to
    // do rather than something already done
    Components []Builder

    // optional CSS style or link tag(s)
    CSS []*VGNode

    // optional JS script tag(s)
    JS  []*VGNode
}

BuildOut is the output from a Build call. It includes Out as the DOM elements produced, plus slices for CSS and JS elements.

func (*BuildOut) AppendCSS Uses

func (b *BuildOut) AppendCSS(nlist ...*VGNode)

AppendCSS will append a unique node to CSS (nodes match exactly will not be added again).

func (*BuildOut) AppendJS Uses

func (b *BuildOut) AppendJS(nlist ...*VGNode)

AppendJS will append a unique node to JS (nodes match exactly will not be added again).

type BuildResults Uses

type BuildResults struct {
    Out    *BuildOut
    AllOut map[interface{}]*BuildOut
}

BuildResults contains the BuildOut values for full tree of components built.

func (*BuildResults) ResultFor Uses

func (r *BuildResults) ResultFor(component interface{}) *BuildOut

ResultFor is alias for indexing into AllOut.

type Builder Uses

type Builder interface {
    // Build is called to construct a tree of VGNodes corresponding to the DOM of this component.
    // Note that Build does not return an error because there is nothing the caller can do about
    // it except for stop rendering.  This way we force errors during Build to either be handled
    // internally or to explicitly result in a panic.
    Build(in *BuildIn) (out *BuildOut)
}

Builder is the interface that components implement.

type BuilderFunc Uses

type BuilderFunc func(in *BuildIn) (out *BuildOut)

BuilderFunc is a Build-like function that implements Builder.

func (BuilderFunc) Build Uses

func (f BuilderFunc) Build(in *BuildIn) (out *BuildOut)

Build implements Builder.

type ChangeCounter Uses

type ChangeCounter int

ChangeCounter is a number that can be incremented to indicate modification. The ModCheck method is implemented using this number. A ChangeCounter can be used directly or embedded in a struct, with its methods calling Changed on each mutating operation, in order to track its modification.

func (*ChangeCounter) Changed Uses

func (c *ChangeCounter) Changed()

Changed increments the counter to indicate a modification.

func (*ChangeCounter) ModCheck Uses

func (c *ChangeCounter) ModCheck(mt *ModTracker, oldData interface{}) (isModified bool, newData interface{})

ModCheck implements the ModChecker interface.

type CompKey Uses

type CompKey struct {
    ID      uint64      // unique ID for this instance of a component, randomly generated and embeded into source code
    IterKey interface{} // optional iteration key to distinguish the same component reference in source code but different loop iterations
}

CompKey is the key used to identify and look up a component instance.

type DOMEvent Uses

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

DOMEvent is an event originated in the browser. It wraps the JS event that comes in. It is meant to be used in WebAssembly but some methods exist here so code can compile server-side as well (although DOMEvents should not ever be generated server-side).

func (*DOMEvent) EventEnv Uses

func (e *DOMEvent) EventEnv() EventEnv

EventEnv returns the EventEnv for the current environment and allows locking and unlocking around modifications. See EventEnv struct.

func (*DOMEvent) EventSummary Uses

func (e *DOMEvent) EventSummary() map[string]interface{}

EventSummary returns a map with simple properties (primitive types) from the event. Accessing values returns by EventSummary incurs no additional performance or memory penalty, whereas calls to JSEvent, JSEventTarget, etc. require a call into the browser JS engine and the attendant resource usage. So if you can get the information you need from the EventSummary, that's better.

func (*DOMEvent) JSEvent Uses

func (e *DOMEvent) JSEvent() js.Value

JSEvent this returns a js.Value in wasm that corresponds to the event object. Non-wasm implementation returns nil.

func (*DOMEvent) JSEventCurrentTarget Uses

func (e *DOMEvent) JSEventCurrentTarget() js.Value

JSEventCurrentTarget returns the value of the "currentTarget" property of the event, the element that is currently processing the event.

func (*DOMEvent) JSEventTarget Uses

func (e *DOMEvent) JSEventTarget() js.Value

JSEventTarget returns the value of the "target" property of the event, the element that the event was originally fired/registered on.

func (*DOMEvent) PreventDefault Uses

func (e *DOMEvent) PreventDefault()

PreventDefault calls preventDefault() on the underlying DOM event. May only be used within event handler in same goroutine.

func (*DOMEvent) Prop Uses

func (e *DOMEvent) Prop(keys ...string) interface{}

Prop returns a value from the EventSummary using the keys you specify. The keys is a list of map keys to be looked up. For example: e.Prop("target", "name") will return the same value as e.EventSummary()["target"]["name"], except that Prop helps with some edge cases and if a value is missing of the wrong type, nil will be returned, instead of panicing.

func (*DOMEvent) PropBool Uses

func (e *DOMEvent) PropBool(keys ...string) bool

PropBool is like Prop but returns it's value as a bool. No type conversion is done, if the requested value is not already a bool then false will be returned.

func (*DOMEvent) PropFloat64 Uses

func (e *DOMEvent) PropFloat64(keys ...string) float64

PropFloat64 is like Prop but returns it's value as a float64. No type conversion is done, if the requested value is not already a float64 then float64(0) will be returned.

func (*DOMEvent) PropString Uses

func (e *DOMEvent) PropString(keys ...string) string

PropString is like Prop but returns it's value as a string. No type conversion is done, if the requested value is not already a string then an empty string will be returned.

func (*DOMEvent) StopPropagation Uses

func (e *DOMEvent) StopPropagation()

StopPropagation calls stopPropagation() on the underlying DOM event. May only be used within event handler in same goroutine.

type DOMEventHandlerSpec Uses

type DOMEventHandlerSpec struct {
    EventType string // "click", "mouseover", etc.
    Func      func(*DOMEvent)
    Capture   bool
    Passive   bool
}

type DataHasher Uses

type DataHasher interface {
    DataHash() uint64
}

DataHasher can be implemented by types to override the hashing behavior. ComputeHash() will call DataHash() on an instance of a type if the method is present. Useful for providing fast and stable hashing for structures that are large but only require a small amount data to be examined to determine if changed, or are already hashed internally, etc.

type EventEnv Uses

type EventEnv interface {
    Lock()         // acquire write lock
    UnlockOnly()   // release write lock
    UnlockRender() // release write lock and request re-render

    RLock()   // acquire read lock
    RUnlock() // release read lock
}

EventEnv provides locking mechanism to for rendering environment to events so data access and rendering can be synchronized and avoid race conditions.

type JSRenderer Uses

type JSRenderer struct {
    MountPointSelector string
    // contains filtered or unexported fields
}

JSRenderer implements Renderer against the browser's DOM.

func NewJSRenderer Uses

func NewJSRenderer(mountPointSelector string) (*JSRenderer, error)

NewJSRenderer will create a new JSRenderer with the speicifc mount point selector. If an empty string is passed then the root component should include a top level <html> tag and the entire page will be rendered.

func (*JSRenderer) EventEnv Uses

func (r *JSRenderer) EventEnv() EventEnv

EventEnv returns an EventEnv that can be used for synchronizing updates.

func (*JSRenderer) EventWait Uses

func (r *JSRenderer) EventWait() (ok bool)

EventWait blocks until an event has occurred which causes a re-render. It returns true if the render loop should continue or false if it should exit.

func (*JSRenderer) Release Uses

func (r *JSRenderer) Release()

Release calls release on any resources that this renderer allocated.

func (*JSRenderer) Render Uses

func (r *JSRenderer) Render(buildResults *BuildResults) error

Render implements Renderer.

type ModChecker Uses

type ModChecker interface {
    ModCheck(mt *ModTracker, oldData interface{}) (isModified bool, newData interface{})
}

ModChecker interface is implemented by types that want to implement their own modification tracking. The ModCheck method is passed a ModTracker (for use in checking child values for modification if needed), and the prior data value stored corresponding to this value (will be nil on the first call). ModCheck should return true if this instance is modified, as well as a new data value to be stored. It is up to the specific implementation to decide what type to use for oldData and newData and how to compare them. In some cases it may be appropriate to return the value itself or a summarized version of it. But for types that use lots of memory and would otherwise take too much time to traverse, a counter or other value can be used to indicate that some changed is occured, with the rest of the application using mutator methods to increment this value upon change.

type ModTracker Uses

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

ModTracker tracks modifications and maintains the appropriate state for this.

func NewModTracker Uses

func NewModTracker() *ModTracker

NewModTracker creates an empty ModTracker, calls TrackNext on it, and returns it.

func (*ModTracker) ModCheckAll Uses

func (mt *ModTracker) ModCheckAll(values ...interface{}) (ret bool)

ModCheckAll performs a modification check on the values provided. For values implementing the ModChecker interface, the ModCheck method will be called. All values passed should be pointers to the types described below. Single-value primitive types are supported. Structs are supported and and are traversed by calling ModCheckAll on each with the tag `vugu:"modcheck"`. Arrays and slices of supported types are supported, their length is compared as well as a pointer to each member. As a special case []byte is treated like a string. Maps are not supported at this time. Other weird and wonderful things like channels and funcs are not supported. Passing an unsupported type will result in a panic.

func (*ModTracker) TrackNext Uses

func (mt *ModTracker) TrackNext()

TrackNext moves the "current" information to the "old" position - starting a new round of change tracking. Calls to ModCheckAll after calling TrackNext will compare current values to the values from before the call to TrackNext. It is generally called once at the start of each build and render cycle. This method must be called at least once before doing modification checks.

type ParserGo Uses

type ParserGo struct {
    PackageName   string // name of package to use at top of files
    StructType    string // just the struct name, no "*" (replaces ComponentType and DataType)
    ComponentType string // just the struct name, no "*"
    DataType      string // just the struct name, no "*"
    OutDir        string // output dir
    OutFile       string // output file name with ".go" suffix

    NoOptimizeStatic bool // set to true to disable optimization of static blocks of HTML into vg-html expressions
}

ParserGo is a template parser that emits Go source code that will construct the appropriately wired VGNodes.

func (*ParserGo) Parse Uses

func (p *ParserGo) Parse(r io.Reader, fname string) error

Parse is an experiment... r is the actual input, fname is only used to emit line directives

type ParserGoPkg Uses

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

ParserGoPkg knows how to perform source file generation in relation to a package folder. Whereas ParserGo handles converting a single template, ParserGoPkg is a higher level interface and provides the functionality of the vugugen command line tool. It will scan a package folder for .vugu files and convert them to .go, with the appropriate defaults and logic.

func NewParserGoPkg Uses

func NewParserGoPkg(pkgPath string, opts *ParserGoPkgOpts) *ParserGoPkg

NewParserGoPkg returns a new ParserGoPkg with the specified options or default if nil. The pkgPath is required and must be an absolute path.

func (*ParserGoPkg) Run Uses

func (p *ParserGoPkg) Run() error

Run does the work and generates the appropriate .go files from .vugu files. It will also create a go.mod file if not present and not SkipGoMod. Same for main.go and SkipMainGo (will also skip if package already has file with package name something other than main). Per-file code generation is performed by ParserGo.

type ParserGoPkgOpts Uses

type ParserGoPkgOpts struct {
    SkipRegisterComponentTypes bool // indicates func init() { vugu.RegisterComponentType(...) } code should not be emitted in each file
    SkipGoMod                  bool // do not try and create go.mod if it doesn't exist
    SkipMainGo                 bool // do not try and create main_wasm.go if it doesn't exist in a main package
}

ParserGoPkgOpts is the options for ParserGoPkg.

type Renderer Uses

type Renderer interface {
    Render(b *BuildOut) error
}

Renderer takes a BuildOut ("virtual DOM") and renders it to it's final output.

type StaticRenderer Uses

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

func NewStaticRenderer Uses

func NewStaticRenderer(w io.Writer) *StaticRenderer

func (*StaticRenderer) Render Uses

func (r *StaticRenderer) Render(buildResults *BuildResults) error

func (*StaticRenderer) SetWriter Uses

func (r *StaticRenderer) SetWriter(w io.Writer)

type VGAttribute Uses

type VGAttribute struct {
    Namespace, Key, Val string
}

VGAttribute is the attribute on an HTML tag.

type VGNode Uses

type VGNode struct {
    Parent, FirstChild, LastChild, PrevSibling, NextSibling *VGNode

    Type VGNodeType
    // DataAtom  VGAtom // this needed to come out, we're not using it and without well-defined behavior it just becomes confusing and problematic
    Data      string
    Namespace string
    Attr      []VGAttribute

    // JS properties to e set during render
    Prop []VGProperty

    InnerHTML *string // indicates that children should be ignored and this raw HTML is the children of this tag; nil means not set, empty string means explicitly set to empty string

    DOMEventHandlerSpecList []DOMEventHandlerSpec // replacing DOMEventHandlers

    // indicates this node's output should be delegated to the specified component
    Component interface{}
}

VGNode represents a node from our virtual DOM with the dynamic parts wired up into functions.

func (*VGNode) AppendChild Uses

func (n *VGNode) AppendChild(c *VGNode)

AppendChild adds a node c as a child of n.

It will panic if c already has a parent or siblings.

func (*VGNode) InsertBefore Uses

func (n *VGNode) InsertBefore(newChild, oldChild *VGNode)

InsertBefore inserts newChild as a child of n, immediately before oldChild in the sequence of n's children. oldChild may be nil, in which case newChild is appended to the end of n's children.

It will panic if newChild already has a parent or siblings.

func (*VGNode) RemoveChild Uses

func (n *VGNode) RemoveChild(c *VGNode)

RemoveChild removes a node c that is a child of n. Afterwards, c will have no parent and no siblings.

It will panic if c's parent is not n.

func (*VGNode) Walk Uses

func (vgn *VGNode) Walk(f func(*VGNode) error) error

Walk will walk the tree under a VGNode using the specified callback function. If the function provided returns a non-nil error then walking will be stopped and this error will be returned. Only FirstChild and NextSibling are used while walking and so with well-formed documents should not loop. (But loops created manually by modifying FirstChild or NextSibling pointers could cause this function to recurse indefinitely.) Note that f may modify nodes as it visits them with predictable results as long as it does not modify elements higher on the tree (up, toward the parent); it is safe to modify self and children.

type VGNodeType Uses

type VGNodeType uint32

VGNodeType is one of the valid node types (error, text, document, element, comment, doctype). Note that only text, element and comment are currently used.

type VGProperty Uses

type VGProperty struct {
    Key string
    Val json.RawMessage
}

VGProperty is a JS property to be set on a DOM element.

Directories

PathSynopsis
cmd/vugufmt
cmd/vugugenvugugen is a command line tool to convert .vugu files into Go source code.
distutilPackage distutil has some useful functions for building your Vugu application's distribution
internal/htmlxPackage htmlx is a fork of https://github.com/golang/net/html.
internal/htmlx/atomPackage atom provides integer codes (also known as atoms) for a fixed set of frequently occurring HTML strings: tag names and attribute keys such as "p" and "id".
internal/htmlx/charsetPackage charset provides common text encodings for HTML documents.
jsPackage js is a drop-in replacement for syscall/js that provides identical behavior in a WebAssembly environment, and useful non-functional behavior outside of WebAssembly.
simplehttpPackage simplehttp provides an http.Handler that makes it easy to serve Vugu applications.
vugufmtPackage vugufmt provides gofmt-like functionality for vugu files.

Package vugu imports 32 packages (graph) and is imported by 2 packages. Updated 2019-11-11. Refresh now. Tools for package owners.