Module:Tincture

From Multilingual Bookbinding Dictionary
Jump to navigation Jump to search

See Template:{{Tincture}}

Comment: There seems to have been a communication failure.
When the minus sign for 'do not categorize' is specified, it means not only
that the error category is suppressed, it means that no categorization at all should occur.
The possibilities are:

  • automatic categorization
  • categorization as with "cat=..."
  • suppress the (automatic) categorization
and the (automatic) error categorization,
either with "cat=-" or a minus sign like a color code ✓ Done now fixed -- sarang사랑 16:48, 13 August 2020 (UTC)

GPL palettes

In August 2020 a substantial expansion occurred, to generate the GPL palettes, wished by users for heraldry works. A new (automatic and optional) Tincture-parameter 'gpltab=' is used to control whether tincture boxes are generated for files, or table data is generated for GPL. Conversion functions care for hexadecimal/decimal conversion as needed for gpl, and additional parameters are passed to the subtemplates. The palettes are generated on the page Commons:Colour palettes and detailled instructions for maintenance and usage are provided.


local p = {}  -- Tincture

-------------- locals 
local function draw(color, ss, tc, pf, gt)
	return mw.getCurrentFrame():expandTemplate{ title = 'Tincture/draw' .. ss, args = { color, gt, tc = tc, pf = pf } }
end -- local function draw
-- 
local function sortc ( itab, otab, ccode )
	for i, v in ipairs(itab) do
		if v == ccode then 
			table.insert(otab, v)
			return true
		end
	end
	return false
end -- local function sortc
--
local function category(colors, ss, tc, cat, no_error_cat)
	return mw.getCurrentFrame():expandTemplate{ title = 'Tincture/cat' .. ss, args = { table.concat(colors, '/'), tc = tc, cat = cat, ['no error cat'] = no_error_cat and '1' or nil } }
end -- local function category

-- local function: converts 'ddd ddd ddd'  to  '#rrggbb' (or '#rgb')
local function convdh ( p1, p2, p3 )
	local lpar = {}; -- separated by either pipe, slash, minus, comma or space 
	local dect = {}
	local hext = {}
	local numb = {}
	local same = true
	lpar [1] = mw.text.trim ( p1 );
	if p3 == nil then				 -- split-pattern: REGEXP won't work
		if p2 ~= nil then 
			lpar[1] = lpar[1] .. '-' .. mw.text.trim(p2)
		end
		lpar[1] = mw.ustring.gsub (lpar[1], '-', '/', 3)
		lpar[1] = mw.ustring.gsub (lpar[1], ',', '/', 3)
		lpar[1] = mw.ustring.gsub (lpar[1], ' ', '/', 3)
		dect = mw.text.split(lpar[1] or '1/2/3', '/');
	else
		lpar [2] = mw.text.trim ( p2 );
		lpar [3] = mw.text.trim ( p3 );
		dect = lpar;
	end
	for i = 1, 3 do
		numb[i] = tonumber( dect[i] )
		if numb[i] == nil or numb[i] > 255 then
			error (i .. 'value "' .. dect[i] or '?' .. '" cannot be converted to hexadecimal')
--				..dect[1]..','..dect[2]..','..dect[3]..'.'..i)
		end
		hext [i] = mw.ustring.format ( "%X", numb[i] )
		if numb[i] < 16 then hext[i] = '0' .. hext[i] end;
		if mw.ustring.byte ( hext [i], 1 )  ~= mw.ustring.byte ( hext[i], 2 )  then
			same = false
		end
	end
	if same then 
		hext[1] = mw.ustring.sub (hext[1], 2)
		hext[2] = mw.ustring.sub (hext[2], 2)
		hext[3] = mw.ustring.sub (hext[3], 2)
	end
	return '#'..hext[1]..hext[2]..hext[3]
end -- local function convdh


