יחידה:תבנית מידע
מראה
ניתן ליצור תיעוד על היחידה הזאת בדף יחידה:תבנית מידע/תיעוד
local propertyLink = require('Module:PropertyLink')
local WikidataCrossValidation = require('Module:WikidataCrossValidation')
local Infobox = {}
function Infobox:new()
local o = {
args={},
templateStructure={},
isSelfUse=false,
autoDocumentation=false,
wikidataCats= {},
root = mw.html.create('table')
}
setmetatable(o, self)
self.__index = self
return o
end
function Infobox:render()
if self.isSelfUse then
local templateDocumentation=''
for k,v in pairs(self.templateParams) do
if mw.ustring.match( k, '-ויקינתונים') then
templateDocumentation = templateDocumentation .. '[[קטגוריה:תבניות שמשתמשות בוויקינתונים]]'
break
end
end
if self.autoDocumentation then
templateDocumentation = templateDocumentation .. self:_generateDocumentation()
end
return self:renderInfobox() .. templateDocumentation
end
return self:renderInfobox() .. table.concat(self.wikidataCats, '')
end
--[[
Generate auto documentation for template.
]]
function Infobox:_generateDocumentation()
local labelDataPrefix = 'תווית-מידע'
local parameters = {}
for k,v in pairs(self.templateParams) do
if mw.ustring.match( tostring(k),'תווית%-מידע%d' ) then
table.insert(parameters, '"'..string.gsub(v, '"', '\\"')..'":'..'{ "description": ""}')
else
for mm in mw.ustring.gmatch( tostring(v),'%{%{%{(.-)[%}|]') do
table.insert(parameters, '"'..string.gsub(mm, '"', '\\"')..'":'..'{ "description": ""}')
end
end
end
local templateDoc = '{ "params": { '..table.concat(parameters,'\n,')..'}}'
return frame:extensionTag( 'templatedata', templateDoc )
end
--[[
Renders the infobox title
]]
function Infobox:renderTitle()
-- renders the title
local titleCaption = self.root
:tag('caption')
:addClass(self.args.titleclass)
:cssText(self.args.titlestyle)
:wikitext(self.args.title)
if self.args.subtitle and self.args.subtitle~=nil and #(self.args.subtitle)>0 then
local row = self.root:tag('tr')
:tag('th')
:attr('colspan', 2)
:css('text-align','center')
:cssText(self.args.subtitlestyle)
:addClass(self.args.subtitleclass)
:wikitext(self.args.subtitle)
end
return self.titleCaption
end
--[[
Renders the right/left images (possibly 1/2/none of them available) and the main image
]]
function Infobox:renderImages()
-- render right an left images
self.args.rightImage = self.args.rightImage~=nil and #(self.args.rightImage)>0 and self.args.rightImage
self.args.leftImage = self.args.leftImage~=nil and #(self.args.leftImage)>0 and self.args.leftImage
if self.args.rightImage or self.args.leftImage then
if self.args.rightImageDesc~=nil and #(self.args.rightImageDesc)>0 then
self.args.rightImage = self.args.rightImage..'<div>' .. self.args.rightImageDesc .. '</div>'
end
if self.args.leftImageDesc~=nil and #(self.args.leftImageDesc)>0 then
self.args.leftImage = self.args.leftImage .. '<div>' .. self.args.leftImageDesc .. '</div>'
end
local row = self.root:tag('tr')
:tag('td')
:attr('colspan', 2)
:css('text-align','center')
if self.args.rightImage and self.args.leftImage then
row:tag('table')
:css('width','100%')
:tag('tr')
:tag('td')
:css('width','50%')
:css('vertical-align','middle')
:css('text-align','center')
:wikitext(self.args.rightImage)
:tag('td')
:css('width','50%')
:css('vertical-align','middle')
:css('text-align','center')
:wikitext(self.args.leftImage)
:done()
else
row:wikitext(self.args.leftImage or self.args.rightImage)
end
end
-- render the main image
if self.args.image then
self.root:tag('tr')
:tag('td')
:attr('colspan', 2)
:css('text-align','center')
:wikitext(self.args.image)
if self.args.imageDesc and #self.args.imageDesc>0 then
self.root:tag('tr')
:tag('td')
:attr('colspan', 2)
:addClass('thumbcaption')
:addClass('borderless')
:css('text-align','center')
:wikitext(self.args.imageDesc)
end
end
end
--[[
Adds edit links for easier editing of the template. If the template use data from wikidata it also adds edit link in Wikidata
]]
function Infobox:renderEditLinks()
local wbEdit='' -- link to wikidata
if self.args.usingWikidata then
local entityId = mw.wikibase.getEntityIdForCurrentPage()
wbEdit = '[[File:Wikidata-logo S.svg|22px|link=d:'..entityId..'|לעריכה בוויקינתונים שמשמש מקור לחלק מהמידע בתבנית]]'
wbEdit = wbEdit .. mw.ustring.format(' [[File:OOjs UI icon info big.svg|16px|link=%s]]', 'עזרה:תבנית מידע')
end
if #wbEdit > 0 then
self.root:tag('tr')
:tag('td')
:attr('colspan', 2)
:css('text-align','left')
:wikitext(wbEdit)
end
end
--[[
Adds a styled row to the table
]]
function Infobox:addRow(rowArgs)
-- Adds a row to the infobox, with either a header cell
-- or a label/data cell combination.
if rowArgs.header then
self.root
:tag('tr')
:addClass(rowArgs.rowclass)
:cssText(self.args.rowsstyle)
:cssText(rowArgs.rowstyle)
:attr('id', rowArgs.rowid)
:tag('th')
:attr('colspan', 2)
:attr('id', rowArgs.headerid)
:addClass(rowArgs.class)
:addClass(self.args.headerclass)
:css('text-align', 'center')
:cssText(self.args.headerstyle)
:cssText(rowArgs.headerstyle)
:newline()
:wikitext(rowArgs.header)
elseif rowArgs.data and #(rowArgs.data) > 0 then
local row = self.root:tag('tr')
row:addClass(rowArgs.rowclass)
:cssText(self.args.rowsstyle)
:cssText(rowArgs.rowstyle)
:attr('id', rowArgs.rowid)
if rowArgs.label then
row
:tag('th')
:attr('scope', 'row')
:attr('id', rowArgs.labelid)
:css('text-align', 'right')
:cssText(self.args.labelstyle)
:cssText(rowArgs.labelstyle)
:newline()
:wikitext(rowArgs.label)
:done()
end
local dataCell = row:tag('td')
if not rowArgs.label then
dataCell
:attr('colspan', 2)
if not rowArgs.datastyle then
dataCell:css('text-align', 'center')
end
end
dataCell
:attr('id', rowArgs.dataid)
:addClass(rowArgs.class)
:cssText(self.args.datastyle)
:cssText(rowArgs.datastyle)
:newline()
:wikitext(rowArgs.data)
end
end
--[[
This function removes redundent keys from templateStructure: nil entries and header entries with no data
]]
function Infobox:removeEmptyHeaders()
local lastHeaderIndex=nil
local removeFirstHeader = (not self.args.image or #self.args.image==0) -- remove the first header if there is no image
local tempTemplateStructure = {}
for i,v in pairs(self.templateStructure) do
if v~=nil then
if v.header then
lastHeaderIndex = i
else
if lastHeaderIndex then
if not removeFirstHeader then
table.insert(tempTemplateStructure, self.templateStructure[lastHeaderIndex])
end
lastHeaderIndex = nil
end
removeFirstHeader = false
table.insert(tempTemplateStructure, v)
end
end
end
self.templateStructure=tempTemplateStructure
end
--[[
This function builds the infobox table using structure templateStructure and args
]]
function Infobox:renderInfobox()
self:removeEmptyHeaders()
-- error if there is no data/structure given to template from wiki page or wikidata
if ((#self.templateStructure)==0) and not self.args.subtemplate then
local templateTitle = mw.getCurrentFrame():getParent():getTitle()
errors = {}
local templateName = mw.ustring.gsub(templateTitle, 'תבנית:', '', 1)
if mw.title.getCurrentTitle().namespace==0 then
table.insert(errors, '[[קטגוריה:שגיאות פרמטריות בתבנית '..templateName..']]')
table.insert(errors, '[[קטגוריה:שגיאות פרמטריות בתבנית מידע]]')
table.insert(errors, '[[קטגוריה:שגיאות פרמטריות]]' )
else
table.insert(errors, '[[קטגוריה:שגיאות פרמטריות מחוץ למרחב הערכים]]')
end
local report = 'תבנית ריקה מתוכן. יש להזין פרמטרים בערך או בוויקינתונים. ' .. table.concat(errors, '')
local ParamValidator = require('Module:ParamValidator')
return ParamValidator.wrapReport(report, templateName, {})
end
-- sub infobox
if self.args.subtemplate then
self.root:cssText(self.args.tablestyle):css('width', '100%'):css('line-height', '1.4em')
else
self.root:addClass('infobox'):css('width', '18em'):cssText(self.args.tablestyle)
end
if self.args.tableclass then
self.root:addClass(self.args.tableclass)
end
if self.args.title ~='-' then
self:renderTitle()
end
self:renderImages()
local infobox_rows={}
for k,v in pairs(self.templateStructure) do
self:addRow(v)
end
if self.args.title ~= '-' then
self:renderEditLinks()
end
return tostring(self.root)
end
--[[
This function adds image using valueArg, or if not specified by the user tries to get image from wikidata using property
]]
function getValueOrWikidataImage(valueArg, wikidataArg, width, imgDesc)
if valueArg and #valueArg>0 then
if valueArg == '-' then
return nil
else
if not mw.ustring.match(valueArg, '^ *%[%[') and
not mw.ustring.match(valueArg, '^ *%[%[') and
not mw.ustring.match(valueArg, '^ *<') then
local imgSuffix = '|220px'
if imgDesc~=nil and #imgDesc>0 then
imgSuffix = imgSuffix .. '|' .. imgDesc
end
imgSuffix = imgSuffix .. ']]'
if mw.ustring.match(valueArg, '^[Ff]ile:') or
mw.ustring.match(valueArg, '^[Ii]mage:') or
mw.ustring.match(valueArg, '^קובץ:') or
mw.ustring.match(valueArg, '^תמונה:') then
valueArg = '[[' .. valueArg .. imgSuffix
else
valueArg = '[[File:' .. valueArg .. imgSuffix
end
end
return valueArg
end
end
if wikidataArg then
return propertyLink.getImageLink(wikidataArg, width)
end
return ''
end
function splitMaintainceCategory(value)
local maintainceCats = nil
local hasData = #(mw.ustring.gsub(value, '%[%[קטגוריה:.-%]%]', ''))>0
if not hasData then
maintainceCats = value
end
return hasData, maintainceCats
end
function getProperty( propertyName, allowMulti, allowNA, entityId, multiSeperator, optionalQualifier, genderAware )
local res = propertyLink.getProperty(propertyName, allowMulti, allowNA, entityId, multiSeperator, optionalQualifier, genderAware)
if res then
local missingTranslation = mw.ustring.find(res, '%[%[קטגוריה:ויקינתונים:ערכים_חסרי_תווית_בעברית%]%]')
local link = 'd:'..mw.wikibase.getEntityIdForCurrentPage().. '#'..propertyName
if not missingTranslation then
res = res .. mw.ustring.format(' [[File:Blue pencil RTL.svg|15px|link=%s|עריכת הנתון בוויקינתונים]]', link)
--else
--res = res .. mw.ustring.format('[[%s|חסר תרגום]] [[File:Red pencil RTL.svg|15px|link=%s|חסר תרגום בוויקינתונים]]', link, link)
end
end
return res
end
--[[
This function fills missing parameter using wikidata
]]
function fillMissingParamFromWikidata(missingParam, templateParams, templateArg, frame)
local inWikidata = false
local hasData=false
local maintainceCats = nil
local propertyName = nil
if templateParams[missingParam..'-ויקינתונים'] then
templateArg.data = getProperty(templateParams[missingParam..'-ויקינתונים'], false, false, nil, nil, templateParams[missingParam..'-ויקינתונים-פרטים']) or nil
inWikidata = templateArg.data and #(templateArg.data)>0
elseif templateParams[missingParam..'-ויקינתונים-מרובה'] then
local genderAware = templateParams[missingParam..'-ויקינתונים-מגדר'] == 'כן'
templateArg.data = getProperty(templateParams[missingParam..'-ויקינתונים-מרובה'], true, false, nil, templateParams[missingParam..'-ויקינתונים-מרובה-הפרדה'], templateParams[missingParam..'-ויקינתונים-פרטים'], genderAware) or nil
inWikidata = templateArg.data and #(templateArg.data)>0
elseif templateParams[missingParam..'-ויקינתונים-פשוט'] then
-- use data should be taken from wikidata and link must not be added
local wikidataParamValue = propertyLink.getLabel(templateParams[missingParam..'-ויקינתונים-פשוט'])
if wikidataParamValue and #wikidataParamValue>0 then
templateArg.data = frame:preprocess(mw.ustring.gsub(templateArg.data, '\{\{\{('..missingParam..')\}\}\}', wikidataParamValue))
inWikidata = true
end
elseif missingParam == 'קואורדינטות' then
templateArg.data = frame:expandTemplate{ title = 'קואורדינטות מוויקינתונים', args = { display = 'title,inline' } }
inWikidata = templateArg.data and #(templateArg.data)>0
end
if inWikidata then
hasData, maintainceCats = splitMaintainceCategory(templateArg.data)
if not hasData then
inWikidata = false
maintainceCats = maintainceCats
end
end
return inWikidata, maintainceCats
end
--[[
This function fills missing parameter using wikidata
]]
function crossValidateWikidata(missingParam, templateParams, templateArg, frame)
local matching = nil
local propertyName
if missingParam==nil then
return nil
end
if templateParams[missingParam..'-ויקינתונים'] then
propertyName = templateParams[missingParam..'-ויקינתונים']
matching = WikidataCrossValidation.crossValidate(templateArg.data, propertyName)
elseif templateParams[missingParam..'-ויקינתונים-מרובה'] then
local genderAware = templateParams[missingParam..'-ויקינתונים-מגדר'] == 'כן'
propertyName = templateParams[missingParam..'-ויקינתונים-מרובה']
matching = WikidataCrossValidation.crossValidate(templateArg.data, propertyName)
end
if matching then
return WikidataCrossValidation.maintainceCategory(matching, propertyName)
end
end
function Infobox:parseArgs(frame)
local DEFAULT_IMAGE_PROPERTY = 'P18'
local templateParams = frame.args
local templateArgs = frame:getParent().args
local args={}
local templateStructure = {}
args.title = frame.args['כותרת תבנית']
args.titlestyle = frame.args['כותרת תבנית-עיצוב']
args.titleclass = frame.args['כותרת תבנית-מחלקה']
args.subtitle = frame.args['תת כותרת תבנית']
args.subtitlestyle = frame.args['תת כותרת תבנית-עיצוב']
args.subtitleclass = frame.args['תת כותרת תבנית-מחלקה']
args.rightImage = getValueOrWikidataImage(frame.args['תמונה ימין'], frame.args['תמונה ימין-ויקינתונים'], '100')
args.rightImageDesc = frame.args['כיתוב ימין']
args.leftImage = getValueOrWikidataImage(frame.args['תמונה שמאל'], frame.args['תמונה שמאל-ויקינתונים'], '100')
args.leftImageDesc = frame.args['כיתוב שמאל']
args.imageDesc = frame.args['כיתוב']
args.image = getValueOrWikidataImage(frame.args['תמונה'], frame.args['תמונה-ויקינתונים'] or 'P18', '250', args.imageDesc)
args.headerclass = frame.args['כותרת-מחלקה']
args.headerstyle = frame.args['כותרת-עיצוב']
args.rowsstyle = frame.args['שורה-עיצוב']
args.labelstyle = frame.args['תווית-עיצוב']
args.datastyle = frame.args['מידע-עיצוב']
args.tablestyle = frame.args['טבלה-עיצוב']
args.tableclass = frame.args['טבלה-מחלקה']
args.subtemplate = frame.args['תת-תבנית']
local isSelfUse = (mw.title.getCurrentTitle().namespace==10)
self.autoDocumentation = frame.args['תיעוד-אוטומטי']
local labelPrefix = 'תווית'
local dataPrefix = 'מידע'
local subheader = 'כותרת'
local labelDataPrefix = 'תווית-מידע'
local rowStylePrefix = 'עיצוב-שורה'
local rowStyleClassPrefix = 'מחלקה-שורה'
local styleSuffix = '-עיצוב'
local k=0
local processedParams = {['0']=1} -- param0 may be used by Lua, not be template
local wikidataCats = {}
for k,v in pairs(templateParams) do
local i= string.match(k, '.-([0-9]+)$')
if i and not (processedParams[i]) then
indic = tonumber(i)
processedParams[i]=1
local subHeaderName = templateParams[subheader..i]
if subHeaderName and #subHeaderName>0 then --subheader type
table.insert(templateStructure, {header=subHeaderName,rowstyle=templateParams[rowStylePrefix..i], rowclass=templateParams[rowStyleClassPrefix..i], headerstyle=templateParams[subheader..i..styleSuffix], indic=indic})
else
local labelName = templateParams[labelPrefix..i]
local dataTemplate = templateParams[dataPrefix..i]
if dataTemplate then
-- if parameter contains only category with no value, replace with with nil and add teh value to maintaince category
local hasData, maintainceCats = splitMaintainceCategory(dataTemplate)
if maintainceCats and not hasData then
table.insert(wikidataCats, maintainceCats)
dataTemplate=nil
end
end
if labelName and dataTemplate then
--label: data type
table.insert(templateStructure, {label=labelName, data=dataTemplate, rowstyle=templateParams[rowStylePrefix..i], rowclass=templateParams[rowStyleClassPrefix..i], datastyle=templateParams[dataPrefix..i..styleSuffix],
labelstyle=templateParams[labelPrefix..i..styleSuffix], indic=indic})
elseif labelName and not dataTemplate then
--skip it. no only label [use subheader]
elseif not labelName and dataTemplate then
--only data type
table.insert(templateStructure, {data=dataTemplate, rowstyle=templateParams[rowStylePrefix..i], rowclass=templateParams[rowStyleClassPrefix..i], datastyle=templateParams[dataPrefix..i..styleSuffix], indic=indic})
else
local label_data_names = templateParams[labelDataPrefix..i]
if label_data_names then
labelName = label_data_names
label_data_names = mw.text.trim(label_data_names, '%[%]')
if templateArgs[label_data_names] and #templateArgs[label_data_names]>0 then
dataTemplate = templateArgs[label_data_names]
else
dataTemplate = '{{{' ..label_data_names.. '}}}'
end
table.insert(templateStructure, {label=labelName, data=dataTemplate, rowstyle=templateParams[rowStylePrefix..i], rowclass=templateParams[rowStyleClassPrefix..i], datastyle=templateParams[dataPrefix..i..styleSuffix],
labelstyle=templateParams[labelPrefix..i..styleSuffix], indic=indic})
end
end
end
end
end
table.sort(templateStructure, function (x, y) return x.indic<y.indic end)
-- use wikidata / remove unused parameters
if not isSelfUse then
local entriesToRemove = {}
for k,v in pairs(templateStructure) do
if v.data then
-- remove parameters that were explicitly defined to be removed
local ignoreParam = mw.ustring.match(v.data, '^%-$')
if ignoreParam then
table.insert(entriesToRemove, 1, k)
else
-- otherwise if the template isn't full - try to use wikidata to fill it
local m = mw.ustring.match(v.data, '\{\{\{(.-)\}\}\}')
if m then
m = mw.uri.decode( m ) -- some templates may add encoding and are preprocessed before
local inWikidata, maintainceCats = fillMissingParamFromWikidata(m, templateParams, v, frame)
if maintainceCats then
table.insert(wikidataCats, maintainceCats)
end
-- if data isn't available remove it
if inWikidata then
args.usingWikidata = true
else
table.insert(entriesToRemove, 1, k)
end
else
local maintainceCats = crossValidateWikidata(v.label,templateParams, v, frame)
if maintainceCats and #maintainceCats>0 then
table.insert(wikidataCats, maintainceCats)
end
end
end
end
end
for k,v in pairs(entriesToRemove) do table.remove(templateStructure, v) end
-- use wikidata in title
if args.title then
local m = mw.ustring.match(args.title, '\{\{\{(.-)\|?\}\}\}')
if m then
local inWikidata = false
if templateParams[m..'-ויקינתונים'] then
local wikidataParamValue = getProperty(templateParams[m..'-ויקינתונים']) or nil
if wikidataParamValue then
args.title = wikidataParamValue
end
elseif templateParams[m..'-ויקינתונים-פשוט'] then
-- use data should be taken from wikidata and link must not be added
local wikidataParamValue = propertyLink.getLabel(templateParams[m..'-ויקינתונים-פשוט'])
if wikidataParamValue then
args.title = frame:preprocess(mw.ustring.gsub(args.title, '\{\{\{('..m..')\|?\}\}\}', wikidataParamValue))
end
end
end
end
end
if args.title=='-' then
args.subtemplate = true
end
self.args = args
self.templateStructure = templateStructure
self.wikidataCats = wikidataCats
self.isSelfUse = isSelfUse
self.templateParams = templateParams
end
function infobox(frame)
local infoObj = Infobox:new()
infoObj:parseArgs(frame)
return infoObj:render()
end
return {
['מידע']=infobox,
Infobox=Infobox
}