Модуль:Validate gadgets

Из Википедии, бесплатной энциклопедии

Документация
local MessageBox = require('Module:Message box') local Gadgets = require('Module:Gadgets')  local p = {}  local function arr_contains(array, val)     for _, value in ipairs(array) do         if value == val then             return true         end     end     return false end  -- Lists of valid options for things that aren't exposed to lua  -- (unlike namespaces that can be accessed from mw.site.namespaces) local VALID_CONTENT_MODELS = {'wikitext', 'javascript', 'css', 'json', 'MassMessageListContent', 'Scribunto', 'sanitized-css'}  p.validate = function (frame) 	local frame = mw.getCurrentFrame() 	-- ignore text in noinclude tags 	local text = frame:expandTemplate{ title = 'MediaWiki:Gadgets-definition' } 	local lines = mw.text.split(text, '\n', false) 	 	local repo = {} 	local allWarnings = {}	 	 	-- A bit of parsing is reimplemented here as [[Module:Gadgets]] doesn't raise warnings 	-- for invalid lines 	for _, line in ipairs(lines) do 		if line:sub(1, 1) == '*' then 			local name, options, pages = Gadgets.parse_line(line) 			if not name or #pages == 0 then 				table.insert(allWarnings, '* Invalid definition: '..line) 			else 				repo[name] = { options = options, pages = pages } 			end 		end 	end 	 	for name, conf in pairs(repo) do 		local warnings = p.create_warnings(name, conf.options, conf.pages, repo) 		for _, warning in ipairs(warnings) do 			table.insert(allWarnings, '*'..name..': '..warning) 		end 	end  	if #allWarnings ~= 0 then 		return MessageBox.main('ombox', { 			text = '<b>Issues in gadget definitions:</b>\n' .. table.concat(allWarnings, '\n'), 			type = 'delete', 			class = 'gadgets-validation' 		}) 	elseif require('Module:If preview/configuration').preview then 		return MessageBox.main('ombox', { 			text = '<b>Issues in gadget definitions:</b> <i>No issues found!</i>', 			type = 'notice', 			image = '[[File:Check-green.svg|30px]]', 			class = 'gadgets-validation' 		}) 	else  		return '' 	end end  p.create_warnings = function(name, options, pages, repo) 	local warnings = {} 	 	-- RL module name (ext.gadget.<name>) should not exceed 255 bytes 	-- so a limit of 255 - 11 = 244 bytes for gadget name 	if string.len(name) > 244 then 		table.insert(warnings, 'Gadget name must not exceed 244 bytes') 	end  	-- Per ResourceLoader::isValidModuleName 	if name:gsub('[|,!]', '') ~= name then 		table.insert(warnings, 'Gadget name must not contain pipes (|), commas (,) or exclamation marks (!)') 	end  	-- Pattern per MediaWikiGadgetDefinitionsRepo::newFromDefinition 	if not string.match(name, "^[a-zA-Z][-_:%.%w ]*[a-zA-Z0-9]?$") then 		table.insert(warnings, 'Gadget name is used as part of the name of a form field, and must follow the rules defined in https://www.w3.org/TR/html4/types.html#type-cdata') 	end      if options.type ~= nil and options.type ~= 'general' and options.type ~= 'styles' then     	table.insert(warnings, 'Allowed values for type are: general, styles')     end     if options.targets ~= nil then     	table.insert(warnings, 'Setting targets in gadget defintion is deprecated and no longer has any effect')     end     if options.namespaces ~= nil then     	for _, id in ipairs(mw.text.split(options.namespaces, ',', false)) do     		if not string.match(id, '^-?%d+$') then     			table.insert(warnings, 'Invalid namespace id: '..id..' - must be numeric')     		elseif mw.site.namespaces[tonumber(id)] == nil then     			table.insert(warnings, 'Namespace id '..id..' is invalid')     		end     	end     end     if options.actions ~= nil then     	for _, action in ipairs(mw.text.split(options.actions, ',', false)) do     		if not mw.message.new('action-' .. action):exists() then     			table.insert(warnings, 'Action '..action..' is unrecognised')     		end     	end     end     if options.contentModels ~= nil then     	for _, model in ipairs(mw.text.split(options.contentModels, ',', false)) do     		if not arr_contains(VALID_CONTENT_MODELS, model) then     			table.insert(warnings, 'Content model '..model..' is unrecognised')     		end     	end     end     if options.skins ~= nil then     	for _, skin in ipairs(mw.text.split(options.skins, ',', false)) do     		if not mw.message.new('skinname-' .. skin):exists() then     			table.insert(warnings, 'Skin '..skin..' is not available')     		end     	end     end     if options.rights ~= nil then     	for _, right in ipairs(mw.text.split(options.rights, ',', false)) do     		if not mw.message.new('right-' .. right):exists() then     			table.insert(warnings, 'User right '..right..' does not exist')     		end     	end     end      local scripts = {}     local styles = {}     local jsons = {}     for _, page in ipairs(pages) do     	page = 'MediaWiki:Gadget-' .. page     	local title = mw.title.new(page)     	if title == nil or not title.exists then     		table.insert(warnings, 'Page [['..page..']] does not exist')     	else  	    	local ext = title.text:match("%.([^%.]+)$") 	    	if ext == 'js' then 	    		if title.contentModel ~= 'javascript' then 	    			table.insert(warnings, 'Page [['..page..']] is not of JavaScript content model') 	    		else 	    			table.insert(scripts, page) 	    		end 	    	elseif ext == 'css' then 	    		if title.contentModel ~= 'css' then 	    			table.insert(warnings, 'Page [['..page..']] is not of CSS content model') 	    		else 	    			table.insert(styles, page) 	    		end 	    	elseif ext == 'json' then 	    		if title.contentModel ~= 'json' then 	    			table.insert(warnings, 'Page [['..page..']] is not of JSON content model') 	    		else 	    			table.insert(jsons, page) 	    		end 	    	else 	    		table.insert(warnings, 'Page [['..page..']] is not JS/CSS/JSON, will be ignored') 	    	end 	    end     end      if not options.hidden then 	    local description_page = mw.title.new('MediaWiki:Gadget-'..name) 	    if description_page == nil or not description_page.exists then 	    	table.insert(warnings, 'Description [['..description_page.fullText..']] for use in Special:Preferences does not exist') 	    end 	end      if options.package == nil and #jsons > 0 then     	table.insert(warnings, 'JSON pages cannot be used in non-package gadgets')     end     if options.requiresES6 ~= nil and options.default ~= nil then     	table.insert(warnings, 'Default gadget cannot use requiresES6 flag')     end     if options.type == 'styles' and #scripts > 0 then     	table.insert(warnings, 'JS pages will be ignored as gadget sets type=styles')     end     if options.type == 'styles' and options.peers ~= nil then     	table.insert(warnings, 'Styles-only gadget cannot have peers')     end     if options.type == 'styles' and options.dependencies ~= nil then     	table.insert(warnings, 'Styles-only gadget cannot have dependencies')     end     if options.package ~= nil and #scripts == 0 then     	table.insert(warnings, 'Package gadget must have at least one JS page')     end     if options.ResourceLoader == nil and #scripts > 0 then     	table.insert(warnings, 'ResourceLoader option must be set')     end     -- Causes warnings on styles-only gadgets using skins param      -- if options.hidden ~= nil and (options.namespaces ~= nil or options.actions ~= nil or options.rights ~= nil or options.contentModels ~= nil or options.skins ~= nil) then     -- 	table.insert(warnings, 'Conditional load options are not applicable for hidden gadget')     -- end  	if options.peers ~= nil then 		for _, peer in ipairs(mw.text.split(options.peers, ',', false)) do  			if repo[peer] == nil then 				table.insert(warnings, 'Peer gadget '..peer..' is not defined') 			elseif Gadgets.get_type(repo[peer]) == 'general' then 				table.insert(warnings, 'Peer gadget '..peer..' must be styles-only gadget') 			end 		end 	end  	if options.dependencies ~= nil then 		for _, dep in ipairs(mw.text.split(options.dependencies, ',', false)) do 			if dep:sub(1, 11) == 'ext.gadget.' then 				local dep_gadget = dep:sub(12) 				if repo[dep_gadget] == nil then 					table.insert(warnings, 'Dependency gadget '..dep_gadget..' is not defined') 				end 			end 		end 	end  	return warnings end  return p