Module:Csv

From Coral Island Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Csv/doc

local p = {}
local getArgs = require("Dev:Arguments").getArgs

local str_find = string.find
local str_sub = string.sub
local str_gsub = string.gsub
local tbl_insert = table.insert

local function escapeMagicCharacters(s)
	-- Lua pattern magic chars are ^$()%.[]*+-?
	return str_gsub(s, '[%^%$%(%)%%%.%[%]%*%+%-%?]', '%%%1')
end

function p.main(frame)
	local args = getArgs(frame)
	local sPageName = args.page
	local fmtparams = {
		delimiter = args.delimiter,
		quotechar = args.quotechar,
	}

	if sPageName then
		return p.csvToHtmlTable(sPageName, fmtparams)
	end
end

function p.csvToHtmlTable(sPage, fmtparams)
	local tLuaTable = p.convertToLua(sPage, fmtparams)

	if tLuaTable then
		return p.generateHtml(tLuaTable, fmtparams)
	end
end

function p.convertToLua(sPage, fmtparams)
	if sPage then
		local oData = mw.title.new(sPage)
		local arrColumns = {}
		
		if oData then
			local contents = oData:getContent()
			if contents then
				arrColumns = p.parseCSV(contents, fmtparams)
			end
		end
		return arrColumns 
	end
end

-- //Converts a csv page to html table
function p.generateHtml(arrColumns, fmtparams)
	local hTable = mw.html.create("table")

	hTable:addClass("wikitable")
	for i, v in ipairs(arrColumns) do 
		local sTag = i == 1 and "th" or "td"
		local tr = hTable:tag("tr")
		for _, sData in ipairs(v) do
			local text = sData:gsub('\n', '<br>')
			tr:tag(sTag):wikitext(text)
		end
	end
	return hTable
end

-- http://lua-users.org/wiki/CsvUtils
-- https://docs.python.org/3/library/csv.html
function p.parseCSV(s, fmtparams)
	if s == '' then return {} end
	local t = {}
	local row = {}
	local pos = 1
	local delimiter = fmtparams and fmtparams.delimiter or ','
	if #delimiter ~= 1 then
		error('"delimiter" must be a 1-character string')
	end
	local quotechar = fmtparams and fmtparams.quotechar or '"'
	if #quotechar ~= 1 then
		error('"quotechar" must be a 1-character string')
	end
	local escapedDelimiter = escapeMagicCharacters(delimiter)
	local escapedQuotechar = escapeMagicCharacters(quotechar)
	repeat
		if str_find(s, '^'..escapedQuotechar, pos) then
			local a, c
			local i = pos
			repeat
				a, i, c = str_find(s, escapedQuotechar..'('..escapedQuotechar..'?)', i + 1)
			until c ~= quotechar
			if not i then error('Unmatched '..quotechar) end
			local f = str_sub(s, pos + 1, i - 1)
			local txt = str_gsub(f, escapedQuotechar..escapedQuotechar, quotechar)
			tbl_insert(row, txt)
			local nexti = str_find(s, escapedDelimiter, i)
			pos = (nexti or i) + 1
		else -- unquoted; str_find next delimiter, newline, or EOL.
			local i = str_find(s, '[\n'..escapedDelimiter..']', pos)
			if i then
				local txt = str_sub(s, pos, i - 1)
				tbl_insert(row, txt)
				if str_sub(s, i, i) == '\n' then
					tbl_insert(t, row)
					row = {}
				end
				pos = i + 1
			else
				local txt = str_sub(s, pos)
				tbl_insert(row, txt)
				break
			end
		end
	until pos > #s
	if row and #row > 0 then
		tbl_insert(t, row)
	end
	return t
end

return p