|
|
| Line 1: |
Line 1: |
| -- This module implements {{find sources}} and other similar templates, and | | -- Module:Find sources |
| -- also provides a mechanism to easily create new source-finding templates.
| | -- Simple implementation for find sources functionality |
| | |
| -- Define constants
| |
| local ROOT_PAGE = 'Module:Find sources'
| |
| local TEMPLATE_ROOT = ROOT_PAGE .. '/templates/' -- for template config modules
| |
| local LINK_ROOT = ROOT_PAGE .. '/links/' -- for link config modules
| |
| local CONFIG_PAGE = ROOT_PAGE .. '/config' -- for global config
| |
| | |
| -- Load required modules
| |
| local checkType = require('libraryUtil').checkType
| |
| local cfg = mw.loadData(CONFIG_PAGE)
| |
|
| |
|
| local p = {} | | local p = {} |
|
| |
|
| local function maybeLoadData(page) | | -- Link configurations |
| local success, data = pcall(mw.loadData, page) | | local links = { |
| return success and data | | news = { |
| end
| | url = 'https://www.google.com/search?tbm=nws&q={{{1}}}', |
| | | display = 'news', |
| local function substituteParams(msg, ...)
| | }, |
| return mw.message.newRawMessage(msg, ...):plain() | | newspapers = { |
| end
| | url = 'https://www.google.com/search?tbm=nws&q={{{1}}}', |
| | | display = 'newspapers', |
| local function renderSearchString(searchTerms, separator, transformFunc)
| | }, |
| -- This takes a table of search terms and turns it into a search string | | books = { |
| -- that can be used in a URL or in a display value. The transformFunc
| | url = 'https://www.google.com/search?tbm=bks&q={{{1}}}', |
| -- parameter can be used to transform each search term in some way (for
| | display = 'books', |
| -- example, URL-encoding them).
| | }, |
| local searchStrings = {}
| | scholar = { |
| for i, s in ipairs(searchTerms) do
| | url = 'https://scholar.google.com/scholar?q={{{1}}}', |
| searchStrings[i] = s | | display = 'scholar', |
| end | | }, |
| if transformFunc then | | jstor = { |
| for i, s in ipairs(searchStrings) do | | url = 'https://www.jstor.org/action/doBasicSearch?Query={{{1}}}', |
| searchStrings[i] = transformFunc(s)
| | display = 'JSTOR', |
| end
| | }, |
| end | | } |
| return table.concat(searchStrings, separator)
| |
| end
| |
| | |
| function p._renderLink(code, searchTerms, display)
| |
| -- Renders the external link wikicode for one link, given the link code, | |
| -- a table of search terms, and an optional display value.
| |
|
| |
|
| -- Get link config.
| | function p._renderLink(code, args) |
| local linkCfg = maybeLoadData(LINK_ROOT .. code) | | local linkCfg = links[code] |
| if not linkCfg then | | if not linkCfg then |
| error(string.format( | | return string.format('[%s]', code) |
| "invalid link code '%s'; no link config found at [[%s]]",
| |
| code,
| |
| LINK_ROOT .. code
| |
| ))
| |
| end | | end |
| | | |
| -- Make URL. | | local query = table.concat(args, '+') |
| local url
| | local url = string.gsub(linkCfg.url, '{{{1}}}', query) |
| do | | url = string.gsub(url, '{{{q}}}', query) |
| local separator = linkCfg.separator or "+"
| | |
| local searchString = renderSearchString(
| | return string.format('[%s %s]', url, linkCfg.display) |
| searchTerms,
| |
| separator,
| |
| mw.uri.encode
| |
| )
| |
| url = substituteParams(linkCfg.url, searchString)
| |
| end | |
| | |
| return string.format('[%s %s]', url, display or linkCfg.display) | |
| end | | end |
|
| |
|
| function p._main(template, args) | | function p._main(template, args) |
| -- The main access point from Lua. | | local templateCfgs = { |
| checkType('_main', 1, template, 'string')
| | mainspace = { |
| checkType('_main', 2, args, 'table', true)
| | blurb = 'Find sources', |
| args = args or {}
| | introLink = nil, |
| local title = mw.title.getCurrentTitle() | | links = { |
| | | {code = 'news'}, |
| -- Get the template config. | | {code = 'newspapers'}, |
| local templateCfgPage = TEMPLATE_ROOT .. template | | {code = 'books'}, |
| local templateCfg = maybeLoadData(templateCfgPage) | | {code = 'scholar'}, |
| if not templateCfg then | | {code = 'jstor'}, |
| error(string.format(
| | }, |
| "invalid template name '%s'; no template config found at [[%s]]",
| | separator = ' ⧼Dot-separator⧽ ', |
| template, templateCfgPage
| | }, |
| ))
| | } |
| | |
| | local templateCfg = templateCfgs[template] or templateCfgs.mainspace |
| | local links_output = {} |
| | |
| | for i, linkCfg in ipairs(templateCfg.links) do |
| | links_output[#links_output + 1] = p._renderLink(linkCfg.code, args) |
| end | | end |
| | |
| | return table.concat(links_output, templateCfg.separator) |
| | end |
|
| |
|
| -- Namespace check.
| | function p.main(frame) |
| if not templateCfg.isUsedInMainspace and title.namespace == 0 then | | local args = {} |
| local formatString = '<strong class="error">%s</strong>'
| | local parentArgs = frame:getParent().args |
| if cfg['namespace-error-category'] then | | |
| formatString = formatString .. '[[%s:%s]]' | | -- Collect numbered arguments |
| | for i = 1, 20 do |
| | if parentArgs[i] and parentArgs[i] ~= '' then |
| | args[#args + 1] = parentArgs[i] |
| end | | end |
| return string.format(
| |
| formatString,
| |
| cfg['namespace-error'],
| |
| mw.site.namespaces[14].name,
| |
| cfg['namespace-error-category']
| |
| )
| |
| end
| |
|
| |
| -- Get the search terms from the arguments.
| |
| local searchTerms = {}
| |
| for i, s in ipairs(args) do
| |
| searchTerms[i] = s
| |
| end | | end |
| if not searchTerms[1] then | | |
| -- Use the current subpage name as the default search term, unless
| | -- If no arguments, use the page name as default search term |
| -- another title is provided. If the page uses a disambiguator like
| | if #args == 0 then |
| -- "Foo (bar)", make "Foo" the first term and "bar" the second.
| | local title = mw.title.getCurrentTitle() |
| local searchTitle = args.title or title.subpageText | | if title and title.namespace == 0 then |
| local term, dab = searchTitle:match('^(.*) (%b())$')
| | args[1] = title.text |
| if dab then | |
| dab = dab:sub(2, -2) -- Remove parens
| |
| end
| |
| if term and dab then
| |
| searchTerms[1] = term | |
| searchTerms[2] = dab
| |
| else | | else |
| searchTerms[1] = searchTitle | | args[1] = 'example' |
| end | | end |
| end | | end |
| searchTerms[1] = '"' .. searchTerms[1] .. '"' | | |
| | | local template = frame.args[1] or 'mainspace' |
| -- Make the intro link
| | |
| local introLink
| | return p._main(template, args) |
| if templateCfg.introLink then
| |
| local code = templateCfg.introLink.code
| |
| local display = templateCfg.introLink.display or renderSearchString(
| |
| searchTerms,
| |
| ' '
| |
| )
| |
| introLink = p._renderLink(code, searchTerms, display)
| |
| else
| |
| introLink = ''
| |
| end
| |
| | |
| -- Make the other links
| |
| local links = {}
| |
| local separator = templateCfg.separator or cfg['default-separator'] | |
| local sep = ''
| |
| for i, t in ipairs(templateCfg.links) do
| |
| links[i] = sep .. p._renderLink(t.code, searchTerms, t.display) ..
| |
| (t.afterDisplay or '')
| |
| sep = t.separator or separator
| |
| end | |
| links = table.concat(links) | |
| | |
| -- Make the blurb.
| |
| local blurb = substituteParams(templateCfg.blurb, introLink, links)
| |
| local span = mw.html.create('span')
| |
| span
| |
| :addClass('plainlinks')
| |
| :addClass(templateCfg.class)
| |
| :cssText(templateCfg.style)
| |
| :wikitext(blurb)
| |
| | |
| return tostring(span)
| |
| end | | end |
|
| |
|
| setmetatable(p, { __index = function(t, template)
| | -- Create the function that the template is looking for |
| -- The main access point from #invoke.
| | p['Find sources mainspace'] = p.main |
| -- Invocations will look like {{#invoke:Find sources|template name}},
| |
| -- where "template name" is a subpage of [[Module:Find sources/templates]].
| |
| local tname = template
| |
| if tname:sub(-8) == '/sandbox' then
| |
| -- This makes {{Find sources/sandbox|Albert Einstein}} work.
| |
| tname = tname:sub(1, -9)
| |
| end
| |
| return function(frame)
| |
| local args = require('Module:Arguments').getArgs(frame, {
| |
| wrappers = mw.site.namespaces[10].name .. ':' .. tname
| |
| })
| |
| return t._main(template, args)
| |
| end
| |
| end})
| |
|
| |
|
| return p | | return p |