<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3AUnicode_chart</id>
	<title>Module:Unicode chart - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3AUnicode_chart"/>
	<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Unicode_chart&amp;action=history"/>
	<updated>2026-05-23T21:38:39Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://stockhub.co/index.php?title=Module:Unicode_chart&amp;diff=147419&amp;oldid=prev</id>
		<title>imported&gt;Cobaltcigs: several changes to range handling to allow, among other things, referring to predefined subsets</title>
		<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Unicode_chart&amp;diff=147419&amp;oldid=prev"/>
		<updated>2019-09-20T13:16:34Z</updated>

		<summary type="html">&lt;p&gt;several changes to range handling to allow, among other things, referring to predefined subsets&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local mArguments = require(&amp;#039;Module:Arguments&amp;#039;)&lt;br /&gt;
local mTableTools = require(&amp;#039;Module:TableTools&amp;#039;)&lt;br /&gt;
local mUnicode = require(&amp;#039;Module:Unicode data&amp;#039;)&lt;br /&gt;
local mAge = require(&amp;#039;Module:Unicode data/age&amp;#039;)&lt;br /&gt;
local mAliases = require(&amp;#039;Module:Unicode data/aliases&amp;#039;)&lt;br /&gt;
local mBlocks = require(&amp;#039;Module:Unicode data/blocks&amp;#039;)&lt;br /&gt;
local mCategory = require(&amp;#039;Module:Unicode data/category&amp;#039;)&lt;br /&gt;
local mControl = require(&amp;#039;Module:Unicode data/control&amp;#039;)&lt;br /&gt;
local mScripts = require(&amp;#039;Module:Unicode data/scripts&amp;#039;)&lt;br /&gt;
local mVersion = require(&amp;#039;Module:Unicode data/version&amp;#039;)&lt;br /&gt;
local mEntities = require(&amp;#039;Module:Unicode chart/entities&amp;#039;)&lt;br /&gt;
local mDisplay = require(&amp;#039;Module:Unicode chart/display&amp;#039;)&lt;br /&gt;
local mSubsets = require(&amp;#039;Module:Unicode chart/subsets&amp;#039;)&lt;br /&gt;
local p = {} &lt;br /&gt;
local args = {}&lt;br /&gt;
local config = {&lt;br /&gt;
	useFontCss = true,&lt;br /&gt;
	showRefs = true,&lt;br /&gt;
	infoMode = false,&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
local refGrammar = {&lt;br /&gt;
	order = { &amp;quot;white&amp;quot;, &amp;quot;combining&amp;quot;, &amp;quot;control&amp;quot;, &amp;quot;format&amp;quot;, &amp;quot;reserved&amp;quot;, &amp;quot;nonchar&amp;quot;, &amp;quot;skip&amp;quot; },&lt;br /&gt;
	white = {&lt;br /&gt;
		format = &amp;#039;White area%s within light green cell%s show%s %s of %sotherwise invisible [[whitespace character]]%s.&amp;#039;,&lt;br /&gt;
		singular = {  &amp;#039;&amp;#039;,  &amp;#039;&amp;#039;, &amp;#039;s&amp;#039;, &amp;#039;the size&amp;#039;, &amp;#039;an &amp;#039;,  &amp;#039;&amp;#039; },&lt;br /&gt;
		plural   = { &amp;#039;s&amp;#039;, &amp;#039;s&amp;#039;,  &amp;#039;&amp;#039;,    &amp;#039;sizes&amp;#039;,    &amp;#039;&amp;#039;, &amp;#039;s&amp;#039; },&lt;br /&gt;
		count = 0,&lt;br /&gt;
		},&lt;br /&gt;
	combining = {&lt;br /&gt;
		format = &amp;#039;Yellow cell%s with [[dotted circle]]%s (◌) indicate%s %s[[combining character]]%s.&amp;#039;,&lt;br /&gt;
		singular = {  &amp;#039;&amp;#039;,  &amp;#039;&amp;#039;, &amp;#039;s&amp;#039;, &amp;#039;a &amp;#039;, &amp;#039;&amp;#039; },&lt;br /&gt;
		plural   = { &amp;#039;s&amp;#039;, &amp;#039;s&amp;#039;,  &amp;#039;&amp;#039;,   &amp;#039;&amp;#039;,&amp;#039;s&amp;#039; },&lt;br /&gt;
		count = 0,&lt;br /&gt;
		},&lt;br /&gt;
	control = {&lt;br /&gt;
		format = &amp;#039;Light blue cell%s indicate%s %snon-printable [[control character]]%s.&amp;#039;,&lt;br /&gt;
		singular = {  &amp;#039;&amp;#039;, &amp;#039;s&amp;#039;, &amp;#039;a &amp;#039;,  &amp;#039;&amp;#039; },&lt;br /&gt;
		plural   = { &amp;#039;s&amp;#039;,  &amp;#039;&amp;#039;,   &amp;#039;&amp;#039;, &amp;#039;s&amp;#039; },&lt;br /&gt;
		count = 0,&lt;br /&gt;
		},&lt;br /&gt;
	format = {&lt;br /&gt;
		format = &amp;#039;Pink cell%s indicate%s %s[[format character]]%s.&amp;#039;,&lt;br /&gt;
		singular = {  &amp;#039;&amp;#039;, &amp;#039;s&amp;#039;, &amp;#039;a &amp;#039;,  &amp;#039;&amp;#039; },&lt;br /&gt;
		plural   = { &amp;#039;s&amp;#039;,  &amp;#039;&amp;#039;,   &amp;#039;&amp;#039;, &amp;#039;s&amp;#039; },&lt;br /&gt;
		count = 0,&lt;br /&gt;
		},&lt;br /&gt;
	reserved = {&lt;br /&gt;
		format = &amp;#039;Gray cell%s indicate%s %sunassigned (reserved) code point%s.&amp;#039;,&lt;br /&gt;
		singular = { &amp;#039;&amp;#039;, &amp;#039;s&amp;#039;, &amp;#039;an &amp;#039;, &amp;#039;&amp;#039; },&lt;br /&gt;
		plural   = { &amp;#039;s&amp;#039;, &amp;#039;&amp;#039;,     &amp;#039;&amp;#039;, &amp;#039;s&amp;#039; },&lt;br /&gt;
		count = 0,&lt;br /&gt;
		},&lt;br /&gt;
	nonchar = {&lt;br /&gt;
		format = &amp;#039;Black cell%s indicate%s %s[[noncharacter]]%s (code point%s that %s guaranteed never to be assigned as %sencoded character%s in the Unicode Standard).&amp;#039;,&lt;br /&gt;
		singular = {  &amp;#039;&amp;#039;,&amp;#039;s&amp;#039;,&amp;#039;a &amp;#039;, &amp;#039;&amp;#039;, &amp;#039;&amp;#039;, &amp;#039;is&amp;#039;,&amp;#039;an &amp;#039;, &amp;#039;&amp;#039; },&lt;br /&gt;
		plural   = { &amp;#039;s&amp;#039;,&amp;#039;&amp;#039;,   &amp;#039;&amp;#039;,&amp;#039;s&amp;#039;,&amp;#039;s&amp;#039;,&amp;#039;are&amp;#039;,   &amp;#039;&amp;#039;,&amp;#039;s&amp;#039; },&lt;br /&gt;
		count = 0,&lt;br /&gt;
		},&lt;br /&gt;
	skip = {&lt;br /&gt;
		format = &amp;#039;Black horizontal line%s indicate%s non-consecutive rows.&amp;#039;,&lt;br /&gt;
		singular = { &amp;#039;&amp;#039;, &amp;#039;s&amp;#039; },&lt;br /&gt;
		plural   = { &amp;#039;s&amp;#039;, &amp;#039;&amp;#039; },&lt;br /&gt;
		count = 0,&lt;br /&gt;
		},&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
local infoTable = {}&lt;br /&gt;
local err = {&lt;br /&gt;
	format = function(...) return error(string.format(...), 0) end,&lt;br /&gt;
	blockName = &amp;#039;Unrecognized block name &amp;quot;%s&amp;quot; does not match those defined in [[Module:Unicode data/blocks]]&amp;#039;,&lt;br /&gt;
	refGarbage = &amp;#039;Refs contain non-ref content: &amp;quot;%s&amp;quot;&amp;#039;,&lt;br /&gt;
	badRange = &amp;#039;Invalid range &amp;quot;%s&amp;quot; specified. Ranges must match [[regular expression]] &amp;lt;code&amp;gt;^[0-9A-F]+(?:[-–][0-9A-F]+)?$&amp;lt;/code&amp;gt;&amp;#039;,&lt;br /&gt;
	noRange = &amp;#039;Please specify a valid block name, range of code points, or named subset&amp;#039;,&lt;br /&gt;
	badSubset = &amp;#039;Invalid subset &amp;quot;%s&amp;quot; specified&amp;#039;,&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
function debug(...)&lt;br /&gt;
	local a = {...}&lt;br /&gt;
	if type(a[1]) ~= &amp;quot;string&amp;quot; then mw.log(a[1]) return end&lt;br /&gt;
	local _,c = string.gsub(string.gsub(a[1], &amp;quot;%%%%&amp;quot;, &amp;quot;&amp;quot;), &amp;quot;%%&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
	for i = 1,math.max(#a, c+1) do &lt;br /&gt;
		if (type(a[i]) == &amp;quot;nil&amp;quot; or type(a[i]) == &amp;quot;boolean&amp;quot;) then a[i] = tostring(a[i]) end&lt;br /&gt;
	end&lt;br /&gt;
	return mw.log(string.format(unpack(a)))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
table.concat2 = function(t1,t2) for i=1,#t2 do t1[#t1+1] = t2[i] end return t1 end&lt;br /&gt;
table.last = function(t) if t then return t[#t] else return nil end end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
string.formatAll = function(fmt, t)&lt;br /&gt;
	for i=1,#t do t[i] = string.format(fmt, t[i]) end&lt;br /&gt;
	return t&lt;br /&gt;
end&lt;br /&gt;
function getUtf8(n)&lt;br /&gt;
	local t = {}&lt;br /&gt;
	for b in mw.ustring.char(n):gmatch(&amp;#039;.&amp;#039;) do table.insert(t, b:byte()) end&lt;br /&gt;
	return t&lt;br /&gt;
end&lt;br /&gt;
function getUtf16(n)&lt;br /&gt;
	if(n &amp;lt; 0 or n &amp;gt; 0x10FFFF) then return nil end&lt;br /&gt;
	if(n &amp;gt;= 0xD800 and n &amp;lt;= 0xDFFF) then return nil end&lt;br /&gt;
	if(n &amp;lt; 0x10000) then return { n } end&lt;br /&gt;
	local u = (n - 0x10000)&lt;br /&gt;
	local low = (u % 0x400)&lt;br /&gt;
	local high = (u - low) / 0x400&lt;br /&gt;
	return { 0xD800 + high, 0xDC00 + low }&lt;br /&gt;
end&lt;br /&gt;
function getUtf16toStr(n) &lt;br /&gt;
	t = getUtf16(n)&lt;br /&gt;
	for i=1,#t do t[i] = string.format(&amp;quot;0x%04X&amp;quot;, t[i]) end&lt;br /&gt;
	return t&lt;br /&gt;
end&lt;br /&gt;
function getUtf8toStr(n)  return string.formatAll(&amp;quot;0x%02X&amp;quot;, getUtf8(n) ) end&lt;br /&gt;
function getUtf16toStr(n) return string.formatAll(&amp;quot;0x%04X&amp;quot;, getUtf16(n)) end&lt;br /&gt;
&lt;br /&gt;
function makeRange(a,b)&lt;br /&gt;
	if(b) then return {first=math.min(a,b),last=math.max(a,b)} else return {first=a,last=a} end&lt;br /&gt;
end&lt;br /&gt;
function rangeContains(r, n) return (n &amp;gt;= r.first and n &amp;lt;= r.last) end&lt;br /&gt;
function rangeCombine(r1,r2) return {first=math.min(r1.first,r2.first), last=math.max(r1.last,r2.last)} end&lt;br /&gt;
function rangesMergeable(r1,r2)&lt;br /&gt;
	if not r1 or not r2 then return false end&lt;br /&gt;
	return rangeContains(r1, r2.first-1) or rangeContains(r1, r2.last+1) or&lt;br /&gt;
		rangeContains(r2, r1.first-1) or rangeContains(r2, r1.last+1)&lt;br /&gt;
end&lt;br /&gt;
function rangeSort(r1,r2)&lt;br /&gt;
	if r1 and not r2 then return true end&lt;br /&gt;
	if not r1 then return false end&lt;br /&gt;
	if r1.first == r2.first then return r1.last &amp;lt; r2.last end&lt;br /&gt;
	return r1.first &amp;lt; r2.first&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function parseHex(s) if s then return tonumber(s,16) else return nil end end&lt;br /&gt;
function parseRanges(str)&lt;br /&gt;
	local r = {}&lt;br /&gt;
	str = str:upper():gsub(&amp;quot;AND&amp;quot;, &amp;quot;,&amp;quot;) --avoid parsing A and D as single control chars in row U+000x, whoops&lt;br /&gt;
	for x in mw.ustring.gmatch(str, &amp;quot;[%dA-FUX%+%-]+&amp;quot;) do&lt;br /&gt;
		local a,b = mw.ustring.match(x, &amp;quot;^[UX0%+%-]*([%dA-F]+)[-–][UX0%+%-]*([%dA-F]+)$&amp;quot;)&lt;br /&gt;
		if(a and b) then&lt;br /&gt;
			table.insert(r, makeRange(parseHex(a),parseHex(b)))&lt;br /&gt;
		else&lt;br /&gt;
			local c = mw.ustring.match(x, &amp;quot;^[UX0%+%-]*([%dA-F]+)$&amp;quot;)&lt;br /&gt;
			if c then&lt;br /&gt;
				table.insert(r, makeRange(parseHex(c)))&lt;br /&gt;
			else&lt;br /&gt;
				err.format(err.badRange, x)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	for i = #r,2,-1 do for j = i-1,1,-1 do if rangesMergeable(r[i], r[j]) then&lt;br /&gt;
		r[j] = rangeCombine(r[i], r[j]) r[i] = nil&lt;br /&gt;
	end end end&lt;br /&gt;
	r2 = {}&lt;br /&gt;
	for k,v in pairs(r) do table.insert(r2,v) end&lt;br /&gt;
	table.sort(r2, rangeSort)&lt;br /&gt;
	return r2&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Official way to match property values that are strings (including block names):&lt;br /&gt;
-- Ignore case, whitespace, underscore (&amp;#039;_&amp;#039;), hyphens, and any initial prefix string &amp;quot;is&amp;quot;.&lt;br /&gt;
-- http://www.unicode.org/reports/tr44/#UAX44-LM3&lt;br /&gt;
local function propertyValueKey(val)&lt;br /&gt;
	return val:lower():gsub(&amp;#039;^is&amp;#039;, &amp;#039;&amp;#039;):gsub(&amp;#039;[-_%s]+&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function getDefaultRange(blockName)&lt;br /&gt;
	if not blockName then return nil end &lt;br /&gt;
	blockName = propertyValueKey(blockName)&lt;br /&gt;
	for i,b in ipairs(mBlocks) do&lt;br /&gt;
		if blockName == propertyValueKey(b[3]) then return makeRange(b[1],b[2]) end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function getAge(n)&lt;br /&gt;
	local a = mAge.singles[n]&lt;br /&gt;
	if(a) then return a end&lt;br /&gt;
	for k,v in pairs(mAge.ranges) do&lt;br /&gt;
		if n &amp;gt;= v[1] and n &amp;lt;= v[2] then return v[3] end&lt;br /&gt;
	end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
function getCategory(n)&lt;br /&gt;
	local cc = mUnicode.lookup_category(n)&lt;br /&gt;
	local cat = mCategory.long_names[cc]&lt;br /&gt;
	if cat then return string.gsub(string.lower(cat), &amp;quot;_&amp;quot;, &amp;quot; &amp;quot;) else return nil end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function getControlAbbrs(n) return getAliasValues(n, &amp;quot;abbreviation&amp;quot;) end&lt;br /&gt;
function getControlAliases(n) return table.concat2(getAliasValues(n, &amp;quot;control&amp;quot;), getAliasValues(n, &amp;quot;figment&amp;quot;)) end&lt;br /&gt;
&lt;br /&gt;
function getAliasValues(n, key)&lt;br /&gt;
	local b,r = mAliases[n], {}&lt;br /&gt;
	if b then for i,t in ipairs(b) do&lt;br /&gt;
		if(not key or t[1] == key) then table.insert(r, t[2]) end &lt;br /&gt;
	end end&lt;br /&gt;
	return r&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function getAnchorId(n) return string.format(&amp;quot;info-%04X&amp;quot;, n) end&lt;br /&gt;
function getTarget(n)&lt;br /&gt;
	if(config.infoMode) then return &amp;quot;#&amp;quot;..getAnchorId(n) end&lt;br /&gt;
	local t = getParamNx(&amp;quot;link&amp;quot;, n, true) &lt;br /&gt;
	if(t==&amp;quot;yes&amp;quot;) then t = char end&lt;br /&gt;
--&amp;quot;ifexist&amp;quot; is a deleted feature, now recognized equal to &amp;quot;no&amp;quot; to avoid linking to the article [[Ifexist]], which incidentally doesn&amp;#039;t exist.&lt;br /&gt;
	if(t==&amp;quot;no&amp;quot; or t==&amp;quot;ifexist&amp;quot;) then t = nil end &lt;br /&gt;
	if(t==&amp;quot;wikt&amp;quot;) then t = &amp;quot;:wikt:&amp;quot;..mw.ustring.char(n) end&lt;br /&gt;
	return t&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function getNamedEntity(n)&lt;br /&gt;
	local e = mEntities[n]&lt;br /&gt;
	if e then return string.gsub(e, &amp;quot;&amp;amp;&amp;quot;, &amp;quot;&amp;amp;amp;&amp;quot;) else return nil end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function getEntities(n)&lt;br /&gt;
	local entH = getNamedEntity(n)&lt;br /&gt;
	local entN = string.format(&amp;#039;&amp;amp;amp;#%d;&amp;#039;, n)&lt;br /&gt;
	local entXN = string.format(&amp;#039;&amp;amp;amp;#x%X;&amp;#039;, n)&lt;br /&gt;
	local t = {}&lt;br /&gt;
	if(entH) then table.insert(t, entH) end&lt;br /&gt;
	table.insert(t, entN)&lt;br /&gt;
	table.insert(t, entXN)&lt;br /&gt;
	return t&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function isControl(n) return mUnicode.lookup_control(n) == &amp;quot;control&amp;quot; end&lt;br /&gt;
function isFormat(n) return mUnicode.lookup_control(n) == &amp;quot;format&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
function isBadTitle(str)&lt;br /&gt;
	if str == nil then return true end&lt;br /&gt;
	if type(str) == &amp;quot;number&amp;quot; then str = mw.ustring.char(str) end&lt;br /&gt;
	if not mUnicode.is_valid_pagename(str) then return true end&lt;br /&gt;
	if mw.ustring.match(str, &amp;quot;[\&amp;lt;\&amp;gt;]&amp;quot;) then return true end&lt;br /&gt;
	if #str == 1 and mw.ustring.match(str, &amp;quot;[\/\.\:\_&amp;#x338;]&amp;quot;) then return true end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function makeVersionRef()&lt;br /&gt;
	if(not config.showRefs or mVersion == nil or mVersion == &amp;#039;&amp;#039;) then return &amp;#039;&amp;#039;&lt;br /&gt;
	else return string.format(&amp;#039;&amp;lt;ref name=&amp;quot;version&amp;quot;&amp;gt;As of [[Unicode#Versions|Unicode version]] %s.&amp;lt;/ref&amp;gt;&amp;#039;, mw.text.nowiki(mVersion)) end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function makeAutoRefs()&lt;br /&gt;
	if not config.showRefs then return &amp;#039;&amp;#039; end&lt;br /&gt;
	local refs = {}&lt;br /&gt;
	for i,refType in ipairs(refGrammar.order) do&lt;br /&gt;
		local g = refGrammar[refType]&lt;br /&gt;
		local refText = nil&lt;br /&gt;
		if(g.count == 1) then refText = string.format(g.format, unpack(g.singular)) end&lt;br /&gt;
		if(g.count &amp;gt;= 2) then refText = string.format(g.format,   unpack(g.plural)) end&lt;br /&gt;
		if(refText) then&lt;br /&gt;
			table.insert(refs, string.format(&amp;#039;&amp;lt;ref name=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/ref&amp;gt;&amp;#039;, refType, refText))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(refs)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--TODO: remove any garbage around/between refs and downgrade this to a warning&lt;br /&gt;
function sanitizeUserRefs(refTxt)&lt;br /&gt;
	if not config.showRefs then return &amp;#039;&amp;#039; end &lt;br /&gt;
	local trim1 = mw.text.killMarkers(refTxt)&lt;br /&gt;
	local trim2 = mw.ustring.gsub(trim1, &amp;#039;%s&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
	if string.len(trim2) &amp;gt; 0 then err.format(err.refGarbage, mw.text.nowiki(trim1))&lt;br /&gt;
	else return refTxt end&lt;br /&gt;
end&lt;br /&gt;
function makeSpan(str, title, repl)&lt;br /&gt;
	local c,t = &amp;#039;&amp;#039;,&amp;#039;&amp;#039;&lt;br /&gt;
	if title then t = string.format(&amp;#039; title=&amp;quot;%s&amp;quot;&amp;#039;, title) end&lt;br /&gt;
	if repl then&lt;br /&gt;
		local s,x = mw.ustring.gsub(str, &amp;#039;%s+&amp;#039;, &amp;#039;\n&amp;#039;)&lt;br /&gt;
		if x &amp;gt; 0 then c = string.format(&amp;#039; class=&amp;quot;small-%s&amp;quot;&amp;#039;, x) str = s end&lt;br /&gt;
	end&lt;br /&gt;
	return string.format(&amp;#039;&amp;lt;span %s%s&amp;gt;%s&amp;lt;/span&amp;gt;&amp;#039;, c, t, str)&lt;br /&gt;
end&lt;br /&gt;
function makeLink(a, b)&lt;br /&gt;
	if not a or (isBadTitle(a) and not config.infoMode) then return (b or &amp;#039;&amp;#039;) end&lt;br /&gt;
	if not b then b = a end&lt;br /&gt;
	return string.format(&amp;quot;[[%s|%s]]&amp;quot;,a,b)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function makeAliasList(n)&lt;br /&gt;
	if not mAliases[n] then return &amp;#039;&amp;#039; end&lt;br /&gt;
	local t = {}&lt;br /&gt;
	table.insert(t, &amp;#039;&amp;lt;div class=&amp;quot;alias&amp;quot;&amp;gt;&amp;lt;ul&amp;gt;&amp;#039;)&lt;br /&gt;
	for k,v in ipairs(mAliases[n]) do&lt;br /&gt;
		local tr = string.format(&amp;#039;&amp;lt;li class=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/li&amp;gt;&amp;#039;, v[1], v[2])&lt;br /&gt;
		table.insert(t, tr)&lt;br /&gt;
	end&lt;br /&gt;
	table.insert(t, &amp;#039;&amp;lt;/ul&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;)&lt;br /&gt;
	return table.concat(t)&lt;br /&gt;
end&lt;br /&gt;
function makeDivUl(t, class) return makeDiv(makeUl(t), class) end&lt;br /&gt;
function makeUl(t, class)&lt;br /&gt;
	if not t then return &amp;#039;&amp;#039; end&lt;br /&gt;
	if class then class = string.format(&amp;#039; class=&amp;quot;%s&amp;quot;&amp;#039;, class) else class = &amp;#039;&amp;#039; end&lt;br /&gt;
	return string.format(&amp;#039;&amp;lt;ul%s&amp;gt;&amp;lt;li&amp;gt;%s&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&amp;#039;, class, table.concat(t, &amp;#039;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&amp;#039;))&lt;br /&gt;
end&lt;br /&gt;
function makeDiv(s, class)&lt;br /&gt;
	if not s or string.len(s) == 0 then return &amp;#039;&amp;#039; end&lt;br /&gt;
	if class then class = string.format(&amp;#039; class=&amp;quot;%s&amp;quot;&amp;#039;, class) else class = &amp;#039;&amp;#039; end&lt;br /&gt;
	return string.format(&amp;#039;&amp;lt;div%s&amp;gt;%s&amp;lt;/div&amp;gt;&amp;#039;, class, s)&lt;br /&gt;
end	&lt;br /&gt;
function makeInfoRow(info)						&lt;br /&gt;
	local alii = makeAliasList(info.n)&lt;br /&gt;
	local html = makeDivUl(getEntities(info.n), &amp;#039;html&amp;#039;)&lt;br /&gt;
	local utf8 = makeDivUl(getUtf8toStr(info.n), &amp;#039;utf8&amp;#039;)&lt;br /&gt;
	local utf16 = makeDivUl(getUtf16toStr(info.n), &amp;#039;utf16&amp;#039;)&lt;br /&gt;
	local age = getAge(info.n)&lt;br /&gt;
	if(age) then age = string.format(&amp;#039;&amp;lt;div class=&amp;quot;age&amp;quot;&amp;gt;Introduced in Unicode version %s.&amp;lt;/div&amp;gt;&amp;#039;, age) else age = &amp;#039;&amp;#039; end&lt;br /&gt;
	if(info.category == &amp;#039;control&amp;#039;) then info.name = mw.text.nowiki(&amp;#039;&amp;lt;control&amp;gt;&amp;#039;) end&lt;br /&gt;
	if(info.category == &amp;#039;space separator&amp;#039;) then info.cBox = &amp;#039; box&amp;#039; end&lt;br /&gt;
	local class = &amp;#039;&amp;#039;&lt;br /&gt;
	if config.useFontCss then class = class..&amp;#039;script-&amp;#039;..info.sCode end&lt;br /&gt;
	local charInfo = &amp;#039;&amp;lt;div class=&amp;quot;char&amp;quot;&amp;gt;&amp;#039;..table.concat({utf8, utf16, html, age})..&amp;#039;&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
	local titleBarFmt = &amp;#039;&amp;lt;div&amp;gt;&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;%s %s&amp;lt;/div&amp;gt;&amp;lt;div class=&amp;quot;category&amp;quot;&amp;gt;%s&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
	local titleBar = string.format(titleBarFmt, info.uPlus, info.name, info.category)&lt;br /&gt;
	local fmt = &amp;#039;&amp;lt;tr class=&amp;quot;info-row&amp;quot; id=&amp;quot;%s&amp;quot;&amp;gt;&amp;lt;th class=&amp;quot;thumb %s%s&amp;quot;&amp;gt;%s&amp;lt;/th&amp;gt;&amp;lt;td colspan=&amp;quot;16&amp;quot; class=&amp;quot;info&amp;quot;&amp;gt;%s%s%s&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;#039;&lt;br /&gt;
	return string.format(fmt, getAnchorId(info.n), class, info.cBox, info.display, titleBar, alii, charInfo)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function getParamNx(key, n, c)&lt;br /&gt;
	local key4 = string.format(&amp;quot;%s_%04X&amp;quot;, key, n)&lt;br /&gt;
	if args[key4] then return args[key4] end&lt;br /&gt;
	if c then&lt;br /&gt;
		local key3 = string.format(&amp;quot;%s_%03Xx&amp;quot;, key, math.floor(n/16))&lt;br /&gt;
		return args[key3] or args[key]&lt;br /&gt;
	end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function makeGridCell(n, charMask)&lt;br /&gt;
	local uPlus =  string.format(&amp;quot;U+%04X&amp;quot;, n)&lt;br /&gt;
	local char = mw.ustring.char(n)&lt;br /&gt;
	local cfFmt = &amp;#039;&amp;lt;td title=&amp;quot;%s&amp;quot; class=&amp;quot;char%s&amp;quot;&amp;gt;&amp;lt;div&amp;gt;\n%s\n&amp;lt;/div&amp;gt;&amp;lt;/td&amp;gt;&amp;#039;&lt;br /&gt;
	local isControlN, isFormatN = isControl(n), isFormat(n)&lt;br /&gt;
	local charName = table.last(getControlAliases(n)) or mUnicode.lookup_name(n)&lt;br /&gt;
	if isControlN then charName = charName or &amp;quot;&amp;amp;lt;control&amp;amp;gt;&amp;quot; end&lt;br /&gt;
	local cBox = &amp;#039;&amp;#039;&lt;br /&gt;
	local masterListDisplay = mDisplay[n]&lt;br /&gt;
	if masterListDisplay then cBox = &amp;#039; box&amp;#039; end&lt;br /&gt;
	local display = masterListDisplay or char&lt;br /&gt;
	local title = uPlus..&amp;#039; &amp;#039;..charName&lt;br /&gt;
	if isControlN or isFormatN then display = makeSpan(display, title, true) end&lt;br /&gt;
	local sCode = nil&lt;br /&gt;
	if config.useFontCss then sCode = mUnicode.lookup_script(n) end&lt;br /&gt;
	--default dir=&amp;quot;ltr&amp;quot; need not be specified&lt;br /&gt;
	local sDir = &amp;#039;&amp;#039;&lt;br /&gt;
	if mUnicode.is_rtl(char) then sDir = &amp;#039; dir=&amp;quot;rtl&amp;quot;&amp;#039; end&lt;br /&gt;
	local sClass = &amp;quot;&amp;quot;&lt;br /&gt;
	local linkThis = getTarget(n)&lt;br /&gt;
	local cell = &amp;#039;&amp;#039;&lt;br /&gt;
	local generateInfoPanel = true&lt;br /&gt;
--3 types of empty cells	&lt;br /&gt;
	if(not charMask[n]) then &lt;br /&gt;
		--fill extra spaces surrounding an irregular (non-multiple of 16) range of displayed chars  &lt;br /&gt;
		cell = &amp;#039;&amp;lt;td class=&amp;quot;excluded&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;#039;&lt;br /&gt;
		generateInfoPanel = false					&lt;br /&gt;
	elseif string.match(charName, &amp;#039;&amp;lt;reserved&amp;#039;) then&lt;br /&gt;
		refGrammar.reserved.count = refGrammar.reserved.count + 1&lt;br /&gt;
		cell = string.format(&amp;#039;&amp;lt;td title=&amp;quot;%s RESERVED&amp;quot; class=&amp;quot;reserved&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;#039;, uPlus)&lt;br /&gt;
		generateInfoPanel = false					&lt;br /&gt;
	elseif string.match(charName, &amp;#039;&amp;lt;noncharacter&amp;#039;) then&lt;br /&gt;
		refGrammar.nonchar.count = refGrammar.nonchar.count + 1&lt;br /&gt;
		cell = string.format(&amp;#039;&amp;lt;td title=&amp;quot;%s NONCHARACTER&amp;quot; class=&amp;quot;nonchar&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;#039;, uPlus)&lt;br /&gt;
		generateInfoPanel = false					&lt;br /&gt;
--actual chars&lt;br /&gt;
	elseif mUnicode.is_whitespace(n) then&lt;br /&gt;
		refGrammar.white.count = refGrammar.white.count + 1&lt;br /&gt;
		local cellFmt = &amp;#039;&amp;lt;td title=&amp;quot;%s&amp;quot; class=&amp;quot;char whitespace&amp;quot;%s&amp;gt;&amp;lt;div&amp;gt;\n%s\n&amp;lt;/div&amp;gt;&amp;lt;/td&amp;gt;&amp;#039;&lt;br /&gt;
		display = makeSpan(display, title, false)&lt;br /&gt;
		cell = string.format(cellFmt, title, sDir, makeLink(linkThis, makeSpan(char, title, false)))&lt;br /&gt;
	elseif isControlN then&lt;br /&gt;
		refGrammar.control.count = refGrammar.control.count + 1&lt;br /&gt;
		cell = string.format(cfFmt, title, &amp;quot; control box&amp;quot;, makeLink(linkThis, display))&lt;br /&gt;
	elseif isFormatN then&lt;br /&gt;
		refGrammar.format.count = refGrammar.format.count + 1&lt;br /&gt;
		cell = string.format(cfFmt, title, &amp;quot; format box&amp;quot;, makeLink(linkThis, display))&lt;br /&gt;
	else&lt;br /&gt;
		if sCode then sClass = sClass..string.format(&amp;#039; script-%s&amp;#039;, sCode) end&lt;br /&gt;
		sClass = sClass..cBox&lt;br /&gt;
		isCombining = mUnicode.is_combining(n)&lt;br /&gt;
		if isCombining then&lt;br /&gt;
			refGrammar.combining.count = refGrammar.combining.count + 1&lt;br /&gt;
			sClass = sClass..&amp;quot; combining&amp;quot;&lt;br /&gt;
			display = &amp;quot;◌&amp;quot;..char&lt;br /&gt;
		end&lt;br /&gt;
		display = makeSpan(display, title, true)&lt;br /&gt;
		local cellFmt = &amp;#039;&amp;lt;td title=&amp;quot;%s&amp;quot; class=&amp;quot;char%s&amp;quot;%s&amp;gt;&amp;lt;div&amp;gt;\n%s\n&amp;lt;/div&amp;gt;&amp;lt;/td&amp;gt;&amp;#039;&lt;br /&gt;
		cell = string.format(cellFmt, title, sClass, sDir, makeLink(linkThis,display))&lt;br /&gt;
	end&lt;br /&gt;
	if(config.infoMode and generateInfoPanel) then&lt;br /&gt;
		local printable = mUnicode.is_printable(n)&lt;br /&gt;
		local category = getCategory(n)&lt;br /&gt;
		local info = {&lt;br /&gt;
			n = n,&lt;br /&gt;
			char = char,&lt;br /&gt;
			name = charName,&lt;br /&gt;
			sCode = sCode,&lt;br /&gt;
			display = display,&lt;br /&gt;
			uPlus = uPlus, &lt;br /&gt;
			printable = printable,&lt;br /&gt;
			category = category,&lt;br /&gt;
			cBox = cBox,&lt;br /&gt;
			}&lt;br /&gt;
		table.insert(infoTable, makeInfoRow(info))&lt;br /&gt;
	end&lt;br /&gt;
	return cell&lt;br /&gt;
end	&lt;br /&gt;
function getMask(ranges)&lt;br /&gt;
	local ch,r = {},{}&lt;br /&gt;
	for i,range in ipairs(ranges) do&lt;br /&gt;
		for n=range.first,range.last do&lt;br /&gt;
			ch[n] = true&lt;br /&gt;
			r[n-n%16] = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local row = {}&lt;br /&gt;
	for i,x in pairs(r) do table.insert(row, i) end&lt;br /&gt;
	table.sort(row)&lt;br /&gt;
	return ch,row&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main( frame )&lt;br /&gt;
	for k, v in pairs(mArguments.getArgs(frame)) do args[k] = v end&lt;br /&gt;
	config.infoMode = (args[&amp;quot;info&amp;quot;] or &amp;#039;no&amp;#039;):lower() ~= &amp;quot;no&amp;quot;&lt;br /&gt;
	config.useFontCss = (args[&amp;quot;fonts&amp;quot;] or args[&amp;quot;font&amp;quot;] or &amp;#039;yes&amp;#039;):lower() ~= &amp;quot;no&amp;quot;&lt;br /&gt;
	local userRefs = args[&amp;quot;refs&amp;quot;] or args[&amp;quot;notes&amp;quot;] or args[&amp;quot;ref&amp;quot;] or args[&amp;quot;note&amp;quot;] or &amp;quot;&amp;quot; &lt;br /&gt;
	config.showRefs = not(userRefs==&amp;#039;off&amp;#039; or userRefs==&amp;#039;no&amp;#039;)&lt;br /&gt;
	local state = args[&amp;quot;state&amp;quot;] or &amp;quot;expanded&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	local subset = args[&amp;quot;subset&amp;quot;]&lt;br /&gt;
	local subsetRangeTxt = &amp;#039;&amp;#039;&lt;br /&gt;
	if subset then&lt;br /&gt;
		subsetRangeTxt = mSubsets[subset:lower():gsub(&amp;#039;%s+&amp;#039;, &amp;#039;_&amp;#039;)]&lt;br /&gt;
		if(not subsetRangeTxt) then err.format(err.badSubset, subset) end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local blockName = args[&amp;quot;block_name&amp;quot;] or args[&amp;quot;block&amp;quot;] or args[&amp;quot;name&amp;quot;] or args[1]&lt;br /&gt;
	local blockNameLink = args[&amp;quot;link_block&amp;quot;] or args[&amp;quot;link_name&amp;quot;]&lt;br /&gt;
	local blockNameDisplay = args[&amp;quot;display_block&amp;quot;] or args[&amp;quot;display_name&amp;quot;] or subset or blockName&lt;br /&gt;
&lt;br /&gt;
	local defaultRange = getDefaultRange(blockName)&lt;br /&gt;
	local actualBlock = (defaultRange ~= nil)&lt;br /&gt;
&lt;br /&gt;
	local ranges = parseRanges(subsetRangeTxt..&amp;#039;,&amp;#039;..(args[&amp;quot;ranges&amp;quot;] or args[&amp;quot;range&amp;quot;] or &amp;#039;&amp;#039;))&lt;br /&gt;
&lt;br /&gt;
	if actualBlock then&lt;br /&gt;
		config.pdf = string.format(&amp;#039;https://www.unicode.org/charts/PDF/U%04X.pdf&amp;#039;, defaultRange.first)&lt;br /&gt;
		if #ranges == 0 then ranges = { defaultRange } end&lt;br /&gt;
		blockNameLink = blockNameLink or blockName..&amp;quot; (Unicode block)&amp;quot;&lt;br /&gt;
	else&lt;br /&gt;
		if #ranges == 0 then err.format(err.noRange, {}) end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local charMask,rowMask = getMask(ranges)&lt;br /&gt;
	local tableBody = {}&lt;br /&gt;
	for i=1,#rowMask do&lt;br /&gt;
		local rowStart = rowMask[i]&lt;br /&gt;
		local trClass=&amp;#039;&amp;#039;&lt;br /&gt;
		if(i &amp;gt; 1 and rowStart ~= (rowMask[i-1]+16)) then&lt;br /&gt;
			trClass = &amp;#039; class=&amp;quot;skip&amp;quot;&amp;#039;&lt;br /&gt;
			refGrammar.skip.count = refGrammar.skip.count + 1&lt;br /&gt;
		end&lt;br /&gt;
		local dataRow = {}&lt;br /&gt;
		local rowOpen, rowClose = string.format(&amp;#039;&amp;lt;tr%s&amp;gt;&amp;#039;, trClass), &amp;#039;&amp;lt;/tr&amp;gt;&amp;#039;&lt;br /&gt;
		local rowHeader = string.format(&amp;#039;&amp;lt;th class=&amp;quot;row&amp;quot;&amp;gt;U+%03Xx&amp;lt;/th&amp;gt;&amp;#039;, rowStart/16)&lt;br /&gt;
		for c = 0,15 do&lt;br /&gt;
			table.insert(dataRow, makeGridCell(rowStart+c, charMask))&lt;br /&gt;
		end&lt;br /&gt;
		local rowHtml = {rowOpen, rowHeader, table.concat(dataRow), rowClose}&lt;br /&gt;
		table.insert(tableBody, table.concat(rowHtml))&lt;br /&gt;
	end&lt;br /&gt;
	local tableOpenFmt = &amp;#039;&amp;lt;table class=&amp;quot;wikitable nounderlines unicode-chart collapsible %s&amp;quot;&amp;gt;&amp;#039;&lt;br /&gt;
	local tableOpen, tableClose = string.format(tableOpenFmt, state), &amp;#039;&amp;lt;/table&amp;gt;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
	local allRefs = table.concat({ makeVersionRef(), makeAutoRefs(), sanitizeUserRefs(userRefs) }) &lt;br /&gt;
	if blockNameLink then&lt;br /&gt;
		blockNameLink = string.format(&amp;quot;[[%s|%s]]&amp;quot;, blockNameLink, blockNameDisplay)&lt;br /&gt;
	else&lt;br /&gt;
		blockNameLink = blockNameDisplay&lt;br /&gt;
	end&lt;br /&gt;
	local titleBar = string.format(&amp;#039;&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;%s%s&amp;lt;/div&amp;gt;&amp;#039;, blockNameLink, allRefs)&lt;br /&gt;
	local fmtpdf = &amp;#039;&amp;lt;div class=&amp;quot;pdf-link&amp;quot;&amp;gt;[%s Official Unicode Consortium code chart] (PDF)&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
	if config.pdf then&lt;br /&gt;
		titleBar = titleBar..string.format(fmtpdf, config.pdf)&lt;br /&gt;
	end&lt;br /&gt;
	local titleBarRow = &amp;#039;&amp;lt;tr&amp;gt;&amp;lt;th class=&amp;quot;title-bar&amp;quot; colspan=&amp;quot;17&amp;quot;&amp;gt;&amp;#039;..titleBar..&amp;#039;&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
	local columnHeaders = { &amp;#039;&amp;lt;tr&amp;gt;&amp;#039;, &amp;#039;&amp;lt;th class=&amp;quot;empty&amp;quot;&amp;gt;&amp;lt;/th&amp;gt;&amp;#039; }&lt;br /&gt;
	for c = 0,15,1 do table.insert(columnHeaders, string.format(&amp;#039;&amp;lt;th class=&amp;quot;column&amp;quot;&amp;gt;%X&amp;lt;/th&amp;gt;&amp;#039;, c)) end&lt;br /&gt;
	table.insert(columnHeaders, &amp;#039;&amp;lt;/tr&amp;gt;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	local infoFooter = &amp;#039;&amp;#039;&lt;br /&gt;
	if(config.infoMode) then infoFooter = table.concat(infoTable) end&lt;br /&gt;
&lt;br /&gt;
	local notesFooter = &amp;#039;&amp;#039;&lt;br /&gt;
	if config.showRefs and string.len(allRefs) &amp;gt; 0 then&lt;br /&gt;
		notesFooter = &amp;#039;&amp;lt;tr&amp;gt;&amp;lt;td class=&amp;quot;notes&amp;quot; colspan=&amp;quot;17&amp;quot;&amp;gt;&amp;#039;..&amp;quot;&amp;#039;&amp;#039;&amp;#039;Notes:&amp;#039;&amp;#039;&amp;#039;{{reflist}}&amp;quot;..&amp;#039;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local tStyles = frame:extensionTag{ name = &amp;#039;templatestyles&amp;#039;, args = { src = &amp;#039;Unicode chart/styles.css&amp;#039;} }&lt;br /&gt;
	local cStyles = &amp;#039;&amp;#039;&lt;br /&gt;
	if config.useFontCss then&lt;br /&gt;
		cStyles = frame:extensionTag{ name = &amp;#039;templatestyles&amp;#039;, args = { src = &amp;#039;Unicode chart/script styles.css&amp;#039;} }&lt;br /&gt;
	end&lt;br /&gt;
	local html = table.concat({&lt;br /&gt;
		tStyles, cStyles, tableOpen, titleBarRow,&lt;br /&gt;
		table.concat(columnHeaders), table.concat(tableBody),&lt;br /&gt;
		infoFooter, notesFooter, tableClose&lt;br /&gt;
		})&lt;br /&gt;
	return frame:preprocess(html)&lt;br /&gt;
end&lt;br /&gt;
		&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>imported&gt;Cobaltcigs</name></author>
	</entry>
</feed>