Module:Artwork/core: Difference between revisions
From The Goon Show Depository
(correct "part_of" parameter) |
m (1 revision imported) |
(No difference)
|
Latest revision as of 16:34, 23 October 2022
--[[
__ __ _ _ _ _ _ __
| \/ | ___ __| |_ _| | ___ _ / \ _ __| |___ _____ _ __| | __ / /__ ___ _ __ ___
| |\/| |/ _ \ / _` | | | | |/ _ (_) / _ \ | '__| __\ \ /\ / / _ \| '__| |/ / / / __/ _ \| '__/ _ \
| | | | (_) | (_| | |_| | | __/_ / ___ \| | | |_ \ V V / (_) | | | < / / (_| (_) | | | __/
|_| |_|\___/ \__,_|\__,_|_|\___(_)_/ \_\_| \__| \_/\_/ \___/|_| |_|\_\/_/ \___\___/|_| \___|
This submodule is intended for converting inputs into html.
Please do not modify this code without applying the changes first at
"Module:Artwork/sandbox" and testing at "Template:
/testcases".
Authors and maintainers:
* User:Jarekt - original version
]]
require('Module:No globals') -- used for debugging purposes as it detects cases of unintended global variables
local getLabel = require("Module:Wikidata label")._getLabel -- used for creation of name based on Wikidata
local core = require("Module:Core")
local labels = require("Module:I18n/artwork") -- internationalization of labels
local bit32 = require("bit32")
local TagQS = require('Module:TagQS')
local City = require("Module:City") -- used to add Wikidata based links to names of places
local ISOdate = require('Module:ISOdate') -- used for simple date formating
local p = {}
-- Lazy loading function: load them only if they are needed
local function ObjectLocation_label()
return mw.loadData('Module:i18n/coordinates').ObjectLocation
end
local function Creator(args)
return require("Module:Creator")._creator(args)
end
local function Institution(args)
return require("Module:Institution")._institution(args)
end
-- ==================================================
-- === Internal functions ===========================
-- ==================================================
-------------------------------------------------------------------------------
local function isodate2timestamp(dateStr)
-- convert isodate to timestamp used by quick statements
local tStamp = nil
if string.match(dateStr,"^[0-1]%d%d%d$") then -- if YYYY format
tStamp = '+' .. dateStr .. '-00-00T00:00:00Z/9'
elseif string.match(dateStr,"^[0-1]%d%d%d%-[0-1]%d$") then -- if YYYY-MM format
tStamp = '+' .. dateStr .. '-00T00:00:00Z/10'
elseif string.match(dateStr,"^[0-1]%d%d%d%-[0-1]%d%-[0-3]%d$") then -- if YYYY-MM-DD format
tStamp = '+' .. dateStr .. 'T00:00:00Z/11'
end
return tStamp
end
-------------------------------------------------------------------------------
local function if_else(Boolean, TrueStatement, FalseStatement)
if Boolean then
return TrueStatement
else
return FalseStatement
end
end
-------------------------------------------------------------------------------
local function empty2nil(str)
if str=='' then
return nil
else
return str
end
end
-- ====================================================================
-- This function is responsible for producing HTML of a single row of the template
-- At this stage all the fields are already filed. There is either one or two fields
-- INPUTS:
-- * param1 and param2 - structures for 2 fields containing fields:
-- - tag - I18n tag used for localization of the field name. Usually name of page in MediaWiki
-- namespace which was imported from translatewiki.org.
-- Alternative is to pass already translated field name.
-- - field - field content
-- - id - ID tag added to HTML's <td> cell. if IDs of 2 fields are the same than we ignore the second one
-- - wrapper - some fields need a <span class=...> wrapper around the field content
-- ====================================================================
local function Build_html_row(param, args)
local LUT = {artwork=0, photograph=1, book=2}
local demo = args.demo and bit32.extract( param.demo or 0, LUT[args.infobox])==1
local field = args[param.field]
if field=='' then field=nil; end
if not (field or demo) then
return nil
end
if not param.id then -- "other fields" parameter
return field
end
local tag = param.tag or 'bad'
if string.sub(tag,1,10) == 'wm-license' then
tag = mw.message.new( tag ):inLanguage(args.lang):plain() -- label message in args.lang language
elseif string.match(tag, "^[QP]%d+$") then
tag = getLabel(tag, args.lang, "-", "ucfirst")
elseif labels[tag] then
tag = core.langSwitch(labels[tag], args.lang)
end
local cell1 = string.format('<td id="%s" class="fileinfo-paramfield" lang="%s">%s</td>\n', param.id, args.lang, tag)
local cell2 = string.format('<td>\n'.. param.wrapper ..'</td>', field or '')
return string.format('<tr valign="top">\n%s%s\n</tr>\n\n', cell1, cell2)
end
-- ====================================================================
-- === This function is just responsible for producing HTML of the ===
-- === template. At this stage all the fields are already filled ===
-- ====================================================================
function p.build_html(args)
-- get text direction
local dir = if_else(mw.language.new( args.lang ):isRTL(),'rtl','ltr')
-- original_description row has a different look than other rows
if args.original_description and (args.original_description_info or args.biased) then
local tag1, tag2 = "", ""
if args.original_description_info then
tag1 = string.format('<div style="background:#dde; font-size:86%%; direction:%s;">%s</div>', dir, args.original_description_info)
end
if args.biased then
tag2 = core.langSwitch(labels.inaccurate_description, args.lang)
tag2 = string.format('<div style="padding:0.5ex; margin:0 0 0.5ex 0; border: 1px solid red;">%s: %s</div>', tag2, args.biased)
end
args.original_description = tag1 .. tag2 .. args.original_description
end
-- files with no source will be flagged
if (not args.source) and (not args.source_) and (args.strict==true) and (args.namespace==6) then
args.nosource = mw.getCurrentFrame():expandTemplate{ title = 'Source missing' }
end
if args.demo or args.coordinates then
labels.ObjectLocation = ObjectLocation_label()
end
local nCol = 2
if not args.image and args.demo then
args.image = args.demo_image
end
if args.image then
nCol = 3
end
-- Top line
local top, results = {}, {}
if args.name then
table.insert(top, string.format('<span class="fn" id="artwork"><bdi>%s\n</bdi></span>', args.name ) )
end
if args.linkback then -- Wikidata Link
table.insert(top, string.format('[[File:Blue pencil.svg|15px|%s|link=%s]]', args.linkback, args.linkback) )
end
if args.wikidata then -- Wikidata Link
table.insert(top, string.format('[[File:Wikidata-logo.svg|20px|wikidata:%s|link=wikidata:%s]]', args.wikidata, args.wikidata) )
table.insert(top, string.format('[[File:Wikidata-Reasonator_small_logo.svg|5px|reasonator:%s|link=https://reasonator.toolforge.org/test/?q=%s]]', args.wikidata, args.wikidata) )
end
if args.wikisource then --Wikisource link
table.insert(top, string.format('[[File:Wikisource-logo.svg|15px|%s|link=%s]]', args.wikisource, args.wikisource) )
end
if args.wikiquote then --Wikiquote link
table.insert(top, string.format('[[File:Wikiquote-logo.svg|15px|%s|link=%s]]', args.wikiquote, args.wikiquote) )
end
if #top>0 and args.QS then -- quick_statement link to upload missing info to Wikidata (add if the row is not empty)
table.insert(top, string.format('%s', args.QS) )
end
if #top>0 then
local line = string.format('<th colspan="%i" style="background-color:#ccf; font-weight:bold; border:1px solid #aaa" text-align="left">%s</th>', nCol, table.concat(top, ' '))
table.insert(results, string.format('<tr valign="top">\n%s\n</tr>\n', line))
end
-- Permissions tag
local tag1 = mw.message.new( "wm-license-information-permission" ):inLanguage(args.lang):plain()
local tag2 = mw.message.new( "wm-license-information-permission-reusing-link" ):inLanguage(args.lang):plain()
local tag3 = mw.message.new( "wm-license-information-permission-reusing-text" ):inLanguage(args.lang):plain()
local permission_tag = string.format("%s<br /><small>([[%s|%s]])</small>", tag1, tag2, tag3)
-- define constants for readability
-- demo=art+photo+book will show that row in demo mode in {{artwork}, {{Photograph}} and {{Book}} templates
local none, art, photo, book = 0, 1, 2, 4
-- add other fields 'author_of_foreword', 'author_of_afterword'
local param = {
-- field name machine readable tag field name i18n approach show in demo mode? field value wrapper
{field='artist' , id='fileinfotpl_aut' , tag='wm-license-artwork-artist', demo=art, wrapper='<div class="fn value">\n%s</div>'},
{field='author' , id='fileinfotpl_aut' , tag='wm-license-information-author', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='editor' , id='fileinfotpl_book_editor' , tag='wm-license-book-editor', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='translator' , id='fileinfotpl_book_translator' , tag='wm-license-book-translator', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='illustrator' , id='fileinfotpl_book_illustrator' , tag='wm-license-book-illustrator', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='author_of_foreword' , id='fileinfotpl_aut' , tag='P2679', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='author_of_afterword' , id='fileinfotpl_aut' , tag='P2680', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='architect' , id='fileinfotpl_aut' , tag='Q42973', demo=none, wrapper='<div class="fn value">\n%s</div>'},
{field='designer' , id='fileinfotpl_aut' , tag='Q5322166', demo=none, wrapper='<div class="fn value">\n%s</div>'},
{field='photographer' , id='fileinfotpl_aut' , tag='Q33231', demo= photo, wrapper='<div class="fn value">\n%s</div>'},
{field='other_fields_1'},
-- title & desctiption block
{field='title' , id='fileinfotpl_art_title' , tag='wm-license-artwork-title', demo=art+photo+book, wrapper='<div class="fn">\n%s</div>'},
{field='subtitle' , id='fileinfotpl_book_subtitle' , tag='wm-license-book-subtitle', demo= book, wrapper='%s'},
{field='part_of' , id='fileinfotpl_art_part_of' , tag='P361', demo=art+photo+book, wrapper='%s'},
{field='series_title' , id='fileinfotpl_book_series-title' , tag='wm-license-book-series-title', demo= book, wrapper='%s'},
{field='volume' , id='fileinfotpl_book_volume' , tag='wm-license-book-volume', demo= book, wrapper='%s'},
{field='edition' , id='fileinfotpl_edition' , tag='wm-license-book-edition', demo= book, wrapper='%s'},
{field='publisher' , id='fileinfotpl_book_publisher' , tag='wm-license-book-publisher', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='printer' , id='fileinfotpl_book_printer' , tag='wm-license-book-printer', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='object_type' , id='fileinfotpl_art_object_type' , tag='object_type', demo=art, wrapper='%s'},
{field='genre' , id='fileinfotpl_art_genre' , tag='Q483394', demo= book, wrapper='%s'},
{field='original_description' , id='fileinfotpl_desc' , tag='original_description', demo= photo, wrapper='<div class="description">\n%s</div>'},
{field='description' , id='fileinfotpl_desc' , tag='wm-license-information-description', demo=art+photo+book, wrapper='<div class="description">\n%s</div>'},
{field='pageoverview' , id='fileinfotpl_book-page-overview' , tag='wm-license-book-page-overview', demo=none, wrapper='%s'},
{field='depicted_people' , id='fileinfotpl_art_depicted_people' , tag='depicted_people', demo=art+photo, wrapper='%s'},
{field='depicted_place' , id='fileinfotpl_art_depicted_place' , tag='depicted_place', demo=art+photo, wrapper='%s'},
{field='depicted_part' , id='fileinfotpl_art_depicted_part' , tag='P5961', demo=art+photo+book, wrapper='%s'},
{field='language' , id='fileinfotpl_book_language' , tag='wm-license-book-language', demo= book, wrapper='%s'},
{field='other_fields_2'},
-- date, object outside description, history, etc.
{field='date' , id='fileinfotpl_date' , tag='wm-license-information-date', demo=art+photo, wrapper='%s'},
{field='publication_date' , id='fileinfotpl_publication_date' , tag='P577', demo= book, wrapper='%s'},
{field='medium' , id='fileinfotpl_art_medium' , tag='wm-license-artwork-medium', demo=art+photo, wrapper='%s'},
{field='dimensions' , id='fileinfotpl_art_dimensions' , tag='wm-license-artwork-dimensions', demo=art+photo, wrapper='%s'},
{field='institution' , id='fileinfotpl_art_gallery' , tag='Q2668072', demo=art+photo, wrapper='%s'},
{field='department' , id='fileinfotpl_art_location' , tag='wm-license-artwork-current-location', demo=art+photo , wrapper='<div class="locality">\n%s</div>'},
{field='id' , id='fileinfotpl_art_id' , tag='wm-license-artwork-id', demo=art+photo, wrapper='<div class="identifier">\n%s</div>'},
{field='coordinates' , id='fileinfo-paramfield' , tag='ObjectLocation', demo=art+photo, wrapper='%s'},
{field='place_of_publication' , id='fileinfotpl_book_place-of-publication' , tag='wm-license-book-place-of-publication', demo= book, wrapper='%s'},
{field='place_of_creation' , id='fileinfotpl_art_creation_place' , tag='place_of_creation', demo=art, wrapper='%s'},
{field='place_of_discovery' , id='fileinfotpl_art_discovery_place' , tag='place_of_discovery', demo=art, wrapper='%s'},
{field='object_history' , id='fileinfotpl_art_object_history' , tag='wm-license-artwork-object-history', demo=art, wrapper='%s'},
{field='exhibition_history' , id='fileinfotpl_art_exhibition_history' , tag='exhibition_history', demo=art+photo, wrapper='%s'},
{field='credit_line' , id='fileinfotpl_art_credit_line' , tag='wm-license-artwork-credit-line', demo=art, wrapper='%s'},
{field='inscriptions' , id='fileinfotpl_art_inscriptions' , tag='wm-license-artwork-inscriptions', demo=art, wrapper='%s'},
{field='notes' , id='fileinfotpl_art_notes' , tag='wm-license-artwork-notes', demo=art+photo, wrapper='%s'},
{field='other_fields_3'},
-- references, and sources
{field='references' , id='fileinfotpl_art_references' , tag='wm-license-artwork-references', demo=art+photo+book, wrapper='%s'},
{field='authority' , id='fileinfotpl_art_authority' , tag='Q36524', demo=none, wrapper='%s'},
{field='source' , id='fileinfotpl_src' , tag='wm-license-artwork-source', demo=art, wrapper='%s'}, -- source/photographer
{field='source_' , id='fileinfotpl_src' , tag='wm-license-information-source', demo= photo+book, wrapper='%s'}, -- source
{field='nosource' , id='fileinfotpl_nosrc' , tag='wm-license-information-source', demo=none, wrapper='%s'},
{field='permission' , id='fileinfotpl_perm' , tag=permission_tag, demo=art+photo+book, wrapper='%s'},
{field='other_versions' , id='fileinfotpl_ver' , tag='wm-license-information-other-versions', demo=art+photo+book, wrapper='%s'},
{field='other_fields'},
{field='camera_coord'},
}
for i=1,#param do
table.insert(results, Build_html_row(param[i], args))
end
-- add material on the right: image, wikisource icon, etc.
if args.image then
if args.image_page and args.image then -- page parameter for DjVu and PDF files
args.image = string.format('%s|page=%i', args.image, args.image_page)
end
if args.infobox=='book' then -- page parameter for DjVu and PDF files
tag1 = mw.message.new( 'wm-license-book-start-this-book' ):inLanguage(args.lang):plain()
tag2 = string.format('|thumb|[[:File:%s|%s]]', args.image, tag1)
else
tag2 = ''
end
local field = string.format('[[File:%s|250x250px|alt=%s|class=photo%s]]', args.image, args.name or '', tag2)
local nRow = #results -- number of rows below
local line = string.format('<td rowspan="%i" style="width:200px; text-align: right;" id="fileinfotpl_creator_image"><span class="wpImageAnnotatorControl wpImageAnnotatorOff">%s</span></td></tr>\n\n', nRow, field)
results[2] = mw.ustring.gsub(results[2], "</tr>%s*$", line); -- attach image section to the right side of the table, by attaching to row #2
end
-- add table and outer layers
local style = string.format('class="fileinfotpl-type-artwork toccolours vevent mw-content-%s" dir="%s" style="width: 100%%" cellpadding="4"', dir, dir)
results = string.format('<table %s>\n%s\n</table>\n', style, table.concat(results)) -- combine "results", an array of strings into a single string
results = string.format('<div class="hproduct commons-file-information-table">\n%s\n</div>\n', results)
return results
end
-- ===========================================================================
-- === Read input "frame", normalize input parameters (lower case, etc.) ===
-- === and resolve potential aliases ===
-- === INPUTS: ===
-- === * frame - contains input parameters passed from the template ===
-- === OUTPUTS: ===
-- === * args - cleaned up inputs ===
-- ===========================================================================
function p.read_input_parameters(frame)
-- switch to lowercase parameters to make them case independent
local args = core.getArgs(frame)
-- resolve aliases
args.permission = args.permission or args.license
args.medium = args.medium or args.technique
args.date = args.date or args.year
args.department = args.department or args.location
args.id = args.accession_number or args.id
args.object_type = args.object_type or args.type
args.dimensions = args.dimensions or args.size
args.object_history = args.object_history or args.history
args.coordinates = args.coordinates or args.object_location
args.institution = args.institution or args.gallery or args.museum
args.place_of_creation = args.place_of_creation or args.place_of_origin or args.country
args.original_description = args.original_description or args.original_caption
-- remove unneeded parameters
args.technique, args.year, args.size, args.gallery = nil, nil, nil, nil
args.location, args.type, args.museum, args.accession_number = nil, nil, nil, nil
args.place_of_origin, args.country, args.history, args.license = nil, nil, nil, nil
args.object_location, args.original_caption = nil, nil
-- ensure the right format
args.wikidata_cat = core.yesno(args.wikidata_cat, true)
args.strict = core.yesno(args.strict, true)
args.noimage = core.yesno(args.noimage, false)
args.no_qs = core.yesno(args.no_qs, false)
args.no_sdc = core.yesno(args.no_sdc, false)
args.image_page = tonumber(args.image_page)
if args.language and #args.language==2 then
args.language = frame:callParserFunction( "#language", { args.language, args.lang } ) -- get language of the written work
end
return args
end
-- ===========================================================================
function p.verify_input_parameters(args)
local cats = '' -- categories
-- add [[Category:Creator templates with unknown parameter]] category, if some parameter not on the following list is used
local fields = { 'title', 'object_type', 'description', 'date', 'medium', 'permission',
'artist', 'author', 'architect', 'designer', 'illustrator', 'publisher', 'editor', 'translator', 'printer', 'photographer',
'dimensions', 'institution', 'department', 'references', 'object_history', 'genre',
'exhibition_history', 'credit_line', 'other_versions', 'source', 'strict', 'inscriptions', 'notes', 'linkback', 'camera_coord',
'other_fields', 'other_fields_1', 'other_fields_2', 'other_fields_3', 'demo', 'id', 'wikidata', 'year', 'homecat', 'authority',
'place_of_creation', 'place_of_discovery', 'source_', 'wikidata_cat', 'namespace', 'lang', 'image', 'noimage',
'depicted_people', 'depicted_place', 'original_description_info', 'original_description', 'biased', 'photo_date', 'infobox',
'place_of_publication', 'publication_date', 'language', 'subtitle', 'series_title', 'volume', 'edition', 'edition_of',
'pageoverview', 'wikisource', 'wikiquote', 'demo_image', 'image_page', 'depicted_part', 'mimeType', 'num_pages',
'author_of_foreword', 'author_of_afterword', 'infobox', 'no_qs', 'no_sdc', 'part_of'
}
local set = {}
for _, field in ipairs(fields) do set[field] = true end
for field, _ in pairs( args ) do
if not set[field] then
local LUT = {artwork='Artwork', photograph='Photograph', book='Book'}
local infobox = LUT[args.infobox]
cats = cats .. '[[Category:Pages using ' .. infobox .. ' template with incorrect parameter]]'
cats = cats .. string.format('\n;<span style="color:red">Error in [[Template:%s|{{%s}} template]]: unknown parameter "%s".</span>', infobox, infobox, field)
end
end
return cats
end
-- ===========================================================================
function p.clean_input_parameters(args)
local lang = args.lang -- user's language
-- === Step 1: clean up of template arguments "args"
local page = mw.title.getCurrentTitle()
args.namespace = page.namespace -- get page namespace
args.url = page:canonicalUrl()
args.pagename = page.text
if args.namespace==6 then -- file namespace
args.mimeType = page.file.mimeType
args.num_pages = 1
if page.file.pages then
args.num_pages = #page.file.pages -- in case of DjVu or PDF files count pages
end
end
if args.date then
args.year = empty2nil(ISOdate._ISOyear(args.date)) -- get year
end
-- for places run them through {{City}} template
local fields = { 'depicted_people', 'depicted_place', 'place_of_discovery', 'part_of' }
for _, field in ipairs( fields ) do
if args[field] and not string.find(args[field], ' ') then
args[field] = City._city(args[field], lang) -- single word depicted_people will get a link
end
end
-- for dates run them through {{ISOdate}} template and add invisible QS tag if possible
local fields = { 'date', 'publication_date'}
for _, field in ipairs( fields ) do
if args[field] then
local val = isodate2timestamp(args[field]) -- if date is in YYYY, YYYY-MM or YYYY-MM-DD formats than it will be saved
args[field] = ISOdate._ISOdate(args[field], lang) -- apply ISODate to function to date string to convert date in ISO format to translated date string
if val then -- if date is in ISO format than add an invisible tag which will be used to potentially add this date to QS used to move it to Wikidata
args[field] = args[field] .. TagQS.createTag('date', nil, val)
end
end
end
-- collapse local {{Creator}} and {{Institution}} templates and extract item ID from them
local fields = {author='creator', artist='creator', photographer='creator', architect='creator', printer='creator',
designer='creator', editor='creator', translator='creator', illustrator='creator', institution='institution'}
for field, keyword in pairs( fields ) do
if args[field] then
if string.match(args[field], "^Q%d+$") and keyword=='creator' then -- this is wikidata item
args[field..'_id'] = args[field]
if keyword=='creator' then
args[field] = Creator({wikidata=args[field], lang=lang, collapse=1})-- create creator based on item id
elseif keyword=='institution' then
args[field] = Institution({wikidata=args[field], lang=lang, collapse=1})-- create institution based on item id
end
else
-- collapse local {{Creator}} and {{Institution}} templates
args[field] = mw.ustring.gsub (args[field], 'table class="toccolours collapsible%s*"', 'table class="toccolours collapsible collapsed"')
-- extract item ID: retrieve the tag and grab the second component
local v = mw.text.split( TagQS.readTag(args[field], keyword) or '', '|', true )
if v and #v>=2 then
args[field..'_id'] = v[2]
end
end
end
end
-- in case of invisible QS tags add correct property based on which field and infobox it come from
local repList = { {'author', 'book', 'creator', 'P170', 'P50' },
{'artist', 'artwork', 'creator', 'P170', 'P170' },
{'illustrator', 'book', 'creator', 'P170', 'P110'},
{'editor', 'book', 'creator', 'P170', 'P98' },
{'translator', 'book', 'creator', 'P170', 'P655'},
{'printer', 'book', 'creator', 'P170', 'P872'},
{'publication_date', 'book', 'date', nil, 'P577'},
{'date', 'photograph', 'date', nil, 'P571'},
{'date', 'artwork', 'date', nil, 'P571'}}
for _, repItem in ipairs( repList ) do
local field, infobox, tag, oldP, newP = unpack(repItem)
if args[field] and args.infobox==infobox then
args[field] = TagQS.changeProperty(args[field], tag, oldP, newP)
args[field] = TagQS.changeField(args[field], tag, field)
end
end
if args.source and mw.ustring.find( args.source, 'www%.wga%.hu' ) then
-- code to help copy links to www.wga.hu to Wikidata
args.reference_wga = string.gsub(args.source, 'http://www%.wga%.hu', 'https://www.wga.hu')
end
return args
end
-- ===========================================================================
function p.test(frame)
local args = p.read_input_parameters(frame)
args.infobox = 'artwork'
local cats0 = p.verify_input_parameters(args)
args = p.clean_input_parameters(args)
return p.build_html(args)
end
return p