Module:Argument
La documentation pour ce module peut être créée à Module:Argument/doc
-- Module:Argument
-- Portage du modèle "Argument" vers Lua (Scribunto)
-- Version avec pré-expansion systématique des parser functions via frame:preprocess()
local p = {}
local i18n = mw.loadData('Module:Argument/i18n')
-- ===== Utilitaires =====
local function _(lang, key)
local L = i18n[lang] or i18n.en or {}
return L[key] or ('['..key..']')
end
local function param(args, ...)
for _,k in ipairs{...} do
local v = args[k]
if v and v ~= '' then return v end
end
return ''
end
local function esc_attr(s)
if not s then return '' end
s = tostring(s)
s = s:gsub('"', '"')
return s
end
local function italics(lang, textKey)
return "'' " .. _(lang, textKey) .. " ''"
end
local function titleData()
local t = mw.title.getCurrentTitle()
local full = t.prefixedText -- FULLPAGENAME
local id = tostring(t.id or '')
return {
full = full,
fullEnc = mw.uri.encode(full, 'WIKI'),
id = id,
url = tostring(mw.uri.fullUrl(full)),
}
end
-- Pré-expansion d'un bloc de wikitexte/ParserFunctions
local function pf(frame, txt)
return frame:preprocess(txt)
end
-- Ajout de catégorie via i18n (nom complet comme "Catégorie:XYZ")
local function emitCategory(lang, key)
local name = _(lang, key)
if not name or name == '' or name:match('^%[') then return '' end
return string.format('[[%s]]', name)
end
-- ===== Sections =====
local function renderKeywords(frame, args, lang)
local out = {}
table.insert(out, '<div style="font-size:95%;margin-top:1em;"><b>' .. _(lang,'keywords') .. '</b> : ')
local mots = param(args,'mots-clés','mots_cles','keywords')
if mots == '' then
table.insert(out, _(lang,'none'))
table.insert(out, emitCategory(lang,'cat-arguments-sans-mot-cle'))
else
table.insert(out, pf(frame, '{{#arraymaptemplate: '..mots..' | '.._(lang,'keyword-template')..' }}'))
end
table.insert(out, pf(frame,
'<span class="modifier-rubrique navigation-not-searchable">{{#formlink:'
.. ' | link text = '.._(lang,'edit')
.. ' | form = '.._(lang,'form-argument-keywords')
.. ' | target = {{FULLPAGENAMEE}}'
.. ' | tooltip = '.._(lang,'edit-keywords-tooltip')
.. ' }}</span>'
))
table.insert(out, '<span style="display:none;">.</span></div>')
return table.concat(out, '')
end
local function renderSummary(frame, args, lang)
local out = {}
table.insert(out, pf(frame, '<div style="display:none;">{{Sommaire | niveau = 1}}</div>'))
table.insert(out, '<h2 id="Summary" class="section-modifiable">'
.. '<span style="margin-right:0.5em;">[[Fichier:Contributions.svg | 17px | link= | alt='..esc_attr(_(lang,'summary-title'))..']]</span>'
.. _(lang,'summary-title') .. pf(frame,
'<span class="modifier-section navigation-not-searchable noprint">{{#formlink:'
.. ' | link text = '.._(lang,'edit')
.. ' | form = '.._(lang,'form-summary')
.. ' | target = {{FULLPAGENAMEE}}'
.. ' | tooltip = '.._(lang,'edit-summary-tooltip')
.. ' }}</span>'
) .. '</h2>')
local resume = param(args,'résumé','summary')
local warnings = param(args,'avertissements-résumé','warnings-summary')
if resume ~= '' then
if warnings ~= '' then
table.insert(out, pf(frame, '{{#arraymap: '..warnings..' | , | x | {{Bandeau x}} |   }}'))
end
table.insert(out, '<div>'..resume..'</div>')
if warnings ~= '' then
table.insert(out, pf(frame, '{{#arraymap: '..warnings..' | , | x | {{#switch: x'
.. ' | Résumé désavantageux = '..emitCategory(lang,'cat-resume-desavantageux')
.. ' | Résumé peu clair = '..emitCategory(lang,'cat-resume-peu-clair')
.. ' | Résumé trop long = '..emitCategory(lang,'cat-resume-trop-long')
.. ' | Résumé à rédiger = '..emitCategory(lang,'cat-resume-a-rediger')
.. ' | Arguments à séparer = '..emitCategory(lang,'cat-arguments-a-separer')
.. ' | Style à revoir = '..emitCategory(lang,'cat-style-a-revoir')
.. ' }} |   }}'))
end
else
table.insert(out, '<div class="aucun-contenu navigation-not-searchable">'..italics(lang,'summary-empty')..'</div>')
table.insert(out, emitCategory(lang,'cat-arguments-sans-resume'))
end
return table.concat(out, '\n')
end
local function renderQuotes(frame, args, lang)
local out = {}
table.insert(out, '<h2 id="Quotes" class="section-modifiable">'
.. '<span style="margin-right:0.5em;">[[Fichier:Citation.svg | 17px | link= | alt='..esc_attr(_(lang,'quotes-title'))..']]</span>'
.. _(lang,'quotes-title') .. pf(frame,
'<span class="modifier-section navigation-not-searchable noprint">{{#formlink:'
.. ' | link text = '.._(lang,'edit')
.. ' | form = '.._(lang,'form-quotes')
.. ' | target = {{FULLPAGENAMEE}}'
.. ' | tooltip = '.._(lang,'edit-quotes-tooltip')
.. ' }}</span>'
) .. '</h2>')
local quotes = param(args,'citations','quotes')
if quotes == '' then
table.insert(out, '<div class="aucun-contenu navigation-not-searchable">'..italics(lang,'quotes-empty')..'</div>')
table.insert(out, emitCategory(lang,'cat-arguments-sans-citation'))
else
table.insert(out, quotes)
end
return table.concat(out, '\n')
end
local function renderDetailedDebate(frame, args, lang)
local debate = param(args,'débat-détaillé','debat-detaille','detailed-debate')
if debate == '' then return '' end
local out = {}
table.insert(out, emitCategory(lang,'cat-arg-debat-detaille'))
table.insert(out, pf(frame, '{{#set: '.._(lang,'prop-debat-detaille')..' = '..debate..' }}'))
table.insert(out,
'<h2 id="Debate" class="section-modifiable">'
.. '<span style="margin-right:0.5em; position:relative; bottom:1px;">[[Fichier:Parcourir.svg | 17px | link= | alt='..esc_attr(_(lang,'detailed-debate'))..']]</span>'
.. _(lang,'detailed-debate')
.. pf(frame,
'<span class="modifier-section navigation-not-searchable noprint">{{#formlink:'
.. ' | link text = '.._(lang,'edit')
.. ' | form = '.._(lang,'form-detailed-debate')
.. ' | target = {{FULLPAGENAMEE}}'
.. ' | tooltip = '.._(lang,'edit-detailed-debate-tooltip')
.. ' }}</span>'
)
.. '</h2>'
)
table.insert(out,
'<div style="border-style:solid; border-width:0 0 0 6px; margin:1em 0; padding:2px 10px; border-color:#02a68f;">\n'
.. '<table style="background-color:transparent"><tr><td style="font-weight:bold;">'
.. _(lang,'debate-banner-1') .. ' <span style="font-weight:normal;">{{FULLPAGENAME}}</span> ' .. _(lang,'debate-banner-2')
.. '</td></tr><tr><td><div class="bandeau-section navigation-not-searchable onglet-externe" style="margin:0.25em 0; padding-right:0.25em; position:inherit;">'
.. '<span style="margin:0 0.5em 0 0.25em">[[Fichier: Loupe.svg | 13px | lien= | class=mw-no-invert]]</span>'
.. _(lang,'detailed-debate') .. ' : [[' .. debate .. ']]</div></td></tr></table></div>'
)
table.insert(out,
'<div style="color:black; background-color:#f9f9f9; font-size:95%; width:100%; padding:5px;" class="onglet-externe">'
.. '<div style="font-weight:bold; font-size:150%; font-family:\'Linux Libertine\',\'Georgia\',\'Times\',serif; line-height:1.25; margin-bottom:0.25em;">'
.. debate .. '</div>'
.. pf(frame, '{{#vardefine: Carte-arguments | {{#show: '..debate..' | ?'.._(lang,'prop-carte-arguments')..'}} }}{{#var: Carte-arguments}}')
.. '</div>'
)
return table.concat(out, '\n')
end
local function renderReferences(frame, args, lang)
local out = {}
table.insert(out, '<h2 id="References" class="section-modifiable">'
.. '<span style="margin-right:0.5em;">[[Fichier:Bibliographie.svg | 15px | link= | alt='..esc_attr(_(lang,'references'))..']]</span>'
.. _(lang,'references') .. pf(frame,
'<span class="modifier-section navigation-not-searchable noprint">{{#formlink:'
.. ' | link text = '.._(lang,'edit')
.. ' | form = '.._(lang,'form-references')
.. ' | target = {{FULLPAGENAMEE}}'
.. ' | tooltip = '.._(lang,'edit-references-tooltip')
.. ' }}</span>'
) .. '</h2>')
local warns = param(args,'avertissements-références','warnings-references')
local biblio = param(args,'références-bibliographiques','references-bibliographiques','ref-biblio')
local sito = param(args,'références-sitographiques','ref-sito')
local video = param(args,'références-vidéographiques','ref-video')
if warns ~= '' then
table.insert(out, pf(frame, '{{#arraymap: '..warns..' | , | x | {{Bandeau x}} |   }}'))
end
if (biblio ~= '' or sito ~= '' or video ~= '') then
table.insert(out, pf(frame, '{{#vardefine: References-argument | }}'))
table.insert(out, pf(frame, '{{#vardefine: References-argument | {{#var: References-argument}}<ul class="references-argument">'..biblio..sito..video..'</ul> }}'))
table.insert(out, pf(frame, '{{#var: References-argument}}'))
else
table.insert(out, '<div class="aucun-contenu navigation-not-searchable">'..italics(lang,'references-empty')..'</div>')
table.insert(out, emitCategory(lang,'cat-arguments-sans-reference'))
end
return table.concat(out, '\n')
end
local function renderList(titleId, icon, labelKey, formKey, paramName, warnParam, emptyCatKey, addButton)
return function(frame, args, lang)
local out = {}
table.insert(out, '<h2 id="'..titleId..'" class="section-modifiable">'
.. '<span style="margin-right:0.5em; position:relative; bottom:1px;">[[Fichier:'..icon..' | 22px | link= | alt='..esc_attr(_(lang,labelKey))..']]</span>'
.. _(lang,labelKey) .. pf(frame,
'<span class="modifier-section navigation-not-searchable noprint">{{#formlink:'
.. ' | link text = '.._(lang,'edit')
.. ' | form = '.._(lang,formKey)
.. ' | target = {{FULLPAGENAMEE}}'
.. ' | tooltip = '.._(lang,'edit-list-tooltip')
.. ' }}</span>'
) .. '</h2>')
local warns = param(args, warnParam)
if warns ~= '' then
table.insert(out, pf(frame, '{{#arraymap: '..warns..' | , | x | {{Bandeau x}} |   }}'))
end
local items = param(args, paramName)
table.insert(out, '<ul class="liste-arguments">')
if items == '' then
table.insert(out, '<div class="aucun-contenu navigation-not-searchable">'..italics(lang,'list-empty')..'</div>')
table.insert(out, emitCategory(lang, emptyCatKey))
else
table.insert(out, items)
end
table.insert(out, '</ul>')
if addButton then
table.insert(out, pf(frame,
'{{#queryformlink:'
.. ' | form = '.._(lang,'form-new-argument-title')
.. ' | query string = '..addButton..'={{PAGEID}}&_run'
.. ' | link type = post button'
.. ' | link text = '.._(lang,'add-argument')
.. ' | tooltip = '.._(lang,'add-argument-tooltip')..' : {{FULLPAGENAME}}'
.. ' }}'
))
end
return table.concat(out, '\n')
end
end
local renderJustifications = renderList('Pros', 'Argument-pour.svg', 'justifications-title', 'form-justifications', 'justifications', 'avertissements-justifications', 'cat-arguments-sans-justification', 'Nouveau titre d\'argument[type]=Justification&Nouveau titre d\'argument[ID]')
local renderObjections = renderList('Cons', 'Argument-contre.svg', 'objections-title', 'form-objections', 'objections', 'avertissements-objections', 'cat-arguments-sans-objection', 'Nouveau titre d\'argument[type]=Objection&Nouveau titre d\'argument[ID]')
local function renderParents(frame, args, lang)
-- On génère le wikitexte SMW et Arrays puis on le pré-expanse en un bloc
local wt = table.concat({
'{{#vardefine: Debats-parents | }}',
'{{#vardefine: Debats-parents-argupour | {{#ask: [[Argument pour::{{FULLPAGENAME}}]] | sep = -;- | link = none }} }}',
'{{#vardefine: Debats-parents-argucontre | {{#ask: [[Argument contre::{{FULLPAGENAME}}]] | sep = -;- | link = none }} }}',
'{{#vardefine: Debats-parents | {{#var: Debats-parents-argupour}} -;- {{#var: Debats-parents-argucontre}} }}',
'{{#arraydefine: Debats-parents | {{#var: Debats-parents}} | -;- }}',
'{{#arrayunique: Debats-parents}}',
'{{#vardefine: Nombre-debats-parents | {{#arraysize: Debats-parents}} }}',
'{{#switch: {{#var: Nombre-debats-parents}}'
.. ' | 0 = '
.. ' | 1 = <h2 id="Parent_debates"><span style="margin-right:0.45em;">[[Fichier:Fleche-haut.svg | 20px | link= | alt='..esc_attr(_(lang,'parent-debate'))..']]</span>'.._(lang,'parent-debate')..'</h2>'
.. ' <ul class="navigation-not-searchable"><li style="position: relative;">{{Carte des arguments | {{#arrayprint: Debats-parents | -;-}} | {{FULLPAGENAME}} | hover-top | débat}}</li></ul>'
.. ' | #default = <h2 id="Parent_debates"><span style="margin-right:0.45em;">[[Fichier:Fleche-haut.svg | 20px | link= | alt='..esc_attr(_(lang,'parent-debates'))..']]</span>'.._(lang,'parent-debates')..'</h2>'
.. ' <ul class="navigation-not-searchable">{{#arraymap: {{#arrayprint: Debats-parents | -;-}} | -;- | x | <li style="position: relative;">{{Carte des arguments | x | {{FULLPAGENAME}} | hover-top | débat}}</li> | }}</ul>'
.. ' }}'
}, '\\n')
return pf(frame, wt)
end
local function renderSEO(frame, args, lang, t)
return pf(frame, '{{#seo:'
.. ' | title = '.._(lang,'seo-title-prefix')..' {{FULLPAGENAME}} '.._(lang,'seo-title-suffix')
.. ' | title_mode = '.._(lang,'seo-title-mode-prefix')..' {{FULLPAGENAME}}'
.. ' | title_separator = –'
.. ' | description = '.._(lang,'seo-description-prefix')..' {{#if: {{{mots-clés|}}} | {{{mots-clés|}}} | {{FULLPAGENAME}} }}. '
.. _(lang,'seo-description-suffix')
.. ' | keywords = '.._(lang,'seo-keywords')..', {{{mots-clés|}}}, {{{rubriques|}}}, débat, objection, thèse, wiki, encyclopédie, opinion'
.. ' | image = '.._(lang,'seo-image')
.. ' | image_alt = '.._(lang,'seo-image-alt')
.. ' | type = article'
.. ' | section = '.._(lang,'seo-section')
.. ' | site_name = '.._(lang,'seo-site-name')
.. ' | twitter_site = '.._(lang,'seo-twitter')
.. ' | google-site-verification = 76d1055d3ec815c'
.. ' | locale = '.._(lang,'seo-locale')
.. ' | hreflang_de-de = https://de.wikidebates.org/'
.. ' | hreflang_en-us = https://en.wikidebates.org/'
.. ' | hreflang_es-es = https://es.wikidebates.org/'
.. ' | hreflang_it-it = https://it.wikidebates.org/'
.. ' | hreflang_pt-pt = https://pt.wikidebates.org/'
.. ' | og:url = '..t.url
.. ' }}')
end
local function renderInterlang(frame, args)
local out = {}
local inter = param(args,'interlangue','interlanguage')
if inter ~= '' then table.insert(out, inter) end
local interwiki = param(args,'interwiki')
if interwiki ~= '' then
table.insert(out, pf(frame, '{{#arraymap: '..interwiki..' | ; | <page> | [[<page>]] | }}'))
end
return table.concat(out, '\n')
end
local function titleChecks(frame, lang, t)
local out = {}
if mw.ustring.len(t.full) < 3 then
table.insert(out,
'<div class="warningbox navigation-not-searchable">\n<b>' ..
_(lang,'title-warning-short') ..
'</b></div>'
)
table.insert(out, emitCategory(lang,'cat-titres-tres-courts'))
end
if mw.ustring.sub(t.full, -1) == '.' then
if mw.ustring.sub(t.full, -4) ~= 'etc.' then
table.insert(out,
'<div class="warningbox navigation-not-searchable">\n<b>' ..
_(lang,'title-warning-dot') ..
'</b></div>'
)
table.insert(out, emitCategory(lang,'cat-titres-terminant-point'))
end
end
-- Catégories par préfixes (éventuellement paramétrées via i18n.title_prefix_categories)
local prefixes = i18n.title_prefix_categories or {}
for n, list in pairs(prefixes) do
local nnum = tonumber(n) or 0
if nnum > 0 then
local sub = mw.ustring.sub(t.full, 1, nnum)
local cats = list[sub]
if cats then
for _, catKey in ipairs(cats) do
table.insert(out, emitCategory(lang, catKey))
end
end
end
end
return table.concat(out, '\n')
end
local function renderEndCatsAndProps(frame, args, lang)
local out = {}
table.insert(out, emitCategory(lang,'cat-arguments'))
table.insert(out, pf(frame, '{{#set: '
.. 'Nom de page d\'argument = {{FULLPAGENAME}}'
.. ' | Carte des arguments = {{#var: Carte-arguments}}'
.. ' | Contenu d\'argument = {{#var: Contenu-argument}}'
.. ' }}'))
table.insert(out, pf(frame, '{{#if: {{{rubriques|}}} | {{#arraymap: {{{rubriques|}}} | , | x | [[Catégorie:x]][[Rubrique::x| ]] | }} | '..emitCategory(lang,'cat-arguments-sans-rubrique')..' }}'))
table.insert(out, pf(frame, '{{#arraymap: {{{mots-clés|}}} | , | x | {{#set: Mot-clé = x}} | }}'))
return table.concat(out, '\n')
end
-- ===== Orchestration =====
function p.render(frame)
local parent = frame:getParent()
local args = parent and parent.args or frame.args
local lang = args.lang or mw.getContentLanguage():getCode()
local t = titleData()
local out = {}
-- SHORTDESC + default form (pré-expansion)
table.insert(out, pf(frame, '{{SHORTDESC: '.._(lang,'shortdesc')..' }}'))
table.insert(out, pf(frame, '{{#default_form: '.._(lang,'default-form-argument')..' }}'))
-- Numéro d'argument (catégorie SMW)
table.insert(out, '[[Numéro d\'argument:: '..t.id..'| ]]')
-- Vérifs et catégories liées au titre
table.insert(out, titleChecks(frame, lang, t))
-- Bandeaux avertissements de titre/argument (pré-expansion)
local avTitre = param(args, 'avertissements-titre')
local avArg = param(args, 'avertissements-argument')
if avTitre ~= '' or avArg ~= '' then
local list = (avTitre ~= '' and avArg ~= '') and (avTitre..','..avArg) or (avTitre ~= '' and avTitre or avArg)
table.insert(out, pf(frame, '{{#arraymap: '..list..' | , | x | {{Bandeau x}} |   }}'))
end
-- Mots-clés
table.insert(out, renderKeywords(frame, args, lang))
-- Résumé
table.insert(out, renderSummary(frame, args, lang))
-- Citations
table.insert(out, renderQuotes(frame, args, lang))
-- Débat détaillé
table.insert(out, renderDetailedDebate(frame, args, lang))
-- Références
table.insert(out, renderReferences(frame, args, lang))
-- Justifications & Objections
table.insert(out, renderJustifications(frame, args, lang))
table.insert(out, renderObjections(frame, args, lang))
-- Carte arguments (résumé des colonnes) — bloc pré-expansé avec variables
table.insert(out, pf(frame, '{{#vardefine: Carte-arguments | <table style="background-color:transparent; width:100%;" class="navigation-not-searchable">'
.. '<tr><th style="text-align:left;">'.._(lang,'justifications-title')..'</th>'
.. '<th style="text-align:left; padding-left:1em;">'.._(lang,'objections-title')..'</th></tr>'
.. "<tr style=\"vertical-align:top;\"><td><div>{{#var: Carte-justifications | <div style=\"font-size:95%\">'' " .. _(lang,'none-entered') .. " ''</div> }}</div></td>"
.. "<td style=\"padding-left:1em;\"><div>{{#var: Carte-objections | <div style=\"font-size:95%\">'' " .. _(lang,'none-entered-fem') .. " ''</div> }}</div></td>"
.. '</tr></table> }}'))
-- Débats parents (liste + cartes)
table.insert(out, renderParents(frame, args, lang))
-- Interlang / interwiki
table.insert(out, renderInterlang(frame, args))
-- Catégorie "sans contenu" si tout vide
table.insert(out, pf(frame, '{{#if: {{{résumé|}}}{{{citations|}}}{{{références-bibliographiques|}}}{{{références-sitographiques|}}}{{{références-vidéographiques|}}} | | '..emitCategory(lang,'cat-arguments-sans-contenu')..' }}'))
-- Catégories & propriétés finales
table.insert(out, renderEndCatsAndProps(frame, args, lang))
-- SEO
table.insert(out, renderSEO(frame, args, lang, t))
-- Boutons masqués (pré-expansion)
table.insert(out, pf(frame, '<span id="bouton-renommer" class="modifier-rubrique navigation-not-searchable" style="display:none;">[[Spécial:Renommage/{{FULLPAGENAME}}| '.._(lang,'rename')..']]</span>'))
table.insert(out, pf(frame, '<span id="bouton-modifier-categories" class="modifier-rubrique navigation-not-searchable noprint" style="display:none;">{{#formlink:'
.. ' | link text = '.._(lang,'edit')
.. ' | form = '.._(lang,'form-argument-rubriques')
.. ' | target = {{FULLPAGENAMEE}}'
.. ' | tooltip = '.._(lang,'edit-rubriques-tooltip')
.. ' }}</span>'))
table.insert(out, pf(frame, '<span id="bouton-modifier-interlangue" class="modifier-rubrique navigation-not-searchable noprint" style="display:none;">{{#formlink:'
.. ' | link text = '.._(lang,'edit')
.. ' | form = '.._(lang,'form-argument-interlang')
.. ' | target = {{FULLPAGENAMEE}}'
.. ' | tooltip = '.._(lang,'edit-interlang-tooltip')
.. ' }}</span>'))
-- NOCACHE (comme l'original)
table.insert(out, '__NOCACHE__')
return table.concat(out, '\n')
end
return p