Skip to content

Instantly share code, notes, and snippets.

@malys
Last active August 21, 2025 17:48
Show Gist options
  • Select an option

  • Save malys/e19ec68a5d5cee1ec1da890b2211438e to your computer and use it in GitHub Desktop.

Select an option

Save malys/e19ec68a5d5cee1ec1da890b2211438e to your computer and use it in GitHub Desktop.
[md advanced tables] advanced md table management #silverbullet #lua
```space-lua
-- To enable debug logs, set LOG_ENABLE to true
local LOG_ENABLE = true
local TEXT_EDITOR = nil
local EDITOR = nil
local function debug_log(message)
if LOG_ENABLE then
js.log("[DEBUG] " .. message)
end
end
-- Import the external JavaScript library
local tableLib = js.import("https://cdn.jsdelivr.net/npm/@tgrosinger/md-advanced-tables/+esm")
debug_log("===================================")
debug_log(tableLib.defaultOptions)
debug_log("===================================")
-- Create text editor interface compatible with md-advanced-tables
-- This bridges SilverBullet's editor API with the library's expected interface
local function createTextEditor()
debug_log("createTextEditor called")
local self = {}
local function get_text()
debug_log("get_text called ".. editor.getText())
return editor.getText()
end
local function get_lines()
debug_log("get_lines called"..string.split(get_text(), "\n"))
return string.split(get_text(), "\n")
end
local function row_col_to_offset(row, col)
local lines = get_lines()
local offset = 0
for i = 1, row do
offset = offset + #lines[i] + 1
end
debug_log("row_col_to_offset called with row: " .. row .. ", col: " .. col..", offset:"..offset)
return offset + col
end
local function offset_to_row_col(offset)
local text = get_text()
local row = 1
local last_newline = 0
for i = 1, #text do
if i == offset then
break
end
if string.sub(text, i, i) == "\n" then
row = row + 1
last_newline = i
end
end
local col = offset - last_newline
debug_log("offset_to_row_col called with offset: " .. offset.." "..row.." "..col)
return row, col
end
function self:getCursorPosition()
local offset = editor.getCursor()
local row, col = offset_to_row_col(offset)
debug_log("getCursorPosition called "..row.." "..col)
return js.tojs({ row = row - 1, column = col - 1 })
end
function self:setCursorPosition(pos)
pos = js.tolua(pos)
local offset = row_col_to_offset(pos.row + 1, pos.column + 1)
debug_log("setCursorPosition called "..offset)
editor.moveCursor(offset)
end
function self:setSelectionRange(range)
range = js.tolua(range)
local from = row_col_to_offset(range.start.row + 1, range.start.column + 1)
local to = row_col_to_offset(range["end"].row + 1, range["end"].column + 1)
debug_log("setSelectionRange called "..from.." "..to)
editor.setSelection(from, to)
end
function self:getLastRow()
debug_log("getLastRow called ".. #get_lines())
return #get_lines() - 1
end
function self:acceptsTableEdit(row)
debug_log("acceptsTableEdit called " .. true)
return js.tojs(true)
end
function self:getLine(row)
local lines = get_lines()
debug_log("getLine called with row: " .. row.." ".. lines[row + 1] )
return js.tojs(lines[row + 1])
end
function self:insertLine(row, line)
local lines = get_lines()
table.insert(lines, row + 1, line)
editor.setText(table.concat(lines, "\n"))
debug_log("insertLine called with row: " .. row.." "..table.concat(lines, "\n"))
end
function self:deleteLine(row)
debug_log("deleteLine called with row: " .. row)
local lines = get_lines()
table.remove(lines, row + 1)
editor.setText(table.concat(lines, "\n"))
end
function self:replaceLines(startRow, endRow, newLines)
debug_log("replaceLines called with startRow: " .. startRow .. ", endRow: " .. endRow)
newLines = js.tolua(newLines)
local lines = get_lines()
local new_lines_table = {}
for i=1, #newLines do
table.insert(new_lines_table, newLines[i])
end
local final_lines = {}
for i=1, startRow do
table.insert(final_lines, lines[i])
end
for i=1, #new_lines_table do
table.insert(final_lines, new_lines_table[i])
end
for i=endRow + 1, #lines do
table.insert(final_lines, lines[i])
end
editor.setText(table.concat(final_lines, "\n"))
end
function self:transact(func)
debug_log("transact called")
func()
end
return js.tojs(self)
end
local function getTableEditor()
debug_log("getTableEditor called")
if TEXT_EDITOR == nil then
EDITOR = createTextEditor()
debug_log(EDITOR)
TEXT_EDITOR = js.new(tableLib.TableEditor, EDITOR)
end
return TEXT_EDITOR
end
command.define {
name = "AdvTable: Format",
run = function()
debug_log("Command 'AdvTable: Format' called")
getTableEditor().format(tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Align Column Left",
run = function()
debug_log("Command 'AdvTable: Align Column Left' called")
getTableEditor().alignColumn(tableLib.Alignment.Left, tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Align Column Center",
run = function()
debug_log("Command 'AdvTable: Align Column Center' called")
getTableEditor().alignColumn(tableLib.Alignment.Center, tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Align Column Right",
run = function()
debug_log("Command 'AdvTable: Align Column Right' called")
getTableEditor().alignColumn(tableLib.Alignment.Right, tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Select Cell",
run = function()
debug_log("Command 'AdvTable: Select Cell' called")
getTableEditor().selectCell(tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Insert Row",
run = function()
debug_log("Command 'AdvTable: Insert Row' called")
getTableEditor().insertRow(tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Delete Row",
run = function()
debug_log("Command 'AdvTable: Delete Row' called")
getTableEditor().deleteRow(tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Move Row Up",
run = function()
debug_log("Command 'AdvTable: Move Row Up' called")
getTableEditor().moveRow(-1, tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Move Row Down",
run = function()
debug_log("Command 'AdvTable: Move Row Down' called")
getTableEditor().moveRow(1, tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Insert Column",
run = function()
debug_log("Command 'AdvTable: Insert Column' called")
getTableEditor().insertColumn(tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Delete Column",
run = function()
debug_log("Command 'AdvTable: Delete Column' called")
getTableEditor().deleteColumn(tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Move Column Left",
run = function()
debug_log("Command 'AdvTable: Move Column Left' called")
getTableEditor().moveColumn(-1, tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Move Column Right",
run = function()
debug_log("Command 'AdvTable: Move Column Right' called")
getTableEditor().moveColumn(1, tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Evaluate Formulas",
run = function()
debug_log("Command 'AdvTable: Evaluate Formulas' called")
local editor=getTableEditor()
local result= editor.evaluateFormulas(tableLib.defaultOptions)
debug_log("Command 'AdvTable: Evaluate Formulas' called " ..result)
return result
end
}
command.define {
name = "AdvTable: Transpose",
run = function()
debug_log("Command 'AdvTable: Transpose' called")
getTableEditor().transpose(tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Sort Rows Ascending",
run = function()
debug_log("Command 'AdvTable: Sort Rows Ascending' called")
getTableEditor().sortRows(tableLib.SortOrder.Ascending, tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Sort Rows Descending",
run = function()
debug_log("Command 'AdvTable: Sort Rows Descending' called")
getTableEditor().sortRows(tableLib.SortOrder.Descending, tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Format All",
run = function()
debug_log("Command 'AdvTable: Format All' called")
getTableEditor().formatAll(tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Export Table as JSON",
run = function()
debug_log("Command 'AdvTable: Export Table as JSON' called")
local data = getTableEditor().exportTable(true, tableLib.defaultOptions)
editor.flashNotification(data)
end
}
command.define {
name = "AdvTable: Export Table as CSV",
run = function()
debug_log("Command 'AdvTable: Export Table as CSV' called")
local data = getTableEditor().exportCSV(true, tableLib.defaultOptions)
editor.flashNotification(data)
end
}
---
command.define {
name = "AdvTable: Escape",
run = function()
debug_log("Command 'AdvTable: Escape' called")
getTableEditor().escape(tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Move Focus Up",
run = function()
debug_log("Command 'AdvTable: Move Focus Up' called")
getTableEditor().moveFocus(-1, 0, tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Move Focus Down",
run = function()
debug_log("Command 'AdvTable: Move Focus Down' called")
getTableEditor().moveFocus(1, 0, tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Move Focus Left",
run = function()
debug_log("Command 'AdvTable: Move Focus Left' called")
getTableEditor().moveFocus(0, -1, tableLib.defaultOptions)
end
}
command.define {
name = "AdvTable: Move Focus Right",
run = function()
debug_log("Command 'AdvTable: Move Focus Right' called")
getTableEditor().moveFocus(0, 1, tableLib.defaultOptions)
end
}
```
Header A Header B
1 2
3 4
5 6
7 8
9 10
11 12
Header A Header B
100 200
300 400
0 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment