跳转到内容

模組:沙盒/Yoyolin0409/Autolink

维基百科,自由的百科全书
local p = {}

local commonPrefix = 'Module:Autolink/'
local commonFallback = 'Other'
local globalDataSources = {}

local function getDataSource( src )
	if src == nil or src == '' then
		return nil
	end
	if string.find(src, '#') then
		local splits = mw.text.split(src, '#')
		if not globalDataSources[splits[1]] then
			globalDataSources[splits[1]] = mw.loadData(commonPrefix .. splits[1])
		end
		return globalDataSources[splits[1]][splits[2]]
	else
		if not globalDataSources[src] then
			globalDataSources[src] = mw.loadData(commonPrefix .. src)
		end
		return globalDataSources[src]
	end
end

local function grabName( tbl, key )
	if tbl[key] == nil then
		return nil
	end
	if type(tbl[key]) == 'string' then
		return tbl[key]
	elseif type(tbl[key]) == 'table' then
		return tbl[key][1]
	else
		return nil
	end
end

local function grabNameTwice( tbl, key )
	local result = grabName( tbl, key )
	if result == nil and key:sub(-1) == 's' then
		result = grabName( tbl, key:sub(0, -2) )
	end
	return result
end

local function grabFlags( tbl, key )
	local entry = tbl[key]
	if entry == nil then
		return nil
	end
	local result = {
		hideinlist = false,
		groups = 'main',
	}
	if type(entry) == 'table' then
		result.hideinlist = tbl[key][2]
		result.groups = tbl[key][3]
	end
	return result
end

local function resolveGroups( src )
	local result = {}
	if string.find(src, ',') then
		for v in mw.text.gsplit(src, ',') do
			local keyname = mw.text.trim(v)
			result[keyname] = 1
		end
	else
		result[src] = 1
	end
	return result
end

-- used by templates, called via #invoke
function p.link( f )
	local args = f
	if f == mw.getCurrentFrame() then
		args = require( 'Module:ProcessArgs' ).merge( true )
	end
	return p.invlink( args[1] , args[2] , args[3] )
end

function p.invlink( str, mode, spritetype )
	local arg = str:gsub('-', ' '):lower()

	local be
	local lce
	-- check for version suffix
	if arg:find(' pe$') or arg:find(' be$') then
		be = 1
		arg = arg:sub(0, -4)
	end
	if arg:find(' lce$') then
		lce = 1
		arg = arg:sub(0, -5)
	end

	-- registry
	local dataSources = {
		BlockSprite                 = { 'Block',                                'Exclusive#BlockSprite',  'Earth#BlockSprite' },
		ItemSprite                  = { 'Item',                                 'Exclusive#ItemSprite' ,  'Earth#ItemSprite'  },
		EntitySprite                = { 'Entity',                               'Exclusive#EntitySprite'                      },
		BiomeSprite                 = { 'Biome'                                                                               },
		EffectSprite                = { 'Effect'                                                                              },
--		?Sprite                     = { 'Enchantment'                                                                         },
		EnvSprite                   = { 'Environment'                                                                         },
		DungeonsItemSprite          = { 'Dungeons#DungeonsItemSprite'                                                         },
		DungeonsEntitySprite        = { 'Dungeons#DungeonsEntitySprite'                                                       },
		DungeonsEnchantmentSprite   = { 'Dungeons#DungeonsEnchantmentSprite'                                                  },
		DungeonsLevelSprite         = { 'Dungeons#DungeonsLevelSprite'                                                        },
		DungeonsEmoteSprite         = { 'Dungeons#DungeonsEmoteSprite'                                                        },
		DungeonsFlairSprite         = { 'Dungeons#DungeonsFlairSprite'                                                        },
		DungeonsMiscellaneousSprite = { 'Dungeons#DungeonsMiscellaneousSprite'                                                },
		LegendsEntitySprite         = { 'Legends#LegendsEntitySprite'                                                         },
		LegendsStructureSprite      = { 'Legends#LegendsStructureSprite'                                                      },
		EarthEntitySprite           = { 'Earth#EarthEntitySprite'                                                             },
		InvSprite                   = { 'Earth#InvSprite'                                                                     },
	}
	local dataSourcesList = {
		'BlockSprite',
		'ItemSprite',
		'EntitySprite',
		'BiomeSprite',
		'EffectSprite',
--		'?Sprite',
		'EnvSprite',
		'DungeonsItemSprite',
		'DungeonsEntitySprite',
		'DungeonsEnchantmentSprite',
		'DungeonsLevelSprite',
		'DungeonsEmoteSprite',
		'DungeonsFlairSprite',
		'DungeonsMiscellaneousSprite',
		'LegendsEntitySprite',
		'LegendsStructureSprite',
		'EarthEntitySprite',
		'InvSprite',
	}
	local dataSources_BE = {
		BlockSprite  = { 'Exclusive#BlockSprite',  'Block',  'Earth#BlockSprite' },
		ItemSprite   = { 'Exclusive#ItemSprite',   'Item',   'Earth#ItemSprite'  },
		EntitySprite = { 'Exclusive#EntitySprite', 'Entity'                      },
	}
	local dataSourcesList_BE = {
		'BlockSprite',
		'ItemSprite',
		'EntitySprite',
	}

	local result = nil
	-- get priored data source, then get name from it
	if spritetype then
		local dataSource_first = nil
		if be then
			dataSource_first = dataSources_BE[spritetype]
			if dataSource_first == nil then
				dataSource_first = dataSources[spritetype]
				if dataSource_first then
					dataSources[spritetype] = nil
				end
			else
				dataSources[spritetype] = nil
				dataSources_BE[spritetype] = nil
			end
		else
			dataSource_first = dataSources[spritetype]
			if dataSource_first and dataSources_BE[spritetype] then
				dataSources_BE[spritetype] = nil
			end
		end
		if dataSource_first then
			for i=1, #dataSource_first do
				result = grabNameTwice(getDataSource(dataSource_first[i]), arg)
				if result then
					break
				end
			end
		end
	end

	-- get name when sprite type is not set, or failed to find in the priored data source, traverse in order
	if result == nil then
		if be then
			for _, current_key in pairs(dataSourcesList_BE) do
				if dataSources_BE[current_key] then
					dataSources[current_key] = nil
					for _, current_value in pairs(dataSources_BE[current_key]) do
						result = grabNameTwice(getDataSource(current_value), arg)
						if result then
							break
						end
					end
					if result then
						break
					end
				end
			end
		end
		if result == nil then
			for _, current_key in pairs(dataSourcesList) do
				if dataSources[current_key] then
					for _, current_value in pairs(dataSources[current_key]) do
						result = grabNameTwice(getDataSource(current_value), arg)
						if result then
							break
						end
					end
					if result then
						break
					end
				end
			end
		end
	end

	-- fallback to Module:Autolink/Other or even the string itself
	if result == nil then
		result = grabNameTwice(getDataSource(commonFallback), arg) or str
	end

	-- formatting
	if be then
		return p.mode(result, mode, '(基岩版)')
	end
	if lce then
		return p.mode(result, mode, '(原主机版)')
	end

	return p.mode(result, mode)
end

function p.mode( str, mode, suffix )
	if suffix then
		if str:find('|') then
			str = str .. suffix
		else
			str = str .. '|' .. str .. suffix
		end
	end
	local index = str:find('|')
	-- return the translated part
	if index then
		if mode == 'nolink' then
		  return str:sub(index + 1)
		end
		-- return the page link part
		if mode == 'linkonly' then
			return str:sub(1, index - 1)
		end
	end
	return str
end

