← 모듈:푸른 저편의 포리듬/ 캐릭터 프로필문서 편집 권한이 없습니다. 다음 이유를 확인해주세요: 요청한 명령은 다음 권한을 가진 사용자에게 제한됩니다: 사용자. 문서의 원본을 보거나 복사할 수 있습니다. 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 -- 안전한 HTML 인코딩 (mw.text.html_encode 대체) local function safe_html_encode(s) if not s or s == '' then return '' end -- mw.text.html_encode가 있다면 사용 if mw.text and mw.text.html_encode then return mw.text.html_encode(tostring(s)) end -- 없으면 최소한의 수동 인코딩 s = tostring(s) s = s:gsub('&', '&') s = s:gsub('<', '<') s = s:gsub('>', '>') return s end -- 시그니처 기술 수집 및 HTML 리스트 반환 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 if #techs > 0 then -- 요청하신 디자인과 유사하게 ①, ② 등으로 표시 local tstr = '<ul style="list-style:none; margin:0; padding:0 0 0 10px; font-size:95%;">' for i, tname in ipairs(techs) do local marker = '①' if i == 2 then marker = '②' end if i == 3 then marker = '③' end if i > 3 then marker = '•' end -- 3개 초과는 점으로 처리 tstr = tstr .. string.format('<li style="margin-top:2px;">%s %s</li>', marker, safe_html_encode(tname)) end tstr = tstr .. '</ul>' return tstr end return '' end -- 이미지 블록 (표 셀 안에 들어갈 위키텍스트) local function build_image_block(args) local file_vn = trim(args['이미지_VN'] or '') local file_ani = trim(args['이미지_애니'] or '') local main_file = file_vn ~= '' and file_vn or file_ani ~= '' and file_ani or 'NoImage.png' local output = {} -- 이미지 table.insert(output, string.format('[[파일:%s|250px|center]]', mw.text.encode(main_file))) -- 탭 이미지 영역 텍스트 (위키텍스트 주석으로 처리하여 출력되지 않게 함) table.insert(output, '') table.insert(output, '<div style="text-align:center; font-size:85%; margin-top:5px;">(애니 / VN 스위치)</div>') return table.concat(output, '\n') end -- 이름 블록 (표 셀 안에 들어갈 HTML) local function build_name_block(args) local kr = trim(args['이름'] or '') local jp = trim(args['이름_일어'] or '') local en = trim(args['이름_영어'] or '') local parts = {} -- 이름: table.insert(parts, string.format('<strong style="font-size:1.1em;">이름: %s</strong>', safe_html_encode(kr))) local sub_parts = {} if jp ~= '' then table.insert(sub_parts, safe_html_encode(jp)) end if en ~= '' then table.insert(sub_parts, safe_html_encode(en)) end if #sub_parts > 0 then table.insert(parts, string.format('<div style="font-size:90%%; margin-top:2px;">%s</div>', table.concat(sub_parts, ' / '))) end return table.concat(parts, '\n') end -- 라벨+값 행 생성 (값 없으면 빈 문자열) local function info_row(label, value) if not value or value == '' then return '' end -- 목록 형태로 반환 ('- 라벨: 값' 형태) return string.format('<div style="margin: 3px 0; padding-left: 10px;">- <strong>%s</strong>: %s</div>', safe_html_encode(label), safe_html_encode(value)) 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', safe_html_encode(nv), safe_html_encode(na)) elseif nv ~= '' then age_str = string.format('VN %s', safe_html_encode(nv)) elseif na ~= '' then age_str = string.format('Anime %s', safe_html_encode(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 = build_name_block(args) -- 섹션별 정보 구성 local basic = table.concat({ info_row('성별', args['성별']), build_age_row(args), info_row('생일', args['생일']), info_row('신장', args['신장']), info_row('체중', args['체중']), info_row('머리색', args['머리색']), info_row('눈색', args['눈색']), }, '\n') local fc_techs = gather_techs(args) local fc = table.concat({ info_row('포지션', args['포지션']), }, '\n') if fc_techs ~= '' then fc = fc .. '<div style="margin: 3px 0; padding-left: 10px;">- <strong>시그니처 기술</strong>:</div>' .. fc_techs end local personal = table.concat({ info_row('학교', args['학교']), info_row('거주지', args['거주지']), info_row('취미', args['취미']), info_row('좋아하는 음식', args['좋아하는음식']), }, '\n') local voice = table.concat({ info_row('일본어', args['성우_JP']), info_row('영어', args['성우_EN']), }, '\n') local debut = table.concat({ info_row('애니메이션', args['애니_데뷔']), info_row('게임(VN)', args['게임_데뷔']), info_row('만화', args['만화_데뷔']), }, '\n') -- ********** 위키 테이블 문자열 조립 ********** local wiki_table = {} -- 1. 전체 컨테이너 테이블 시작 (2열: 이미지 / 정보) table.insert(wiki_table, string.format('{| class="wikitable" style="width: 100%%; max-width: 650px; border: 2px solid %s; border-collapse: collapse; margin: 1em auto; font-size: 95%%;"', safe_html_encode(theme))) table.insert(wiki_table, '|-') -- 2. 좌측 열 (이미지 영역) table.insert(wiki_table, string.format('| style="width: 35%%; vertical-align: top; padding: 10px; background-color: #f8f8f8;" | %s', image_block)) -- 3. 우측 열 (정보 영역) table.insert(wiki_table, '| style="width: 65%%; vertical-align: top; padding: 10px;" |') -- 우측 영역 내부 내용 (이름, 섹션 헤더, 정보 리스트) local right_content = {} table.insert(right_content, name_block) table.insert(right_content, '<hr style="border: 0; border-top: 1px solid #ccc; margin: 8px 0;">') local function add_section(title, content) if trim(content) ~= '' then table.insert(right_content, string.format('<h4 style="color:%s; margin:8px 0 4px 0; padding:0; font-size:1em; border-bottom:1px solid %s;"><%s></h4>', safe_html_encode(theme), safe_html_encode(theme), safe_html_encode(title))) table.insert(right_content, content) end end add_section('기본 정보', basic) add_section('FC 프로필', fc) add_section('개인 정보', personal) add_section('성우', voice) add_section('데뷔', debut) table.insert(wiki_table, table.concat(right_content, '\n')) -- 4. 테이블 닫기 table.insert(wiki_table, '|}') return table.concat(wiki_table, '\n') end return p 이 문서에서 사용한 틀: 모듈:푸른 저편의 포리듬/ 캐릭터 프로필/설명문서 (원본 보기) 모듈:푸른 저편의 포리듬/ 캐릭터 프로필 문서로 돌아갑니다.