打开/关闭菜单
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

模块:Navplate:修订间差异

来自INFWiki
9Yan留言 | 贡献
创建页面,内容为“-------------------------------------------------------------------------------- -- Module:Navplate -- -- This module implements {{Navplate}} -- -- Based on Module:Infobox -- -- This is a work in progress -- ------------------------------------------------------------…”
 
9Yan留言 | 贡献
无编辑摘要
第9行: 第9行:
local args = {}
local args = {}
local origArgs = {}
local origArgs = {}
local root
local header
local content


local function union( t1, t2 )
local function union( t1, t2 )
第17行: 第14行:
local vals = {}
local vals = {}
for k, v in pairs( t1 ) do
for k, v in pairs( t1 ) do
vals[ v ] = true
vals[v] = true
end
end
for k, v in pairs( t2 ) do
for k, v in pairs( t2 ) do
vals[ v ] = true
vals[v] = true
end
end
local ret = {}
local ret = {}
第42行: 第39行:
end
end


local function addRow( rowArgs, content )
--- Get the string of the <details> element
--- TODO: Perhaps we should turn this into another module
---
--- @param data table
--- @param frame table
--- @return string
local function getDetailsHTML( data, frame )
local summary = frame:extensionTag {
name = 'summary',
content = data.summary.content,
args = {
class = data.summary.class
}
}
local details = frame:extensionTag {
name = 'details',
content = summary .. data.details.content,
args = {
class = data.details.class,
role = data.details.role,
open = data.details.open or 'no'
}
}
return details
end
 
 
--- @param rowArgs table
--- @return mw.html
local function getRowHTML( rowArgs )
local html = mw.html.create()
-- Adds a row to the navplate, with either a header
-- Adds a row to the navplate, with either a header
-- or a label/list combination.
-- or a label/list combination.
if rowArgs.header then
if rowArgs.header then
content
html
:tag( 'div' )
:tag( 'div' )
:addClass( 'template-navplate__groupheader' )
:addClass( 'template-navplate__groupheader' )
:wikitext( rowArgs.header )
:wikitext( rowArgs.header )
elseif rowArgs.list then
elseif rowArgs.list then
local row = content:tag( 'div' )
html
row:addClass( 'template-navplate-item' )
:tag( 'div' )
row
:addClass( 'template-navplate-item' )
:tag( 'div' )
:tag( 'div' )
:addClass( 'template-navplate-item__label' )
:addClass( 'template-navplate-item__label' )
:wikitext( rowArgs.label )
:wikitext( rowArgs.label )
:done()
:done()
 
:tag( 'div' )
local list = row:tag( 'div' )
list
:addClass( 'template-navplate-item__list' )
:addClass( 'template-navplate-item__list' )
:wikitext( rowArgs.list )
:wikitext( rowArgs.list )
end
end
return html
end
end


local function renderTitle( header )
 
local headerContent = mw.html.create( 'div' )
--- @return mw.html
headerContent:addClass( 'template-navplate__headerContent' )
local function getTitleHTML()
local html = mw.html.create( 'div' )
html:addClass( 'template-navplate__headerContent' )


if not args.title then return end
if not args.title then return end
if args.subtitle then
if args.subtitle then
headerContent
html
:tag( 'div' )
:tag( 'div' )
:addClass( 'template-navplate__subtitle' )
:addClass( 'template-navplate__subtitle' )
第78行: 第106行:
:done()
:done()
end
end
headerContent
html
:tag( 'div' )
:tag( 'div' )
:addClass( 'template-navplate__title' )
:addClass( 'template-navplate__title' )
:wikitext( args.title )
:wikitext( args.title )


header:node( headerContent )
return html
end
end


local function renderRows( content )
 
--- @return mw.html
local function getRowsHTML()
local html = mw.html.create()
-- Gets the union of the header and list argument numbers,
-- Gets the union of the header and list argument numbers,
-- and renders them all in order using addRow.
-- and renders them all in order using addRow.
local rownums = union( getArgNums( 'header' ), getArgNums( 'list' ) )
local rownums = union( getArgNums( 'header' ), getArgNums( 'list' ) )
table.sort( rownums )
table.sort( rownums )
for k, num in ipairs( rownums ) do
for _, num in ipairs( rownums ) do
addRow( {
html:node( getRowHTML( {
header = args[ 'header' .. tostring( num ) ],
header = args['header' .. tostring( num )],
label = args[ 'label' .. tostring( num ) ],
label = args['label' .. tostring( num )],
list = args[ 'list' .. tostring( num ) ]
list = args['list' .. tostring( num )]
},
} ) )
content )
end
end
return html
end
end


