Module:TagQS
CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules
Introduction
This module has functions for creation, reading and operating on invisible tags which can be used to pass language independent data between templates. The initial goal of those tags was for templates often called from infoboxes like {{Artwork}}, {{Book}}, {{Photograph}} to pass invisible language independent data to those infoboxes in addition to localized text. So for example, if we have file showing an artwork that has an item on Wikidata and that file has some metadata, like author or dimensions, which are missing on Wikidata, then with the help of those tags {{Artwork}} template an create an icon , which when clicked would allow the transfer of this metadata from Commons to Wikidata. See Category:Artworks with Wikidata item: quick statements for files where such transfer is possible.
Structure
Each tag has 3 parts:
- field - a broad category of tags. For example {{Size}} template adds tags using dimensions field, {{Institution}} template adds tags using institution field, etc.
- property - part one of property/value pair: id of a Wikidata property.
- value - part two of property/value pair: value of a property, as described in d:Help:QuickStatements
Templates and modules using TagQS
Template | Module | Tag's Field | Tag's Properties | Comment |
---|---|---|---|---|
{{Size}} | Module:Size | dimensions | height (P2048), width (P2049), +8 more | create tag |
{{Title}} | Module:Title | title | title (P1476) | create tag |
{{Title}} | Module:Title | label | labels | create tag |
{{Creator}} | Module:Creator | creator | creator (P170) | create tag |
{{Institution}} | Module:Institution | institution | collection (P195) | create tag |
{{Complex date}} | Module:Complex_date | date | not set | create tag |
{{Artwork}} (date or publication date field) | Module:Artwork/core | date | not set | create tags for simple dates like the ones in YYYY-MM-DD or YYYY formats |
{{Technique}} | Module:Technique | medium | made from material (P186), fabrication method (P2079) | create tag without TagQS |
{{Oil on canvas}} | medium | made from material (P186) | create tag using {{CreateTag}} | |
{{Oil on panel}} | medium | made from material (P186) | create tag using {{CreateTag}} | |
{{Wood carving}} | medium | made from material (P186) | create tag using {{CreateTag}} |
Code
--[[
_____ .___ .__ ___________ ________ _________
/ \ ____ __| _/_ __| | ____ /\ \__ ___/____ ____ \_____ \ / _____/
/ \ / \ / _ \ / __ | | \ | _/ __ \ \/ | | \__ \ / ___\ / / \ \ \_____ \
/ Y ( <_> ) /_/ | | / |_\ ___/ /\ | | / __ \_/ /_/ > \_/. \/ \
\____|__ /\____/\____ |____/|____/\___ > \/ |____| (____ /\___ /\_____\ \_/_______ /
\/ \/ \/ \//_____/ \__> \/
This module is intended for creating invisible tags which can be used to pass
language independent data from some templates to infoboxes. Those tags are often
used by templates like [Template:Artwork] to pass data to Wikidata
Authors and maintainers:
* User:Jarekt - original version
]]
require('strict') -- used for debugging purposes as it detects cases of unintended global variables
-- ==================================================
-- === External functions ===========================
-- ==================================================
local p = {}
function p.replaceUnlessQuoted(str, oldChar, newChar)
-- String "str" has some sections that are in quotes and some that are not.
-- Do replacements only in the text sections which are not in "" quotes.
local quote = string.byte('"')
local comma = string.byte(oldChar)
local quoted = false
for pos = 1, #str do
if str:byte(pos) == quote then
quoted = not quoted
end
if str:byte(pos) == comma and not quoted then
str = str:sub(1,pos-1) .. newChar .. str:sub(pos+1, str:len())
end
end
return str
end
-- ===========================================================================
-- === Version of the function to be called from other LUA codes
-- ===========================================================================
function p.createTag(field, property, value)
-- create tags to insert using "field" "property" and "value" strings.
-- "field" is an unique label to distinguish it from other tags.
-- "property" and "value" are actually in a format similar to the one expected by QuickStatements
return mw.ustring.format('<div style="display: none;">%s QS:%s,%s</div>', field, property or 'P', value)
end
function p.changeField(text, old, new)
-- replace "field" part of the tag. It is needed as sometimes template adding those tags does not
-- know the meaning, which is known the the outside template. For example in
-- "{{Book|translator={{Creator|wikidata=Q12345}}" the Creator template will create initial
-- tag with the wikidata item and {{Book}} template will add label and property for "transaltor".
local patrn = '%<div style="display: none;"%>'.. old ..' QS:([^%<]+)%</div%>'
local repl = '<div style="display: none;">'.. new ..' QS:%1</div>'
return mw.ustring.gsub(text, patrn, repl)
end
function p.changeProperty(text, field, old, new)
-- replace "property" part of the tag. It is needed as sometimes template adding those tags does not
-- know the meaning, which is known the the outside template. For example in
-- "{{Book|translator={{Creator|wikidata=Q12345}}" the Creator template will create initial
-- tag with the wikidata item and {{Book}} template will add label and property for "transaltor".
if not old then -- string "old" is optional if nil than any property will be replaced
old = '[^%,]+'
end
local patrn = '%<div style="display: none;"%>' .. field .. ' QS:' .. old .. ',([^%<]+)%</div%>'
local repl = '<div style="display: none;">' .. field .. ' QS:' .. new .. ',%1</div>'
return mw.ustring.gsub(text, patrn, repl)
end
function p.append2value(text, field, text2append)
-- append "text" to the "value" part of the tag
local patrn = '%<div style="display: none;"%>'.. field ..' QS:([^%<]+)%</div%>'
local repl = '<div style="display: none;">' .. field ..' QS:%1,' .. text2append .. '</div>'
return mw.ustring.gsub(text, patrn, repl)
end
function p.readTag(text, field)
-- read a single tag
local pat = '%<div style="display: none;"%>'..field..' QS:([^%<]+)%</div%>'
local qs = string.match(text, pat) -- find hidden tag with QS code
local _, nMatch = string.gsub(text, pat, "") -- count matches
if qs and nMatch==1 then -- allow only single matches
return p.replaceUnlessQuoted(qs, ',', '|')
end
end
function p.readTags(text, field)
-- read multiple tags and return array of them
local pat = '%<div style="display: none;"%>'..field..' QS:([^%<]+)%</div%>'
local ret = {}
for qs in mw.ustring.gmatch(text, pat) do
table.insert(ret, p.replaceUnlessQuoted(qs, ',', '|') )
end
return ret
end
function p.hasTag(text, field)
-- does the "text" has a tag with field "field", or if field=nil does it have any tags?
return text~= p.removeTag(text, field)
end
function p.removeTag(text, field)
-- remove tags with field "field" from the string. Field =nil will replace all tags
if not field then
field = '[^ ]+'
end
local patrn = '%<div style="display: none;"%>' .. field .. ' QS:[^%<]+%</div%>'
return mw.ustring.gsub(text, patrn, '')
end
-- ===========================================================================
-- === Versions of the function to be called from template namespace
-- ===========================================================================
function p.CreateTag(frame)
return p.createTag(frame.args[1], frame.args[2], frame.args[3])
end
return p