-------------------- local / global ----------``-------------------------------
-- local / global function: converts h → d: #rrggbb or #rgb to table {rr, gg, bb}
function p.convht ( frame )
	local gpar = {};	
	local hexv =  nil;
	local hexi =  '000';
	local hwxt =  '0';
 	local gpar = frame.args;
 	if gpar then 
 		hexv = tostring (gpar[1]);	-- global
 	else	 
		hexv = tostring ( frame );	-- local
 	end

	hexv = mw.text.trim( hexv )
	if  mw.ustring.sub ( hexv, 1, 1 ) == '#' then 
		hexi = mw.ustring.sub (hexv, 2)
		hext = '1'
	elseif mw.ustring.sub ( hexv, 1, 3) == '\\35' then 
		hexi = mw.ustring.sub (hexv, 4)
		hext = '2'
	elseif mw.ustring.sub ( hexv, 1, 5) == '&#35;' then 
		hexi = mw.ustring.sub (hexv, 6)
		hext = '3'
	elseif mw.ustring.sub ( hexv, 1, 6) == '&#035;' then 
		hexi = mw.ustring.sub (hexv, 7)
		hext = '4'
	elseif mw.ustring.sub ( hexv, 1, 6) == '&#x23;' then 
		hexi = mw.ustring.sub (hexv, 7, #hexv)
		hext = '5'
	elseif mw.ustring.sub ( hexv, 1, 7) == '&#x023;' then 
		hexi = mw.ustring.sub (hexv, 8, #hexv)
		hext = '6'
	else	
		hext = '9'
		error ('value "' .. hexv .. '" cannot be converted to decimal ' .. #hexv )
	end
	if #hexi ~= 3 and #hexi ~= 6 then
		error ('value "' .. hexi .. '" with length ' .. #hexi .. ' are invalid' )
	end
--	error ('value "' .. hexv .. '" type ' .. hext .. ' = ' .. hexi)
	local dec  =  {};
	for i = 1, 3 do
		if #hexi == 3 then
			dec [i] = tonumber ( mw.ustring.sub (hexi, i, i)..mw.ustring.sub (hexi, i, i), 16 ) 
		else
			dec [i] = tonumber ( mw.ustring.sub (hexi, 2*i - 1, 2*i), 16 ) 
		end
	end	
	return dec;
end -- function convht

-- local / global function: converts h ← d '#rrggbb' or '#rgb' and returns 'ddd ddd ddd'
function p.convhd ( frame )
	local gpar = frame.args;
	if gpar then decval = p.convht (gpar[1]);	-- global
		else	 decval = p.convht ( frame );	-- local
	end
	return decval[1]..' '..decval[2]..' '..decval[3]
end -- function convhd

-- local / global function: converts h → d'#rrggbb' or '#rgb' and returns 'ddd ddd ddd' formatted
function p.convhdf ( frame )
	local gpar = frame.args;
	if gpar then dtab = p.convht (gpar[1]);	-- global
			else dtab = p.convht ( frame );	-- local
	end
	local dtxt = '&nbsp;'
	for i = 1, 3 do
		if dtab[i] < 100 then
			if dtab[i] < 10 then 
				dtxt = dtxt .. ' '
			end
			dtxt = dtxt .. '&nbsp;'
		end
		dtxt = dtxt .. ' ' .. tostring ( dtab [i] ) 
	end
	local contrast = '0';
	if  dtab [1] + dtab [2] + dtab [3] < 400 then 
		  contrast = 'F'; 
	end
-- TEST ----------
--	local contval = dtab [1] + dtab [2] + dtab [3]
-- 	contrast = contrast .. ' - ';
--	if contval < 100 then
--		if contval < 10 then 
--			contrast = contrast .. '&nbsp;'
--		end
--		contrast = contrast .. '&nbsp;'
--	end
-- 	contrast = contrast .. tostring ( contval ); 
-- TEST ----------
	dtxt = contrast .. dtxt; 
	return dtxt
end -- function convhdf

-- function returns contrast color
function p.titcolor ( frame )
	local gpar = frame.args
	local decval = p.convhdf ( gpar[1] );
	if mw.ustring.sub ( decval, 1, 1 ) == 'F'
		then return 'FFF'
		else return '000'
	end
end -- function titcolor 

-- global function convgpl: gets #rgb, contrast, name; returns line formatted
function p.convgpl ( frame )
	local gpar = frame.args;
	local line = p.convhdf ( gpar [1] );						-- convert #rgb  
	local expl = mw.ustring.sub ( line, 2) .. ' ' .. gpar [1];	-- d d d   #rgb
	if #gpar[1] == 4 then
		expl = expl .. '&nbsp; &nbsp;'
	end
	local contrast = gpar [2] or '#001'
--	expl = expl .. ' ' .. contrast;								-- contrast		-test 
	if mw.ustring.sub ( contrast, 2, 2) == mw.ustring.sub ( line, 1, 1) 
		then	expl = expl .. '<tt> </tt>'
		else	expl = expl .. '<tt>·</tt>'
	end
	expl = expl .. gpar [3];									-- name
	return expl
end -- function convgpl


-- global function convert:  gets 3 num, returns hex and dec formatted
function p.convert ( frame )
	local gpar = frame.args;
	local hcod = convdh ( gpar[1], gpar[2], gpar[3] );
	local fnum = p.convhdf (hcod)
	return '&#35;' .. mw.ustring.sub ( hcod, 2 ) .. mw.ustring.sub ( fnum, 2);
end -- function convert


--  ============================================================================
--  main function tincture
function p.main (frame)
	local getArgs = require( 'Module:Arguments' ).getArgs
	local args = getArgs(frame)
	local ss = args.ss  or '0'
	if ss == '≈' then ss = '0' end
	local tc = args.tc
	local pf = args.pf
	local gt = args.gpltab or ""
	local align = 'tincturebox-left'
	local error_cat = true
	local InFi = (args['+'] == '+')
	local cols = args
	local colors = {}
	local box = {}
	local tab = {}
	local out = {}
	local ordtab = { }
	local insert = false

	if gt == "" then 
		if mw.title.getCurrentTitle().namespace == 4 then gt = '3' 
		else gt = '1'
		end
	end
	if gt == "2" or gt == "3" then
		InFi = true
		error_cat = false
	end

	ss = mw.ustring.upper( ss )
	if type(args[1]) == 'string' and args[1]:sub(1, 6) == '<table' then
		return args[1]
	end

	if args[2] == nil  then
		cols = mw.text.split(args[1] or '', '%s*/%s*')
	end
	if cols.ss	then
		ss =  mw.ustring.upper( cols.ss )
	end 	
	for _, v in ipairs(cols) do
		if not v or v == '' then
			break
		elseif v == '-' then
			error_cat = false
		elseif v == '+' then
			InFi = true
		elseif mw.ustring.sub( v, 1, 3 ) == 'ss=' then  -- any case when ss=
			ss = mw.ustring.upper( mw.ustring.sub( v, 4 ) )
		elseif mw.ustring.len( v ) == 2 
		   and v == mw.ustring.upper( v ) then  -- belongs to character class %u
			ss = v
		else
			table.insert(colors, v)
		end
	end
	
--  0) headline and boxes
	if gt == "2" or gt =="3" then
		table.insert(out, frame:expandTemplate{title='=', args={'<h4>GPLtab '..draw('gpltabnam',ss,'','','tab')..'</h4>'}})
	end
	for i, v in ipairs(colors) do
		box[i] = draw(v, ss, tc, pf, 'box')
	end

-- 1) cat: sorted table
	if error_cat == true then
		insort = sortc (colors, ordtab, 'a' )
		insort = sortc (colors, ordtab, 'A' )
		insort = sortc (colors, ordtab, 'o' )
		insort = sortc (colors, ordtab, 'b' )
		insort = sortc (colors, ordtab, 'B' )
		insort = sortc (colors, ordtab, 'c' )
		insort = sortc (colors, ordtab, 'C' )
		insort = sortc (colors, ordtab, 'g' )
		insort = sortc (colors, ordtab, 'n' )
		insort = sortc (colors, ordtab, 'p' )
		insort = sortc (colors, ordtab, 's' )
		insort = sortc (colors, ordtab, 't' )
		insort = sortc (colors, ordtab, 'v' )
		insort = sortc (colors, ordtab, 'x' )
		table.insert(box, category(ordtab, ss, tc, args.cat, no_error_cat))
	end
	
-- 2) box
	if gt == "1" or gt =="3" then
		if args.align == 'right' or args.align == 'center' then
			align = 'tincturebox-' .. align
		end
		local frame = mw.getCurrentFrame()
		text = frame:extensionTag('templatestyles', '', { src = 'Tincture/styles.css' }) ..
			'<div class="tincturebox ' .. align .. '">' .. table.concat(box) .. '</div>'
		if InFi then
			local name = mw.getContentLanguage():ucfirst(frame:expandTemplate{ title = 'I18n/COA', args = { 'tincture' } })
			local link = ' ([[Template:Tincture/draw'..ss..'|'..ss..']])'
			if ss ~= '' and ss ~= '0' then name = name .. link end 
			table.insert(out, frame:expandTemplate{ title = 'InFi', args = { name, text } })
		else
			table.insert(out, text )
		end
	end
	
-- 3) tab
	if gt == "2" or gt =="3" then
		table.insert(out, frame:expandTemplate{ title = '=', args = { "&#35;<br>" } })
		for i, v in ipairs(colors) do
			table.insert(out, draw( v, ss, tc, pf, 'tab') ) 
		end
		table.insert(out, frame:expandTemplate{ title = '=', args = { "<br><br>" } })
	end
	return table.concat(out)
end -- function main / tincture 

return p;