This is a module to implement logic for MediaWiki:Proofreadpage index template


--[=[
This is a module to implement logic for [[MediaWiki:Proofreadpage index template]]

It doesn't do everything yet, but over time it can accrete functions from
the template, which will become simpler and simpler until it's just an invoke.

Implemented so far:
 * Status categorisation and field
 * Some auxiliary data fields
]=]

local getArgs = require('Module:Arguments').getArgs
local ISO_639 = require('Module:ISO 639')

local p = {} --p stands for package

-- mapping of field ID to field properties
headings = {
	progress = {
		txt = 'Progress',
	},
	oclc = {
		txt = 'OCLC',
	},
    transclusion = {
    	txt = 'Transclusion',
    },
    validation_date = {
    	txt = 'Validated in',
    },
    source = {
    	txt = 'Source'
    },
    place = {
    	txt = 'Location'
    },
    year = {
    	txt = 'Year'
    },
    publisher = {
    	txt = 'Publisher'
    },
    author = {
    	txt = 'Author'
    },
    editor = {
    	txt = 'Editor'
    },
    translator = {
    	txt = 'Translator'
    },
    illustrator = {
    	txt = 'Illustrator'
    },
    doi = {
    	txt = 'DOI'
    }
}

local DEFAULTS = {
	Source = '_empty_',
}

function get_heading(id)
	
	if headings[id] then
		return headings[id]['txt']
	end
	error( "Can't find heading for ID: " .. id )
end

-- mapping from status code to category and status text
index_status_data = {
	T = {
		cat = 'Index Validated',
		txt = 'Done—All pages of the work proper are validated',
	},
	V = {
		cat = 'Index Proofread',
		txt = 'Proofread—All pages of the work proper are proofread, but not all are validated',
	},
	C = {
		cat = 'Index Not-Proofread',
		txt = 'To be proofread',
	},
	MS = {
		cat = 'Index - Ready for Match and Split',
		txt = 'Ready for Match and Split',
	},
	OCR = {
		cat = 'Index - Text Layer Requested',
		txt = 'Source file needs an OCR text layer',
	},
	L = {
		cat = 'Index - File to fix',
		txt = 'Source file must be fixed before proofreading',
		error = true,
	},
	X = {
		cat = 'Index - File to check',
		txt = 'Create a pagelist for the source file before commencing proofreading (to verify file is correct)',
		error = true
	},
	_default = {
		cat = 'Index - Unknown progress',
		txt = 'Unknown progress (template error)',
		error = true,
	}
}

-- construct a basic "field" row
function construct_field(id, content)
	
	if id == nil or content == nil then
		return ''
	end
	
	local title = get_heading( id )
	
	local s = "<tr id=\"index-field-" .. id .. "\">\n"
	s = s .. "<th scope=\"row\" style=\"padding-right:0.50em; text-align:right; vertical-align:top;\">" .. title .. "</th>\n"
	s = s .. "<td style=\"vertical-align:top;\">" .. content .. "</td>\n"
	s = s .. "</tr>\n"
	return s
end

function construct_link(url, text)
	return '[' .. url .. ' ' .. text .. ']'
end

function int_link(target, text)
	return '[' .. '[' .. target .. '|' .. text .. ']]'	
end

-- handy URL generators (remember to use mw.uri.encode on the bits you need to)
local url_gens = {
	oclc = function(id)
		return 'https://www.worldcat.org/oclc/' .. id	
	end,
	ark = function(id)
		return 'https://n2t.net/' .. mw.uri.encode(id)
	end,
	doi = function(id)
		return 'https://doi.org/' .. id
	end
}

-- construct a span which might be classed "error"
function maybe_error_span(text, error) 
	span = mw.html.create('span')
		:wikitext(text)
	if error then
		span:addClass('error')
	end
	return span
end

-- construct the source field:
-- - if a file exists, link it
-- - else just the text
function construct_source_field(source)
	
	local value
	local file = mw.title.new( mw.title.getCurrentTitle().text, 'File' )

	if file.file.exists then
		value = int_link( ':' .. file.fullText, source )
	else
		value = source
	end

	local out = construct_field( 'source', value )
	return out
end

function construct_location_field( loc )
	return construct_field('place', loc)
end

-- construct the status (proofread/validated/...) field
function construct_status_field(status)

	local out = ''
	local sd = index_status_data[status]
	
	if not sd then
		sd = index_status_data['_default']
	end
	
	out = out .. '[[Category:' .. sd['cat'] .. ']]'

	local link_text = tostring(maybe_error_span(sd['txt'], sd['error']))
	local catlink = '[[:Category:' .. sd['cat'] .. '|' .. link_text .. ']]'
	out = out .. construct_field("progress", catlink)

	return out
