Module:Firehose links: Difference between revisions
From PickiPedia: A knowledge base of bluegrass, old time psychedelic jams, and other public domain music
Jump to navigationJump to search
Rename guestlinks to topiclinks; episodes record topics, not only guests (via update-page on MediaWiki MCP Server) |
Strip SMW's span markup before matching names, or every person files as a topic (via update-page on MediaWiki MCP Server) |
||
| (One intermediate revision by the same user not shown) | |||
| Line 8: | Line 8: | ||
-- when an episode has more than one. Linking that string whole would produce a | -- when an episode has more than one. Linking that string whole would produce a | ||
-- single broken redlink -- one link containing "Sam Bush, Jerry Douglas" -- so | -- single broken redlink -- one link containing "Sam Bush, Jerry Douglas" -- so | ||
-- split it and link each name on its own | -- split it and link each name on its own. | ||
-- | -- | ||
-- Note for future editors: do not wrap this header in a --[==[ ]==] block | -- Note for future editors: do not wrap this header in a --[==[ ]==] block | ||
| Line 27: | Line 25: | ||
} | } | ||
function | local function split( raw ) | ||
local | local out = {} | ||
for name in ( ( raw or "" ) .. "," ):gmatch( "%s*(.-)%s*," ) do | |||
if name ~= "" then | |||
table.insert( out, name ) | |||
end | |||
end | |||
return out | |||
end | |||
local function link( name ) | |||
if NOT_AN_ENTITY[ name:lower() ] then | |||
return name | |||
end | |||
return "[[" .. name .. "]]" | |||
end | |||
-- Which of these names are pages in Category:People. | |||
-- | |||
-- One query for the whole row rather than one per name, since a tribute | |||
-- episode can name nine people and a firehose shows twenty-five rows. | |||
local function peopleAmong( frame, names ) | |||
local candidates = {} | |||
for _, name in ipairs( names ) do | |||
if not NOT_AN_ENTITY[ name:lower() ] then | |||
table.insert( candidates, name ) | |||
end | |||
end | |||
if #candidates == 0 then | |||
return {} | |||
end | |||
local found = frame:callParserFunction( "#ask", { | |||
"[[Category:People]][[" .. table.concat( candidates, "||" ) .. "]]", | |||
"format=list", | |||
"link=none", | |||
"sep=;", | |||
"searchlabel=", | |||
"limit=50", | |||
} ) | |||
-- SMW wraps each value in span markup, even with link=none, and may hand | |||
-- the result back as a strip marker. Reduce it to the bare names first, or | |||
-- "<span class=smw-value>Billy Strings</span>" never equals Billy Strings | |||
-- and every person gets filed as a topic. | |||
found = mw.text.unstrip( found ):gsub( "<[^>]+>", "" ) | |||
local set = {} | |||
for name in ( found .. ";" ):gmatch( "%s*(.-)%s*;" ) do | |||
if name ~= "" then | |||
set[ name ] = true | |||
end | |||
end | |||
return set | |||
end | |||
-- Every subject of an episode, linked, and filed as people or topics. | |||
-- | |||
-- A page in Category:People is a person. A page that exists and is not in it — | |||
-- a band, a festival, a tune — is a topic. A name with no page yet is filed | |||
-- with the people, because nothing yet says otherwise and nearly everything | |||
-- the title parser extracts is a personal name. That default corrects itself: | |||
-- the moment somebody writes East Nash Grass up as a band, it moves across. | |||
function p.subjects( frame ) | |||
local names = split( frame.args[1] ) | |||
if #names == 0 then | |||
return "" | return "" | ||
end | end | ||
local | local people = peopleAmong( frame, names ) | ||
for name in ( | local persons, topics = {}, {} | ||
if name | |||
for _, name in ipairs( names ) do | |||
local title = mw.title.new( name ) | |||
if people[ name ] then | |||
table.insert( persons, link( name ) ) | |||
elseif title and title.exists then | |||
table.insert( topics, link( name ) ) | |||
else | |||
table.insert( persons, link( name ) ) | |||
end | end | ||
end | end | ||
local parts = {} | |||
if #persons > 0 then | |||
table.insert( parts, "people " .. table.concat( persons, ", " ) ) | |||
end | |||
if #topics > 0 then | |||
table.insert( parts, "topics " .. table.concat( topics, ", " ) ) | |||
end | |||
return table.concat( parts, " · " ) | |||
end | |||
-- Every subject linked, unlabelled. Kept for callers that want a plain list. | |||
function p.topiclinks( frame ) | |||
local out = {} | |||
for _, name in ipairs( split( frame.args[1] ) ) do | |||
table.insert( out, link( name ) ) | |||
end | |||
return table.concat( out, ", " ) | return table.concat( out, ", " ) | ||
end | end | ||
Latest revision as of 17:44, 14 September 2026
Documentation for this module may be created at Module:Firehose links/doc
-- Helpers for Template:Firehose.
--
-- The firehose runs its #ask with link=none, because Semantic MediaWiki
-- otherwise hands the template a pre-rendered link for every value, which
-- defeats both #titleparts and any attempt to relabel the episode link.
--
-- The cost of link=none is that topic names arrive as plain text, comma-joined
-- when an episode has more than one. Linking that string whole would produce a
-- single broken redlink -- one link containing "Sam Bush, Jerry Douglas" -- so
-- split it and link each name on its own.
--
-- Note for future editors: do not wrap this header in a --[==[ ]==] block
-- comment containing wiki link syntax. Lua reads the inner brackets as nested
-- long brackets and refuses to load the module.
local p = {}
-- Values the title parser sometimes yields that are not entities, and so
-- should be shown but never linked.
local NOT_AN_ENTITY = {
["and more"] = true,
["more"] = true,
["etc"] = true,
["etc."] = true,
}
local function split( raw )
local out = {}
for name in ( ( raw or "" ) .. "," ):gmatch( "%s*(.-)%s*," ) do
if name ~= "" then
table.insert( out, name )
end
end
return out
end
local function link( name )
if NOT_AN_ENTITY[ name:lower() ] then
return name
end
return "[[" .. name .. "]]"
end
-- Which of these names are pages in Category:People.
--
-- One query for the whole row rather than one per name, since a tribute
-- episode can name nine people and a firehose shows twenty-five rows.
local function peopleAmong( frame, names )
local candidates = {}
for _, name in ipairs( names ) do
if not NOT_AN_ENTITY[ name:lower() ] then
table.insert( candidates, name )
end
end
if #candidates == 0 then
return {}
end
local found = frame:callParserFunction( "#ask", {
"[[Category:People]][[" .. table.concat( candidates, "||" ) .. "]]",
"format=list",
"link=none",
"sep=;",
"searchlabel=",
"limit=50",
} )
-- SMW wraps each value in span markup, even with link=none, and may hand
-- the result back as a strip marker. Reduce it to the bare names first, or
-- "<span class=smw-value>Billy Strings</span>" never equals Billy Strings
-- and every person gets filed as a topic.
found = mw.text.unstrip( found ):gsub( "<[^>]+>", "" )
local set = {}
for name in ( found .. ";" ):gmatch( "%s*(.-)%s*;" ) do
if name ~= "" then
set[ name ] = true
end
end
return set
end
-- Every subject of an episode, linked, and filed as people or topics.
--
-- A page in Category:People is a person. A page that exists and is not in it —
-- a band, a festival, a tune — is a topic. A name with no page yet is filed
-- with the people, because nothing yet says otherwise and nearly everything
-- the title parser extracts is a personal name. That default corrects itself:
-- the moment somebody writes East Nash Grass up as a band, it moves across.
function p.subjects( frame )
local names = split( frame.args[1] )
if #names == 0 then
return ""
end
local people = peopleAmong( frame, names )
local persons, topics = {}, {}
for _, name in ipairs( names ) do
local title = mw.title.new( name )
if people[ name ] then
table.insert( persons, link( name ) )
elseif title and title.exists then
table.insert( topics, link( name ) )
else
table.insert( persons, link( name ) )
end
end
local parts = {}
if #persons > 0 then
table.insert( parts, "people " .. table.concat( persons, ", " ) )
end
if #topics > 0 then
table.insert( parts, "topics " .. table.concat( topics, ", " ) )
end
return table.concat( parts, " · " )
end
-- Every subject linked, unlabelled. Kept for callers that want a plain list.
function p.topiclinks( frame )
local out = {}
for _, name in ipairs( split( frame.args[1] ) ) do
table.insert( out, link( name ) )
end
return table.concat( out, ", " )
end
-- Former name, kept so an older revision of a calling template does not break.
p.guestlinks = p.topiclinks
return p