模块:Wikitable.lua:修订间差异
来自「荏苒之境」
无编辑摘要 |
无编辑摘要 |
||
第37行: | 第37行: | ||
local function find_table_start(str, pos) | local function find_table_start(str, pos) | ||
pos = find_character(str, pos, BYTE_OPEN_CURLY) | while true do | ||
pos = find_character(str, pos, BYTE_OPEN_CURLY) | |||
if pos == nil then return nil end | |||
pos = pos + 1 | |||
if string.byte(str, pos) == BYTE_SEPARATOR then | |||
return pos + 1 | |||
end | |||
end | |||
end | end | ||
第90行: | 第93行: | ||
if pos == nil then return rows end | if pos == nil then return rows end | ||
pos = skip_to_next_line(str, pos) | pos = skip_to_next_line(str, pos) | ||
local cell_type, cell_content | local cell_type, cell_content | ||
2025年8月6日 (三) 01:03的最新版本
此模块的文档可以在模块:Wikitable.lua/doc创建
local unpack = unpack or table.unpack
local BYTE_ENTER = string.byte('\r')
local BYTE_NEWLINE = string.byte('\n')
local BYTE_OPEN_CURLY = string.byte('{')
local BYTE_CLOSE_CURLY = string.byte('}')
local BYTE_SEPARATOR = string.byte('|')
local BYTE_EXCLAMATION = string.byte('!')
local BYTE_ADD = string.byte('+')
local BYTE_MINUS = string.byte('-')
local wikitable = {}
local function skip_to_next_line(str, pos)
while true do
local b = string.byte(str, pos)
if b == BYTE_NEWLINE or b == BYTE_ENTER then
return pos + 1
elseif b == nil then
return nil
end
pos = pos + 1
end
end
local function find_character(str, pos, cbyte)
while true do
local b = string.byte(str, pos)
if b == cbyte then
return pos
elseif b == nil then
return nil
end
pos = pos + 1
end
end
local function find_table_start(str, pos)
while true do
pos = find_character(str, pos, BYTE_OPEN_CURLY)
if pos == nil then return nil end
pos = pos + 1
if string.byte(str, pos) == BYTE_SEPARATOR then
return pos + 1
end
end
end
local function parse_cell(str, pos)
local head = string.byte(str, pos)
pos = pos + 1
local bytes = {}
while true do
local b = string.byte(str, pos)
if b == BYTE_SEPARATOR or b == BYTE_EXCLAMATION then
break
elseif b == nil then
pos = nil
break
elseif b ~= BYTE_ENTER then
bytes[#bytes+1] = b
end
pos = pos + 1
end
if bytes[#bytes] == BYTE_NEWLINE then
bytes[#bytes] = nil
end
if head == BYTE_EXCLAMATION then
return pos, "header", string.char(unpack(bytes))
elseif head == BYTE_SEPARATOR then
local fst_byte = bytes[1]
if fst_byte == BYTE_ADD then
return pos, "header_start"
elseif fst_byte == BYTE_MINUS then
return pos, "row_start"
elseif fst_byte == BYTE_CLOSE_CURLY then
return pos, "table_end"
else
return pos, "text", string.char(unpack(bytes))
end
end
end
wikitable.parse = function(str)
local header = {}
local rows = { header = header }
local curr_row
local pos = find_table_start(str, 1)
if pos == nil then return rows end
pos = skip_to_next_line(str, pos)
local cell_type, cell_content
while pos ~= nil do
pos, cell_type, cell_content = parse_cell(str, pos)
if cell_type == "header" then
header[#header+1] = cell_content
elseif cell_type == "row_start" then
if curr_row ~= nil then
rows[#rows+1] = curr_row
end
curr_row = {}
elseif cell_type == "table_end" then
if curr_row ~= nil then
rows[#rows+1] = curr_row
end
break
elseif cell_type == "text" then
if curr_row == nil then
curr_row = {}
end
curr_row[#curr_row+1] = cell_content
end
end
return rows
end
return wikitable