第104行: 第135行:
-- Blank arguments are treated as nil to match the behaviour of ParserFunctions.
-- Blank arguments are treated as nil to match the behaviour of ParserFunctions.
local function preprocessSingleArg( argName )
local function preprocessSingleArg( argName )
if origArgs[ argName ] and origArgs[ argName ] ~= '' then
if origArgs[argName] and origArgs[argName] ~= '' then
args[ argName ] = origArgs[ argName ]
args[argName] = origArgs[argName]
end
end
end
end
第133行: 第164行:
-- Only parse the depend parameter if the prefix parameter is present
-- Only parse the depend parameter if the prefix parameter is present
-- and not blank.
-- and not blank.
if args[ v.prefix ] and v.depend then
if args[v.prefix] and v.depend then
for j, dependValue in ipairs( v.depend ) do
for j, dependValue in ipairs( v.depend ) do
if type( dependValue ) ~= 'string' then
if type( dependValue ) ~= 'string' then
第151行: 第182行:
for j, v in ipairs( prefixTable ) do
for j, v in ipairs( prefixTable ) do
local prefixArgName = v.prefix .. tostring( i )
local prefixArgName = v.prefix .. tostring( i )
if origArgs[ prefixArgName ] then
if origArgs[prefixArgName] then
-- Do another loop if any arguments are found, even blank ones.
-- Do another loop if any arguments are found, even blank ones.
moreArgumentsExist = true
moreArgumentsExist = true
第159行: 第190行:
-- and not blank, or we are processing "prefix1" and "prefix" is
-- and not blank, or we are processing "prefix1" and "prefix" is
-- present and not blank, and if the depend table is present.
-- present and not blank, and if the depend table is present.
if v.depend and (args[ prefixArgName ] or (i == 1 and args[ v.prefix ])) then
if v.depend and (args[prefixArgName] or (i == 1 and args[v.prefix])) then
for j, dependValue in ipairs( v.depend ) do
for j, dependValue in ipairs( v.depend ) do
local dependArgName = dependValue .. tostring( i )
local dependArgName = dependValue .. tostring( i )
第182行: 第213行:


local function _navplate()
local function _navplate()
root = mw.html.create( 'div' )
local frame = mw.getCurrentFrame()
header = mw.html.create( 'div' )
content = mw.html.create( 'div' )


header
local summaryHTML = mw.html.create()
:addClass( 'template-navplate__header' )
:addClass( 'mw-collapsible-toggle' )
:attr( 'role', 'button' )
:attr( 'aria-owns', 'template-navplate__content' )
:tag( 'div' )
:tag( 'div' )
:addClass( 'citizen-ui-icon mw-ui-icon-wikimedia-collapse' )
:addClass( 'citizen-ui-icon mw-ui-icon-wikimedia-collapse' )
:done()
:done()
:node( getTitleHTML() )


content
local contentHTML = mw.html.create( 'div' )
:addClass( 'template-navplate__content' )
:addClass( 'template-navplate__content citizen-text-small' )
:addClass( 'mw-collapsible-content' )
:node( getRowsHTML() )
:attr( 'id', 'template-navplate__content' )
 
renderTitle( header )
renderRows( content )
 
root
:addClass( 'template-navplate' )
:addClass( 'mw-collapsible' )
:attr( 'role', 'navigation' )
:node( header )
:node( content )


if args.id then root:attr( 'id', 'navplate-' .. args.id ) end
local output = getDetailsHTML( {
details = {
class = 'template-navplate',
content = tostring( contentHTML )
},
summary = {
class = 'template-navplate__header',
content = tostring( summaryHTML )
}
}, frame )


return mw.getCurrentFrame():extensionTag {
return frame:extensionTag {
name = 'templatestyles', args = { src = 'Module:Navplate/styles.css' }
name = 'templatestyles', args = { src = 'Module:Navplate/styles.css' }
} .. tostring( root )
} .. output
end
end


第231行: 第255行:
end
end


-- Legacy method, do not use
-- For calling via #invoke within a template
-- For calling via #invoke within a template
function p.navplateTemplate( frame )
function p.navplateTemplate( frame )
origArgs = {}
origArgs = {}
for k, v in pairs( frame.args ) do origArgs[ k ] = mw.text.trim( v ) end
for k, v in pairs( frame.args ) do origArgs[k] = mw.text.trim( v ) end


parseDataParameters()
parseDataParameters()


return _navplate()
return _navplate()
end
-- For calling via other modules
function p.fromData( data )
local directArgs = {}
if not data or type( data ) ~= 'table' then
-- TODO: Add error state
else
if data.title then
directArgs.title = data.title
end
if data.subtitle then
directArgs.subtitle = data.subtitle
end
if data.id then
directArgs.id = data.id
end
if data.items and type( data.items ) == 'table' and #data.items > 0 then
for i, item in ipairs( data.items ) do
if type( item ) == 'table' then
if item.label then
directArgs['label' .. tostring( i )] = item.label
end
if item.pages then -- 'pages' from Manufacturers.lua maps to 'list' here
directArgs['list' .. tostring( i )] = item.pages
end
if item.header then -- Also support 'header' if needed
directArgs['header' .. tostring( i )] = item.header
end
end
end
else
-- TODO: Add empty state to navplate
end
end
return p.navplateTemplate( { args = directArgs } )
end
end


