Module:DPLlua: Difference between revisions

Jump to navigation Jump to search
osrsw>CephHunter
No edit summary
osrsw>CephHunter
No edit summary
Line 1: Line 1:
-- <nowiki>
-- <nowiki>
local dpl = {}
local dpl = {}
local checkType = require( 'libraryUtil' ).checkType
local libraryUtil = require( 'libraryUtil' )
local checkType = libraryUtil.checkType
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg


dpl.pipe = '¦'
dpl.pipe = '¦'
local dataContentMarker = '`#@@#`'
local dataContentMarker = '`#@@#`'
local usesInclude = {}
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:
['}'] = '&#125;',
['}'] = '&#125;',
['\181'] = '&#125;',
['\181'] = '&#125;',
['\147'] = '&ndash;',
['['] = '&#91;',
['['] = '&#91;',
[']'] = '&#93;',
[']'] = '&#93;',
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+E29DB4) and ❵ (U+E29DB5) wich are 3 bytes long so
-- 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 count = #query
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 _ in params:gmatch( ':' ) do
 
count = count + 1
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, ',' ), count
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 _usesInclude = false
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 = {}
local includeCount = 0


for k, v in pairs( query ) do
for k, v in pairs( query ) do
if k == 'include' then
if k == 'include' then
v, includeCount = formatInclude( v )
v, includedParamNames = formatInclude( v )
_usesInclude =  true
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
table.insert( params, k .. '=' .. tostring( v ):gsub( '|', '¦' ) )
end
end


if _usesInclude then
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..',', includeCount )
string.rep( dataContentMarker..'%%'..dataContentMarker..',', #includedParamNames )
) )
) )
else
else
Line 190: Line 209:
end
end


table.insert( usesInclude, _usesInclude )
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 _usesInclude = table.remove( usesInclude, 1 )
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


if not query:match( '^@@' ) then -- @@ is used when no result is found
query = trim( query )
if _usesInclude then
query = split( query, '|-', true ) -- Results of the returned pages are separated by |-
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 )
for _, v in ipairs( query ) do
query = split( query, '|-', true ) -- Results of the returned pages are separated by |-
if v:match( '%S' ) then
v = trim( v )
local title = v:match( '^|%[%[(.-)|' )
local rawDataList = v:match( '^|.-|.-|(.*)' ) -- This is everything after the title


for _, v in ipairs( query ) do
if not usesInclude then
if v:match( '%S' ) then
if title and title ~= '' then
v = trim( v )
table.insert( res, title )
local title = v:match( '^|%[%[(.-)|' )
end
local dataList = v:match( '^|.-|.-|(.*)' ) -- This is everything after the title
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 = {}


if not _usesInclude then
for incIndex, dataItem in ipairs( rawDataList ) do
if title and title ~= '' then
dataItem = unEscape( dataItem )
table.insert( res, title )
-- When we include an entire template we use the %ARGS% parameter supplied by dpl.
end
-- However all | characters are repaced with §, e.g.:
else
-- §nameLessParam
-- When multiple includes are used (e.g. include={Template1},{Template2}) its results are separated by a pipe
-- §param = text [[wowee§link text]]
dataList = split( dataList, '|', true )
-- §param2 = text {{something§something else}}
local _dataList = {}
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 )


for _, dataItem in ipairs( dataList ) do
if includedParamNames[ incIndex ].isTemplate and includedParamNames[ incIndex ].includeAll then -- Check if we included a full template
dataItem = unEscape( dataItem )
local _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 dataItem:match( '' ) then -- Check if we included a full template
if dataItem ~= '' then
dataItem = split( dataItem, '\', true )
dataItem = split( dataItem, '\n%s*§' )
local _dataItem = {}


for i, item in ipairs( dataItem ) do
for i, item in ipairs( dataItem ) do
Line 258: Line 283:
end
end
end
end
dataItem = _dataItem
end
end


table.insert( _dataList, dataItem )
dataItem = _dataItem
end
end


if title and title ~= '' then
if includedParamNames[ incIndex ].isTemplate and not includedParamNames[ incIndex ].includeAll then -- This means there was an include in the form 'include = {template}:param'
table.insert( res, { title=title, include=_dataList } )
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