lua/onthefly/onthefly.go
Rama main · réplica de lectura del repositorio original.
// Package onthefly provides Lua functions for building HTML, XML and TinySVG documents
package onthefly
import (
"errors"
"github.com/sirupsen/logrus"
lua "github.com/xyproto/gopher-lua"
"github.com/xyproto/onthefly"
"github.com/xyproto/tinysvg"
)
const (
// PageClass is an identifier for the Page class in Lua
PageClass = "Page"
// TagClass is an identifier for the Tag class in Lua
TagClass = "Tag"
)
// Get the first argument, "self", and cast it from userdata to a Tag.
func checkTag(L *lua.LState) *onthefly.Tag {
ud := L.CheckUserData(1)
if tag, ok := ud.Value.(*onthefly.Tag); ok {
return tag
}
L.ArgError(1, "Tag expected")
return nil
}
// Get the first argument, "self", and cast it from userdata to a Page.
func checkPage(L *lua.LState) *onthefly.Page {
ud := L.CheckUserData(1)
if page, ok := ud.Value.(*onthefly.Page); ok {
return page
}
L.ArgError(1, "Page expected")
return nil
}
// pushSelf re-pushes the first argument (self) so that setters can be chained.
// Always returns 1, to be used as the return value of a Lua function.
func pushSelf(L *lua.LState) int {
L.Push(L.Get(1))
return 1
}
// pushTag wraps the given Tag in a Lua userdata with the Tag metatable.
// Pushes nil if the given Tag is nil.
func pushTag(L *lua.LState, tag *onthefly.Tag) {
if tag == nil {
L.Push(lua.LNil)
return
}
ud := L.NewUserData()
ud.Value = tag
L.SetMetatable(ud, L.GetTypeMetatable(TagClass))
L.Push(ud)
}
// Create a new onthefly.Tag node.
// Logs an error if the given tag name is empty.
// Always returns a Tag userdata.
func constructTag(L *lua.LState) (*lua.LUserData, error) {
// Use the first argument as the name of the tag
name := L.ToString(1)
if name == "" {
L.ArgError(1, "tag name expected")
return nil, errors.New("tag name expected")
}
// Create a new onthefly.Tag
tag := onthefly.NewTag(name)
// Create a new userdata struct
ud := L.NewUserData()
ud.Value = tag
L.SetMetatable(ud, L.GetTypeMetatable(TagClass))
return ud, nil
}
// Create a new HTML5 onthefly.Page.
func constructHTML5Page(L *lua.LState) (*lua.LUserData, error) {
// Use the first argument as the title of the page
title := L.ToString(1)
// Create a new HTML5 Page
page := onthefly.NewHTML5Page(title)
// Create a new userdata struct
ud := L.NewUserData()
ud.Value = page
L.SetMetatable(ud, L.GetTypeMetatable(PageClass))
return ud, nil
}
// Construct a TinySVG document that is wrapped in a Page-compatible userdata.
// NOTE: tinysvg.Document is a separate type from onthefly.Page, so only
// __tostring works on the returned userdata. Use this for SVG generation only.
func constructTinySVGPage(L *lua.LState) (*lua.LUserData, error) {
// Use the first arguments as the width and height of the SVG
w := L.ToInt(1)
h := L.ToInt(2)
description := L.ToString(3)
// Create a new TinySVG Page
document, svgTag := tinysvg.NewTinySVG(w, h)
svgTag.Describe(description)
// Create a new userdata struct
ud := L.NewUserData()
ud.Value = document
L.SetMetatable(ud, L.GetTypeMetatable(PageClass))
return ud, nil
}
// Create a new onthefly.Page
func constructPage(L *lua.LState) (*lua.LUserData, error) {
// Use the first argument as the title of the page
title := L.ToString(1)
if title == "" {
L.ArgError(1, "page title expected")
return nil, errors.New("page title expected")
}
// Use the second argument as the name of the root tag
rootTagName := L.ToString(2)
if rootTagName == "" {
L.ArgError(2, "root tag name expected")
return nil, errors.New("root tag name expected")
}
// Create a new onthefly.Page
page := onthefly.NewPage(title, rootTagName)
// Create a new userdata struct
ud := L.NewUserData()
ud.Value = page
L.SetMetatable(ud, L.GetTypeMetatable(PageClass))
return ud, nil
}
// Load makes functions related to onthefly.Page nodes available to the given Lua state
func Load(L *lua.LState) {
// Register the Page class and the methods that belongs with it.
metaTablePage := L.NewTypeMetatable(PageClass)
metaTablePage.RawSetH(lua.LString("__index"), metaTablePage)
L.SetFuncs(metaTablePage, pageMethods)
// Register the Tag class and the methods that belongs with it.
metaTableTag := L.NewTypeMetatable(TagClass)
metaTableTag.RawSetH(lua.LString("__index"), metaTableTag)
L.SetFuncs(metaTableTag, tagMethods)
// The constructor for Page
L.SetGlobal("Page", L.NewFunction(func(L *lua.LState) int {
// Construct a new Page
userdata, err := constructPage(L)
if err != nil {
logrus.Error(err)
L.Push(lua.LString(err.Error()))
return 1 // Number of returned values
}
// Return the Lua Page object
L.Push(userdata)
return 1 // number of results
}))
// The constructor for HTML5 returns a Page
L.SetGlobal("HTML5", L.NewFunction(func(L *lua.LState) int {
// Construct a new Page
userdata, err := constructHTML5Page(L)
if err != nil {
logrus.Error(err)
L.Push(lua.LString(err.Error()))
return 1 // Number of returned values
}
// Return the Lua Page object
L.Push(userdata)
return 1 // number of results
}))
// The constructor for TinySVG returns a Page
L.SetGlobal("TinySVG", L.NewFunction(func(L *lua.LState) int {
// Construct a new Page
userdata, err := constructTinySVGPage(L)
if err != nil {
logrus.Error(err)
L.Push(lua.LString(err.Error()))
return 1 // Number of returned values
}
// Return the Lua Page object
L.Push(userdata)
return 1 // number of results
}))
// The constructor for Tag
L.SetGlobal("Tag", L.NewFunction(func(L *lua.LState) int {
// Construct a new Tag
userdata, err := constructTag(L)
if err != nil {
logrus.Error(err)
L.Push(lua.LString(err.Error()))
return 1 // Number of returned values
}
// Return the Lua Tag object
L.Push(userdata)
return 1 // number of results
}))
}