Module:New texts/sandbox

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

local p = {} --p stands for package

local getArgs = require('Module:Arguments').getArgs local yesno = require('Module:Yesno') local error_function = require('Module:Error')['error']

local DEFAULTS = { data_source = "Template:New texts/data", currentyear = tonumber(os.date("%Y")), frame = mw.getCurrentFrame }

function get_data(src, year) local data if not src or src == '' then src = DEFAULTS["data_source"] end year = tonumber(year) or DEFAULTS["currentyear"] src = src .. "/" .. year .. ".json" local data if pcall(function		local jsondata = mw.title.new(tostring(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 creator link/nonlink ]=] function construct_author(str, nowiki) str = mw.text.trim(str) -- strip "Portal:" prefixes if not piped str = string.gsub(str, "%[%[%s*[Pp]ortal:([^|]-)|?%]%]", function (target)		return "" .. target .. ""	end) -- plain portal syntax str = string.gsub(str, "^[Pp]ortal:(.*)$", function (target)		if nowiki then			return target		else			return "" .. target .. ""		end	end) -- strip "Author:" prefixes if not piped str = string.gsub(str, "%[%[%s*[Aa]uthor:([^|]-)|?%]%]", function (target)		return "" .. target .. ""	end) -- plain author syntax str = string.gsub(str, "^[Aa]uthor:(.*)$", function (target)		if nowiki then			return target		else			return "" .. target .. ""		end	end) -- auto-strip bracketed dates if not nowiki then str = string.gsub(str, "^((.*) +%([0-9]+[-–][0-9]+%))$", function (full_target, no_date)			return "" .. no_date .. ""		end, 1) end -- if the string has its own links, return it now if string.match(str, "%[%[") then return str end -- if the author is anonymous if string.match(str, "[uU]nknown") or string.match(str, "[aA]non") or string.match(str, "[aA]nonymous") then if nowiki then return "Anonymous" else return "Anonymous" end end if string.match(str, "[Vv]arious") then return "Various authors" end -- if nowiki then don't make link if nowiki then return str end -- if a pipe is provided if string.match(str, "|") then return "Author:" .. str .. "" end -- make our own piped link return "" .. str .. "" end

--[=[ Format new items ]=] function p._new_texts_item(args) -- parse args local image_name = args.image_name local image_size = mw.text.trim(args.image_size or '100px') local title = args.title or args[1] local display = args.display or title local edition = args.edition local work_date = args['date'] or args[3] local work_type = args['type'] local nowiki = yesno(mw.text.trim(args.nowiki or 'no')) local author = args.author or args[2] local translator = args.translator local translation_date = args.translation_date local editor = args.editor local illustrator = args.illustrator -- image local image = "" if image_name then image = "" -- no link to image's page in the File namespace end -- title local text if title then text = " " .. mw.text.trim(display) .. " " else text = error_function({"Error: No title entered"}) end -- edition if edition then text = text .. ", " .. mw.text.trim(edition) end -- date/type if work_date or work_type then text = text .. " ("		if work_date then			text = text .. mw.text.trim(work_date)			if translation_date then				text = text .. ', '			end		end		if translation_date then			text = text .. 'tr. ' .. mw.text.trim(translation_date)		end		if work_type then			if mw.text.trim(work_type) == "film" then				local type_indicator = DEFAULTS["frame"]:expandTemplate {					title = "media",					args = {						15,						['type'] = "film"					}				}				if work_date then					text = text .. " "				end				text = text .. type_indicator			end		end		text = text .. ")" end -- creators if author or translator or editor or illustrator then text = text .. ' ' -- list name(s) in their own paragraph local creators = {} if author then creators[1] = 'by ' .. construct_author(author, nowiki) end if translator then creators[2] = 'translated by ' .. construct_author(translator, nowiki) end if editor then creators[3] = 'edited by ' .. construct_author(editor, nowiki) end if illustrator then creators[4] = 'illustrated by ' .. construct_author(illustrator, nowiki) end text = text .. table.concat(creators, ', ') .. ' '	end return image .. text end function p.new_texts_item(frame) return p._new_texts_item(getArgs(frame)) end

--[=[ Construct an author link for the given key (e.g "author" or "translator") ]=] function construct_author_from_item(item, key, nowiki) if not item or not item[key] then return nil end

-- explicit nowiki if item[key .. "_nowiki"] then return item[key] end local tab = item[key] if type(tab) ~= 'table' then tab = {tab} end entries = {} for k, v in pairs(tab) do		table.insert(entries, construct_author(v, nowiki)) end return table.concat({table.concat(entries, ", ", 1, #entries - 1), entries[#entries]}, " and ") end

--[=[ Construct an entry using new_texts_item with the data from item ]=] function item_to_new_texts_item(item) -- suppress auto links for the authors, etc local nowiki = yesno(item.nowiki) args = { ["nowiki"] = "yes", -- we always construct this ourselves ["image_name"] = item["image_name"], ["image_size"] = item["image_size"], ["title"] = item["title"], ["author"] = construct_author_from_item(item, "author", nowiki), ["edition"] = item["edition"], ["editor"] = construct_author_from_item(item, "editor", nowiki), ["illustrator"] = construct_author_from_item(item, "editor", nowiki), ["translator"] = construct_author_from_item(item, "translator", nowiki), ["translation_date"] = item["translation_year"], ["date"] = item["year"], }	if item["display"] then args["display"] = item["display"] else -- if title is a subpage of some other title, use subpage as display title mwt = mw.title.new(tostring(title)) if mwt and mwt.isSubpage then args["display"] = mwt.subpageText end end return p._new_texts_item(args) end

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

--[=[ Construct the new texts list from instances of new_texts_item

Arguments:
 * limit: how many items to display
 * offset: how many items to skip the display of

not in use AFAICT ]=] function p._new_texts(args) -- 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 = tonumber(args["offset"]) or 0 local limit = tonumber(args["limit"]) or 7 -- count the months 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 s = s .. item_to_new_texts_item(v) .. "\n" end count = count + 1

if count >= limit + offset then broken = true break end end if broken then break end end return s end function p.new_texts(frame) return p._new_texts(getArgs(frame)) end

function construct_month_list(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] s = s .. "#"		if first_in_month then s = s .. "" end s = s .. " " .. item_to_new_texts_item(v) .. "\n" count = count + 1 -- reset first_in_month = false end return s, count end

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

Arguments: ]=] function p._archive_list(args) local month = tonumber(args["month"]) local year = tonumber(args["year"]) or DEFAULTS["currentyear"] -- pull in the data from the relevant archive local data = get_data(args["data_source"], year)
 * month: the month to show (nil to show whole year)
 * year: the year to show

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 .. tostring(mw.html.create("span"):attr("id", numeric_anchor)) .. "\n" s = s .. "==" .. os.date("%B", os.time({year=2000, month=k, day=1})) .. "==\n\n" --mw.logObject(m) content, m_count = construct_month_list(m, count) s = s .. content count = count + m_count end

return s end function p.archive_list(frame) return p._archive_list(getArgs(frame)) end

--[=[ Construct the process header for the list of archived items for the given year

Arguments: ]=] function p._archive_list_header(args) local year = tonumber(args["year"] or args[1] or mw.title.getCurrentTitle.subpageText) local nextlink if year < DEFAULTS["currentyear"] then nextlink = "" .. year + 1 .. "" end return DEFAULTS["frame"]:expandTemplate { ['title'] = 'Process header', ['args'] = { ['title'] = 'Proofread works added in ' .. year, ['previous'] = "" .. year - 1 .. "", ['next'] = nextlink, ['notes'] = 'These works are from scanned texts and have been proofread at least once, if not fully validated.' }	} end function p.archive_list_header(frame) return p._archive_list_header(getArgs(frame)) end
 * year: the year to show

--[=[ Combine archive_list and archive_list_header to implement Template:New texts archive

Arguments: ]=]
 * year: the year to show

function p.new_texts_archive(frame) local args = getArgs(frame) args.year = args.year or args[1] local header = p._archive_list_header(args) local toc = frame:expandTemplate { ['title'] = 'Right block', ['args'] = { frame:preprocess('') }	}	local list = p._archive_list(args) return header .. toc .. list end

return p