Module:RedirectChecker

--

-- Checks redirects to sections for their target

-- Also checks if a page is a redirect page

--

-- Adds tracking categories in both cases

--

require( 'strict' )

local p = {}

local getArgs = require( 'Module:Arguments' ).getArgs

local delink

local escapePattern = require( 'Module:String' )._escapePattern

-- Module:RedirectChecker/config.json

local config = mw.loadJsonData( 'Module:RedirectChecker/config.json' )

local function isEmpty( str )

return str == nil or str == ''

end

local function getConfigVal( key )

if not isEmpty( config[ key ] ) then

return config[ key ]

end

return error( 'RedirectChecker: config needs to be fixed.' )

end

local function getError( str )

return string.format( '

%s
Category:%s', str, getConfigVal( 'errorCat' ) )

end

local function escape( text )

-- Account for   (or Unicode variant of it)

text = mw.ustring.gsub( escapePattern( text ), ' ', ' ' )

return mw.ustring.gsub( text, '%s', '%%s' )

end

-- Separate function for testing

function p._parse( anchor, content, frame )

if isEmpty( content ) then

return false

end

-- Find a heading of any level matching anchor

local headingPattern = '=%s*' .. escape( anchor ) .. '%s*='

local heading = mw.ustring.match( content, headingPattern )

if heading ~= nil then

return true

end

-- Remove all wikilinks with Module:Delink and remove italic/bold and try again

delink = require( 'Module:Delink' )._delink

for capture in mw.ustring.gmatch( content, '\n=+[^\n]+=+' ) do

local text = escape( capture )

-- Remove bold/italics from replacement only

local r = mw.ustring.gsub( capture, '%%', '%%%' )

r = mw.ustring.gsub( r, '(=+)%s*\'+(.-)\'+%s*%1', '%1 %2 %1' )

content = mw.ustring.gsub( content, text, delink( { r } ) )

end

heading = mw.ustring.match( content, headingPattern )

if heading ~= nil then

return true

end

-- Preprocess and try to find an ID

content = ( frame or mw.getCurrentFrame() ):preprocess( content )

content = mw.text.killMarkers( content )

local id = mw.ustring.match( content, ' id="?' .. escape( anchor ) .. '"?' )

if id ~= nil then

return true

end

-- Try to find HTML heading tag

local hX = mw.ustring.match( content, '%<(h[1-6])%>%s*' .. escapePattern( anchor ) .. '%s*' )

if hX ~= nil then

return true

end

return false

end

function p._main( page, frame )

local mwTitle = mw.title.new( page )

if mwTitle == nil or not mwTitle.exists then

return false, getError( string.format( getConfigVal( 'errorMissing' ), page ) )

end

local target = mwTitle.redirectTarget

if target == false then

return false, getError( string.format( getConfigVal( 'errorNotRedirect' ), page ) )

end

local anchor = target.fragment

if isEmpty( anchor ) then

return false, getError( string.format( getConfigVal( 'errorNoSection' ), page ) )

end

return p._parse( anchor, target:getContent(), frame )

end

function p.main( frame )

local args = getArgs( frame )

local result, err = p._main( args.page or mw.title.getCurrentTitle().fullText, frame )

if result == true then

return ''

end

return string.format( '%sCategory:%s', err or '', getConfigVal( 'brokenSectionCat' ) )

end

return p