← 모듈:푸른 저편의 포리듬/ 캐릭터 프로필문서 편집 권한이 없습니다. 다음 이유를 확인해주세요: 요청한 명령은 다음 권한을 가진 사용자에게 제한됩니다: 사용자. 문서의 원본을 보거나 복사할 수 있습니다. 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 이 문서에서 사용한 틀: 모듈:푸른 저편의 포리듬/ 캐릭터 프로필/설명문서 (원본 보기) 모듈:푸른 저편의 포리듬/ 캐릭터 프로필 문서로 돌아갑니다.