# Inline math expressions

**URL:** https://community.silverbullet.md/t/inline-math-expressions/2056
**Category:** Lua
**Created:** [March 27, 2025, 2:14pm UTC](https://community.silverbullet.md/t/inline-math-expressions/2056 "2025-03-27T14:14:22Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Maarrk](https://community.silverbullet.md/user_avatar/community.silverbullet.md/maarrk/32/56_2.png) [@Maarrk](https://community.silverbullet.md/u/Maarrk)
#### Post date: [March 27, 2025, 2:14pm UTC](https://community.silverbullet.md/t/inline-math-expressions/2056/1 "2025-03-27T14:14:22Z")

</div>

I wanted to write an inline mathematical expression, which isn’t possible using [KaTeX Plug](https://github.com/silverbulletmd/silverbullet-katex/issues/1), but something that Lua expression should allow. Inspired by [SXML](https://okmij.org/ftp/Scheme/SXML.html) (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](https://developer.mozilla.org/en-US/docs/Web/MathML), which is the format that browsers can render and libraries like KaTeX translate into.

![obraz](https://community.silverbullet.md/uploads/default/original/2X/7/766ab280ffbcb7e52b9f4c50a33d28577b1499a8.png)

```auto
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**
>
> ````auto
> ```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](https://community.silverbullet.md/t/mathematical-expressions/421), but I don’t even try to parse anything at the cost of typing out the syntax tree manually.

---

<div class="post-metadata">

### Author: ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)
#### Post date: [March 27, 2025, 5:38pm UTC](https://community.silverbullet.md/t/inline-math-expressions/2056/2 "2025-03-27T17:38:02Z")

</div>

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…

---

<div class="post-metadata">

### Author: ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)
#### Post date: [March 27, 2025, 5:53pm UTC](https://community.silverbullet.md/t/inline-math-expressions/2056/3 "2025-03-27T17:53:47Z")

</div>

@Maarrk

````auto
```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.

---

<div class="post-metadata">

### Author: ![Maarrk](https://community.silverbullet.md/user_avatar/community.silverbullet.md/maarrk/32/56_2.png) [@Maarrk](https://community.silverbullet.md/u/Maarrk)
#### Post date: [March 27, 2025, 6:05pm UTC](https://community.silverbullet.md/t/inline-math-expressions/2056/4 "2025-03-27T18:05:16Z")

</div>

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

---

<div class="post-metadata">

### Author: ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)
#### Post date: [March 27, 2025, 6:09pm UTC](https://community.silverbullet.md/t/inline-math-expressions/2056/5 "2025-03-27T18:09:42Z")

</div>

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