편집 요약 없음
편집 요약 없음
135번째 줄: 135번째 줄:
     value = value:gsub("DEP", '<span style="font-size: 0.92rem;">發</span>')
     value = value:gsub("DEP", '<span style="font-size: 0.92rem;">發</span>')
     value = value:gsub("ARR", '<span style="font-size: 0.92rem;">着</span>')
     value = value:gsub("ARR", '<span style="font-size: 0.92rem;">着</span>')
     value = value:gsub("GRR", '<span class="forcedcenter" style="font-size: 2rem;"></span>')
     value = value:gsub("GRR", '<span class="forcedcenter" style="font-size: 1.9rem;"></span>')
     value = value:gsub("GRN", '<span class="forcedcenter" style="font-size: 2rem;"></span>')
     value = value:gsub("GRN", '<span class="forcedcenter" style="font-size: 1.9rem;"></span>')


value = u.gsub(value, 'C{(.-)}', function(inner)
value = u.gsub(value, 'C{(.-)}', function(inner)

2025년 8월 10일 (일) 20:16 판

이 모듈에 대한 설명문서는 모듈:Timetable/설명문서에서 만들 수 있습니다

local p = {}
local u = mw.ustring

-- CSV 데이터를 받아 wikitable 형식으로 변환하는 함수
function p.csv(frame)

local function u_chars(s)
    local t = {}
    for ch in u.gmatch(s, ".") do  -- dot matches one Unicode char in ustring
        t[#t+1] = ch
    end
    return t
end


local function justifys(s)
    return u.gsub(s, "'(.-)'", function(inner)
        local pieces = {}
        for ch in u.gmatch(inner, ".") do
            pieces[#pieces+1] = "<span>" .. ch .. "</span>"
        end
        return '<span class="justify-chars">' .. table.concat(pieces) .. "</span>"
    end)
end

local function csv_to_array(csv)
    local rows = {}
    for line in tostring(csv):gmatch("[^\r\n]+") do
        local row = {}
        for cell in line:gmatch("([^,]+)") do
            cell = cell:gsub("^%s+", ""):gsub("%s+$", "")
            table.insert(row, cell)
        end
        table.insert(rows, row)
    end
    return rows
end

local function array_to_csv(t, sep)
    sep = sep or ","
    local lines = {}
    for r = 1, #t do
        local row = {}
        for c = 1, #t[r] do
            local cell = tostring(t[r][c] or "")
            -- 쉼표, 큰따옴표, 줄바꿈이 들어있으면 CSV 규칙에 맞게 감싸기
            if cell:find('[,"\n]') then
                cell = '"' .. cell:gsub('"', '""') .. '"'
            end
            table.insert(row, cell)
        end
        table.insert(lines, table.concat(row, sep))
    end
    return table.concat(lines, "\n")
end

-- m = { {a,b,c}, {d,e,f}, ... }
local function transpose(m, fill)
    fill = fill or ""            -- 빈 칸 채울 값
    local out, rows, maxc = {}, #m, 0
    for r = 1, rows do
        maxc = math.max(maxc, #m[r])
    end
    for c = 1, maxc do
        out[c] = {}
        for r = 1, rows do
            out[c][r] = m[r][c] ~= nil and m[r][c] or fill
        end
    end
    return out
end




    local headerRowCount = tonumber(frame.args["header"]) or 4
    local headerColCount = tonumber(frame.args["left"]) or 3
    local footerRowCount = tonumber(frame.args["footer"]) or 1
    local title = frame.args["title"] or '제목 (title 변수 입력)'
    local csv = frame.args[1] or ''
    local csv = array_to_csv(transpose(csv_to_array(csv)))
    local lines = {}

    title = title:gsub(">", '—')
    title = title:gsub("%.", '</div>')
    title = title:gsub("u", 'UNBOLD')
    title = title:gsub("l", '<div style="border: var(--text) 1.5px solid; display: inline-block; padding-top: 2px; padding-bottom: 3px; font-size: 1.14rem; font-weight: normal; vertical-align: top; line-height: 1.35rem;">')
    title = title:gsub("UNBOLD", '<div style="font-weight: 400; display: inline; font-size: 1.17rem;">')

    local result = '<div style="display: flex; flex-direction: row;"><div class="wm-rl" style="font-size: 1.26rem; padding-right: 4px; font-weight: 700; line-height: 1.54rem;">' .. title .. '</div><div style="border: 2.5px solid var(--text); padding: 3px !important; overflow-x: scroll;">\n{| class="timetable" style="text-align: right; border-spacing: 30px;"\n'

    -- CSV 데이터를 줄 단위로 분리
    for line in csv:gmatch("[^\r\n]+") do
        table.insert(lines, line)
    end

    for i = 1, #lines do
        local row = lines[i]
        local values = {}
        -- 데이터를 쉼표로 분리하여 values 테이블에 저장
        for value in row:gmatch("[^,]+") do

            value = value:gsub("c",'OPENCENTERSPAN')
            value = value:gsub("<", ' colspan=')
            value = value:gsub(">", '⇨')
            value = value:gsub("h", 'HEADERSTYLE')
            value = value:gsub("%~", 'HEIGHTSET')
            value = value:gsub("r", "RIGHTLEFT")
            value = value:gsub("%#", "NOBORDERTOP")
            value = value:gsub("%&", "YESBORDERTOP")
            value = value:gsub("g", 'GREATER')
            value = value:gsub("%^", ' rowspan=')
            value = value:gsub(";", ' |')
            value = value:gsub("x", "ELLIPSIS")
            value = value:gsub("%.","ENDSPAN")
            value = value:gsub("%+","ENDSPANOPENSPAN")
            value = value:gsub("i", 'OPENCENTERSPAN&#124;')
            value = value:gsub("q", 'OPENCENTERSPAN〃')
            value = value:gsub("-", 'OPENCENTERSPAN⸺')
            value = value:gsub("v", 'OPENCENTERSPAN↓')
            value = value:gsub("k", '<span style="font-weight: 700;">')
            value = value:gsub("b", '<span style="font-size: 1.25em; font-weight: 700;">')
            value = value:gsub("/", "<br/>")
            value = value:gsub("ENDSPAN","</span>")
            value = value:gsub("ELLIPSIS",'OPENCENTERSPAN⋯')
            value = value:gsub("OPENSPAN", '<span></span>')
            value = value:gsub("HEADERSTYLE", [[colspan="]] .. tostring(headerColCount) .. [[" style="padding-left: 1.08rem; padding-right: 1.08rem; text-align: justify; text-align-last: justify; border-right: none; vertical-align: middle;"]])
            value = value:gsub("HEIGHTSET", ' height=')
            value = value:gsub("RIGHTLEFT", '<span class="wm-rl">')  
            value = value:gsub("NOBORDERTOP", '<span class="nobordertop"></span>') 
            value = value:gsub("YESBORDERTOP", '<span class="yesbordertop"></span>') 
            value = value:gsub("GREATER", '<span style="font-size: 1.2em;">')
            value = value:gsub("OPENCENTERSPAN", '<span class="forcedcenter"></span>')

    value = value:gsub("DEP", '<span style="font-size: 0.92rem;">發</span>')
    value = value:gsub("ARR", '<span style="font-size: 0.92rem;">着</span>')
    value = value:gsub("GRR", '<span class="forcedcenter" style="font-size: 1.9rem;"></span>')
    value = value:gsub("GRN", '<span class="forcedcenter" style="font-size: 1.9rem;"></span>')

value = u.gsub(value, 'C{(.-)}', function(inner)
    inner = inner:gsub("^%s*(.-)%s*$", "%1") -- trim spaces
    local as_num = tonumber(inner)
    if as_num and as_num >= 0 and as_num <= 34 then
        if as_num == 0 then return "⓪" end
        if as_num <= 20 then return '<span class="forcedcenter"></span>' .. u.char(0x2460 + (as_num - 1)) end -- ①..⑳
        return '<span class="forcedcenter"></span>' .. u.char(0x3251 + (as_num - 21))                        -- ㉑..㉟
    end
    return '<span class="forcedcenter" style="height: 1rem;  width: 1.9rem;  display: inline-block;  border: 1px solid var(--text);  border-radius: 40%;  font-size: 0.75rem;  line-height: 1.1;  vertical-align: middle; overflow: hidden;"><span class="stretch-text" data-max-width="1.1rem"><span>' .. inner .. '</span></span></span>'
end)

value = u.gsub(value, 'S{(.-)}', function(inner)
    inner = inner:gsub("^%s*(.-)%s*$", "%1") -- trim spaces
    if tonumber(inner) ~= nil then
return '<span class="forcedcenter" style="height: 0.95rem;  width: 1.8rem;  display: inline-block; overflow: hidden; border: 1px solid var(--text);  font-size: 0.75rem;  line-height: 0.9;  vertical-align: middle;">' .. inner .. '</span>'
    end
    return '<span class="forcedcenter" style="height: 1rem;  width: 1.9rem;  display: inline-block; overflow: hidden; border: 1px solid var(--text);  font-size: 0.75rem;  line-height: 1.1;  vertical-align: middle;"><span class="stretch-text" data-max-width="1.4rem"><span>' .. inner .. '</span></span></span>'
end)

            value = justifys(value)

            if string.find(value, "|") then
                table.insert(values, value)
            else
                table.insert(values, "|" .. value)
            end
        end

        for j, value in ipairs(values) do
            if j == headerColCount - 1 then
                values[j] = [[style="padding-left: 1.1rem; padding-right: 0.2rem; text-align: justify; text-align-last: justify; border-right: none; vertical-align: middle; min-width: 10ch;"]] .. value
            elseif j == headerColCount then
                values[j] = 'style="text-align: center; border-left: none; border-right: 1px solid var(--text); margin-left: -1rem;"' .. value
            elseif j == headerColCount + 1 then
                values[j] = [[style="min-width: 2.36rem; border-left: 1px solid var(--text);"]] .. value
            else
                values[j] = [[style="min-width: 2.36rem;"]] .. value
            end
        end

        for j = #values, 1, -1 do
            if string.find(values[j], "!!") then
                table.remove(values, j)
            end
        end

        if i < headerRowCount + 1 then
            result = result .. '|- class="serifnumbers" style="border-top: 1px solid var(--text); text-align: center !important;"\n| ' .. table.concat(values, " \n| ") .. "\n"
        elseif i == headerRowCount + 1 then
            result = result .. '|- style="border-top: double var(--text);"\n| ' .. table.concat(values, " \n| ") .. "\n"
        elseif i > #lines - footerRowCount then
            result = result .. '|- style="border-top: 1px solid var(--text); text-align: left !important;"\n| ' .. table.concat(values, " \n| ") .. "\n"
        else
            result = result .. "|-\n| " .. table.concat(values, " \n| ") .. "\n"
        end
    end

    result = result .. "|}\n</div></div>"
    return result
end

return p