익명
×
새 문서 만들기
여기에 문서 제목을 쓰세요:
We currently have 900 articles on 루리위키. Type your article name above or click on one of the titles below and start writing!



900Articles

모듈:푸른 저편의 포리듬/ 캐릭터 프로필: 두 판 사이의 차이

편집 요약 없음
편집 요약 없음
164번째 줄: 164번째 줄:
     -- 우측
     -- 우측
     local right = mw.html.create('div'):addClass('prf-right'):cssText('flex:1 1 auto;')
     local right = mw.html.create('div'):addClass('prf-right'):cssText('flex:1 1 auto;')
     right:node(mw.html.create('div').addClass('prf-name').wikitext(name_block))
     local right = mw.html.create('div'):addClass('prf-right'):cssText('flex:1 1 auto;')
    local output = mw.html.create('div')
 
    output:tag('div'):addClass('prf-name'):wikitext(name_block):done()


     if basic ~= '' then right:node(mw.html.create('div').addClass('prf-section').wikitext('<h4>기본 정보</h4>' .. basic)) end
     if basic ~= '' then right:node(mw.html.create('div').addClass('prf-section').wikitext('<h4>기본 정보</h4>' .. basic)) end

2025년 12월 5일 (금) 02:49 판

이 모듈에 대한 설명문서는 모듈:푸른 저편의 포리듬/ 캐릭터 프로필/설명문서에서 만들 수 있습니다

local p = {}
local mw = mw
local tt = mw.text

-- 안전 문자열 트림
local function trim(s)
    if not s then return '' end
    return tt.trim(tostring(s))
end

-- 시그니처 기술 수집 (시그니처기술1..10)
local function gather_techs(args)
    local techs = {}
    for i = 1, 10 do
        local k = '시그니처기술' .. i
        if args[k] and args[k] ~= '' then
            table.insert(techs, trim(args[k]))
        end
    end
    return techs
end

-- 이미지 블록 (VN 먼저, 애니 다음). 파일명은 그대로 사용.
local function build_image_block(args)
    local images = {}
    if args['이미지_VN'] and args['이미지_VN'] ~= '' then
        table.insert(images, { title = "비주얼 노벨", file = trim(args['이미지_VN']) })
    end
    if args['이미지_애니'] and args['이미지_애니'] ~= '' then
        table.insert(images, { title = "애니메이션", file = trim(args['이미지_애니']) })
    end
    if args['이미지_추가'] and args['이미지_추가'] ~= '' then
        for img in string.gmatch(args['이미지_추가'], '([^,]+)') do
            img = trim(img)
            if img ~= '' then
                table.insert(images, { title = "추가", file = img })
            end
        end
    end

    if #images == 0 then
        return '[[파일:NoImage.png|200px]]'
    elseif #images == 1 then
        return string.format('[[파일:%s|200px]]', mw.text.encode(images[1].file))
    else
        local t = {}
        table.insert(t, '<tabber>')
        for i, im in ipairs(images) do
            local title = mw.text.escape(im.title)
            local file = mw.text.encode(im.file)
            table.insert(t, string.format('%s= [[파일:%s|200px]]', title, file))
            if i < #images then table.insert(t, '|-|') end
        end
        table.insert(t, '</tabber>')
        return table.concat(t, '\n')
    end
end

-- 이름 블록: 한글(첫줄) / 일어 → 영어(둘째줄, 일어 우선)
local function build_name_block(args)
    local kr = trim(args['이름'] or '')
    local jp = trim(args['이름_일어'] or '')
    local en = trim(args['이름_영어'] or '')

    local parts = {}
    if kr ~= '' then table.insert(parts, string.format('<div class="prf-name-kr">%s</div>', mw.text.escape(kr))) end

    if jp ~= '' or en ~= '' then
        local second = ''
        if jp ~= '' and en ~= '' then
            second = mw.text.escape(jp) .. ' / ' .. mw.text.escape(en)
        else
            second = mw.text.escape((jp ~= '' and jp) or en)
        end
        table.insert(parts, string.format('<div class="prf-name-sub">%s</div>', second))
    end

    return table.concat(parts, '\n')
end

-- 라벨+값 행 생성 (값 없으면 빈 문자열)
local function row(label, value)
    if not value or value == '' then return '' end
    return string.format('<div class="prf-row"><strong>%s</strong> %s</div>', mw.text.escape(label), mw.text.escape(value))
end

-- 나이 출력 규칙: VN 먼저, 애니 다음
local function build_age_row(args)
    local nv = trim(args['나이_VN'])
    local na = trim(args['나이_애니'])
    if nv ~= '' and na ~= '' then
        return string.format('<div class="prf-row"><strong>나이</strong> VN %s / 애니 %s</div>', mw.text.escape(nv), mw.text.escape(na))
    elseif nv ~= '' then
        return string.format('<div class="prf-row"><strong>나이</strong> VN %s</div>', mw.text.escape(nv))
    elseif na ~= '' then
        return string.format('<div class="prf-row"><strong>나이</strong> 애니 %s</div>', mw.text.escape(na))
    else
        return ''
    end
