Modul:External links

Moduldokumentasjon

Modulen "External links" inneholder følgende metoder som er ment brukt via maler

getLinks
Henter eksterne lenker fra Wikidata i henhold til en konfigurasjonsfil
Funksjonen har noen få felles standard-parametre som kan benyttes
conf
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=...}}
Den vil da returnere en rekke formaterte lenker til eksterne sider i henhold til en konfigurasjon som ligger som undersider av denne modulen.
Følgende konfigurasjoner er tilgjengelige
  • Arter - Artslenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Arter}}. Se {{Artslenker}} for eksempel på bruk.
  • Astronomi - Astronomi, Kalles opp slik: {{#invoke:External links|getLinks|conf=Astronomi}}. Se {{Astronomilenker}} for eksempel på bruk.
  • Autoritetsdata - Autoritetsdata, Kalles opp slik: {{#invoke:External links|getLinks|conf=Autoritetsdata}}. Se {{Autoritetsdata}} for eksempel på bruk.
  • Bryggeri - Bryggerilenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Bryggeri}}. Se {{Bryggerilenker}} for eksempel på bruk.
  • Film - Filmlenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Film}}. Se {{Filmlenker}} for eksempel på bruk.
  • Filmperson - Filmpersonlenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Filmperson}}. Se {{Filmperson}} for eksempel på bruk.
  • Musikk - Musikklenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Musikk}}. Se {{Musikklenker}} for eksempel på bruk.
  • Offisielle lenker - Offisielle lenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Offisielle lenker}}. Se {{Offisielle lenker}} for eksempel på bruk.
  • Politiker - Politiker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Politiker}}. Se {{Politiker}} for eksempel på bruk.
  • Some - Sosiale medie-lenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Some}}. Se {{Somelenker}} for eksempel på bruk.
  • Spill - Spill-lenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Spill}}. Se {{Spill-lenker}} for eksempel på bruk.
  • Sport - Sportslenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Sport}}. Se {{Sportslenker}} for eksempel på bruk.
  • Skip - Skipslenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Skip}}. Se {{Skipslenker}} for eksempel på bruk.
  • Forsker - Forskerlenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Forsker}}. Se {{Forskerlenker}} for eksempel på bruk.
  • Test - For testing av nye typer og utvikling, Kalles opp slik: {{#invoke:External links|getLinks|conf=Test}}. Skal ikke benyttes i produksjon.
tittel
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|tittel=...}}
Denne parameteren kan overstyre artikkelnavnet som benyttes videre i modulen. Hvis dette ikke er satt, vil den som standard bruke sidenavnet til artikkelen.
maxlink
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|maxlink=...}}
Denne parameteren setter maksimum antall lenker som vises frem. Standardverdien er satt til 10.
prop
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|prop=<egenskap>,<egenskap2>,...}}
Denne parameteren setter en begrensning på hvilke egenskaper som skal vises frem. De skilles av med et komma, mellomrom, semikolon eller kolon. Dersom egenskapen starter med et minus-tegn (-), f.eks. -P345, så vil alle egenskaper, unntatt den som er angitt forsøkes vist frem. Det er mulig å legge inn flere av disse.
kort
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|kort=1}}
Denne parameteren bestemmer om kort-versjonen av lenkene skal benyttes.
inline
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|inline=1}}
Denne parameteren bestemmer om lenkene skal legges på en linje med en separator i mellom seg. Linjen vil ikke prefikses med noen bullet eller lignenden. Se definisjonen av separatoren i Module:External links/conf under ['msg-inline-separator']. Denne funksjonaliteten er ment brukt i tilfeller hvor man ønsker å benytte lenkene i referanser eller lignende.
språk
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|språk=<langcode1>,<langcode2>...}}
Denne parameteren setter en begrensning på hvilke språk som skal vises frem. De skilles av med et komma, mellomrom, semikolon eller kolon. Dersom språkkoden starter med et minus-tegn (-), f.eks. -fr, så vil alle språkkoder, unntatt den vises frem. Det er mulig å legge inn flere av disse. Spesial-verdien alle overstyrer og tillater alle språk.
track
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|track=<egenskap1>,<egenskap2>...}}
Denne parameteren styrer individuelle sporingskategorier for hver egenskap. De skilles av med et komma, mellomrom, semikolon eller kolon. Dersom egenskapen starter med et minus-tegn (-), f.eks. -P345, så vil den ikke spores (i tilfelle den er konfigurert til å spores i felleskonfigurasjonen). Det er mulig å legge inn flere av disse, og spesial-koden alle vil slå på sporing på alle.
<egenskapsnavn>
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|<egenskapsnavn>=<verdi>}}
Dette er en generell måte å sette verdien til en egenskap manuelt fra artikler/maler. Dette er ment brukt for tilfeller hvor man bruker en lokalt definert egenskap og trenger å gi den en verdi fra artikkelen. F.eks. bbfc=46443 vil gi ID-en til Blue Thunder i BBFc sin database, og den manuelle definisjonen av bbfc i Module:External links/conf/Film vil da benyttes sammen med den ID-en for å bygge den eksterne lenken.

