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



900Articles

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

편집 요약 없음
편집 요약 없음
1번째 줄: 1번째 줄:
local p = {}
local p = {}
local mw = mw
local tt = mw.text


function p.main(frame)
-- 안전 문자열 트림
     local args = frame:getParent().args
local function trim(s)
     if not s then return '' end
    return tt.trim(tostring(s))
end


    local function F(x)
-- 시그니처 기술 수집 (시그니처기술1..10)
         return (args[x] and args[x] ~= "") and args[x] or "정보 없음"
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
    -- 리스트 아이템 HTML로 반환
    if #techs > 0 then
        local tstr = '<ul class="prf-list">'
        for _, tname in ipairs(techs) do
            tstr = tstr .. string.format('<li>%s</li>', mw.text.escape(tname))
        end
        tstr = tstr .. '</ul>'
        return tstr
     end
     end
    return ''
end


     return string.format([[
-- 이미지 블록 (탭 기능 대신 선택된 이미지 반환)
<div class="profile-container" style="border:2px solid %s; padding:10px;">
local function build_image_block(args)
     local version = trim(args['버전'] or 'VN')
    local file_name = ''
   
    if version == 'Anime' then
        file_name = trim(args['이미지_Anime'] or '')
    else -- VN 또는 기본값
        file_name = trim(args['이미지_VN'] or '')
    end


     <div class="profile-left">
     if file_name ~= '' then
         <div class="tab-buttons">
         return string.format('<div class="prf-img-wrapper">[[파일:%s|250px|center]]</div>', mw.text.encode(file_name))
            <button class="tab-btn active">애니</button>
    else
            <button class="tab-btn">VN</button>
        return '<div class="prf-img-wrapper">[[파일:NoImage.png|250px|center]]</div>'
        </div>
    end
end


        <div class="profile-image-tabs">
-- 라벨+값 행 생성 (값 없으면 빈 문자열)
            <div class="tab-content active">
local function info_row(label, value)
                %s
    if not value or value == '' then return '' end
            </div>
    -- 목록 형태로 반환
            <div class="tab-content">
    return string.format('<li><strong>%s</strong>: %s</li>', mw.text.escape(label), mw.text.escape(value))
                %s
end
            </div>
        </div>
    </div>


     <div class="profile-right">
-- 섹션 헤더 생성
        <h2>%s</h2>
local function section_header(title)
        <span>%s / %s</span>
     return string.format('<div class="prf-header"><h4>%s</h4></div>', mw.text.escape(title))
end


        <table class="profile-table">
-- 나이 출력 규칙
            <tr><th>성별</th><td>%s</td></tr>
local function build_age_row(args)
            <tr><th>나이</th><td>애니: %s / VN: %s</td></tr>
    local nv = trim(args['나이_VN'])
            <tr><th>생일</th><td>%s</td></tr>
    local na = trim(args['나이_애니'])
            <tr><th>신장</th><td>%s</td></tr>
   
            <tr><th>체중</th><td>%s</td></tr>
    local age_str = ''
            <tr><th>머리색</th><td>%s</td></tr>
    if nv ~= '' and na ~= '' then
            <tr><th>눈색</th><td>%s</td></tr>
        age_str = string.format('VN %s / Anime %s', mw.text.escape(nv), mw.text.escape(na))
         </table>
    elseif nv ~= '' then
     </div>
        age_str = string.format('VN %s', mw.text.escape(nv))
</div>
    elseif na ~= '' then
        age_str = string.format('Anime %s', mw.text.escape(na))
    else
         return ''
    end
     return info_row('나이', age_str)
end


<style>
-- 메인 생성 함수
.profile-container{display:flex; gap:10px;}
function p.main(frame)
.profile-left{width:250px; text-align:center;}
    local parent = frame:getParent() or frame
.profile-right{flex:1;}
    local args = parent.args or {}
 
    for k, v in pairs(args) do args[k] = trim(v) end
.tab-buttons{display:flex; gap:5px; margin-bottom:5px;}
   
.tab-btn{flex:1; padding:5px; cursor:pointer; background:#ddd; border:none;}
    local theme = args['색상'] and args['색상'] ~= '' and args['색상'] or '#007bff'
.tab-btn.active{background:#999; font-weight:bold;}
   
 
    -- ********** 데이터 구성 **********
.tab-content{display:none;}
    local image_block = build_image_block(args)
.tab-content.active{display:block;}
   
 
    -- 이름 블록
@media(max-width:720px){
    local name_block = ''
     .profile-container{flex-direction:column;}
    name_block = name_block .. string.format('<div class="prf-name-kr">%s</div>', mw.text.escape(args['이름'] or ''))
     .profile-left{width:100%;}
    local sub_name = {}
}
    if args['이름_일어'] then table.insert(sub_name, mw.text.escape(args['이름_일어'])) end
</style>
    if args['이름_영어'] then table.insert(sub_name, mw.text.escape(args['이름_영어'])) end
 
    if #sub_name > 0 then
<script>
        name_block = name_block .. string.format('<div class="prf-name-sub">%s</div>', table.concat(sub_name, ' / '))
document.addEventListener("DOMContentLoaded", function(){
    end
    const buttons = document.querySelectorAll(".tab-btn");
   
    const tabs = document.querySelectorAll(".tab-content");
    -- 섹션별 정보 구성
    local sections = {}
   
    -- 1. 기본 정보
    local basic = {
        info_row('성별', args['성별']),
        build_age_row(args),
        info_row('생일', args['생일']),
        info_row('신장', args['신장']),
        info_row('체중', args['체중']),
        info_row('머리색', args['머리색']),
        info_row('눈색', args['눈색']),
    }
   
    -- 2. FC 프로필
    local fc_techs = gather_techs(args)
    local fc = {
        info_row('포지션', args['포지션']),
    }
    if fc_techs ~= '' then
        -- 시그니처 기술은 별도 HTML로 구성
        table.insert(fc, string.format('<li><strong>시그니처 기술</strong>:%s</li>', fc_techs))
    end
   
    -- 3. 개인 정보
    local personal = {
        info_row('학교', args['학교']),
        info_row('거주지', args['거주지']),
        info_row('취미', args['취미']),
        info_row('좋아하는 음식', args['좋아하는음식']),
    }
   
    -- 4. 성우
    local voice = {
        info_row('일본어', args['성우_JP']),
        info_row('영어', args['성우_EN']),
    }
   
    -- 5. 데뷔
    local debut = {
        info_row('애니메이션', args['애니_데뷔']),
        info_row('게임(VN)', args['게임_데뷔']),
        info_row('만화', args['만화_데뷔']),
    }
   
    -- ********** HTML 문자열 조립 **********
    local html = {}
   
    -- 전체 컨테이너 시작
    table.insert(html, string.format('<div class="prf-card-wrap" style="border: 1px solid %s; border-radius: 5px; max-width: 600px; margin: 1em auto;">', theme))
    table.insert(html, '<div class="prf-card-inner" style="display: flex; flex-wrap: wrap;">')
   
    -- 좌측: 이미지 및 스위치 (40%)
    table.insert(html, '<div class="prf-left-col" style="flex: 0 0 40%; padding: 10px; border-right: 1px solid #ddd;">')
    table.insert(html, image_block)
    -- 버전 스위치 (간단한 HTML 텍스트로 대체)
    table.insert(html, '<div style="text-align: center; font-size: 85%; margin-top: 5px;">(VN / Anime 스위치 필요)</div>')
    table.insert(html, '</div>')
   
    -- 우측: 정보 (60%)
     table.insert(html, '<div class="prf-right-col" style="flex: 1 1 58%; padding: 10px; background-color: #f9f9f9;">')
   
    -- 이름 블록
     table.insert(html, string.format('<div class="prf-name-block">%s</div>', name_block))
    table.insert(html, '<hr style="border: 0; border-top: 1px solid #ccc; margin: 8px 0;">')
   
    -- 섹션 추가 함수 (빈 섹션은 제외)
    local function add_section(title, data_table)
        local content = table.concat(data_table, '\n')
        if content ~= '' then
            table.insert(html, section_header(title))
            table.insert(html, string.format('<ul class="prf-section-list">%s</ul>', content))
        end
    end


     buttons.forEach((btn,i)=>{
     add_section('기본 정보', basic)
        btn.onclick=function(){
    add_section('FC 프로필', fc)
            buttons.forEach(b=>b.classList.remove("active"));
    add_section('개인 정보', personal)
            tabs.forEach(t=>t.classList.remove("active"));
    add_section('성우', voice)
            btn.classList.add("active");
    add_section('데뷔', debut)
            tabs[i].classList.add("active");
   
        }
    table.insert(html, '</div>') -- prf-right-col 닫기
     });
    table.insert(html, '</div>') -- prf-card-inner 닫기
});
    table.insert(html, '</div>') -- prf-card-wrap 닫기
</script>
   
]],  
    -- ********** CSS 정의 **********
args["색상"] or "black",
     -- 인라인 CSS는 HTML 요소에 직접 넣었지만, 여기서 추가적인 스타일 정의 (선택 사항)
args["이미지_애니"] and ("[[파일:"..args["이미지_애니"].."|200px]]") or "이미지 없음",
    local style = [[
args["이미지_VN"] and ("[[파일:"..args["이미지_VN"].."|200px]]") or "이미지 없음",
    <style>
F("이름"), F("이름_일어"), F("이름_영어"),
    /* 폰트, 리스트 스타일 등 추가 정의 가능 */
F("성별"), F("나이_애니"), F("나이_VN"),
    .prf-name-kr { font-size: 1.3em; font-weight: bold; color: ]] .. theme .. [[; }
F("생일"), F("신장"), F("체중"),
    .prf-name-sub { font-size: 0.9em; color: #555; margin-top: 2px; }
F("머리색"), F("눈색")
    .prf-header h4 { margin: 8px 0 4px 0; padding: 0; font-size: 1em; color: ]] .. theme .. [[; border-bottom: 1px solid ]] .. theme .. [[; font-weight: bold; }
)
    .prf-section-list, .prf-list { list-style: none; margin: 0 0 10px 0; padding: 0; }
    .prf-section-list li, .prf-list li { margin: 3px 0; font-size: 0.95em; }
    .prf-img-wrapper { text-align: center; }
    @media screen and (max-width: 600px) {
        .prf-left-col, .prf-right-col { flex: 0 0 100% !important; border-right: none !important; }
        .prf-left-col { border-bottom: 1px solid #ddd; }
    }
    </style>
    ]]
   
    -- 최종 출력: 스타일 + HTML 문자열
    return style .. table.concat(html, '\n')
end
end


return p
return p

2025년 12월 5일 (금) 03:18 판

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

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
    -- 리스트 아이템 HTML로 반환
    if #techs > 0 then
        local tstr = '<ul class="prf-list">'
        for _, tname in ipairs(techs) do
            tstr = tstr .. string.format('<li>%s</li>', mw.text.escape(tname))
        end
        tstr = tstr .. '</ul>'
        return tstr
    end
    return ''
end

-- 이미지 블록 (탭 기능 대신 선택된 이미지 반환)
local function build_image_block(args)
    local version = trim(args['버전'] or 'VN')
    local file_name = ''
    
    if version == 'Anime' then
        file_name = trim(args['이미지_Anime'] or '')
    else -- VN 또는 기본값
        file_name = trim(args['이미지_VN'] or '')
    end

    if file_name ~= '' then
        return string.format('<div class="prf-img-wrapper">[[파일:%s|250px|center]]</div>', mw.text.encode(file_name))
    else
        return '<div class="prf-img-wrapper">[[파일:NoImage.png|250px|center]]</div>'
    end
end

-- 라벨+값 행 생성 (값 없으면 빈 문자열)
local function info_row(label, value)
    if not value or value == '' then return '' end
    -- 목록 형태로 반환
    return string.format('<li><strong>%s</strong>: %s</li>', mw.text.escape(label), mw.text.escape(value))
end

-- 섹션 헤더 생성
local function section_header(title)
    return string.format('<div class="prf-header"><h4>%s</h4></div>', mw.text.escape(title))
end

-- 나이 출력 규칙
local function build_age_row(args)
    local nv = trim(args['나이_VN'])
    local na = trim(args['나이_애니'])
    
    local age_str = ''
    if nv ~= '' and na ~= '' then
        age_str = string.format('VN %s / Anime %s', mw.text.escape(nv), mw.text.escape(na))
    elseif nv ~= '' then
        age_str = string.format('VN %s', mw.text.escape(nv))
    elseif na ~= '' then
        age_str = string.format('Anime %s', mw.text.escape(na))
    else
        return ''
    end
    return info_row('나이', age_str)
end

-- 메인 생성 함수
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 '#007bff'
    
    -- ********** 데이터 구성 **********
    local image_block = build_image_block(args)
    
    -- 이름 블록
    local name_block = ''
    name_block = name_block .. string.format('<div class="prf-name-kr">%s</div>', mw.text.escape(args['이름'] or ''))
    local sub_name = {}
    if args['이름_일어'] then table.insert(sub_name, mw.text.escape(args['이름_일어'])) end
    if args['이름_영어'] then table.insert(sub_name, mw.text.escape(args['이름_영어'])) end
    if #sub_name > 0 then
        name_block = name_block .. string.format('<div class="prf-name-sub">%s</div>', table.concat(sub_name, ' / '))
    end
    
    -- 섹션별 정보 구성
    local sections = {}
    
    -- 1. 기본 정보
    local basic = {
        info_row('성별', args['성별']),
        build_age_row(args),
        info_row('생일', args['생일']),
        info_row('신장', args['신장']),
        info_row('체중', args['체중']),
        info_row('머리색', args['머리색']),
        info_row('눈색', args['눈색']),
    }
    
    -- 2. FC 프로필
    local fc_techs = gather_techs(args)
    local fc = {
        info_row('포지션', args['포지션']),
    }
    if fc_techs ~= '' then
        -- 시그니처 기술은 별도 HTML로 구성
        table.insert(fc, string.format('<li><strong>시그니처 기술</strong>:%s</li>', fc_techs))
    end
    
    -- 3. 개인 정보
    local personal = {
        info_row('학교', args['학교']),
        info_row('거주지', args['거주지']),
        info_row('취미', args['취미']),
        info_row('좋아하는 음식', args['좋아하는음식']),
    }
    
    -- 4. 성우
    local voice = {
        info_row('일본어', args['성우_JP']),
        info_row('영어', args['성우_EN']),
    }
    
    -- 5. 데뷔
    local debut = {
        info_row('애니메이션', args['애니_데뷔']),
        info_row('게임(VN)', args['게임_데뷔']),
        info_row('만화', args['만화_데뷔']),
    }
    
    -- ********** HTML 문자열 조립 **********
    local html = {}
    
    -- 전체 컨테이너 시작
    table.insert(html, string.format('<div class="prf-card-wrap" style="border: 1px solid %s; border-radius: 5px; max-width: 600px; margin: 1em auto;">', theme))
    table.insert(html, '<div class="prf-card-inner" style="display: flex; flex-wrap: wrap;">')
    
    -- 좌측: 이미지 및 스위치 (40%)
    table.insert(html, '<div class="prf-left-col" style="flex: 0 0 40%; padding: 10px; border-right: 1px solid #ddd;">')
    table.insert(html, image_block)
    -- 버전 스위치 (간단한 HTML 텍스트로 대체)
    table.insert(html, '<div style="text-align: center; font-size: 85%; margin-top: 5px;">(VN / Anime 스위치 필요)</div>')
    table.insert(html, '</div>')
    
    -- 우측: 정보 (60%)
    table.insert(html, '<div class="prf-right-col" style="flex: 1 1 58%; padding: 10px; background-color: #f9f9f9;">')
    
    -- 이름 블록
    table.insert(html, string.format('<div class="prf-name-block">%s</div>', name_block))
    table.insert(html, '<hr style="border: 0; border-top: 1px solid #ccc; margin: 8px 0;">')
    
    -- 섹션 추가 함수 (빈 섹션은 제외)
    local function add_section(title, data_table)
        local content = table.concat(data_table, '\n')
        if content ~= '' then
            table.insert(html, section_header(title))
            table.insert(html, string.format('<ul class="prf-section-list">%s</ul>', content))
        end
    end

    add_section('기본 정보', basic)
    add_section('FC 프로필', fc)
    add_section('개인 정보', personal)
    add_section('성우', voice)
    add_section('데뷔', debut)
    
    table.insert(html, '</div>') -- prf-right-col 닫기
    table.insert(html, '</div>') -- prf-card-inner 닫기
    table.insert(html, '</div>') -- prf-card-wrap 닫기
    
    -- ********** CSS 정의 **********
    -- 인라인 CSS는 HTML 요소에 직접 넣었지만, 여기서 추가적인 스타일 정의 (선택 사항)
    local style = [[
    <style>
    /* 폰트, 리스트 스타일 등 추가 정의 가능 */
    .prf-name-kr { font-size: 1.3em; font-weight: bold; color: ]] .. theme .. [[; }
    .prf-name-sub { font-size: 0.9em; color: #555; margin-top: 2px; }
    .prf-header h4 { margin: 8px 0 4px 0; padding: 0; font-size: 1em; color: ]] .. theme .. [[; border-bottom: 1px solid ]] .. theme .. [[; font-weight: bold; }
    .prf-section-list, .prf-list { list-style: none; margin: 0 0 10px 0; padding: 0; }
    .prf-section-list li, .prf-list li { margin: 3px 0; font-size: 0.95em; }
    .prf-img-wrapper { text-align: center; }
    @media screen and (max-width: 600px) { 
        .prf-left-col, .prf-right-col { flex: 0 0 100% !important; border-right: none !important; }
        .prf-left-col { border-bottom: 1px solid #ddd; }
    }
    </style>
    ]]
    
    -- 최종 출력: 스타일 + HTML 문자열
    return style .. table.concat(html, '\n')
end

return p