Module:DPLlua: Difference between revisionsGive feedback
osrsw>CephHunter No edit summary |
osrsw>CephHunter No edit summary |
||
| Line 1: | Line 1: | ||
-- <nowiki> | -- <nowiki> | ||
local dpl = {} | local dpl = {} | ||
local | local libraryUtil = require( 'libraryUtil' ) | ||
local checkType = libraryUtil.checkType | |||
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg | |||
dpl.pipe = '¦' | dpl.pipe = '¦' | ||
local dataContentMarker = '`#@@#`' | local dataContentMarker = '`#@@#`' | ||
local | local allIncludedParamNames = {} | ||
-- Custom function for splitting a string because mw.text.split() is waaay too slow | -- Custom function for splitting a string because mw.text.split() is waaay too slow | ||
| Line 37: | Line 39: | ||
['}'] = '}', | ['}'] = '}', | ||
['\181'] = '}', | ['\181'] = '}', | ||
['\147'] = '–', | |||
['['] = '[', | ['['] = '[', | ||
[']'] = ']', | [']'] = ']', | ||
| Line 43: | Line 46: | ||
['\226'] = '', | ['\226'] = '', | ||
['\157'] = '', | ['\157'] = '', | ||
['\128'] = '' | |||
} | } | ||
local function escape( str ) | local function escape( str ) | ||
-- the \226\157\180\181 are used to match ❴ (U+ | -- 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. | -- we can't use them directly inside [] patterns. Ustring would fix this but it's way too slow. | ||
str = string.gsub( str, '[{}%[%]|%-\226\157\180\181]', escapeChars ) | -- \226\128\147 used to match – (U+2013) | ||
str = string.gsub( str, '[{}%[%]|%-\226\157\128\180\181\147]', escapeChars ) | |||
return str | return str | ||
end | end | ||
| Line 101: | Line 106: | ||
local function formatInclude( query ) | local function formatInclude( query ) | ||
checkTypeForNamedArg( 'include', 'Module:DPLlua.ask', query, 'string' ) | |||
query = split( query, ',', true ) | query = split( query, ',', true ) | ||
local | local includedParamNames = {} | ||
for i = 1, #query do | for i = 1, #query do | ||
| Line 110: | Line 116: | ||
params:gsub( '^:%-', '' ) | params:gsub( '^:%-', '' ) | ||
query[i] = string.format( '{%s}%s', templateName, params ) | query[i] = string.format( '{%s}%s', templateName, params ) | ||
for | |||
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 } ) | |||
end | end | ||
else | |||
table.insert( includedParamNames, { name=trim( query[i] ) } ) | |||
end | end | ||
end | end | ||
return table.concat( query, ',' ), | return table.concat( query, ',' ), includedParamNames | ||
end | end | ||
| Line 126: | Line 138: | ||
local count = query.count or 500 | local count = query.count or 500 | ||
local offset = query.offset or 0 | local offset = query.offset or 0 | ||
local | local usesInclude = false | ||
local includedParamNames = {} | |||
query.count = nil | query.count = nil | ||
query.offset = nil | query.offset = nil | ||
| Line 135: | Line 148: | ||
[=[ | [=[ | ||
{{#dpl: | {{#dpl: | ||
|noresultsheader = @@ | |noresultsheader=@@ | ||
|count=%s | |count=%s | ||
|offset=%s | |offset=%s | ||
| Line 148: | Line 161: | ||
[=[ | [=[ | ||
{{#dpl: | {{#dpl: | ||
|noresultsheader = @@ | |noresultsheader=@@ | ||
|count=%s | |count=%s | ||
|offset=%s | |offset=%s | ||
| Line 159: | Line 172: | ||
for i = 1, math.ceil( count / 500 ) do | for i = 1, math.ceil( count / 500 ) do | ||
local params = {} | local params = {} | ||
for k, v in pairs( query ) do | for k, v in pairs( query ) do | ||
if k == 'include' then | if k == 'include' then | ||
v, | v, includedParamNames = formatInclude( v ) | ||
usesInclude = true | |||
end | |||
if type( v ) == 'table' then | |||
for _, x in ipairs( v ) do | |||
table.insert( params, k .. '=' .. tostring( x ):gsub( '|', '¦' ) ) | |||
end | |||
else | |||
table.insert( params, k .. '=' .. tostring( v ):gsub( '|', '¦' ) ) | |||
end | end | ||
end | end | ||
if | if usesInclude then | ||
table.insert( queries, string.format( | table.insert( queries, string.format( | ||
dplStringInclude, | dplStringInclude, | ||
| Line 175: | Line 194: | ||
offset, | offset, | ||
table.concat( params, '\n|' ), | table.concat( params, '\n|' ), | ||
string.rep( dataContentMarker..'%%'..dataContentMarker..',', | string.rep( dataContentMarker..'%%'..dataContentMarker..',', #includedParamNames ) | ||
) ) | ) ) | ||
else | else | ||
| Line 190: | Line 209: | ||
end | end | ||
table.insert( | table.insert( allIncludedParamNames, includedParamNames ) | ||
return table.concat( queries ) | return table.concat( queries ) | ||
| Line 196: | Line 215: | ||
local function toTable( query ) | local function toTable( query ) | ||
local | local includedParamNames = table.remove( allIncludedParamNames, 1 ) | ||
local usesInclude = #includedParamNames > 0 | |||
local res = {} | local res = {} | ||
query = query:gsub( '<p>Extension:DynamicPageList .-</p>', function(item) res.error = item; return '' end) | query = query:gsub( '<p>Extension:DynamicPageList .-</p>', function(item) res.error = item; return '' end ) | ||
if query:match( '^@@' ) then -- @@ is used when no result is found | |||
return res | |||
end | |||
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( '{|.-|%-', '' ) -- 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 | |||
query = trim( query ) | |||
query = split( query, '|-', true ) -- Results of the returned pages are separated by |- | |||
for _, v in ipairs( query ) do | |||
if v:match( '%S' ) then | |||
v = trim( v ) | |||
local title = v:match( '^|%[%[(.-)|' ) | |||
local rawDataList = v:match( '^|.-|.-|(.*)' ) -- This is everything after the title | |||
if not usesInclude then | |||
if title and title ~= '' then | |||
table.insert( res, title ) | |||
end | |||
local | else | ||
-- 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 ) | |||
local cleanedDataList = {} | |||
for incIndex, dataItem in ipairs( rawDataList ) do | |||
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 ) | |||
if includedParamNames[ incIndex ].isTemplate and includedParamNames[ incIndex ].includeAll then -- Check if we included a full template | |||
local _dataItem = {} | |||
if dataItem | if dataItem ~= '' then | ||
dataItem = split( dataItem, '\ | dataItem = split( dataItem, '\n%s*§' ) | ||
for i, item in ipairs( dataItem ) do | for i, item in ipairs( dataItem ) do | ||
| Line 258: | Line 283: | ||
end | end | ||
end | end | ||
end | end | ||
dataItem = _dataItem | |||
end | end | ||
if | if includedParamNames[ incIndex ].isTemplate and not includedParamNames[ incIndex ].includeAll then -- This means there was an include in the form 'include = {template}:param' | ||
local templateName = includedParamNames[ incIndex ].name | |||
local paramName = includedParamNames[ incIndex ].param | |||
paramName = tonumber( paramName ) or paramName -- Keep as string if tonumber fails | |||
cleanedDataList[ templateName ] = cleanedDataList[ templateName ] or {} | |||
cleanedDataList[ templateName ][ paramName ] = dataItem | |||
else | |||
cleanedDataList[ includedParamNames[ incIndex ].name ] = dataItem | |||
end | end | ||
end | |||
if title and title ~= '' then | |||
table.insert( res, { title=title, include=cleanedDataList } ) | |||
end | end | ||
end | end | ||