Difference between revisions of "Module:Excerpt slideshow"
(preprocess parser functions) |
m (1 revision imported) |
(No difference)
|
Latest revision as of 09:06, 6 November 2018
Documentation for this module may be created at Module:Excerpt slideshow/doc
local p = {} local excerptModule = require('Module:Excerpt') local slideshowModule = require('Module:Random slideshow') local randomModule = require('Module:Random') function cleanupArgs(argsTable) local cleanArgs = {} for key, val in pairs(argsTable) do if type(val) == 'string' then val = val:match('^%s*(.-)%s*$') if val ~= '' then cleanArgs[key] = val end else cleanArgs[key] = val end end return cleanArgs end --[[ @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}) end table.insert(listParts, {level='', item=''}) local htmlList = {} for i, this in ipairs( listParts ) do local 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) end return 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 conversion return wikitextToHtmlList(listWikitext, symbol, outerTag, innerTag) end ) end local replacePipesWithMagicword = function(t) return mw.ustring.gsub(t, '|', '{{!}}') 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 then return '' end -- else it's a template or parser function local first = mw.ustring.sub(t, 1, 1) local last = mw.ustring.sub(t, -1) local isNotPartOfProse = first == '\n' and last == '\n' if isNotPartOfProse then return '' end local isParserFunction = mw.ustring.sub(mw.text.trim(t), 3, 3) == '#' if isParserFunction then local frame = mw.getCurrentFrame() return frame:preprocess(t) end -- else replace pipes and remove internal linebreaks return replacePipesWithMagicword(mw.ustring.gsub(t, '\n*', '')) end local makeGalleryArgs = function(titles, options, limit) options.nostubs = true local galleryArgs = {} local titlesSequence = {} local i = 1 while titles[i] do titlesSequence[i] = titles[i] i = i + 1 end local randomTitles = randomModule.main('array', {t=titlesSequence, limit=limit}) for _, title in pairs(randomTitles) do local excerpt = mw.text.trim(excerptModule.main({title}, options)) if excerpt and excerpt ~= '' and #excerpt > 10 then -- temporarily take off the '''[[Page title|Read more...]]''' link if present readmore_start_index, readmore_end_index, readmore_text = mw.ustring.find(excerpt, "('''%b[]''')$", -350) --- Starting from end should improve efficiency. 350 characters allows for long page titles and/or a long custom label for the link if readmore_start_index then excerpt = mw.ustring.sub(excerpt, 1, readmore_start_index-2) end -- strip galleries excerpt = mw.ustring.gsub(excerpt, "<%s*[Gg]allery.->.-<%s*/%s*[Gg]allery%s*>", "") -- strip tables and block templates; strip newlines and replace pipes within inline templates excerpt = mw.ustring.gsub(excerpt..'\n', '\n?%b{}\n?', processBraces) -- replace pipes within links excerpt = mw.ustring.gsub(excerpt, '%b[]', replacePipesWithMagicword) -- replace other pipes with html entity excerpt = mw.ustring.gsub(excerpt, '|', '|') -- replace wikitext bulleted lists with html bulleted lists excerpt = gsubWikitextLists(excerpt, '*', 'ul', 'li') -- replace wikitext numbered lists with html numbered lists excerpt = gsubWikitextLists(excerpt, '#', 'ol', 'li') excerpt = mw.text.trim(excerpt) -- add back the "Read more..." link if it was present if readmore_text then excerpt = excerpt .. " " .. readmore_text end local text = '<div style{{=}}text-align:left;>' .. mw.ustring.gsub(excerpt, '%c', '<br>') .. '</div>' table.insert(galleryArgs, 'File:Blank.png') table.insert(galleryArgs, text) end end return galleryArgs end local makeOptions = function(args) local options = args -- pick up miscellaneous options: more, errors, fileargs options.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 numbers return options end local isArticle = function(pagetitle) local titleObject = mw.title.new(pagetitle) return ( titleObject and titleObject.namespace == 0 ) and true or false end local getLinkedTitles = function(args, method, limit) local pagenames = {} local ii = 1 local isNotCategory while args[ii] and ii < limit do local pageContent = excerptModule.getContent(args[ii]) if pageContent then local pageSection = args["section"..ii] or args["section"] local sectionOnly = args["sectiononly"..ii] or args["sectiononly"] local text = pageContent if pageSection then -- check relevant section only text = excerptModule.getsection(pageContent, pageSection, sectionOnly) or pageContent end -- replace annotated links with real links text = mw.ustring.gsub(text, "{{%s*[Aa]nnotated[ _]link%s*|%s*(.-)%s*}}", "[[%1]]") if method == "linked" then for p in mw.ustring.gmatch(text, "%[%[%s*([^%]|\n]*)") do if isArticle(p) then table.insert(pagenames, p) end end else -- listitem: first wikilink on a line beginning *, :#, etc. except in "See also" or later section text = mw.ustring.gsub(text, "\n== *See also.*", "") for p in mw.ustring.gmatch(text, "\n:*[%*#][^\n]-%[%[%s*([^%]|\n]*)") do if isArticle(p) then table.insert(pagenames, p) end end end end ii = ii + 1 end return pagenames end -- 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: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: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:preprocess(output) end -- Module entry point: p._excerpt = function(_args, method) local args = cleanupArgs(_args) -- check for blank value in more parameter if _args.more and not args.more then args.more = "Read more..." -- default text for blank more= end local galleryArgs = {} local options = makeOptions(args) local limit = args.limit and tonumber(args.limit) or 50 local titles if method == 'linked' or method == 'listitem' then titles = getLinkedTitles(args, method, 50) else titles = args end local galleryArgs = makeGalleryArgs(titles, options, limit) return slideshowModule._main(galleryArgs, false, 'excerptSlideshow-container') end return p