end

local transclusion_data = {
	yes = {
		cat = 'Fully transcluded',
		text = 'Fully transcluded',
		help = 'The work is fully transcluded, including front and end matter and images'
	},
	notimg = {
		cat = 'Images not fully transcluded',
		text = 'Images not fully transcluded',
		help = 'The work is fully transcluded, but that some images are still missing or need improvement',
	},
	notadv = {
		cat = 'Advertising not transcluded',
		text = 'Advertising not transcluded',
		help = 'The main body of the work is properly transcluded, though front- or end-matter advertising material is not'
	},
	held = {
		cat = 'Transclusion on hold',
		text = 'Transclusion on hold',
		help = 'There is a problem with transcluding the work (which should be explained on the talk page)'
	},
	check = {
		cat = 'Transclusion check required',
		text = 'Transclusion check required',
		help = ' The transclusion of the work is incomplete or needs checking'
	},
	no = {
		cat = 'Index not transcluded',
		text = 'Index not transcluded or unreviewed',
		help = ' This work is not transcluded or has not been reviewed for transclusion'
	}
}

function construct_cat(cat)
	return "[[Category:" .. cat .. "]]"	
end

-- construct the transclusion status
function construct_transclusion_status(status, date)
	
	-- handle templates with no explicit status
	if status == nil then
		status = "no"
	end
	
	local td = transclusion_data[status]
	
	if td == nil then
		error("Unknown index status: " .. status)
	end

	local catlink = '[[:Category:' .. td['cat'] .. '|' .. td['text'] .. ']]'
	local out = construct_field("transclusion", catlink)
	out = out .. construct_cat( td['cat'])
	return out
end

function construct_validated_date(date)
	local cat = 'Indexes validated in ' .. date
	local indicator_text = 'Validated in ' .. date
	
	local out = '[[Category:' .. cat .. ']]'
	
	local catlink = '[[:Category:' .. cat .. '|' .. date .. ']]'
	out = out .. construct_field("validation_date", catlink)
	
	out = out .. '<indicator name="validated-index-date">[[File:Yes Check Circle.svg|15px|link=Category:' .. cat .. '|' .. indicator_text .. '|alt=Validated index page.]]</indicator>'
	return out
end

function getLanguageCat(l)
	-- get the name or nil
	local lang = ISO_639.language_name(l)
	
	if lang then
		return "Index pages of works originally in " .. lang
	end
end

function p.fields(frame)
	
	local args = getArgs(frame)
	
	-- set any defaults
	for k, v in pairs( DEFAULTS ) do
		if args[ k ] == nil then
			args[ k ] = DEFAULTS[ k ]
		end
	end

	local s = ""

	s = s .. construct_field('author', args['Author'])
	s = s .. construct_field('translator', args['Translator'])
	s = s .. construct_field('editor', args['Editor'])
	s = s .. construct_field('illustrator', args['Illustrator'])
	s = s .. construct_field('year', args['Year'])
	s = s .. construct_field('publisher', args['Publisher'])
	s = s .. construct_location_field(args['Address'])
	s = s .. construct_source_field(args['Source'])
	
	s = s .. construct_status_field(args['Progress'])
	
	-- always do this, even if the arg is not set
	s = s .. construct_transclusion_status(args["Transclusion"], args['Transclusion_date'])
	
	if args["Validation_date"] then
		s = s .. construct_validated_date(args["Validation_date"])	
	end

	if args["OCLC"] then
		local link = construct_link(url_gens['oclc'](args["OCLC"]), args['OCLC'])
		s = s .. construct_field("oclc", link)
	end
	
	if args["DOI"] then
		local link = construct_link(url_gens['doi'](args["DOI"]), args['DOI'])
		s = s .. construct_field("doi", link)
	end
	
	-- language categorisations
	if args.Language then
		
		local langs = mw.text.split( args.Language, ',%s?', false)
		for _, lang in pairs(langs) do
			local cat = getLanguageCat(lang)
			if cat then
				s = s .. construct_cat(cat)
			else
				s = s .. construct_cat('Index pages of works originally in an unknown language')
			end
		end
		
		if #langs > 1 then
			s = s .. construct_cat('Index pages of works originally in multiple languages')
		end
	end

	return s
	
end

return p