Inline math expressions

I wanted to write an inline mathematical expression, which isn’t possible using KaTeX Plug, but something that Lua expression should allow. Inspired by SXML (a very elegant encoding of DOM in lisp), I wrote up this minimal example, but adapted a bit to keep a similar shape of table as editor.parseMarkdown() returns. The function names correspond to MathML, which is the format that browsers can render and libraries like KaTeX translate into.

obraz

I just wanted this equation ${math(mn(1), mo("+"), mfrac(mi("H"), msup(mi("W"), mn(2))))} in the middle of a sentence.
Space Lua implementation
```space-lua
function xmlFromTree(tree)
  if tree.tag then
    local out = "<" .. tree.tag
    if tree.attributes then
      for k, v in pairs(tree.attributes) do
        out = out .. " " .. k .. '="' .. v .. '"'
      end
    end
    out = out .. ">"
    if tree.children then
      for _, child in ipairs(tree.children) do
        out = out .. xmlFromTree(child)
      end
    end
    out = out .. "</" .. tree.tag .. ">"
    return out
  elseif tree.text then
    return tree.text
  else
    error("Each node must have a tag or text")
  end
end

function math(...)
  return widget.new({
    html = xmlFromTree({ tag = "math", attributes = { display = "inline" }, children = {...} }),
    display = "inline"
  })
end

function mn(number)
  return { tag = "mn", children = { { text = tostring(number) }}}
end

function mo(operator)
  return { tag = "mo", children = { { text = tostring(operator) }}}
end

function mi(identifier)
  return { tag = "mi", children = { { text = tostring(identifier) }}}
end

function mfrac(numerator, denominator)
  return { tag = "mfrac", children = { numerator, denominator }}
end

function msup(base, superscript)
  return { tag = "msup", children = { base, superscript }}
end
```

This is similar to Mathematical expressions, but I don’t even try to parse anything at the cost of typing out the syntax tree manually.

4 Likes

Very nice, but the real interesting little nugget in there (to me) is that xmlFromTree function you sneaked in there. I had in mind doing something like this, just with a slightly different syntax. Now you make me want to prototype it…

@Maarrk

```space-lua
-- exposes html.randomTag {attribute="value", "body text"} API, rendering to string
html = setmetatable({}, {
  __index = function(self, attr)
    return function(spec)
      local code = "<" .. attr
      local bodyText = ""
      for key, val in pairs(spec) do
        if type(key) == "string" then
          -- This is an attribute
          code = code .. " " .. key .. "='" .. val .. "'"
        else
          -- Otherwise we'll consider it body text
          bodyText = bodyText .. val
        end
      end
      code = code .. ">"
      code = code .. bodyText .. "</" .. attr .. ">"
      return code
    end
  end
})
```

${widget.new {
  html = html.marquee {
    class="my-class",
    "Plain strings are just body text.",
    html.span {
      style = "color: red;",
      "And you can nest tags like this"
    },
  }
}}

Waddaya think? Gotta love Lua meta tables. Implementation needs some escaping stuff, just like yours, but you get the concept.

Oh wow, I expected something nicer to lurk on the dark side of the moon (get it?), but not this nice!

1 Like

Had to add a custom emoji to this Discourse instance: :lua: