<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ar">
	<id>https://malaqet.com/index.php?action=history&amp;feed=atom&amp;title=%D9%88%D8%AD%D8%AF%D8%A9%3ANavplate</id>
	<title>وحدة:Navplate - تاريخ المراجعة</title>
	<link rel="self" type="application/atom+xml" href="https://malaqet.com/index.php?action=history&amp;feed=atom&amp;title=%D9%88%D8%AD%D8%AF%D8%A9%3ANavplate"/>
	<link rel="alternate" type="text/html" href="https://malaqet.com/index.php?title=%D9%88%D8%AD%D8%AF%D8%A9:Navplate&amp;action=history"/>
	<updated>2026-08-01T20:07:00Z</updated>
	<subtitle>تاريخ التعديل لهذه الصفحة في الويكي</subtitle>
	<generator>MediaWiki 1.43.1</generator>
	<entry>
		<id>https://malaqet.com/index.php?title=%D9%88%D8%AD%D8%AF%D8%A9:Navplate&amp;diff=107&amp;oldid=prev</id>
		<title>عبود السكاف: أنشأ الصفحة ب&#039;-------------------------------------------------------------------------------- -- Module:Navplate                                                            -- -- This module implements {{Navplate}}                                        -- -- Based on Module:Infobox                                                    -- -- This is a work in progress                                                 -- ----------------------------------------------------------------...&#039;</title>
		<link rel="alternate" type="text/html" href="https://malaqet.com/index.php?title=%D9%88%D8%AD%D8%AF%D8%A9:Navplate&amp;diff=107&amp;oldid=prev"/>
		<updated>2025-06-20T20:03:54Z</updated>

		<summary type="html">&lt;p&gt;أنشأ الصفحة ب&amp;#039;-------------------------------------------------------------------------------- -- Module:Navplate                                                            -- -- This module implements {{Navplate}}                                        -- -- Based on Module:Infobox                                                    -- -- This is a work in progress                                                 -- ----------------------------------------------------------------...&amp;#039;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;صفحة جديدة&lt;/b&gt;&lt;/p&gt;&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
-- Module:Navplate                                                            --&lt;br /&gt;
-- This module implements {{Navplate}}                                        --&lt;br /&gt;
-- Based on Module:Infobox                                                    --&lt;br /&gt;
-- This is a work in progress                                                 --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
local args = {}&lt;br /&gt;
local origArgs = {}&lt;br /&gt;
&lt;br /&gt;
local function union( t1, t2 )&lt;br /&gt;
	-- Returns the union of the values of two tables, as a sequence.&lt;br /&gt;
	local vals = {}&lt;br /&gt;
	for k, v in pairs( t1 ) do&lt;br /&gt;
		vals[v] = true&lt;br /&gt;
	end&lt;br /&gt;
	for k, v in pairs( t2 ) do&lt;br /&gt;
		vals[v] = true&lt;br /&gt;
	end&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k, v in pairs( vals ) do&lt;br /&gt;
		table.insert( ret, k )&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Returns a table containing the numbers of the arguments that exist&lt;br /&gt;
