Module:GrigoripediaJsonLD
Appearance
Documentation for this module may be created at Module:GrigoripediaJsonLD/doc
local p = {}
-- ============================================================
-- Utility functions
-- ============================================================
local function trim(value)
if value == nil then
return nil
end
value = mw.text.trim(tostring(value))
if value == '' then
return nil
end
return value
end
-- Convert common wikitext/HTML found in infobox parameters
-- into simple plain text suitable for JSON-LD.
local function cleanText(value)
value = trim(value)
if not value then
return nil
end
-- Line breaks
value = value:gsub('<br%s*/>', '; ')
value = value:gsub('<br%s*>', '; ')
-- Piped wikilinks:
-- [[Watcher|Grigori]] -> Grigori
value = value:gsub(
'%[%[[^%]]-|([^%]]-)%]%]',
'%1'
)
-- Ordinary wikilinks:
-- [[Watcher]] -> Watcher
value = value:gsub(
'%[%[([^%]]-)%]%]',
'%1'
)
-- Bold / italics
value = value:gsub("'''", '')
value = value:gsub("''", '')
-- Remaining HTML
value = value:gsub('<[^>]+>', '')
-- Common entities
value = value:gsub(' ', ' ')
value = value:gsub('&', '&')
value = value:gsub('"', '"')
value = value:gsub(''', "'")
value = value:gsub('<', '<')
value = value:gsub('>', '>')
-- Normalize whitespace
value = value:gsub('%s+', ' ')
value = mw.text.trim(value)
if value == '' then
return nil
end
return value
end
-- Convert an infobox's alternative-name list
-- into Schema.org alternateName values.
local function getAlternateNames(value)
value = trim(value)
if not value then
return nil
end
value = value:gsub('\r\n', '\n')
value = value:gsub('\r', '\n')
value = value:gsub('<br%s*/>', '\n')
value = value:gsub('<br%s*>', '\n')
value = value:gsub('•', '\n')
value = value:gsub(';', '\n')
local names = {}
local seen = {}
for part in mw.text.gsplit(value, '\n', true) do
local name = cleanText(part)
if name and not seen[name] then
table.insert(names, name)
seen[name] = true
end
end
if #names == 0 then
return nil
elseif #names == 1 then
return names[1]
end
return names
end
local function addUnique(list, seen, value)
value = cleanText(value)
if value and not seen[value] then
table.insert(list, value)
seen[value] = true
end
end
local function setSingleOrArray(entity, property, values)
if #values == 1 then
entity[property] = values[1]
elseif #values > 1 then
entity[property] = values
end
end
local function getImageUrl(filename)
filename = trim(filename)
if not filename then
return nil
end
filename = filename:gsub('^File:', '')
return tostring(
mw.uri.fullUrl(
'Special:FilePath/' .. filename
)
)
end
local function getTemplateArgs(frame)
local parent = frame:getParent()
if parent then
return parent.args
end
return frame.args
end
-- ============================================================
-- Entity builder
-- ============================================================
local function setEntity(kind, args)
local title = mw.title.getCurrentTitle()
-- Only generate entity data on actual encyclopedia articles.
if title.namespace ~= 0 then
return ''
end
-- Fail harmlessly if DynamicJsonLD is unavailable.
if
not mw.ext
or not mw.ext.JsonLD
or not mw.ext.JsonLD.setMainEntity
then
return ''
end
local pageUrl = tostring(title:fullUrl())
local entity = {
["@type"] = "Thing",
["@id"] = pageUrl .. "#entity",
["name"] = cleanText(args.name) or title.text,
["url"] = pageUrl
}
-- Alternate names
local alternateNames = getAlternateNames(args.other_names)
if alternateNames then
entity["alternateName"] = alternateNames
end
-- Representative image
local image = getImageUrl(args.image)
if image then
entity["image"] = image
end
-- Classification / entity type
local types = {}
local seenTypes = {}
if kind == 'watcher' then
-- Every Infobox Watcher entity is a Watcher.
addUnique(types, seenTypes, 'Watcher')
local position = cleanText(args.position)
if
position
and position:find('Dekadarch', 1, true)
then
addUnique(types, seenTypes, 'Dekadarch')
end
elseif kind == 'satanael' then
-- Every Infobox Satanael entity represents Satanael.
addUnique(types, seenTypes, 'Satanael')
-- Allow the template's type field to add a broader
-- classification, such as "Deity".
addUnique(types, seenTypes, args.type)
-- Retained for compatibility if classification is ever
-- supplied manually or by an older template revision.
addUnique(types, seenTypes, args.classification)
else
addUnique(types, seenTypes, args.type)
addUnique(types, seenTypes, args.classification)
end
setSingleOrArray(
entity,
'additionalType',
types
)
mw.ext.JsonLD.setMainEntity(entity)
return ''
end
-- ============================================================
-- Public functions
-- ============================================================
-- Generic being infoboxes.
function p.being(frame)
return setEntity(
'being',
getTemplateArgs(frame)
)
end
-- Watcher-specific infoboxes.
function p.watcher(frame)
return setEntity(
'watcher',
getTemplateArgs(frame)
)
end
-- Satanael-specific infobox.
function p.satanael(frame)
return setEntity(
'satanael',
getTemplateArgs(frame)
)
end
return p