본문으로 이동

모듈:ko-utilities

위키낱말사전, 말과 글의 누리

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

local export = {}

local m_str_utils = require("모듈:string utilities")
local lang = require("모듈:languages").getByCode("ko")
local m_scripts = require("모듈:scripts")
local m_link = require("모듈:also/link")

local codepoint = m_str_utils.codepoint
local concat = table.concat
local floor = math.floor
local gmatch = m_str_utils.gmatch
local gsplit = m_str_utils.gsplit
local gsub = m_str_utils.gsub
local insert = table.insert
local len = m_str_utils.len
local match = m_str_utils.match
local min = math.min
local remove = table.remove
local sub = m_str_utils.sub
local u = m_str_utils.char
local upper = m_str_utils.upper

export.lang = lang
local HangChars = m_scripts.getByCode("Hang"):getCharacters()
local HaniChars = m_scripts.getByCode("Hani"):getCharacters()

-- makes hanjatab automatically
function export.hanjatab()
    local hanja = mw.ustring.gsub(mw.title.getCurrentTitle().text, '[^一-鿌]', '')
        local table_head = '<table class="floatright wikitable" style="text-align:center; font-size:small;"><tr><th colspan="' ..
        mw.ustring.len(hanja) ..
        '" style="font-weight:normal;">[[hanja|Hanja]] in this term</th></tr><tr lang="ko" class="Kore" style="font-size:2em; background:white; line-height:1em;">'
    return table_head ..
        mw.ustring.gsub(hanja, '(.)', '<td style="padding:0.5em;">[[%1#한국어|%1]]</td>') ..
        '</table>'
end

-- return only non-hangeul contained in text
function export.remove_hangeul(f)
    local nonhangeul = mw.ustring.gsub(f.args[1], '[가-힣]', '')
    return nonhangeul
end

function export.boldify(f)
    local pagename = mw.title.getCurrentTitle().text
    hangul = f.args[1]
    if match(hangul, pagename) and not match(hangul, "'") then
        hangul = gsub(hangul, pagename, "'''" .. pagename .. "'''")
    end
    return hangul
end

function export.usex_hangul(f)
    local pagename = mw.title.getCurrentTitle().text
    hangul = f.args[1]
    if match(hangul, pagename) and not match(hangul, "'") then
        hangul = gsub(hangul, pagename, "'''" .. pagename .. "'''")
    end
    hangul = mw.ustring.gsub(hangul,'[%^%-]','')
    return hangul
end

function export.link(frame)
    local arg = frame:getParent().args
    local args, distances = {}, {}
    local m_pron = require("Module:ko-translit")
    local curr_distance, closest_match = 1000, 0
    local word, translit, definition, hanja, note = false, false, false, false, false
    
    for i = 1, 4, 1 do
        if arg[i] and arg[i] ~= "" then
            table.insert(args, arg[i])
        end
    end

    local curr_hangul_level, closest_hangul = 0, 0
    for i, parameter in ipairs(args) do
        local _, tentative_hangul_level = gsub(parameter, "[가-힣\225\132\128-\225\135\191]", "")
        if tentative_hangul_level > curr_hangul_level then
            curr_hangul_level = tentative_hangul_level
            closest_hangul = i
        end
    end

    if curr_hangul_level > 0 then
        word = args[closest_hangul]
        table.remove(args, closest_hangul)
    end
    
    local function compute_distance(str1, str2)
        local len1, len2 = #str1, #str2
        local char1, char2, distance = {}, {}, {}
        
        str1:gsub('.', function (c)
            table.insert(char1, c) end)
        
        str2:gsub('.', function (c)
            table.insert(char2, c) end)
        
        for i = 0, len1 do
            distance[i] = {}
        end
        
        for i = 0, len1 do
            distance[i][0] = i
        end
        
        for i = 0, len2 do
            distance[0][i] = i
        end
        
        for i = 1, len1 do
            for j = 1, len2 do
                distance[i][j] = math.min(
                    distance[i-1][j] + 1,
                    distance[i][j-1] + 1,
                    distance[i-1][j-1] + (char1[i] == char2[j] and 0 or 1)
                )
            end
        end
    
        return distance[len1][len2]
    end
    
    local m_link = require("Module:links")
    test_translit = m_pron.tr_revised(m_link.remove_links(word or arg[1])) or ""
    
    if arg[5] and arg[5] ~= "" then
        note = arg[5]
    end
    
    for i, parameter in ipairs(args) do
        if not match(parameter, '[가-힣㐀-䶵一-鿌\239\164\128-\239\171\153𠀀-𯨟]') then
            local tentative_distance = compute_distance(test_translit, parameter)
            if tentative_distance < curr_distance then
                curr_distance = tentative_distance
                closest_match = i
            end
        end
    end

    if curr_distance < 3 and #args > 1 then
        translit = args[closest_match]
        table.remove(args, closest_match)
    end

    for i, parameter in ipairs(args) do
        if match(parameter, "[㐀-䶵一-鿌\239\164\128-\239\171\153𠀀-𯨟]") then
            hanja = parameter
            table.remove(args, i)
        end
    end
    
    if not hanja and not word then
        word = args[1]
        table.remove(args, 1)
    end
    
    if #args > 1 then
        translit = args[1]
        definition = args[2]
    
    elseif #args > 0 then
        definition = args[1]
    end
    
    if hanja and not match(hanja, "[%[%]]") then
        for hanja_word in mw.ustring.gmatch(hanja, "[㐀-䶵一-鿌\239\164\128-\239\171\153𠀀-𯨟]+") do
            hanja = gsub(hanja, hanja_word, "[[" .. hanja_word .. "]]")
        end
        for hangul_word in mw.ustring.gmatch(hanja, "[가-힣]+") do
            hanja = gsub(hanja, hangul_word, "<span lang=\"ko\" class=\"Hang\">[[" .. hangul_word .. "]]</span>")
        end
        hanja = gsub(hanja, "%[%[%[%[", "[[")
        hanja = gsub(hanja, "%]%]%]%]", "]]")
    end
    
    if arg["tr"] or translit or test_translit then
        translit = "<i>" .. (arg["tr"] or translit or test_translit) .. "</i>"
    end
    
    if definition then
        definition = "“" .. definition .. "”"
    end
    
    if hanja then
        hanja = '<span lang="ko" class="Hani">' .. m_link.language_link({lang = lang, term = hanja}, true) .. '</span>'
    end

    word = gsub(word, "%^", "")
    
    if not match(word, "[%[%]]") then
        if match(word, "^—.+—$") then
            word = gsub(word, "—(.+)—", "—[[%1]]—")
            
        elseif match(word, "^—.+$") then
            word = gsub(word, "—(.+)", "—[[%1]]")
            
        elseif match(word, "^.+—$") then
            word = gsub(word, "(.+)—", "[[%1다|%1—]]")
        
        elseif match(word, "^.+–$") then
            word = gsub(word, "(.+)–", "[[%1]]—")
        
        elseif match(word, "^\*") then
            word = gsub(word, "\*", "")
        
        else
            word = "[[" .. word .. "]]"
        end
    end
    
    local info = {}
    table.insert(info, word and (hanja or nil) or nil)
    table.insert(info, translit or nil)
    table.insert(info, definition or nil)

    result = word
        and
            ("<span lang=\"ko\" class=\"Hang\">" .. word .. "</span>")
        or
            ('<span lang="ko" class="Hani">' .. m_link.language_link({lang = lang, term = hanja}, true) .. '</span>')
    
    if #info > 0 then
        result = result .. " (" .. table.concat(info, ", ") .. ")"
    end
    
    if note then
        result = result .. " (<i>" .. note .. "</i>)"
    end
    
    return result