-- for the specified prefix. For example, if the prefix was &amp;#039;data&amp;#039;, and&lt;br /&gt;
-- &amp;#039;data1&amp;#039;, &amp;#039;data2&amp;#039;, and &amp;#039;data5&amp;#039; exist, it would return {1, 2, 5}.&lt;br /&gt;
local function getArgNums( prefix )&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k, v in pairs( args ) do&lt;br /&gt;
		local num = tostring( k ):match( &amp;#039;^&amp;#039; .. prefix .. &amp;#039;([1-9]%d*)$&amp;#039; )&lt;br /&gt;
		if num then table.insert( nums, tonumber( num ) ) end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort( nums )&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Get the string of the &amp;lt;details&amp;gt; element&lt;br /&gt;
--- TODO: Perhaps we should turn this into another module&lt;br /&gt;
---&lt;br /&gt;
--- @param data table&lt;br /&gt;
--- @param frame table&lt;br /&gt;
--- @return string&lt;br /&gt;
local function getDetailsHTML( data, frame )&lt;br /&gt;
	local summary = frame:extensionTag {&lt;br /&gt;
		name = &amp;#039;summary&amp;#039;,&lt;br /&gt;
		content = data.summary.content,&lt;br /&gt;
		args = {&lt;br /&gt;
			class = data.summary.class&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	local details = frame:extensionTag {&lt;br /&gt;
		name = &amp;#039;details&amp;#039;,&lt;br /&gt;
		content = summary .. data.details.content,&lt;br /&gt;
		args = {&lt;br /&gt;
			class = data.details.class,&lt;br /&gt;
			role = data.details.role,&lt;br /&gt;
			open = data.details.open or &amp;#039;no&amp;#039;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	return details&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- @param rowArgs table&lt;br /&gt;
--- @return mw.html&lt;br /&gt;
local function getRowHTML( rowArgs )&lt;br /&gt;
	local html = mw.html.create()&lt;br /&gt;
	-- Adds a row to the navplate, with either a header&lt;br /&gt;
	-- or a label/list combination.&lt;br /&gt;
	if rowArgs.header then&lt;br /&gt;
		html&lt;br /&gt;
			:tag( &amp;#039;div&amp;#039; )&lt;br /&gt;
			:addClass( &amp;#039;template-navplate__groupheader&amp;#039; )&lt;br /&gt;
			:wikitext( rowArgs.header )&lt;br /&gt;
	elseif rowArgs.list then&lt;br /&gt;
		html&lt;br /&gt;
			:tag( &amp;#039;div&amp;#039; )&lt;br /&gt;
			:addClass( &amp;#039;template-navplate-item&amp;#039; )&lt;br /&gt;
			:tag( &amp;#039;div&amp;#039; )&lt;br /&gt;
			:addClass( &amp;#039;template-navplate-item__label&amp;#039; )&lt;br /&gt;
			:wikitext( rowArgs.label )&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag( &amp;#039;div&amp;#039; )&lt;br /&gt;
			:addClass( &amp;#039;template-navplate-item__list&amp;#039; )&lt;br /&gt;
			:wikitext( rowArgs.list )&lt;br /&gt;
	end&lt;br /&gt;
	return html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- @return mw.html&lt;br /&gt;
local function getTitleHTML()&lt;br /&gt;
	local html = mw.html.create( &amp;#039;div&amp;#039; )&lt;br /&gt;
	html:addClass( &amp;#039;template-navplate__headerContent&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
	if not args.title then return end&lt;br /&gt;
	if args.subtitle then&lt;br /&gt;
		html&lt;br /&gt;
			:tag( &amp;#039;div&amp;#039; )&lt;br /&gt;
			:addClass( &amp;#039;template-navplate__subtitle&amp;#039; )&lt;br /&gt;
			:wikitext( args.subtitle )&lt;br /&gt;
			:done()&lt;br /&gt;
	end&lt;br /&gt;
	html&lt;br /&gt;
		:tag( &amp;#039;div&amp;#039; )&lt;br /&gt;
		:addClass( &amp;#039;template-navplate__title&amp;#039; )&lt;br /&gt;
		:wikitext( args.title )&lt;br /&gt;
&lt;br /&gt;
	return html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- @return mw.html&lt;br /&gt;
local function getRowsHTML()&lt;br /&gt;
	local html = mw.html.create()&lt;br /&gt;
	-- Gets the union of the header and list argument numbers,&lt;br /&gt;
	-- and renders them all in order using addRow.&lt;br /&gt;
	local rownums = union( getArgNums( &amp;#039;header&amp;#039; ), getArgNums( &amp;#039;list&amp;#039; ) )&lt;br /&gt;
	table.sort( rownums )&lt;br /&gt;
	for _, num in ipairs( rownums ) do&lt;br /&gt;
		html:node( getRowHTML( {&lt;br /&gt;
			header = args[&amp;#039;header&amp;#039; .. tostring( num )],&lt;br /&gt;
			label = args[&amp;#039;label&amp;#039; .. tostring( num )],&lt;br /&gt;
			list = args[&amp;#039;list&amp;#039; .. tostring( num )]&lt;br /&gt;
		} ) )&lt;br /&gt;
	end&lt;br /&gt;
	return html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- If the argument exists and isn&amp;#039;t blank, add it to the argument table.&lt;br /&gt;
-- Blank arguments are treated as nil to match the behaviour of ParserFunctions.&lt;br /&gt;
local function preprocessSingleArg( argName )&lt;br /&gt;
	if origArgs[argName] and origArgs[argName] ~= &amp;#039;&amp;#039; then&lt;br /&gt;
		args[argName] = origArgs[argName]&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Assign the parameters with the given prefixes to the args table, in order, in&lt;br /&gt;
-- batches of the step size specified. This is to prevent references etc. from&lt;br /&gt;
-- appearing in the wrong order. The prefixTable should be an array containing&lt;br /&gt;
-- tables, each of which has two possible fields, a &amp;quot;prefix&amp;quot; string and a&lt;br /&gt;
-- &amp;quot;depend&amp;quot; table. The function always parses parameters containing the &amp;quot;prefix&amp;quot;&lt;br /&gt;
-- string, but only parses parameters in the &amp;quot;depend&amp;quot; table if the prefix&lt;br /&gt;
-- parameter is present and non-blank.&lt;br /&gt;
local function preprocessArgs( prefixTable, step )&lt;br /&gt;
	if type( prefixTable ) ~= &amp;#039;table&amp;#039; then&lt;br /&gt;
		error( &amp;#039;Non-table value detected for the prefix table&amp;#039;, 2 )&lt;br /&gt;
	end&lt;br /&gt;
	if type( step ) ~= &amp;#039;number&amp;#039; then&lt;br /&gt;
		error( &amp;#039;Invalid step value detected&amp;#039;, 2 )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Get arguments without a number suffix, and check for bad input.&lt;br /&gt;
	for i, v in ipairs( prefixTable ) do&lt;br /&gt;
		if type( v ) ~= &amp;#039;table&amp;#039; or type( v.prefix ) ~= &amp;#039;string&amp;#039; or&lt;br /&gt;
			(v.depend and type( v.depend ) ~= &amp;#039;table&amp;#039;) then&lt;br /&gt;
			error( &amp;#039;Invalid input detected to preprocessArgs prefix table&amp;#039;, 2 )&lt;br /&gt;
		end&lt;br /&gt;
		preprocessSingleArg( v.prefix )&lt;br /&gt;
		-- Only parse the depend parameter if the prefix parameter is present&lt;br /&gt;
		-- and not blank.&lt;br /&gt;
		if args[v.prefix] and v.depend then&lt;br /&gt;
			for j, dependValue in ipairs( v.depend ) do&lt;br /&gt;
				if type( dependValue ) ~= &amp;#039;string&amp;#039; then&lt;br /&gt;
					error( &amp;#039;Invalid &amp;quot;depend&amp;quot; parameter value detected in preprocessArgs&amp;#039; )&lt;br /&gt;
				end&lt;br /&gt;
				preprocessSingleArg( dependValue )&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Get arguments with number suffixes.&lt;br /&gt;
	local a = 1 -- Counter variable.&lt;br /&gt;
	local moreArgumentsExist = true&lt;br /&gt;
	while moreArgumentsExist == true do&lt;br /&gt;
		moreArgumentsExist = false&lt;br /&gt;
		for i = a, a + step - 1 do&lt;br /&gt;
			for j, v in ipairs( prefixTable ) do&lt;br /&gt;
				local prefixArgName = v.prefix .. tostring( i )&lt;br /&gt;
				if origArgs[prefixArgName] then&lt;br /&gt;
					-- Do another loop if any arguments are found, even blank ones.&lt;br /&gt;
					moreArgumentsExist = true&lt;br /&gt;
					preprocessSingleArg( prefixArgName )&lt;br /&gt;
				end&lt;br /&gt;
				-- Process the depend table if the prefix argument is present&lt;br /&gt;
				-- and not blank, or we are processing &amp;quot;prefix1&amp;quot; and &amp;quot;prefix&amp;quot; is&lt;br /&gt;
				-- present and not blank, and if the depend table is present.&lt;br /&gt;
				if v.depend and (args[prefixArgName] or (i == 1 and args[v.prefix])) then&lt;br /&gt;
					for j, dependValue in ipairs( v.depend ) do&lt;br /&gt;
						local dependArgName = dependValue .. tostring( i )&lt;br /&gt;
						preprocessSingleArg( dependArgName )&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		a = a + step&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function parseDataParameters()&lt;br /&gt;
	preprocessSingleArg( &amp;#039;id&amp;#039; )&lt;br /&gt;
	preprocessSingleArg( &amp;#039;subtitle&amp;#039; )&lt;br /&gt;
	preprocessSingleArg( &amp;#039;title&amp;#039; )&lt;br /&gt;
	preprocessArgs( {&lt;br /&gt;
		{ prefix = &amp;#039;header&amp;#039; },&lt;br /&gt;
		{ prefix = &amp;#039;list&amp;#039;,  depend = { &amp;#039;label&amp;#039; } },&lt;br /&gt;
	}, 50 )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function _navplate()&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
&lt;br /&gt;
	local summaryHTML = mw.html.create()&lt;br /&gt;
		:tag( &amp;#039;div&amp;#039; )&lt;br /&gt;
		:addClass( &amp;#039;citizen-ui-icon mw-ui-icon-wikimedia-collapse&amp;#039; )&lt;br /&gt;
		:done()&lt;br /&gt;
		:node( getTitleHTML() )&lt;br /&gt;
&lt;br /&gt;
	local contentHTML = mw.html.create( &amp;#039;div&amp;#039; )&lt;br /&gt;
		:addClass( &amp;#039;template-navplate__content citizen-text-small&amp;#039; )&lt;br /&gt;
		:node( getRowsHTML() )&lt;br /&gt;
&lt;br /&gt;
	local output = getDetailsHTML( {&lt;br /&gt;
		details = {&lt;br /&gt;
			class = &amp;#039;template-navplate&amp;#039;,&lt;br /&gt;
			content = tostring( contentHTML )&lt;br /&gt;
		},&lt;br /&gt;
		summary = {&lt;br /&gt;
			class = &amp;#039;template-navplate__header&amp;#039;,&lt;br /&gt;
			content = tostring( summaryHTML )&lt;br /&gt;
		}&lt;br /&gt;
	}, frame )&lt;br /&gt;
&lt;br /&gt;
	return frame:extensionTag {&lt;br /&gt;
		name = &amp;#039;templatestyles&amp;#039;, args = { src = &amp;#039;Module:Navplate/styles.css&amp;#039; }&lt;br /&gt;
	} .. output&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- If called via #invoke, use the args passed into the invoking template.&lt;br /&gt;
-- Otherwise, for testing purposes, assume args are being passed directly in.&lt;br /&gt;
function p.navplate( frame )&lt;br /&gt;
	if frame == mw.getCurrentFrame() then&lt;br /&gt;
		origArgs = frame:getParent().args&lt;br /&gt;
	else&lt;br /&gt;
		origArgs = frame&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	parseDataParameters()&lt;br /&gt;
&lt;br /&gt;
	return _navplate()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Legacy method, do not use&lt;br /&gt;
-- For calling via #invoke within a template&lt;br /&gt;
function p.navplateTemplate( frame )&lt;br /&gt;
	origArgs = {}&lt;br /&gt;
	for k, v in pairs( frame.args ) do origArgs[k] = mw.text.trim( v ) end&lt;br /&gt;
&lt;br /&gt;
	parseDataParameters()&lt;br /&gt;
&lt;br /&gt;
	return _navplate()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- For calling via other modules&lt;br /&gt;
function p.fromData( data )&lt;br /&gt;
	local directArgs = {}&lt;br /&gt;
&lt;br /&gt;
	if not data or type( data ) ~= &amp;#039;table&amp;#039; then&lt;br /&gt;
		-- TODO: Add error state&lt;br /&gt;
	else&lt;br /&gt;
		if data.title then&lt;br /&gt;
			directArgs.title = data.title&lt;br /&gt;
		end&lt;br /&gt;
		if data.subtitle then&lt;br /&gt;
			directArgs.subtitle = data.subtitle&lt;br /&gt;
		end&lt;br /&gt;
		if data.id then&lt;br /&gt;
			directArgs.id = data.id&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if data.items and type( data.items ) == &amp;#039;table&amp;#039; and #data.items &amp;gt; 0 then&lt;br /&gt;
			for i, item in ipairs( data.items ) do&lt;br /&gt;
				if type( item ) == &amp;#039;table&amp;#039; then&lt;br /&gt;
					if item.label then&lt;br /&gt;
						directArgs[&amp;#039;label&amp;#039; .. tostring( i )] = item.label&lt;br /&gt;
					end&lt;br /&gt;
					if item.pages then -- &amp;#039;pages&amp;#039; from Manufacturers.lua maps to &amp;#039;list&amp;#039; here&lt;br /&gt;
						directArgs[&amp;#039;list&amp;#039; .. tostring( i )] = item.pages&lt;br /&gt;
					end&lt;br /&gt;
					if item.header then -- Also support &amp;#039;header&amp;#039; if needed&lt;br /&gt;
						directArgs[&amp;#039;header&amp;#039; .. tostring( i )] = item.header&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			-- TODO: Add empty state to navplate&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return p.navplateTemplate( { args = directArgs } )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>عبود السكاف</name></author>
	</entry>
</feed>