Module:Part

Revision as of 01:00, 14 February 2026 by Arclight (talk | contribs) (Arclight changed the content model of the page Module:Part from "wikitext" to "Scribunto module")

Documentation for this module may be created at Module:Part/doc

-- Module:Part
-- Builds the Part infobox (CRT tubes, ICs, flybacks, boards, yokes, etc.)

local p = {}

local function trim(s)
	if s == nil then return nil end
	s = tostring(s)
	s = s:gsub('^%s+', ''):gsub('%s+$', '')
	if s == '' then return nil end
	return s
end

local function css(node, cssText)
	if cssText and cssText ~= '' then
		node:cssText(cssText)
	end
	return node
end

local function addSectionRow(container, title)
	local section = container:tag('div')
	section:addClass('infobox-section-header')
	css(section, 'grid-column: 1 / -1; text-align:center; padding:0.5em; font-weight:bold;')
	section:wikitext(title)
end

local function addRow(container, label, valueHtmlOrWikitext, isRawHtml)
	local labelDiv = container:tag('div')
	labelDiv:addClass('infobox-label')
	css(labelDiv, 'padding:0.2em 0.4em; font-weight:bold; text-align:left;')
	labelDiv:wikitext(label)

	local valueDiv = container:tag('div')
	valueDiv:addClass('infobox-value')
	css(valueDiv, 'padding:0.2em 0.4em;')

	if isRawHtml then
		valueDiv:node(mw.html.create('span'):wikitext(valueHtmlOrWikitext))
	else
		valueDiv:wikitext(valueHtmlOrWikitext)
	end
end

local function addFullRow(container, valueHtmlOrWikitext, cssText, isRawHtml, extraClass)
	local fullDiv = container:tag('div')
	css(fullDiv, 'grid-column: 1 / -1; ' .. (cssText or ''))
	if extraClass then
		fullDiv:addClass(extraClass)
	end

	if isRawHtml then
		fullDiv:wikitext(valueHtmlOrWikitext)
	else
		fullDiv:wikitext(valueHtmlOrWikitext)
	end
end

