Module:CRTModel

Revision as of 03:45, 23 December 2025 by Arclight (talk | contribs)

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

-- Module:CRTModel
-- Builds the CRT infobox as strict HTML to avoid whitespace -> <p><br></p>
-- Uses frame:preprocess() so parser functions like #ask and #formredlink evaluate.

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(tbl, title)
	local tr = tbl:tag('tr')
	css(tr:tag('td'), 'text-align:center; padding:0.5em; background:#e0e0e0; font-weight:bold;')
		:attr('colspan', '2')
		:wikitext(title)
end

local function addRow(tbl, label, valueHtmlOrWikitext, isRawHtml)
	local tr = tbl:tag('tr')
	css(tr:tag('th'), 'text-align:left; padding:0.2em 0.4em;')
		:wikitext(label)

	local td = tr:tag('td')
	css(td, 'padding:0.2em 0.4em;')

	-- After preprocess, what we have is HTML. Use :node() to insert it as HTML.
	if isRawHtml then
		td:node(mw.html.create('span'):wikitext(valueHtmlOrWikitext))
	else
		td:wikitext(valueHtmlOrWikitext)
	end
end

local function addFullRow(tbl, valueHtmlOrWikitext, cssText, isRawHtml)
	local tr = tbl:tag('tr')
	local td = tr:tag('td'):attr('colspan', '2')
	css(td, cssText or '')

	if isRawHtml then
		-- For raw HTML, insert directly without the span wrapper
		td:wikitext(valueHtmlOrWikitext)
	else
		td: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

	local brand = trim(args.brand)
	local model_code = trim(args.model_code)
	local image_main = trim(args.image_main)
	local model_3d = trim(args.model_3d)
	local crt_type = trim(args.crt_type)
	local screen_size_in = trim(args.screen_size_in)
	local tvl = trim(args.tvl)
	local chassis = trim(args.chassis)
	local height = trim(args.height)
	local width = trim(args.width)
	local depth = trim(args.depth)
	local weight = trim(args.weight)
	local standards_semantic = trim(args.standards_semantic)
	local crtdatabase = trim(args.crtdatabase)
	local consolemods = trim(args.consolemods)

	local tbl = mw.html.create('table')
	tbl:addClass('infobox')
	css(tbl, 'float:right; clear:right; margin:0 0 1em 1em; width:22em; border:1px solid #a2a9b1; border-spacing:3px; background:#f8f9fa; font-size:88%; line-height:1.5em;')

	-- Title row (no background color, centered, bold)
	addFullRow(
		tbl,
		(brand or '') .. ' ' .. (model_code or ''),
		'text-align:center; font-size:125%; font-weight:bold; padding:0.5em;',
		false
	)

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

	-- 3D model display (right below main photo)
	if model_3d then
		local file = model_3d:gsub('^File:', '')
		addFullRow(
			tbl,
			string.format('[[File:%s]]', file),
			'text-align:center; padding:0;',
			false
		)
	end

	addSectionRow(tbl, 'Overview')

	-- Brand row using #formredlink (must preprocess)
	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(tbl, 'Brand', brandHtml, true)
	end

	if model_code then
		addRow(tbl, 'Model code', model_code, false)
	else
		addRow(tbl, 'Model code', '', false)
	end

	if crt_type then
		addRow(tbl, 'Type', crt_type, false)
	end
	if screen_size_in then
		addRow(tbl, 'Screen size', screen_size_in .. '″', false)
	end
	if tvl then
		addRow(tbl, 'TVL', tvl, false)
	end

	if chassis then
		local chassisWikitext = string.format(
			'{{#formredlink: target=%s |form=Chassis |existing page link text=%s }}',
			chassis, chassis
		)
		local chassisHtml = frame:preprocess(chassisWikitext)
		addRow(tbl, 'Chassis', chassisHtml, true)
	end

	-- ECID row: build as a normal external link wikitext; preprocess not required, but fine.
	local ecidWikitext = string.format('[{{fullurl:%s|curid=%d}} EC%d]', pageName, pageId, pageId)
	addRow(tbl, 'ECID', frame:preprocess(ecidWikitext), true)

	if height or width or depth then
		addSectionRow(tbl, 'Dimensions')
		local h = height or '–'
		local w = width or '–'
		local d = depth or '–'
		addRow(tbl, 'H × W × D', string.format('%s × %s × %s', h, w, d), false)
	end

	-- Weight row: uses #show, so preprocess it
	if weight then
		local weightWikitext = '{{#show: ' .. fullPageName .. ' |?Weight # lb }} / {{#show: ' .. fullPageName .. ' |?Weight # kg }}'
		addRow(tbl, 'Weight', frame:preprocess(weightWikitext), true)
	end

	-- Inputs section: preprocess #ask so it renders, but only show section if there are results
	local askWikitext =
		'{{#ask:\n' ..
		' [[Has CRT model::' .. fullPageName .. ']]\n' ..
		' |?Has video signal format=signal\n' ..
		' |?Has connector type=connector\n' ..
		' |?Has input count=count\n' ..
		' |?Has input location=location\n' ..
		' |format=ul\n' ..
		' |template=CRT input inline\n' ..
		' |named args=yes\n' ..
		' |searchlabel=\n' ..
		'}}'
	local askHtml = frame:preprocess(askWikitext)
	-- Only display Inputs section if the query returned content (not just whitespace)
	if askHtml and trim(askHtml) then
		addSectionRow(tbl, 'Inputs')
		addFullRow(tbl, askHtml, 'padding:0.2em 0.4em;', true)
	end

	-- Only display Standards section if standards_semantic has content
	if standards_semantic then
		addSectionRow(tbl, 'Standards')
		addFullRow(tbl, standards_semantic, 'padding:0.2em 0.4em;', false)
	end

    -- Documents section
	addSectionRow(tbl, 'Documents')
	
	-- Build the upload link  
	local target = pageName .. " - document"
	local uploadUrl = mw.uri.fullUrl(
		"Special:FormEdit",
		{
			form = "Document",
			target = target,
			["Document[crt_model]"] = pageName
		}
	)
	
	-- Query for document count
	local documentsCountWikitext =
		'{{#ask:\n' ..
		' [[Category:Documents]]\n' ..
		' [[Has related CRT model::' .. 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 row
	local tr = tbl:tag('tr')
	local td = tr:tag('td'):attr('colspan', '2')
	css(td, 'padding:0.2em 0.4em;')
	
	if hasDocuments then
		-- Create UL element
		local ul = mw.html.create('ul')
		ul:css('margin', '0'):css('padding-left', '1.5em')
		
		-- Get list of document pages
		local docPagesWikitext =
			'{{#ask:\n' ..
			' [[Category:Documents]]\n' ..
			' [[Has related CRT model::' .. fullPageName .. ']]\n' ..
			' |limit=100\n' ..
			' |link=none\n' ..
			'}}'
		local docPages = frame:preprocess(docPagesWikitext)
		
		-- Process each document page
		if docPages and trim(docPages) then
			for docPage in docPages:gmatch('[^,\n]+') do
				docPage = trim(docPage)
				if docPage and docPage ~= '' then
					-- Get type and URL
					local typeQuery = '{{#show:' .. docPage .. '|?Has document type}}'
					local urlQuery = '{{#show:' .. docPage .. '|?Has document URL}}'
					
					local docType = trim(frame:preprocess(typeQuery))
					local docUrl = trim(frame:preprocess(urlQuery))
					
					if docUrl and docUrl ~= '' then
						local displayText = (docType and docType ~= '') and docType or 'Document'
						
						-- Create list item with link
						local li = ul:tag('li')
						local a = li:tag('a')
						a:attr('href', docUrl)
						a:attr('class', 'external')
						a:wikitext(displayText)
					end
				end
			end
		end
		
		-- Add the UL to the td
		td:node(ul)
		
		-- Add upload link
		local uploadDiv = mw.html.create('div')
		uploadDiv:css('margin-top', '0.5em'):css('font-style', 'italic')
		local uploadLink = uploadDiv:tag('a')
		uploadLink:attr('href', tostring(uploadUrl))
		uploadLink:attr('class', 'external')
		uploadLink:wikitext('Upload a document')
		
		td:node(uploadDiv)
	else
		-- Just show the upload link
		local uploadDiv = mw.html.create('div')
		uploadDiv:css('font-style', 'italic')
		local uploadLink = uploadDiv:tag('a')
		uploadLink:attr('href', tostring(uploadUrl))
		uploadLink:attr('class', 'external')
		uploadLink:wikitext('Upload a document')
		
		td:node(uploadDiv)
	end

	-- Other Databases section: only display if there are links
	if crtdatabase or consolemods then
		addSectionRow(tbl, 'Other Databases')
		local links = {}
		if crtdatabase then
			table.insert(links, '<li>[' .. crtdatabase .. ' CRT Database]</li>')
		end
		if consolemods then
			table.insert(links, '<li>[' .. consolemods .. ' Console Mods Wiki]</li>')
		end
		local linksHtml = '<ul style="margin:0; padding-left:1.5em;">' .. table.concat(links, '') .. '</ul>'
		addFullRow(tbl, linksHtml, 'padding:0.2em 0.4em;', true)
	end

	return tostring(tbl)
end

return p
MediaWiki Appliance - Powered by TurnKey Linux