end

function export.new(frame)
    local args = frame:getParent().args

    local function other(class, title, args)
        local code = ""
        if args[class] then
            code = code .. "\n\n===" .. title .. "===\n* {{ko-l|" .. args[class] .. "}}"
 
            if args[class .. "2"] then
                code = code .. "\n* {{ko-l|" .. args[class .. "2"] .. "}}"
 
                if args[class .. "3"] then
                    code = code .. "\n* {{ko-l|" .. args[class .. "3"] .. "}}"
 
                    if args[class .. "4"] then
                        code = code .. "\n* {{ko-l|" .. args[class .. "4"] .. "}}"
                    end
                end
            end
        end
        return code
    end
    
    local result = "== 한국어 =="
    if args["wp"] then
        result = result .. "\n{{wikipedia|lang=ko}}"
    end
    
    result = result .. other("alt", "Alternative forms", args)
    
    if args["e"] or args["ee"] or args["h"] or args["h1"] then
        result = result .. "\n\n=== 어원 ===\n"
        
            result = result .. (args["ee"] or
                ("From {{etyl|" .. (args["el"] or "en") .. "|ko}} {{m|" ..
                    (args["el"] or "en") .. "|" .. args["e"] .. "}}."))
    end
end

function export.decompose_jamo(syllable)
    if not match(syllable, "[가-힣]") then return { initial = "Ø", vowel = " ", final = "" } end
    local char = mw.ustring.char
    local cp = mw.ustring.codepoint(syllable)
    if not cp then return { "", "", "" } end
    relative_cp = cp - 0xAC00
    jongseong = relative_cp % 28
    jungseong = math.floor((relative_cp % 588) / 28)
    choseong = math.floor(relative_cp / 588)
    choseong, jungseong, jongseong =
        char(0x1100 + choseong),
        char(0x1161 + jungseong),
        jongseong ~= 0 and char(0x11A7 + jongseong) or ""
    return { initial = choseong, vowel = jungseong, final = jongseong }
end

-- 종성 판별 및 조사 선택 함수 추가. 분류명에 존재하는 이형태를 처리하기 위함
function export.allomorphy(word, type)
    local suffixes = {
        top = { final = "은", no_final = "는" },  -- 보조사
        sbj = { final = "이", no_final = "가" },  -- 주격 조사
        obj = { final = "을", no_final = "를" },  -- 목적격 조사
        conj = { final = "과", no_final = "와" }, -- 공동격 조사
        ins = { final = "으로", no_final = "로" } -- 도구격 조사
    }
    local particle = suffixes[type]
    if not particle then
        error("유효하지 않은 조사 형태입니다: " .. type)
    end
    -- HTML 태그나 위키링크 제거
    local clean_word = gsub(word, "<.->", "")
    clean_word = gsub(clean_word, "%[%[([^%]|]+)|?([^%]]*)%]%]", function(target, display) return display or target end)
    
    local last_char = sub(clean_word, -1)
    if not match(last_char, "[" .. HangChars .. "]") then
        return word .. particle.final -- 한글이 아니면 받침 있는 것으로 간주
    end
    
    local cp = codepoint(last_char)
    if not cp then return word .. particle.final end
    
    local jongseong = (cp - 0xAC00) % 28
    local has_final = jongseong ~= 0
    
    local suffix = has_final and particle.final or particle.no_final
    return word .. suffix
end

return export