模块:Wikitable.lua:修订间差异

来自「荏苒之境」
无编辑摘要
无编辑摘要
第7行: 第7行:
local BYTE_SEPARATOR = string.byte('|')
local BYTE_SEPARATOR = string.byte('|')
local BYTE_EXCLAMATION = string.byte('!')
local BYTE_EXCLAMATION = string.byte('!')
local BYTE_ADD = string.byte('+')
local BYTE_MINUS = string.byte('-')
local BYTE_MINUS = string.byte('-')


第50行: 第51行:
     while true do
     while true do
         local b = string.byte(str, pos)
         local b = string.byte(str, pos)
         if b == BYTE_NEWLINE then
         if b == BYTE_SEPARATOR or b == BYTE_EXCLAMATION then
            pos = pos + 1
             break
             break
         elseif b == nil then
         elseif b == nil then
             pos = nil
             pos = nil
             break
             break
         end
         elseif b ~= BYTE_ENTER then
        if b ~= BYTE_ENTER then
             bytes[#bytes+1] = b
             bytes[#bytes+1] = b
         end
         end
         pos = pos + 1
         pos = pos + 1
    end
    if bytes[#bytes] == BYTE_NEWLINE then
        bytes[#bytes] = nil
     end
     end


第67行: 第70行:
     elseif head == BYTE_SEPARATOR then
     elseif head == BYTE_SEPARATOR then
         local fst_byte = bytes[1]
         local fst_byte = bytes[1]
         if fst_byte == BYTE_MINUS then
         if fst_byte == BYTE_ADD then
             return pos, "row_end"
            return pos, "header_start"
        elseif fst_byte == BYTE_MINUS then
             return pos, "row_start"
         elseif fst_byte == BYTE_CLOSE_CURLY then
         elseif fst_byte == BYTE_CLOSE_CURLY then
             return pos, "table_end"
             return pos, "table_end"
第92行: 第97行:
         if cell_type == "header" then
         if cell_type == "header" then
             header[#header+1] = cell_content
             header[#header+1] = cell_content
         elseif cell_type == "row_end"
         elseif cell_type == "row_start" then
            or cell_type == "table_end" then
             if curr_row ~= nil then
             if curr_row then
                 rows[#rows+1] = curr_row
                 rows[#rows+1] = curr_row
             end
             end
             curr_row = {}
             curr_row = {}
            if cell_type == "table_end" then
        elseif cell_type == "table_end" then
                 break
            if curr_row ~= nil then
                 rows[#rows+1] = curr_row
             end
             end
         else
            break
         elseif cell_type == "text" then
             if curr_row == nil then
             if curr_row == nil then
                 curr_row = {}
                 curr_row = {}

2025年8月6日 (三) 00:54的版本

此模块的文档可以在模块: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)
    pos = find_character(str, pos, BYTE_OPEN_CURLY)
    if pos == nil then return nil end
    pos = find_character(str, pos, BYTE_SEPARATOR)
    if pos == nil then return nil end
    return pos + 1
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