Модуль:Isomer

Поделись знанием:
Перейти к: навигация, поиск
 Документация

Функции

Section

{{#invoke:Isomer|Section|full-width|half-width|title-background|desc-background|data-background|border-color|shortnames|title|mandatory-title|wide-column|collapsed|nocat|1|2|3|…}} — отображает несколько строк (секцию) таблицы. Перед первым вызовом функции в тексте должно быть начало таблицы ({|) или начало новой строки (|-), после последнего — окончание таблицы (|}) или следующая строка. Параметры вызова:

half-width
Ширина блока, расположенного в правой ячейке.
full-width
Ширина блока, занимающего две объединённые ячейки.
title-background
Цвет фона заголовка секции.
desc-background
Цвет фона левой ячейки.
data-background
Цвет фона правой ячейки.
border-color
Цвет границы заголовка секции.
shortnames
Краткое имя, список, элементы которого идентифицируют отображаемое значение как относящееся к определённому изомеру.
title
Текст заголовка секции, при отсутствии заголовок не отображается.
mandatory-title
Заголовок отображается даже для пустой секции (любое непустое значение).
wide-column
Таблица должна иметь три столбца (см. например {{drugbox}}), если параметр равен 1 — объединяются первый и второй столбец, если 2 — второй и третий.
collapsed
Секция свёрнута (любое непустое значение).
nocat
Автоматическая категоризация (см. ниже category) отключена (любое непустое значение).

Далее идут тройки безымянных параметров:

1
Описание параметра, текст левой ячейки. При пустом значении ячейки объединяются.
2
Величина параметра, текст правой ячейки. Если все параметры 2 в секции пустые, секция не отображается.
3
Дополнительные параметры.

Строка может иметь несколько дополнительных параметров, которые отделяются друг от друга точкой с запятой. Значения параметра, если они имеются, отделяются от его имени двоеточием. Значение параметра не должно содержать точку с запятой, знаки равенства должны экранироваться. Дополнительные параметры:

unit:единица\минимальная степень\максимальная степень\используемая степень
Отображается физическая величина с нормализацией значения.
  • единица — единица физической величины, обычно используется без приставок, например «г»;
  • минимальная и максимальная степень — степени десятичных множителей, используемые для данной величины, например «г\-6\3» указывает, что могут использоваться микрограммы, миллиграммы, граммы, килограммы, но не мегаграммы («0\0» запрещает модификацию значения, в этом случае можно указывать величину с приставкой, например «нм\0\0»);
  • используемая степень — множитель, применяющийся для величины, например «Дж\\\3» означает, что энергия указывается в килоджоулях.
Параметр 2 может быть диапазоном значений.
link:ссылка
Отображается указанная ссылка, параметр 2 добавляется к ссылке и используется как её заголовок.
columns:колонки
Указывает число колонок, используется для вывода изображений. Параметр 2 интерпретируется как имя файла, если файл не найден, то значение параметра выводится без изменений.
templates:шаблон
Параметр 2 передаётся в указанный шаблон.
word-wrap
Длинные слова могут разбиваться для переноса.
image-width:ширина
Ограничивает ширину изображения по сравнению с расчётной по ширине поля или колонки.
category:категория
Если параметр 2 пустой, страница включается в указанную категорию.
multivalue-separator:входной\выходной
Разделитель нескольких значений параметров внутри изомера, по умолчанию «; \<br />». Входной используется для разделения входных значений, выходной добавляется к обработанным строкам. Если указан пустой входной разделитель, строка будет обрабатываться целиком, без разделения.
extension:расширение
Используется дополнительная обработка значения параметра 2.
  • GHS — коды разделённые произвольным, но одинаковым для всей строки символом передаются в шаблон {{H-фраза}} или {{P-фраза}}.
  • NFPA704 — четыре значения, разделённые запятыми, используются в качестве соответствующих параметров шаблона {{NFPA 704}}.
  • ICD10 — каждое значение из списка, разделённого запятыми, используется в шаблоне {{ICD10}} (с необходимым разделением на части).
  • capitalise — заменяет первый символ на заглавный.

IsomerButtons

{{#invoke:Isomer|IsomerButtons|1}} — отображает строку — список изомеров. Параметры вызова:

title-background
Цвет фона заголовка.
border-color
Цвет границы заголовка.
dark-color
Цвет тёмного фона.
light-color
Цвет светлого фона.
title
Текст заголовка, см. выше.
1
Краткое имя, см. shortnames выше.

Isomers

{{#invoke:Isomer|Isomers|1|2|unit|link|columns|width}} — отображает значения параметра для каждого изомера. Функция в шаблоне {{Изомеры}} непосредственно больше не используется (заменена на Section) и будет исключена из модуля. Параметры вызова:

1
Краткое имя, см. выше.
2
Отображаемая величина, ссылка, файл.
unit
Отображается физическая величина с нормализацией значения, см. выше.
link
Отображается указанная ссылка, см. выше.
columns
Указывает число колонок, см. выше.
width
Ширина поля или общая ширина всех колонок.


Во избежание поломок страниц, использующих данный модуль, желательно экспериментировать в Песочнице для модулей.

local I={}
-- Формирует содержимое ячейки для шаблона Изомеры

local IsDigit
IsDigit=function(char)
	return mw.ustring.find('0123456789⁰¹²³⁴⁵⁶⁷⁸⁹',char,1,true)
end

local IsExclus
IsExclus=function(char)
	return mw.ustring.find('%°℃K',char,1,true)
end

local physval
physval=function(text,physunit)
	local s=mw.text.trim(text);
	local lastchar=mw.ustring.sub(s,-1);
	if (IsDigit(lastchar)) then
		local prefs={
			[-24]='и',
			[-21]='з',
			[-18]='а',
			[-15]='ф',
			[-12]='п',
			[-9]='н',
			[-6]='мк',
			[-3]='м',
			[0]='',
			[3]='к',
			[6]='М',
			[9]='Г',
			[12]='Т',
			[15]='П',
			[18]='Э',
			[21]='З',
			[24]='И'
		}
		local p=mw.text.split(physunit,'\\',true);	-- например: г\-6\3\0
		local punit=p[1];							-- граммы (г)
		local pmin=tonumber(p[2]) or -24;			-- допустимые приставки и множители: от мк (10⁻⁶) 
		local pmax=tonumber(p[3]) or 24;			-- до к (10³)
		local pval=tonumber(p[4]) or 0;				-- текущее значение: граммы (10⁰)
		local v=mw.text.split(s,'[—…]',false);	-- если диапазон значений
		local vmin=v[1];
		local vmax=v[2];
		local firstchar=mw.ustring.sub(vmin,1,1);	-- знаки <, > и т. д. перед числом, но не минус
		if ((firstchar~='-') and (firstchar~='−') and not IsDigit(firstchar)) then
			vmin=mw.ustring.sub(vmin,2);
		else
			firstchar=nil;
		end
		local lang=mw.language.new('ru');
		vmin=lang:parseFormattedNumber(vmin);
		vmax=lang:parseFormattedNumber(vmax);
		if ((vmin) and (not v[2] or vmax)) then	-- распознаны оба числа диапазона или единственное
			local pow, p;
			if (not IsExclus(mw.ustring.sub(punit,1,1))) then
				if (vmax and ((math.abs(math.floor(math.log10(math.abs(vmax)))) % 3) < (math.abs(math.floor(math.log10(math.abs(vmin)))) % 3))) then
					p=math.log10(math.abs(vmax));	-- напр.: 120—1400 Ед → 0,12—1,4 кЕд
				else
					p=math.log10(math.abs(vmin));
					if ((p<0) and (p>=-1)) then
						p=0;	-- напр.: 120 мЕд → 0,12 Ед
					end;
				end;
				pow=math.floor(p / 3) * 3 +pval;
				pow=math.max(pow,pmin);
				pow=math.min(pow,pmax);
			else
				pow=0	-- к указанным ед. приставки не применяем
			end
			vmin=vmin/(10^(pow-pval));
			s=firstchar or '';	-- начало форматирования
			if (firstchar and (vmin<0)) then
				s=s..'&nbsp;';
			end
			s=s..lang:formatNum(vmin);
			if (vmax) then
				vmax=vmax/(10^(pow-pval));
				if (vmin<0) then
					s=s..'…';
				else
					s=s..'—';
				end
				if (vmax<0) then
					s=s..'&nbsp;';
				else
					if (vmin<0) then
						s=s..'+';
					end
				end
				s=s..lang:formatNum(vmax);
			end
			punit=prefs[pow]..punit;
		else
			punit=prefs[pval]..punit;	-- похоже на число, но не обработано
		end
		if (punit~='°') then
			s=s..'&nbsp;';
		end
		s=s..punit;
	end
	return s
end

local formatimg
formatimg=function(text,width)
	local s=text;
	if (mw.ustring.sub(text,1,1)~='[') then
		local o=mw.title.new(text,'Media');
		if (o) and (o.exists) then
			s='[[File:'..text..'|'..tostring(width)..'px]]';
		end
	end
	return s
end

local splitPrefValSuff
splitPrefValSuff=function(text)
	local p,s;
	local pref='';
	local val;
	local suff='';
	p=mw.ustring.find(text,':');
	s=mw.ustring.find(text,'(',p or 2,true);
	if (p) then
		pref=mw.ustring.sub(text,1,p)..'&nbsp;';
		p=p+1;
	end
	if (s) then
		suff=' '..mw.ustring.sub(text,s,-1);
		s=s-1;
	end
	val=mw.ustring.sub(text,p or 1,s);
	return pref,val,suff
end

local extGHS
extGHS=function(text)
	local s='';
	local v={};
	local firstchar=mw.ustring.sub(text,1,1);
	if ((firstchar=='P') or (firstchar=='H')) then
		local f=mw.getCurrentFrame();
		local pos=1;
		local delimiter;
		repeat	-- разделитель может быть любой, но + используется внутри фразы
			pos=mw.ustring.find(text,firstchar,pos+1,true);
			if (pos) then
				delimiter=mw.ustring.sub(text,pos-1,pos-1);
			end
		until ((not pos) or (delimiter~='+'))
		if (pos) then
			v=mw.text.split(text,delimiter,true);
		else
			v={text};
		end
		for i=1,#v do
			if (firstchar=='P') then
				s=s..f:expandTemplate{title='P-фраза',args={v[i]}};
			else
				s=s..f:expandTemplate{title='H-фраза',args={v[i]}};
			end
			if (i<#v) then
				s=s..', ';
			end
		end
	else
		s=text;
	end
	return s
end

local extNFPA
extNFPA=function(text)
	local s='';
	local v={};
	local f=mw.getCurrentFrame();
	if (mw.ustring.find(text,',',1,true)) then
		v=mw.text.split(text,',',true);
	else	-- викиданные без разд. дабы не вывод. пустое поле)
		v[1]=mw.ustring.sub(text,1,1);
		v[2]=mw.ustring.sub(text,2,2);
		v[3]=mw.ustring.sub(text,3,3);
		v[4]=mw.ustring.sub(text,4,-1);
	end
	s=f:expandTemplate{title='NFPA 704',args={['опасность для здоровья'] = v[1], ['огнеопасность'] = v[2], ['реакционоспособность'] = v[3], ['прочее'] = v[4]}}
	return s
end

local extICD10
extICD10=function(text)
	local s='';
	if (mw.ustring.find(text,']]',1,true)) then
		s=text;		-- есть викификация, не трогаем
	else
		local v=mw.text.split(text,',',true);
		local str,sA,sB;
		local f=mw.getCurrentFrame();
		for i=1,#v do
			str=mw.text.trim(v[i]);
			sA=mw.ustring.sub(str,1,1);
			sB=mw.ustring.sub(str,2,-1);
			s=s..f:expandTemplate{title='ICD10',args={sA,sB}};
			if (i<#v) then
				s=s..', ';
			end
		end
	end
	return s
end

local capitalise
capitalise=function(text)
	local pos=(mw.ustring.find(text,'|') or 0) + 1;	-- если викифицированно
	local s=mw.ustring.sub(text,1,pos-1)..mw.ustring.upper(mw.ustring.sub(text,pos,pos))..mw.ustring.sub(text,pos+1,-1);
	return s
end

local processvalue
processvalue=function(text,opt)
	local s;
	if (opt.ext=='GHS') then	--extensions
		text=extGHS(text);
	elseif (opt.ext=='NFPA704') then
		text=extNFPA(text);
	elseif (opt.ext=='ICD10') then
		text=extICD10(text);
	end
	if (opt.physunit) then
		s=physval(text,opt.physunit);
	elseif (opt.link) then
		s=[[<span class="reflink plainlinksneverexpand">[]]..opt.link..text..' '..text..[[]</span>]];
	elseif (opt.columns) then
		s=formatimg(text,opt.imgwidth);
	elseif (opt.temps) then
		local f=mw.getCurrentFrame();
		s=f:expandTemplate{title=opt.temps,args={text}};
	else
		s=text;
	end
	return s
end

local getmultivalues
getmultivalues=function(text,opt)
	local multivalues={};
	local prefvalsuff={};
	local strsepin='; ';
	if (opt.mvsep) then		-- разделители множественных значений (на входе и на выходе)
		local sep=mw.text.split(opt.mvsep,'\\',true)
		strsepin=sep[1];
	end
	local pref,val,suff;
	local hasHtml = mw.ustring.find(text,'<%a.->');
--	((mw.ustring.sub(text,1,1)=='<') and (mw.ustring.sub(text,2,2)~=' ') and (not IsDigit(mw.ustring.sub(text,2,2))))
	if (hasHtml or (#strsepin==0)) then
		if (hasHtml) then
			opt.ext=nil;	--на входе html, ничего не трогаем
		end
		prefvalsuff={
			pref='',
			val=text,
			suff=''
		}
		table.insert(multivalues,prefvalsuff);
	else
		local v=mw.text.split(text,strsepin,true);		-- значения можно разделять '; '
		for i=1,#v do
			if (opt.columns) then
				pref,val,suff='',v[i],'';	--имя файла, не трогаем
			else
				pref,val,suff=splitPrefValSuff(v[i]);	-- с собственными пояснениями
			end
			val=mw.text.trim(val);
			prefvalsuff={
				pref=pref,
				val=val,
				suff=suff
			}
			table.insert(multivalues,prefvalsuff);
		end
	end
	return multivalues
end

local processmultivalues
processmultivalues=function(values,opt)
	local s='';
	local strsepout=[[<br />]];
	if (opt.mvsep) then		-- разделители множественных значений (на входе и на выходе)
		local sep=mw.text.split(opt.mvsep,'\\',true)
		if (sep[2]) then
			strsepout=sep[2];
		end
	end
	if (opt.capitalise) then
		values[1].val=capitalise(values[1].val);
	end
	for i=1, #values do
		s=s..values[i].pref..processvalue(values[i].val,opt)..values[i].suff;
		if (i<#values) then
			s=s..strsepout;
		end
	end
	return s
end

local getlocalisomers
getlocalisomers=function(shortnamelist,textlist,opt)
	local isomers={};
	local shortnames, text;
	if ((#shortnamelist>0) and (mw.ustring.find(textlist,'\\'))) then
		shortnames=mw.text.split(shortnamelist,'\\');
		text=mw.text.split(textlist,'\\');
		n=#shortnames;
	else
		shortnames={};
		text={textlist};
		n=1;
	end
	for i=1,n do
		if (text[i]) and (#text[i]~=0) then
			local isomer={
				shortname = shortnames[i],
				values = getmultivalues(text[i],opt)
			}
			table.insert(isomers,isomer);
		end
	end
	return isomers
end

local getproperty
getproperty=function(property,firstonly)
	local propertyvalues={};
	local entity=mw.wikibase.getEntityObject();
	if (entity and entity.claims and entity.claims[string.upper(property)]) then
		local rank = 'normal'
		for i, statement in pairs( entity.claims[string.upper(property)] ) do
			if (statement.rank == 'preferred') then
				rank = 'preferred'
				break
			end
		end
		for i, statement in pairs( entity.claims[string.upper(property)] ) do
			if (statement.rank == rank) then
				if (statement.mainsnak.snaktype == 'value') then
					local val;
					if (statement.mainsnak.datavalue.type == 'wikibase-entityid') then
						local id = 'Q'..statement.mainsnak.datavalue.value['numeric-id'];
						local link = mw.wikibase.sitelink(id)
						local label = mw.wikibase.label(id);
						if link then
							if label then
								val='[['..link..'|'..label..']]';
							else
								val='[['..link..']]';
							end
						else
							if label then
								val=label;
							else
								val='[[d:'..id..'|'..id..']]';
							end
						end
					elseif statement.mainsnak.datavalue.type == 'quantity' then
						val=statement.mainsnak.datavalue.value['amount'];
					else
						val=statement.mainsnak.datavalue.value;
					end
					table.insert(propertyvalues,val);
					if (firstonly) then
						break;
					end
				end
			end
		end
	end
	return propertyvalues
end

local getwikidataisomers
getwikidataisomers=function(shortnamelist,textlist,opt)
	local isomers={};
	local multivalues={};
	local prefvalsuff={};
	local val={};
	if (mw.ustring.find(opt.property,'\\')) then
		local s='';		--several prop. in one cell (NFPA 704)
		local properties=mw.text.split(opt.property,'\\');
		for i=1, #properties do
			s = s..(getproperty(properties[i],true)[1] or '');
		end
		if (#s>0) then
			val={s};
		end
	else
		val = getproperty(opt.property,false);
	end
	for i=1, #val do
		prefvalsuff={
			pref='',
			val=val[i],
			suff=''
		}
		table.insert(multivalues,prefvalsuff);
	end
	if (#multivalues > 0) then
		local isomer={
			shortname = nil,
			values = multivalues
		}
		table.insert(isomers,isomer);
	end
	return isomers
end

local processisomers
processisomers=function(row)
	local s='';
	local str, str2, colwidth;
	if (row.options.columns) then
		colwidth=math.floor(row.options.width/row.options.columns);
	else
		colwidth=row.options.width;
	end
	if ((not row.options.imgwidth) or (row.options.imgwidth > colwidth)) then
		row.options.imgwidth=colwidth;
	end
	if (row.options.width and row.isomers[1].shortname) then
		row.options.imgwidth=row.options.imgwidth-20;
	end
	for i=1,#row.isomers do
--		if (text[i]) and (#text[i]~=0) then
			if ((row.isomers[i].shortname) or row.options.width) then	-- оборачиваем рез-т в div и (или) подписываем кратким названием
				str='<div';
				if (row.isomers[i].shortname) then
					str=str..[[ class="mw-collapsible" id="mw-customcollapsible-isomer]]..tostring(i)..[=["]=];
				end
				if (row.options.width) then
					str=str..[[ style="width:]]..tostring(colwidth)..[=[px; word-wrap:break-word;]=];
					if (row.options.columns) then
						str=str..' display:inline-block; vertical-align:top';
					end
					str=str..[["]]; --end style
				end
				str=str..'>'; --end div
				if (row.isomers[i].shortname) then
					if (row.options.columns) then
						str=str..[[<span style="vertical-align:top; letter-spacing:normal;">]];
					end
					str=str..[[''']]..row.isomers[i].shortname..[=[''':&nbsp;]=];
					if (row.options.columns) then
						str=str..[[</span>]];
					end
				end
				str2=[[</div>]];
			else
				str='';
				str2='';
			end
			s=s..str..processmultivalues(row.isomers[i].values,row.options)..str2;
--		end
	end
	if (row.options.columns) then
		s=string.format([[<div style="width:%ipx; text-align:center; letter-spacing:-5px; margin: 0 auto">%s</div>]],row.options.width,s);
	end
	return s
end

--[=[function I.Isomers(frame)
	local shortnamelist=frame.args[1];
	local textlist=frame.args[2];
	local opt={};
	opt.physunit=frame.args['unit'];
	opt.link=frame.args['link'];
	opt.width=tonumber(frame.args['width']);
	opt.columns=tonumber(frame.args['columns']);
	return isomers(shortnamelist,textlist,opt)
end]=]

local getrow
getrow=function(shortnames,desc,value,opt)
	local row;
	local isomers={};
	if (opt.property) then
		isomers=getwikidataisomers(shortnames,value,opt);
	end
	if (#isomers == 0) then
		opt.property = nil;	--данные получены не из викиданных
		isomers=getlocalisomers(shortnames,value,opt);
	end
	if (#isomers > 0) then
		row={
			isomers = isomers,
			description = desc,
			options = opt
		}
	end
	return row
end

-- Формирует строку - список изомеров

function I.IsomerButtons(frame)
	local titlebg=frame.args['title-background'] or '#F8EABA';
	local bordercolor=frame.args['border-color'] or '#C0C090';
	local darkcolor=frame.args['dark-color'] or '#F0F0C0';
	local lightcolor=frame.args['light-color'] or '#F8F8C8';
	local title=frame.args['title'];
	local shortnamelist=frame.args[1];
	local s='';
	local bgcolor;
	if (#shortnamelist>0) then
		if ((title) and (#title>0)) then
			s=s..string.format([[!colspan="2" align="center" cellspacing="3" style="border:1px solid %s;background:%s;margin-bottom:3px"|%s]],bordercolor,titlebg,title);
			s=s..'\n|-\n|colspan="2" style="padding:0"|\n';
		end;
		local shortname=mw.text.split(shortnamelist,'\\');
		local n=#shortname;
		local width=math.floor(100 / n + 0.5);
		s=s..[[{| style="border: 0px; border-collapse:collapse; text-align:center; width:100%"]]..'\n';
		for i=1,n do
			if ((i % 2) ==0) then
				bgcolor=darkcolor;
			else
				bgcolor=lightcolor;
			end
			s=s..string.format([[|bgcolor="%s" width="%i%%"|<div class="mw-customtoggle-isomer%i">%s</div>]],bgcolor,width,i,shortname[i])..'\n';
		end
		s=s..'|}';
		if ((title) and (#title>0)) then
			s=s..'\n|-\n';
		end
	end
	return s
end

-- Формирует секцию: заголовок и поля

local hash
hash=function(text)
	local h={0,0,0,0,0,0}
	local s=''
	for i = 1, mw.ustring.len(text) do
		h[(i % 6) + 1]=h[(i % 6) + 1]+mw.ustring.codepoint(text,i);
	end
	for i = 1, 6 do
		s=s..mw.ustring.char((h[i] % 26)+mw.ustring.codepoint('a',1));
	end
	return s
end

local splitfirst
splitfirst=function(s,pattern,plain)
	local s1,s2;
	local i=mw.ustring.find(s,pattern,1,plain);
	if (i) then
		s1=mw.ustring.sub(s,1,i-1);
		s2=mw.ustring.sub(s,i+1,-1);
	else
		s1=s;
		s2='';
	end
	return s1,s2
end

function I.Section(frame)
	local fullwidth=tonumber(frame.args['full-width']) or 225;
	local halfwidth=tonumber(frame.args['half-width']) or math.floor(fullwidth * 0.6);
	local titlebg=frame.args['title-background'] or '#F8EABA';
	local bordercolor=frame.args['border-color'] or '#C0C090';
	local descbg=frame.args['desc-background'] or '#F0F0C0';
	local databg=frame.args['data-background'] or '#FFFFFF';
	local shortnames=frame.args['shortnames'] or '';
	local title=frame.args['title'];
	local mand=frame.args['mandatory-title'];
	local widecol=tonumber(frame.args['wide-column']) or 0;
	local strcolspan1='';
	local strcolspan2='';
	local strcolspan3='colspan="2"';
	if (widecol > 0) then
		strcolspan3='colspan="3"';
		if (widecol == 1) then
			strcolspan1='colspan="2"';
		else
			strcolspan2='colspan="2"';
		end			
	end
	local strcollapsed='';
	if (frame.args['collapsed']) then
		strcollapsed='mw-collapsed';
	end
	local nocat=frame.args['nocat'];
	local rows={};
	local s='';
	local r=2;
	local strid='';
	local desc,value,options;
	local physunit,link,width,columns,ext;
	local w,optname,optval;
	r=1;
	while (frame.args[r]) do
		desc=mw.text.trim(frame.args[r]);
		value=mw.text.trim(frame.args[r+1] or '');
		options=mw.text.trim(frame.args[r+2]);
		r=r+3;
		if (#desc>0) then
			w=halfwidth;
		else
			w=fullwidth;
		end
		opt={};
		if (options) then
			for j,u in ipairs(mw.text.split(options,';',true)) do
				optname,optval=splitfirst(u,'[:=]',false);
				optname=mw.ustring.lower(mw.text.trim(optname));
				optval=optval or '';
				optval=mw.ustring.gsub(optval,'&sem&',';')
				if (optname=='unit') then
					opt.physunit=optval;
				elseif (optname=='link') then
					opt.link=optval;
				elseif (optname=='capitalise') then
					opt.capitalise=true;
				elseif (optname=='word-wrap') then
					opt.width=w;
				elseif (optname=='columns') then
					opt.columns=optval;
					opt.width=w;
				elseif (optname=='image-width') then
					opt.imgwidth=tonumber(optval);
					opt.width=w;
				elseif (optname=='extension') then
					opt.ext=optval;
				elseif (optname=='templates') then
					opt.temps=optval;
				elseif (optname=='multivalue-separator') then
					opt.mvsep=optval;
				elseif (optname=='category') then
					if ((#value==0) and not nocat) then
						local o=mw.title.getCurrentTitle();
						if (o.namespace==0) then
							s=s..string.format('[[Category:%s]]\n',optval);
						end
					end
				elseif (optname=='property') then
					opt.property=optval;
				end
			end
		end
		table.insert(rows,getrow(shortnames,desc,value,opt));
	end
	if ((title) and (#title>0)) then
		if ((#rows>0) or mand) then
			local h=hash(title);
			strid=string.format([[id="mw-customcollapsible-%s" class="mw-collapsible %s"]],h,strcollapsed)
			s=string.format([[!%s align="center" cellspacing="3" style="border:1px solid %s;background:%s;margin-bottom:3px"|<div class="mw-customtoggle-%s">%s</div>]],strcolspan3,bordercolor,titlebg,h,title)..'\n';
		end
	end
	for i=1, #rows do
		if (#rows[i].isomers > 0) then
			s=s..string.format('|-%s\n',strid);
			if ((rows[i].description) and (#rows[i].description>0)) then
				s=s..string.format([[|%s bgcolor="%s"|%s||%s bgcolor="%s"|]],strcolspan1,descbg,rows[i].description,strcolspan2,databg);
			else
				s=s..string.format([[|%s bgcolor="%s"|]],strcolspan3,databg);
			end
			s=s..processisomers(rows[i])..'\n';
		end
	end
	s=s..'|-\n';
	return s
end

return I