Модуль:Sources/песочница
Тесты8 тестов из 33 провалено.
Большая советская энциклопедия: [в 30 т.] / Под ред. А. М. Прохорова — 3-е изд. — М.: Советская энциклопедия, 1969. Дмитрий Владимирович Веневитинов [1]Идентификатор «test» неизвестен системе. Используйте один из действующих идентификаторов сущностей. Идентификатор «test» неизвестен системе. Используйте один из действующих идентификаторов сущностей.
---@alias args table
---@alias frame { args: args, extensionTag: function, newChild: ( fun( args: args ): frame ) }
---@alias source { publication: source, [string]: any }
---@alias value: string | { id: string }
---@alias snak { datatype: string, snaktype: string, datavalue: { type: string, value: value } }
---@alias snaks table<string, table<number, snak>>
---@alias statement { mainsnak: snak, rank: string, qualifiers: snaks }
---@alias statements table<string, table<number, statement>>
---@alias map { name: string, ids: string[] }[]>
---@type table
local p = {}
---@type table<string, string>
local NORMATIVE_DOCUMENTS = {
Q20754888 = 'Закон Российской Федерации',
Q20754884 = 'Закон РСФСР',
Q20873831 = 'Распоряжение Президента Российской Федерации',
Q20873834 = 'Указ исполняющего обязанности Президента Российской Федерации',
Q2061228 = 'Указ Президента Российской Федерации',
}
---@type table<string, string>
local LANG_CACHE = {
Q150 = 'fr',
Q188 = 'de',
Q1321 = 'es',
Q1860 = 'en',
Q652 = 'it',
Q7737 = 'ru',
Q8798 = 'uk',
}
---@type map
local PROPERTY_MAP = {
{ name = 'sourceId', ids = { 'P248', 'P805' } },
{ name = 'lang', ids = { 'P407', 'P364' } },
{ name = 'author', ids = { 'P50', 'P2093' } },
{ name = 'part', ids = { 'P958', 'P1810' } },
{ name = 'title', ids = { 'P1476' } },
{ name = 'subtitle', ids = { 'P1680' } },
{ name = 'url', ids = { 'P953', 'P1065', 'P854', 'P973', 'P2699', 'P888' } },
{ name = 'editor', ids = { 'P98' } },
{ name = 'translator', ids = { 'P655' } },
{ name = 'publication-id', ids = { 'P1433' } },
{ name = 'edition', ids = { 'P393' } },
{ name = 'publisher', ids = { 'P123' } },
{ name = 'place', ids = { 'P291' } },
{ name = 'volume', ids = { 'P478' } },
{ name = 'issue', ids = { 'P433' } },
{ name = 'dateOfCreation', ids = { 'P571' } },
{ name = 'dateOfPublication', ids = { 'P577' } },
{ name = 'pages', ids = { 'P304' } },
{ name = 'articleID', ids = { 'P2322' } },
{ name = 'numberOfPages', ids = { 'P1104' } },
{ name = 'tirage', ids = { 'P1092' } },
{ name = 'isbn', ids = { 'P212', 'P957' } },
{ name = 'issn', ids = { 'P236' } },
-- { name = 'accessdate', ids = { 'P813' } }, -- disable, creates duplicate references
{ name = 'docNumber', ids = { 'P1545' } },
{ name = 'type', ids = { 'P31' } },
{ name = 'bibcode', ids = { 'P819' } },
{ name = 'arxiv', ids = { 'P818' } },
{ name = 'doi', ids = { 'P356' } },
{ name = 'pmid', ids = { 'P698' } },
}
-- table.insert( PROPERTY_MAP.url, 'P856' ) -- only as qualifier
---@type map
local PUBLICATION_PROPERTY_MAP = mw.clone( PROPERTY_MAP )
---@type string[]
local monthGen = { 'января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря' }
---@type string
local i18nDefaultLanguage = mw.language.getContentLanguage():getCode()
p.i18nDefaultLanguage = i18nDefaultLanguage
---@type string
local i18nEtAlDefault = ' et al.'
---@type table<string, string>
local i18nEtAl = {
ru = ' и др.',
uk = ' та ін.',
}
---@type table<string, string>
local i18nEditors = {
fr = 'Éd.: ',
de = 'Hrsg.: ',
es = 'Ed.: ',
en = 'Ed.: ',
it = 'Ed.: ',
ru = 'Под ред. ',
uk = 'За ред. ',
}
---@type table<string, string>
local i18nTranslators = {
fr = '',
de = '',
es = '',
en = '',
it = '',
ru = 'пер. ',
uk = 'пер. ',
}
---@type table<string, string>
local i18nVolume = {
de = 'Bd.',
fr = 'Vol.',
es = 'Vol.',
en = 'Vol.',
it = 'Vol.',
ru = 'Т.',
uk = 'Т.',
}
---@type table<string, string>
local i18nIssue = {
de = 'H.',
en = 'Iss.',
ru = 'вып.',
uk = 'вип.',
}
---@type table<string, string>
local i18nPages = {
fr = 'P.',
de = 'S.',
es = 'P.',
en = 'P.',
it = 'P.',
ru = 'С.',
uk = 'С.',
}
---@type table<string, string>
local i18nArticleID = {
en = 'Article',
ru = 'Статья',
uk = 'Стаття',
}
---@type table<string, string>
local i18nNumberOfPages = {
en = 'p.',
ru = 'с.',
uk = 'с.',
}
---@type table<string, string>
local i18nTirage = {
en = 'ed. size: %d',
ru = '%d экз.',
}
---@param args args
---@return source
local function getFilledArgs( args )
---@type source
local data = {}
for key, value in pairs( args ) do
if mw.text.trim( value ) ~= '' then
if key == 1 then
key = 'sourceId'
end
data[ key ] = mw.text.trim( value )
end
end
return data
end
---Returns formatted pair {Family name(s), First name(s)}
---@param fullName string
---@return table<number, string>
local function tokenizeName( fullName )
local space = '%s+' -- matches single or more spacing character
local name = "(%a[%a%-']*)%.?" -- matches single name, have to start with letter, can contain apostrophe and hyphen, may end with dot
local surname = "(%a[%a%-']*)" -- same as name, but can't end with dot
local surnamePrefixes = { 'ван', 'van', 'де', 'de' }
local nm, nm2, srn, srn2, pref
fullName = ' ' .. fullName .. ' '
fullName = mw.ustring.gsub( fullName, ' оглы ', ' ' )
fullName = mw.text.trim( fullName )
-- Surname, Name
local pattern = '^' .. surname .. ',' .. space .. name .. '$'
srn, nm = mw.ustring.match( fullName, pattern )
if srn then
return {
srn,
mw.ustring.sub( nm, 1, 1 ) .. '.'
}
end
-- Surname, Name prefix
for _, surnamePrefix in pairs( surnamePrefixes ) do
pattern = '^' .. surname .. ',' .. space .. name .. space .. '(' .. surnamePrefix .. ')' .. '$'
srn, nm, pref = mw.ustring.match( fullName, pattern )
if srn then
return {
mw.ustring.sub( pref ) .. ' ' .. srn,
mw.ustring.sub( nm, 1, 1 ) .. '.' }
end
end
-- Surname, Name Name
pattern = '^' .. surname .. ',' .. space .. name .. space .. name .. '$'
srn, nm, nm2 = mw.ustring.match( fullName, pattern )
if srn then
return {
srn,
mw.ustring.sub( nm, 1, 1 ) .. '. ' .. mw.ustring.sub( nm2, 1, 1 ) .. '.'
}
end
-- Surname Surname, Name
pattern = '^' .. surname .. space .. surname .. ',' .. space .. name .. '$'
srn, srn2, nm = mw.ustring.match( fullName, pattern )
if srn then
return {
srn .. ' ' .. srn2,
mw.ustring.sub( nm, 1, 1 ) .. '.'
}
end
-- Name prefix Surname
for _, surnamePrefix in pairs( surnamePrefixes ) do
pattern = '^' .. name .. space .. '(' .. surnamePrefix .. ')' .. space .. surname .. '$'
nm, pref, srn = mw.ustring.match( fullName, pattern )
if srn then
return {
mw.ustring.sub( pref ) .. ' ' .. srn,
mw.ustring.sub( nm, 1, 1 ) .. '.'
}
end
end
-- Name Name Surname
pattern = '^' .. name .. space .. name .. space .. surname .. '$'
nm, nm2, srn = mw.ustring.match( fullName, pattern )
if srn then
return {
srn,
mw.ustring.sub( nm, 1, 1 ) .. '. ' .. mw.ustring.sub( nm2, 1, 1 ) .. '.'
}
end
-- Name Name prefix Surname
for _, surnamePrefix in pairs( surnamePrefixes ) do
pattern = '^' .. name .. space .. name .. space .. '(' .. surnamePrefix .. ')' .. space .. surname .. '$'
nm, nm2, pref, srn = mw.ustring.match( fullName, pattern )
if srn then
return {
mw.ustring.sub( pref ) .. ' ' .. srn,
mw.ustring.sub( nm, 1, 1 ) .. '. ' .. mw.ustring.sub( nm2, 1, 1 ) .. '.'
}
end
end
-- Surname, Name Name prefix
for _, surnamePrefix in pairs( surnamePrefixes ) do
pattern = '^' .. surname .. ',' .. space .. name .. space .. name .. space .. '(' .. surnamePrefix .. ')' .. '$'
srn, nm, nm2, pref = mw.ustring.match( fullName, pattern )
if srn then
return {
mw.ustring.sub( pref ) .. ' ' .. srn,
mw.ustring.sub( nm, 1, 1 ) .. '. ' .. mw.ustring.sub( nm2, 1, 1 ) .. '.'
}
end
end
-- Name{1,4} Surname
for k = 1, 4 do
pattern = '^' .. string.rep( name .. space, k ) .. surname .. '$'
---@type string[]
local matched = { mw.ustring.match( fullName, pattern ) }
if #matched ~= 0 then
for j = 1, k do
matched[ j ] = mw.ustring.sub( matched[ j ], 1, 1 )
end
return {
matched[ k + 1 ],
table.concat( matched, '. ', 1, k ) .. '.'
}
end
end
-- Surname Name{1,4}
for k = 1, 4 do
pattern = '^' .. surname .. string.rep( space .. name, k ) .. '$'
---@type string[]
local matched = { mw.ustring.match( fullName, pattern ) }
if #matched ~= 0 then
for j = 2, k + 1 do
matched[ j ] = mw.ustring.sub( matched[ j ], 1, 1 )
end
return {
matched[ 1 ],
table.concat( matched, '. ', 2, k + 1 ) .. '.'
}
end
end
return { fullName }
end
---@param fullName string | nil
---@return string | nil
local function personNameToAuthorName( fullName )
if not fullName then
return nil
end
local tokenized = tokenizeName( fullName )
if #tokenized == 1 then
return tokenized[ 1 ]
end
return tokenized[ 1 ] .. ' ' .. tokenized[ 2 ]
end
---@param fullName string | nil
---@return string | nil
local function personNameToResponsibleName( fullName )
if not fullName then
return nil
end
local tokenized = tokenizeName( fullName )
if #tokenized == 1 then
return tokenized[ 1 ]
end
return tokenized[ 2 ] .. ' ' .. tokenized[ 1 ]
end
---@alias options { separator: string, conjunction: string, format: ( fun( data: string ): string ), nolinks: boolean, preferids: boolean, short: boolean }
---@type options
local options_commas = {
separator = ', ',
conjunction = ', ',
format = function( data ) return data end,
nolinks = false,
preferids = false,
short = false,
}
---@type options
local options_commas_short = mw.clone( options_commas )
options_commas_short.short = true
---@type options
local options_commas_it_short = mw.clone( options_commas_short )
options_commas_it_short.format = function( data ) return "''" .. data .. "''" end
---@type options
local options_commas_nolinks = mw.clone( options_commas )
options_commas_nolinks.nolinks = true
---@type options
local options_citetypes = {
separator = ' ',
conjunction = ' ',
format = function( data ) return 'citetype_' .. data end,
nolinks = true ,
preferids = true,
short = false,
}
---@type options
local options_commas_authors = mw.clone( options_commas )
options_commas_authors.format = personNameToAuthorName
---@type options
local options_commas_responsible = mw.clone( options_commas )
options_commas_responsible.format = personNameToResponsibleName
---@type options
local options_ids = {
separator = '; ',
conjunction = '; ',
format = function( id ) return id end,
nolinks = true,
preferids = false,
short = false,
}
---@type options
local options_bibcode = mw.clone( options_ids )
options_bibcode.format = function( id ) return '[https://ui.adsabs.harvard.edu/abs/' .. id .. ' Bibcode: ' .. id .. '].' end
---@type options
local options_arxiv = mw.clone( options_ids )
options_arxiv.format = function( id ) return '[https://arxiv.org/abs/' .. id .. ' arXiv:' .. id .. '].' end
---@type options
local options_doi = mw.clone( options_ids )
options_doi.format = function( doi ) return '[https://dx.doi.org/' .. doi .. ' doi:' .. doi .. '].' end
---@type options
local options_issn = mw.clone( options_ids )
options_issn.format = function( issn ) return '[https://www.worldcat.org/issn/' .. issn .. ' ' .. issn .. ']' end
---@type options
local options_pmid = mw.clone( options_ids )
options_pmid.format = function( pmid ) return '[https://www.ncbi.nlm.nih.gov/pubmed/?term=' .. pmid .. ' PMID:' .. pmid .. '].' end
---@param str string | nil
---@return boolean
local function isEmpty( str )
return not str or #str == 0
end
---@param allQualifiers snaks
---@param qualifierPropertyId string
---@return string | nil
local function getSingleStringQualifierValue( allQualifiers, qualifierPropertyId )
if not allQualifiers or not allQualifiers[ qualifierPropertyId ] then
return nil
end
---@type table<number, snak>
local propertyQualifiers = allQualifiers[ qualifierPropertyId ]
for _, qualifier in pairs( propertyQualifiers ) do
if ( qualifier
and qualifier.datatype == 'string'
and qualifier.datavalue
and qualifier.datavalue.type == 'string'
and qualifier.datavalue.value ~= ''
) then
return qualifier.datavalue.value
end
end
return nil
end
---@param data table
---@param resultProperty string
---@return void
local function appendImpl_toTable( data, resultProperty )
if not data[ resultProperty ] then
data[ resultProperty ] = {}
elseif ( type( data[ resultProperty ] ) == 'string' or ( type( data[ resultProperty ] ) == 'table' and type( data[ resultProperty ].id ) == 'string' ) ) then
data[ resultProperty ] = { data[ resultProperty ] }
end
end
---@param datavalue table
---@param qualifiers snaks
---@param data table
---@param propertyName string
---@param options table
local function appendImpl( datavalue, qualifiers, data, propertyName, options )
data[ propertyName ] = data[ propertyName ] or {}
if propertyName == 'issn' then
table.insert( data[ propertyName ], datavalue.value )
elseif propertyName == 'url' or datavalue.type == 'url' then
local value = datavalue.value
if options.format then
value = options.format( value )
end
appendImpl_toTable( data, propertyName )
table.insert( data[ propertyName ], value )
elseif datavalue.type == 'string' then
local value = getSingleStringQualifierValue( qualifiers, 'P1932' )
if not value then
value = getSingleStringQualifierValue( qualifiers, 'P1810' )
end
if not value then
value = datavalue.value
if options.format then
value = options.format( value )
end
end
appendImpl_toTable(data, propertyName)
local pos = getSingleStringQualifierValue( qualifiers, 'P1545' )
if pos then
table.insert( data[ propertyName ], tonumber(pos), value )
else
table.insert( data[ propertyName ], value )
end
elseif datavalue.type == 'monolingualtext' then
local value = datavalue.value.text
if options.format then
value = options.format( value )
end
appendImpl_toTable( data, propertyName )
table.insert( data[ propertyName ], value )
elseif datavalue.type == 'quantity' then
local value = datavalue.value.amount
if ( mw.ustring.sub( value , 1, 1 ) == '+' ) then
value = mw.ustring.sub( value , 2 )
end
if options.format then
value = options.format( value )
end
appendImpl_toTable( data, propertyName )
table.insert( data[ propertyName ], value )
elseif datavalue.type == 'wikibase-entityid' then
local pos = getSingleStringQualifierValue( qualifiers, 'P1545' )
local value = datavalue.value
appendImpl_toTable(data, propertyName)
local label = getSingleStringQualifierValue( qualifiers, 'P1932' )
if not label then
label = getSingleStringQualifierValue( qualifiers, 'P1810' )
end
local toInsert = {
id = value.id,
label = label
}
if pos and tonumber( pos ) then
table.insert( data[ propertyName ], tonumber( pos ), toInsert )
else
table.insert( data[ propertyName ], toInsert )
end
elseif datavalue.type == 'time' then
local value = datavalue.value
if options.format then
value = options.format( value )
end
appendImpl_toTable( data, propertyName )
table.insert( data[ propertyName ], tostring( value.time ) )
end
end
---@param entityId string
---@param propertyId string
---@return table<number, statement>
local function getAllStatements( entityId, propertyId )
---@type boolean, table<number, statement>
local wdStatus, statements = pcall( mw.wikibase.getAllStatements, entityId, propertyId )
if wdStatus and statements then
return statements
end
return {}
end
---@param entityId string
---@param propertyId string
---@return table<number, statement>
local function getBestStatements( entityId, propertyId )
---@type boolean, table<number, statement>
local wdStatus, statements = pcall( mw.wikibase.getBestStatements, entityId, propertyId )
if wdStatus and statements then
return statements
end
return {}
end
---@param entityId string
---@param projectToCheck string?
---@return string | nil
local function getSitelink( entityId, projectToCheck )
---@type boolean, string
local wbStatus, sitelink
if projectToCheck then
wbStatus, sitelink = pcall( mw.wikibase.getSitelink, entityId, projectToCheck )
else
wbStatus, sitelink = pcall( mw.wikibase.getSitelink, entityId )
end
if not wbStatus then
return nil
end
return sitelink
end
---@param args any[]
---@return any | nil
local function coalesce( args )
for _, arg in pairs( args ) do
if not isEmpty( arg ) then return arg end
end
return nil
end
---@param value any
---@return string | nil
local function getSingle( value )
if type( value ) == 'string' then
return tostring( value )
elseif type( value ) == 'table' then
if value.id then
return tostring( value.id )
end
for _, tableValue in pairs( value ) do
return getSingle( tableValue )
end
end
return nil
end
---@param langEntityId string
---@return string | nil
local function getLangCode( langEntityId )
if not langEntityId then
return nil
end
langEntityId = getSingle( langEntityId )
if not string.match( langEntityId, '^Q%d+$' ) then
return langEntityId
end
local cached = LANG_CACHE[ langEntityId ]
if cached then
if cached == '' then
return nil
end
return cached
end
local claims = getBestStatements( langEntityId, 'P424' )
for _, claim in pairs( claims ) do
if claim
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.value
then
LANG_CACHE[ langEntityId ] = claim.mainsnak.datavalue.value
return claim.mainsnak.datavalue.value
end
end
LANG_CACHE[ langEntityId ] = ''
return nil
end
---@param entityId string
---@param propertyId string
---@param data source
---@param propertyName string
---@param options table?
---@return void
local function appendEntitySnaks( entityId, propertyId, data, propertyName, options )
options = options or {}
-- do not populate twice
if data[ propertyName ] and ( propertyName ~= 'author' or data[ propertyId ] ) then
return
end
local statements = getBestStatements( entityId, propertyId )
if propertyName == 'author' then
data[ propertyId ] = true
end
local lang = getLangCode( data.lang ) or i18nDefaultLanguage
if propertyId == 'P1680' then -- if there is a default language
for _, statement in pairs( statements ) do
if statement and
statement.mainsnak and
statement.mainsnak.datavalue and
statement.mainsnak.datavalue.value and
statement.mainsnak.datavalue.value.language == lang
then
--found default language string
appendImpl( statement.mainsnak.datavalue, statement.qualifiers, data, propertyName, options )
return
end
end
end
for _, statement in pairs( statements ) do
if statement and statement.mainsnak and statement.mainsnak.datavalue then
appendImpl( statement.mainsnak.datavalue, statement.qualifiers or {}, data, propertyName, options )
if propertyName == 'publication-id' and statement.qualifiers then
data[ 'publication-qualifiers' ] = statement.qualifiers
end
end
end
end
---@param claims table<number, statement>
---@param qualifierPropertyId string
---@param result table
---@param resultPropertyId string
---@param options table
---@return void
local function appendQualifiers( claims, qualifierPropertyId, result, resultPropertyId, options )
-- do not populate twice
if not claims or result[ resultPropertyId ] then
return
end
for _, claim in pairs( claims ) do
if claim.qualifiers and claim.qualifiers[ qualifierPropertyId ] then
---@type table<number, snak>
local propertyQualifiers = claim.qualifiers[ qualifierPropertyId ]
for _, qualifier in pairs( propertyQualifiers ) do
if qualifier and qualifier.datavalue then
appendImpl( qualifier.datavalue, nil, result, resultPropertyId, options )
end
end
end
end
end
---@param entityId string
---@param propertyId string
---@param value any
---@return table<number, statement>
local function findClaimsByValue( entityId, propertyId, value )
local result = {}
local claims = getAllStatements( entityId, propertyId )
for _, claim in pairs( claims ) do
if ( claim.mainsnak and claim.mainsnak.datavalue ) then
local datavalue = claim.mainsnak.datavalue
if ( datavalue.type == "string" and datavalue.value == value ) or
( datavalue.type == "wikibase-entityid" and
datavalue.value[ "entity-type" ] == "item" and
tostring( datavalue.value.id ) == value )
then
table.insert( result, claim )
end
end
end
return result
end
---@param entityId string
---@param typeEntityId string
---@return boolean
local function isInstanceOf( entityId, typeEntityId )
return findClaimsByValue( entityId, 'P31', typeEntityId )[ 1 ] ~= nil
end
---@param entityId string
---@param typeEntityIds string[]
---@return string
---@todo Rewrite
local function getFirstType( entityId, typeEntityIds )
for _, typeEntityId in pairs( typeEntityIds ) do
if isInstanceOf( entityId, typeEntityId ) then
return typeEntityId
end
end
return nil
end
---@param snaks snaks
---@param data source
---@param map map
---@return void
local function populateDataFromSnaks( snaks, data, map )
for _, row in ipairs( map ) do
local parameterName, propertyIds = row.name, row.ids
for _, propertyId in pairs( propertyIds ) do
if not data[ parameterName ] and snaks[ propertyId ] then
local options = {}
if propertyId == 'P888' then
options = { format = function( id ) return 'http://www.jstor.org/stable/' .. id end }
end
for _, snak in pairs( snaks[ propertyId ] ) do
if snak and snak.datavalue then
appendImpl( snak.datavalue, {}, data, parameterName, options )
end
end
end
end
end
end
---@param entityId string | nil
---@param data source
---@param map map
---@return void
local function populateDataFromEntity( entityId, data, map )
if not data.title then
if not isEmpty( entityId ) then
local optionsAsLinks = { format = function( text ) return { id = entityId, label = text } end }
appendEntitySnaks( entityId, 'P1476', data, 'title', optionsAsLinks )
else
appendEntitySnaks( entityId, 'P1476', data, 'title', {} )
end
appendEntitySnaks( entityId, 'P1680', data, 'subtitle', {} )
end
local bookSeriesStatements = getBestStatements( entityId, 'P361' )
for _, statement in pairs( bookSeriesStatements ) do
if statement and
statement.mainsnak and
statement.mainsnak.datavalue and
statement.mainsnak.datavalue.value and
statement.mainsnak.datavalue.value.id
then
local possibleBookSeriesEntityId = statement.mainsnak.datavalue.value.id
if isInstanceOf( possibleBookSeriesEntityId, 'Q277759' ) then
appendImpl_toTable( data, 'bookSeries' )
table.insert( data.bookSeries, { id = possibleBookSeriesEntityId } )
appendQualifiers( { statement }, 'P478', data, 'bookSeriesVolume', {} )
appendQualifiers( { statement }, 'P433', data, 'bookSeriesIssue', {} )
end
end
end
for _, row in ipairs( map ) do
local parameterName, propertyIds = row.name, row.ids
for _, propertyId in pairs( propertyIds ) do
local options = {}
if propertyId == 'P888' then
options = { format = function( id ) return 'http://www.jstor.org/stable/' .. id end }
end
appendEntitySnaks( entityId, propertyId, data, parameterName, options )
end
end
end
---@param data source
---@return void
local function expandPublication( data )
if not data[ 'publication-id' ] then
return
end
local publicationId = getSingle( data[ 'publication-id' ] )
data.publication = {}
for key, value in pairs( data ) do
if not string.match( key, '^publication-' ) then
data.publication[ key ] = value
end
end
data.publication.sourceId = publicationId
data.publication.title = data[ 'publication-title' ]
data.publication.subtitle = data[ 'publication-subtitle' ]
if data[ 'publication-qualifiers' ] then
populateDataFromSnaks( data[ 'publication-qualifiers' ], data.publication, PUBLICATION_PROPERTY_MAP )
end
populateDataFromEntity( publicationId, data.publication, PUBLICATION_PROPERTY_MAP )
if type( data.publication.title ) == 'table' and data.publication.title[ 1 ] then
data.publication.title = data.publication.title[ 1 ]
end
if type( data.publication.subtitle ) == 'table' and data.publication.subtitle[ 1 ] then
data.publication.subtitle = data.publication.subtitle[ 1 ]
end
for key, value in pairs( data.publication ) do
if key ~= 'sourceId' and key ~= 'title' and key ~= 'subtitle' and key ~= 'url' and not data[ key ] then
data[ key ] = value
end
end
end
---@param data source
---@return void
local function expandBookSeries( data )
local bookSeries = data.bookSeries
if not bookSeries then
return
end
-- use only first one
if type( bookSeries ) == 'table' and bookSeries[ 1 ] and bookSeries[ 1 ].id then
data.bookSeries = bookSeries[ 1 ]
bookSeries = data.bookSeries
end
if not bookSeries or not bookSeries.id then
return
end
appendEntitySnaks( bookSeries.id, 'P123', data, 'publisher', {} )
appendEntitySnaks( bookSeries.id, 'P291', data, 'place', {} )
appendEntitySnaks( bookSeries.id, 'P236', data, 'issn', {} )
end
---@param entityId string
---@return string | nil
local function getNormativeTitle( entityId )
local possibleTypeIds = {}
for typeId, _ in pairs( NORMATIVE_DOCUMENTS ) do
table.insert( possibleTypeIds, typeId )
end
local foundTypeId = getFirstType( entityId, possibleTypeIds )
if foundTypeId then
return NORMATIVE_DOCUMENTS[ foundTypeId ]
end
return nil
end
---@param urls table<number, string> | string
---@param text string
---@return string
local function wrapInUrl( urls, text )
local url = getSingle( urls )
if string.sub( url, 1, 1 ) == ':' then
return '[[' .. url .. '|' .. text .. ']]'
else
return '[' .. url .. ' ' .. text .. ']'
end
end
---@param entityId string
---@param lang string
---@return string
local function getElementLink( entityId, lang )
local sitelink = getSitelink( entityId, nil )
if sitelink then
return ':' .. sitelink
end
if lang ~= 'mul' then
-- link to entity in source language
sitelink = getSitelink( entityId, lang .. 'wiki' )
if sitelink then
return ':' .. lang .. ':' .. sitelink
end
end
return ':d:' .. entityId
end
---@param entityId string
---@param lang string
---@return string
local function getLabel( entityId, lang )
local wbStatus, label = pcall( mw.wikibase.getLabelByLang, entityId, lang )
if not wbStatus then
return ''
end
if label and label ~= '' then
return label
end
wbStatus, label = pcall( mw.wikibase.getLabel, entityId )
if not wbStatus then
return ''
end
return label or ''
end
---@param lang string
---@param entityId string
---@param customTitle string
---@param options table
local function renderLink( lang, entityId, customTitle, options )
if not entityId then
error( 'entityId is not specified' )
end
if type( entityId ) ~= 'string' then
error( 'entityId is not string, but ' .. type( entityId ) )
end
if type( customTitle or '' ) ~= 'string' then
error( 'customTitle is not string, but ' .. type( customTitle ) )
end
local title = customTitle
-- ISO 4
if isEmpty( title ) then
local propertyStatements = getBestStatements( entityId, 'P1160' )
for _, claim in pairs( propertyStatements ) do
if ( claim
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.value
and claim.mainsnak.datavalue.value.language == lang
) then
title = claim.mainsnak.datavalue.value.text
-- mw.log( 'Got title of ' .. entityId .. ' from ISO 4 claim: «' .. title .. '»' )
break
end
end
end
-- official name P1448
-- short name P1813
if isEmpty( title ) and options.short then
local propertyStatements = getBestStatements( entityId, 'P1813' )
for _, claim in pairs( propertyStatements ) do
if ( claim
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.value
and claim.mainsnak.datavalue.value.language == lang
) then
title = claim.mainsnak.datavalue.value.text
-- mw.log( 'Got title of ' .. entityId .. ' from short name claim: «' .. title .. '» (' .. lang .. ')' )
break
end
end
end
-- person name P1559
-- labels
if isEmpty( title ) then
title = getLabel( entityId, lang )
-- mw.log( 'Got title of ' .. entityId .. ' from label: «' .. title .. '» (' .. lang .. ')' )
end
local actualText = title or '\'\'(untranslated)\'\''
local link = getElementLink( entityId, lang )
return wrapInUrl( link, actualText )
end
---@param lang string
---@param value value
---@param options options
---@return string
local function asString( lang, value, options )
if type( value ) == 'string' then
return options.format( value )
end
if type( value ) ~= 'table' then
return options.format( '(unknown type)' )
end
if value.id then
-- this is link
if type( value.label or '' ) ~= 'string' then
mw.logObject( value, 'error value' )
error( 'label of table value is not string but ' .. type( value.label ) )
end
local title
if options.preferids then
title = value.id
elseif options.nolinks then
title = value.label or getLabel( value.id, lang )
else
title = renderLink( lang, value.id, value.label, options )
end
if title == '' then
title = "''(untranslated title)''"
end
return options.format( title )
end
local resultList = {}
for _, tableValue in pairs( value ) do
table.insert( resultList, asString( lang, tableValue, options ) )
end
return mw.text.listToText( resultList, options.separator, options.conjunction )
end
---@param entityId string
---@param data source
---@return source
local function populateSourceDataImpl( entityId, data, map )
local wsLink = getSitelink( entityId, 'ruwikisource' )
if wsLink and not mw.ustring.gmatch( wsLink, 'Категория:' ) then
data.url = ":ru:s:" .. wsLink
end
populateDataFromEntity( entityId, data, map )
local normativeTitle = getNormativeTitle( entityId )
if normativeTitle then
local y, m, d = mw.ustring.match( getSingle( data.dateOfCreation ) , "(%-?%d+)%-(%d+)%-(%d+)T" )
y, m, d = tonumber( y ),tonumber( m ), tonumber( d )
local title = asString( 'ru', data.title, options_commas_nolinks )
local docNumber = getSingle( data.docNumber )
data.title = {
normativeTitle ..
" от " .. tostring( d ) .. " " .. monthGen[ m ] .. " " .. tostring( y ) .. " г." ..
( docNumber and ( " № " .. docNumber ) or '' ) ..
' «' .. title.. '»'
}
end
if not data.title then
local lang = getLangCode( data.lang ) or i18nDefaultLanguage
local label = getLabel( entityId, lang )
if label ~= '' then
data.title = { label }
end
end
return data
end
---@param entityId string
---@param propertyId string
---@param data source
---@return void
local function expandSpecialsQualifiers( entityId, propertyId, data )
local statements = getBestStatements( entityId, propertyId )
for _, statement in pairs( statements ) do
populateDataFromSnaks( statement.qualifiers or {}, data, PROPERTY_MAP )
end
end
---Expand special types of references when additional data could be found in OTHER entity properties
---@param data source
---@return void
local function expandSpecials( data )
if not data.entityId then
return
end
if data.sourceId == 'Q36578' then
-- Gemeinsame Normdatei -- specified by P227
appendEntitySnaks( data.entityId, 'P227', data, 'part', { format = function(gnd ) return 'Record #' .. gnd; end } )
appendEntitySnaks( data.entityId, 'P227', data, 'url', { format = function(gnd ) return 'http://d-nb.info/gnd/' .. gnd .. '/'; end } )
data.year = '2012—2016'
expandSpecialsQualifiers( data.entityId, 'P227', data )
elseif data.sourceId == 'Q15222191' then
-- BNF -- specified by P268
appendEntitySnaks( data.entityId, 'P268', data, 'part', { format = function(id ) return 'Record #' .. id; end } )
appendEntitySnaks( data.entityId, 'P268', data, 'url', { format = function(id ) return 'http://catalogue.bnf.fr/ark:/12148/cb' .. id; end } )
expandSpecialsQualifiers( data.entityId, 'P268', data )
elseif data.sourceId == 'Q54919' then
-- VIAF -- specified by P214
appendEntitySnaks( data.entityId, 'P214', data, 'part', { format = function(id ) return 'Record #' .. id; end } )
appendEntitySnaks( data.entityId, 'P214', data, 'url', { format = function(id ) return 'https://viaf.org/viaf/' .. id; end } )
expandSpecialsQualifiers( data.entityId, 'P214', data )
else
-- generic property search
for _, sourceClaim in pairs( getBestStatements( data.sourceId, 'P1687' ) ) do
if sourceClaim.mainsnak.snaktype == 'value' then
local sourcePropertyId = sourceClaim.mainsnak.datavalue.value.id
for _, sourcePropertyClaim in pairs( getBestStatements( sourcePropertyId, 'P1630' ) ) do
if sourcePropertyClaim.mainsnak.snaktype == 'value' then
appendEntitySnaks( data.entityId, sourcePropertyId, data, 'url', {
format = function( id )
return mw.ustring.gsub( mw.ustring.gsub( sourcePropertyClaim.mainsnak.datavalue.value, '$1', id ), ' ', '%%20' )
end
} )
expandSpecialsQualifiers( data.entityId, sourcePropertyId, data )
break
end
end
end
end
end
-- do we have appropriate record in P1433 ?
local claims = findClaimsByValue( currentEntityId, 'P1343', data.sourceId )
if claims and #claims ~= 0 then
for _, claim in pairs( claims ) do
populateDataFromSnaks( claim.qualifiers, data, PROPERTY_MAP )
populateDataFromEntity( data.sourceId, data, PROPERTY_MAP )
end
end
end
---@param text string
---@param tip string
---@return string
local function toTextWithTip( text, tip )
return '<span title="' .. tip .. '" style="border-bottom: 1px dotted; cursor: help; white-space: nowrap">' .. text .. '</span>'
end
---@param lang string
---@param placeId string
---@return string
local function getPlaceName( placeId, lang )
-- ГОСТ Р 7.0.12—2011
if lang == 'ru' then
if placeId == 'Q649' then return toTextWithTip( 'М.', 'Москва' ); end
if placeId == 'Q656' then return toTextWithTip( 'СПб.', 'Санкт-Петербург' ); end
if placeId == 'Q891' then return toTextWithTip( 'Н. Новгород', 'Нижний Новгород' ); end
if placeId == 'Q908' then return toTextWithTip( 'Ростов н/Д.', 'Ростов-на-Дону' ); end
end
return nil
end
---@param data source
---@param lang string
---@return void
local function preprocessPlace( data, lang )
if not data.place then
return
end
---@type table<number, string>
local newPlace = {}
for index, place in pairs( data.place ) do
if place.id then
local newPlaceStr = getPlaceName( place.id, lang )
if newPlaceStr then
newPlace[ index ] = newPlaceStr
else
newPlace[ index ] = getLabel( place.id, lang )
end
else
newPlace[ index ] = place
end
end
data.place = newPlace
end
---@param entityId string
---@param lang string
---@param providedLabel string | nil
---@param options options
---@return string
local function getPersonNameAsLabel( entityId, lang, providedLabel, options )
-- would custom label provided we don't need to check entity at all
if not isEmpty( providedLabel ) then
return options.format( providedLabel )
end
if lang == 'mul' then
lang = i18nDefaultLanguage
end
---@type string | nil
local personName = getLabel( entityId, lang )
if isEmpty( personName ) then
return '\'\'(not translated to ' .. lang .. ')\'\''
end
if not isInstanceOf( entityId, 'Q5' ) then
return personName
end
return options.format( personName )
end
---@param entityId string
---@param lang string
---@param customLabel string | nil
---@param options options
---@return string
local function getPersonNameAsWikitext( entityId, lang, customLabel, options )
local personName = getPersonNameAsLabel( entityId, lang, customLabel, options )
local link = getElementLink( entityId, lang )
return wrapInUrl( link, personName )
end
---@param value value
---@param lang string
---@param options options
---@return string
local function getPeopleAsWikitext( value, lang, options )
if type( value ) == 'string' then
return options.format( value )
elseif type( value ) == 'table' then
if value.id then
-- this is link
if options.preferids then
return tostring( value.id )
else
if options.nolinks then
return getPersonNameAsLabel( value.id, lang, value.label, options )
else
return getPersonNameAsWikitext( value.id, lang, value.label, options )
end
end
end
local maxAuthors = 10 -- need some restrictions, as some publications have enormous amount of authors (e.g. 115 authors of Q68951544)
local resultList = {}
for _, tableValue in pairs( value ) do
local nextWikitext = getPeopleAsWikitext( tableValue, lang, options )
if not isEmpty( nextWikitext ) then
table.insert( resultList, nextWikitext )
if #resultList == maxAuthors + 1 then
-- keep one more to indicate that there are too many
break
end
end
end
local resultWikitext = ''
for i, wikitext in pairs( resultList ) do
if i == maxAuthors + 1 then
resultWikitext = resultWikitext .. ( i18nEtAl[ lang ] or i18nEtAlDefault )
break
end
if i ~= 1 then
resultWikitext = resultWikitext .. ', '
end
resultWikitext = resultWikitext .. wikitext
end
return resultWikitext
end
return '' -- options.format( '(unknown type)' )
end
---@param lang string
---@param data source
---@return string
local function generateAuthorLinks( lang, data )
local result = ''
if data.author then
result = getPeopleAsWikitext( data.author, lang, options_commas_authors )
result = '<i class="wef_low_priority_links">' .. result .. '</i> '
end
return result
end
---@param lang string
---@param data source
---@param conjunction string
---@param propertyName string
---@param urlPropertyName string?
---@return string
local function appendProperty( lang, data, conjunction, propertyName, urlPropertyName )
if not data[ propertyName ] then
return ''
end
local out
if urlPropertyName and data[ urlPropertyName ] then
out = wrapInUrl( data[ urlPropertyName ], asString( lang, data[ propertyName ], options_commas_nolinks ) )
else
out = asString( lang, data[ propertyName ], options_commas )
end
if not out or out == '' then
return ''
end
return conjunction .. out
end
---@param lang string
---@param data source
---@return string
local function appendTitle( lang, data )
local conjunction = ''
local result = ''
if data.part then
result = result .. appendProperty( lang, data, '', 'part', 'parturl' )
conjunction = ' // '
end
return result .. appendProperty( lang, data, conjunction, 'title', 'url' )
end
---@param lang string
---@return string
local function appendLanguage( lang )
if lang == i18nDefaultLanguage then
return ''
end
---@type { getRefHtml: ( fun( lang: string ): string ), list_ref: ( fun( frame: frame ): string ) }
local langs = require( 'Module:Languages' )
return langs.list_ref( p.currentFrame:newChild{ args = { lang } } )
end
---@param lang string
---@param data source
---@return string
local function appendSubtitle( lang, data )
return appendProperty( lang, data, ': ', 'subtitle', nil )
end
---@param lang string
---@param data source
---@return string
local function appendOriginalTitle( lang, data )
return appendProperty( lang, data, ' = ', 'originaltitle', nil )
end
---@param lang string
---@param data source
---@return string
local function appendPublication( lang, data )
if not data.publication then
return ''
end
local result = ' // ' .. asString( lang, data.publication.title, options_commas_it_short )
if data.publication.subtitle and data.publication.subtitle ~= '' then
result = result .. ': ' .. asString( lang, data.publication.subtitle, options_commas_it_short )
end
return result
end
---@param lang string
---@param data source
---@return string
local function appendEditor( lang, data )
if not data.editor and not data.translator then
return ''
end
if data.issue or data.volume then -- нет необходимости указывать редакторов периодических изданий, например научных журналов --
return ''
end
local result = ' / '
if data.editor then
local prefix = i18nEditors[ lang ] or i18nEditors[ i18nDefaultLanguage ]
result = result .. prefix .. getPeopleAsWikitext( data.editor, lang, options_commas_responsible )
if data.translator then
result = result .. ', '
end
end
if data.translator then
local prefix = i18nTranslators[ lang ] or i18nTranslators[ i18nDefaultLanguage ]
result = result .. prefix .. getPeopleAsWikitext( data.translator, lang, options_commas_responsible )
end
return result
end
---@param lang string
---@param data source
local function appendEdition( lang, data )
return appendProperty( lang, data, ' — ', 'edition', nil )
end
---@param lang string
---@param data source
---@return string
local function appendPublicationData( lang, data )
if not data.place and not data.publisher and not data.year then
return ''
end
local result = ' — '
if data.place then
result = result .. asString( lang, data.place, options_commas_short )
if data.publisher or data.year then
result = result .. ': '
end
end
if data.publisher then
result = result .. asString( lang, data.publisher, options_commas_short )
if data.year then
result = result .. ', '
end
end
if data.year then
result = result .. asString( lang, data.year, options_commas )
end
result = result .. '.'
return result
end
---@param lang string
---@param data source
---@return string
local function appendVolumeAndIssue( lang, data )
if not data.volume and not data.issue then
return ''
end
local result = ' — '
local letter_vol = i18nVolume[ lang ] or i18nVolume[ i18nDefaultLanguage ]
local letter_iss = i18nIssue[ lang ] or i18nIssue[ i18nDefaultLanguage ]
if data.volume then
result = result .. appendProperty( lang, data, letter_vol .. ' ', 'volume', nil )
result = result ..appendProperty( lang, data, ', ' .. letter_iss .. ' ', 'issue', nil )
else
result = result .. appendProperty( lang, data, letter_iss .. ' ', 'issue', nil )
end
result = result .. '.'
return result
end
---@param lang string
---@param data source
---@return string
local function appendPages( lang, data )
if not data.pages then
return ''
end
local letter = i18nPages[ lang ] or i18nPages[ i18nDefaultLanguage ]
local strPages = asString( lang, data.pages, options_commas )
strPages = mw.ustring.gsub( strPages, '[-—]', '—' )
return ' — ' .. letter .. ' ' .. strPages .. '.'
end
---@param lang string
---@param data source
---@return string
local function appendArticleID( lang, data )
if not data.articleID then
return ''
end
local letter = i18nArticleID[ lang ] or i18nArticleID[ i18nDefaultLanguage ]
return ' — ' .. letter .. ' ' .. appendProperty( lang, data, '', 'articleID', nil ) .. '.'
end
---@param lang string
---@param data source
---@return string
local function appendNumberOfPages( lang, data )
if not data.numberOfPages then
return ''
end
local letter = i18nNumberOfPages[ lang ] or i18nNumberOfPages[ i18nDefaultLanguage ]
return appendProperty( lang, data, ' — ', 'numberOfPages', nil ) .. ' ' .. letter
end
---@param lang string
---@param data source
---@return string
local function appendBookSeries( lang, data )
if not data.bookSeries then
return ''
end
local result = appendProperty( lang, data, ' — (', 'bookSeries', nil )
if data.bookSeriesVolume or data.bookSeriesIssue then
result = result .. '; '
local letter_vol = i18nVolume[ lang ] or i18nVolume[ i18nDefaultLanguage ]
local letter_iss = i18nIssue[ lang ] or i18nIssue[ i18nDefaultLanguage ]
if data.bookSeriesVolume then
result = result .. appendProperty( lang, data, letter_vol .. ' ', 'bookSeriesVolume', nil )
result = result .. appendProperty( lang, data, ', ' .. letter_iss .. ' ', 'bookSeriesIssue', nil )
else
result = result .. appendProperty( lang, data, letter_iss .. ' ', 'bookSeriesIssue', nil )
end
end
result = result .. ').'
return result
end
---@param lang string
---@param data source
---@return string
local function appendTirage( lang, data )
if not data.tirage then
return ''
end
local tirageTemplate = i18nTirage[ lang ] or i18nTirage[ i18nDefaultLanguage ]
---@type options
local optionsTirage = {
separator = '; ',
conjunction = '; ',
format = function( _data ) return tostring( mw.ustring.format( tirageTemplate, _data ) ) end,
short = false,
nolinks = false,
preferids = false,
}
return ' — ' .. asString( lang, data.tirage, optionsTirage )
end
---@param lang string
---@param value string | nil
---@param options options
---@param prefix string?
---@return string
local function appendIdentifier( lang, value, options, prefix )
if not value then
return ''
end
return ' — ' .. ( prefix or '' ) .. asString( lang, value, options )
end
---@param result string
---@param lang string
---@param data source
---@return string
local function wrapSourceId( result, lang, data )
if not data.sourceId then
return result
end
local citeType = data.type and asString( lang, data.type, options_citetypes ) or 'citetype_unknown'
return '<span class="wikidata_cite ' .. citeType .. '" data-entity-id="' .. data.sourceId .. '">' .. result .. '</span>'
end
---@param data source
---@return string
local function appendAccessDate( data )
if not data.accessdate then
return ''
end
local date = getSingle( data.accessdate )
local pattern = "(%-?%d+)%-(%d+)%-(%d+)T"
local y, m, d = mw.ustring.match( date, pattern )
y, m, d = tonumber( y ), tonumber( m ), tonumber( d )
local date_str = ( d > 0 and ' ' .. tostring( d ) or '' )
.. ( m > 0 and ' ' .. monthGen[ m ] or '' )
.. ( y > 0 and ' ' .. tostring( y ) or '' )
return " <small>Проверено" .. date_str .. ".</small>"
end
---@param data source
---@param lang string
---@return void
local function populateUrl( data, lang )
if data.sourceId and not data.url then
local sitelink = getSitelink( data.sourceId, lang .. 'wikisource' )
if sitelink then
data.url = ':' .. lang .. ':s:' .. sitelink
end
end
end
---@param data source
---@return void
local function populateYear( data )
if not data.year and data.dateOfPublication then
local date = getSingle( data.dateOfPublication )
data.year = mw.ustring.sub( date, 2, 5 )
end
if not data.year and data.dateOfCreation then
local date = getSingle( data.dateOfCreation )
data.year = mw.ustring.sub( date, 2, 5 )
end
end
---@param data source
---@return void
local function populateTitle( data )
data.title = data.title or getSingle( data.url )
end
---@param data source
---@return string
local function renderSource( data )
local lang = getLangCode( data.lang ) or i18nDefaultLanguage
preprocessPlace( data, lang )
populateUrl( data, lang )
populateTitle( data )
if not data.title then
return ''
end
populateYear( data )
local result = generateAuthorLinks( lang, data )
result = result .. appendTitle( lang, data )
result = result .. appendLanguage( lang )
result = result .. appendSubtitle( lang, data )
result = result .. appendOriginalTitle( lang, data )
result = result .. appendPublication( lang, data )
result = result .. '<span class="wef_low_priority_links">'
result = result .. appendEditor( lang, data ) -- Might take current editor instead of actual. Use with caution
result = result .. appendEdition( lang, data )
result = result .. appendPublicationData( lang, data )
result = result .. appendVolumeAndIssue( lang, data )
result = result .. appendPages( lang, data )
result = result .. appendArticleID( lang, data )
result = result .. appendNumberOfPages( lang, data )
result = result .. appendBookSeries( lang, data )
result = result .. appendTirage( lang, data )
result = result .. appendIdentifier( lang, data.isbn, options_commas, 'ISBN ' )
result = result .. appendIdentifier( lang, data.issn, options_issn, 'ISSN ' )
result = result .. appendIdentifier( lang, data.doi, options_doi, nil )
result = result .. appendIdentifier( lang, data.pmid, options_pmid, nil )
result = result .. appendIdentifier( lang, data.bibcode, options_bibcode, nil )
result = result .. appendIdentifier( lang, data.arxiv, options_arxiv, nil )
result = result .. appendAccessDate( data )
result = result .. '</span>'
return wrapSourceId( result, lang, data )
end
---@param data source Данные в простом формате, согласованном с модулями формирования библиографического описания
---@param snaks snaks
---@return string | nil
local function renderReferenceImpl( data, snaks )
-- не показывать источники с "импортировано из"
if snaks.P143 then
return nil
end
-- забрать данные из reference
populateDataFromSnaks( snaks or {}, data, PROPERTY_MAP )
data.sourceId = getSingle( data.sourceId )
populateDataFromEntity( data.sourceId, data, PROPERTY_MAP )
expandSpecials( data )
populateSourceDataImpl( data.sourceId, data, PROPERTY_MAP )
expandPublication( data )
expandBookSeries( data )
if next( data ) == nil then
return nil
end
local rendered = renderSource( data )
if mw.ustring.len( rendered ) == 0 then
return nil
end
if data.ref then
local anchorValue = 'CITEREF' .. data.ref .. ( coalesce( { data[ 'ref-year' ], data.year } ) or '' )
rendered = '<span class="citation" id="' .. mw.uri.anchorEncode( anchorValue ) .. '">' .. rendered .. '</span>'
end
return rendered
end
---@param frame frame
---@param currentEntityId string | { id: string }
---@param reference table{ snaks: snaks }
---@return string | nil
function p.renderSource( frame, currentEntityId, reference )
reference = reference or { snaks = {} }
p.currentFrame = frame
local data = getFilledArgs( frame.args or {} )
populateDataFromSnaks( reference.snaks, data, PROPERTY_MAP )
data.sourceId = getSingle( data.sourceId )
if not currentEntityId then
data.entityId = mw.wikibase.getEntityIdForCurrentPage()
elseif type( currentEntityId ) == 'string' then
data.entityId = currentEntityId
elseif type( currentEntityId ) == 'table' and currentEntityId.id then
data.entityId = currentEntityId.id
end
---@type string
local rendered = renderReferenceImpl( data, reference.snaks or {} )
if not rendered then
return ''
end
return rendered
end
---@param frame frame
---@param currentEntityId string
---@param reference table
---@return string
function p.renderReference( frame, currentEntityId, reference )
local rendered = p.renderSource( frame, currentEntityId, reference )
if not rendered or rendered == '' then
return ''
end
-- Про выбор алгоритма хеширования см. [[Модуль:Hash]]. Знак подчёркивания в начале позволяет
-- исключить ошибку, когда имя сноски — чисто числовое значение, каковыми иногда бывают хеши.
return frame:extensionTag( 'ref', rendered, { name = '_' .. mw.hash.hashValue( 'fnv164', rendered ) } ) .. '[[Category:Википедия:Статьи с источниками из Викиданных]]'
end
---@param frame frame
---@return string | nil
function p.testPersonNameToAuthorName( frame )
return personNameToAuthorName( frame.args[ 1 ] )
end
---@param frame frame
---@return string | nil
function p.testPersonNameToResponsibleName( frame )
return personNameToResponsibleName( frame.args[ 1 ] )
end
return p
|
Index:
pl ar de en es fr it arz nl ja pt ceb sv uk vi war zh ru af ast az bg zh-min-nan bn be ca cs cy da et el eo eu fa gl ko hi hr id he ka la lv lt hu mk ms min no nn ce uz kk ro simple sk sl sr sh fi ta tt th tg azb tr ur zh-yue hy my ace als am an hyw ban bjn map-bms ba be-tarask bcl bpy bar bs br cv nv eml hif fo fy ga gd gu hak ha hsb io ig ilo ia ie os is jv kn ht ku ckb ky mrj lb lij li lmo mai mg ml zh-classical mr xmf mzn cdo mn nap new ne frr oc mhr or as pa pnb ps pms nds crh qu sa sah sco sq scn si sd szl su sw tl shn te bug vec vo wa wuu yi yo diq bat-smg zu lad kbd ang smn ab roa-rup frp arc gn av ay bh bi bo bxr cbk-zam co za dag ary se pdc dv dsb myv ext fur gv gag inh ki glk gan guw xal haw rw kbp pam csb kw km kv koi kg gom ks gcr lo lbe ltg lez nia ln jbo lg mt mi tw mwl mdf mnw nqo fj nah na nds-nl nrm nov om pi pag pap pfl pcd krc kaa ksh rm rue sm sat sc trv stq nso sn cu so srn kab roa-tara tet tpi to chr tum tk tyv udm ug vep fiu-vro vls wo xh zea ty ak bm ch ny ee ff got iu ik kl mad cr pih ami pwn pnt dz rmy rn sg st tn ss ti din chy ts kcg ve
Portal di Ensiklopedia Dunia