Module:Excerpt slideshow

local p = {}local excerptModule = require('Module:Excerpt/portals')local slideshowModule = require('Module:Random slideshow')local randomModule = require('Module:Random')local DEFAULT_LIMIT = 25 -- max number of excerpts to be shown in the slideshowlocal SOURCE_PAGES_LIMIT = 10 -- max number of pages to check for links / list items-- begin BHG addition for tracking source pageslocal sourcepgagesused = {};local sourcepgagesusedcounter = 0;local articlelistcount = -1;local usesEmbeddedList = false;-- end BHG addition for tracking source pagesfunction 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 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 falseend--[[@param {String} wikitext: Wikitext of just the list (i.e. each line is a list item)@param {String} symbol:   Special character used in the wikitext markup for the list, e.g. '*' or '#'@param {String} outerTag: Text portion of the tag for each list or sublist, e.g. 'ul' or 'ol'@param {String} innerTag: Text portion of the tag for each list item, e.g. 'li']]local wikitextToHtmlList = function(wikitext, symbol, outerTag, innerTag)local listParts = {}for level, item in mw.ustring.gmatch('\n'..wikitext..'\n', '\n(%'..symbol..'+)(.-)%f[\n]') do    table.insert(listParts, {level=level, item=item})endtable.insert(listParts, {level='', item=''})local htmlList = {}for i, this in ipairs( listParts ) dolocal isFirstItem = (i == 1)local isLastItem = (i == #listParts)    local lastLevel = isFirstItem and '' or listParts[i-1]['level']    local tags    if #lastLevel == #this.level then    tags = '</'..innerTag..'><'..innerTag..'>'    elseif #this.level > #lastLevel then    tags = string.rep('<'..outerTag..'><'..innerTag..'>', #this.level - #lastLevel)    elseif isLastItem then    tags = string.rep('</'..innerTag..'></'..outerTag..'>', #lastLevel)    else -- ( #this.level < #lastLevel ) and not last item    tags = string.rep('</'..innerTag..'></'..outerTag..'>', #lastLevel - #this.level ) .. '</'..innerTag..'><'..innerTag..'>'    end    table.insert(htmlList, tags .. this.item)endreturn table.concat(htmlList)end--[[@param {String} wikitext: Wikitext excertp containg zero or more lists@param {String} symbol:   Special character used in the wikitext markup for the list, e.g. '*' or '#'@param {String} outerTag: Text portion of the tag for each list or sublist, e.g. 'ul' or 'ol'@param {String} innerTag: Text portion of the tag for each list item, e.g. 'li']]local gsubWikitextLists = function(wikitext, symbol, outerTag, innerTag)-- temporarily remove list linebreaks... wikitext = mw.ustring.gsub(wikitext..'\n', '\n%'..symbol, '¿¿¿'..symbol) -- ...so we can grab the whole list (and just the list)...return mw.ustring.gsub(wikitext,'¿¿¿%'..symbol..'[^\n]+', function(listWikitext)-- ...and then reinstate linebreaks...listWikitext = mw.ustring.gsub(listWikitext, '¿¿¿%'..symbol, '\n'..symbol)-- ...and finally do the conversionreturn wikitextToHtmlList(listWikitext, symbol, outerTag, innerTag)end)end--[[ help gsub strip tables and templates that aren't part of the prose,     and remove linebreaks from within other templates,     and preprocess parser functions ]]local processBraces = function(t)local isTable = mw.ustring.sub(mw.text.trim(t), 2, 2) == '|'if isTable thenreturn ''end-- else it's a template or parser functionlocal first = mw.ustring.sub(t, 1, 1)local last = mw.ustring.sub(t, -1)local isNotPartOfProse = first == '\n' and last == '\n'if isNotPartOfProse thenreturn ''endlocal isParserFunction = mw.ustring.sub(mw.text.trim(t), 3, 3) == '#'if isParserFunction thenlocal frame = mw.getCurrentFrame()return frame:preprocess(t)end-- else remove internal linebreaksreturn mw.ustring.gsub(t, '\n*', '')endlocal cleanUpExcerpt = function(excerpt)-- strip galleriesexcerpt = mw.ustring.gsub(excerpt, "<%s*[Gg]allery.->.-<%s*/%s*[Gg]allery%s*>", "")-- strip tables and block templates; strip newlinesexcerpt = mw.ustring.gsub(excerpt..'\n', '\n?%b{}\n?', processBraces)-- replace wikitext bulleted lists with html bulleted listsexcerpt = gsubWikitextLists(excerpt, '*', 'ul', 'li')-- replace wikitext numbered lists with html numbered listsexcerpt = gsubWikitextLists(excerpt, '#', 'ol', 'li')excerpt = mw.text.trim(excerpt)return excerptendfunction makeGalleryArgs(titles, options, limit, nonRandom)local galleryArgs = {}local titlesSequence = {}local i = 1while titles[i] dotitlesSequence[i] = titles[i]i  = i + 1endlocal sortedTitles = nonRandom and titlesSequence or randomModule.main('array', {t=titlesSequence, limit=limit})for _i, title in ipairs(sortedTitles) doif (#galleryArgs / 2) < limit thenlocal success, excerpt = pcall(excerptModule.get, title, options)if not success thenmw.log("require('Module:Excerpt').get failed: " .. excerpt) -- probably got a redlinkexcerpt = nilendif excerpt and excerpt ~= '' and #excerpt > 10 then -- check again in case we had a few characters plus (Full article...)excerpt = cleanUpExcerpt(excerpt)if options.more thenexcerpt = excerpt .. " ('''[[" .. title .. "|" .. options.more .. "]]''')"endlocal text = '<div style="text-align:left;">' .. mw.ustring.gsub(excerpt, '%c', '<br>') .. '</div>'table.insert(galleryArgs, 'File:Blank.png')table.insert(galleryArgs, text)endendendif nonRandom thengalleryArgs.random = 'false'endif #galleryArgs == 0 and options.nostubs then-- try again, this time including stubsoptions.nostubs = falsereturn makeGalleryArgs(titles, options, limit, nonRandom)elsereturn galleryArgsendendlocal makeOptions = function(args)local options = args -- pick up miscellaneous options: more, errors, fileargsoptions.paraflags = excerptModule.numberFlags(args.paragraphs or "") -- parse paragraphs, e.g. "1,3-5" → {"1","3-5"}options.fileflags = excerptModule.numberFlags(args.files or "") -- parse file numbersif args.nostubs and isDeclined(args.nostubs) thenoptions.nostubs = falseelse options.nostubs = trueendreturn optionsendlocal isArticle = function(pagetitle)local titleObject = mw.title.new(pagetitle)return ( titleObject and titleObject.namespace == 0 ) and true or falseendlocal getLinkedTitles = function(args, method, limit)local pagenames = {}local ii = 1local isNotCategorywhile args[ii] and ii < limit dolocal pageContent = excerptModule.getContent(args[ii])if pageContent thenlocal pageSection = args["section"..ii] or args["section"]local sectionOnly = args["sectiononly"..ii] or args["sectiononly"]local text = pageContentif pageSection then -- check relevant section onlylocal success, result = pcall(excerptModule.getSection, pageContent, pageSection, sectionOnly)if not success thenmw.log("require('Module:Excerpt').getSection failed on the content of " .. args[ii] .. ": " .. result)result = nilendtext = result or pageContentend-- begin BHG addition for tracking source pageslocal thisPage = mw.title.getCurrentTitle().nsText .. ":" .. mw.title.getCurrentTitle().textlocal thisBareParam = mw.ustring.gsub(args[ii], "^([^#]+).*$", "%1", 1) -- strip any section anchor from the parameter's page nameif (thisPage == thisBareParam) thenusesEmbeddedList = true;end-- end BHG addition for tracking source pages-- replace annotated links with real linkstext = mw.ustring.gsub(text, "{{%s*[Aa]nnotated[ _]link%s*|%s*(.-)%s*}}", "[[%1]]")if method == "linked" thenfor p in mw.ustring.gmatch(text, "%[%[%s*([^%]|\n]*)") doif isArticle(p) thentable.insert(pagenames, p)endendelse-- listitem: first wikilink on a line beginning *, :#, etc. except in "See also" or later sectiontext = mw.ustring.gsub(text, "\n== *See also.*", "")for p in mw.ustring.gmatch(text, "\n:*[%*#][^\n]-%[%[%s*([^%]|\n]*)") doif isArticle(p) thentable.insert(pagenames, p)endendend-- begin BHG addition for tracking source pagesif ((method == "listitem") or (method == "linked")) thentable.insert(sourcepgagesused, args[ii])sourcepgagesusedcounter = sourcepgagesusedcounter + 1end-- end BHG addition for tracking source pagesendii = ii + 1end-- begin BHG addition for trackingarticlelistcount = #pagenames-- end BHG addition for trackingreturn pagenamesend-- Template entry points:-- randomExcerpt: Titles specified in template parameters (equivalent to {{Transclude random excerpt}})p.randomExcerpt = function(frame)local parent = frame.getParent(frame)local output = p._excerpt(parent.args, 'random')return frame:extensionTag{ name='templatestyles', args = { src='Module:Random slideshow/styles.css'} } .. frame:preprocess(output)end-- linkedExcerpt: Titles from links on one or more pages (similar to {{Transclude linked excerpt}})p.linkedExcerpt = function(frame)local parent = frame.getParent(frame)local output = p._excerpt(parent.args, 'linked')return frame:extensionTag{ name='templatestyles', args = { src='Module:Random slideshow/styles.css'} } .. frame:preprocess(output)end-- listItemExcerpt: Titles from linked list items one one or more pages (similar to {{Transclude list item excerpt}})p.listItemExcerpt = function(frame)local parent = frame.getParent(frame)local output = p._excerpt(parent.args, 'listitem')return frame:extensionTag{ name='templatestyles', args = { src='Module:Random slideshow/styles.css'} } .. frame:preprocess(output)end-- Module entry point:p._excerpt = function(_args, method)local args = cleanupArgs(_args)args.more = excerptModule.getMoreLinkText(_args.more)local options = makeOptions(args)local limit = args.limit and tonumber(args.limit) or DEFAULT_LIMITlocal titlesif method == 'linked' or method == 'listitem' thentitles = getLinkedTitles(args, method, SOURCE_PAGES_LIMIT)elsetitles = argsendlocal galleryArgs = makeGalleryArgs(titles, options, limit, isDeclined(_args.random))return slideshowModule._main(galleryArgs, false, 'excerptSlideshow-container') .. checksourcepages()endp._cleanUpExcerpt = cleanUpExcerpt-- begin BHG addition for tracking source pagesfunction checksourcepages()-- no tracking unless we are in Portal namespaceif (mw.title.getCurrentTitle().nsText ~= "Portal") thenreturn ""endlocal pagecounter = 0;local templatecount = 0;local outlinecount = 0;local retval ="";local usesEponymousArticle = false;local debugging = false;local thisPageBareName = mw.title.getCurrentTitle().text;if debugging thenretval = '<div style="display:block; border:10px solid green; background-color:#efe; padding:1em; margin:1em">\n----\n'retval = retval .. "sourcepgagesusedcounter: " .. sourcepgagesusedcounter .. "\n----\n"retval = retval .. "pages used:"endlocal apagefor apage in arrayvalues(sourcepgagesused) doif debugging then retval = retval .. "\n# [[:" .. apage .. "]]"retval = retval .. " — " .. "First 999 = /" .. string.sub(apage, 1, 999) .. "/"endif (string.find(apage, "^[tT]emplate ?:") == 1) thentemplatecount = templatecount + 1;endif (string.find(apage, "^[oO]utline +of ") == 1) thenoutlinecount = outlinecount + 1;endif (apage == thisPageBareName) thenusesEponymousArticle = true;endpagecounter = pagecounter + 1endif debugging thenretval = retval .. "\nTotal pages: " .. pagecounterretval = retval .. "\ntemplatecount: " .. templatecountretval = retval .. "</div>"end-- first do a sanity check that both counting methods have produced the same resultif (sourcepgagesusedcounter == pagecounter) then-- if all pages are templates, then populate tracking categoriesif (pagecounter == templatecount) thenif (templatecount == 1) thenretval = retval .. "[[Category:Automated article-slideshow portals with article list built solely from one template]]"elseif (templatecount == 2) thenretval = retval .. "[[Category:Automated article-slideshow portals with article list built solely from two templates]]"elseif (templatecount == 3) thenretval = retval .. "[[Category:Automated article-slideshow portals with article list built solely from three templates]]"elseif (templatecount > 3) thenretval = retval .. "[[Category:Automated article-slideshow portals with article list built solely from four or more templates]]"endelseif (templatecount > 0) thenretval = retval .. "[[Category:Automated article-slideshow portals with article list built using one or more templates, and other sources]]"endendif (outlinecount >= 1) thenretval = retval .. "[[Category:Automated article-slideshow portals with article list built using one or more outline pages]]"endif (articlelistcount < 2) thenretval = retval .. "[[Category:Automated article-slideshow portals with less than 2 articles in article list]]"elseif (articlelistcount <= 5) thenretval = retval .. "[[Category:Automated article-slideshow portals with 2–5 articles in article list]]"elseif (articlelistcount <= 10) thenretval = retval .. "[[Category:Automated article-slideshow portals with 6–10 articles in article list]]"elseif (articlelistcount <= 15) thenretval = retval .. "[[Category:Automated article-slideshow portals with 11–15 articles in article list]]"elseif (articlelistcount <= 20) thenretval = retval .. "[[Category:Automated article-slideshow portals with 16–20 articles in article list]]"elseif (articlelistcount <= 25) thenretval = retval .. "[[Category:Automated article-slideshow portals with 21–25 articles in article list]]"elseif (articlelistcount <= 30) thenretval = retval .. "[[Category:Automated article-slideshow portals with 26–30 articles in article list]]"elseif (articlelistcount <= 40) thenretval = retval .. "[[Category:Automated article-slideshow portals with 31–40 articles in article list]]"elseif (articlelistcount <= 50) thenretval = retval .. "[[Category:Automated article-slideshow portals with 41–50 articles in article list]]"elseif (articlelistcount <= 100) thenretval = retval .. "[[Category:Automated article-slideshow portals with 51–100 articles in article list]]"elseif (articlelistcount <= 200) thenretval = retval .. "[[Category:Automated article-slideshow portals with 101–200 articles in article list]]"elseif (articlelistcount <= 500) thenretval = retval .. "[[Category:Automated article-slideshow portals with 201–500 articles in article list]]"elseif (articlelistcount <= 1000) thenretval = retval .. "[[Category:Automated article-slideshow portals with 501–1000 articles in article list]]"elseif (articlelistcount > 1000) thenretval = retval .. "[[Category:Automated article-slideshow portals with over 1000 articles in article list]]"endif usesEmbeddedList thenretval = retval .. "[[Category:Automated article-slideshow portals with embedded list]]"endif usesEponymousArticle thenretval = retval .. "[[Category:Automated article-slideshow portals with article list built using eponymous article]]"endreturn retvalendfunction arrayvalues(t)local i = 0return function() i = i + 1; return t[i] endend-- end BHG addition for tracking source pagesreturn p