跳转到内容

模組:沙盒/PexEric/csv2wikitable

维基百科,自由的百科全书
local p = {}

local function parseCsv(csvText)
    local rows = {}
    local pos = 1
    local csvLen = #csvText

    while pos <= csvLen do
        local row = {}
        while pos <= csvLen do
            local c = csvText:sub(pos, pos)
            if c == '"' then
                local field = ""
                pos = pos + 1
                while pos <= csvLen do
                    c = csvText:sub(pos, pos)
                    if c == '"' then
                        if csvText:sub(pos + 1, pos + 1) == '"' then
                            field = field .. '"'
                            pos = pos + 2
                        else
                            pos = pos + 1
                            break
                        end
                    else
                        field = field .. c
                        pos = pos + 1
                    end
                end
                table.insert(row, field)
            else
                local start = pos
                while pos <= csvLen do
                    c = csvText:sub(pos, pos)
                    if c == ',' or c == '\n' or c == '\r' then break end
                    pos = pos + 1
                end
                table.insert(row, csvText:sub(start, pos - 1))
            end

            if pos > csvLen then break end
            c = csvText:sub(pos, pos)
            if c == ',' then
                pos = pos + 1
            elseif c == '\n' or c == '\r' then
                if c == '\r' and csvText:sub(pos + 1, pos + 1) == '\n' then
                    pos = pos + 2
                else
                    pos = pos + 1
                end
                break
            end
        end
        if #row > 0 then table.insert(rows, row) end
    end
    return rows
end

local function expandIfNeeded(frame, text)
    if not frame or text == nil or text == '' then
        return text or ''
    end
    return frame:preprocess(text)
end

function p._main(args, frame)
    local csvText = args.csv or ''
    if csvText == '' then return '' end

    local hasHeader = args.hasHeader and mw.text.trim(args.hasHeader):lower() == 'true'
    local customHeaders = args.headers and mw.text.split(mw.text.trim(args.headers), ',')
    local prefixes = args.prefixes and mw.text.split(mw.text.trim(args.prefixes), ',') or {}
    local suffixes = args.suffixes and mw.text.split(mw.text.trim(args.suffixes), ',') or {}

    local rows = parseCsv(csvText)
    if #rows == 0 then return '' end

    local colCount = 0
    for _, row in ipairs(rows) do
        if #row > colCount then colCount = #row end
    end

    for i = #prefixes + 1, colCount do prefixes[i] = '' end
    for i = #suffixes + 1, colCount do suffixes[i] = '' end

    local result = {'{| class="wikitable"'}

    local dataStartRow = 1
    if hasHeader or customHeaders then
        table.insert(result, '|-')
        local headerRow = {}
        if customHeaders then
            for i = 1, colCount do
                local h = customHeaders[i] or ''
                table.insert(headerRow, '! ' .. expandIfNeeded(frame, mw.text.trim(h)))
            end
        else
            local firstRow = rows[1]
            for i = 1, colCount do
                local h = firstRow[i] or ''
                table.insert(headerRow, '! ' .. expandIfNeeded(frame, mw.text.trim(h)))
            end
            dataStartRow = 2
        end
        table.insert(result, table.concat(headerRow, '\n'))
    end

    -- 数据行
    for i = dataStartRow, #rows do
        local row = rows[i]
        if #row == 0 then
            -- skip
        else
            table.insert(result, '|-')
            local cells = {}
            for j = 1, colCount do
                local cell = row[j] or ''
                cell = mw.text.trim(cell)
                local fullText = prefixes[j] .. cell .. suffixes[j]
                fullText = expandIfNeeded(frame, fullText)
                table.insert(cells, '| ' .. fullText)
            end
            table.insert(result, table.concat(cells, '\n'))
        end
    end

    table.insert(result, '|}')
    return table.concat(result, '\n')
end

function p.main(frame)
    local args = require('Module:Arguments').getArgs(frame, {
        trim = true,
        removeBlanks = false
    })
    return p._main(args, frame)
end

return p