Module:DeclarativeUI

From the Star Citizen Wiki, the fidelity™ encyclopedia
Module documentation[view][edit][history][purge]
This documentation is transcluded from Module:DeclarativeUI/doc. Changes can be proposed in the talk page.
Function list
L 55 — iterateChildren
L 87 — element:render
L 101 — render

DeclarativeUI is an alternative to the existing Scribunto HTML library in the style of React's createElement.

createElement

Parameter Description Type Status
type Element tag string required
attributes Dictionary of attributes table<string, any> optional
...children Children element or table<element> or string optional
local createElement = require( 'Module:DeclarativeUI' )

-- You can create a simple element like this
createElement( 'div' ):render() -- <div/>

-- Add some attributes
createElement( 'div', { a = 'b' } ):render() -- <div a="b"/>

-- What about some text?
createElement( 'h1', nil, 'Scream!' ):render() -- <h1>Scream!</h1>

-- What about other elements?
local someElement = createElement( 'span', { style = 'color: red' }, 'Hello World' )
createElement( 'div', nil, 'This goes first', someElement ) -- <div>This goes first<span style="color: red">Hello World</span></div>

-- You can have as much children as you want
createElement( 'div', nil, 'a', 'b', 'c' ) -- <div>abc</div>

-- Code bundled using https://github.com/ari-party/scribunto-bundler
-- Find module source code at https://github.com/ari-party/sct-module-declarativeui
local _bundler_load, _bundler_register = (function(superRequire)
    local loadingPlaceholder = { [{}] = true }

    local register
    local modules = {}

    local load
    local loaded = {}

    ---@param name string
    ---@param body function
    register = function(name, body)
        if not modules[name] then
            modules[name] = body
        end
    end

    ---@param name string
    ---@return any
    load = function(name)
        local loadedModule = loaded[name]

        if loadedModule then
            if loadedModule == loadingPlaceholder then
                return nil
            end
        else
            if not modules[name] then
                if not superRequire then
                    local identifier = type(name) == 'string' and '\"' .. name .. '\"' or tostring(name)
                    error('Tried to require ' .. identifier .. ', but no such module has been registered')
                else
                    return superRequire(name)
                end
            end

            loaded[name] = loadingPlaceholder
            loadedModule = modules[name]()
            loaded[name] = loadedModule
        end

        return loadedModule
    end

    return load, register
end)(require)

_bundler_register('bundler_main', function()
    local render = _bundler_load("h8J-Dk7WgG3zsDJHmMUkB")

---@alias Element { type: string; attributes: table<string, any>; children: table, render?: function }

local function iterateChildren( child )
    local children = {}

    if type( child ) == 'table' and child[ 1 ] then
        for _, value in ipairs( iterateChildren( child ) ) do
            table.insert( children, value )
        end
    else
        table.insert( children, child )
    end

    return children
end

---@param type string HTML Tag
---@param attributes table<string, any>? HTML Attributes
---@param ... Element | Element[] | string
---@return Element
return function ( type, attributes, ... )
    local children = {}
    for _, child in ipairs( { ... } ) do
        for _, iteratedChild in ipairs( iterateChildren( child ) ) do
            table.insert( children, iteratedChild )
        end
    end

    local element = {
        type = type,
        attributes = attributes or {},
        children = children
    }

    function element:render()
        return render( element )
    end

    return element
end

end)

_bundler_register('h8J-Dk7WgG3zsDJHmMUkB', function()
    local xmlAttributes = _bundler_load("gwhNHWeA8kSzFpHIDE6Sk")

---@param element Element
---@return string rendered Rendered HTML
local function render( element )
    local attributes = table.concat( xmlAttributes( element.attributes ), ' ' )

    local segments = {}

    table.insert( segments, '<' .. element.type ) -- Partial opening tag
    if string.len( attributes ) > 0 then table.insert( segments, ' ' .. attributes ) end

    if #element.children == 0 then
        table.insert( segments, '/>' ) -- Closing 'tag'
    else
        table.insert( segments, '>' )  -- Finish opening tag

        local children = {}

        for _, child in ipairs( element.children ) do
            if type( child ) == 'table' then
                table.insert( children, render( child ) )
            else
                table.insert( children, tostring( child ) )
            end
        end

        table.insert( segments, table.concat( children, '' ) )

        table.insert( segments, '</' .. element.type .. '>' ) -- Closing tag
    end

    return table.concat( segments, '' )
end

return render

end)

_bundler_register('gwhNHWeA8kSzFpHIDE6Sk', function()
    ---@param input table<string, any>
---@return table<string> attributes
return function ( input )
    local attributes = {}

    for key, value in pairs( input ) do
        table.insert( attributes,
            key .. '="' .. string.gsub( tostring( value ), '"', '\\"' ) .. '"' )
    end

    return attributes
end

end)

return _bundler_load('bundler_main')
🍪 We use cookies to keep session information to provide you a better experience.