-- list out all entries with the type
function p.list( f )
	local args = f
	if f == mw.getCurrentFrame() then
		args = require( 'Module:ProcessArgs' ).merge( true )
	end
	local type = args[1]
	type = type:lower()
	local groups = args.groups or 'main'
	groups = groups:lower()
	groups = mw.text.trim(groups)
	local sprite = nil
	local list = nil
	
	local dataRegistry = {
		block                 = { 'Block',                                'BlockSprite'                 },
		item                  = { 'Item',                                 'ItemSprite'                  },
		entity                = { 'Entity',                               'EntitySprite'                },
		biome                 = { 'Biome',                                'BiomeSprite'                 },
		effect                = { 'Effect',                               'EffectSprite'                },
		enchantment           = { 'Enchantment',                          ''                            },
		environment           = { 'Environment',                          'EnvSprite'                   },
		dungeonsitem          = { 'Dungeons#DungeonsItemSprite',          'DungeonsItemSprite'          },
		dungeonsentity        = { 'Dungeons#DungeonsEntitySprite',        'DungeonsEntitySprite'        },
		dungeonsenchantment   = { 'Dungeons#DungeonsEnchantmentSprite',   'DungeonsEnchantmentSprite'   },
		dungeonslevel         = { 'Dungeons#DungeonsLevelSprite',         'DungeonsLevelSprite'         },
		dungeonsemote         = { 'Dungeons#DungeonsEmoteSprite',         'DungeonsEmoteSprite'         },
		dungeonsflair         = { 'Dungeons#DungeonsFlairSprite',         'DungeonsFlairSprite'         },
		dungeonsmiscellaneous = { 'Dungeons#DungeonsMiscellaneousSprite', 'DungeonsMiscellaneousSprite' },
		legendsentity         = { 'Legends#LegendsEntitySprite',          'LegendsEntitySprite'         },
		legendsstructure      = { 'Legends#LegendsStructureSprite',       'LegendsStructureSprite'      },
		earthentity           = { 'Earth#EarthEntitySprite',              'EarthEntitySprite'           },
	}
	if dataRegistry[type] == nil then
		return ''
	end
	list = getDataSource(dataRegistry[type][1])
	sprite = dataRegistry[type][2]
	if list == nil or sprite == nil then
		return ''
	end

	local result = ''
	local t = {}

	for k, _ in pairs(list) do
		local flags = grabFlags(list, k)
		if flags.hideinlist == false then
			local query_groups = resolveGroups(groups)
			local store_groups = resolveGroups(flags.groups)
			for current_query, _ in pairs(query_groups) do
				if store_groups[current_query] then
					table.insert(t, k)
				end
			end
		end
	end

	table.sort(t)

	local limit = 50
	local count = 0

	local frame = mw.getCurrentFrame()

	local itemlist = nil
	local header = mw.html.create('tr')
	local spriteids = nil
	if sprite ~= '' then
		spriteids = mw.loadData( 'Module:' .. sprite ).ids
		header:tag('th'):wikitext('图标')
	end
	header:tag('th'):wikitext('英文名称')
	header:tag('th'):wikitext('中文名称')

	for _, v in ipairs(t) do
		if count == 0 then
			if itemlist ~= nil then
				result = result .. tostring(itemlist)
			end
			itemlist = mw.html.create('table')
				:addClass('data-table')
				:node(header)
		end

		local row = mw.html.create('tr')
		if sprite ~= '' then
			if spriteids[v] or spriteids[mw.ustring.lower( v ):gsub( '[%s%+]', '-' )] then
				row:tag('td'):wikitext(frame:expandTemplate{ title = sprite, args = { v } })
			else
				row:tag('td')
			end
		end
		local words = {}
		v:gsub('[^%s]+', function(w) table.insert(words, w) end)
		for k, w in ipairs(words) do
			if w ~= 'of' and w ~= 'or' and w ~= 'o\'' then
				words[k] = w:gsub('(%l)(.+)', function(a, b) return a:upper() .. b end)
			end
		end
		row:tag('td'):wikitext(tostring(table.concat(words, ' ')))
		row:tag('td'):wikitext(p.mode(grabName(list, v), 'nolink'))
		itemlist:node(row)
		count = count + 1
		if count == limit then
			count = 0
		end
	end

	result = result .. tostring(itemlist)
	return result
end

return p