pathshape.sevenpointstar = "M10 0 L12.048 5.747 17.818 3.765 14.602 8.95 19.749 12.225 13.69 12.943 14.339 19.01 10 14.72 5.661 19.01 6.31 12.943 0.251 12.225 5.398 8.95 2.182 3.765 7.952 5.747Z"
pathshape.sevenpointstard = "M10 1.5 L11.7408 6.38495 16.6453 4.70025 13.9117 9.1075 18.28665 11.89125 13.1365 12.50155 13.68815 17.6585 10 14.012 6.31185 17.6585 6.8635 12.50155 1.71335 11.89125 6.0883 9.1075 3.3547 4.70025 8.2592 6.38495 ZM0,10a10,10 0 1,0 20,0a10,10 0 1,0 -20,0zm1.5,0a8.5,8.5 0 1,1 17,0a8.5,8.5 0 1,1 -17,0z"
pathshape.eightpointstar = "M10 0 L11.88 5.46 17.071 2.929 14.54 8.12 20 10 14.54 11.88 17.071 17.071 11.88 14.54 10 20 8.12 14.54 2.929 17.071 5.46 11.88 0 10 5.46 8.12 2.929 2.929 8.12 5.46Z"
pathshape.eightpointstard = "M10 0 L10 1.5 L11.598 6.141 16.01035 3.98965 13.859 8.402 18.5 10 13.859 11.598 16.01035 16.01035 11.598 13.859 10 18.5 8.402 13.859 3.98965 16.01035 6.141 11.598 1.5 10 6.141 8.402 3.98965 3.98965 8.402 6.141ZM0,10a10,10 0 1,0 20,0a10,10 0 1,0 -20,0zm1.5,0a8.5,8.5 0 1,1 17,0a8.5,8.5 0 1,1 -17,0z"
pathshape.ring="M2.6,9.5a7.5,7.5 0 1,0 15,0a7.5,7.5 0 1,0 -15,0zm1,0a6.5,6.5 0 1,1 13,0a6.5,6.5 0 1,1 -13,0z"
pathshape.boxd=pathshape.squared
pathshape.boxdd=pathshape.squaredd
pathshape.ellipsed=pathshape.circled
pathshape.ellipsedd=pathshape.circledd  
local msg={}
local function debugmsg(txt)
table.insert(msg,txt)
end
local pmsg={}
local function previewMsg(txt)
table.insert(pmsg,txt)
end  
local function colorLookup(color)
for c,l in pairs(colorList) do
if string.find(color,c) then return l end
end
return color
end  
local function getColor (color,chk)
local c
local opacity="100"
if not color or color=='' then color='hardgrey' end
if color=="transparent" then return color end
if color=="background1" then color='background' end
if string.byte(color,1,1)==35 and (#color == 7 or #color == 9) then
c=color
elseif string.byte(color,1,1)==35 and #color == 4 then
c=string.sub(color,1,2)..'f'..string.sub(color,3,3)..'f'..string.sub(color,4,4)..'f'
else
local s=color..'1'
s= s:sub(0,s:find("%d")-1)
opacity=string.match(color,"%d+")
if not CTB[s] then s= colorList[s] end -- check for synonyms and translations
if not CTB[s] then debugmsg(mw.addWarning('color = '..color..'. The color name is not defined. Used default grey instead')) end
c=CTB[s] or CTB.hardgrey
end
if opacity and (tonumber(opacity) < 100) and string.find(c,"#")==1 and string.len(c)==7 and opacity~="" then
local hexval=string.format("%x",(math.floor(tonumber(opacity)*2.55)))
c=c..hexval
end
return c
end  
function p.colorvalue -- enable external access to the CTB colorTable values. usage:
local c
if not .args.color or .args.color=='' then c='grey'
else c=string.lower(string.gsub(.args.color,'%s+','')) end
return string.upper(string.sub(getColor(c),2))
end  
local function checkColors(color)
local c=getColor(color,'check')
local opacity =1 -- calculate colour brightness and return black or white for contrast
if c=='transparent' then return c,'#000000',0 end
if not (string.find(c,'#')==1) then return colorCap(c),'#FFFFFF',0 end
if #c>8 then opacity= tonumber('0x'..(string.sub(c,8,9)))/500 end
local r=tonumber('0x'..(string.sub(c,2,3)))/255
local g=tonumber('0x'..(string.sub(c,4,5)))/255
local b=tonumber('0x'..(string.sub(c,6,7)))/255
if 0.2126 * r + 0.7152 * g + 0.0722 * b / opacity < 0.7 then
return c,'#FFFFFF',0.2126 * r + 0.7152 * g + 0.0722 * b / opacity
else return c,'#000000',0.2126 * r + 0.7152 * g + 0.0722 * b / opacity
end
end  
local function morethan(a,b)
a = tonumber(string.match(a, '%f[%d]%d[,.%d]*%f[%D]') or '0')
b = tonumber(string.match(b, '%f[%d]%d[,.%d]*%f[%D]') or '0')
return a>b
end  
local function lessthan(a,b)
if tonumber(string.match(a, '%f[%d]%d[,.%d]*%f[%D]')) then
a = tonumber(string.match(a, '%f[%d]%d[,.%d]*%f[%D]'))
b = tonumber(string.match(b, '%f[%d]%d[,.%d]*%f[%D]') or '0')
end
return a<b
end  
local function getsize(size)
--size1 is between 1 and 3 values, each with px, equating to width,height,corner-rounding
--eg ' ' (spaces are optional) or ''. returns three numbers
local sizeval = {}
for v in string.gmatch(size, "[^px]+") do
table.insert(sizeval,v)
end
sizeval[1] = tonumber(sizeval[1]) or 13
sizeval[2] = tonumber(sizeval[2]) or sizeval[1]
sizeval[3] = tonumber(sizeval[3]) or 0  
return sizeval[1],sizeval[2],sizeval[3]
end  
local function coord2text(coord) -- looks through the output from to find the lat and long decimal values
-- and converts compass points to minus or not-minus, return with separating comma.
local lat = string.match(coord,'[%.%d]+°[NS]')
local lon = string.match(coord,'[%.%d]+°[EW]')
local neg={N="",S="-",W="-",E=""}
return neg[string.match(lat, '[NS]')]..string.match(lat,'[%.%d]+')..","..neg[string.match(lon, '[EW]')]..string.match(lon,'[%.%d]+')
end  
local function convertCoordsTrad (row)
local coords=''
if row and string.find (row,'<span>') then
local a,b=string.find(row,'<span>')
local start=b+1
a,b=string.find(row,"</span>",b)
local finish=a-1
coords=string.sub(row,start,finish)
coords=string.gsub(coords,'; ',',')
end
return coords
end  
local function convertCoords (row)
local start,finish,lat,lon,coords,says
if row then
local a,b=string.find(row,"<spanspan>",b)
end
if start then
coords= string.sub(row,start,finish)
says=""
if string.find(coords,'<span>') then
error("coord error: badly formed coordinates",0)
end
coords=coord2text(coords)
coords = string.sub(row,1,start-1)..coords..string.sub(row,finish+1)
else
coords=row
end
return coords
else
return "Nothing to see here"
end
end  
local function fillCommas(val,max)
local line=''
if not val then line=',' -- ensure there is some content
else line = val --string.lower(string.gsub(val,"%s+","")) -- or strip spaces
end
if string.find(line,',') == 1 then line=' '..line end -- ensure initial comma is not skipped
local _, count=string.gsub(line,",","") -- add enough subsequent commas for all entries
line=line..string.rep(',',max-count)
while(string.find(line,",,") ) do
line=string.gsub(line,",,",", ,") --ensure string.gmatch doesn't ignore any empty items by padding with spaces
end
return line
end  
local function makeLinkBox(,top,wid,label, link)
local linkBoxName='Transparent square.svg'
if visibleLinks or '' =='yes' then linkBoxName='Red hollow square.svg' end
local builder = mw.html.create('div') --display:inline-block;
builder
:cssText('position:absolute;:'..tostring(-1-wid/2)..'px;top:'..tostring(top-1 + math.min(wid/2-12,0) - wid/2)..'px')
:wikitext(string.format( '', linkBoxName, wid+2, link, label ))
return tostring(builder)
end  
local function extractItem(row,searchItem)
-- remove text following a searchItem or start of line, which might be in quote-marks to allow commas
local xend,xstart=1,0
if not row then return *,* end
if searchItem then xend,xstart= string.find(row or '',searchItem or 'image:') end
if not xstart then return string.gsub(string.gsub(row or *,"%b\"\"", *),"%b\'\'", *) or *,'' end
while row:byte(xstart+1) == 32 and xstart<#row do -- skip over any leading spaces
xstart=xstart+1
end
local xbyte=row:byte(xstart+1)
if xbyte == 34 or xbyte == 39 then -- are they wrapped in single or double quotes
xstart=xstart+1
xend=row:find(string.char(xbyte),xstart+1)
else
xend = row:find(',',xstart+1) -- if no quotes, we assume no commas
if not xend then xend=#row+1 end
end -- return residual row and extracted text
return row:sub(0,xstart)..row:sub(xend), row:sub(xstart+1,xend-1)
end  
local function itemCheck(item,ext)
if not item then return nil end
if not ext then ext='' end
return (string.match(item,"[%.%-?%d]+") or '0')..ext
end  
local function stripdivs(line)
return string.gsub(line or '',"%b<>", ' ')
end  
local function splitItem(item,max) -- takes a commas-sep list and returns a table of lowercase items with no spaces, or nil
local r={}
local x=1
item=string.lower(fillCommas(item,max))
for t in string.gmatch(item,"[^,]+") do
r[x]=string.gsub(t,"%s+","")
if r[x]=='' then r[x]= nil else -- residual items might have commas