Module:ArgumentMap
La documentation pour ce module peut être créée à Module:ArgumentMap/doc
-- Module:ArgumentMap (MediaWiki 1.43)
-- I18N : via Module:WD/I18N (DATA + @aliases + caches internes)
-- Perf :
-- - mw.smw.ask (2 props en 1 requête)
-- - Comparaison par page ID (renommage OK)
-- - ask léger (mainlabel=-, headers=hide, link=none)
-- - Cache split limité (listes courtes seulement)
local p = {}
----------------------------------------------------------------------
-- I18N (minimal) : délègue tout à Module:WD/I18N
----------------------------------------------------------------------
local WD_I18N = require( 'Module:WD/I18N' )
local msg = WD_I18N.msg
----------------------------------------------------------------------
-- Locaux (micro-opt)
----------------------------------------------------------------------
local mw = mw
local smw = mw.smw
local makeTitle = mw.title.makeTitle
local title_new = mw.title.new
local text_trim = mw.text.trim
local uri_decode = mw.uri.decode
local str_find = string.find
local str_sub = string.sub
local t_concat = table.concat
local type = type
----------------------------------------------------------------------
-- Constantes (perf)
----------------------------------------------------------------------
local SPLIT_CACHE_MAX = 800
----------------------------------------------------------------------
-- Cache local (par parse)
----------------------------------------------------------------------
local _idCache = {} -- [titre] = id | false
local _listSplit = {} -- [delim.."\n"..listStr] = { ...paires... } (si #s <= SPLIT_CACHE_MAX)
----------------------------------------------------------------------
-- Helpers
----------------------------------------------------------------------
local function trim( s )
return text_trim( s or "" )
end
local function urldecodeMaybe( s )
s = trim( s )
if s == "" then
return ""
end
if not str_find( s, "%%", 1, true ) and not str_find( s, "+", 1, true ) then
return s
end
return uri_decode( s )
end
local function titleFromText( titleText )
if str_find( titleText, ":", 1, true ) then
return title_new( titleText )
end
return makeTitle( 0, titleText )
end
local function idCached( titleText )
titleText = trim( titleText )
if titleText == "" then
return nil
end
local cached = _idCache[ titleText ]
if cached ~= nil then
return ( cached ~= false ) and cached or nil
end
local t = titleFromText( titleText )
if not t or not t.exists then
_idCache[ titleText ] = false
return nil
end
local id = t.id or nil
_idCache[ titleText ] = id or false
return id
end
local function splitListCached( s, delim )
if s == "" then
return {}
end
local useCache = ( #s <= SPLIT_CACHE_MAX )
local key
if useCache then
key = delim .. "\n" .. s
local cached = _listSplit[ key ]
if cached then
return cached
end
end
local out = {}
local start = 1
local n = 0
while true do
local i, j = str_find( s, delim, start, true )
if not i then
n = n + 1
out[ n ] = str_sub( s, start )
break
end
n = n + 1
out[ n ] = str_sub( s, start, i - 1 )
start = j + 1
end
if useCache then
_listSplit[ key ] = out
end
return out
end
local function splitPairOnce( s, delim )
local i, j = str_find( s, delim, 1, true )
if not i then
return trim( s ), ""
end
return trim( str_sub( s, 1, i - 1 ) ), trim( str_sub( s, j + 1 ) )
end
local function renderTable( leftTitle, rightTitle, leftHtml, rightHtml )
return t_concat{
'<table style="background-color:transparent; width: 100%;" class="navigation-not-searchable">',
'<tr>',
'<th style="text-align:left;">', leftTitle, '</th>',
'<th style="text-align:left; padding-left: 1em;">', rightTitle, '</th>',
'</tr>',
'<tr style="vertical-align:top;">',
'<td><div class="is-pro">', leftHtml, '</div></td>',
'<td style="padding-left: 1em;"><div class="is-con">', rightHtml, '</div></td>',
'</tr>',
'</table>'
}
end
local function smwGetProps( subjectTitle, propNames )
if not smw or not smw.ask then
return {}
end
local ask = { '[[' .. subjectTitle .. ']]' }
for i = 1, #propNames do
if propNames[ i ] and propNames[ i ] ~= "" then
ask[ #ask + 1 ] = '?' .. propNames[ i ]
end
end
ask[ #ask + 1 ] = 'mainlabel=-'
ask[ #ask + 1 ] = 'headers=hide'
ask[ #ask + 1 ] = 'link=none'
ask[ #ask + 1 ] = 'limit=1'
local res = smw.ask( ask )
if type( res ) ~= "table" or type( res[ 1 ] ) ~= "table" then
return {}
end
local row = res[ 1 ]
local out = {}
for i = 1, #propNames do
local k = propNames[ i ]
if k and k ~= "" then
local v = row[ k ]
if type( v ) == "table" then
out[ k ] = t_concat( v, "," )
elseif type( v ) == "string" then
out[ k ] = v
else
out[ k ] = ""
end
end
end
return out
end
local function smwGetProp( subjectTitle, propName )
if not smw or not smw.ask or not propName or propName == "" then
return ""
end
local ask = {
'[[' .. subjectTitle .. ']]',
'?' .. propName,
'mainlabel=-',
'headers=hide',
'link=none',
'limit=1',
}
local res = smw.ask( ask )
if type( res ) ~= "table" or type( res[ 1 ] ) ~= "table" then
return ""
end
local v = res[ 1 ][ propName ]
if type( v ) == "table" then
return t_concat( v, "," )
end
if type( v ) == "string" then
return v
end
return ""
end
local function emptyCard( msg )
return '<div class="carte-vide">' .. msg .. '</div>'
end
local function renderCards( listStr, pairDelim, fieldDelim, emptyHtml, sourceId )
listStr = trim( listStr )
if listStr == "" then
return emptyHtml
end
local pairsList = splitListCached( listStr, pairDelim )
if #pairsList == 0 then
return emptyHtml
end
local out = {}
local n = 0
if not sourceId then
-- Optim : ne split que si le délimiteur existe
for i = 1, #pairsList do
local rawPair = pairsList[ i ]
if rawPair and rawPair ~= "" then
local pageTitle, label
local iDelim, jDelim = str_find( rawPair, fieldDelim, 1, true )
if iDelim then
pageTitle = trim( str_sub( rawPair, 1, iDelim - 1 ) )
label = trim( str_sub( rawPair, jDelim + 1 ) )
else
pageTitle = trim( rawPair )
label = ""
end
if pageTitle ~= "" then
local display = ( label ~= "" ) and label or pageTitle
n = n + 1
out[ n ] = '<div class="argument-title--map wk-icon argument-icon">[[' .. pageTitle .. '|' .. display .. ']]</div>'
end
end
end
return ( n > 0 ) and t_concat( out ) or emptyHtml
end
for i = 1, #pairsList do
local rawPair = pairsList[ i ]
if rawPair and rawPair ~= "" then
local pageTitle, label = splitPairOnce( rawPair, fieldDelim )
if pageTitle ~= "" then
local display = ( label ~= "" ) and label or pageTitle
local itemId = idCached( pageTitle )
local link
if itemId and itemId == sourceId then
link = "'''" .. display .. "'''"
else
link = '[[' .. pageTitle .. '|' .. display .. ']]'
end
n = n + 1
out[ n ] = '<div class="argument-title--map wk-icon argument-icon">' .. link .. '</div>'
end
end
end
return ( n > 0 ) and t_concat( out ) or emptyHtml
end
----------------------------------------------------------------------
-- Entrée
----------------------------------------------------------------------
function p.main( frame )
local parent = frame:getParent()
local args = ( parent and parent.args ) or frame.args
-- Langue : utilise le moteur central (args.lang / args.language sinon contentLanguage)
local lang = WD_I18N.getLangFromArgs( args )
local page = urldecodeMaybe( args[ 1 ] )
if page == "" then
return ""
end
local source = urldecodeMaybe( args[ 2 ] )
local showArgs = trim( args[ 3 ] ) ~= ""
-- I18N (ArgumentMap.* via domaines)
local propMap = msg( 'ArgumentMap.props', lang, 'arg_map' )
local headPro = msg( 'ArgumentMap.text', lang, 'arg_map_pro_label' )
local headCon = msg( 'ArgumentMap.text', lang, 'arg_map_con_label' )
local headJust = msg( 'ArgumentMap.text', lang, 'justifs_label' )
local headObj = msg( 'ArgumentMap.text', lang, 'objs_label' )
local nonePro = msg( 'ArgumentMap.text', lang, 'none_pro_args_msg_short' )
local noneCon = msg( 'ArgumentMap.text', lang, 'none_con_args_msg_short' )
local noneJust = msg( 'ArgumentMap.text', lang, 'none_justifications_msg' )
local noneObj = msg( 'ArgumentMap.text', lang, 'none_objections_msg' )
local propProList = msg( 'ArgumentMap.props', lang, 'pro_list' )
local propConList = msg( 'ArgumentMap.props', lang, 'con_list' )
local propJustList = msg( 'ArgumentMap.props', lang, 'justifs_list' )
local propObjList = msg( 'ArgumentMap.props', lang, 'objs_list' )
-- Optim : emptyCard pré-calculé
local emptyPro = emptyCard( nonePro )
local emptyCon = emptyCard( noneCon )
local emptyJust = emptyCard( noneJust )
local emptyObj = emptyCard( noneObj )
-- Sans “Source” : fallback historique (propriété SMW “argument map”)
if source == "" then
return smwGetProp( page, propMap )
end
local sourceId = idCached( source )
if showArgs then
local props = smwGetProps( page, { propProList, propConList } )
local listPro = props[ propProList ] or ""
local listCon = props[ propConList ] or ""
local left = renderCards( listPro, '-;-', '⟬', emptyPro, sourceId )
local right = renderCards( listCon, '-;-', '⟬', emptyCon, sourceId )
return renderTable( headPro, headCon, left, right )
end
local props = smwGetProps( page, { propJustList, propObjList } )
local listJust = props[ propJustList ] or ""
local listObj = props[ propObjList ] or ""
local left = renderCards( listJust, '⟭', '⟬', emptyJust, sourceId )
local right = renderCards( listObj, '⟭', '⟬', emptyObj, sourceId )
return renderTable( headJust, headObj, left, right )
end
return p