Module:Part: Difference between revisions
Create Module:Part for rendering part infoboxes (via create-page on MediaWiki MCP Server) |
Change type badge to breadcrumb style: Part › [subtype] [type] (via update-page on MediaWiki MCP Server) |
||
| (4 intermediate revisions by 2 users not shown) | |||
| Line 111: | Line 111: | ||
'infobox-title' | 'infobox-title' | ||
) | ) | ||
-- Type badge (breadcrumb) | |||
local badgeWikitext = '[[:Category:Parts|Part]]' | |||
local badgeDetail = part_type or '' | |||
if part_subtype then | |||
badgeDetail = part_subtype .. ' ' .. badgeDetail | |||
end | |||
if badgeDetail ~= '' then | |||
badgeWikitext = badgeWikitext .. ' › ' .. badgeDetail | |||
end | |||
addFullRow(container, badgeWikitext, '', false, 'infobox-type-badge') | |||
if image_main then | if image_main then | ||
| Line 228: | Line 239: | ||
local crt_models = trim(args.crt_models) | local crt_models = trim(args.crt_models) | ||
if crt_models and crt_models ~= '' then | if crt_models and crt_models ~= '' then | ||
-- Parse crt_models names | |||
local crtNames = {} | |||
local | |||
local crtConditions = {} | local crtConditions = {} | ||
for crt in crt_models:gmatch('[^,]+') do | for crt in crt_models:gmatch('[^,]+') do | ||
local c = trim(crt) | local c = trim(crt) | ||
if c then | if c then | ||
table.insert(crtNames, c) | |||
table.insert(crtConditions, '[[' .. c .. ']]') | table.insert(crtConditions, '[[' .. c .. ']]') | ||
end | end | ||
| Line 243: | Line 251: | ||
if #crtConditions > 0 then | if #crtConditions > 0 then | ||
-- Query for CRT types | |||
local crtQueryWikitext = | local crtQueryWikitext = | ||
'{{#ask:\n' .. | '{{#ask:\n' .. | ||
' [[Category:CRT models]]\n' .. | ' [[Category:CRT models]]\n' .. | ||
' <q>' .. table.concat(crtConditions, ' OR ') .. '</q>\n' .. | ' <q>' .. table.concat(crtConditions, ' OR ') .. '</q>\n' .. | ||
' |?Has | ' |?Has CRT type\n' .. | ||
' |format=broadtable\n' .. | |||
' |headers=hide\n' .. | |||
' |format= | ' |link=none\n' .. | ||
' | | |||
' |link= | |||
'}}' | '}}' | ||
local | local crtResult = frame:preprocess(crtQueryWikitext) | ||
-- Parse results into a lookup of page name -> CRT type | |||
local crtTypes = {} | |||
if crtResult then | |||
for rowContent in crtResult:gmatch('<tr[^>]*>(.-)</tr>') do | |||
local cells = {} | |||
for cellContent in rowContent:gmatch('<td[^>]*>(.-)</td>') do | |||
local cleanContent = cellContent:gsub('<[^>]+>', '') | |||
table.insert(cells, trim(cleanContent)) | |||
end | |||
if #cells >= 2 and cells[1] and cells[2] then | |||
crtTypes[cells[1]] = cells[2] | |||
end | |||
end | |||
end | |||
-- Group by type | |||
local byType = {} | |||
local typeOrder = {} | |||
local typeSeen = {} | |||
for _, crtName in ipairs(crtNames) do | |||
local cType = crtTypes[crtName] or 'Unknown' | |||
if not typeSeen[cType] then | |||
typeSeen[cType] = true | |||
table.insert(typeOrder, cType) | |||
byType[cType] = {} | |||
end | |||
table.insert(byType[cType], crtName) | |||
end | |||
if #typeOrder > 0 then | |||
addSectionRow(container, 'Compatible CRT Models') | |||
for _, cType in ipairs(typeOrder) do | |||
local deviceLinks = {} | |||
for _, crtName in ipairs(byType[cType]) do | |||
table.insert(deviceLinks, '[[' .. crtName .. ']]') | |||
end | |||
addRow(container, cType, table.concat(deviceLinks, '<br>'), true) | |||
end | |||
end | |||
end | end | ||
end | end | ||
| Line 263: | Line 310: | ||
local av_devices = trim(args.av_devices) | local av_devices = trim(args.av_devices) | ||
if av_devices and av_devices ~= '' then | if av_devices and av_devices ~= '' then | ||
-- Parse av_devices names | |||
local avNames = {} | |||
local | |||
local avConditions = {} | local avConditions = {} | ||
for av in av_devices:gmatch('[^,]+') do | for av in av_devices:gmatch('[^,]+') do | ||
local a = trim(av) | local a = trim(av) | ||
if a then | if a then | ||
table.insert(avNames, a) | |||
table.insert(avConditions, '[[' .. a .. ']]') | table.insert(avConditions, '[[' .. a .. ']]') | ||
end | end | ||
| Line 278: | Line 322: | ||
if #avConditions > 0 then | if #avConditions > 0 then | ||
-- Query for device types | |||
local avQueryWikitext = | local avQueryWikitext = | ||
'{{#ask:\n' .. | '{{#ask:\n' .. | ||
' [[Category:AV devices]]\n' .. | ' [[Category:AV devices]]\n' .. | ||
' <q>' .. table.concat(avConditions, ' OR ') .. '</q>\n' .. | ' <q>' .. table.concat(avConditions, ' OR ') .. '</q>\n' .. | ||
' |?Has device type\n' .. | |||
' |format=broadtable\n' .. | |||
' |?Has device type | ' |headers=hide\n' .. | ||
' |format= | ' |link=none\n' .. | ||
' | | |||
' |link= | |||
'}}' | '}}' | ||
local | local avResult = frame:preprocess(avQueryWikitext) | ||
-- Parse results into a lookup of page name -> device type | |||
local deviceTypes = {} | |||
if avResult then | |||
for rowContent in avResult:gmatch('<tr[^>]*>(.-)</tr>') do | |||
local cells = {} | |||
for cellContent in rowContent:gmatch('<td[^>]*>(.-)</td>') do | |||
local cleanContent = cellContent:gsub('<[^>]+>', '') | |||
table.insert(cells, trim(cleanContent)) | |||
end | |||
if #cells >= 2 and cells[1] and cells[2] then | |||
deviceTypes[cells[1]] = cells[2] | |||
end | |||
end | |||
end | |||
-- Group by type | |||
local byType = {} | |||
local typeOrder = {} | |||
local typeSeen = {} | |||
for _, avName in ipairs(avNames) do | |||
local dtype = deviceTypes[avName] or 'Unknown' | |||
if not typeSeen[dtype] then | |||
typeSeen[dtype] = true | |||
table.insert(typeOrder, dtype) | |||
byType[dtype] = {} | |||
end | |||
table.insert(byType[dtype], avName) | |||
end | |||
if #typeOrder > 0 then | |||
addSectionRow(container, 'Compatible AV Devices') | |||
for _, dtype in ipairs(typeOrder) do | |||
local deviceLinks = {} | |||
for _, avName in ipairs(byType[dtype]) do | |||
table.insert(deviceLinks, '[[' .. avName .. ']]') | |||
end | |||
addRow(container, dtype, table.concat(deviceLinks, '<br>'), true) | |||
end | |||
end | |||
end | end | ||
end | end | ||
| Line 298: | Line 381: | ||
addSectionRow(container, 'Documents') | addSectionRow(container, 'Documents') | ||
-- Build upload link with prefilled part | |||
local timestamp = os.time() | local timestamp = os.time() | ||
math.randomseed(timestamp + pageId) | math.randomseed(timestamp + pageId) | ||
local random = math.random(1000, 9999) | local random = math.random(1000, 9999) | ||
local target = "Document:" .. timestamp .. "-" .. random | local target = "Document:" .. timestamp .. "-" .. random | ||
local uploadUrl = mw.uri.fullUrl( | local uploadUrl = mw.uri.fullUrl( | ||
"Special:FormEdit", | "Special:FormEdit", | ||
{ | { | ||
form = "Document", | form = "Document", | ||
target = target | target = target, | ||
["Document[parts]"] = pageName | |||
} | } | ||
) | ) | ||
-- Query for document count | |||
local documentsCountWikitext = | |||
'{{#ask:\n' .. | |||
' [[Category:Documents]]\n' .. | |||
' [[Has related part::' .. fullPageName .. ']]\n' .. | |||
' |format=count\n' .. | |||
'}}' | |||
local documentCount = frame:preprocess(documentsCountWikitext) | |||
local hasDocuments = documentCount and tonumber(trim(documentCount)) and tonumber(trim(documentCount)) > 0 | |||
-- Create the content div | |||
local docsDiv = container:tag('div') | local docsDiv = container:tag('div') | ||
css(docsDiv, 'grid-column: 1 / -1; padding:0.2em 0.4em; text-align:center | css(docsDiv, 'grid-column: 1 / -1; padding:0.2em 0.4em;') | ||
if hasDocuments then | |||
-- Use #ask to get documents | |||
local docsQueryWikitext = | |||
'{{#ask:\n' .. | |||
' [[Category:Documents]]\n' .. | |||
' [[Has related part::' .. fullPageName .. ']]\n' .. | |||
' |?Has document type\n' .. | |||
' |?Has document URL\n' .. | |||
' |?Has document file\n' .. | |||
' |?Has document title\n' .. | |||
' |format=broadtable\n' .. | |||
' |headers=hide\n' .. | |||
' |link=none\n' .. | |||
'}}' | |||
local docsResult = frame:preprocess(docsQueryWikitext) | |||
-- Create UL element | |||
local ul = mw.html.create('ul') | |||
ul:css('margin', '0'):css('padding-left', '1.5em') | |||
-- Parse the HTML table | |||
if docsResult then | |||
for rowContent in docsResult:gmatch('<tr[^>]*>(.-)</tr>') do | |||
local cells = {} | |||
for cellContent in rowContent:gmatch('<td[^>]*>(.-)</td>') do | |||
local cleanContent = cellContent:gsub('<[^>]+>', '') | |||
table.insert(cells, cleanContent) | |||
end | |||
-- cells[1] = page name, cells[2] = type, cells[3] = URL, cells[4] = file, cells[5] = title | |||
if #cells >= 2 then | |||
local docType = trim(cells[2]) | |||
local docTitle = trim(cells[5]) | |||
local docPageName = trim(cells[1]) | |||
if docPageName then | |||
local displayText = 'Document' | |||
if docTitle then | |||
displayText = docTitle | |||
elseif docType then | |||
displayText = docType | |||
end | |||
local li = ul:tag('li') | |||
li:wikitext('[[' .. docPageName .. '|' .. displayText .. ']]') | |||
end | |||
end | |||
end | |||
end | |||
docsDiv:node(ul) | |||
-- Add upload link as a button | |||
local uploadDiv = mw.html.create('div') | |||
uploadDiv:css('margin-top', '0.5em'):css('text-align', 'center') | |||
uploadDiv:wikitext('[' .. tostring(uploadUrl) .. ' <span class="infobox-button infobox-button-secondary">Add a document</span>]') | |||
docsDiv:node(uploadDiv) | |||
else | |||
-- Just show the upload link as a button | |||
local uploadDiv = mw.html.create('div') | |||
uploadDiv:css('text-align', 'center') | |||
uploadDiv:wikitext('[' .. tostring(uploadUrl) .. ' <span class="infobox-button infobox-button-secondary">Add a document</span>]') | |||
docsDiv:node(uploadDiv) | |||
end | |||
-- Contribute section | -- Contribute section | ||