return p
return p

2025年8月11日 (一) 13:58的版本

模板文档[查看][编辑][历史][刷新]
以下是模板的文档,点击右侧按钮去编辑文档

Module:Navplate implements the {{navplate}} template.


--------------------------------------------------------------------------------
-- Module:Navplate                                                            --
-- This module implements {{Navplate}}                                        --
-- Based on Module:Infobox                                                    --
-- This is a work in progress                                                 --
--------------------------------------------------------------------------------

local p = {}
local args = {}
local origArgs = {}

local function union( t1, t2 )
	-- Returns the union of the values of two tables, as a sequence.
	local vals = {}
	for k, v in pairs( t1 ) do
		vals[v] = true
	end
	for k, v in pairs( t2 ) do
		vals[v] = true
	end
	local ret = {}
	for k, v in pairs( vals ) do
		table.insert( ret, k )
	end
	return ret
end

-- Returns a table containing the numbers of the arguments that exist
-- for the specified prefix. For example, if the prefix was 'data', and
-- 'data1', 'data2', and 'data5' exist, it would return {1, 2, 5}.
local function getArgNums( prefix )
	local nums = {}
	for k, v in pairs( args ) do
		local num = tostring( k ):match( '^' .. prefix .. '([1-9]%d*)$' )
		if num then table.insert( nums, tonumber( num ) ) end
	end
	table.sort( nums )
	return nums
end

--- Get the string of the <details> element
--- TODO: Perhaps we should turn this into another module
---
--- @param data table
--- @param frame table
--- @return string
local function getDetailsHTML( data, frame )
	local summary = frame:extensionTag {
		name = 'summary',
		content = data.summary.content,
		args = {
			class = data.summary.class
		}
	}
	local details = frame:extensionTag {
		name = 'details',
		content = summary .. data.details.content,
		args = {
			class = data.details.class,
			role = data.details.role,
			open = data.details.open or 'no'
		}
	}
	return details
end


--- @param rowArgs table
--- @return mw.html
local function getRowHTML( rowArgs )
	local html = mw.html.create()
	-- Adds a row to the navplate, with either a header
	-- or a label/list combination.
	if rowArgs.header then
		html
			:tag( 'div' )
			:addClass( 'template-navplate__groupheader' )
			:wikitext( rowArgs.header )
	elseif rowArgs.list then
		html
			:tag( 'div' )
			:addClass( 'template-navplate-item' )
			:tag( 'div' )
			:addClass( 'template-navplate-item__label' )
			:wikitext( rowArgs.label )
			:done()
			:tag( 'div' )
			:addClass( 'template-navplate-item__list' )
			:wikitext( rowArgs.list )
	end
	return html
end


--- @return mw.html
local function getTitleHTML()
	local html = mw.html.create( 'div' )
	html:addClass( 'template-navplate__headerContent' )

	if not args.title then return end
	if args.subtitle then
		html
			:tag( 'div' )
			:addClass( 'template-navplate__subtitle' )
			:wikitext( args.subtitle )
			:done()
	end
	html
		:tag( 'div' )
		:addClass( 'template-navplate__title' )
		:wikitext( args.title )

	return html
end


--- @return mw.html
local function getRowsHTML()
	local html = mw.html.create()
	-- Gets the union of the header and list argument numbers,
	-- and renders them all in order using addRow.
	local rownums = union( getArgNums( 'header' ), getArgNums( 'list' ) )
	table.sort( rownums )
	for _, num in ipairs( rownums ) do
		html:node( getRowHTML( {
			header = args['header' .. tostring( num )],
			label = args['label' .. tostring( num )],
			list = args['list' .. tostring( num )]
		} ) )
	end
	return html
end

-- If the argument exists and isn't blank, add it to the argument table.
-- Blank arguments are treated as nil to match the behaviour of ParserFunctions.
local function preprocessSingleArg( argName )
	if origArgs[argName] and origArgs[argName] ~= '' then
		args[argName] = origArgs[argName]
	end
end

