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



900Articles

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

편집 요약 없음
편집 요약 없음
21번째 줄: 21번째 줄:
end
end


-- 이미지 블록 (VN 먼저, 애니 다음). 파일명은 그대로 사용.
-- 이미지 블록 (탭 기능을 표준 위키텍스트로 반환)
local function build_image_block(args)
local function build_image_block(args)
     local images = {}
     local images = {}
     if args['이미지_VN'] and args['이미지_VN'] ~= '' then
     if args['이미지_VN'] and args['이미지_VN'] ~= '' then
         table.insert(images, { title = "비주얼 노벨", file = trim(args['이미지_VN']) })
         table.insert(images, { title = "VN", file = trim(args['이미지_VN']) })
     end
     end
     if args['이미지_애니'] and args['이미지_애니'] ~= '' then
     if args['이미지_애니'] and args['이미지_애니'] ~= '' then
         table.insert(images, { title = "애니메이션", file = trim(args['이미지_애니']) })
         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
     end
    -- 추가 이미지는 생략 (탭 충돌 방지)
      
      
     if #images == 0 then
     if #images == 0 then
         return '[[파일:NoImage.png|200px]]'
         return '[[파일:NoImage.png|250px|center]]'
     elseif #images == 1 then
     elseif #images == 1 then
         return string.format('[[파일:%s|200px]]', mw.text.encode(images[1].file))
         return string.format('[[파일:%s|250px|center]]', mw.text.encode(images[1].file))
     else
     else
         local t = {}
         -- 탭 대신 간단한 이미지 갤러리 또는 첫 번째 이미지 사용 (가장 안전)
        table.insert(t, '<tabber>')
         return string.format('[[파일:%s|250px|center]]<div style="font-size:80%%;text-align:center;">(VN/애니 버전 전환은 갤러리/탭 구현 필요)</div>', mw.text.encode(images[1].file))
         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
end
end


-- 이름 블록: 한글(첫줄) / 일어 → 영어(둘째줄, 일어 우선)
-- 이름 블록 (표 셀용으로 간단히 변환)
local function build_name_block(args)
local function build_name_block(args)
     local kr = trim(args['이름'] or '')
     local kr = trim(args['이름'] or '')
63번째 줄: 48번째 줄:
     local en = trim(args['이름_영어'] or '')
     local en = trim(args['이름_영어'] or '')
     local parts = {}
     local parts = {}
     if kr ~= '' then table.insert(parts, string.format('<div class="prf-name-kr">%s</div>', mw.text.escape(kr))) end
     if kr ~= '' then table.insert(parts, string.format('<strong>%s</strong>', mw.text.escape(kr))) end
     if jp ~= '' or en ~= '' then
     if jp ~= '' or en ~= '' then
         local second = ''
         local second = ''
71번째 줄: 56번째 줄:
             second = mw.text.escape((jp ~= '' and jp) or en)
             second = mw.text.escape((jp ~= '' and jp) or en)
         end
         end
         table.insert(parts, string.format('<div class="prf-name-sub">%s</div>', second))
         table.insert(parts, string.format('<br/><span style="font-size:90%%;">(%s)</span>', second))
     end
     end
     return table.concat(parts, '\n')
     return table.concat(parts, '\n')
end
end


-- 라벨+값 행 생성 (값 없으면 빈 문자열)
-- 라벨+값 행 생성 (표의 행)
local function row(label, value)
local function table_row(label, value, is_header)
     if not value or value == '' then return '' end
     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))
    local tag = is_header and '!' or '|'
     return string.format('|- \n|%s style="width: 30%%; background-color: #f2f2f2; padding: 5px;" | %s \n|%s style="padding: 5px;" | %s', tag, mw.text.escape(label), tag, mw.text.escape(value))
end
end


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


