Module:Soldier: Difference between revisions
Import soldier lead module |
Import soldier lead module |
||
| Line 3: | Line 3: | ||
local function trim(s) | local function trim(s) | ||
return mw.text.trim(tostring(s or '')) | return mw.text.trim(tostring(s or '')) | ||
end | |||
local function countChar(s, ch) | |||
local _, n = mw.ustring.gsub(s, ch, '') | |||
return n | |||
end | |||
local function tidyDisplay(s) | |||
s = trim(s) | |||
if s == '' then | |||
return '' | |||
end | |||
s = mw.text.decode(s, true) | |||
s = mw.ustring.gsub(s, mw.ustring.char(160), ' ') | |||
s = mw.ustring.gsub(s, mw.ustring.char(0xFFFD), '') | |||
s = mw.ustring.gsub(s, mw.ustring.char(0x200B), '') | |||
s = trim(s) | |||
local lower = mw.ustring.lower(s) | |||
if lower == '#n/a' or lower == 'n/a' or lower == 'none' or lower == 'null' or lower == '-' then | |||
return '' | |||
end | |||
if s == '.' or s == '?' then | |||
return '' | |||
end | |||
local prev | |||
repeat | |||
prev = s | |||
s = mw.ustring.gsub(s, '""', '"') | |||
until s == prev | |||
s = trim(s) | |||
local changed = true | |||
while changed and mw.ustring.len(s) >= 2 do | |||
changed = false | |||
local first = mw.ustring.sub(s, 1, 1) | |||
local last = mw.ustring.sub(s, -1) | |||
if first == '"' and last == '"' then | |||
local inner = mw.ustring.sub(s, 2, -2) | |||
if countChar(inner, '"') == 0 then | |||
s = trim(inner) | |||
changed = true | |||
elseif countChar(s, '"') % 2 == 1 then | |||
local second = mw.ustring.find(s, '"', 2, true) | |||
local slen = mw.ustring.len(s) | |||
if second and second + 1 < slen then | |||
local nxt = mw.ustring.sub(s, second + 1, second + 1) | |||
if mw.ustring.find(nxt, '%w') then | |||
s = mw.ustring.sub(s, 2) | |||
else | |||
s = mw.ustring.sub(s, 1, -2) | |||
end | |||
else | |||
s = mw.ustring.sub(s, 1, -2) | |||
end | |||
s = trim(s) | |||
changed = true | |||
end | |||
elseif first == "'" and last == "'" then | |||
local inner = mw.ustring.sub(s, 2, -2) | |||
if not mw.ustring.find(inner, "'", 1, true) then | |||
s = trim(inner) | |||
changed = true | |||
end | |||
end | |||
end | |||
local q = countChar(s, '"') | |||
local first = mw.ustring.sub(s, 1, 1) | |||
local last = mw.ustring.sub(s, -1) | |||
if first == '"' and q == 1 and last ~= '"' then | |||
s = trim(mw.ustring.sub(s, 2)) | |||
end | |||
last = mw.ustring.sub(s, -1) | |||
first = mw.ustring.sub(s, 1, 1) | |||
q = countChar(s, '"') | |||
if last == '"' and q == 1 and first ~= '"' then | |||
s = trim(mw.ustring.sub(s, 1, -2)) | |||
end | |||
s = mw.ustring.gsub(s, '^\\+', '') | |||
s = trim(s) | |||
if s == '"' or s == "'" or s == '.' or s == '?' or s == '\\' then | |||
return '' | |||
end | |||
s = mw.ustring.gsub(s, '%s+', ' ') | |||
return trim(s) | |||
end | end | ||
local function parentArg(frame, name) | local function parentArg(frame, name) | ||
local parent = frame:getParent() | local parent = frame:getParent() | ||
local raw | |||
if parent and parent.args[name] then | if parent and parent.args[name] then | ||
raw = parent.args[name] | |||
else | |||
raw = frame.args[name] | |||
end | end | ||
return | return tidyDisplay(raw) | ||
end | end | ||
| Line 19: | Line 107: | ||
end | end | ||
s = mw.ustring.lower(s) | s = mw.ustring.lower(s) | ||
s = mw.ustring.gsub(s, "(%a)([%w']*)", function(first, rest) | |||
return mw.ustring.upper(first) .. rest | return mw.ustring.upper(first) .. rest | ||
end) | end) | ||
return s | |||
end | |||
local function containsIgnoreCase(haystack, needle) | |||
return mw.ustring.find(mw.ustring.lower(haystack), mw.ustring.lower(needle), 1, true) ~= nil | |||
end | end | ||
| Line 51: | Line 144: | ||
end | end | ||
return name | return name | ||
end | |||
local function classLinkList(raw, withPrefix) | |||
local out = {} | |||
for part in mw.text.gsplit(raw, ';', true) do | |||
part = trim(part) | |||
if part ~= '' then | |||
if withPrefix then | |||
table.insert(out, string.format('[[Class %s]]', part)) | |||
else | |||
table.insert(out, string.format('[[Class %s|%s]]', part, part)) | |||
end | |||
end | |||
end | |||
return out | |||
end | |||
local function addHeader(tbl, text) | |||
tbl:tag('tr'):tag('th') | |||
:attr('colspan', '2') | |||
:addClass('infobox-header') | |||
:wikitext(text) | |||
end | |||
local function addRow(tbl, label, value, dataClass) | |||
if trim(value) == '' then | |||
return | |||
end | |||
local tr = tbl:tag('tr') | |||
tr:tag('th'):addClass('infobox-label'):wikitext(label) | |||
local td = tr:tag('td'):addClass('infobox-data') | |||
if dataClass and dataClass ~= '' then | |||
td:addClass(dataClass) | |||
end | |||
td:wikitext(value) | |||
end | end | ||
| Line 58: | Line 186: | ||
function p.classLinks(frame) | function p.classLinks(frame) | ||
return table.concat(classLinkList(parentArg(frame, 'class_number'), false), ', ') | |||
local | end | ||
function p.infobox(frame) | |||
if | local name = displayName(frame) | ||
local tbl = mw.html.create('table') | |||
tbl:addClass('infobox'):addClass('vcard'):addClass('soldier-infobox') | |||
tbl:tag('tr'):tag('th') | |||
:attr('colspan', '2') | |||
:addClass('infobox-above fn') | |||
:wikitext(name) | |||
local photo = parentArg(frame, 'photo') | |||
if photo ~= '' then | |||
local size = parentArg(frame, 'image_size') | |||
if size == '' then | |||
size = '220px' | |||
end | |||
local alt = parentArg(frame, 'alt') | |||
if alt == '' then | |||
alt = name | |||
end | |||
local td = tbl:tag('tr'):tag('td') | |||
:attr('colspan', '2') | |||
:addClass('infobox-image') | |||
td:wikitext(string.format('[[File:%s|%s|alt=%s]]', photo, size, alt)) | |||
local caption = parentArg(frame, 'caption') | |||
if caption ~= '' then | |||
td:tag('div'):addClass('infobox-caption'):wikitext(caption) | |||
end | |||
end | |||
local alias = parentArg(frame, 'alias') | |||
local birth = parentArg(frame, 'birth_year') | |||
local death = parentArg(frame, 'death_year') | |||
local nativity = parentArg(frame, 'nativity') | |||
local religion = parentArg(frame, 'religion') | |||
local marital = parentArg(frame, 'marital') | |||
local education = parentArg(frame, 'education') | |||
local occupation = parentArg(frame, 'occupation') | |||
local state = parentArg(frame, 'state') | |||
if alias ~= '' or birth ~= '' or death ~= '' or nativity ~= '' | |||
or religion ~= '' or marital ~= '' or education ~= '' | |||
or occupation ~= '' or state ~= '' then | |||
addHeader(tbl, 'Personal details') | |||
end | |||
addRow(tbl, 'Nickname', alias, 'nickname') | |||
addRow(tbl, 'Born', birth) | |||
addRow(tbl, 'Nativity', nativity) | |||
addRow(tbl, 'Died', death) | |||
addRow(tbl, 'Religion', religion) | |||
addRow(tbl, 'Spouse / marital', marital) | |||
addRow(tbl, 'Education', education) | |||
addRow(tbl, 'Occupation', occupation) | |||
if state ~= '' then | |||
addRow(tbl, 'State', titleCase(state)) | |||
end | |||
addHeader(tbl, 'Military service') | |||
addRow(tbl, 'Allegiance', 'United States') | |||
local branch = parentArg(frame, 'class_branch') | |||
if branch == '' then | |||
branch = 'United States Army' | |||
end | |||
addRow(tbl, 'Branch', branch) | |||
addRow(tbl, 'ASN', parentArg(frame, 'asn'), 'serial') | |||
local rankFinal = parentArg(frame, 'rank_final') | |||
local classRank = parentArg(frame, 'class_rank') | |||
if rankFinal ~= '' and classRank ~= '' and classRank ~= rankFinal then | |||
addRow(tbl, 'Rank', rankFinal) | |||
addRow(tbl, 'Rank at Ritchie', classRank) | |||
else | |||
local rank = rankFinal | |||
if rank == '' then | |||
rank = classRank | |||
end | end | ||
addRow(tbl, 'Rank', rank) | |||
end | end | ||
local classRaw = parentArg(frame, 'class_number') | |||
local classBits = classLinkList(classRaw, false) | |||
if #classBits > 0 then | |||
addRow(tbl, 'Camp Ritchie', 'Class ' .. table.concat(classBits, ', ')) | |||
end | |||
addRow(tbl, 'Section', parentArg(frame, 'class_section')) | |||
addRow(tbl, 'Other class', parentArg(frame, 'other_class')) | |||
local enlist = parentArg(frame, 'enlistment_place') | |||
if enlist ~= '' then | |||
addRow(tbl, 'Enlisted', titleCase(enlist)) | |||
end | |||
addRow(tbl, 'Assignment', parentArg(frame, 'assignment')) | |||
addRow(tbl, 'Unit / division', parentArg(frame, 'division')) | |||
addRow(tbl, 'IPW (German)', parentArg(frame, 'ipw_ge')) | |||
addRow(tbl, 'IPW (Italian)', parentArg(frame, 'ipw_it')) | |||
addRow(tbl, 'Overseas', parentArg(frame, 'overseas')) | |||
addRow(tbl, 'Special', parentArg(frame, 'special')) | |||
addRow(tbl, 'LOC', parentArg(frame, 'loc')) | |||
addRow(tbl, 'Arrived', parentArg(frame, 'date_arrive')) | |||
addRow(tbl, 'Departed', parentArg(frame, 'date_depart')) | |||
addRow(tbl, 'Certificate', parentArg(frame, 'certificate')) | |||
return tostring(tbl) | |||
end | end | ||
| Line 86: | Line 312: | ||
end | end | ||
local | local classLinks = classLinkList(parentArg(frame, 'class_number'), true) | ||
local trained | |||
if #classLinks == 1 then | if #classLinks == 1 then | ||
trained = ' who trained at [[Camp Ritchie]], Maryland, in ' .. classLinks[1] | |||
elseif #classLinks > 1 then | elseif #classLinks > 1 then | ||
trained = ' who trained at [[Camp Ritchie]], Maryland, in classes ' .. table.concat(classLinks, ', ') | |||
else | else | ||
trained = ' associated with Camp Ritchie, Maryland' | |||
end | end | ||
local | local first = string.format( | ||
"'''%s'''%s was a United States Army soldier%s.", | |||
name, | |||
dates, | |||
trained | |||
) | |||
local more = {} | |||
local enlist = parentArg(frame, 'enlistment_place') | local enlist = parentArg(frame, 'enlistment_place') | ||
local state = parentArg(frame, 'state') | local state = parentArg(frame, 'state') | ||
| Line 122: | Line 335: | ||
local place = titleCase(enlist) | local place = titleCase(enlist) | ||
if state ~= '' then | if state ~= '' then | ||
place = place .. ', ' .. | local stateTitle = titleCase(state) | ||
if not containsIgnoreCase(place, stateTitle) then | |||
place = place .. ', ' .. stateTitle | |||
end | |||
end | end | ||
table.insert( | table.insert(more, surname .. ' enlisted at ' .. place .. '.') | ||
elseif state ~= '' then | elseif state ~= '' then | ||
table.insert( | table.insert(more, 'Records list ' .. titleCase(state) .. ' as the state of enlistment or residence.') | ||
end | |||
local rank = parentArg(frame, 'rank_final') | |||
if rank == '' then | |||
rank = parentArg(frame, 'class_rank') | |||
end | |||
if rank ~= '' then | |||
table.insert(more, 'Records list the rank as ' .. rank .. '.') | |||
end | end | ||
local assignment = parentArg(frame, 'assignment') | local assignment = parentArg(frame, 'assignment') | ||
if assignment ~= '' then | if assignment ~= '' then | ||
table.insert( | table.insert(more, surname .. ' was assigned to ' .. assignment .. '.') | ||
end | end | ||
| Line 144: | Line 368: | ||
end | end | ||
if #ipw > 0 then | if #ipw > 0 then | ||
table.insert( | table.insert(more, 'Interrogation duty included ' .. table.concat(ipw, ' and ') .. '.') | ||
end | end | ||
if #more == 0 then | |||
return first | |||
return table.concat( | end | ||
return first .. '\n\n' .. table.concat(more, ' ') | |||
end | end | ||
return p | return p | ||