Module:Story: Difference between revisions

From FictionBase
Words fix
Wikidata ID support
 
(2 intermediate revisions by the same user not shown)
Line 45: Line 45:
Collections = args.collections,
Collections = args.collections,
Tags = args.tags,
Tags = args.tags,
Notes = args.notes
Notes = args.notes,
IDWikidata = args.id_wikidata
})
})
end
end


local function addField(meta, label, value, full)
local function makeNsLink(ns, label)
label = trim(label)
if not label then return nil end
local target = mw.ustring.gsub(label, "%s+", "_")
return string.format("[[%s:%s|%s]]", ns, target, label)
end
 
local function addField(meta, label, value, full, ns)
value = trim(value)
value = trim(value)
if not value then return end
if not value then return end
if ns then
value = makeNsLink(ns, value) or value
end
local field = meta:tag("div"):addClass("story-field")
local field = meta:tag("div"):addClass("story-field")
if full then field:addClass("story-field-full") end
if full then field:addClass("story-field-full") end
Line 58: Line 71:
end
end


local function addMultiField(meta, label, raw, full)
local function addMultiField(meta, label, raw, full, ns)
local items = split_semicolons(raw)
local items = split_semicolons(raw)
if #items == 0 then return end
if #items == 0 then return end
Line 66: Line 79:
local val = field:tag("div"):addClass("story-value")
local val = field:tag("div"):addClass("story-value")
for _, item in ipairs(items) do
for _, item in ipairs(items) do
val:tag("span"):addClass("story-chip"):wikitext(item)
local wikitext = item
if ns then
wikitext = makeNsLink(ns, item) or item
end
val:tag("span"):addClass("story-chip"):wikitext(wikitext)
end
end
end
end
Line 117: Line 134:
local plot_summary = trim(args.plot_summary)
local plot_summary = trim(args.plot_summary)
local notes = trim(args.notes)
local notes = trim(args.notes)
local id_wikidata = trim(args.id_wikidata)


local root = mw.html.create("div"):addClass("story-card")
local root = mw.html.create("div"):addClass("story-card")
Line 136: Line 154:


local meta = root:tag("div"):addClass("story-meta")
local meta = root:tag("div"):addClass("story-meta")
addField(meta, "Author", author)
addField(meta, "Author", author, false, "Author")
addField(meta, "Published in", publication)
addField(meta, "Published in", publication, false, "Publication")
addField(meta, "Year", year)
addField(meta, "Year", year, false, "Year")
addField(meta, "Words", words)
addField(meta, "Words", words)
addReadOnline(meta, args)
addReadOnline(meta, args)


-- Split-capable multi-value fields (semicolon-separated)
-- Split-capable multi-value fields (semicolon-separated)
addMultiField(meta, "Genres", args.genres)
addMultiField(meta, "Genres", args.genres, false, "Genre")
addMultiField(meta, "Collections", args.collections)
addMultiField(meta, "Collections", args.collections, false, "Collection")
addMultiField(meta, "Tags", args.tags, true)
addMultiField(meta, "Tags", args.tags, true, "Tag")


if plot_summary then
if plot_summary then
Line 157: Line 175:
section:tag("div"):addClass("story-section-title"):wikitext("Notes")
section:tag("div"):addClass("story-section-title"):wikitext("Notes")
section:tag("div"):addClass("story-section-body"):wikitext(notes)
section:tag("div"):addClass("story-section-body"):wikitext(notes)
end
if id_wikidata then
local section = root:tag("div"):addClass("story-section")
section:tag("div"):addClass("story-section-title"):wikitext("External links")
local body = section:tag("div"):addClass("story-section-body")
body:wikitext("* [https://www.wikidata.org/wiki/" .. id_wikidata .. " Wikidata entry]")
end
end

Latest revision as of 06:38, 8 March 2026

Documentation for this module may be created at Module:Story/doc

local p = {}

local function trim(s)
	if s == nil then return nil end
	s = tostring(s)
	s = mw.text.trim(s)
	if s == "" then return nil end
	return s
end

local function split_semicolons(s)
	s = trim(s)
	if not s then return {} end
	local parts = mw.text.split(s, "%s*;%s*", false)
	local out = {}
	for _, part in ipairs(parts) do
		part = trim(part)
		if part then
			table.insert(out, part)
		end
	end
	return out
end

local function storeCargo(args)
	if not mw.ext.cargo then return end

	mw.ext.cargo.store("Stories", {
		Title = args.title,
		Author = args.author,
		Publication = args.publication,
		Year = tonumber(args.year),
		Words = tonumber((args.words or ""):gsub(",", ""):match(".*")),
		Logline = args.logline,
		Read1Site = args.read1_site,
		Read1URL = args.read1_url,
		Read1Access = args.read1_access,
		Read2Site = args.read2_site,
		Read2URL = args.read2_url,
		Read2Access = args.read2_access,
		Read3Site = args.read3_site,
		Read3URL = args.read3_url,
		Read3Access = args.read3_access,
		Genres = args.genres,
		Collections = args.collections,
		Tags = args.tags,
		Notes = args.notes,
		IDWikidata = args.id_wikidata
	})