-- 메인 생성 함수 (ASCII 식별자 사용: "main")
-- 메인 생성 함수 (순수 위키텍스트 반환)
function p.main(frame)
function p.main(frame)
     local parent = frame:getParent() or frame
     local parent = frame:getParent() or frame
     local args = parent.args or {}
     local args = parent.args or {}
      
      
    -- 인수를 안전하게 트림 및 할당
     for k, v in pairs(args) do args[k] = trim(v) end
     for k, v in pairs(args) do args[k] = trim(v) end
      
      
     local theme = args['색상'] and args['색상'] ~= '' and args['색상'] or '#4cc9ff'
     local theme_color = args['색상'] and args['색상'] ~= '' and args['색상'] or '#007bff'
   
    -- ********** 위키 테이블 문자열 구성 시작 **********
    local wiki_table = {}
      
      
     -- ********** 변수 초기화 강화 **********
     -- 외부 테이블 시작 (표준 인포박스 스타일)
     -- 모든 지역 변수를 nil이 아닌 빈 문자열로 초기화하여 안전성 확보
     table.insert(wiki_table, string.format('{| class="infobox" style="width: 300px; margin: 0 0 1em 1em; border: 1px solid #aaa; border-collapse: collapse; background-color: #f9f9f9; float: right; font-size: 90%%;"'))
    local image_block = ''
    local name_block = ''
    local basic = ''
    local fc = ''
    local personal = ''
    local voice = ''
    local debut = ''
      
      
     -- 함수 호출 (이 함수들은 문자열을 반환하므로 안전)
     -- 1. 제목 및 이미지
     image_block = build_image_block(args)
    table.insert(wiki_table, string.format('! colspan="2" style="background-color: %s; color: white; padding: 5px; text-align: center; font-size: 110%%;" | %s 프로필', theme_color, args['이름'] or ''))
     name_block = build_name_block(args)
     table.insert(wiki_table, '|-')
     table.insert(wiki_table, string.format('| colspan="2" style="padding: 10px; text-align: center;" | %s', build_image_block(args)))
      
      
     -- 기본 정보 내용 구성
     -- 2. 이름 정보 (이름 블록을 하나의 셀로 처리)
    basic = basic .. row('성별', args['성별'])
     table.insert(wiki_table, '|-')
    basic = basic .. build_age_row(args)
     table.insert(wiki_table, string.format('| colspan="2" style="text-align: center; padding: 5px;" | %s', build_name_block(args)))
     basic = basic .. row('생일', args['생일'])
 
     basic = basic .. row('신장', args['신장'])
    basic = basic .. row('체중', args['체중'])
    basic = basic .. row('머리색', args['머리색'])
    basic = basic .. row('눈색', args['눈색'])
      
      
     -- FC 프로필 내용 구성
     -- 3. 기본 정보
     fc = fc .. row('포지션', args['포지션'])
    table.insert(wiki_table, '|-')
     fc = fc .. row('소속 팀', args['소속_팀'])
     table.insert(wiki_table, string.format('! colspan="2" style="background-color: #e0e0e0; padding: 5px; text-align: center;" | 기본 정보'))
   
    table.insert(wiki_table, build_age_row(args))
    table.insert(wiki_table, table_row('성별', args['성별']))
    table.insert(wiki_table, table_row('생일', args['생일']))
    table.insert(wiki_table, table_row('신장', args['신장']))
    table.insert(wiki_table, table_row('체중', args['체중']))
    table.insert(wiki_table, table_row('머리색', args['머리색']))
    table.insert(wiki_table, table_row('눈색', args['눈색']))
    table.insert(wiki_table, table_row('학교', args['학교']))
    table.insert(wiki_table, table_row('거주지', args['거주지']))
   
     -- 4. FC 프로필
    local fc_content = table_row('포지션', args['포지션']) .. table_row('소속 팀', args['소속_팀'])
     local techs = gather_techs(args)
     local techs = gather_techs(args)
     if #techs > 0 then
     if #techs > 0 then
         local tstr = '<div class="prf-row"><strong>시그니처 기술</strong><ol class="sig-list">'
         fc_content = fc_content .. table_row('시그니처 기술', table.concat(techs, '<br/>'))
        for _, tname in ipairs(techs) do
    end
            tstr = tstr .. string.format('<li>%s</li>', mw.text.escape(tname))
 
         end
    if trim(args['포지션']) ~= '' or trim(args['소속_팀']) ~= '' or #techs > 0 then
        tstr = tstr .. '</ol></div>'
        table.insert(wiki_table, '|-')
         fc = fc .. tstr
         table.insert(wiki_table, string.format('! colspan="2" style="background-color: #a0d0ff; padding: 5px; text-align: center;" | FC 프로필'))
         table.insert(wiki_table, fc_content)
     end
     end
      
      
     -- 개인정보 내용 구성
     -- 5. 성우 및 데뷔
    personal = personal .. row('학교', args['학교'])
     if trim(args['성우_JP']) ~= '' or trim(args['성우_EN']) ~= '' then
    personal = personal .. row('거주지', args['거주지'])
        table.insert(wiki_table, '|-')
    personal = personal .. row('취미', args['취미'])
        table.insert(wiki_table, string.format('! colspan="2" style="background-color: #e0e0e0; padding: 5px; text-align: center;" | 성우 정보'))
    personal = personal .. row('좋아하는 음식', args['좋아하는음식'])
        table.insert(wiki_table, table_row('일본어', args['성우_JP']))
   
        table.insert(wiki_table, table_row('영어', args['성우_EN']))
    -- 성우 내용 구성
     voice = voice .. row('일본어', args['성우_JP'])
    voice = voice .. row('영어', args['성우_EN'])
   
    -- 데뷔 내용 구성
    debut = debut .. row('애니메이션', args['애니_데뷔'])
    debut = debut .. row('게임(VN)', args['게임_데뷔'])
    debut = debut .. row('만화', args['만화_데뷔'])
   
   
    -- 최종 HTML 문자열 구성 (html 테이블은 이 지점에서 안전하게 초기화 및 사용됨)
    local html = {}
    table.insert(html, '<div class="prf-card" style="display:flex;gap:14px;border-radius:10px;padding:12px;align-items:flex-start;">')
   
    -- 좌측 이미지
    table.insert(html, '<div class="prf-left" style="flex:0 0 36%;min-width:200px;">')
    table.insert(html, image_block) -- 위키텍스트 이미지 삽입
    table.insert(html, '</div>')
   
    -- 우측 정보
    table.insert(html, '<div class="prf-right" style="flex:1 1 auto;">')
   
    -- 이름 블록
    table.insert(html, name_block)
   
    -- 섹션별 정보 (내용이 있을 경우에만 출력)
    local function add_section(title, content)
        if content ~= '' then
            table.insert(html, string.format('<div class="prf-section"><h4>%s</h4>%s</div>', title, content))
        end
     end
     end


     add_section('기본 정보', basic)
     table.insert(wiki_table, '|}') -- 테이블 닫기
    add_section('FC 프로필', fc)
    add_section('개인 정보', personal)
    add_section('성우', voice)
    add_section('데뷔', debut)


    table.insert(html, '</div>')
     -- 최종 출력: 스타일 태그가 없으므로 Lua 모듈은 순수한 위키텍스트를 반환함.
    table.insert(html, '</div>')
     return table.concat(wiki_table, '\n')
   
    -- 인라인 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)
   
     -- 최종 출력: 스타일 + HTML 문자열 (table.concat(html, '\n')에서 html은 절대 nil이 아님)
     return style .. table.concat(html, '\n')
