Module:New texts

-- This is an module to implement listings of new texts

local p = {} --p stands for package

local getArgs = require('Module:Arguments').getArgs

local DEFAULTS = { data_source = "Template:New texts/data", }

function is_table(t) return type(t) == 'table' end

function get_data(src, year) local data if src == nil then src = DEFAULTS["data_source"] end

if year == "" or year == nil then year = os.date( '%Y' ) end src = src .. "/" .. year .. ".json" local data if pcall(function		local jsondata = mw.title.new(src):getContent		data = mw.text.jsonDecode(jsondata)	end) then -- no errors while loading else error("Failed to load new text data from " .. src .. "") end return data end

-- construct an author link from a given string function construct_author_link(str) -- strip "Portal:" prefixes if not piped str = string.gsub(str, "%[%[%s*Portal:([^|]-)|?%]%]", function (target)		return "" .. target .. ""	end) -- plain portal syntax str = string.gsub(str, "^[Pp]ortal:(.*)$", function (target)		return "" .. target .. ""	end) -- And for authors str = string.gsub(str, "%[%[%s*[Aa]uthor:([^|]-)|?%]%]", function (target)		return "" .. target .. ""	end) -- auto-strip bracketed dates str = string.gsub(str, "^((.*) +%([0-9]+[-–][0-9]+%))$", function (full_target, no_date)		return "" .. no_date .. ""	end, 1)

-- if the string has its own links, return it now if string.match(str, "%[%[") then return str end

if string.match(str, "[uU]nknown") then return "Anonymous" end if string.match(str, "[Vv]arious") then return "Various authors" end -- if a pipe is provided if string.match(str, "|") then return "Author:" .. str .. "" end -- make our own piped link return "" .. str .. "" end

-- construct a list like "a, b and c" function comma_and_list(entries) local s = "" --mw.logObject(entries) for k, v in pairs(entries) do		if k > 1 and #entries > 1 then if k == #entries then s = s .. " and " else s = s .. ", "			end end s = s .. v	end

return s end

--[=[ Construct an author link for the given key (e.g "author" or "translator")

If nowiki is given, ]=] function construct_author(item, key, nowiki)

-- explicit nowiki, or the string contains its own links if item[key .. "_nowiki"] then return item[key] end local tab = item[key] if not is_table(tab) then tab = {tab} end entries = {} for k, v in pairs(tab) do		if nowiki then table.insert(entries, v)		else table.insert(entries, construct_author_link(v)) end end

local s = comma_and_list(entries) return s end

--[=[ Construct a display text for a title

Nil if no display text seems sensible ]=] function construct_display(title) mwt = mw.title.new(title) if mwt and mwt.isSubpage then return mwt.subpageText end return nil end

--[=[ Construct template arguments for an entry using ]=] function get_item_template_args(frame, item) -- suppress auto links for the authors, etc local nowiki = item.nowiki args = { item["title"], construct_author(item, "author", nowiki), item["year"], ["nowiki"] = "yes" -- we always construct this ourselves }	if item["display"] then args["display"] = item["display"] else local auto_display = construct_display(item["title"]) if auto_display then args["display"] = auto_display end end if item["image_name"] then args["image_name"] = item["image_name"] end

if item["image_size"] then args["image_size"] = item["image_size"] end if item["edition"] then args["edition"] = item["edition"] end if item["translator"] then local trans = construct_author(item, "translator", nowiki)

if item["translation_year"] then trans = trans .. " (" .. item["translation_year"]	.. ")" end

args["translator"] = trans end if item["editor"] then local editor = construct_author(item, "editor", nowiki) args["editor"] = editor end if item["illustrator"] then local illustrator = construct_author(item, "illustrator", nowiki) args["illustrator"] = illustrator end if item["type"] == "film" then local film_indicator = frame:expandTemplate{title="media", args={15, type = "film"}} args[3] = mw.text.trim( args[3] ) .. ", " .. film_indicator end return args end

function table_len(data) -- count the items (#data doesn't work?) local count = 0 for k, _ in pairs(data) do		count = count + 1 end return count end

function month_name(n) return os.date("%B", os.time({year=2000, month=n, day=1})) end

--[=[ Construct the new tests list from instances of

Arguments: ]=] function p.new_texts(frame) local args = getArgs(frame) -- pull in the data from the data module at Template:New texts/data(/YEAR).json local data = get_data(args["data_source"], nil) -- how many items to show local offset = 0 if args["offset"] ~= nil and args["offset"] ~= "" then offset = tonumber(args["offset"]) end local limit = 7 if args["limit"] ~= nil and args["limit"] ~= "" then limit = tonumber(args["limit"]) end -- count the months (#data doesn't work?) local months = table_len(data) s = "" count = 0 -- iterate in reverse, because we want the most recent months for i = months, 1, -1 do		local month = data[i] local broken = false for k, v in pairs(month) do			if count >= offset then local template_args = get_item_template_args(frame, v) s = s .. frame:expandTemplate{title="new texts/item", args=template_args} .. "\n" end count = count + 1
 * limit: how many items to display
 * offset: how many items to skip the display of

if count >= limit + offset then broken = true break end end if broken then break end end return s end

function construct_month_list(frame, items, start_num) local s = "" local count = 0 local first_in_month = true for i=table_len(items), 1, -1 do		local v = items[i]

local template_args = get_item_template_args(frame, v)

s = s .. "#"		if first_in_month then s = s .. "" end s = s .. " " .. frame:expandTemplate{title="new texts/item", args=template_args} .. "\n" count = count + 1 -- reset first_in_month = false end return s, count end

function construct_anchor(id) local anchor = mw.html.create("span") :attr("id", id) return tostring(anchor) end

--[=[ Construct the list of archived items for the given month

Arguments: ]=] function p.archive_list(frame) local args = getArgs(frame)
 * month: the month to show (nil to show whole year)
 * year: the year to show

local args = frame["args"] local month = tonumber(args["month"]) local year = tonumber(args["year"]) -- pull in the data from the relevant archive local data = get_data(args["data_source"], year)

local s = "" local count = 1 local months if month then months = {} months[month] = data[month] else months = data end local count = 0 local max_m = table_len(months) for k, m in pairs(months) do		local numeric_anchor = string.format("%02d", k) s = s .. construct_anchor(numeric_anchor) .. "\n" s = s .. "==" .. month_name(k) .. "==\n\n" --mw.logObject(m) content, m_count = construct_month_list(frame, m, count) s = s .. content count = count + m_count end

return s end

return p