Se også

require('strict')local genitiv = require('Module:Genitiv')._genitivlocal contLang = mw.language.getContentLanguage()local cmodule = {}local conf = require 'Module:External links/conf'(contLang:getCode())local hasdatafromwikidata = falselocal hasdatafromlocal = falselocal haswikidatalink = true -- we assume it's connectedlocal themainentity = mw.wikibase.getEntity()local linktarget = 'https://www.wikidata.org/wiki/%s?uselang=%s#%s'local p = {}local function getLabel(entity, use_genitiv, pagetitle)local label = (pagetitle and pagetitle ~= '') and pagetitle or nilif not label and not entity thenlabel = mw.title.getCurrentTitle().textelseif not label thenlabel = mw.wikibase.label(entity.id) or mw.title.getCurrentTitle().textendreturn use_genitiv and genitiv(label, 'sitt') or labelend-- @todo cleanup, this is in production, use the consolelocal function dump(obj)return "<pre>" .. mw.dumpObject(obj) .. "</pre>"endlocal function stringFormatter( datavalue )if datavalue == nil or datavalue['type'] ~= 'string' thenreturn nilendreturn datavalue.valueendlocal pval = {}pval.P1793 = { -- format as a regular expressiontypes = {snaktype = 'value',datatype = 'string',},}pval.P407 = { -- language of work or nametypes = {snaktype = 'value',datatype = 'wikibase-item',datavalue = {type = 'wikibase-entityid', }},}pval.P364 = { -- original language of work types = {snaktype = 'value',datatype = 'wikibase-item',datavalue = {type = 'wikibase-entityid', }},}pval.P218 = { -- ISO 639-1 language types = {snaktype = 'value',datatype = 'external-id',datavalue = {type = 'string', }},}pval.P305 = { -- IETF language tagtypes = {snaktype = 'value',datatype = 'external-id',datavalue = {type = 'string', }},}pval.P582 = { -- end timetypes = {snaktype = 'value',datatype = 'time',datavalue = {type = 'string', }},}-- This is a really makeshift crappy converter, but it'll do some basic-- conversion from PCRE to Lua-style patterns (note that this only works-- in very few cases)local function regexConverter( regex )local output = regexoutput = string.gsub(output, "\\d{2}", "%%d%%d")output = string.gsub(output, "\\d{3}", "%%d%%d%%d")output = string.gsub(output, "\\d{4}", "%%d%%d%%d%%d")output = string.gsub(output, "\\d{5}", "%%d%%d%%d%%d%%d")output = string.gsub(output, "\\d{6}", "%%d%%d%%d%%d%%d%%d")output = string.gsub(output, "\\d{7}", "%%d%%d%%d%%d%%d%%d%%d")output = string.gsub(output, "\\d{8}", "%%d%%d%%d%%d%%d%%d%%d%%d")output = string.gsub(output, "\\d", "%%d")return outputendfunction string.urlEncode( str )   if ( str ) then      str = string.gsub( str, "\n", "\r\n" )      str = string.gsub( str, "([^-%w/ ])",         function (c) return string.format( "%%%02X", string.byte(c) ) end )      str = string.gsub( str, " ", "+" )   end   return strendlocal function getFormatterUrl( prop, value )local head = ""local tail = ""local entity = mw.wikibase.getEntity(prop)-- to avoid deep testsif not entity or not entity.claims thenreturn headend-- get the claims for this entitylocal statements = entity.claims['P1630'] -- formatter URL-- to avoid deep testsif not statements thenreturn headendlocal formatters = {}-- let's go through the claimsfor _, claim in ipairs( statements ) do-- to avoid deep testsif not claim thenclaim = {}endlocal valid = claim['type'] == 'statement'and claim['rank'] ~= 'deprecated'if valid thenlocal mainsnak = claim.mainsnak or {}local preferred = claim['rank'] == 'preferred'-- get any qualifiers for this claim (we are interested in P1793 for-- indication of which claim is correct) local qualifiers = claim.qualifiers or {}-- now let's check the qualifier we are interested inlocal qualid = 'P1793' -- format as a regular expression-- if the claim has this qualifierif qualifiers[qualid] then-- it's here, let's check it out!local items = {}-- traverse all snaks in this qualifierfor _, qualsnak in ipairs( qualifiers[qualid] ) doif qualsnak and pval[qualid] then--mw.log("qualsnak = " .. dump(qualsnak))-- check if the snak is of the correct snaktype and datatypelocal valid = qualsnak.snaktype == pval[qualid].types.snaktypeand qualsnak.datatype == pval[qualid].types.datatypeif valid then-- we'll have to convert the regex to Lua-stylelocal regex = regexConverter(qualsnak.datavalue.value)local test = string.match( value, '^'..regex..'$' )if test then-- it matched, this is correct and overrides any other.if preferred thenhead = mainsnak.datavalue.valueelsetail = mainsnak.datavalue.valueendendendendendelse-- we don't have any qualifier, is it preferred?if mainsnak.datavalue and (head == '' and preferred) or (tail == '' and not preferred) then-- if we don't have any other, use this oneif preferred and head == '' thenhead = mainsnak.datavalue.valueelseif not preferred and tail == '' thentail = mainsnak.datavalue.valueendendendendendreturn head ~= '' and head or tailendlocal function getLanguageData(prop, qid)local head = {}local tail = {}-- mw.log("getLanguageData, prop="..dump(prop).." qid="..dump(qid))-- get the entity we are checkinglocal entity = mw.wikibase.getEntityObject(qid)-- to avoid deep testsif not entity thenreturn nilendif not entity.claims thenreturn {}end-- get the claims for this entitylocal statements = entity.claims[prop]-- to avoid deep testsif not statements thenreturn {}end-- mw.log("getLanguageData going through claims="..dump(statements))-- let's go through the claimsfor _, claim in ipairs( statements ) do-- to avoid deep testsif not claim thenclaim = {}endlocal valid = claim['type'] == 'statement'and claim['rank'] ~= 'deprecated'if valid thenlocal mainsnak = claim.mainsnak or {}local preferred = claim['rank'] == 'preferred'-- verify the item is what we expectlocal valid = mainsnak.snaktype == pval[prop].types.snaktypeand mainsnak.datatype == pval[prop].types.datatypeand mainsnak.datavalue.type == pval[prop].types.datavalue.typeif valid then-- mw.log("getLanguageData claim is valid="..dump(claim))-- if this is the correct P-value, dive into it and get P218 (ISO 639-1)if mainsnak.property == 'P364' then -- original language of workif preferred thenhead[#head+1] = table.concat(getLanguageData('P218', 'Q'..mainsnak.datavalue.value['numeric-id']), conf:a('mod-filter-separator'))elsetail[#tail+1] = table.concat(getLanguageData('P218', 'Q'..mainsnak.datavalue.value['numeric-id']), conf:a('mod-filter-separator'))endelseif mainsnak.property == 'P218' or mainsnak.property == 'P305' then -- ISO 639-1 code or IETF language tagif preferred thenhead[#head+1] = stringFormatter(mainsnak.datavalue)elsetail[#tail+1] = stringFormatter(mainsnak.datavalue)endendendendend-- mw.log("getLanguageData returning head="..dump(head).." tail="..dump(tail))return #head>0 and head or tailendlocal langqvalorder = {'P407','P364'}local otherqvalorder = {'P582'}local function getValuesFromWikidata(props)local head = {}local tail = {}-- mw.log("getValuesFromWikidata, props="..dump(props))-- get the entity we are checkinglocal entity = themainentity-- to avoid deep testsif not entity then--mw.log("getValuesFromWikidata no entity")return nilendif not entity.claims or not props or not props.prop or props.prop == '' then--mw.log("getValuesFromWikidata no claims or no props")return {}end-- get the claims for this entitylocal statements = entity.claims[props.prop]-- to avoid deep testsif not statements thenreturn {}end-- let's go through the claimsfor _, claim in ipairs( statements ) do-- to avoid deep testsif not claim thenclaim = {}endlocal valid = claim['type'] == 'statement'and claim['rank'] ~= 'deprecated'if valid then-- mw.log("getValuesFromWikidata valid claim="..dump(claim))local mainsnak = claim.mainsnak or {}local preferred = claim['rank'] == 'preferred'-- get the content of the claim (the identifier)local langcode = props.langcodelocal checklangcode = nilif props.langcode and props.langcode ~= '' thenchecklangcode = string.find(langcode, "([pP]%d+)")endif checklangcode and checklangcode ~= "" then-- this is a P-value for language-code, so we'll check qualifiers for languagedata-- first get any qualifierslocal qualifiers = claim.qualifiers or {}for _, qualid in ipairs( langqvalorder ) do-- if the claim has this qualifierif qualifiers[qualid] then-- it's here, let's check it out!local items = {}-- traverse all snaks in this qualifierfor _, qualsnak in ipairs( qualifiers[qualid] ) doif qualsnak and pval[qualid] then-- mw.log("qualsnak = " .. dump(qualsnak))-- check if the snak is of the correct snaktype and datatypelocal valid = qualsnak.snaktype == pval[qualid].types.snaktypeand qualsnak.datatype == pval[qualid].types.datatypeif valid then-- now get the actual datalangcode = table.concat(getLanguageData('P305', 'Q'..qualsnak.datavalue.value['numeric-id']), '')endendendend-- mw.log("langcode is now="..dump(langcode))endif string.find(langcode, "([pP]%d+)") then-- we still don't have any langcode, so we default to "en"langcode = nilendendlocal stillvalid = true-- we should check a couple of other qualifiers as well-- first get any qualifierslocal qualifiers = claim.qualifiers or {}for _, qualid in ipairs( otherqvalorder ) do-- if the claim has this qualifierif qualifiers[qualid] then-- it's here, let's check it out!local items = {}-- traverse all snaks in this qualifierfor _, qualsnak in ipairs( qualifiers[qualid] ) doif qualsnak and pval[qualid] then-- mw.log("qualsnak = " .. dump(qualsnak))-- check if the snak is of the correct snaktype and datatypelocal valid = qualsnak.snaktype == pval[qualid].types.snaktypeand qualsnak.datatype == pval[qualid].types.datatypeif not valid then-- sorry, this is not correctmw.log("qualsnak = INCORRECT")stillvalid = falseendendendend-- mw.log("langcode is now="..dump(langcode))endif stillvalid thenif preferred thenhead[#head+1] = { value=stringFormatter(mainsnak.datavalue) }if langcode and langcode ~= '' thenhead[#head]['langcode'] = langcodeendelsetail[#tail+1] = { value=stringFormatter(mainsnak.datavalue) }if langcode and langcode ~= '' thentail[#tail]['langcode'] = langcodeendendendendend-- mw.log("getValuesFromWikidata returning head="..dump(head).." tail="..dump(tail))return #head>0 and head or tailendlocal function findMainLinksOnWikidata(props, pagetitle, short_links)local output = {}local pid = nil-- get the entity we are checkinglocal entity = themainentity-- to avoid deep testsif not entity thenreturn nilendlocal values = getValuesFromWikidata(props)for _, value in ipairs( values ) dolocal verified_value = nilif props.regex then-- we have a local defined regex, so this will have to pass first-- maybe we'll have to convert the regex to Lua-stylelocal regex = regexConverter(props.regex)local test = string.match( value.value, '^'..regex..'$' )-- mw.log("testing with "..regex.. " and test="..dump(test).." and value="..id)if test then-- it matched, this is correct and overrides any other.verified_value = value.valueendelseverified_value = value.valueendif verified_value thenlocal url = ''output[#output+1] = {}output[#output].langcode = value.langcodeoutput[#output].category = {}if props.url_f then-- we have a local defined url-formatter function, use it as first priorityurl = props.url_f(verified_value)if props.track and not string.find(props.langcode, "([pP]%d+)") then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-wd'), props.prop):plain()elseif props.track then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-wd'), props.prop):plain()endelseif props.url then-- we have a local defined url-formatter string, use it as second priorityurl = mw.message.newRawMessage(props.url, string.urlEncode(verified_value)):plain()if props.track and not string.find(props.langcode, "([pP]%d+)") then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-wd'), props.prop):plain()elseif props.track then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-wd'), props.prop):plain()endelse-- get the formatvalue from the property, if it existslocal formatterUrl = getFormatterUrl(props.prop, verified_value)if formatterUrl ~= '' thenurl = mw.message.newRawMessage(formatterUrl, string.urlEncode(verified_value)):plain()if props.track then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-wd'), props.prop):plain()endendendif url ~= '' thenlocal this_wiki = mw.getContentLanguage()local this_wiki_code = this_wiki:getCode()local langlink = (value.langcode and value.langcode ~= '' and value.langcode ~= this_wiki_code) and mw.message.newRawMessage(conf:g('msg-langcode'), value.langcode, mw.language.fetchLanguageName(value.langcode, this_wiki_code)) or ""if short_links and props.short thenoutput[#output].text =mw.message.newRawMessage(props.short,getLabel(entity, props.genitiv, pagetitle),url,langlink,verified_value,mw.uri.encode(verified_value, 'PATH')):plain()elseoutput[#output].text =mw.message.newRawMessage(props.message,getLabel(entity, props.genitiv, pagetitle),url,langlink,verified_value,mw.uri.encode(verified_value, 'PATH')):plain()endendendend--mw.log("findMainLinksOnWikidata returning="..dump(output))return outputendlocal function getSitelinksFromWikidata(props, entity)local output = {}--mw.log("getSitelinksFromWikidata, props="..dump(props))-- to avoid deep testsif not entity thenentity = themainentityif not entity then--mw.log("getSitelinksFromWikidata no entity")return nilendendlocal requested_sitelink = string.match(props.prop, "SL(%l+)")local sitelinks = entity:getSitelink(requested_sitelink)if sitelinks and sitelinks ~= '' thenoutput[#output+1] = { value = sitelinks }end--mw.log("getSitelinksFromWikidata returning output="..dump(output))return outputendlocal function findSiteLinksOnWikidata(props, pagetitle, short_links)local output = {}local pid = nil-- get the entity we are checkinglocal entity = themainentity-- to avoid deep testsif not entity thenreturn nilendlocal values = getSitelinksFromWikidata(props)for _, value in ipairs( values ) dolocal verified_value = nilif props.regex then-- we have a local defined regex, so this will have to pass first-- maybe we'll have to convert the regex to Lua-stylelocal regex = regexConverter(props.regex)local test = string.match( value.value, '^'..regex..'$' )--mw.log("testing with "..regex.. " and test="..dump(test).." and value="..id)if test then-- it matched, this is correct and overrides any other.verified_value = value.valueendelseverified_value = value.valueendif verified_value then--mw.log("it's verified..")local url = ''output[#output+1] = {}output[#output].langcode = value.langcodeoutput[#output].category = {}if props.url_f then-- we have a local defined url-formatter function, use it as first priorityurl = props.url_f(verified_value)if props.track and not string.find(props.langcode, "(SL%l+)") then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-wd'), props.prop):plain()elseif props.track then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-wd'), props.prop):plain()endelseif props.url then-- we have a local defined url-formatter string, use it as second priorityurl = mw.message.newRawMessage(props.url, verified_value):plain()if props.track and not string.find(props.langcode, "(SL%l+)") then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-wd'), props.prop):plain()elseif props.track then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-wd'), props.prop):plain()endelseurl = verified_value:gsub(' ','_')if props.track then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-wd'), props.prop):plain()endendif url ~= '' thenlocal this_wiki = mw.getContentLanguage()local this_wiki_code = this_wiki:getCode()local langlink = (value.langcode and value.langcode ~= '' and value.langcode ~= this_wiki_code) and mw.message.newRawMessage(conf:g('msg-langcode'), value.langcode, mw.language.fetchLanguageName(value.langcode, this_wiki_code)) or ""if short_links and props.short thenoutput[#output].text =mw.message.newRawMessage(props.short,getLabel(entity, props.genitiv, pagetitle),url,langlink,verified_value,mw.uri.encode(verified_value, 'PATH')):plain()elseoutput[#output].text =mw.message.newRawMessage(props.message,getLabel(entity, props.genitiv, pagetitle),url,langlink,verified_value,mw.uri.encode(verified_value, 'PATH')):plain()endendendend--mw.log("findSiteLinksOnWikidata returning="..dump(output))return outputendlocal function findMainLinksLocal(props, pagetitle, short_links, local_value)local output = {}-- to avoid deep testsif not props.prop thenreturn nilendif not (local_value or local_value == '') then-- bail out if no value is presentreturn outputend-- get the formatvalue from the propertylocal verified_value = local_valueif props.regex and props.regex ~= '' then-- let's verify the id-- maybe we'll have to convert the regex to Lua-stylelocal regex = regexConverter(props.regex)local test = string.match( local_value, '^'..regex..'$' )if test then-- it matched, this is correctverified_value = local_valueelseverified_value = nilendendif not verified_value thenreturn outputendlocal wikidata_property = string.find(props.prop, "([pP]%d+)")local wikidata_values = {}if wikidata_property then-- get any wikidata values to see if they are equal to local valueswikidata_values = getValuesFromWikidata(props)endif wikidata_property or (props.url and props.url ~= '') or (props.url_f) thenoutput[#output+1] = {}output[#output].langcode = string.find(props.langcode, "([pP]%d+)") and "" or props.langcode--mw.log("findMainLinksLocal - props="..dump(props).." langcode="..output[#output].langcode)output[#output].category = {}local url = ''if props.track and wikidata_property and wikidata_values and #wikidata_values thenlocal local_value_in_wikidata = falsefor _,value in ipairs( wikidata_values ) doif value.value == verified_value thenlocal_value_in_wikidata = trueendendoutput[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), (local_value_in_wikidata and 'track-cat-local-wd-equal' or 'track-cat-local-wd-unequal')), props.prop):plain()endif wikidata_property and wikidata_values and #wikidata_values thenhasdatafromwikidata = true -- signal up the chain this article has a wikidata claimendif props.url_f then-- we have a local defined url-formatter function, use it as first priorityurl = props.url_f(verified_value)if props.track then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-local'), props.prop):plain()endelseif props.url then-- we have a local defined url-formatter string, use it as second priorityurl = mw.message.newRawMessage(props.url, string.urlEncode(verified_value)):plain()if props.track then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-local'), props.prop):plain()endelseif wikidata_property then-- get the formatvalue from the property, if it existslocal formatterUrl = getFormatterUrl(props.prop, string.urlEncode(verified_value))if formatterUrl ~= '' thenurl = mw.message.newRawMessage(formatterUrl, verified_value):plain()if props.track then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-local'), props.prop):plain()endendelse-- no other choice, bail outreturn {}endlocal this_wiki = mw.getContentLanguage()local this_wiki_code = this_wiki:getCode()local langlink = (output[#output].langcode and output[#output].langcode ~= '' and output[#output].langcode ~= this_wiki_code) and mw.message.newRawMessage(conf:g('msg-langcode'), props.langcode, mw.language.fetchLanguageName(props.langcode, this_wiki_code)) or ""if short_links and props.short thenoutput[#output].text =mw.message.newRawMessage(props.short,getLabel(nil, props.genitiv, pagetitle),url,langlink,verified_value,mw.uri.encode(verified_value, 'PATH')):plain()elseoutput[#output].text =mw.message.newRawMessage(props.message,getLabel(nil, props.genitiv, pagetitle),url,langlink,verified_value,mw.uri.encode(verified_value, 'PATH')):plain()endend--mw.log("findMainLinksLocal returning="..dump(output))return outputendlocal function findSiteLinksLocal(props, pagetitle, short_links, local_value)local output = {}-- to avoid deep testsif not props.prop thenreturn nilendif not (local_value or local_value == '') then-- bail out if no value is presentreturn outputend-- get the formatvalue from the propertylocal verified_value = local_valueif props.regex and props.regex ~= '' then-- let's verify the id-- maybe we'll have to convert the regex to Lua-stylelocal regex = regexConverter(props.regex)local test = string.match( local_value, '^'..regex..'$' )if test then-- it matched, this is correctverified_value = local_valueelseverified_value = nilendendif not verified_value thenreturn outputendlocal wikidata_property = string.find(props.prop, "(SL.+)")local wikidata_values = {}if wikidata_property then-- get any wikidata values to see if they are equal to local valueswikidata_values = getSitelinksFromWikidata(props)endif wikidata_property or (props.url and props.url ~= '') or (props.url_f) thenoutput[#output+1] = {}output[#output].langcode = string.find(props.langcode, "(SL.+)") and "" or props.langcode--mw.log("findSiteLinksLocal - props="..dump(props).." langcode="..output[#output].langcode .." wikidata_values="..dump(wikidata_values))output[#output].category = {}local url = ''if props.track and wikidata_property and wikidata_values and #wikidata_values thenlocal local_value_in_wikidata = falsefor _,value in ipairs( wikidata_values ) doif value.value == verified_value thenlocal_value_in_wikidata = trueendendoutput[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), (local_value_in_wikidata and 'track-cat-local-wd-equal' or 'track-cat-local-wd-unequal')), props.prop):plain()endif wikidata_property and wikidata_values and #wikidata_values thenhasdatafromwikidata = true -- signal up the chain this article has a wikidata claimendif props.url_f then-- we have a local defined url-formatter function, use it as first priorityurl = props.url_f(verified_value)if props.track then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-local'), props.prop):plain()endelseif props.url then-- we have a local defined url-formatter string, use it as second priorityurl = mw.message.newRawMessage(props.url, verified_value):plain()if props.track then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-local'), props.prop):plain()endelseif wikidata_property thenurl = verified_value:gsub(' ','_')if props.track then output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-local'), props.prop):plain()endelse-- no other choice, bail outreturn {}endlocal this_wiki = mw.getContentLanguage()local this_wiki_code = this_wiki:getCode()local langlink = (output[#output].langcode and output[#output].langcode ~= '' and output[#output].langcode ~= this_wiki_code) and mw.message.newRawMessage(conf:g('msg-langcode'), props.langcode, mw.language.fetchLanguageName(props.langcode, this_wiki_code)) or ""if short_links and props.short thenoutput[#output].text =mw.message.newRawMessage(props.short,getLabel(nil, props.genitiv, pagetitle),url,langlink,verified_value,mw.uri.encode(verified_value, 'PATH')):plain()elseoutput[#output].text =mw.message.newRawMessage(props.message,getLabel(nil, props.genitiv, pagetitle),url,langlink,verified_value,mw.uri.encode(verified_value, 'PATH')):plain()endend--mw.log("findSiteLinksLocal returning="..dump(output))return outputendlocal function addLinkback(str, property)local id = themainentityif not id thenreturn strendif type(id) == 'table' thenid = id.idendif not property thenreturn strendlocal cls = string.format( 'wd_%s', string.lower( property ) )local lnk = string.format( linktarget, id, contLang:getCode(), property )local lbe = conf:g('wikidata-linkback-edit')local txt = '[[File:OOjs UI icon edit-ltr-progressive.svg'.. '|frameless|text-top|10px'.. '|alt=' .. mw.text.nowiki( lbe ).. '|link=' .. mw.text.nowiki( lnk ).. '|' .. mw.text.nowiki( lbe ).. ']]'local html = mw.html.create( 'span' ):addClass('noprint plainlinks wikidata-linkback ' .. cls )-- @todo add back with correct definition-- :attr( 'data-bridge-edit-flow', 'single-best-value' ):wikitext( txt )return str .. ' ' .. tostring( html )endlocal function getArgument(frame, argument)local args = frame.argsif args[1] == nil thenlocal pFrame = frame:getParent();args = pFrame.args;for k,v in pairs( frame.args ) doargs[k] = v;endendif args[argument] thenreturn args[argument]endreturn nilendlocal function removeEntry(conf_claims, identifier, property)for i, props in ipairs(conf_claims) doif props[identifier] == property thentable.remove(conf_claims, i)endendreturn conf_claimsendfunction p.getLinks(frame)local configured_conf = getArgument(frame, conf:a('arg-conf'))if configured_conf thencmodule = require ('Module:External_links/conf/'..configured_conf)elseerror(mw.message.newRawMessage(conf:g('missing-conf'), configured_conf):plain())endlocal output = {}local category = {}local conf_claims = cmodule:getConfiguredClaims(contLang:getCode())local limits = cmodule:getLimits()assert(limits, mw.message.newRawMessage(conf:g('missing-limits'), configured_conf):plain())local links_shown = getArgument(frame, conf:a('arg-maxlink'))local pagetitle = getArgument(frame, conf:a('arg-title'))-- get a list of tracked properties from the article itselflocal requested_tracking = getArgument(frame, conf:a('arg-track'))if requested_tracking and requested_tracking ~= '' then-- the properties should be written as P1234, P2345 and other -- version corresponding to the applicable property-identifiers in the configfor track_prop in string.gmatch(requested_tracking,"([^ ,;:]+)") do-- get the requested properties and be able to access them-- like req_prop['P345'] to verify if it was requestedlocal remove_track = string.match(track_prop, "^-(.*)")for i,claim in ipairs ( conf_claims )  doif remove_track == claim.prop or remove_track == conf:a('mod-filter-all') then-- if a property starts with "-", then we'll simply remove that -- property from the conf_claimsconf_claims[i]['track'] = falseelseif track_prop == claim.prop or track_prop == conf:a('mod-filter-all') thenconf_claims[i]['track'] = trueendendendend-- get a list of "approved" properties from the article itselflocal requested_properties = getArgument(frame, conf:a('arg-properties'))--mw.log("requested_properties="..dump(requested_properties))-- assume all properties are allowedlocal req_prop = {}local no_req_prop = false  -- we'll allow properties to be filtered for now if requested_properties and requested_properties ~= '' then-- the properties should be written as P1234, P2345 and other -- version corresponding to the applicable property-identifiers in the configfor i in string.gmatch(requested_properties,"([^ ,;:]+)") do-- get the requested properties and be able to access them-- like req_prop['P345'] to verify if it was requestedif i == conf:a('mod-filter-all') then-- this is a special modifier, saying we should ignore -- all previous and future positive filters and remove the-- filter (with exception of negative filters)req_prop = {}no_req_prop = trueendlocal remove_prop = string.match(i, "^-(.*)")if remove_prop then-- if a property starts with "-", then we'll simply remove that -- property from the conf_claimsconf_claims = removeEntry(conf_claims, 'prop', remove_prop)elseif not no_req_prop then -- only if we are allowing properties to be filtered req_prop[i] = 1-- cheat to make #req_prop indicate populated tablereq_prop[1] = 1endendendlocal requested_langs = getArgument(frame, conf:a('arg-languages'))--mw.log("requested_langs="..dump(requested_langs))-- assume all languages are allowedlocal req_lang = {}local no_req_lang = false  -- we'll allow languages to be filtered for nowif requested_langs and requested_langs ~= '' then-- the languages should be written as langcodes as used in the conf_claimsfor i in string.gmatch(requested_langs,"([^ ,;:]+)") do-- get the requested languages and be able to access themif i == conf:a('mod-filter-all') then-- this is a special modifier, saying we should ignore -- all previous and future positive filters and remove the-- filter (with exception of negative filters)req_lang = {}no_req_lang = trueend-- like req_lang['en'] to verify if it was requestedlocal remove_lang = string.match(i, "^-(.*)")if remove_lang then-- if a language starts with "-", then we'll simply remove that -- language from the conf_claimsconf_claims = removeEntry(conf_claims, 'langcode', remove_lang)elseif not no_req_lang then -- only if we are allowing languages to be filtered req_lang[i] = 1-- cheat to make #req_lang indicate populated tablereq_lang[1] = 1endendendlocal short_links = getArgument(frame, conf:a('arg-short'))if short_links and short_links ~= '' thenshort_links = trueelseshort_links = falseendlocal showinline = getArgument(frame, conf:a('arg-inline'))if showinline and showinline ~= '' thenshowinline = trueelseshowinline = falseendif not links_shown or links_shown == '' thenlinks_shown = limits['links-shown'] and limits['links-shown'] or 10elselinks_shown = tonumber(links_shown)endlocal somedataonwikidata = (short_links and false or true)--mw.log("conf_claims="..dump(conf_claims))--mw.log("req_prop="..dump(req_prop))--mw.log("req_lang="..dump(req_lang))--mw.log("short_links="..dump(short_links))for _, props in ipairs(conf_claims) do-- if we're called with a list of approved properties or languages, check if this one is "approved"if (#req_prop==0 or req_prop[props.prop]) and (#req_lang==0 or req_lang[props.langcode] or string.find(props.langcode, "([pP]%d+)")) then--mw.log("checking claim="..dump(props))local links = {}local checkedonwikidata = false-- get the any local overriding value from the calllocal wikivalue = getArgument(frame, props.prop)--mw.log("wikivalue="..dump(wikivalue))if (not wikivalue or wikivalue == "") and string.find(props.prop, "([pP]%d+)") then-- the property is a Pnnn type, and therefore on Wikidatalinks = findMainLinksOnWikidata(props, pagetitle, short_links)if links == nil then-- a nil-value indicated no wikidata-linkhaswikidatalink = falselinks = {}elsecheckedonwikidata = trueendelseif (not wikivalue or wikivalue == "") and string.find(props.prop, "(SL%l+)") then-- this is a sitelink-type (SLspecieswiki)--mw.log("finding sitelinks..")links = findSiteLinksOnWikidata(props, pagetitle, short_links)if links == nil then-- a nil-value indicated no wikidata-linkhaswikidatalink = falselinks = {}elsecheckedonwikidata = trueendelseif (wikivalue and wikivalue ~= "") and string.find(props.prop, "(SL%l+)") then-- this is a sitelink-type (SLspecieswiki)links = findSiteLinksLocal(props, pagetitle, short_links, wikivalue)elseif wikivalue and wikivalue ~= '' then-- the property is of another annotation, and therefore a local constructlinks = findMainLinksLocal(props, pagetitle, short_links, wikivalue)endfor _,v in ipairs(links) do-- we'll have to check langcodes again as they may have come from wikidataif (#req_lang==0 or req_lang[v.langcode]) thenif checkedonwikidata and not hasdatafromwikidata then-- add a general tracking category for articles with data from wikidatahasdatafromwikidata = truecategory[#category+1] = cmodule:getMessage(contLang:getCode(), 'with-data-cat')elseif not checkedonwikidata and not hasdatafromlocal then-- add a general tracking category for articles with data from template-calls in local articleshasdatafromlocal = truecategory[#category+1] = cmodule:getMessage(contLang:getCode(), 'with-local-cat')endif short_links and props.short and v.text and v.text ~= '' then-- if short links were requested, and a short definition exists for this property, let's use itif #output==0 thenoutput[#output+1] = v.textelseoutput[#output] = output[#output] .. cmodule:getMessage(contLang:getCode(),'short-list-separator') .. v.textendsomedataonwikidata = trueelseif not short_links and not showinline and v.text and v.text ~= '' then-- only if short links were not requestedoutput[#output+1] = (#output>=1 and conf:g('msg-ul-prepend') or '')-- if this is the first link, we won't output a list-element (msg-ul-prepend) .. (checkedonwikidata and addLinkback(v.text, props.prop) or v.text)-- if the link comes from wikidata, also output a linkback.elseif not short_links and showinline and v.text and v.text ~= '' then-- only if short links were not requestedoutput[#output+1] = v.textendif props.track and v.category and #v.category then-- add category if tracking is on for this property and a category exists in the link-result.for _,cats in ipairs( v.category ) docategory[#category+1] = catsendendif links_shown>0 thenlinks_shown = links_shown - 1elsebreakendendendif links_shown==0 thenbreakendendendlocal outtext = "" if short_links and #output>0 then-- if these are short links, output the whole thing with linkback to wikidata--mw.log("somedataonwikidata="..dump(somedataonwikidata).." and output="..dump(output).." and #output="..dump(#output))outtext = (somedataonwikidata and addLinkback(table.concat(output,cmodule:getMessage(contLang:getCode(),'short-list-separator')), nil)or table.concat(output,cmodule:getMessage(contLang:getCode(),'short-list-separator')))elseif not short_links and not showinline and #output>0 thenouttext = table.concat(output,"\n")elseif not short_links and showinline and #output>0 thenouttext = table.concat(output,conf:g('msg-inline-separator'))endif not hasdatafromwikidata thencategory[#category+1] = cmodule:getMessage(contLang:getCode(), 'no-data-cat')if not hasdatafromlocal and not short_links thenouttext = cmodule:getMessage(contLang:getCode(), 'no-data-text')endendif not haswikidatalink thencategory[#category+1] = cmodule:getMessage(contLang:getCode(), 'no-wikilink-cat')if not hasdatafromlocal and not short_links thenouttext = cmodule:getMessage(contLang:getCode(), 'no-wikilink')endendlocal nocategory = getArgument(frame, conf:a('arg-no-categories'))category = #category>0 and "\n" .. table.concat(category,"\n") or ""--mw.log("nocategory="..dump(nocategory).." and outtext="..dump(outtext).." and category="..dump(category))outtext = outtext .. (nocategory and '' or category)return outtextendfunction p.getLanguageCode(frame)local prop = getArgument(frame, conf:a('arg-properties'))local output = getLanguageData(prop)if output and #output>0 thenreturn table.concat(output, conf:a('mod-filter-separator'))endendreturn p