توضیحات این پودمان می‌تواند در ماژول:Protection/توضیحات قرار گیرد.

-- Ce module implémente les modèles {{Protection}}, {{Semi-protection étendue}}, {{Semi-protection}}, {{Semi-protection longue}} et {{Nom protégé}}.

local p = {}

-- Chargement du module de données.
local donnees = mw.loadData('Module:Protection/Données')

-- Définition des tables de données.
local types = donnees.types
local cfg = donnees.configuration

--Redéfinitions utiles.
local format = mw.ustring.format
local insert = table.insert

local function protectionPage(typeProtection, modeProtection, titrePage)
	-- Retourne vrai si la page courante est protégée et correspond
	-- au type de protection.
	local action = types[typeProtection].action or 'edit'
	local niveau = titrePage.protectionLevels[action] and titrePage.protectionLevels[action][1]
	return modeProtection.niveau == niveau
end

local function estSousPage(titrePage)
	-- Teste si la page actuelle est une sous-page /Documentation,
	-- /Bac à sable ou /Test de modèle ou de module. Retourne vrai
	-- si c'est le cas et faux sinon.
	local espaceNom = titrePage.nsText == 'Modèle' or titrePage.nsText == 'Module'
	local sousPage = titrePage.isSubpage and 
		(titrePage.subpageText == 'Documentation'
		or titrePage.subpageText == 'Bac à sable'
		or titrePage.subpageText == 'Test')
 
	return espaceNom and sousPage
end
 
local function creerIconeTitre(modeProtection)
	local iconeTitre = require('Module:Icône de titre')._main
	local argsIcone = {
		image  = modeProtection.image,
		lien   = modeProtection.lien,
		texte  = modeProtection.texte,
		taille = 15,
		id     = modeProtection.id or 'protection-edition'
	}
 
	return iconeTitre(argsIcone)
end

local function insertionCategorie(typeProtection, nsPage)
	local nomCategorie = typeProtection.categorie[nsPage]
	local defautCategorie = typeProtection.categorie['défaut']
	local lienCategorie = '[[Catégorie:%s]]'
 
	return format(lienCategorie, nomCategorie or defautCategorie)
end

local function bandeauProtection(titrePage, args)
	local nsPage = args.nsdoc or titrePage.nsText
	local titre = cfg[nsPage] or cfg['titreDéfaut']
	local texte = mw.html.create('span')
	local pageDiscussion, lienAdmin, lienJournal
 
	-- Gestion du nombre d'inclusions pour les modèles/modules.
	if nsPage == 'Modèle' or nsPage == 'Module' then
		titre = format(titre, titrePage:partialUrl())
	end
 
	-- Gestion du paramètre 'texte' et de ses liens internes
	pageDiscussion = tostring(titrePage.talkPageTitle)
	lienAdmin = mw.title.new(cfg['lienAdmin'])
		:fullUrl(format(cfg['optionAdmin'],
			mw.uri.encode(titrePage.fullText, 'WIKI')))
	if nsPage == '' then lienAdmin = lienAdmin .. cfg['option2Admin'] end
	lienJournal = mw.title.new(cfg['lienJournal'])
		:fullUrl(format(cfg['optionJournal'],
			mw.uri.encode(titrePage.fullText, 'WIKI')))
 	
	texte
		:addClass('plainlinks')
		:wikitext(format(cfg['texteBandeau'], 
			pageDiscussion, pageDiscussion, lienAdmin, lienJournal))
 
	return require('Module:Bandeau')._bandeauAvertissement{
		niveau    = 'information',
		['icône'] = types['protection'].image,
		['domaine public'] = true,
		titre     = args[1] or titre,
		texte     = tostring(texte)
	}
end

function p.main(args, typeProtection, titrePage)
	typeProtection = typeProtection or 'protection'
	local modeProtection = types[typeProtection]
	local titrePage = titrePage or mw.title.getCurrentTitle()
	local res = {}
 
	if typeProtection == 'protection' and args.nocat then
		return bandeauProtection(titrePage, args)
	end
 
	if protectionPage(typeProtection, modeProtection, titrePage) then
		-- Création de l'icône de titre selon le mode de protection.
		insert(res, creerIconeTitre(modeProtection))
		-- Création du bandeau de protection pour le mode 'protection'.
		if typeProtection == 'protection' then
			insert(res, bandeauProtection(titrePage, args))
		end
		-- Catégorisation selon le mode de protection.
		insert(res, insertionCategorie(modeProtection, titrePage.nsText))
	elseif not estSousPage(titrePage) then
		-- Catégorisation lorsque le niveau de protection en écriture ne
		-- correspond pas ou plus. Note : les sous-pages '/Documentation',
		-- '/Bac à sable' ou '/Test' appartenant aux modèles ou aux modules
		-- ne sont pas – et ne doivent pas être – concernées.
		insert(res, '[[Catégorie:Page dont la protection est à vérifier]]')
	end
 
	return table.concat(res)
end

local function adaptateur(nomFonction)
	return function (frame)
		local args = {}
		local argsParent = frame:getParent().args
 
		-- Paramètres vides interprétés par Lua.
		for cle, val in pairs(argsParent) do
			if type(cle) == number then
				val = mw.text.trim(val)
			end
			if val ~= '' or cle == 'nsdoc' then
				args[cle] = val
			end
		end
 
		return p.main(args, nomFonction)
	end
end
 
-- Insertion dans la table p des fonctions appelées par les
-- modèles à l'aide d'un adaptateur de fonction.
local nomsFonction = {'protection', 'semiProtectionEtendue', 'semiProtection', 'semiProtectionLongue', 'nomProtégé'} 
for _, nomFonction in ipairs(nomsFonction) do
	p[nomFonction] = adaptateur(nomFonction)
end

return p