Module:Debate
La documentation pour ce module peut être créée à Module:Debate/doc
-- Module:Debate (i18n FR/EN) — Optimisé
-- Objectif : rendu du modèle « Débat » (MediaWiki 1.43) fidèle au rendu existant
local p = {}
----------------------------------------------------------------------
-- Accès global au frame + VariablesLua (accélération sans changer le rendu)
----------------------------------------------------------------------
local mw = mw
local F = mw.getCurrentFrame()
local V = ( mw.ext and mw.ext.VariablesLua ) or nil
local WD_I18N = require( 'Module:WD/I18N' )
local uri_encode = mw.uri.encode
local string_format = string.format
local title_getCurrentTitle = mw.title.getCurrentTitle
local uri_fullUrl = mw.uri.fullUrl
local uri_localUrl = mw.uri.localUrl
-- Locaux (micro-optis)
local tostring = tostring
local type = type
local ipairs = ipairs
local pairs = pairs
local table_concat = table.concat
local function table_insert( t, a, b )
if b == nil then
return table.insert( t, a )
end
if type( a ) ~= "number" then
if type( b ) == "number" then
return table.insert( t, a )
end
return table.insert( t, b )
end
return table.insert( t, a, b )
end
local t_trim = mw.text.trim
local t_gsplit = mw.text.gsplit
local t_nowiki = mw.text.nowiki
local t_jsonEncode = mw.text.jsonEncode
local t_jsonDecode = mw.text.jsonDecode
local html_create = mw.html.create
local gsub = string.gsub
-- Forward decl (utilisé avant définition)
local escapeAttr
local ITEM_SEP = "⟭"
local FIELD_SEP = "⟬"
-- wrappers VariablesLua (no-op si extension absente)
local function vset( name, val )
if V and type( V.vardefine ) == "function" then
pcall( V.vardefine, name, val ~= nil and tostring( val ) or "" )
end
end
local function vget( name )
if V and type( V.var ) == "function" then
local ok, res = pcall( V.var, name )
if ok then return res end
end
return nil
end
local function detectLang( args )
return WD_I18N.getLangFromArgs( args or {} )
end
local function L( lang, section, key, ... )
return WD_I18N.msg( "Debate." .. section, lang, key, ... )
end
local function smwProp( lang, key )
return WD_I18N.msg( "Debate.props", lang, key )
end
local function isProgress( lang, val, key )
if not val or val == "" then return false end
local label = WD_I18N.msg( "Debate.progress", lang, key )
return val == label
end
----------------------------------------------------------------------
-- Anchor intégré (remplace Module:Anchor)
----------------------------------------------------------------------
local function anchorId( s )
s = tostring( s or "" )
-- Normalisation des apostrophes HTML éventuelles
s = gsub( s, "'", "'" )
s = gsub( s, "'", "'" )
s = gsub( s, "'", "'" )
-- Nettoyage minimal
s = gsub( s, "%s+", " " )
s = t_trim( s )
-- Espaces → underscore
s = gsub( s, " ", "_" )
-- Suppression caractères cassants (HTML / wiki)
s = gsub( s, '[%[%]{}|#<>"]', "" )
return s
end
----------------------------------------------------------------------
-- Helpers
----------------------------------------------------------------------
local function getArgs( frame )
local parent = frame:getParent()
local A = {}
local function add( k, v )
if v == nil then return end
v = t_trim( tostring( v ) )
if v ~= "" then
A[ k ] = v
end
end
if parent and parent.args then
for k, v in pairs( parent.args ) do
add( k, v )
end
end
if frame.args then
for k, v in pairs( frame.args ) do
add( k, v )
end
end
return A
end
local function splitCSV( s, sep )
if not s or s == "" then return {} end
sep = sep or ","
local out = {}
for part in t_gsplit( s, sep, true ) do
part = t_trim( part )
if part ~= "" then table_insert( out, part ) end
end
return out
end
local function wkParseWikipediaMarkers( raw )
raw = tostring( raw or "" )
raw = t_trim( raw )
if raw == "" then
return {}
end
-- On attend maintenant une série de "Titre⟭"
if not raw:find( ITEM_SEP, 1, true ) then
return {}
end
local pages = {}
for part in t_gsplit( raw, ITEM_SEP, true ) do
part = t_trim( part )
if part ~= "" then
pages[ #pages + 1 ] = part
end
end
return pages
end
local function expand( frame, title, params )
local ok, res = pcall( function()
return frame:expandTemplate{ title = title, args = params or {} }
end )
return ok and ( res or "" ) or ""
end
local function hasSMW()
return type( mw.smw ) == "table" and type( mw.smw.set ) == "function"
end
local function smwSetSafe( props )
if not mw.smw or type( mw.smw.set ) ~= "function" then
return
end
pcall( function()
mw.smw.set( props )
end )
end
local function smwAskSafe( q )
if not hasSMW() then return nil end
local ok, res = pcall( function() return mw.smw.ask( q ) end )
return ok and res or nil
end
----------------------------------------------------------------------
-- SEO : cache “par rendu”
----------------------------------------------------------------------
local SEO_CACHE = {}
local function seoCacheKey( args, pv, lang )
return table_concat( {
tostring( lang or "" ),
pv.pageId or "",
tostring( pv.rawTitle or "" ),
tostring( args[ "complete-topic" ] or "" ),
tostring( args[ "keywords" ] or "" ),
tostring( args[ "sections" ] or "" ),
}, "\n" )
end
----------------------------------------------------------------------
-- Wikiseo helpers
----------------------------------------------------------------------
local function wkSeoHas()
return mw.ext
and mw.ext.seo
and type( mw.ext.seo.set ) == "function"
end
local function wkSeoSet( data )
if not wkSeoHas() then
return
end
pcall( mw.ext.seo.set, data )
end
local function seoL( lang, key, ... )
return WD_I18N.msg( "Debate.seo", lang, key, ... ) or ""
end
local function seoJoinList( items )
local out = {}
local seen = {}
for _, v in ipairs( items or {} ) do
v = t_trim( tostring( v or "" ) )
if v ~= "" and not seen[ v ] then
seen[ v ] = true
out[ #out + 1 ] = v
end
end
return table_concat( out, ", " )
end
local function buildSeoKeywords( args, lang )
local items = {}
for _, k in ipairs( splitCSV( args[ "keywords" ], "," ) ) do
items[ #items + 1 ] = k
end
for _, s in ipairs( splitCSV( args[ "sections" ], "," ) ) do
items[ #items + 1 ] = s
end
return seoJoinList( items )
end
local function getPageCreation(pv, args)
-- 1) Priorité : paramètre PageForms / modèle
local v = args and args[ "creation-date" ]
v = (type(v) == "string") and t_trim(v) or ""
if v ~= "" then
return v
end
local title = pv and pv.title
local page = title and title.prefixedText or ""
if page == "" then
return nil
end
-- 2) Sinon : SMW ?Date de création
if hasSMW() and type(mw.smw.ask) == "function" then
local res = smwAskSafe({
"[[" .. page .. "]]",
"?Creation date#-F[Y-m-d\\TH:i:s\\Z]=cd",
"limit=1",
"link=none"
})
if type(res) == "table" and res[1] then
local cd = res[1].cd
return cd
end
end
end
----------------------------------------------------------------------
-- SEO principal (avec cache)
----------------------------------------------------------------------
local function renderFullSEO( args, pv, lang )
-- cache par rendu
local ck = seoCacheKey( args, pv, lang )
if SEO_CACHE[ ck ] then
return
end
SEO_CACHE[ ck ] = true
local pageTitle = pv.rawTitle or ""
local topic = t_trim( tostring( args[ "complete-topic" ] or "" ) )
if topic == "" then
topic = pageTitle
end
local kw = buildSeoKeywords( args, lang )
local published = getPageCreation(pv, args)
wkSeoSet{
title = string_format( seoL( lang, "title" ), pageTitle ),
title_mode = string_format( seoL( lang, "title_mode" ), pageTitle ),
title_separator = string_format( seoL( lang, "title_separator" ), pageTitle ),
description = string_format( seoL( lang, "description" ), topic ),
keywords = kw,
image = seoL( lang, "image" ),
image_alt = seoL( lang, "image_alt" ),
type = "article",
section = seoL( lang, "section" ),
site_name = seoL( lang, "site_name" ),
twitter_site = seoL( lang, "twitter_site" ),
locale = seoL( lang, "locale" ),
author = seoL( lang, "author" ),
published_time = published,
robots = "index,follow",
googlebot = "index,follow",
}
end
----------------------------------------------------------------------
-- Helpers PERF : preprocess conditionnel + cache Bandeau
----------------------------------------------------------------------
local function getBanner( x, bannerCache )
x = t_trim( tostring( x or "" ) )
if x == "" then
return ""
end
local v = bannerCache[ x ]
if v ~= nil then
return v
end
-- Le rendu historique faisait {{Bandeau x}} (et non un appel Lua)
v = expand( F, "Bandeau " .. x, {} ) or ""
bannerCache[ x ] = v
return v
end
----------------------------------------------------------------------
-- SMW batch : on accumule et on flush une fois à la fin
----------------------------------------------------------------------
local function smwQueueAdd( pending, key, val, multi )
if not key or key == "" or val == nil then
return
end
if type( val ) == "string" then
val = t_trim( val )
if val == "" then
return
end
end
local cur = pending[ key ]
if multi then
-- Multi-valeurs : toujours en table côté pending
if cur == nil then
pending[ key ] = ( type( val ) == "table" ) and val or { val }
return
end
if type( cur ) ~= "table" then
cur = { cur }
pending[ key ] = cur
end
if type( val ) == "table" then
for _, x in ipairs( val ) do
if x ~= nil then
cur[ #cur + 1 ] = x
end
end
else
cur[ #cur + 1 ] = val
end
return
end
-- Scalar : dernière valeur gagne (comportement le plus sûr)
pending[ key ] = val
end
local function smwQueueAddFromSepString( pending, key, raw, sep )
raw = ( type( raw ) == "string" ) and t_trim( raw ) or ""
if raw == "" then
return
end
sep = sep or ITEM_SEP
local vals = {}
if raw:find( sep, 1, true ) then
for part in t_gsplit( raw, sep, true ) do
part = t_trim( part )
if part ~= "" then
vals[ #vals + 1 ] = part
end
end
else
vals[ 1 ] = raw
end
if #vals > 0 then
smwQueueAdd( pending, key, vals, true )
end
end
local function smwQueueAddFromCSV( pending, key, raw )
smwQueueAddFromSepString( pending, key, raw, "," )
end
local function smwQueueMerge( dst, src )
for k, v in pairs( src or {} ) do
if type( v ) == "table" then
smwQueueAdd( dst, k, v, true )
else
smwQueueAdd( dst, k, v, false )
end
end
end
----------------------------------------------------------------------
-- PageForms : utilitaires HTML / attributs
----------------------------------------------------------------------
escapeAttr = function( s )
s = tostring( s or "" )
return s
:gsub( "[\r\n\t]", " " )
:gsub( "&", "&" )
:gsub( "<", "<" )
:gsub( ">", ">" )
:gsub( '"', """ )
-- pas besoin d'échapper ' si on entoure l'attribut avec des guillemets doubles
end
-- {{#tag}} utilitaire
local function tag( name, content, attrs )
local parts = {}
if attrs then
for k, v in pairs( attrs ) do
table_insert( parts, string_format( "%s=%s", k, v ) )
end
end
local src
if #parts > 0 then
src = string_format( "{{#tag:%s|%s|%s}}", name, content or "", table_concat( parts, "|" ) )
else
src = string_format( "{{#tag:%s|%s}}", name, content or "" )
end
return F:preprocess( src )
end
local function pf_escape( v )
if not v then return "" end
v = tostring( v )
v = v:gsub( "|", "|" ):gsub( "=", "=" )
return v
end
----------------------------------------------------------------------
-- PageForms : remplacement des #formlink (link) par Special:AddData
----------------------------------------------------------------------
local function wkDbKey( page )
local t = mw.title.new( page )
if not t then
return tostring( page or "" ):gsub( "%s", "_" )
end
return t.prefixedText:gsub( " ", "_" )
end
local function wkEncodeAddDataSegment( s )
s = tostring( s or "" )
s = s:gsub( "%%", "%%25" )
s = s:gsub( "%?", "%%3F" )
s = s:gsub( "#", "%%23" )
s = s:gsub( "/", "%%2F" )
return s
end
local function wkWikipediaUrl( page, lang )
if not page or page == "" then
return ""
end
local base = L( lang, "urls", "wikipedia" )
if not base or base == "" then
return ""
end
return base .. uri_encode( page, "WIKI" )
end
local function wkAddDataPath( formName, pageTitle )
local form = wkEncodeAddDataSegment( wkDbKey( formName ) )
local page = wkEncodeAddDataSegment( wkDbKey( pageTitle ) )
return "Special:AddData/" .. form .. "/" .. page
end
local function addDataLink( formName, pageTitle, linktext, tooltip )
formName = tostring( formName or "" )
pageTitle = tostring( pageTitle or "" )
if formName == "" or pageTitle == "" then
return ""
end
local target = wkAddDataPath( formName, pageTitle )
local lt = " "
local tt = tostring( tooltip or "" )
if tt ~= "" then
return string_format(
'<span class="wk-adddata-link" data-wk-tooltip="%s">[[%s|%s]]</span>',
escapeAttr( tt ),
target,
lt
)
end
return string_format( '[[%s|%s]]', target, lt )
end
local function wkRunQueryPath( formName )
local form = wkEncodeAddDataSegment( wkDbKey( formName ) )
return "Special:RunQuery/" .. form
end
local function normalizeTooltipText( s )
s = tostring( s or "" )
-- Apostrophes
s = s:gsub( "'", "’" )
-- Guillemets droits → typographiques
s = s:gsub( '"', '“' )
return s
end
local function wkRunQueryHtmlTagButton( formName, label, tooltip, query )
formName = tostring( formName or "" )
label = tostring( label or "" )
query = ( type( query ) == "table" ) and query or {}
tooltip = tostring( tooltip or "" )
tooltip = normalizeTooltipText( tooltip )
if formName == "" then
return ""
end
local title = wkRunQueryPath( formName )
local href = tostring( uri_localUrl( title, query ) )
local content = "+ " .. label
return F:preprocess(
'<htmltag tagname="a"'
.. ' href="#"'
.. ' data-href="' .. escapeAttr( href ) .. '"'
.. ' class="wk-btn__a wk-js-nav"'
.. ( tooltip ~= "" and ( ' title="' .. escapeAttr( tooltip ) .. '"' ) or "" )
.. '>'
.. content
.. '</htmltag>'
)
end
local function wkAddDataGetButton( formName, pageTitle, label, tooltip, query )
formName = tostring( formName or "" )
pageTitle = tostring( pageTitle or "" )
label = tostring( label or "" )
tooltip = tostring( tooltip or "" )
query = ( type( query ) == "table" ) and query or {}
if formName == "" or pageTitle == "" then
return ""
end
local title = wkAddDataPath( formName, pageTitle )
local url = tostring( uri_fullUrl( title, query ) ) -- URL absolue obligatoire
local linkInner =
'<span class="wk-btn__icon" aria-hidden="true">➜</span>'
.. '<span class="wk-btn__label">' .. label .. '</span>'
local link = '[' .. url .. ' ' .. linkInner .. ']'
return
'<div class="wk-btn wk-auto-id mw-ui-button navigation-not-searchable"'
.. ( tooltip ~= "" and ( ' title="' .. escapeAttr( tooltip ) .. '"' ) or "" )
.. '>'
.. link
.. '</div>'
end
local function runQueryLink( formName, fieldLabel, fieldName, value, linktext, tooltip, extraParams )
formName = tostring( formName or "" )
fieldLabel = tostring( fieldLabel or "" )
fieldName = tostring( fieldName or "" )
value = tostring( value or "" )
if formName == "" or fieldLabel == "" or fieldName == "" or value == "" then
return ""
end
local title = wkRunQueryPath( formName )
local q = {}
q[ fieldLabel .. "[" .. fieldName .. "]" ] = value
if type( extraParams ) == "table" then
for k, v in pairs( extraParams ) do
if k and k ~= "" and v ~= nil and tostring( v ) ~= "" then
q[ k ] = tostring( v )
end
end
end
q[ "_run" ] = ""
local url = tostring( uri_fullUrl( title, q ) )
local label = linktext or value
local tt = tostring( tooltip or "" )
local link = "[" .. url .. " " .. label .. "]"
if tt ~= "" then
return string_format(
'<span class="wk-adddata-link masquer-externe" data-wk-tooltip="%s">%s</span>',
escapeAttr( tt ),
link
)
end
return string_format( '<span class="wk-adddata-link">%s</span>', link )
end
local function joinArticles( items, lang )
local n = #items
if n == 0 then return "" end
if n == 1 then return items[ 1 ] end
local conj = WD_I18N.msg( "Common.text", lang, "list_conjunction_text" )
if n == 2 then
return items[ 1 ] .. conj .. items[ 2 ]
end
local last = items[ n ]
local first = {}
for i = 1, n - 1 do first[ i ] = items[ i ] end
return table_concat( first, ", " ) .. conj .. last
end
local function listBreaker()
return "\n\n<!--__WD_LIST_BREAK__-->"
end
local function push( t, s )
t[ #t + 1 ] = s
end
----------------------------------------------------------------------
-- Arguments : extraction depuis chaînes
----------------------------------------------------------------------
local function wkSplit2( s, sep )
s = tostring( s or "" )
sep = tostring( sep or "" )
if sep == "" then
return s, ""
end
local i = s:find( sep, 1, true )
if not i then
return s, ""
end
return s:sub( 1, i - 1 ), s:sub( i + #sep )
end
local function wkExtractArgumentItemsFromData( raw )
raw = tostring( raw or "" )
raw = t_trim( raw )
if raw == "" then
return {}
end
if not raw:find( ITEM_SEP, 1, true ) and not raw:find( FIELD_SEP, 1, true ) then
return {}
end
local items = {}
for block in t_gsplit( raw, ITEM_SEP, true ) do
block = t_trim( block )
if block ~= "" then
local page, rest = wkSplit2( block, FIELD_SEP )
local title, warnings = wkSplit2( rest, FIELD_SEP )
page = t_trim( page )
if page ~= "" then
title = t_trim( title )
warnings = t_trim( warnings )
if title == "" then
title = page
end
items[ #items + 1 ] = {
page = page,
title = title,
warnings = warnings
}
end
end
end
return items
end
local function wkComputeArgumentItems( raw )
local items = wkExtractArgumentItemsFromData( raw )
if #items > 0 then
return items, "data"
end
return {}, "none"
end
local function wkBuildArgumentData( items, lang, kind )
items = items or {}
local idPrefix = ( kind == "pro" ) and "Pro_argument_" or "Con_argument_"
local listLines = {}
for _, it in ipairs( items ) do
table_insert( listLines, "* " .. it.title )
end
local listText = table_concat( listLines, "\n" )
local argsVarParts = {}
for _, it in ipairs( items ) do
if it.page == it.title then
table_insert( argsVarParts, it.page )
else
table_insert( argsVarParts, it.page .. "⟬" .. it.title )
end
end
local argsVar = table_concat( argsVarParts, " -;- " )
local mapLines = {}
for i, it in ipairs( items ) do
table_insert( mapLines,
'<div id="' .. idPrefix .. i .. '_map" class="argument-title--map wk-icon argument-icon">' .. it.title .. '</div>'
)
end
local mapHtml = table_concat( mapLines, "\n" )
local hoverLines = {}
for _, it in ipairs( items ) do
table_insert( hoverLines,
'<div class="argument-title--map wk-icon argument-icon">' .. '[[' .. it.page .. '|' .. it.title .. ']]</div>'
)
end
local mapHoverHtml = table_concat( hoverLines, "\n" )
return {
items = items,
list = listText,
argsVar = argsVar,
map = mapHtml,
mapHover = mapHoverHtml
}
end
local function computeArgumentMapsFromArgs( args, lang )
local rawPro = args[ "pro-arguments" ] or ""
local rawCon = args[ "con-arguments" ] or ""
if rawPro ~= "" then
rawPro = F:preprocess( rawPro )
end
if rawCon ~= "" then
rawCon = F:preprocess( rawCon )
end
local pro, proMode = wkComputeArgumentItems( rawPro )
local con, conMode = wkComputeArgumentItems( rawCon )
return {
pro = wkBuildArgumentData( pro, lang, "pro" ),
con = wkBuildArgumentData( con, lang, "con" ),
_mode = { pro = proMode, con = conMode }
}
end
local function wkRenderArgumentLi( pv, lang, it, kind, idx )
local isPro = ( kind == "pro" )
local idPrefix = isPro and "Pro_argument_" or "Con_argument_"
local page = tostring( it.page or "" )
local titleShown = tostring( it.title or "" )
if titleShown == "" then
titleShown = page
end
local aId = anchorId(titleShown)
local warnings = tostring( it.warnings or "" )
return
'<li id="'
.. idPrefix .. tostring( idx )
.. '" class="argument level-1">'
.. '<div id="'
.. escapeAttr( aId )
.. '" class="argument-title wk-icon argument-icon wk-carret"'
.. ( warnings ~= "" and ( ' data-warnings="' .. escapeAttr( warnings ) .. '"' ) or "" ) .. '>'
.. '[[' .. page .. '|' .. titleShown .. ']]'
.. '</div>'
.. '</li>'
end
----------------------------------------------------------------------
-- Bloc d’en-tête / variables de page
----------------------------------------------------------------------
local function computePageVars()
local title = title_getCurrentTitle()
local rawTitle = title.prefixedText
local encoded = uri_encode( rawTitle, "WIKI" )
local pageUrl = tostring( uri_fullUrl( title.prefixedText ) )
local pageId = tostring( title.id or "" )
return {
title = title,
rawTitle = rawTitle,
encoded = encoded,
pageUrl = pageUrl,
pageId = pageId
}
end
----------------------------------------------------------------------
-- Bandeau principal + JSON-LD breadcrumb (i18n)
----------------------------------------------------------------------
local function renderMetaWarningHtml( params )
local color = tostring( params.color or "" )
local icon = tostring( params.icon or "" )
local size = tostring( params.size or "40px" )
local alt = tostring( params.alt or "" )
local title = tostring( params.title or "" )
local text = tostring( params.text or "" )
return
'<div class="bandeau bandeau-' .. color .. ' navigation-not-searchable">'
.. '<table style="background-color:transparent">'
.. '<tr>'
.. '<td class="bandeau-icone">'
.. '<div style="width:60px; text-align:center">[[File: ' .. icon .. '|' .. size .. '|alt=' .. escapeAttr( alt ) .. '|link=]]</div>'
.. '</td>'
.. '<td style="width: 100%;">'
.. '<div class="bandeau-titre"><strong>' .. title .. '</strong></div><!--'
.. '--><div class="bandeau-texte">' .. text .. '</div>'
.. '</td>'
.. '</tr>'
.. '</table><!--'
.. '--></div>'
end
local function renderMainBanner( frame, pv, lang )
local titre = string_format( L( lang, "text", "main_banner_title" ), t_nowiki( pv.rawTitle ) )
return renderMetaWarningHtml{
color = L( lang, "text", "main_banner_color" ),
icon = L( lang, "files", "icon_wikidebats" ),
size = "48px",
alt = L( lang, "text", "main_banner_alt" ),
title = titre,
text =
'<div class="bandeau-section" style="margin: 0.5em 0 0.35em 0;">'
.. '<table style="background-color:transparent"><tr>'
.. '<td><div style="text-align:center; margin-right: 0.5em;">[[File: ' .. L( lang, "files", "search" ) .. ' | 13px | link= | class=mw-no-invert]]</div></td>'
.. '<td>' .. L( lang, "text", "learn_more_label" ) .. L( lang, "text", "founding_principles_link" ) .. '</td>'
.. '</tr></table></div>'
}
end
----------------------------------------------------------------------
-- JSON-LD breadcrumb + FAQPage (i18n complet, listes en puces texte "•")
----------------------------------------------------------------------
local function wkBulletsFromArgListText( listText )
listText = t_trim( tostring( listText or "" ) )
if listText == "" then
return ""
end
local lines = {}
for line in t_gsplit( listText, "\n", true ) do
line = t_trim( tostring( line or "" ) )
if line ~= "" then
line = line:gsub( "^%*%s*", "" )
line = t_trim( line )
if line ~= "" then
table_insert( lines, "• " .. line )
end
end
end
if #lines == 0 then
return ""
end
return table_concat( lines, "\n" )
end
local function renderBreadcrumbJSONLD( pv, lang, args, maps )
local rootName = L( lang, "text", "breadcrumb_debates_label" )
local rootUrl = L( lang, "urls", "breadcrumb_debates" )
local breadcrumb = {
[ "@type" ] = "BreadcrumbList",
itemListElement = {
{
[ "@type" ] = "ListItem",
position = 1,
item = { [ "@id" ] = rootUrl, name = rootName }
},
{
[ "@type" ] = "ListItem",
position = 2,
item = { [ "@id" ] = pv.pageUrl, name = pv.rawTitle }
}
}
}
local graph = { breadcrumb }
local includeFaq = not isProgress( lang, ( args or {} )[ "progress" ], "stub" )
if includeFaq then
local topic = t_trim( tostring( ( args or {} )[ "complete-topic" ] or "" ) )
if topic == "" then
topic = pv.rawTitle
end
local proListText = ( maps and maps.pro and maps.pro.list ) and tostring( maps.pro.list ) or ""
local conListText = ( maps and maps.con and maps.con.list ) and tostring( maps.con.list ) or ""
local proList = wkBulletsFromArgListText( proListText )
local conList = wkBulletsFromArgListText( conListText )
local titlePro = L( lang, "text", "args_pro_title" )
local titleCon = L( lang, "text", "args_con_title" )
local noPro = L( lang, "text", "none_pro_args_msg_short" )
local noCon = L( lang, "text", "none_con_args_msg_short" )
local learnMore = L( lang, "text", "learn_more_label" ) .. L( lang, "text", "site_title_text" )
local anchorPro = L( lang, "text", "faq_anchor_pro" )
local anchorCon = L( lang, "text", "faq_anchor_con" )
local function mainAnswerText()
local parts = {}
table_insert( parts, titlePro )
table_insert( parts, ( proList ~= "" and proList or noPro ) )
table_insert( parts, titleCon )
table_insert( parts, ( conList ~= "" and conList or noCon ) )
table_insert( parts, learnMore )
return table_concat( parts, "\n" )
end
local mainEntity = {}
table_insert( mainEntity, {
[ "@type" ] = "Question",
name = pv.rawTitle,
acceptedAnswer = {
[ "@type" ] = "Answer",
text = mainAnswerText(),
url = pv.pageUrl
}
} )
if proList ~= "" then
local qFor = string_format( L( lang, "text", "faq_q_pro" ), " " .. topic )
table_insert( mainEntity, {
[ "@type" ] = "Question",
name = qFor,
acceptedAnswer = {
[ "@type" ] = "Answer",
text = proList .. "\n" .. learnMore,
url = pv.pageUrl .. anchorPro
}
} )
end
if conList ~= "" then
local qCon = string_format( L( lang, "text", "faq_q_con" ), " " .. topic )
table_insert( mainEntity, {
[ "@type" ] = "Question",
name = qCon,
acceptedAnswer = {
[ "@type" ] = "Answer",
text = conList .. "\n" .. learnMore,
url = pv.pageUrl .. anchorCon
}
} )
end
table_insert( graph, {
[ "@type" ] = "FAQPage",
mainEntity = mainEntity
} )
end
local data = {
[ "@context" ] = "https://schema.org",
[ "@graph" ] = graph
}
local json = t_jsonEncode( data )
return tag(
"htmltag",
json,
{
tagname = "script",
type = "application/ld+json",
[ "class" ] = "navigation-not-searchable"
}
)
end
----------------------------------------------------------------------
-- Bandeaux : rendu natif + résolution via label i18n (C optimisée)
----------------------------------------------------------------------
local PROGRESS_BANNER_KEYS = {
"progress_under_construction",
"progress_draft",
}
local TITLE_WARNING_BANNER_KEYS = {
"title_non_standard",
"title_to_explain",
"title_to_simplify",
}
local DEBATE_WARNING_BANNER_KEYS = {
"debate_unbalanced",
"debate_redundant",
"debate_fanciful",
"debate_sensitive",
"outline_to_improve",
"debate_generated_by_chatgpt",
}
local function bannerMsg( lang, key, ... )
return WD_I18N.msg( "Debate.banners", lang, key, ... ) or ""
end
local function renderBannerByKey( pv, lang, key, cats )
key = tostring( key or "" )
if key == "" then
return ""
end
local color = bannerMsg( lang, key .. "_color" )
local icon = bannerMsg( lang, key .. "_icon" )
local size = bannerMsg( lang, key .. "_size" )
local alt = bannerMsg( lang, key .. "_alt" )
local title = bannerMsg( lang, key .. "_title", pv.rawTitle )
local text = bannerMsg( lang, key .. "_text", pv.rawTitle )
if color == "" and icon == "" and title == "" and text == "" then
return ""
end
local html = renderMetaWarningHtml{
color = color,
icon = icon,
size = size ~= "" and size or "40px",
alt = alt,
title = title,
text = text
}
local cat = bannerMsg( lang, key .. "_category" )
if cats and cat and cat ~= "" then
table_insert( cats, "[[Category:" .. cat .. "]]" )
end
return html
end
local function buildBannerLabelLookup( lang, keys )
local lookup = {}
for _, key in ipairs( keys or {} ) do
local lab = t_trim( bannerMsg( lang, key .. "_label" ) )
if lab ~= "" then
lookup[ lab ] = key
end
end
return lookup
end
local function resolveBannerKeyFromLookup( raw, lookup )
raw = t_trim( tostring( raw or "" ) )
if raw == "" then
return ""
end
return ( lookup and lookup[ raw ] ) or ""
end
local function renderWarningBanners( args, pv, cats, lang )
local av = args[ "progress" ]
local out = {}
local titleLookup = buildBannerLabelLookup( lang, TITLE_WARNING_BANNER_KEYS )
local debateLookup = buildBannerLabelLookup( lang, DEBATE_WARNING_BANNER_KEYS )
local progLookup = buildBannerLabelLookup( lang, PROGRESS_BANNER_KEYS )
local function renderBannersFromList( list, lookup )
local html = {}
for _, x in ipairs( splitCSV( list, "," ) ) do
local key = resolveBannerKeyFromLookup( x, lookup )
if key ~= "" then
table_insert( html, renderBannerByKey( pv, lang, key, cats ) )
end
end
return table_concat( html )
end
if args[ "title-warnings" ] then
table_insert( out, renderBannersFromList( args[ "title-warnings" ], titleLookup ) )
end
if av and t_trim( av ) ~= "" then
local key = resolveBannerKeyFromLookup( av, progLookup )
if key ~= "" then
table_insert( out, renderBannerByKey( pv, lang, key, cats ) )
end
end
if isProgress( lang, av, "constructed" ) then
table_insert( cats, "[[Category:" .. L( lang, "categories", "constructed" ) .. "]]" )
elseif not isProgress( lang, av, "stub" ) and not isProgress( lang, av, "building" ) and not isProgress( lang, av, "constructed" ) then
table_insert( cats, "[[Category:" .. L( lang, "categories", "progress_missing" ) .. "]]" )
end
if args[ "debate-warnings" ] then
table_insert( out, renderBannersFromList( args[ "debate-warnings" ], debateLookup ) )
end
return table_concat( out )
end
----------------------------------------------------------------------
-- Carte des arguments (en-tête)
----------------------------------------------------------------------
local function renderArgumentMapTop( lang, maps )
maps = maps or {}
local pro = ( maps.pro and maps.pro.map ) or ""
local con = ( maps.con and maps.con.map ) or ""
local labelPour = L( lang, "text", "arg_map_pro_label" )
local labelContre = L( lang, "text", "arg_map_con_label" )
local msgPour = L( lang, "text", "none_pro_args_msg_short" )
local msgContre = L( lang, "text", "none_con_args_msg_short" )
local tbl = html_create( "table" )
:attr( "id", "Argument_map" )
:css( "color", "var(--color-emphasized,#101418)" )
:css( "width", "100%" )
:attr( "align", "center" )
local tr = html_create( "tr" )
local tdP = html_create( "td" ):addClass( "is-pro" ):css( "width", "50%" ):css( "vertical-align", "top" ):css( "padding", "5px 1.5% 0" )
local tdC = html_create( "td" ):addClass( "is-con" ):css( "width", "50%" ):css( "vertical-align", "top" ):css( "padding", "5px 0 0" )
tdP:wikitext( '<div style="font-size:101%; font-weight:bold; margin-bottom: 0.5em;">' .. labelPour .. '</div>' )
tdP:wikitext( pro ~= "" and pro or '<div class="carte-vide navigation-not-searchable">' .. msgPour .. '</div>' )
tdC:wikitext( '<div style="font-size:101%; font-weight:bold; margin-bottom: 0.5em;">' .. labelContre .. '</div>' )
tdC:wikitext( con ~= "" and con or '<div class="carte-vide navigation-not-searchable">' .. msgContre .. '</div>' )
tr:node( tdP ):node( tdC )
tbl:node( tr )
return tostring( tbl )
end
----------------------------------------------------------------------
-- Sections
----------------------------------------------------------------------
local function renderIntroduction( args, pv, lang )
local h2 =
'<h2 class="section-modifiable">'
.. '<span style="margin-right: 0.5em;">[[File: ' .. L( lang, "files", "intro" ) .. ' | 22px | link= | alt=' .. L( lang, "text", "understand_debate_title" ) .. ']]</span>'
.. L( lang, "text", "understand_debate_title" )
.. '<span class="modifier-section navigation-not-searchable noprint">'
.. addDataLink(
L( lang, "forms", "intro_edit_title" ),
pv.rawTitle,
L( lang, "text", "edit_label" ),
L( lang, "text", "intro_edit_tt" )
)
.. '</span></h2>'
local body
if args[ "introduction" ] and t_trim( args[ "introduction" ] ) ~= "" then
body = args[ "introduction" ]
else
local cat = "[[Category:" .. L( lang, "categories", "intro_missing" ) .. "]]"
body = '<div class="aucun-contenu navigation-not-searchable" style="margin-bottom: 1em;">' .. L( lang, "text", "none_intro_msg" ) .. '</div>' .. cat
end
return ( h2 .. body ):gsub( "%s*$", "" )
end
local function renderWikipediaLinks( args, pv, lang )
local raw = args[ "wikipedia-articles" ]
raw = ( type( raw ) == "string" ) and t_trim( raw ) or ""
local wrap = html_create( "div" ):addClass( "bandeau-section hover-top navigation-not-searchable" )
local tbl = html_create( "table" ):css( "background-color", "transparent" )
local tr = html_create( "tr" )
local tdIcon = html_create( "td" )
:wikitext( '<div style="text-align:center; margin-right: 0.5em;">[[File: ' .. L( lang, "files", "wikipedia" ) .. ' | 18px | link=]]</div>' )
tr:node( tdIcon )
local tdMain = html_create( "td" ):addClass( "width-100" ):css( "line-height", "1.5" )
local hasPages = false
if raw ~= "" then
local expanded = F:preprocess( raw )
local pages = wkParseWikipediaMarkers( expanded )
if #pages > 0 then
hasPages = true
local items = {}
for _, page in ipairs( pages ) do
local url = wkWikipediaUrl( page, lang )
items[ #items + 1 ] = '<span class="hover-wikipedia">[' .. url .. ' ' .. page .. ']</span>'
end
tdMain:wikitext(
string_format(
L( lang, "text", "wikipedia_seealso_msg" ),
joinArticles( items, lang )
)
)
else
tdMain:addClass( "aucun-contenu" )
:cssText( "line-height: 1.5; font-style: italic;" )
:wikitext( L( lang, "text", "none_wikipedia_msg" ) )
end
else
tdMain:addClass( "aucun-contenu" )
:cssText( "line-height: 1.5; font-style: italic;" )
:wikitext( L( lang, "text", "none_wikipedia_msg" ) )
end
local tdBtn = html_create( "td" )
tdBtn:wikitext(
'<span class="modifier-section navigation-not-searchable noprint">'
.. addDataLink(
L( lang, "forms", "wiki_seealso_edit_title" ),
pv.rawTitle,
L( lang, "text", "edit_label" ),
L( lang, "text", "wikipedia_edit_tt" )
)
.. '</span>'
)
tr:node( tdMain ):node( tdBtn )
tbl:node( tr )
wrap:node( tbl )
if raw == "" or not hasPages then
return tostring( wrap ) .. "[[Category:" .. L( lang, "categories", "wikipedia_missing" ) .. "]]"
end
return tostring( wrap )
end
local function renderQuestionsFAQ( sujetComplet, sens, lang )
local topic = ( sujetComplet and sujetComplet ~= "" ) and sujetComplet or ""
local isCon = ( sens == "con" )
local q
if isCon then
q = string_format( L( lang, "text", "faq_q_con" ), topic )
else
q = string_format( L( lang, "text", "faq_q_pro" ), topic )
end
return string_format( L( lang, "text", "faq_wrapper_text" ), q )
end
local function renderArgsList( args, pv, lang, sens, maps, cats )
local isCon = ( sens == "con" )
local hIconCon = '[[File: ' .. L( lang, "files", "arg_con" ) .. ' | 22px | link= | alt=' .. L( lang, "text", "args_con_title" ) .. ' | class=mw-no-invert]]'
local hIconPro = '[[File: ' .. L( lang, "files", "arg_pro" ) .. ' | 22px | link= | alt=' .. L( lang, "text", "args_pro_title" ) .. ']]'
local title = isCon and L( lang, "text", "args_con_title" ) or L( lang, "text", "args_pro_title" )
local btnForm = addDataLink(
isCon and L( lang, "forms", "args_con_edit_title" ) or L( lang, "forms", "args_pro_edit_title" ),
pv.rawTitle,
L( lang, "text", "edit_label" ),
isCon and L( lang, "text", "args_con_edit_tt" ) or L( lang, "text", "args_pro_edit_tt" )
)
local out = {}
push( out, listBreaker() )
push( out,
'<h2 class="section-modifiable"><span style="margin-right: 0.5em;">'
.. ( isCon and hIconCon or hIconPro )
.. '</span>'
.. title
.. '<span class="modifier-section navigation-not-searchable noprint">'
.. btnForm
.. '</span></h2>'
)
push( out, renderQuestionsFAQ( args[ "complete-topic" ], sens, lang ) )
local ul = html_create( "ul" )
:addClass( "argument-list" )
:addClass( isCon and "is-con" or "is-pro" )
local mode = maps and maps._mode and ( isCon and maps._mode.con or maps._mode.pro ) or "none"
local data = maps and ( isCon and maps.con or maps.pro ) or nil
local items = data and data.items or {}
if ( mode == "data" ) and #items > 0 then
local lis = {}
local anyTitleWarnings = false
for i, it in ipairs( items ) do
if it.warnings and t_trim( it.warnings ) ~= "" then
anyTitleWarnings = true
end
table_insert( lis, wkRenderArgumentLi( pv, lang, it, isCon and "con" or "pro", i ) )
end
ul:wikitext( table_concat( lis, "\n" ) )
if anyTitleWarnings then
table_insert( cats, "[[Category:" .. L( lang, "categories", "refs_to_review" ) .. "]]" )
end
else
local cat = isCon and ( "[[Category:" .. L( lang, "categories", "con_missing" ) .. "]]" ) or ( "[[Category:" .. L( lang, "categories", "pro_missing" ) .. "]]" )
local msg = isCon and L( lang, "text", "none_con_args_msg" ) or L( lang, "text", "none_pro_args_msg" )
table_insert( out, '<div class="aucun-argument navigation-not-searchable">' .. msg .. '</div>' .. cat )
end
push( out, tostring( ul ) )
local sideLabel = isCon and L( lang, "text", "side_con_word" ) or L( lang, "text", "side_pro_word" )
local label = string_format( L( lang, "text", "args_add_label" ), sideLabel )
local tooltip = string_format( L( lang, "text", "arg_add_tt" ), sideLabel, pv.rawTitle )
local baseField = L( lang, "text", "arg_new_title_field_base" )
local rqForm = L( lang, "forms", "new_arg_title" )
local rqTypeValue = isCon and L( lang, "forms", "new_arg_con_type_label" ) or L( lang, "forms", "new_arg_pro_type_label" )
local rqQuery = {}
rqQuery[ baseField .. "[type]" ] = rqTypeValue
rqQuery[ baseField .. "[ID]" ] = pv.pageId
rqQuery[ "_run" ] = "1"
push( out,
'<div class="bouton-ajouter wk-btn mw-ui-button navigation-not-searchable noprint">'
.. wkRunQueryHtmlTagButton( rqForm, label, tooltip, rqQuery )
.. '</div>'
)
return table_concat( out )
end
----------------------------------------------------------------------
-- Sections de références
----------------------------------------------------------------------
local REF_SEP = "⟭"
local REF_FIELD_SEP = "⟬"
local function wkParseBiblioMarkers( raw )
raw = tostring( raw or "" )
raw = t_trim( raw )
if raw == "" then
return {}
end
if not raw:find( REF_FIELD_SEP, 1, true ) and not raw:find( REF_SEP, 1, true ) then
return {}
end
local items = {}
for block in t_gsplit( raw, REF_SEP, true ) do
block = t_trim( block )
if block ~= "" then
local f = {}
for part in t_gsplit( block, REF_FIELD_SEP, true ) do
f[ #f + 1 ] = t_trim( tostring( part or "" ) )
end
for i = #f + 1, 12 do
f[ i ] = ""
end
items[ #items + 1 ] = {
authors = f[ 1 ],
article = f[ 2 ],
work = f[ 3 ],
volume = f[ 4 ],
number = f[ 5 ],
location = f[ 6 ],
page = f[ 7 ],
publisher = f[ 8 ],
place = f[ 9 ],
date = f[ 10 ],
link = f[ 11 ],
warnings = f[ 12 ]
}
end
end
return items
end
local function wkRenderOneBiblioLi( item, lang, categories, smwPending, bannerCache )
local out = {}
local authors = t_trim( item.authors or "" )
if authors == "" then
authors = "Auteur non renseigné"
table_insert( categories, "[[Catégorie:Références à revoir]]" )
end
out[ #out + 1 ] = authors
local article = t_trim( item.article or "" )
local work = t_trim( item.work or "" )
local link = t_trim( item.link or "" )
if article ~= "" then
smwQueueAdd( smwPending, smwProp( lang, "article_name" ), article, true )
end
if work ~= "" then
smwQueueAdd( smwPending, smwProp( lang, "work_name" ), work, true )
end
if article ~= "" then
if link ~= "" then
out[ #out + 1 ] = ", « [" .. link .. " " .. article .. "] »"
else
out[ #out + 1 ] = ", « " .. article .. " »"
end
end
if work ~= "" then
if article ~= "" then
out[ #out + 1 ] = ", ''" .. work .. "''"
else
if link ~= "" then
out[ #out + 1 ] = ", ''[" .. link .. " " .. work .. "]''"
else
out[ #out + 1 ] = ", ''" .. work .. "''"
end
end
end
if work ~= "" then
local volume = t_trim( item.volume or "" )
if volume ~= "" then
out[ #out + 1 ] = ", " .. volume
end
local number = t_trim( item.number or "" )
if number ~= "" then
out[ #out + 1 ] = ", n°" .. number
end
end
local location = t_trim( item.location or "" )
if location ~= "" then
out[ #out + 1 ] = ", " .. location
end
local page = t_trim( item.page or "" )
if page ~= "" then
out[ #out + 1 ] = ", p." .. page
end
local publisher = t_trim( item.publisher or "" )
if publisher ~= "" then
smwQueueAdd( smwPending, smwProp( lang, "publishing_house" ), publisher, true )
out[ #out + 1 ] = ", " .. publisher
end
local place = t_trim( item.place or "" )
if place ~= "" then
smwQueueAdd( smwPending, smwProp( lang, "place_of_publication" ), place, true )
out[ #out + 1 ] = ", " .. place
end
local date = t_trim( item.date or "" )
if date ~= "" then
out[ #out + 1 ] = ", " .. date
end
local warnings = t_trim( item.warnings or "" )
if warnings ~= "" then
for x in t_gsplit( warnings, ",", true ) do
x = t_trim( x )
if x ~= "" then
out[ #out + 1 ] = " " .. getBanner( x, bannerCache )
end
end
end
return "<li>" .. table_concat( out ) .. "</li>"
end
local function wkRenderBiblioListFromArg( raw, lang, categories, smwPending, bannerCache )
local items = wkParseBiblioMarkers( raw )
if #items == 0 then
return ""
end
local lis = {}
for _, item in ipairs( items ) do
lis[ #lis + 1 ] = wkRenderOneBiblioLi( item, lang, categories, smwPending, bannerCache )
end
return table_concat( lis, "\n" )
end
local function wkParseWeblioMarkers( raw )
raw = tostring( raw or "" )
raw = t_trim( raw )
if raw == "" then
return {}
end
if not raw:find( "⟭", 1, true ) and not raw:find( "⟬", 1, true ) then
return {}
end
local items = {}
for block in t_gsplit( raw, "⟭", true ) do
block = t_trim( block )
if block ~= "" then
local f = {}
for part in t_gsplit( block, "⟬", true ) do
f[ #f + 1 ] = t_trim( tostring( part or "" ) )
end
for i = #f + 1, 6 do
f[ i ] = ""
end
items[ #items + 1 ] = {
page = f[ 1 ],
site = f[ 2 ],
link = f[ 3 ],
authors = f[ 4 ],
date = f[ 5 ],
warnings = f[ 6 ]
}
end
end
return items
end
local function wkRenderOneWeblioLi( item, lang, categories, smwPending, bannerCache, side )
local out = {}
local page = t_trim( item.page or "" )
local site = t_trim( item.site or "" )
local link = t_trim( item.link or "" )
local authors = t_trim( item.authors or "" )
local date = t_trim( item.date or "" )
if page ~= "" then
smwQueueAdd( smwPending, smwProp( lang, "article_name" ), page, true )
end
if site ~= "" then
smwQueueAdd( smwPending, smwProp( lang, "website_name" ), site, true )
end
do
local label = ""
if page ~= "" then
label = page
elseif site ~= "" then
label = site
end
if label == "" then
return ""
end
if link ~= "" then
out[ #out + 1 ] = "[" .. link .. " " .. label .. "]"
else
out[ #out + 1 ] = label
end
end
if site ~= "" and page ~= "" then
out[ #out + 1 ] = ", ''" .. site .. "''"
end
if authors ~= "" then
out[ #out + 1 ] = ", " .. authors
end
if date ~= "" then
out[ #out + 1 ] = ", " .. date
end
-- Bandeaux d’avertissement
local warnings = t_trim( item.warnings or "" )
if warnings ~= "" then
for x in t_gsplit( warnings, ",", true ) do
x = t_trim( x )
if x ~= "" then
out[ #out + 1 ] = " " .. getBanner( x, bannerCache )
end
end
end
-- SMW auteurs (par côté)
if authors ~= "" then
local propKey = "author"
if side == "pro" then
propKey = "author_pro"
elseif side == "con" then
propKey = "author_con"
end
for a in t_gsplit( authors, ",", true ) do
a = t_trim( a )
if a ~= "" then
smwQueueAdd( smwPending, smwProp( lang, propKey ), a, true )
end
end
end
return "<li>" .. table_concat( out ) .. "</li>"
end
local function wkRenderWeblioListFromArg( raw, lang, categories, smwPending, bannerCache, side )
local items = wkParseWeblioMarkers( raw )
if #items == 0 then
return ""
end
local lis = {}
for _, item in ipairs( items ) do
local li = wkRenderOneWeblioLi( item, lang, categories, smwPending, bannerCache, side )
if li ~= "" then
lis[ #lis + 1 ] = li
end
end
return table_concat( lis, "\n" )
end
local function wkParseVideoMarkers( raw )
raw = tostring( raw or "" )
raw = t_trim( raw )
if raw == "" then
return {}
end
if not raw:find( "⟭", 1, true ) and not raw:find( "⟬", 1, true ) then
return {}
end
local items = {}
for block in t_gsplit( raw, "⟭", true ) do
block = t_trim( block )
if block ~= "" then
local f = {}
for part in t_gsplit( block, "⟬", true ) do
f[ #f + 1 ] = t_trim( tostring( part or "" ) )
end
for i = #f + 1, 4 do
f[ i ] = ""
end
items[ #items + 1 ] = {
title = f[ 1 ],
link = f[ 2 ],
authors = f[ 3 ],
warnings = f[ 4 ]
}
end
end
return items
end
local function wkRenderOneVideoLi( item, lang, categories, smwPending, bannerCache )
local title = t_trim( item.title or "" )
if title == "" then
return ""
end
local link = t_trim( item.link or "" )
local authors = t_trim( item.authors or "" )
local out = {}
if link ~= "" then
out[ #out + 1 ] = "[" .. link .. " " .. title .. "]"
else
out[ #out + 1 ] = title
end
if authors ~= "" then
out[ #out + 1 ] = ", " .. authors
end
local warnings = t_trim( item.warnings or "" )
if warnings ~= "" then
for x in t_gsplit( warnings, ",", true ) do
x = t_trim( x )
if x ~= "" then
out[ #out + 1 ] = " " .. getBanner( x, bannerCache )
end
end
end
return "<li>" .. table_concat( out ) .. "</li>"
end
local function wkRenderVideoListFromArg( raw, lang, categories, smwPending, bannerCache, side )
local items = wkParseVideoMarkers( raw )
if #items == 0 then
return ""
end
local lis = {}
for _, item in ipairs( items ) do
local li = wkRenderOneVideoLi( item, lang, categories, smwPending, bannerCache )
if li ~= "" then
lis[ #lis + 1 ] = li
end
end
return table_concat( lis, "\n" )
end
local function renderRefBlock( pageVars, lang, titleIcon, titleText, formKey, value )
local out = {}
table_insert( out,
'<div class="titre-references navigation-not-searchable">'
.. titleIcon .. titleText
.. '<span class="modifier-rubrique flottant-droite navigation-not-searchable noprint">'
.. addDataLink(
L( lang, "forms", formKey ),
pageVars.rawTitle,
L( lang, "text", "edit_label" ),
L( lang, "text", "section_edit_tt" )
)
.. '</span></div>'
)
if value and t_trim( value ) ~= "" then
table_insert( out, "<ul>" .. value .. "</ul>" )
else
table_insert( out, '<div class="aucune-reference navigation-not-searchable">' .. L( lang, "text", "none_references_msg" ) .. '</div>' )
end
return table_concat( out )
end
local function renderReferences( args, pageVars, lang, categories, smwPending )
local wrap = {}
local bannerCache = {}
table_insert( wrap, '<h2><span style="margin-right: 0.5em;">[[File: ' .. L( lang, "files", "further" ) .. ' | 20px | link= | alt=' .. L( lang, "text", "further_reading_title" ) .. ']]</span>' .. L( lang, "text", "further_reading_title" ) .. '</h2>' )
-- Bibliography
do
local h3 = '<h3 id="Bibliography" class="fr-collapsible-toggle wk-icon wk-carret">'
.. '[[File: ' .. L( lang, "files", "biblio" ) .. ' | 13px | middle | link= | alt=' .. L( lang, "text", "bibliography_title" ) .. ' | class=sub pictogramme-h3]]'
.. L( lang, "text", "bibliography_title" ) .. '</h3>'
local content = {}
local proRaw = args[ "pro-bibliography" ] or ""
if proRaw ~= "" then
proRaw = F:preprocess( proRaw )
proRaw = wkRenderBiblioListFromArg( proRaw, lang, categories, smwPending, bannerCache )
end
local conRaw = args[ "con-bibliography" ] or ""
if conRaw ~= "" then
conRaw = F:preprocess( conRaw )
conRaw = wkRenderBiblioListFromArg( conRaw, lang, categories, smwPending, bannerCache )
end
local neuRaw = args[ "bibliography" ] or ""
if neuRaw ~= "" then
neuRaw = F:preprocess( neuRaw )
neuRaw = wkRenderBiblioListFromArg( neuRaw, lang, categories, smwPending, bannerCache )
end
table_insert( content, renderRefBlock( pageVars, lang,
'[[File: ' .. L( lang, "files", "arg_pro" ) .. ' | 17px | link= | alt=' .. escapeAttr( L( lang, "text", "side_pro_alt" ) ) .. ' | class=pictogramme-h3 mw-no-invert]]',
L( lang, "text", "side_pro_title" ),
"biblio_pro_title",
proRaw
) )
table_insert( content, renderRefBlock( pageVars, lang,
'[[File: ' .. L( lang, "files", "arg_con" ) .. ' | 17px | link= | alt=' .. escapeAttr( L( lang, "text", "side_con_alt" ) ) .. ' | class=pictogramme-h3 mw-no-invert]]',
L( lang, "text", "side_con_title" ),
"biblio_con_title",
conRaw
) )
table_insert( content, renderRefBlock( pageVars, lang,
'[[File: ' .. L( lang, "files", "arg_neutral" ) .. ' | 17px | text-bottom | link= | alt=' .. escapeAttr( L( lang, "text", "side_neutral_alt" ) ) .. ' | class=pictogramme-h3 mw-no-invert]]',
L( lang, "text", "side_neutral_title" ),
"biblio_neutral_title",
neuRaw
) )
table_insert( wrap, '<div class="fr-collapsible fr-collapsed">' .. h3 .. '<div class="fr-collapsible-content contenu-references">' .. table_concat( content ) .. '</div></div>' )
end
-- Webliography
do
local h3 = '<h3 id="Webliography" class="fr-collapsible-toggle wk-icon wk-carret">'
.. '[[File: ' .. L( lang, "files", "webliography" ) .. ' | 15px | link= | alt=' .. L( lang, "text", "webliography_title" ) .. ' | class=pictogramme-h3]]'
.. L( lang, "text", "webliography_title" ) .. '</h3>'
local content = {}
local proRaw = args[ "pro-webliography" ] or ""
if proRaw ~= "" then
proRaw = F:preprocess( proRaw )
proRaw = wkRenderWeblioListFromArg( proRaw, lang, categories, smwPending, bannerCache, "pro" )
end
local conRaw = args[ "con-webliography" ] or ""
if conRaw ~= "" then
conRaw = F:preprocess( conRaw )
conRaw = wkRenderWeblioListFromArg( conRaw, lang, categories, smwPending, bannerCache, "con" )
end
local neuRaw = args[ "webliography" ] or ""
if neuRaw ~= "" then
neuRaw = F:preprocess( neuRaw )
neuRaw = wkRenderWeblioListFromArg( neuRaw, lang, categories, smwPending, bannerCache, "neutral" )
end
table_insert( content, renderRefBlock( pageVars, lang,
'[[File: ' .. L( lang, "files", "arg_pro" ) .. ' | 17px | link= | alt=' .. escapeAttr( L( lang, "text", "side_pro_alt" ) ) .. ' | class=pictogramme-h3 mw-no-invert]]',
L( lang, "text", "side_pro_title" ),
"webliography_pro_title",
proRaw
) )
table_insert( content, renderRefBlock( pageVars, lang,
'[[File: ' .. L( lang, "files", "arg_con" ) .. ' | 17px | link= | alt=' .. escapeAttr( L( lang, "text", "side_con_alt" ) ) .. ' | class=pictogramme-h3 mw-no-invert]]',
L( lang, "text", "side_con_title" ),
"webliography_con_title",
conRaw
) )
table_insert( content, renderRefBlock( pageVars, lang,
'[[File: ' .. L( lang, "files", "arg_neutral" ) .. ' | 17px | text-bottom | link= | alt=' .. escapeAttr( L( lang, "text", "side_neutral_alt" ) ) .. ' | class=pictogramme-h3 mw-no-invert]]',
L( lang, "text", "side_neutral_title" ),
"webliography_neutral_title",
neuRaw
) )
table_insert( wrap, '<div class="fr-collapsible fr-collapsed">' .. h3 .. '<div class="fr-collapsible-content contenu-references">' .. table_concat( content ) .. '</div></div>' )
end
-- Videography
do
local h3 = '<h3 id="Videography" class="fr-collapsible-toggle wk-icon wk-carret">'
.. '[[File: ' .. L( lang, "files", "videography" ) .. ' | 17px | link= | alt=' .. L( lang, "text", "videography_title" ) .. ' | class=pictogramme-h3]]'
.. L( lang, "text", "videography_title" ) .. '</h3>'
local content = {}
local proRaw = args[ "pro-videography" ] or ""
if proRaw ~= "" then
proRaw = F:preprocess( proRaw )
proRaw = wkRenderVideoListFromArg( proRaw, lang, categories, smwPending, bannerCache, "pro" )
end
local conRaw = args[ "con-videography" ] or ""
if conRaw ~= "" then
conRaw = F:preprocess( conRaw )
conRaw = wkRenderVideoListFromArg( conRaw, lang, categories, smwPending, bannerCache, "con" )
end
local neuRaw = args[ "videography" ] or ""
if neuRaw ~= "" then
neuRaw = F:preprocess( neuRaw )
neuRaw = wkRenderVideoListFromArg( neuRaw, lang, categories, smwPending, bannerCache, "neutral" )
end
table_insert( content, renderRefBlock( pageVars, lang,
'[[File: ' .. L( lang, "files", "arg_pro" ) .. ' | 17px | link= | alt=' .. escapeAttr( L( lang, "text", "side_pro_alt" ) ) .. ' | class=pictogramme-h3 mw-no-invert]]',
L( lang, "text", "side_pro_title" ),
"videography_pro_title",
proRaw
) )
table_insert( content, renderRefBlock( pageVars, lang,
'[[File: ' .. L( lang, "files", "arg_con" ) .. ' | 17px | link= | alt=' .. escapeAttr( L( lang, "text", "side_con_alt" ) ) .. ' | class=pictogramme-h3 mw-no-invert]]',
L( lang, "text", "side_con_title" ),
"videography_con_title",
conRaw
) )
table_insert( content, renderRefBlock( pageVars, lang,
'[[File: ' .. L( lang, "files", "arg_neutral" ) .. ' | 17px | text-bottom | link= | alt=' .. escapeAttr( L( lang, "text", "side_neutral_alt" ) ) .. ' | class=pictogramme-h3 mw-no-invert]]',
L( lang, "text", "side_neutral_title" ),
"videography_neutral_title",
neuRaw
) )
table_insert( wrap, '<div class="fr-collapsible fr-collapsed">' .. h3 .. '<div class="fr-collapsible-content contenu-references">' .. table_concat( content ) .. '</div></div>' )
end
return table_concat( wrap )
end
----------------------------------------------------------------------
-- Champs divers (mots-clés, rubriques, connexes, interlangue)
----------------------------------------------------------------------
local function renderKeywords( args, pv, cats, lang )
local out = {}
table_insert( out, '<div style="font-size: 95%; margin-top: 1em;">' .. L( lang, "text", "keywords_label_text" ) )
if args[ "keywords" ] and t_trim( args[ "keywords" ] ) ~= "" then
local rendered = {}
local formName = L( lang, "forms", "search_by_keywords_title" )
local fieldLabel = formName
local fieldName = L( lang, "params", "keywords_field" )
local tt = L( lang, "text", "search_by_keyword_tt" )
local typeField = L( lang, "params", "search_type_field" )
local typeValue = L( lang, "params", "search_type_value" )
local extra = {
[ fieldLabel .. "[" .. typeField .. "]" ] = typeValue
}
for _, k in ipairs( splitCSV( args[ "keywords" ], "," ) ) do
k = t_trim( tostring( k or "" ) )
if k ~= "" then
local chip = runQueryLink( formName, fieldLabel, fieldName, k, k, tt, extra )
if not chip or chip == "" then
chip = k
end
if chip ~= "" then
table_insert( rendered, chip )
end
end
end
if #rendered > 0 then
table_insert( out, table_concat( rendered, ", " ) )
else
table_insert( out, L( lang, "text", "none_label" ) )
table_insert( cats, "[[Category:" .. L( lang, "categories", "keywords_missing" ) .. "]]" )
end
else
table_insert( out, L( lang, "text", "none_label" ) )
table_insert( cats, "[[Category:" .. L( lang, "categories", "keywords_missing" ) .. "]]" )
end
table_insert( out,
'<span class="modifier-rubrique navigation-not-searchable noprint">'
.. addDataLink(
L( lang, "forms", "keywords_edit_title" ),
pv.rawTitle,
L( lang, "text", "edit_label" ),
L( lang, "text", "keywords_edit_tt" )
)
.. '</span><span style="display: none;">.</span></div>'
)
return table_concat( out )
end
local function renderConnexes( args, pv, cats, lang )
local h2 =
'<h2 class="section-modifiable">'
.. '<span style="margin-right: 0.5em;">[[File: ' .. L( lang, "files", "related" ) .. ' | 20px | link= | alt=' .. L( lang, "text", "related_debates_title" ) .. ']]</span>'
.. L( lang, "text", "related_debates_title" )
.. '<span class="modifier-section navigation-not-searchable noprint">'
.. addDataLink(
L( lang, "forms", "related_edit_title" ),
pv.rawTitle,
L( lang, "text", "edit_label" ),
L( lang, "text", "related_edit_tt" )
)
.. '</span></h2>'
if args[ "related-debates" ] and t_trim( args[ "related-debates" ] ) ~= "" then
return h2 .. '<ul class="hover-top searchaux">' .. args[ "related-debates" ] .. '</ul>'
end
table_insert( cats, "[[Category:" .. L( lang, "categories", "related_missing" ) .. "]]" )
return h2 .. '<div class="aucun-contenu navigation-not-searchable">' .. L( lang, "text", "none_related_msg" ) .. '</div>'
end
local function renderRubriques( args, cats, lang )
if args[ "sections" ] and t_trim( args[ "sections" ] ) ~= "" then
local out = {}
for _, r in ipairs( splitCSV( args[ "sections" ], "," ) ) do
table_insert( out, "[[Category:" .. r .. "]]" )
end
return table_concat( out )
end
return "[[Category:" .. L( lang, "categories", "sections_missing" ) .. "]]"
end
----------------------------------------------------------------------
-- SMW (sans legacy)
----------------------------------------------------------------------
local function setSemanticData( args, pv, lang, maps, smwPending )
maps = maps or {}
local pro = maps.pro or {}
local con = maps.con or {}
local pourPages = {}
local contrePages = {}
for _, it in ipairs( pro.items or {} ) do
if it.page and it.page ~= "" then
table_insert( pourPages, it.page )
end
end
for _, it in ipairs( con.items or {} ) do
if it.page and it.page ~= "" then
table_insert( contrePages, it.page )
end
end
local props = {}
local pourSurvol = t_trim( pro.mapHover or "" )
local contreSurvol = t_trim( con.mapHover or "" )
if pourSurvol == "" then
pourSurvol = '<div class="carte-vide">' .. L( lang, "text", "none_pro_args_msg_short" ) .. '</div>'
end
if contreSurvol == "" then
contreSurvol = '<div class="carte-vide">' .. L( lang, "text", "none_con_args_msg_short" ) .. '</div>'
end
local listePour = t_trim( pro.argsVar or "" )
local listeContre = t_trim( con.argsVar or "" )
props[ smwProp( lang, "debate_name" ) ] = pv.rawTitle
props[ smwProp( lang, "debate_number" ) ] = pv.pageId
props[ smwProp( lang, "breadcrumb" ) ] = pv.rawTitle
props[ smwProp( lang, "pro_list" ) ] = listePour
props[ smwProp( lang, "con_list" ) ] = listeContre
props[ smwProp( lang, "arg_map" ) ] =
'<table style="background-color:transparent; width: 100%; margin: 0em 0.5em 0.15em 0;" class="navigation-not-searchable">'
.. '<tr><th style="text-align:left;">' .. L( lang, "text", "arg_map_pro_label" ) .. '</th>'
.. '<th style="text-align:left; padding-left: 1em;">' .. L( lang, "text", "arg_map_con_label" ) .. '</th></tr>'
.. '<tr class="is-pro" style="vertical-align:top;"><td>' .. pourSurvol .. '</td>'
.. '<td class="is-con" style="padding-left: 1em;">' .. contreSurvol .. '</td></tr></table>'
if #pourPages > 0 then
props[ smwProp( lang, "arg_pro" ) ] = pourPages
end
if #contrePages > 0 then
props[ smwProp( lang, "arg_con" ) ] = contrePages
end
if smwPending then
smwQueueMerge( props, smwPending )
end
smwSetSafe( props )
end
----------------------------------------------------------------------
-- Rendu principal
----------------------------------------------------------------------
function p.render( frame )
for k in pairs( SEO_CACHE ) do
SEO_CACHE[ k ] = nil
end
local args = getArgs( frame )
local lang = detectLang( args )
local pv = computePageVars()
local pieces, cats = {}, {}
local smwPending = {}
smwQueueAddFromCSV(
smwPending,
smwProp( lang, "keyword" ),
args[ "keywords" ]
)
local maps = computeArgumentMapsFromArgs( args, lang )
table_insert( cats, "[[Category:" .. L( lang, "categories", "debates" ) .. "]]" )
if args[ "topic" ] and t_trim( args[ "topic" ] ) ~= "" then
smwQueueAdd( smwPending, smwProp( lang, "debate_subject" ), args[ "topic" ], false )
else
table_insert( cats, "[[Category:" .. L( lang, "categories", "topic_missing" ) .. "]]" )
end
if args[ "complete-topic" ] and t_trim( args[ "complete-topic" ] ) ~= "" then
table_insert( pieces, F:preprocess( "{{SHORTDESC: " .. string_format( L( lang, "text", "shortdesc_topic" ), args[ "complete-topic" ] ) .. "}}" ) )
else
table_insert( cats, "[[Category:" .. L( lang, "categories", "topic_complete_missing" ) .. "]]" )
table_insert( pieces, F:preprocess( "{{SHORTDESC: " .. L( lang, "text", "shortdesc_plain" ) .. "}}" ) )
end
table_insert( pieces, renderBreadcrumbJSONLD( pv, lang, args, maps ) )
table_insert( pieces, renderArgumentMapTop( lang, maps ) )
table_insert( pieces, renderKeywords( args, pv, cats, lang ) )
local btnForm = addDataLink(
L( lang, "forms", "banners_edit_title" ),
pv.rawTitle,
L( lang, "text", "edit_label" ),
L( lang, "text", "debate_banners_edit_tt" )
)
table_insert( pieces, '<h2 class="section-modifiable"><span style="margin-right: 0.5em; position: relative;">[[File: ' .. L( lang, "files", "banner" ) .. ' | 14px | link= | alt=' .. L( lang, "text", "warnings_title" ) .. ']]</span>' .. L( lang, "text", "warnings_title" ) .. '<span class="modifier-section navigation-not-searchable noprint">' .. btnForm .. '</span></h2>' )
table_insert( pieces, renderMainBanner( F, pv, lang ) )
table_insert( pieces, renderWarningBanners( args, pv, cats, lang ) )
if not isProgress( lang, args[ "progress" ], "stub" ) then
local target = L( lang, "text", "self_eval_ns_label" ) .. ":" .. pv.rawTitle .. " (ID)"
local ns = L( lang, "text", "self_eval_ns_label" )
local f_debat = L( lang, "text", "self_eval_debate_field" )
local box = {}
table_insert( box, '<h2 class="navigation-not-searchable noprint" style="margin-bottom: 0;"><span style="margin-right: 0.5em; position: relative; bottom: 2px;">[[File: ' .. L( lang, "files", "selftest" ) .. ' | 17px | link= | alt=' .. L( lang, "text", "self_eval_title" ) .. ']]</span>' .. L( lang, "text", "self_eval_title" ) .. '</h2>' )
local startBtn = wkAddDataGetButton(
L( lang, "forms", "self_eval_home_title" ),
target,
L( lang, "text", "self_eval_start_label" ),
L( lang, "text", "self_eval_start_tt" ),
{
[ ns .. "[" .. f_debat .. "]" ] = pv.rawTitle
}
)
table_insert(
box,
'<div class="boite-info navigation-not-searchable noprint">'
.. L( lang, "text", "self_eval_blurb" )
.. startBtn
.. '</div>'
)
table_insert( pieces, table_concat( box ) )
end
table_insert( pieces, renderIntroduction( args, pv, lang ) )
table_insert( pieces, renderWikipediaLinks( args, pv, lang ) )
table_insert( pieces, renderArgsList( args, pv, lang, "pro", maps, cats ) )
table_insert( pieces, renderArgsList( args, pv, lang, "con", maps, cats ) )
table_insert( pieces, renderReferences( args, pv, lang, cats, smwPending ) )
table_insert( pieces, renderConnexes( args, pv, cats, lang ) )
table_insert( pieces,
'<h2 class="latest-changes-button navigation-not-searchable noprint">'
.. '<span style="margin-right: 0.5em;">[[File: '
.. L( lang, "files", "changes" )
.. ' | 16px | link= | alt='
.. L( lang, "text", "latest_changes_title" )
.. ']]</span>'
.. L( lang, "text", "latest_changes_title" )
.. '</h2>'
.. '<div class="latest-changes navigation-not-searchable noprint">'
.. '<div class="latest-changes-button wk-btn mw-ui-button"'
.. ' title="' .. L( lang, "text", "latest_changes_show_tt" ) .. '"'
.. ' data-page="' .. t_nowiki( pv.rawTitle ) .. '">'
.. L( lang, "text", "latest_changes_show_label" )
.. '</div>'
.. '<div class="latest-changes-wrapper"></div>'
.. '</div>'
)
if args[ "interlanguage" ] and t_trim( args[ "interlanguage" ] ) ~= "" then
table_insert( pieces, args[ "interlanguage" ] )
end
table_insert( pieces, renderRubriques( args, cats, lang ) )
setSemanticData( args, pv, lang, maps, smwPending )
renderFullSEO( args, pv, lang )
table_insert( pieces, table_concat( cats ) )
local renameLink = string_format( L( lang, "text", "rename_special_page_text" ), pv.encoded )
table_insert( pieces,
'<span id="bouton-renommer" class="modifier-rubrique navigation-not-searchable noprint" style="display: none;">[['
.. renameLink .. '|' .. L( lang, "text", "rename_link_label" ) .. ']]</span>'
)
table_insert( pieces, '<span id="bouton-modifier-sujet" class="modifier-rubrique navigation-not-searchable noprint" style="display: none;">'
.. addDataLink( L( lang, "forms", "subject_edit_title" ), pv.rawTitle, L( lang, "text", "edit_label" ), L( lang, "text", "subject_edit_tt" ) )
.. '</span>' )
table_insert( pieces, '<span id="bouton-modifier-categories" class="modifier-rubrique navigation-not-searchable noprint" style="display: none;">'
.. addDataLink( L( lang, "forms", "sections_edit_title" ), pv.rawTitle, L( lang, "text", "edit_label" ), L( lang, "text", "sections_edit_tt" ) )
.. '</span>' )
if args["interlanguage"] and t_trim( tostring( args["interlanguage"] or "" ) ) ~= "" then
table_insert( pieces,
'<span id="bouton-modifier-interlangue" class="modifier-rubrique navigation-not-searchable noprint" style="display: none;"'
.. ' data-wk-tooltip="' .. escapeAttr( L( lang, "text", "interlanguage_edit_tt" ) ) .. '">'
.. addDataLink(
L( lang, "forms", "interlanguage_edit_title" ),
pv.rawTitle,
L( lang, "text", "edit_label" ),
L( lang, "text", "interlanguage_edit_tt" )
)
.. '</span>'
)
end
return table_concat( pieces, "" )
end
return p