local p = {} -- p stands for package -- technical functions for takeAdjacentNumbersFromStrings function isYear(number) -- TODO: settings not hardcoded return number >= 1800 and number <= 2100 end function isAr(number) return number >= 0 and number < 100 end function notTooFar(number1, number2, maximalPeriod) return number2 - number1 > 0 and number2 - number1 <= maximalPeriod end -- takes two strings and returns either two substrings that form the only difference between them or nil -- considers several possible formats of substrings given in options.formats function takeAdjacentNumbersFromStrings(options, string1, string2) if type(string1) 'string' and type(string2) 'string' then local formats = options.formats or -- TODO: not repeat with properties if formats then formats 'year, year/ar, year/year' elseif formats '-' then formats = end local formats = mw.text.split(formats, ', ?') local line = '!' .. string1 .. '!!' .. string2.. '!' -- -- TODO: without hacks local maximalPeriod = tonumber(options.maximalPeriod) or 5 -- TODO: here or in main function? for _, format in pairs(formats) do if format 'year' or format 'number' then local match = {mw.ustring.match(line, '^(.*%D)(%d+)(%D.*)%1(%d+)%3$')} if #match > 0 then local number1 = tonumber(match[2]) local number2 = tonumber(match[4]) if notTooFar(number1, number2, maximalPeriod) then if (format 'year' and isYear(number1) and isYear(number2)) or (format 'number') then return {number1, number2} end end end elseif format 'year/ar' or format 'year/year' then local match = {mw.ustring.match(line, '^(.*%D)((%d+)[-–\/](%d+))(%D.*)%1((%d+)\/(%d+))%5$')} if #match > 0 then local period1 = match[2] local period1_start = tonumber(match[3]) local period1_end = tonumber(match[4]) local period2 = match[6] local period2_start = tonumber(match[7]) local period2_end = tonumber(match[8]) if notTooFar(period1_start, period2_start, maximalPeriod) and isYear(period1_start) and isYear(period2_start) and period2_start - period1_start period2_end - period1_end then if (format 'year/ar' and isAr(period1_end) and isAr(period2_end)) or (format == 'year/year' and isYear(period1_end) and isYear(period2_end)) then return {period1, period2} end end end end end end return nil end -- takes two Wikidata entities and returns either two strings or nil -- considers sitelinks and labels in the local langauge and in English function takeAdjacentNumbersFromEntities(options, entity1, entity2) if entity1 and entity2 then local adjacentNumbers = nil local languageCodes = {mw.getContentLanguage:getCode, 'en'} for _, languageCode in pairs(languageCodes) do local wikiCode = languageCode .. 'wiki' local sitelink1 = entity1:getSitelink(wikiCode) local sitelink2 = entity2:getSitelink(wikiCode) adjacentNumbers = takeAdjacentNumbersFromStrings(options, sitelink1, sitelink2) if adjacentNumbers then return adjacentNumbers end local label1 = entity1:getLabel(languageCode) -- TODO: get rid of fallback? local label2 = entity2:getLabel(languageCode) adjacentNumbers = takeAdjacentNumbersFromStrings(options, label1, label2) if adjacentNumbers then return adjacentNumbers end end end return nil end function formatAdjacentSnak(context, options, snak) local direction = options.direction or if snak and snak.datavalue and snak.datavalue.value and snak.datavalue.value.id then local mainText = nil local adjacentEntity = mw.wikibase.getEntity(snak.datavalue.value.id) if direction 'P155' then -- previous local adjacentNumbers takeAdjacentNumbersFromEntities(options, adjacentEntity, options.entity) -- or reverse order if adjacentNumbers then mainText adjacentNumbers[1] -- or 2 end elseif direction 'P156' then -- next local adjacentNumbers = takeAdjacentNumbersFromEntities(options, options.entity, adjacentEntity) if adjacentNumbers then mainText = adjacentNumbers[2] end end -- options should not be changed, as they are reused for P155 and P156 local optionsCopy = {} for k, v in pairs(options) do optionsCopy[k] = v end if (not optionsCopy.text) and mainText then local prefix = options.prefix or local postfix = options.postfix or optionsCopy.text = prefix .. mainText .. postfix end local link = context.formatSnak(optionsCopy, snak) if mainText or (options.formats and options.formats == '-') then return link else if link ~= nil then return link .. 'Kategori:Vikipedi:Kronoloji hatası olan maddeler' end end end return nil end -- function is available from outside, see documentation function p.formatAdjacentProperty(context, options) if (not context) then error('context not specified'); end; if (not options) then error('options not specified'); end; if (not options.entity) then error('options.entity missing'); end; if options.value '-' then return end if options.value then return options.value end local properties options.property or -- TODO: properties vs. property? if properties then properties = 'Q' elseif properties '-' then properties end local properties mw.text.split(properties, ', ?') local direction options.direction or -- TODO: not repeating inside local formattedClaims {} for _, property in pairs(properties) do if property 'Q' then local claims = context.selectClaims(options, direction) if claims then for _, claim in pairs(claims) do if claim.mainsnak then local link = formatAdjacentSnak(context, options, claim.mainsnak) if link and link ~= then local formattedClaim = table.insert(formattedClaims, formattedClaim) end end end end elseif mw.ustring.match(property, '^P%d+$') then local claims = context.selectClaims(options, property) if claims then for _, claim in pairs(claims) do if claim.qualifiers and claim.qualifiers[direction] then for _, snak in pairs(claim.qualifiers[direction]) do local link = formatAdjacentSnak(context, options, snak) if link and link ~= then local formattedClaim = table.insert(formattedClaims, formattedClaim) end end end end end end end -- from wikidata.selectClaims if options.limit and options.limit ~= and options.limit ~= '-' then local limit = tonumber(options.limit, 10); while #formattedClaims > limit do table.remove(formattedClaims); end end -- from wikidata.formatPropertyDefault local out = mw.text.listToText(formattedClaims, options.separator, options.conjunction) if out ~= '' then if options.before then out = options.before .. out end if options.after then out = out .. options.after end end return out end return p