Module:InfoboxNPC: Difference between revisions
Jump to navigation
Jump to search
mNo edit summary Tag: Reverted |
mNo edit summary Tags: Manual revert Reverted |
||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
-- | -- Define the CSS variables/hex codes as Lua constants for use in inline styles | ||
local STYLE_FLOATING = 'float: right !important; clear: right !important; max-width: 320px !important; margin: 0 0 16px 16px !important; border: 1px solid #B0C4D9 !important; border-radius: 10px !important; background-color: #FFFFFF !important; font-size: .9em !important; box-shadow: 0 2px 8px rgba(14, 77, 100, 0.1) !important;' | |||
local STYLE_HEADER = 'background: linear-gradient(135deg, #0E4D64 0%, #1a6a7a 100%) !important; color: white !important; padding: 10px 12px !important; text-align: center !important; font-weight: bold !important; font-size: 1.5em !important; border-top-left-radius: 9px !important; border-top-right-radius: 9px !important; text-shadow: 1px 1px 2px rgba(0,0,0,0.2) !important;' | |||
local STYLE_DATAROW = 'display: flex !important; justify-content: space-between !important; padding: 6px 10px !important; border-bottom: 1px dotted #D1DCE6 !important;' | |||
local STYLE_DATALABEL = 'font-weight: 600 !important; color: #2C3E50 !important; width: 40% !important; text-align: left !important;' | |||
local STYLE_DATAVALUE = 'color: #34495E !important; text-align: right !important; width: 60% !important;' | |||
local STYLE_FLOATING = | |||
local STYLE_HEADER = | |||
local STYLE_DATAROW = | |||
local STYLE_DATALABEL = | |||
local STYLE_DATAVALUE = | |||
-- Helper function to properly handle wikilinks | -- Helper function to properly handle wikilinks | ||
| Line 97: | Line 14: | ||
end | end | ||
-- If it already contains wikilink syntax, we need to process it carefully | |||
-- We'll use frame:preprocess to expand wikilinks | |||
local frame = mw.getCurrentFrame() | local frame = mw.getCurrentFrame() | ||
| Line 109: | Line 28: | ||
end | end | ||
-- Function to generate a single data row | -- Function to generate a single data row | ||
local function make_data_row(label, value, is_optional) | local function make_data_row(label, value, is_optional) | ||
if value and value ~= '' then | if value and value ~= '' then | ||
local formatted_value = format_wikitext(value) | local formatted_value = format_wikitext(value) | ||
return string.format( | return string.format( | ||
'<div | '<div style="%s"><span style="%s">%s:</span> <span style="%s">%s</span></div>', | ||
STYLE_DATAROW, | STYLE_DATAROW, | ||
STYLE_DATALABEL, | STYLE_DATALABEL, | ||
label, | label, | ||
| Line 131: | Line 44: | ||
return '' | return '' | ||
else | else | ||
return '' | -- For non-optional fields, show "Unknown" if empty | ||
return string.format( | |||
'<div style="%s"><span style="%s">%s:</span> <span style="%s"><em>Unknown</em></span></div>', | |||
STYLE_DATAROW, | |||
STYLE_DATALABEL, | |||
label, | |||
STYLE_DATAVALUE | |||
) | |||
end | end | ||
end | end | ||
-- Function to create a section divider | -- Function to create a section divider | ||
local function make_section(title) | local function make_section(title) | ||
return string.format( | return string.format( | ||
'<div style="padding: 10px | '<div class="section-title" style="padding: 8px 10px; background-color: #E8F4F8 !important; color: #0E4D64 !important; font-weight: bold; font-size: 1.1em; border-top: 1px solid #B0C4D9; border-bottom: 1px solid #B0C4D9; margin-top: 5px;">%s</div>', | ||
title | title | ||
) | ) | ||
end | end | ||
| Line 188: | Line 71: | ||
local html = {} | local html = {} | ||
-- Start the main infobox container | -- Start the main infobox container | ||
table.insert(html, string.format('<div class="npc-infobox" style="%s">', STYLE_FLOATING)) | table.insert(html, string.format('<div class="npc-infobox" style="%s">', STYLE_FLOATING)) | ||
-- Header/Title | -- Header/Title | ||
table.insert(html, string.format( | table.insert(html, string.format('<div class="npc-header" style="%s">%s</div>', STYLE_HEADER, name)) | ||
-- Image Section | -- Image Section | ||
if image and image ~= '' then | if image and image ~= '' then | ||
local image_link = string.format('[[File:%s|250px|alt=%s|class=npc-portrait]]', image, name) | local image_link = string.format('[[File:%s|250px|alt=%s|class=npc-portrait]]', image, name) | ||
table.insert(html, string.format( | table.insert(html, string.format('<div class="npc-image" style="padding: 12px !important; text-align: center !important; background-color: #F8FAFC;">%s</div>', image_link)) | ||
end | end | ||
-- Start Quick Facts Section | -- Start Quick Facts Section | ||
table.insert(html, make_section('Character Details')) | |||
-- | -- Core Character Data Rows | ||
table.insert(html, make_data_row('Gender', args.gender)) | |||
table.insert(html, make_data_row('Age', args.age, true)) | |||
table.insert(html, make_data_row('Race', args.race)) | |||
table.insert(html, make_data_row('Role', args.role)) | |||
table.insert(html, make_data_row('Location', args.location)) | |||
-- Category and Subcategory with wikilink support | |||
if args.category or args.sub then | |||
table.insert(html, make_section('Classification')) | |||
table.insert(html, make_data_row('Category', args.category, true)) | |||
table.insert(html, make_data_row('Subcategory', args.sub, true)) | |||
end | end | ||
| Line 251: | Line 104: | ||
local has_schedule = args.schedule1 or args.schedule2 or args.schedule3 | local has_schedule = args.schedule1 or args.schedule2 or args.schedule3 | ||
if has_schedule then | if has_schedule then | ||
table.insert(html, make_section('Daily Schedule')) | table.insert(html, make_section('Daily Schedule')) | ||
-- Create schedule | -- Create a mini-schedule table | ||
local schedule_html = | local schedule_html = '<div style="padding: 5px 10px; font-size: 0.95em;">' | ||
if args.schedule1 and args.schedule1 ~= '' then | if args.schedule1 and args.schedule1 ~= '' then | ||
schedule_html = schedule_html .. '<div style="padding: 3px 0;">• ' .. mw.text.nowiki(args.schedule1) .. '</div>' | |||
end | end | ||
if args.schedule2 and args.schedule2 ~= '' then | if args.schedule2 and args.schedule2 ~= '' then | ||
schedule_html = schedule_html .. '<div style="padding: 3px 0;">• ' .. mw.text.nowiki(args.schedule2) .. '</div>' | |||
end | end | ||
if args.schedule3 and args.schedule3 ~= '' then | if args.schedule3 and args.schedule3 ~= '' then | ||
schedule_html = schedule_html .. '<div style="padding: 3px 0;">• ' .. mw.text.nowiki(args.schedule3) .. '</div>' | |||
schedule_html = schedule_html .. | |||
end | end | ||
| Line 293: | Line 123: | ||
end | end | ||
-- Metadata note (for internal references) | -- Metadata note (for internal references) | ||
if args.note and args.note ~= '' then | if args.note and args.note ~= '' then | ||
table.insert(html, | table.insert(html, make_section('Notes')) | ||
table.insert(html, string.format('<div style="padding: 8px 10px; font-size: 0.85em; color: #7B8A8B; font-style: italic; background-color: #F5F7FA; border-radius: 4px; margin: 5px 10px;">%s</div>', mw.text.nowiki(args.note))) | |||
table.insert(html, string.format( | |||
end | end | ||
-- End container | -- End container | ||
table.insert(html, '</div>') -- End npc-infobox | table.insert(html, '</div>') -- End npc-infobox | ||
return table.concat(html, '\n') | return table.concat(html, '\n') | ||
Revision as of 03:03, 6 February 2026
Documentation for this module may be created at Module:InfoboxNPC/doc
local p = {}
-- Define the CSS variables/hex codes as Lua constants for use in inline styles
local STYLE_FLOATING = 'float: right !important; clear: right !important; max-width: 320px !important; margin: 0 0 16px 16px !important; border: 1px solid #B0C4D9 !important; border-radius: 10px !important; background-color: #FFFFFF !important; font-size: .9em !important; box-shadow: 0 2px 8px rgba(14, 77, 100, 0.1) !important;'
local STYLE_HEADER = 'background: linear-gradient(135deg, #0E4D64 0%, #1a6a7a 100%) !important; color: white !important; padding: 10px 12px !important; text-align: center !important; font-weight: bold !important; font-size: 1.5em !important; border-top-left-radius: 9px !important; border-top-right-radius: 9px !important; text-shadow: 1px 1px 2px rgba(0,0,0,0.2) !important;'
local STYLE_DATAROW = 'display: flex !important; justify-content: space-between !important; padding: 6px 10px !important; border-bottom: 1px dotted #D1DCE6 !important;'
local STYLE_DATALABEL = 'font-weight: 600 !important; color: #2C3E50 !important; width: 40% !important; text-align: left !important;'
local STYLE_DATAVALUE = 'color: #34495E !important; text-align: right !important; width: 60% !important;'
-- Helper function to properly handle wikilinks
local function format_wikitext(value)
if not value or value == '' then
return ''
end
-- If it already contains wikilink syntax, we need to process it carefully
-- We'll use frame:preprocess to expand wikilinks
local frame = mw.getCurrentFrame()
-- Check if it looks like a wikilink
if string.find(value, '%[%[') and string.find(value, '%]%]') then
-- It's a wikilink, expand it through the parser
return frame:preprocess(value)
else
-- Plain text, escape it
return mw.text.nowiki(value)
end
end
-- Function to generate a single data row
local function make_data_row(label, value, is_optional)
if value and value ~= '' then
local formatted_value = format_wikitext(value)
return string.format(
'<div style="%s"><span style="%s">%s:</span> <span style="%s">%s</span></div>',
STYLE_DATAROW,
STYLE_DATALABEL,
label,
STYLE_DATAVALUE,
formatted_value
)
elseif is_optional then
return ''
else
-- For non-optional fields, show "Unknown" if empty
return string.format(
'<div style="%s"><span style="%s">%s:</span> <span style="%s"><em>Unknown</em></span></div>',
STYLE_DATAROW,
STYLE_DATALABEL,
label,
STYLE_DATAVALUE
)
end
end
-- Function to create a section divider
local function make_section(title)
return string.format(
'<div class="section-title" style="padding: 8px 10px; background-color: #E8F4F8 !important; color: #0E4D64 !important; font-weight: bold; font-size: 1.1em; border-top: 1px solid #B0C4D9; border-bottom: 1px solid #B0C4D9; margin-top: 5px;">%s</div>',
title
)
end
-- Main function to create the infobox HTML
function p.infobox(frame)
local args = frame:getParent().args
local name = args.name or 'Unknown Character'
local image = args.image
local html = {}
-- Start the main infobox container
table.insert(html, string.format('<div class="npc-infobox" style="%s">', STYLE_FLOATING))
-- Header/Title
table.insert(html, string.format('<div class="npc-header" style="%s">%s</div>', STYLE_HEADER, name))
-- Image Section
if image and image ~= '' then
local image_link = string.format('[[File:%s|250px|alt=%s|class=npc-portrait]]', image, name)
table.insert(html, string.format('<div class="npc-image" style="padding: 12px !important; text-align: center !important; background-color: #F8FAFC;">%s</div>', image_link))
end
-- Start Quick Facts Section
table.insert(html, make_section('Character Details'))
-- Core Character Data Rows
table.insert(html, make_data_row('Gender', args.gender))
table.insert(html, make_data_row('Age', args.age, true))
table.insert(html, make_data_row('Race', args.race))
table.insert(html, make_data_row('Role', args.role))
table.insert(html, make_data_row('Location', args.location))
-- Category and Subcategory with wikilink support
if args.category or args.sub then
table.insert(html, make_section('Classification'))
table.insert(html, make_data_row('Category', args.category, true))
table.insert(html, make_data_row('Subcategory', args.sub, true))
end
-- Start Schedule Section (if schedule data exists)
local has_schedule = args.schedule1 or args.schedule2 or args.schedule3
if has_schedule then
table.insert(html, make_section('Daily Schedule'))
-- Create a mini-schedule table
local schedule_html = '<div style="padding: 5px 10px; font-size: 0.95em;">'
if args.schedule1 and args.schedule1 ~= '' then
schedule_html = schedule_html .. '<div style="padding: 3px 0;">• ' .. mw.text.nowiki(args.schedule1) .. '</div>'
end
if args.schedule2 and args.schedule2 ~= '' then
schedule_html = schedule_html .. '<div style="padding: 3px 0;">• ' .. mw.text.nowiki(args.schedule2) .. '</div>'
end
if args.schedule3 and args.schedule3 ~= '' then
schedule_html = schedule_html .. '<div style="padding: 3px 0;">• ' .. mw.text.nowiki(args.schedule3) .. '</div>'
end
schedule_html = schedule_html .. '</div>'
table.insert(html, schedule_html)
end
-- Metadata note (for internal references)
if args.note and args.note ~= '' then
table.insert(html, make_section('Notes'))
table.insert(html, string.format('<div style="padding: 8px 10px; font-size: 0.85em; color: #7B8A8B; font-style: italic; background-color: #F5F7FA; border-radius: 4px; margin: 5px 10px;">%s</div>', mw.text.nowiki(args.note)))
end
-- End container
table.insert(html, '</div>') -- End npc-infobox
return table.concat(html, '\n')
end
return p