Module:New texts/sandbox
Appearance
This is the module sandbox page for Module:New texts (diff). |
Functions to provide lists of new works shown at {{new texts}} (and therefore also the Main page)
Add work data to Template:New texts/data/2024.json.
Archived data is pulled from Template:New texts/data/YYYY.json
.
Functions
[edit]new_texts
: function called by {{new texts}} for a list of recent new text- limit: how many items to show
- skip: how many items to skip
- data_source: alternative source base title for data (default is
Template:New texts/data
. Year and.json
are appended.
archive_list
: function called by {{new texts archive}} for a list of new texts by year- year: the year to show, omit for current year
- month: the month to show, omit for entire year
- data_source: alternative source base title for data (default is
Template:New texts/data
. Year and.json
are appended.
Archives
[edit]-- 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 "[[Portal:" .. target .. "|" .. target .. "]]"
end)
-- plain portal syntax
str = string.gsub(str, "^[Pp]ortal:(.*)$", function (target)
if nowiki then
return target
else
return "[[Portal:" .. target .. "|" .. target .. "]]"
end
end)
-- strip "Author:" prefixes if not piped
str = string.gsub(str, "%[%[%s*[Aa]uthor:([^|]-)|?%]%]", function (target)
return "[[Author:" .. target .. "|" .. target .. "]]"
end)
-- plain author syntax
str = string.gsub(str, "^[Aa]uthor:(.*)$", function (target)
if nowiki then
return target
else
return "[[Author:" .. target .. "|" .. 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 "[[Author:" .. full_target .. "|" .. 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 "[[Portal:Anonymous texts|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 "[[Author:" .. str .. "|" .. 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 = "[[File:" .. mw.text.trim(image_name) .. "|right|" .. image_size .. "|link=]]" -- no link to image's page in the File namespace
end
-- title
local text
if title then
text = "<span style='font-style:italic; font-weight:bold;'>[[" .. mw.text.trim(title) .. "|" .. mw.text.trim(display) .. "]]</span>"
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 .. '<div style="margin-left:1em; font-size:83%;" class="creators">' -- 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, ', ') .. '</div>'
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 .. "<li value=\"" .. (start_num + 1) .. "\">"
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:
* month: the month to show (nil to show whole year)
* year: the year to show
]=]
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)
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:
* year: the year to show
]=]
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 = "[[Wikisource:Works/" .. year + 1 .. "|" .. year + 1 .. "]]"
end
return DEFAULTS["frame"]:expandTemplate {
['title'] = 'Process header',
['args'] = {
['title'] = 'Proofread works added in ' .. year,
['previous'] = "[[Wikisource:Works/" .. year - 1 .. "|" .. year - 1 .. "]]",
['next'] = nextlink,
['notes'] = 'These works are from [[Help:DjVu files|scanned texts]] and have been [[Help:proofread|proofread]] at least once, if not fully validated.'
}
}
end
function p.archive_list_header(frame)
return p._archive_list_header(getArgs(frame))
end
--[=[
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('__TOC__')
}
}
local list = p._archive_list(args)
return header .. toc .. list
end
return p