Модуль:External links/песочница
Файл:Sandbox.png |
Галилей, Галилео: Шаблон:Внешние ссылки/песочница
Лукницкий, Павел Николаевич: Шаблон:Внешние ссылки/песочница
Сергеев, Александр Михайлович (физик): Шаблон:Внешние ссылки/песочница
Жилберту, Аструд: Шаблон:Внешние ссылки/песочница
Лингвистика: Шаблон:Внешние ссылки/песочница
local data = require( 'Module:External links/data' ) -- Localizable part -- Please note that labels for websites and catalogs are taken from Wikidata (i.e. Wikidata label) -- Feel free to correct labels and categories here local categoryTemplateEmpty = 'Википедия:Шаблон «Внешние ссылки» пуст' local templateLink = 'Внешние ссылки' -- The language codes that should always be displayed even if they have normal rank and a claim with another language and preferred rank exists local preferredLanguage = 'Q7737' -- russian local templateColorName = 'цвет' -- Some projects have "named" colors, defined by templates local function colorByTitle( frame, colorTitle ) local templateName = 'Цвет/' .. colorTitle local templateTitle = mw.title.makeTitle( 'Template', templateName ) if not templateTitle or not templateTitle.exists then return false end return frame:expandTemplate{ title = templateName } end -- Non-localizable part (not need to localize ) local moduleNavbox = require( 'Module:Navbox' ) local moduleLanguages -- accessed if necessary local propertyQualifiers = { P553 = { P554 = 'url', }, P1343 = { P805 = 'iw', P248 = 'iw', -- deprecated, fallback for P805 P953 = 'url', P854 = 'url', -- deprecated, fallback for P953 }, } local p = {} -- Helper functions local function replace( str, pattern, repl ) pattern = mw.ustring.gsub( pattern, "[%(%)%.%+%-%*%?%[%]%^%$%%]", "%%%1" ) -- escape pattern repl = mw.ustring.gsub( repl, "[%%]", "%%%%" ) -- escape replacement repl = mw.ustring.gsub( repl, " ", "%%%%20" ) -- escape replacement return mw.ustring.gsub( str, pattern, repl ) end -- Render functions local function renderList( elements ) if #elements == 0 then return '' end return '*' .. table.concat( elements , '\n*' ) .. '\n' end local function renderLabel( params ) if type( params ) == 'string' then return params end local qid = params[ 1 ] local default = params[ 2 ] if #params >= 3 then local label = params[ 3 ] local link = mw.wikibase.sitelink( qid ) if link then return '[[' .. link .. '|' .. label .. ']]' end local title = mw.wikibase.label( qid ) or default return '<span title="' .. title .. '" style="border-bottom: 1px dotted; cursor: help;">' .. label .. '</span>' end return mw.wikibase.label( qid ) or default end local function renderLink( resourceData, label, formatter, idAsLabel ) if resourceData.itemId == nil then return '<span class="error">' .. label .. ': Не удаётся определить элемент</span>[[Категория:Статьи с ошибкой в шаблоне Внешние ссылки]]' end local link if not formatter then link = resourceData.itemId idAsLabel = false elseif type( formatter ) == 'string' then link = replace( formatter, '$1', resourceData.itemId ) elseif type ( formatter ) == 'function' then link = formatter( resourceData.itemId, resourceData.qualifiers ) end -- "Label: ID" without link if not link or link == '' then return renderLabel( label ) .. ': ' .. resourceData.itemId end local resourceLabel = resourceData.itemId if not idAsLabel then resourceLabel = renderLabel( label ) end local linkFirstChar = mw.ustring.sub( link, 1, 1 ) if linkFirstChar == ':' then return '[[' .. link .. '|' .. resourceLabel .. ']]' end return '[' .. link .. ' ' .. resourceLabel .. ']' end local function renderRef( languages ) local result = '' if languages and #languages > 0 then if moduleLanguages ~= false then -- not false, but maybe nil if mw.title.makeTitle( 'Module', 'Languages' ).exists and mw.title.makeTitle( 'Module', 'Languages/data' ).exists and mw.title.makeTitle( 'Module', 'Wikidata/Language-codes' ).exists then moduleLanguages = require( 'Module:Languages' ) else moduleLanguages = false end end if moduleLanguages then for langIndex, language in pairs( languages ) do result = result .. ' ' .. moduleLanguages.getRefHtml( language ) end end end return result end local function renderLinkWithRef( resourceData, label, formatter, idAsLabel ) local link = renderLink( resourceData, label, formatter, idAsLabel ) if link ~= '' then link = link .. renderRef( resourceData.languages ) end return link end -- Data fetching functions local function getValueFromSnak( snak ) if snak.datavalue.type == 'wikibase-entityid' then return snak.datavalue.value.id end if snak.datavalue.type == 'monolingualtext' then return snak.datavalue.value.text end return snak.datavalue.value end local function getQualifierSingleValue( statement, qualifierName ) if not statement or not statement.qualifiers or not statement.qualifiers[ qualifierName ] then return nil end for qualifierIndex, qualifier in pairs( statement.qualifiers[ qualifierName ] ) do if qualifier.datavalue and qualifier.datavalue.type and qualifier.datavalue.value then return getValueFromSnak( qualifier ) end end return nil end local function getQualifierValues( statement ) if not statement or not statement.qualifiers then return {} end local result = {} for qualifierName, qualifiers in pairs( statement.qualifiers ) do for _, qualifier in pairs( qualifiers ) do if qualifier.datavalue and qualifier.datavalue.type and qualifier.datavalue.value then if not result[ qualifierName ] then result[ qualifierName ] = {} end table.insert( result[ qualifierName ], getValueFromSnak( qualifier ) ) end end end return result end local function contains( tableStructure, value ) if not tableStructure or not value then return true end for index, line in pairs( tableStructure ) do if line == value then return true end end return false end local function filterByRank( resourceDatas ) -- itemId, languages. rank = rank local hasPreffered = false for index, resourceData in pairs( resourceDatas ) do if resourceData.rank == 'preferred' then hasPreffered = true end end if not hasPreffered then return resourceDatas end local result = {} for index, resourceData in pairs( resourceDatas ) do if resourceData.rank == 'preferred' or contains( resourceData.languages, preferredLanguage ) then table.insert( result, resourceData ) end end return result end local function getLinkData( statement, qualifier, project ) local rank = statement.rank or 'normal' if rank == 'deprecated' or not statement.mainsnak.datavalue then return nil end local itemId if qualifier then itemId = getQualifierSingleValue( statement, qualifier ) else itemId = statement.mainsnak.datavalue.value end if itemId and project then itemId = mw.wikibase.getSitelink( itemId, project ) end if not itemId then return nil end local qualifiers = getQualifierValues( statement ) local languages = qualifiers[ 'P407' ] if not languages then languages = {} end return { itemId = itemId, qualifiers = qualifiers, languages = languages, rank = rank, } end local function collectLinks( configuration, elementId, separateLabel ) -- Create rows local elements = {} local data = {} local item = mw.wikibase.getEntity( elementId ) if item == nil or item.claims == nil then return elements end for _, params in pairs( configuration ) do local resourceId = params[ 2 ] local pid = resourceId local qid if string.match( resourceId, '^P%d+:Q%d+$' ) then local parts = mw.text.split( resourceId, ':', true ) pid = parts[ 1 ] qid = parts[ 2 ] end local claims = item.claims[ pid ] or {} for _, statement in pairs( claims ) do local linkData if not qid then linkData = getLinkData( statement ) elseif getValueFromSnak( statement.mainsnak ) == qid then for qualifierId, qualifierType in pairs( propertyQualifiers[ pid ] ) do local project = nil if qualifierType == 'iw' then project = params.project end linkData = getLinkData( statement, qualifierId, project ) if linkData then break end end end if linkData then if not data[ resourceId ] then data[ resourceId ] = {} end table.insert( data[ resourceId ], linkData ) end end end for resourceId, resourceDatas in pairs( data ) do data[ resourceId ] = filterByRank( resourceDatas ) end for _, params in pairs( configuration ) do local label = params[ 1 ] local resourceId = params[ 2 ] local resourceDatas = data[ resourceId ] if resourceDatas ~= nil then local preitemId local links = {} for index, resourceData in pairs( resourceDatas ) do local itemId = resourceData.itemId if index == 2 then --даёт возможность поставить id из одного свойства в разные ссылки (что?) if itemId == preitemId then break end end if separateLabel then -- Label: ID1, ID2 table.insert( links, renderLinkWithRef( resourceData, '', params[ 3 ], true ) ) else -- Label · Label table.insert( elements, renderLinkWithRef( resourceData, label, params[ 3 ] ) ) end preitemId = resourceData.itemId end if separateLabel and #links then local result = renderLabel( params[ 1 ] ) .. ': ' .. table.concat( links, ', ' ) table.insert( elements, result ) end end end return elements end function p.render( frame ) local colorArg = '' local elementId = nil if frame ~= nil then local parentArgs = frame:getParent().args colorArg = parentArgs[ templateColorName ] or parentArgs[ 'color' ] or parentArgs[ 1 ] or '' if parentArgs[ 'from' ] and parentArgs[ 'from' ] ~= '' then elementId = string.upper( parentArgs[ 'from' ] ) elseif parentArgs[ 'd' ] and parentArgs[ 'd' ] ~= '' then elementId = string.upper( parentArgs[ 'd' ] ) end if colorArg ~= '' then local firstChar = mw.ustring.sub( colorArg, 1, 1 ) if firstChar ~= '#' then local byTemplate = colorByTitle( frame, colorArg ) if byTemplate then colorArg = byTemplate end end end end local navboxData = { name = 'External links', navboxclass = 'navbox ruwikiArticleExternalLinksTable', bodyclass = 'hlist', } if colorArg and colorArg ~= '' then navboxData.groupstyle = 'background: ' .. colorArg .. ';' end local rowIndex = 1 for _, groupData in pairs( data ) do local isAuthorityControl = groupData.hider local groupLabel = groupData.label local groupList = groupData.list local groupElements = collectLinks( groupList, elementId, isAuthorityControl ) if #groupElements > 0 then navboxData[ 'group' .. rowIndex ] = groupLabel navboxData[ 'list' .. rowIndex ] = renderList( groupElements ) if isAuthorityControl then local groupExtElements = collectLinks( groupData.ext, elementId, true ) navboxData['list' .. rowIndex] = navboxData['list' .. rowIndex] .. renderList( groupExtElements ) if #groupElements > 5 then navboxData[ 'group' .. rowIndex ] = nil local templateStyles = frame:extensionTag{ name = 'templatestyles', args = { src = 'Шаблон:Навигационная таблица/styles.css' } } local collapsibleNavbox = moduleNavbox._navbox( { title = groupLabel, list1 = navboxData['list' .. rowIndex], border = 'subgroup', navbar = 'plain', state = 'collapsed', titleclass = 'ts-navbox-plaintitle', bodyclass = 'authoritycontrol', titlestyle = navboxData.groupstyle, bodystyle = 'text-align: left;', } ) navboxData[ 'list' .. rowIndex ] = templateStyles .. collapsibleNavbox end end rowIndex = rowIndex + 1 end end if rowIndex == 1 then if mw.title.getCurrentTitle().namespace == 0 then return '[[Category:' .. categoryTemplateEmpty .. ']]' end return '' end local tnavbar = frame:expandTemplate{ title = 'tnavbar-view', args = { templateLink } } if navboxData[ 'group1' ] then navboxData[ 'group1' ] = '<div style="padding: 0 18px 0 0; width: 100%;">' .. '<div style="float: left;">' .. tnavbar .. '</div> ' .. navboxData[ 'group1' ] .. '</div>' else navboxData[ 'group1' ] = '<div style="padding: 0; width: 100%;">' .. tnavbar .. '</div>' end return moduleNavbox._navbox( navboxData ) end -- Documentation functions local function renderDocumentationLine( params ) local result = '' local resourceLabel = renderLabel( params[ 1 ] ) local pid = params[ 2 ] local qid if string.match( pid, '^P%d+:Q%d+$' ) then local parts = mw.text.split( pid, ':', true ) pid = parts[ 1 ] qid = parts[ 2 ] end result = result .. '| ' .. resourceLabel .. '\n' result = result .. '| [[:d:Property:' .. pid .. '|' .. pid .. ']]' if qid then result = result .. ' = [[:d:' .. qid .. '|' .. qid .. ']]' end result = result .. '\n' result = result .. '|-\n' return result end function p.renderDocumentation() local result = '' for _, groupData in pairs( data ) do local groupLabel = groupData.label local groupList = groupData.list result = result .. '|-\n' result = result .. '! colspan=2 | ' .. groupLabel .. '\n' result = result .. '|-\n' for _, linkParams in pairs( groupList ) do result = result .. renderDocumentationLine( linkParams ) end end return result end return p