end

-- 메인 생성 함수 (ASCII 식별자 사용: "main")
function p.main(frame)
    local parent = frame:getParent() or frame
    local args = parent.args or {}
    for k, v in pairs(args) do args[k] = trim(v) end

    local theme = args['색상'] and args['색상'] ~= '' and args['색상'] or '#4cc9ff'

    local image_block = build_image_block(args)
    local name_block = build_name_block(args)

    -- 기본 정보
    local basic = ''
    basic = basic .. row('성별', args['성별'])
    basic = basic .. build_age_row(args)
    basic = basic .. row('생일', args['생일'])
    basic = basic .. row('신장', args['신장'])
    basic = basic .. row('체중', args['체중'])
    basic = basic .. row('머리색', args['머리색'])
    basic = basic .. row('눈색', args['눈색'])

    -- FC 프로필
    local fc = ''
    fc = fc .. row('포지션', args['포지션'])
    fc = fc .. row('소속 팀', args['소속_팀'])
    local techs = gather_techs(args)
    if #techs > 0 then
        local tstr = '<div class="prf-row"><strong>시그니처 기술</strong><ol class="sig-list">'
        for _, tname in ipairs(techs) do
            tstr = tstr .. string.format('<li>%s</li>', mw.text.escape(tname))
        end
        tstr = tstr .. '</ol></div>'
        fc = fc .. tstr
    end

    -- 개인정보 (학교는 개인정보 안에)
    local personal = ''
    personal = personal .. row('학교', args['학교'])
    personal = personal .. row('거주지', args['거주지'])
    personal = personal .. row('취미', args['취미'])
    personal = personal .. row('좋아하는 음식', args['좋아하는음식'])

    -- 성우
    local voice = ''
    voice = voice .. row('일본어', args['성우_JP'])
    voice = voice .. row('영어', args['성우_EN'])

    -- 데뷔
    local debut = ''
    debut = debut .. row('애니메이션', args['애니_데뷔'])
    debut = debut .. row('게임(VN)', args['게임_데뷔'])
    debut = debut .. row('만화', args['만화_데뷔'])

    -- HTML 구성
    local html = mw.html.create()
    html:tag('div'):addClass('prf-card'):cssText('display:flex;gap:14px;border-radius:10px;padding:12px;align-items:flex-start;'):done()

    -- 좌측 이미지
    local left = mw.html.create('div'):addClass('prf-left'):cssText('flex:0 0 36%;min-width:200px;')
    left:wikitext(image_block)
    html:node(left)

    -- 우측
    local right = mw.html.create('div'):addClass('prf-right'):cssText('flex:1 1 auto;')
    local right = mw.html.create('div'):addClass('prf-right'):cssText('flex:1 1 auto;')
    local output = mw.html.create('div')

    output:tag('div'):addClass('prf-name'):wikitext(name_block):done()

    if basic ~= '' then right:node(mw.html.create('div').addClass('prf-section').wikitext('<h4>기본 정보</h4>' .. basic)) end
    if fc ~= '' then right:node(mw.html.create('div').addClass('prf-section').wikitext('<h4>FC 프로필</h4>' .. fc)) end
    if personal ~= '' then right:node(mw.html.create('div').addClass('prf-section').wikitext('<h4>개인 정보</h4>' .. personal)) end
    if voice ~= '' then right:node(mw.html.create('div').addClass('prf-section').wikitext('<h4>성우</h4>' .. voice)) end
    if debut ~= '' then right:node(mw.html.create('div').addClass('prf-section').wikitext('<h4>데뷔</h4>' .. debut)) end

    html:node(right)

    -- 인라인 CSS (반응형 포함) - 테마 색상 적용
    local style = string.format([[
<style>
.prf-card { border:2px solid %s; background:#ffffff; }
.prf-name-kr { font-size:1.25em; font-weight:700; color:%s; margin-bottom:4px; }
.prf-name-sub { font-size:0.95em; color:#444; margin-bottom:8px; }
.prf-row { margin:4px 0; }
.prf-section h4 { margin:8px 0 6px 0; color:%s; font-size:0.95em; }
.sig-list { margin:4px 0 0 18px; padding:0; }
.tabber { margin-bottom:8px; }
@media screen and (max-width:768px) {
  .prf-card { flex-direction:column; }
  .prf-left { width:100%%; min-width:0; }
}
</style>
]], theme, theme, theme)

    return style .. tostring(html)
end

return p