-- Assign the parameters with the given prefixes to the args table, in order, in
-- batches of the step size specified. This is to prevent references etc. from
-- appearing in the wrong order. The prefixTable should be an array containing
-- tables, each of which has two possible fields, a "prefix" string and a
-- "depend" table. The function always parses parameters containing the "prefix"
-- string, but only parses parameters in the "depend" table if the prefix
-- parameter is present and non-blank.
local function preprocessArgs( prefixTable, step )
	if type( prefixTable ) ~= 'table' then
		error( 'Non-table value detected for the prefix table', 2 )
	end
	if type( step ) ~= 'number' then
		error( 'Invalid step value detected', 2 )
	end

	-- Get arguments without a number suffix, and check for bad input.
	for i, v in ipairs( prefixTable ) do
		if type( v ) ~= 'table' or type( v.prefix ) ~= 'string' or
			(v.depend and type( v.depend ) ~= 'table') then
			error( 'Invalid input detected to preprocessArgs prefix table', 2 )
		end
		preprocessSingleArg( v.prefix )
		-- Only parse the depend parameter if the prefix parameter is present
		-- and not blank.
		if args[v.prefix] and v.depend then
			for j, dependValue in ipairs( v.depend ) do
				if type( dependValue ) ~= 'string' then
					error( 'Invalid "depend" parameter value detected in preprocessArgs' )
				end
				preprocessSingleArg( dependValue )
			end
		end
	end

	-- Get arguments with number suffixes.
	local a = 1 -- Counter variable.
	local moreArgumentsExist = true
	while moreArgumentsExist == true do
		moreArgumentsExist = false
		for i = a, a + step - 1 do
			for j, v in ipairs( prefixTable ) do
				local prefixArgName = v.prefix .. tostring( i )
				if origArgs[prefixArgName] then
					-- Do another loop if any arguments are found, even blank ones.
					moreArgumentsExist = true
					preprocessSingleArg( prefixArgName )
				end
				-- Process the depend table if the prefix argument is present
				-- and not blank, or we are processing "prefix1" and "prefix" is
				-- present and not blank, and if the depend table is present.
				if v.depend and (args[prefixArgName] or (i == 1 and args[v.prefix])) then
					for j, dependValue in ipairs( v.depend ) do
						local dependArgName = dependValue .. tostring( i )
						preprocessSingleArg( dependArgName )
					end
				end
			end
		end
		a = a + step
	end
end

local function parseDataParameters()
	preprocessSingleArg( 'id' )
	preprocessSingleArg( 'subtitle' )
	preprocessSingleArg( 'title' )
	preprocessArgs( {
		{ prefix = 'header' },
		{ prefix = 'list',  depend = { 'label' } },
	}, 50 )
end

local function _navplate()
	local frame = mw.getCurrentFrame()

	local summaryHTML = mw.html.create()
		:tag( 'div' )
		:addClass( 'citizen-ui-icon mw-ui-icon-wikimedia-collapse' )
		:done()
		:node( getTitleHTML() )

	local contentHTML = mw.html.create( 'div' )
		:addClass( 'template-navplate__content citizen-text-small' )
		:node( getRowsHTML() )

	local output = getDetailsHTML( {
		details = {
			class = 'template-navplate',
			content = tostring( contentHTML )
		},
		summary = {
			class = 'template-navplate__header',
			content = tostring( summaryHTML )
		}
	}, frame )

	return frame:extensionTag {
		name = 'templatestyles', args = { src = 'Module:Navplate/styles.css' }
	} .. output
end

-- If called via #invoke, use the args passed into the invoking template.
-- Otherwise, for testing purposes, assume args are being passed directly in.
function p.navplate( frame )
	if frame == mw.getCurrentFrame() then
		origArgs = frame:getParent().args
	else
		origArgs = frame
	end

	parseDataParameters()

	return _navplate()
end

-- Legacy method, do not use
-- For calling via #invoke within a template
function p.navplateTemplate( frame )
	origArgs = {}
	for k, v in pairs( frame.args ) do origArgs[k] = mw.text.trim( v ) end

	parseDataParameters()

	return _navplate()
end

-- For calling via other modules
function p.fromData( data )
	local directArgs = {}

	if not data or type( data ) ~= 'table' then
		-- TODO: Add error state
	else
		if data.title then
			directArgs.title = data.title
		end
		if data.subtitle then
			directArgs.subtitle = data.subtitle
		end
		if data.id then
			directArgs.id = data.id
		end

		if data.items and type( data.items ) == 'table' and #data.items > 0 then
			for i, item in ipairs( data.items ) do
				if type( item ) == 'table' then
					if item.label then
						directArgs['label' .. tostring( i )] = item.label
					end
					if item.pages then -- 'pages' from Manufacturers.lua maps to 'list' here
						directArgs['list' .. tostring( i )] = item.pages
					end
					if item.header then -- Also support 'header' if needed
						directArgs['header' .. tostring( i )] = item.header
					end
				end
			end
		else
			-- TODO: Add empty state to navplate
		end
	end

	return p.navplateTemplate( { args = directArgs } )
end

return p