Модуль:Wikidata: различия между версиями
/>Vlsergey (Новая страница: «Test») |
/>Vlsergey (Новая страница: «Test») |
||
Строка 18: | Строка 18: | ||
} | } | ||
local moduleSources = require('Module: | local moduleSources = require('Module:Sources') | ||
local p = {} | local p = {} | ||
Строка 54: | Строка 54: | ||
return '<span class="error">' .. i18n.errors[key] .. '</span>' | return '<span class="error">' .. i18n.errors[key] .. '</span>' | ||
end | end | ||
function formatStatements( options ) | function formatStatements( options ) | ||
--Get entity | --Get entity | ||
local entity = getEntityFromId( options.entityId ) | local entity = getEntityFromId( options.entityId ) | ||
Строка 86: | Строка 81: | ||
local formattedStatement = p.formatStatement( statement, options ) | local formattedStatement = p.formatStatement( statement, options ) | ||
if (formattedStatement) then | if (formattedStatement) then | ||
formattedStatement = '<span class="wikidata-claim" data-wikidata-claim-id="' .. statement.id .. '">' .. formattedStatement .. '</span>' | |||
table.insert( formattedStatements, formattedStatement ) | table.insert( formattedStatements, formattedStatement ) | ||
end | end | ||
Строка 126: | Строка 119: | ||
function formatStatement( statement, options, formatSnak, formatRefs ) | function formatStatement( statement, options, formatSnak, formatRefs ) | ||
if ( options.references ) then | if ( options.references ) then | ||
return formatSnak( statement.mainsnak, options ) .. formatRefs( statement ); | return formatSnak( statement.mainsnak, options ) .. formatRefs( statement ); | ||
Строка 147: | Строка 137: | ||
local before = '<span class="wikidata-snak ' .. mainSnakClass .. '"' .. hash .. '>' | local before = '<span class="wikidata-snak ' .. mainSnakClass .. '"' .. hash .. '>' | ||
local after = '</span>' | local after = '</span>' | ||
if snak.snaktype == 'somevalue' then | if snak.snaktype == 'somevalue' then | ||
return before .. (options['somevalue'] or i18n['somevalue']) .. after; | return before .. (options['somevalue'] or i18n['somevalue']) .. after; | ||
Строка 165: | Строка 150: | ||
function formatGlobeCoordinate( value, options ) | function formatGlobeCoordinate( value, options ) | ||
if options['subvalue'] == 'latitude' then | if options['subvalue'] == 'latitude' then | ||
return value['latitude'] | return value['latitude'] | ||
Строка 237: | Строка 217: | ||
return formatGlobeCoordinate( datavalue.value, options ) | return formatGlobeCoordinate( datavalue.value, options ) | ||
elseif datavalue.type == 'quantity' then | elseif datavalue.type == 'quantity' then | ||
local value = string.gsub(datavalue.value['amount'], '^%+', '') | |||
local lang = mw.language.new( 'ru' ) | |||
return lang:formatNum( tonumber( value ) ) | |||
else | else | ||
return formatError( 'unknown-datavalue-type' ) | return formatError( 'unknown-datavalue-type' ) | ||
Строка 247: | Строка 229: | ||
if ( options.text and options.text ~= '' ) then | if ( options.text and options.text ~= '' ) then | ||
label = options.text | label = options.text | ||
end | end | ||
Строка 275: | Строка 249: | ||
function p.formatStatements( frame ) | function p.formatStatements( frame ) | ||
local args = frame.args | local args = frame.args | ||
Строка 283: | Строка 256: | ||
end | end | ||
local plain = toBoolean( frame.args.plain, false ); | |||
frame.args.references = toBoolean( frame.args.references, true ); | frame.args.references = toBoolean( frame.args.references, true ); | ||
if not frame.args.property then | |||
return formatError( 'property-param-not-provided' ) | |||
end | |||
if ( plain ) then | |||
return frame:callParserFunction( '#property', frame.args.property ); | |||
end | |||
g_frame = frame | |||
return formatStatements( frame.args ) | return formatStatements( frame.args ) | ||
end | end | ||
function p.formatRefs( statement ) | function p.formatRefs( statement ) | ||
local result = ''; | local result = ''; | ||
if ( statement.references ) then | if ( statement.references ) then | ||
for _, reference in pairs( statement.references ) do | for _, reference in pairs( statement.references ) do | ||
result = result .. | result = result .. moduleSources.renderReference( g_frame, reference ); | ||
end | end | ||
end | end | ||
return result | return result | ||
end | end | ||
return p | return p |
Версия от 20:25, 12 августа 2014
Внимание! Это один из самых используемых модулей. |
Этот модуль относится к критическим. У него очень много включений или он используется с подстановкой. Из-за опасности вандализма или ошибочного редактирования он был защищён. |
Используется в {{Wikidata}} (см. описания параметров там же). Настраивается при помощи Модуль:Wikidata/config.
Прежде чем вносить какие-либо изменения в данный модуль, просьба оттестировать их в /песочнице. Обратите внимание, что не всё корректно работает в песочнице.
Общие сведения
Функции данного модуля не предназначены для прямого вызова из шаблонов карточек или других модулей, не являющихся функциями расширения данного. Для вызова из шаблонов карточек используйте шаблон {{wikidata}} или один из специализированных шаблонов для свойств. Для вызова функций Викиданных предназначенных для отображения чаще всего достаточно вызова frame:expandTemplate{}
с вызовом шаблона, ответственного за отрисовку свойства. С другой стороны, вызов определённых функций модуля (в основном это касается getEntityObject()
) может в будущем стать предпочтительным. Данный Lua-функционал в любом случае стоит рассматривать как unstable с точки зрения сохранения совместимости на уровне кода (вместе с соответствующими функциями API для Wikibase Client).
Далее описывается внутренняя документация. Названия функций и параметров могут изменяться. При их изменении автор изменений обязан обновить шаблон {{wikidata}} и специализированные шаблоны свойств. Изменения в других местах, если кто-то всё-таки вызывает функции модуля напрямую, остаются на совести автора «костыля». Итак, при вызове шаблона {{wikidata}} или специализированного шаблона свойства управление отдаётся на функцию formatStatements, которая принимает frame. Из frame достаются следующие опции, которые так или иначе передаются в остальные функции:
plain
— булевый переключатель (по умолчанию false). Если true, результат совпадает с обычным вызовом{{#property:pNNN}}
(по факту им и будет являться)references
— булевый переключатель (по умолчанию true). Если true, после вывода значения параметра дополнительно выводит ссылки на источники, указанные в Викиданных. Для вывода используется Модуль:Sources. Обычно отключается для тех свойств, которые являются «самоописываемыми», например, внешними идентификаторами или ссылками (когда такая ссылка является доказательством своей актуальности), например, идентификаторы IMDb.value
— значение, которое надо выводить вместо значений из Викиданных (используется, если что-то задано уже в карточке в виде т. н. локального свойства)
По умолчанию модуль поддерживает вывод следующих значений без дополнительных настроек:
- географические координаты (coordinates)
- количественные значения (quantity)
- моноязычный текст (monolingualtext)
- строки (string)
- даты (time)
Остальные типы данных требуют указания функции форматирования значения.
Кастомизация
Поддерживаются три типа параметров-функций, которые дополнительно указывают, как надо форматировать значения:
property-module
,property-function
— название модуля и функции модуля, которые отвечают за форматирование вывода массива значений свойства (statements, claims) с учётом квалификаторов, ссылок и прочего. Например, оформляет множество выводов в таблицу или график. Характерные примеры:- вывод таблицы и графика населения в {{wikidata/Population}} и Модуль:Wikidata/Population.
- Спецификация функции:
function p.…( context, options )
, поведение по умолчанию: Модуль:Wikidata#formatPropertyDefault.
claim-module
,claim-function
— название модуля и функции модуля, которые отвечают за форматирование вывода значения свойства (statement, claim) с учётом квалификаторов, ссылок и прочего. Может, например, дополнительно к основному значению (main snak) вывести значения квалификаторов. Характерные примеры:- вывод вышестоящих административных единиц и страны в Модуль:Wikidata/Places;
- вывод авторов латинского названия и даты публикации в Модуль:Wikidata/Biology;
- вывод операционной системы и даты релиза в Модуль:Wikidata/Software;
- вывод количества и даты, на которую оно верно, в Модуль:Wikidata/number;
- Спецификация функции:
function p.…( context, statement )
value-module
,value-function
— название модуля и функции модуля, которые отвечают за форматирование значения (snak, snak data value), в зависимости от контекста, как значений свойства, так и значений квалификатора (если вызывается изclaim-module/claim-function
). Необходимо для изменения отображения свойства, например, генерации викиссылки вместо простой строки или даже вставки изображения вместо отображения имени файла изображения (так как ссылки на изображения хранятся как строки). Характерные примеры:- вывод ссылки на Викисклад в Модуль:Wikidata/media
- вывод ссылок на внешние сайты в Модуль:Wikidata/link
- Спецификация функции:
function p.…( value, options )
Заготовки функций
function p.formatSomeProperty( context, options )
local claims = context.selectClaims( options, options.property );
if claims == nil then
return ''
end
local formattedStatements = {}
for _, claim in ipairs( claims ) do
local formattedStatement = context.formatStatement( options, claim )
-- local formattedStatement = p.formatSomeStatement( context, options, claim )
if ( formattedStatement and formattedStatement ~= '' ) then
formattedStatement = context.wrapStatement( formattedStatement, options.property, claim.id )
table.insert( formattedStatements, formattedStatement )
end
end
return mw.text.listToText( formattedStatements, options.separator, options.conjunction )
end
Также см. код метода formatPropertyDefault
ниже, в нём присутствует больше проверок и работа параметрами вызова.
function formatSomeClaim( context, options, statement )
local circumstances = context.getSourcingCircumstances( statement );
options.qualifiers = statement.qualifiers;
local result = context.formatSnak( options, statement.mainsnak, circumstances );
if ( result and result ~= '' and options.references ) then
result = result .. context.formatRefs( options, statement );
end
return result;
end
Также см. код метода formatStatementDefault
ниже, в нём есть пример работы с квалификаторами.
function formatSomeValue( context, options, value )
return value;
end
Также см. код метода formatUrlSingle
в модуле Модуль:URL.
Context API
Этот раздел не завершён. |
Переменные
entity
frame
Методы
cloneOptions( options )
getSourcingCircumstances( statement )
formatProperty( options )
formatPropertyDefault( context, options )
formatSnak( options, snak, circumstances )
formatStatement( options, statement )
formatStatementDefault( context, options, statement )
formatRefs( options, statement )
formatValueDefault( context, options, value )
parseTimeBoundariesFromSnak( snak )
parseTimeFromSnak( snak )
selectClaims( options, propertyId )
wrapSnak( value, hash, attributes )
wrapStatement( value, propertyId, claimId, attributes )
wrapQualifier( value, qualifierId, attributes )
Функции для форматирования
property-function
- Wikidata/date::formatDateIntervalProperty
- Wikidata/Medals::formatProperty
- Wikidata/Software::formatVersionProperty
- Wikidata/P512::formatAcademicDegree
- Wikidata/number::formatPropertyWithMostRecentClaimAndIndicator
- Wikidata/number::formatColorIndex
claim-function
- Wikidata/Places::formatCountryClaimWithFlag
- Wikidata/Places::formatPlaceWithQualifiers
- Wikidata/item::formatEntityWithGenderClaim
- Wikidata/Biology::formatTaxonNameClaim
- Wikidata/item::applyDefaultTemplate
- Wikidata/date::formatDateOfBirthClaim
- Wikidata/date::formatDateOfDeathClaim
value-function
- Wikidata::extractCategory
- Wikidata/link::fromModule
- Wikidata/Medals::formatValue
- Wikidata/media::formatCommonsCategory
- Wikidata/Software::formatExtension
- Wikidata/number::formatRA
- Wikidata/number::formatDMS
- Wikidata/url::formatUrlValue
- Wikidata/url::formatLangRefs
См. также
- Модуль:Wikibase
- Независимые иноязычные аналоги:
local i18n = { ["errors"] = { ["property-param-not-provided"] = "Не дан параметр свойства", ["entity-not-found"] = "Сущность не найдена.", ["unknown-claim-type"] = "Неизвестный тип заявления.", ["unknown-snak-type"] = "Неизвестный тип снэка.", ["unknown-datavalue-type"] = "Неизвестный тип значения данных.", ["unknown-entity-type"] = "Неизвестный тип сущности.", ["unknown-claim-module"] = "Вы должны установить и claim-module, и claim-function.", ["unknown-value-module"] = "Вы должны установить и value-module, и value-function.", ["claim-module-not-found"] = "Модуль, на который указывает утверждение, не найден.", ["claim-function-not-found"] = "Функция, на которую указывает утверждение, не найдена.", ["value-module-not-found"] = "Модуль, на который указывает значение, не найден.", ["value-function-not-found"] = "Функция, на которую указывает значение, не найдена." }, ["somevalue"] = "", ["novalue"] = "" } local moduleSources = require('Module:Sources') local p = {} function toBoolean( valueToParse, defaultValue ) if ( valueToParse ) then if valueToParse == '' or valueToParse == 'false' or valueToParse == '0' then return false end return true end return defaultValue; end function getEntityFromId( id ) if id then return mw.wikibase.getEntity( id ) end return mw.wikibase.getEntity() end function getEntityIdFromValue( value ) local prefix = '' if value['entity-type'] == 'item' then prefix = 'q' elseif value['entity-type'] == 'property' then prefix = 'p' else return formatError( 'unknown-entity-type' ) end return prefix .. value['numeric-id'] end function formatError( key ) return '<span class="error">' .. i18n.errors[key] .. '</span>' end function formatStatements( options ) --Get entity local entity = getEntityFromId( options.entityId ) if not entity then return -- formatError( 'entity-not-found' ) end if (entity.claims == nil) or (not entity.claims[string.lower(options.property)]) then return '' --TODO error? end --Find if any statements are prefered local rank = 'normal' for i, statement in pairs( entity.claims[string.lower(options.property)] ) do if (statement.rank == 'preferred') then rank = 'preferred' break end end --Format statement and concat them cleanly local formattedStatements = {} for i, statement in pairs( entity.claims[string.lower(options.property)] ) do if (statement.rank == rank) then local formattedStatement = p.formatStatement( statement, options ) if (formattedStatement) then formattedStatement = '<span class="wikidata-claim" data-wikidata-claim-id="' .. statement.id .. '">' .. formattedStatement .. '</span>' table.insert( formattedStatements, formattedStatement ) end end end return mw.text.listToText( formattedStatements, options.separator, options.conjunction ) end function p.formatStatement( statement, options ) if not statement.type or statement.type ~= 'statement' then return formatError( 'unknown-claim-type' ) end local claim --Use the customize handler if provided if options['claim-module'] or options['claim-function'] then if not options['claim-module'] or not options['claim-function'] then return formatError( 'unknown-claim-module' ) end local formatter = require ('Module:' .. options['claim-module']) if formatter == nil then return formatError( 'claim-module-not-found' ) end local fun = formatter[options['claim-function']] if fun == nil then return formatError( 'claim-function-not-found' ) end claim = fun( statement, options, formatSnak, p.formatRefs ) else --Default formatter claim = formatStatement( statement, options, formatSnak, p.formatRefs ) end return claim end function formatStatement( statement, options, formatSnak, formatRefs ) if ( options.references ) then return formatSnak( statement.mainsnak, options ) .. formatRefs( statement ); else return formatSnak( statement.mainsnak, options ); end end function formatSnak( snak, options ) local hash = ''; local mainSnakClass = ''; if ( snak.hash ) then hash = ' data-wikidata-hash="' .. snak.hash .. '"'; else mainSnakClass = ' wikidata-main-snak'; end local before = '<span class="wikidata-snak ' .. mainSnakClass .. '"' .. hash .. '>' local after = '</span>' if snak.snaktype == 'somevalue' then return before .. (options['somevalue'] or i18n['somevalue']) .. after; elseif snak.snaktype == 'novalue' then return before .. (options['novalue'] or i18n['novalue']) .. after; elseif snak.snaktype == 'value' then return before .. formatDatavalue( snak.datavalue, options ) .. after; else return before .. formatError( 'unknown-snak-type' ) .. after; end end function formatGlobeCoordinate( value, options ) if options['subvalue'] == 'latitude' then return value['latitude'] elseif options['subvalue'] == 'longitude' then return value['longitude'] else local eps = 0.0000001 -- < 1/360000 local globe = '' -- TODO local lat = {} lat['abs'] = math.abs(value['latitude']) lat['ns'] = value['latitude'] >= 0 and 'N' or 'S' lat['d'] = math.floor(lat['abs'] + eps) lat['m'] = math.floor((lat['abs'] - lat['d']) * 60 + eps) lat['s'] = math.max(0, ((lat['abs'] - lat['d']) * 60 - lat['m']) * 60) local lon = {} lon['abs'] = math.abs(value['longitude']) lon['ew'] = value['longitude'] >= 0 and 'E' or 'W' lon['d'] = math.floor(lon['abs'] + eps) lon['m'] = math.floor((lon['abs'] - lon['d']) * 60 + eps) lon['s'] = math.max(0, ((lon['abs'] - lon['d']) * 60 - lon['m']) * 60) local coord = '{{coord' if (value['precision'] == nil) or (value['precision'] < 1/60) then -- по умолчанию с точностью до секунды coord = coord .. '|' .. lat['d'] .. '|' .. lat['m'] .. '|' .. lat['s'] .. '|' .. lat['ns'] coord = coord .. '|' .. lon['d'] .. '|' .. lon['m'] .. '|' .. lon['s'] .. '|' .. lon['ew'] elseif value['precision'] < 1 then coord = coord .. '|' .. lat['d'] .. '|' .. lat['m'] .. '|' .. lat['ns'] coord = coord .. '|' .. lon['d'] .. '|' .. lon['m'] .. '|' .. lon['ew'] else coord = coord .. '|' .. lat['d'] .. '|' .. lat['ns'] coord = coord .. '|' .. lon['d'] .. '|' .. lon['ew'] end coord = coord .. '|globe:' .. globe if options['display'] then coord = coord .. '|display=' .. options.display else coord = coord .. '|display=title' end coord = coord .. '}}' return g_frame:preprocess(coord) end end function formatDatavalue( datavalue, options ) --Use the customize handler if provided if options['value-module'] or options['value-function'] then if not options['value-module'] or not options['value-function'] then return formatError( 'unknown-value-module' ) end local formatter = require ('Module:' .. options['value-module']) if formatter == nil then return formatError( 'value-module-not-found' ) end local fun = formatter[options['value-function']] if fun == nil then return formatError( 'value-function-not-found' ) end return fun( datavalue.value, options ) end --Default formatters if datavalue.type == 'wikibase-entityid' then return formatEntityId( getEntityIdFromValue( datavalue.value ), options ) elseif datavalue.type == 'string' then return datavalue.value --TODO ids + media elseif datavalue.type == 'globecoordinate' then return formatGlobeCoordinate( datavalue.value, options ) elseif datavalue.type == 'quantity' then local value = string.gsub(datavalue.value['amount'], '^%+', '') local lang = mw.language.new( 'ru' ) return lang:formatNum( tonumber( value ) ) else return formatError( 'unknown-datavalue-type' ) end end function formatEntityId( entityId, options ) local label = mw.wikibase.label( entityId ) if ( options.text and options.text ~= '' ) then label = options.text end local link = mw.wikibase.sitelink( entityId ) if link then if label then return '[[' .. link .. '|' .. label .. ']]' else return '[[' .. link .. ']]' end end if label then return label end -- not good, but better than nothing return '[[d:' .. entityId .. '|' .. entityId .. ']]<span style="border-bottom: 1px dotted; cursor: help; white-space: nowrap" title="На Викиданных нет русской подписи к элементу. Вы можете помочь, указав русский вариант подписи.">?</span>[[Категория:ЭАНМ:Статьи со ссылками на элементы Викиданных без русской подписи]]'; end function p.formatStatements( frame ) local args = frame.args --If a value if already set, use it if args.value and args.value ~= '' then return args.value end local plain = toBoolean( frame.args.plain, false ); frame.args.references = toBoolean( frame.args.references, true ); if not frame.args.property then return formatError( 'property-param-not-provided' ) end if ( plain ) then return frame:callParserFunction( '#property', frame.args.property ); end g_frame = frame return formatStatements( frame.args ) end function p.formatRefs( statement ) local result = ''; if ( statement.references ) then for _, reference in pairs( statement.references ) do result = result .. moduleSources.renderReference( g_frame, reference ); end end return result end return p