end

local function makeNsLink(ns, label)
	label = trim(label)
	if not label then return nil end
	local target = mw.ustring.gsub(label, "%s+", "_")
	return string.format("[[%s:%s|%s]]", ns, target, label)
end

local function addField(meta, label, value, full, ns)
	value = trim(value)
	if not value then return end

	if ns then
		value = makeNsLink(ns, value) or value
	end

	local field = meta:tag("div"):addClass("story-field")
	if full then field:addClass("story-field-full") end
	field:tag("div"):addClass("story-label"):wikitext(label)
	field:tag("div"):addClass("story-value"):wikitext(value)
end

local function addMultiField(meta, label, raw, full, ns)
	local items = split_semicolons(raw)
	if #items == 0 then return end
	local field = meta:tag("div"):addClass("story-field")
	if full then field:addClass("story-field-full") end
	field:tag("div"):addClass("story-label"):wikitext(label)
	local val = field:tag("div"):addClass("story-value")
	for _, item in ipairs(items) do
		local wikitext = item
		if ns then
			wikitext = makeNsLink(ns, item) or item
		end
		val:tag("span"):addClass("story-chip"):wikitext(wikitext)
	end
end

local function normalizeAccess(access)
	access = trim(access)
	if not access then return nil end
	access = mw.ustring.lower(access)
	if access ~= "free" and access ~= "paid" then return nil end
	return access
end

local function addReadOnline(meta, args)
	local links = {}
	for i = 1, 3 do
		local url = trim(args["read" .. i .. "_url"])
		if url then
			local site = trim(args["read" .. i .. "_site"]) or ("Link " .. i)
			local access = normalizeAccess(args["read" .. i .. "_access"])
			table.insert(links, { url = url, site = site, access = access })
		end
	end
	if #links == 0 then return end

	local field = meta:tag("div"):addClass("story-field"):addClass("story-field-full")
	field:tag("div"):addClass("story-label"):wikitext("Read online")
	local val = field:tag("div"):addClass("story-value")
	for _, l in ipairs(links) do
		local row = val:tag("div"):addClass("story-link")
		row:wikitext("[" .. l.url .. " " .. l.site .. "]")
		if l.access then
			row:wikitext(" ")
			row:tag("span")
				:addClass("story-badge")
				:addClass("story-badge-" .. l.access)
				:wikitext(mw.language.getContentLanguage():ucfirst(l.access))
		end
	end
end

function p.main(frame)
	local args = frame:getParent() and frame:getParent().args or frame.args

	local title = trim(args.title) or ""
	local author = trim(args.author)
	local publication = trim(args.publication)
	local year = trim(args.year)
	local words = trim(args.words)
	local logline = trim(args.logline)
	local plot_summary = trim(args.plot_summary)
	local notes = trim(args.notes)
	local id_wikidata = trim(args.id_wikidata)

	local root = mw.html.create("div"):addClass("story-card")

	local header = root:tag("div"):addClass("story-header")
	header:tag("div"):addClass("story-title"):wikitext(title ~= "" and title or "Untitled")

	if author then
		local byline = "By " .. author
		if publication then
			byline = byline .. ", first published in " .. publication
		end
		header:tag("div"):addClass("story-byline"):wikitext(byline)
	end

	if logline then
		header:tag("div"):addClass("story-logline"):wikitext(logline)
	end

	local meta = root:tag("div"):addClass("story-meta")
	addField(meta, "Author", author, false, "Author")
	addField(meta, "Published in", publication, false, "Publication")
	addField(meta, "Year", year, false, "Year")
	addField(meta, "Words", words)
	addReadOnline(meta, args)

	-- Split-capable multi-value fields (semicolon-separated)
	addMultiField(meta, "Genres", args.genres, false, "Genre")
	addMultiField(meta, "Collections", args.collections, false, "Collection")
	addMultiField(meta, "Tags", args.tags, true, "Tag")

	if plot_summary then
		local section = root:tag("div"):addClass("story-section")
		section:tag("div"):addClass("story-section-title"):wikitext("Plot Summary")
		section:tag("div"):addClass("story-section-body"):wikitext(plot_summary)
	end

	if notes then
		local section = root:tag("div"):addClass("story-section")
		section:tag("div"):addClass("story-section-title"):wikitext("Notes")
		section:tag("div"):addClass("story-section-body"):wikitext(notes)
	end

	if id_wikidata then
		local section = root:tag("div"):addClass("story-section")
		section:tag("div"):addClass("story-section-title"):wikitext("External links")
		local body = section:tag("div"):addClass("story-section-body")
		body:wikitext("* [https://www.wikidata.org/wiki/" .. id_wikidata .. " Wikidata entry]")
	end
	
	storeCargo(args)

	return tostring(root)
end

return p