end
end


return p
return p

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

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

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

-- 이미지 블록 (탭 기능을 표준 위키텍스트로 반환)
local function build_image_block(args)
    local images = {}
    if args['이미지_VN'] and args['이미지_VN'] ~= '' then
        table.insert(images, { title = "VN", file = trim(args['이미지_VN']) })
    end
    if args['이미지_애니'] and args['이미지_애니'] ~= '' then
        table.insert(images, { title = "애니", file = trim(args['이미지_애니']) })
    end
    -- 추가 이미지는 생략 (탭 충돌 방지)
    
    if #images == 0 then
        return '[[파일:NoImage.png|250px|center]]'
    elseif #images == 1 then
        return string.format('[[파일:%s|250px|center]]', mw.text.encode(images[1].file))
    else
        -- 탭 대신 간단한 이미지 갤러리 또는 첫 번째 이미지 사용 (가장 안전)
        return string.format('[[파일:%s|250px|center]]<div style="font-size:80%%;text-align:center;">(VN/애니 버전 전환은 갤러리/탭 구현 필요)</div>', mw.text.encode(images[1].file))
    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('<strong>%s</strong>', 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('<br/><span style="font-size:90%%;">(%s)</span>', second))
    end
    return table.concat(parts, '\n')
end

-- 라벨+값 행 생성 (표의 행)
local function table_row(label, value, is_header)
    if not value or value == '' then return '' end
    local tag = is_header and '!' or '|'
    return string.format('|- \n|%s style="width: 30%%; background-color: #f2f2f2; padding: 5px;" | %s \n|%s style="padding: 5px;" | %s', tag, mw.text.escape(label), tag, mw.text.escape(value))
