Editing Module:DPLluaGive feedback
The edit can be undone.
Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
| Latest revision | Your text | ||
| Line 2: | Line 2: | ||
local dpl = {} | local dpl = {} | ||
local libraryUtil = require( 'libraryUtil' ) | local libraryUtil = require( 'libraryUtil' ) | ||
local checkType = libraryUtil.checkType | local checkType = libraryUtil.checkType | ||
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg | local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg | ||
| Line 32: | Line 31: | ||
-- Also custom function for speed | -- Also custom function for speed | ||
local function trim( str ) | local function trim( str ) | ||
return | return string.match( str, '^%s*(.-)%s*$' ) | ||
end | end | ||
local escapeChars = { | local escapeChars = { | ||
['{'] = '{', | ['{'] = '{', | ||
['❴'] = '{', -- Wtf dpl... | |||
['}'] = '}', | ['}'] = '}', | ||
['❵'] = '}', | |||
['['] = '[', | ['['] = '[', | ||
[']'] = ']', | [']'] = ']', | ||
| Line 56: | Line 45: | ||
} | } | ||
local function escape( str ) | local function escape( str ) | ||
-- the \226\157\180\181 are used to match ❴ (U+2774) and ❵ (U+2775) wich are 3 bytes long (UTF-8) so | |||
-- we can't use them directly inside [] patterns. Ustring would fix this but it's way too slow. | |||
str = string.gsub( str, '[{}%[%]|%-]', escapeChars ):gsub( '\226\157[\180\181]', escapeChars ) | |||
return str | |||
end | end | ||
| Line 68: | Line 60: | ||
} | } | ||
local function unEscape( str ) | local function unEscape( str ) | ||
str = string.gsub( str, '&#%d+;', unEscapeChars ) | |||
return str | |||
return | |||
end | end | ||
| Line 105: | Line 92: | ||
'suppresserrors', | 'suppresserrors', | ||
'noresultsfooter', | 'noresultsfooter', | ||
'format | 'format' | ||
} | } | ||
| Line 115: | Line 101: | ||
local function formatInclude( query ) | local function formatInclude( query ) | ||
checkTypeForNamedArg( 'Module:DPLlua.ask | checkTypeForNamedArg( 'include', 'Module:DPLlua.ask', query, 'string' ) | ||
query = split( query, ',', true ) | query = split( query, ',', true ) | ||
local includedParamNames = {} | local includedParamNames = {} | ||
for i = 1, #query do | for i = 1, #query do | ||
if query[i]:match( '%b{}' ) then -- Check if we are including a template | if query[i]:match( '%b{}' ) then -- Check if we are including a template | ||
local templateName, | local templateName, params = query[i]:match( '{(.-)[¦|}]([^,]*)' ) | ||
if | if params:find( '%S' ) then | ||
params:gsub( '^:%-', '' ) | |||
query[i] = string.format( '{%s}%s', templateName, params ) | |||
query[i] = string.format( '{ | |||
for param in params:gmatch( ':([^:]*)' ) do | |||
param = trim( param ) | |||
table.insert( includedParamNames, { name=templateName, isTemplate=true, param=param } ) | |||
end | end | ||
else | else | ||
query[i] = string.format( '{%s¦DPLlua helper}', templateName ) -- Use a helper template to get all the parameters of our included template | query[i] = string.format( '{%s¦DPLlua helper}', templateName ) -- Use a helper template to get all the parameters of our included template | ||
table.insert( includedParamNames, { name=templateName, isTemplate=true, includeAll=true } ) | table.insert( includedParamNames, { name=templateName, isTemplate=true, includeAll=true } ) | ||
end | end | ||
else | else | ||
table.insert( includedParamNames, { name=trim( query[i] ) } ) | table.insert( includedParamNames, { name=trim( query[i] ) } ) | ||
end | end | ||
end | end | ||
return table.concat( query, ',' ), includedParamNames | return table.concat( query, ',' ), includedParamNames | ||
end | end | ||
| Line 160: | Line 135: | ||
local usesInclude = false | local usesInclude = false | ||
local includedParamNames = {} | local includedParamNames = {} | ||
query.count = nil | query.count = nil | ||
query.offset = nil | query.offset = nil | ||
-- | -- We use table format when the include parameter is used to make sure we can | ||
-- is | -- differentiate between the results in case more than one item is included | ||
local dplStringInclude = | local dplStringInclude = | ||
[=[ | [=[ | ||
| Line 174: | Line 148: | ||
|%s | |%s | ||
|table=, | |table=, | ||
|tablerow=%s | |tablerow=%s | ||
}}]=] | }}]=] | ||
| Line 198: | Line 170: | ||
for k, v in pairs( query ) do | for k, v in pairs( query ) do | ||
if k == 'include' then | if k == 'include' then | ||
v, includedParamNames | v, includedParamNames = formatInclude( v ) | ||
usesInclude = true | usesInclude = true | ||
end | end | ||
| Line 212: | Line 184: | ||
if usesInclude then | if usesInclude then | ||
table.insert( queries, string.format( | table.insert( queries, string.format( | ||
dplStringInclude, | dplStringInclude, | ||
| Line 227: | Line 189: | ||
offset, | offset, | ||
table.concat( params, '\n|' ), | table.concat( params, '\n|' ), | ||
string.rep( dataContentMarker..'%%'..dataContentMarker..',', #includedParamNames ) | string.rep( dataContentMarker..'%%'..dataContentMarker..',', #includedParamNames ) | ||
) ) | ) ) | ||
else | else | ||
| Line 244: | Line 205: | ||
table.insert( allIncludedParamNames, includedParamNames ) | table.insert( allIncludedParamNames, includedParamNames ) | ||
return table.concat( queries ) | return table.concat( queries ) | ||
end | end | ||
local function toTable( query | local function toTable( query ) | ||
local includedParamNames = table.remove( allIncludedParamNames, 1 ) | local includedParamNames = table.remove( allIncludedParamNames, 1 ) | ||
local usesInclude = #includedParamNames > 0 | local usesInclude = #includedParamNames > 0 | ||
| Line 259: | Line 221: | ||
if usesInclude then | if usesInclude then | ||
query = query:gsub( '\127\'"`UNIQ%-%-nowiki%-%x+%-QINU`"\'\127', function(item) return '<nowiki>' .. item .. '</nowiki>' end ) -- Unstrip nowiki so we can clean their content | |||
query = mw.text.unstripNoWiki( query ) | |||
query = query:gsub( dataContentMarker..'(.-)'..dataContentMarker, escape ) | query = query:gsub( dataContentMarker..'(.-)'..dataContentMarker, escape ) | ||
query = query:gsub( '{|.-|%-', '' ) -- Remove the header of the table | |||
-- Replace the footer of the table width a row indicator. This effectively | |||
-- combines the output of multiple dpl queries when count > 500 | |||
query = query:gsub( '|}', '|-' ) | |||
end | end | ||
| Line 266: | Line 234: | ||
for _, v in ipairs( query ) do | for _, v in ipairs( query ) do | ||
if | if v:find( '%S' ) and not v:find( '^@@' ) then | ||
v = trim( v ) | v = trim( v ) | ||
local title = v:match( '^|%[%[(.-)|' ) | local title = v:match( '^|%[%[(.-)|' ) | ||
| Line 276: | Line 244: | ||
end | end | ||
else | else | ||
-- When multiple includes are used (e.g. include={Template1},{Template2} or include={Template}:1:2) | -- When multiple includes are used (e.g. include={Template1},{Template2} or include={Template}:1:2) its results are separated by a pipe | ||
rawDataList = split( rawDataList, '|', true ) | rawDataList = split( rawDataList, '|', true ) | ||
local cleanedDataList = {} | local cleanedDataList = {} | ||
for | for incIndex, dataItem in ipairs( rawDataList ) do | ||
dataItem = unEscape( dataItem ) | dataItem = unEscape( dataItem ) | ||
-- When we include an entire template we use the %ARGS% parameter supplied by dpl. | |||
-- However all | characters are repaced with §, e.g.: | |||
-- §nameLessParam | |||
-- §param = text [[wowee§link text]] | |||
-- §param2 = text {{something§something else}} | |||
dataItem = dataItem:gsub( '%b{}', function(x) return x:gsub( '§', '|' ) end ) -- Restore pipe characters inside links and templates | |||
dataItem = dataItem:gsub( '%b[]', function(x) return x:gsub( '§', '|' ) end ) | |||
dataItem = dataItem:gsub( '<nowiki>(.-)</nowiki>', function(x) return mw.getCurrentFrame():extensionTag( 'nowiki', x ) end ) -- Restrip nowiki | |||
dataItem = trim( dataItem ) | dataItem = trim( dataItem ) | ||
if includedParamNames[ incIndex ].isTemplate and includedParamNames[ incIndex ].includeAll then -- Check if we included a full template | if includedParamNames[ incIndex ].isTemplate and includedParamNames[ incIndex ].includeAll then -- Check if we included a full template | ||
local _dataItem = {} | local _dataItem = {} | ||
| Line 315: | Line 279: | ||
end | end | ||
if includedParamNames[ incIndex ].isTemplate and not includedParamNames[ incIndex ].includeAll then -- This means there was an include in the form 'include = {template}:param' | |||
if | |||
local templateName = includedParamNames[ incIndex ].name | local templateName = includedParamNames[ incIndex ].name | ||
local paramName = includedParamNames[ incIndex ].param | local paramName = includedParamNames[ incIndex ].param | ||
paramName = tonumber( paramName ) or paramName -- Keep as string if tonumber fails | paramName = tonumber( paramName ) or paramName -- Keep as string if tonumber fails | ||
cleanedDataList | cleanedDataList[ templateName ] = cleanedDataList[ templateName ] or {} | ||
cleanedDataList[ templateName ][ paramName ] = dataItem | |||
else | else | ||
cleanedDataList[ includedParamNames[ incIndex ].name ] = dataItem | |||
end | end | ||
end | end | ||
if title and title ~= '' then | if title and title ~= '' then | ||
table.insert( res, { title=title, include=cleanedDataList } ) | |||
end | end | ||
end | end | ||
| Line 359: | Line 303: | ||
-- Combinig multiple dpl queries yields better performance than doing them sequentially | -- Combinig multiple dpl queries yields better performance than doing them sequentially | ||
function dpl.ask( ... ) | function dpl.ask( ... ) | ||
local queries = { ... } | local queries = { ... } | ||
for i = 1, #queries do | for i = 1, #queries do | ||
checkType( 'Module:DPLlua.ask', i, queries[i], 'table' ) | checkType( 'Module:DPLlua.ask', i, queries[i], 'table' ) | ||
removeFormattingSettings( queries[i] ) | removeFormattingSettings( queries[i] ) | ||
queries[i] = formatDpl( queries[i] ) | queries[i] = formatDpl( queries[i] ) | ||
end | end | ||
queries = table.concat( queries, '$@µ@$' ) | queries = table.concat( queries, '$@µ@$' ) | ||
local time = os.clock() | |||
queries = mw.getCurrentFrame():preprocess( queries ) | queries = mw.getCurrentFrame():preprocess( queries ) | ||
time = os.clock() - time | |||
queries = split( queries, '$@µ@$', true ) | queries = split( queries, '$@µ@$', true ) | ||
for i = 1, #queries do | for i = 1, #queries do | ||
queries[i] = toTable( queries[i] ) | |||
queries[i] = toTable( queries | queries[i].time = time | ||
queries[i] | |||
end | end | ||
return unpack( queries ) | return unpack( queries ) | ||
end | end | ||
return dpl | return dpl | ||
-- </nowiki> | -- </nowiki> | ||