Module:Random slideshow

-- Creates a slideshow gallery where the order is randomised. Intended for use on portal pages.local p = {}local excerptModule =  require('Module:Excerpt/portals')local randomModule = require('Module:Random')function cleanupArgs(argsTable)local cleanArgs = {}for key, val in pairs(argsTable) doif type(val) == 'string' thenval = val:match('^%s*(.-)%s*$')if val ~= '' thencleanArgs[key] = valendelsecleanArgs[key] = valendendreturn cleanArgsendfunction normaliseCssMeasurement(input)local suffix = string.reverse(string.sub(string.reverse(input), 1, 2))if ( suffix == 'px' ) or ( suffix == 'em' ) or ( string.sub(suffix, 2, 2) == '%' ) thenreturn inputelsereturn input .. 'px'endendfunction isDeclined(val)if not val then return false endlocal declinedWords = " decline declined exclude excluded false none not no n off omit omitted remove removed "return string.find(declinedWords , ' '..val..' ', 1, true ) and true or falseendfunction makeOutput(galleryLines, maxWidth, containerClassName, nonRandom)local randomiseArgs = {['t'] = galleryLines }local sortedLines = nonRandom and galleryLines or randomModule.main('array', randomiseArgs)for i = 1, #sortedLines do-- insert a switcher-label span just after the first pipe, which should ideally be the captionsortedLines[i] = sortedLines[i]:gsub("|",'|<span class="switcher-label" style="display:none"><span class="randomSlideshow-sr-only">Image ' .. tostring(i) .. '</span></span>',1)endlocal galleryContent = table.concat(sortedLines, '\n')local output = '<div class="' .. containerClassName .. '" style="max-width:' .. normaliseCssMeasurement(maxWidth) .. '; margin:-4em auto;"><div class="nomobile"><!--intentionally empty on desktop, and is not present on mobile website (outside template namesapce)--></div>'.. mw.getCurrentFrame():extensionTag({name="gallery",content=galleryContent,args={mode="slideshow",class="switcher-container"}}) .. '</div>'return outputendfunction makeGalleryLine(file, caption, credit)local title = mw.title.new(file, "File" )if not titlethenreturn "File:Blank.png|{{Error|File [[:File:" .. file .. "]] does not exist.}}"endlocal creditLine = ( credit and '<p><span style="font-size:88%">' .. credit .. '</span></p>' or '' )return title.prefixedText .. '|' .. ( caption or '' ) .. creditLineendfunction makeGalleryLinesTable(args)local galleryLinesTable = {}local i = 1while args[i] dotable.insert(galleryLinesTable, makeGalleryLine(args[i], args[i+1], args['credit' .. (i+1)/2]))i = i + 2endreturn galleryLinesTable endfunction hasCaption(line)local caption = mw.ustring.match(line, ".-|(.*)")-- require caption to exist with more than 5 characters (avoids sizes etc being mistaken for captions)return caption and #caption>5 and true or falseendfunction extractGalleryFiles(wikitext)local gallery = mw.ustring.match(wikitext, '<gallery.->%s*(.-)%s*</gallery>')if not gallery thenreturn falseendreturn mw.text.split(gallery, '%c')endfunction extractRegularFiles(wikitext)local files = {}local frame = mw.getCurrentFrame()local expand = function(template)return frame:preprocess(template)endfor file in mw.ustring.gmatch(wikitext, '%b[]' ) do-- remove keywords that don't work in galleriesfile = mw.ustring.gsub(file, '|%s*thumb%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*thumbnail%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*border%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*left%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*right%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*center%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*centre%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*none%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*baseline%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*sub%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*super%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*top%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*text%-top%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*bottom%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*text%-bottom%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*framed?%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*frameless%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*upright%s*[0-9%.]*%s*([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*upright%s*=.-([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*link%s*=.-([|%]])', '%1')file = mw.ustring.gsub(file, '|%s*lang%s*=.-([|%]])', '%1')-- remove spaces prior to captions (which cause pre-formatted text)file = mw.ustring.gsub(file, '|%s*', '|')-- remove sizes, which sometimes get mistaken for captionsfile = mw.ustring.gsub(file, '|%s*%d*x?%d+%s*px%s*([|%]])', '%1')-- remove linebreaksfile = mw.ustring.gsub(file, '\n\n', '<br>')file = mw.ustring.gsub(file, '\n', '')-- remove surrounding square bracketsfile = mw.ustring.gsub(file, '^%[%[', '')file = mw.ustring.gsub(file, '%]%]$', '')table.insert(files, file)endreturn filesend--Central function for fixing issues that could occur in both gallery-fetched and file-fetched fileslocal function doubleCheck(file)-- disable pipes in wikilinksfile = file:gsub("%[%[([^%]]-)|(.-)]]","[[%1__PIPE__%2]]")-- move any alt parameter to the end to avoid putting the switcher in too early and causing a linter errorfile = file:gsub("^(.+)(|alt=[^|]*)(.*)$","%1%3%2")-- bring back pipes in wikilinksfile = file:gsub("%[%[(.-)__PIPE__(.-)]]","[[%1|%2]]")return fileendfunction makeTranscludedGalleryLinesTables(args)local namespaceNumber = function(pagetitle)local titleObject = mw.title.new(pagetitle)return titleObject and titleObject.namespaceendlocal lines = {}local i = 1while args[i] doif namespaceNumber(args[i]) == 6 then -- file namespace-- args[i] is either just the filename, or uses syntax File:Name.jpg##Caption##Creditlocal parts = mw.text.split(args[i], '##%s*')local filename = parts[1]local caption = args['caption'..i] or parts[2] or falselocal credit = args['credit'..i] or parts[3] or falselocal line = makeGalleryLine(filename, caption, credit)table.insert(lines, line)elselocal content, pagename = excerptModule.getContent(args[i])if not pagename thenreturn error('Cannot read a valid page for "' .. args[i] .. '"', 0)elseif not content thenreturn error('No content found on page "' .. args[i] .. '"', 0)endif args['section'..i] thencontent = excerptModule.getSection(content, args['section'..i]) or ''endcontent = excerptModule.cleanupText(content, {keepSubsections=true}) -- true means keep subsectionslocal galleryFiles = extractGalleryFiles(content)if galleryFiles thenfor _, f in pairs(galleryFiles) doif hasCaption(f) thenlocal filename = string.gsub(f, '|.*', '')local isOkay = excerptModule.checkImage(filename)if isOkay thentable.insert(lines, doubleCheck(f.." (from '''[["..pagename.."]]''')"))endendendendlocal otherFiles = excerptModule.parse(content, {fileflags="1-100", filesOnly=true})if otherFiles thenfor _, f in pairs(extractRegularFiles(otherFiles)) doif f and f ~= '' and mw.ustring.sub(f, 1, 5) == 'File:' and hasCaption(f) thentable.insert(lines, doubleCheck(f.." (from '''[["..pagename.."]]''')"))endendendendi = i + 1endreturn ( #lines > 0 ) and lines or error('No images found')endp._main = function(args, transclude, extraClassName)if not args[1] thenreturn error(linked and 'No page specified' or 'No page specified', 0)endlocal lines = transclude and makeTranscludedGalleryLinesTables(args) or makeGalleryLinesTable(args)local classNames = 'randomSlideshow-container'if extraClassName then classNames = classNames .. ' ' .. extraClassName endreturn makeOutput(lines, args.width or '100%', classNames, isDeclined(args.random))endp.main = function(frame)local parent = frame.getParent(frame)local parentArgs = parent.argslocal args = cleanupArgs(parentArgs)local output = p._main(args, false)return frame:extensionTag{ name='templatestyles', args = { src='Module:Random slideshow/styles.css'} } .. frame:preprocess(output)endp.transclude = function(frame)local parent = frame.getParent(frame)local parentArgs = parent.argslocal args = cleanupArgs(parentArgs)local output = p._main(args, true)return frame:extensionTag{ name='templatestyles', args = { src='Module:Random slideshow/styles.css'} } .. frame:preprocess(output)endreturn p