end

-- 나이 출력 규칙 (표의 행)
local function build_age_row(args)
    local nv = trim(args['나이_VN'])
    local na = trim(args['나이_애니'])
    if nv ~= '' and na ~= '' then
        return table_row('나이', 'VN ' .. nv .. ' / 애니 ' .. na)
    elseif nv ~= '' then
        return table_row('나이', 'VN ' .. nv)
    elseif na ~= '' then
        return table_row('나이', '애니 ' .. na)
    else
        return ''
    end
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_color = args['색상'] and args['색상'] ~= '' and args['색상'] or '#007bff'
    
    -- ********** 위키 테이블 문자열 구성 시작 **********
    local wiki_table = {}
    
    -- 외부 테이블 시작 (표준 인포박스 스타일)
    table.insert(wiki_table, string.format('{| class="infobox" style="width: 300px; margin: 0 0 1em 1em; border: 1px solid #aaa; border-collapse: collapse; background-color: #f9f9f9; float: right; font-size: 90%%;"'))
    
    -- 1. 제목 및 이미지
    table.insert(wiki_table, string.format('! colspan="2" style="background-color: %s; color: white; padding: 5px; text-align: center; font-size: 110%%;" | %s 프로필', theme_color, args['이름'] or ''))
    table.insert(wiki_table, '|-')
    table.insert(wiki_table, string.format('| colspan="2" style="padding: 10px; text-align: center;" | %s', build_image_block(args)))
    
    -- 2. 이름 정보 (이름 블록을 하나의 셀로 처리)
    table.insert(wiki_table, '|-')
    table.insert(wiki_table, string.format('| colspan="2" style="text-align: center; padding: 5px;" | %s', build_name_block(args)))

    
    -- 3. 기본 정보
    table.insert(wiki_table, '|-')
    table.insert(wiki_table, string.format('! colspan="2" style="background-color: #e0e0e0; padding: 5px; text-align: center;" | 기본 정보'))
    
    table.insert(wiki_table, build_age_row(args))
    table.insert(wiki_table, table_row('성별', args['성별']))
    table.insert(wiki_table, table_row('생일', args['생일']))
    table.insert(wiki_table, table_row('신장', args['신장']))
    table.insert(wiki_table, table_row('체중', args['체중']))
    table.insert(wiki_table, table_row('머리색', args['머리색']))
    table.insert(wiki_table, table_row('눈색', args['눈색']))
    table.insert(wiki_table, table_row('학교', args['학교']))
    table.insert(wiki_table, table_row('거주지', args['거주지']))
    
    -- 4. FC 프로필
    local fc_content = table_row('포지션', args['포지션']) .. table_row('소속 팀', args['소속_팀'])
    local techs = gather_techs(args)
    if #techs > 0 then
        fc_content = fc_content .. table_row('시그니처 기술', table.concat(techs, '<br/>'))
    end

    if trim(args['포지션']) ~= '' or trim(args['소속_팀']) ~= '' or #techs > 0 then
        table.insert(wiki_table, '|-')
        table.insert(wiki_table, string.format('! colspan="2" style="background-color: #a0d0ff; padding: 5px; text-align: center;" | FC 프로필'))
        table.insert(wiki_table, fc_content)
    end
    
    -- 5. 성우 및 데뷔
    if trim(args['성우_JP']) ~= '' or trim(args['성우_EN']) ~= '' then
        table.insert(wiki_table, '|-')
        table.insert(wiki_table, string.format('! colspan="2" style="background-color: #e0e0e0; padding: 5px; text-align: center;" | 성우 정보'))
        table.insert(wiki_table, table_row('일본어', args['성우_JP']))
        table.insert(wiki_table, table_row('영어', args['성우_EN']))
    end

    table.insert(wiki_table, '|}') -- 테이블 닫기

    -- 최종 출력: 스타일 태그가 없으므로 Lua 모듈은 순수한 위키텍스트를 반환함.
    return table.concat(wiki_table, '\n')
end

return p