matchSubTag(tbl, tag)

-- Define a Boolean function that returns true iff
-- the desired <tag> is in the <tbl> or 
-- some <value> in <tbl> starts with <tag>. 
-- The <tbl> is the <tags> of a page.
function matchSubTag(tbl, tag)
  for _, value in ipairs(tbl) do -- The variable _ is the table index.
    if value == tag or string.startsWith(value,tag) then
      return true
    end
  end
  return false
end

noteLink

function pdfLink(path)
  local base = js.window.location.origin
  local name = path:match("([^/]+)$")
  local url
  if base:find("localhost") then
  url = base.."/.fs/"..path
  else
  url = "https://static.wentaoli.xyz/"..path
  end
return "["..name.."]("..url..")"
end

-- function noteLink(noteName) -- Use with just the note project title, no .pdf
    --local base = js.window.location.origin
    --local notePath = base.."/.fs/typeset-notes/"..noteName.."/"..noteName..".pdf"
   -- return "["..noteName..".pdf]("..notePath..")"
-- end

function noteLink(noteName)
  local base = js.window.location.origin
  local notePath

  if base:find("localhost") then
    notePath = base .. "/.fs/typeset-notes/"..noteName.."/"..noteName..".pdf"
  else
    notePath = "https://static.wentaoli.xyz/typeset-notes/"..noteName.."/"..noteName..".pdf"
  end

  return "["..noteName..".pdf]("..notePath..")"
end

function refLink(refName) -- Use with just the reference title, no .pdf
    local base = js.window.location.origin
    local refPath  -- = base.."/.fs/Refs/"..refName..".pdf"

    if base:find("localhost:") then
      refPath = base.."/.fs/Refs/"..refName..".pdf"
    else
      refPath = "https://static.wentaoli.xyz/Refs/"..refName..".pdf"
    end
    return "["..refName..".pdf]("..refPath..")"
end

KaTeX Plug

latex = {
  header = [<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.css">](<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.css">),
  katex = js.import("https://cdn.jsdelivr.net/npm/katex@0.16.22/+esm")
}

function latex.inline(expression)  
  local html = latex.katex.renderToString(expression, {
    trust = true,
    throwOnError = false,
    displayMode = false
  })
  
  return widget.new {
    html = "<span>" + latex.header + html + "</span>"
  }
end

function latex.block(expression)
  local html = latex.katex.renderToString(expression, {
    trust = true,
    throwOnError = false,
    displayMode = true
  })
  
  return widget.new {
    html = "<span>" + latex.header + html + "</span>"
  }
end 

slashcommand.define {
  name = "math",
  run = function()
    editor.insertAtCursor("${latex.inline[[]]}", false, true)
    editor.moveCursor(editor.getCursor() - 3)
  end
}

slashcommand.define {
  name = "equation",
  run = function()
    editor.insertAtCursor("${latex.block[[]]}", false, true)
    editor.moveCursor(editor.getCursor() - 3)
  end
}

.sb-lua-directive-inline:has(.katex-html) {
  border: none !important;
}

Dark Theme

html[data-theme="dark"] {
  --root-color: rgb(217,222,232);
  --root-background-color: rgb(52,57,68);
  --top-background-color: rgb(67,72,83);
  --bhs-background-color: rgb(67,72,83);
  --editor-panels-bottom-background-color: rgb(67,72,83);
  --subtle-background-color: rgba(25,26,29,0.4);
}

Tag Page

virtualPage.define {
  pattern = "tag:(.+)",
  run = function(tagName)
    local text = "# 📍"..tagName.."\n\n"
    local allObjects = query[
      from index.tag(tagName)
      order by ref
    ](
      from index.tag(tagName)
      order by ref
    )
    local tagParts = tagName:split("/")
    local parentTags = {}
    for i in ipairs(tagParts) do
      local slice = table.pack(table.unpack(tagParts, 1, i))
      if i != #tagParts then
        table.insert(parentTags, {name=table.concat(slice, "/")})
      end
    end
    if #parentTags > 0 then
      text = text .. "## Parent tags\n"
        ..markdown.objectsToTable(parentTags, {
          renderCell=function(value, key)
            if key == "name" then
              return "[tag:" .. value .."|#"..value.. "](tag:" .. value .."|#"..value.. ")"
            end
          end  
          }).. "\n\n"
    end
    local subTags = query[
      from index.tag "tag"
      where string.startsWith(_.name, tagName .. "/")
      select {name="[[tag:"..name.."|#"..name.."](
      from index.tag "tag"
      where string.startsWith(_.name, tagName .. "/")
      select {name="[[tag:"..name.."|#"..name..")"}
      order by name
    ]]
    if #subTags > 0 then
      text = text.."## Subtags\n"
      .. markdown.objectsToTable(subTags).."\n\n"
    end
    local taggedPages = query[
      from p = index.tag "page"
      where matchSubTag(p.tags, tagName)
      select {Page = "[["..p.name.."](
      from p = index.tag "page"
      where matchSubTag(p.tags, tagName)
      select {Page = "[["..p.name..")"}
      order by name
    ]]
    if #taggedPages > 0 then
      text = text .. "## Pages\n"
        .. markdown.objectsToTable(taggedPages).. "\n\n"
    end
    local taggedTasks = query[
      from allObjects where table.includes(_.itags, "task")
    ](
      from allObjects where table.includes(_.itags, "task")
    )
    
    if #taggedTasks > 0 then
      text = text .. "## Tasks\n"
        .. template.each(taggedTasks, templates.taskItem).. "\n"
    end
    local taggedItems = query[
      from allObjects where table.includes(_.itags, "item")
    ](
      from allObjects where table.includes(_.itags, "item")
    )
    
    if #taggedItems > 0 then
      text = text .. "## Items\n"
        .. template.each(taggedItems, templates.itemItem).. "\n"
    end
    local taggedData = query[
      from allObjects where table.includes(_.itags, "data")
    ](
      from allObjects where table.includes(_.itags, "data")
    )
    if #taggedData > 0 then
      text = text .. "## Data\n"
        .. markdown.objectsToTable(taggedData) .. "\n"
    end
    local taggedParagraphs = query[
      from allObjects where table.includes(_.itags, "paragraph")
    ](
      from allObjects where table.includes(_.itags, "paragraph")
    )
    if #taggedParagraphs > 0 then
      text = text .. "## Paragraphs\n"
        .. template.each(taggedParagraphs, templates.paragraphItem)
        .. "\n"
    end
    return text
  end
}

Light Theme

html{
  --editor-width: 1100px;
  
  /*--root-background-color: rgb(256,251,243);*/
  --top-background-color: rgba(248,248,248,0.5);
  --top-border-color: rgb(256,256,256);
  --bhs-background-color: rgb(67,72,83);
  /*--subtle-background-color: rgba(25,26,29,0.4);*/
  --link-color: rgb(59,124,160);
  --ui-accent-color: rgb(59,124,160);
  --modal-hint-background-color: rgb(68,79,207);
  --editor-table-head-background-color: rgb(244,247,254);
  --editor-table-head-color: rgb(75,102,159);
}