function p.infobox(frame)
	local parent = frame:getParent()
	local args = parent and parent.args or frame.args

	local title = mw.title.getCurrentTitle()
	local pageName = title.text
	local fullPageName = title.fullText
	local pageId = title.id or 0

	-- Core fields
	local brand = trim(args.brand)
	local model_code = trim(args.model_code)
	local part_type = trim(args.part_type)
	local part_subtype = trim(args.part_subtype)
	local description = trim(args.description)
	local image_main = trim(args.image_main)
	local equivalent_parts = trim(args.equivalent_parts)
	local oem_part_numbers = trim(args.oem_part_numbers)
	
	-- CRT tube specific
	local tube_size = trim(args.tube_size)
	local tube_neck_diameter = trim(args.tube_neck_diameter)
	local tube_deflection_angle = trim(args.tube_deflection_angle)
	local tube_phosphor_type = trim(args.tube_phosphor_type)
	local tube_mask_type = trim(args.tube_mask_type)
	
	-- IC specific
	local package_type = trim(args.package_type)
	local pin_count = trim(args.pin_count)
	local datasheet_url = trim(args.datasheet_url)
	
	-- Flyback specific
	local cross_references = trim(args.cross_references)
	local hr_diemen_number = trim(args.hr_diemen_number)
	
	-- Board specific
	local board_subtype = trim(args.board_subtype)

	-- Load stylesheet
	local styleTag = frame:extensionTag('templatestyles', '', {src = 'Template:Infobox styles.css'})

	local container = mw.html.create('div')
	container:addClass('infobox')
	container:addClass('infobox-part')
	css(container, 'float:right; clear:right; margin:0 0 1em 1em; width:22em; font-size:88%; line-height:1.5em; display:grid; grid-template-columns:auto 1fr; gap:3px; padding:3px;')

	-- Title row
	addFullRow(
		container,
		(brand or '') .. ' ' .. (model_code or ''),
		'text-align:center; font-size:125%; font-weight:bold; padding:0.5em;',
		false,
		'infobox-title'
	)

	if image_main then
		local file = image_main:gsub('^File:', '')
		addFullRow(
			container,
			string.format('[[File:%s|frameless|300px]]', file),
			'text-align:center; padding:0;',
			false,
			'infobox-image'
		)
	end

	addSectionRow(container, 'Overview')

	-- Brand row using #formredlink
	if brand then
		local brandWikitext = string.format(
			'{{#formredlink: target=%s |form=Manufacturer |existing page link text=%s }}',
			brand, brand
		)
		local brandHtml = frame:preprocess(brandWikitext)
		addRow(container, 'Brand', brandHtml, true)
	end

	if model_code then
		addRow(container, 'Part #', model_code, false)
	end

	if part_type then
		local typeDisplay = part_type
		if part_subtype then
			typeDisplay = part_type .. ' (' .. part_subtype .. ')'
		end
		addRow(container, 'Type', typeDisplay, false)
	end

	if description then
		addRow(container, 'Description', description, false)
	end

	-- ECID row
	local ecidWikitext = string.format('[{{fullurl:%s|curid=%d}} EC%d]', pageName, pageId, pageId)
	addRow(container, 'ECID', frame:preprocess(ecidWikitext), true)

	-- CRT Tube specifications section
	if part_type == 'CRT tube' and (tube_size or tube_neck_diameter or tube_deflection_angle or tube_phosphor_type or tube_mask_type) then
		addSectionRow(container, 'Tube Specs')
		
		if tube_size then
			addRow(container, 'Size', tube_size .. '″', false)
		end
		if tube_neck_diameter then
			addRow(container, 'Neck', tube_neck_diameter .. ' mm', false)
		end
		if tube_deflection_angle then
			addRow(container, 'Deflection', tube_deflection_angle .. '°', false)
		end
		if tube_phosphor_type then
			addRow(container, 'Phosphors', tube_phosphor_type, false)
		end
		if tube_mask_type then
			addRow(container, 'Mask', tube_mask_type, false)
		end
	end

	-- IC specifications section
	if part_type == 'IC' and (package_type or pin_count or datasheet_url) then
		addSectionRow(container, 'IC Specs')
		
		if package_type then
			local pkgDisplay = package_type
			if pin_count then
				pkgDisplay = package_type .. '-' .. pin_count
			end
			addRow(container, 'Package', pkgDisplay, false)
		elseif pin_count then
			addRow(container, 'Pins', pin_count, false)
		end
		
		if datasheet_url then
			addRow(container, 'Datasheet', '[' .. datasheet_url .. ' View]', true)
		end
	end

	-- Flyback specifications section
	if part_type == 'Flyback transformer' and (cross_references or hr_diemen_number) then
		addSectionRow(container, 'Cross-References')
		
		if hr_diemen_number then
			addRow(container, 'HR Diemen', hr_diemen_number, false)
		end
		if cross_references then
			addRow(container, 'Equivalents', cross_references, false)
		end
	end

	-- Board specifications section
	if part_type == 'Board' and board_subtype then
		addSectionRow(container, 'Board Specs')
		addRow(container, 'Board type', board_subtype, false)
	end

	-- Cross-references section (for non-flyback parts)
	if part_type ~= 'Flyback transformer' and (equivalent_parts or oem_part_numbers) then
		addSectionRow(container, 'Cross-References')
		
		if equivalent_parts then
			addRow(container, 'Equivalents', equivalent_parts, false)
		end
		if oem_part_numbers then
			addRow(container, 'OEM #s', oem_part_numbers, false)
		end
	end

	-- Compatible CRT models section
	local crt_models = trim(args.crt_models)
	if crt_models and crt_models ~= '' then
		addSectionRow(container, 'Compatible CRT Models')
		
		local crtDiv = container:tag('div')
		css(crtDiv, 'grid-column: 1 / -1; padding:0.2em 0.4em;')
		
		-- Parse crt_models and create OR conditions
		local crtConditions = {}
		for crt in crt_models:gmatch('[^,]+') do
			local c = trim(crt)
			if c then
				table.insert(crtConditions, '[[' .. c .. ']]')
			end
		end
		
		if #crtConditions > 0 then
			local crtQueryWikitext =
				'{{#ask:\n' ..
				' [[Category:CRT models]]\n' ..
				' <q>' .. table.concat(crtConditions, ' OR ') .. '</q>\n' ..
				' |?Has image#70px;x70px=Photo\n' ..
				' |?Has model code=Model\n' ..
				' |?Has screen size inches=Size\n' ..
				' |format=table\n' ..
				' |class=wikitable\n' ..
				' |mainlabel=CRT model\n' ..
				' |link=subject\n' ..
				'}}'
			local crtHtml = frame:preprocess(crtQueryWikitext)
			crtDiv:wikitext(crtHtml)
		end
	end

	-- Compatible AV devices section
	local av_devices = trim(args.av_devices)
	if av_devices and av_devices ~= '' then
		addSectionRow(container, 'Compatible AV Devices')
		
		local avDiv = container:tag('div')
		css(avDiv, 'grid-column: 1 / -1; padding:0.2em 0.4em;')
		
		-- Parse av_devices and create OR conditions
		local avConditions = {}
		for av in av_devices:gmatch('[^,]+') do
			local a = trim(av)
			if a then
				table.insert(avConditions, '[[' .. a .. ']]')
			end
		end
		
		if #avConditions > 0 then
			local avQueryWikitext =
				'{{#ask:\n' ..
				' [[Category:AV devices]]\n' ..
				' <q>' .. table.concat(avConditions, ' OR ') .. '</q>\n' ..
				' |?Has image#70px;x70px=Photo\n' ..
				' |?Has model code=Model\n' ..
				' |?Has device type=Type\n' ..
				' |format=table\n' ..
				' |class=wikitable\n' ..
				' |mainlabel=AV device\n' ..
				' |link=subject\n' ..
				'}}'
			local avHtml = frame:preprocess(avQueryWikitext)
			avDiv:wikitext(avHtml)
		end
	end

	-- Documents section
	addSectionRow(container, 'Documents')
	
	local timestamp = os.time()
	math.randomseed(timestamp + pageId)
	local random = math.random(1000, 9999)
	local target = "Document:" .. timestamp .. "-" .. random
	
	local uploadUrl = mw.uri.fullUrl(
		"Special:FormEdit",
		{
			form = "Document",
			target = target
		}
	)
	
	local docsDiv = container:tag('div')
	css(docsDiv, 'grid-column: 1 / -1; padding:0.2em 0.4em; text-align:center;')
	docsDiv:wikitext('[' .. tostring(uploadUrl) .. ' <span class="infobox-button infobox-button-secondary">Add a document</span>]')

	-- Contribute section
	addSectionRow(container, 'Contribute')
	
	local editUrl = mw.uri.fullUrl(
		"Special:FormStart",
		{
			form = "Part",
			page_name = pageName
		}
	)
	
	local editDiv = container:tag('div')
	css(editDiv, 'grid-column: 1 / -1; padding:0.2em 0.4em; text-align:center;')
	editDiv:wikitext('[' .. tostring(editUrl) .. ' <span class="infobox-button infobox-button-primary">Edit this data</span>]')

	return styleTag .. tostring(container)
end

return p
MediaWiki Appliance - Powered by TurnKey Linux