Jump to content
Wikipedia The Free Encyclopedia

Module:Chem2

From Wikipedia, the free encyclopedia
Module documentation[view] [edit] [history] [purge]
[画像:Ready for use] This module is rated as ready for general use. It has reached a mature form and is thought to be relatively bug-free and ready for use wherever appropriate. It is ready to mention on help pages and other Wikipedia resources as an option for new users to learn. To reduce server load and bad output, it should be improved by sandbox testing rather than repeated trial-and-error editing.
[画像:Protected] This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing.
Warning This Lua module is used on approximately 7,800 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them.
This module depends on the following other modules:

This module implements {{chem2 }}. Please see its documentation for details.

The above documentation is transcluded from Module:Chem2/doc. (edit | history)
Editors can experiment in this module's sandbox (edit | diff) and testcases (create) pages.
Subpages of this module.

 local getArgs = require('Module:Arguments').getArgs
 local p = {} -- module's table

 -- Elements with wiki links
 local am = {
	H = "Hydrogen",
	He = "Helium",
	Li = "Lithium",
	Be = "Beryllium",
	B = "Boron",
	C = "Carbon",
	N = "Nitrogen",
	O = "Oxygen",
	F = "Fluorine",
	Ne = "Neon",
	Na = "Sodium",
	Mg = "Magnesium",
	Al = "Aluminium",
	Si = "Silicon",
	P = "Phosphorus",
	S = "Sulfur",
	Cl = "Chlorine",
	Ar = "Argon",
	K = "Potassium",
	Ca = "Calcium",
	Sc = "Scandium",
	Ti = "Titanium",
	V = "Vanadium",
	Cr = "Chromium",
	Mn = "Manganese",
	Fe = "Iron",
	Co = "Cobalt",
	Ni = "Nickel",
	Cu = "Copper",
	Zn = "Zinc",
	Ga = "Gallium",
	Ge = "Germanium",
	As = "Arsenic",
	Se = "Selenium",
	Br = "Bromine",
	Kr = "Krypton",
	Rb = "Rubidium",
	Sr = "Strontium",
	Y = "Yttrium",
	Zr = "Zirconium",
	Nb = "Niobium",
	Mo = "Molybdenum",
	Tc = "Technetium",
	Ru = "Ruthenium",
	Rh = "Rhodium",
	Pd = "Palladium",
	Ag = "Silver",
	Cd = "Cadmium",
	In = "Indium",
	Sn = "Tin",
	Sb = "Antimony",
	Te = "Tellurium",
	I = "Iodine",
	Xe = "Xenon",
	Cs = "Caesium",
	Ba = "Barium",
	La = "Lanthanum",
	Ce = "Cerium",
	Pr = "Praseodymium",
	Nd = "Neodymium",
	Pm = "Promethium",
	Sm = "Samarium",
	Eu = "Europium",
	Gd = "Gadolinium",
	Tb = "Terbium",
	Dy = "Dysprosium",
	Ho = "Holmium",
	Er = "Erbium",
	Tm = "Thulium",
	Yb = "Ytterbium",
	Lu = "Lutetium",
	Hf = "Hafnium",
	Ta = "Tantalum",
	W = "Tungsten",
	Re = "Rhenium",
	Os = "Osmium",
	Ir = "Iridium",
	Pt = "Platinum",
	Au = "Gold",
	Hg = "Mercury (element)",
	Tl = "Thallium",
	Pb = "Lead",
	Bi = "Bismuth",
	Po = "Polonium",
	At = "Astatine",
	Rn = "Radon",
	Fr = "Francium",
	Ra = "Radium",
	Ac = "Actinium",
	Th = "Thorium",
	Pa = "Protactinium",
	U = "Uranium",
	Np = "Neptunium",
	Pu = "Plutonium",
	Am = "Americium",
	Cm = "Curium",
	Bk = "Berkelium",
	Cf = "Californium",
	Es = "Einsteinium",
	Fm = "Fermium",
	Md = "Mendelevium",
	No = "Nobelium",
	Lr = "Lawrencium",
	Rf = "Rutherfordium",
	Db = "Dubnium",
	Sg = "Seaborgium",
	Bh = "Bohrium",
	Hs = "Hassium",
	Mt = "Meitnerium",
	Ds = "Darmstadtium",
	Rg = "Roentgenium",
	Cn = "Copernicium",
	Nh = "Nihonium",
	Fl = "Flerovium",
	Mc = "Moscovium",
	Lv = "Livermorium",
	Ts = "Tennessine",
	Og = "Oganesson",
	
	-- Groups etc with element-like names
	Bn = 'Benzyl group',
	Bu = 'Butyl group',
	Bz = 'Benzoyl group',
	Cp = 'Cyclopentadienyl',
	D = 'Deuterium',
	Et = 'Ethyl group',
	Ln = 'Lanthanide',
	Me = 'Methyl group',
	Nu = 'Nucleophile',
	Ph = 'Phenyl group',
	Pn = 'Pentyl group',
	R = 'Substituent',
	T = 'Tritium',
	Tf = 'Trifluoromethylsulfonyl group',
	X = 'Halogen',
 }

 -- Groups which are redirected from their normal target if wikilinked; never
 -- autolinked.
 local groups = {
	CH3 = 'Methyl group',
	CO3 = 'Carbonate',
	COOH = 'Carboxyl group',
	ClO = 'Hypochlorite',
	ClO2 = 'Chlorite',
	ClO3 = 'Chlorate',
	ClO4 = 'Perchlorate',
	H2O = 'Water of crystallization',
	H3O = 'Hydronium',
	NH2 = 'Amine group',
	NH4 = 'Ammonium',
	NO3 = 'Nitrate',
	PO3 = 'Phosphite',
	PO4 = 'Phosphate',
	SH = 'Thiol group',
	SO3 = 'Sulfite',
	SO4 = 'Sulfate',
	SeH = 'Selenol group'
 }

 local T_ELEM = 0 -- token types
 local T_NUM = 1 -- number
 local T_OPEN = 2 -- open '('
 local T_CLOSE = 3 -- close ')'
 local T_PM_CHARGE = 4 -- + or −
 local T_WATER = 6 -- .xH2O x number
 local T_CRYSTAL = 9 -- .x
 local T_CHARGE = 8 -- charge (x+), (x-)
 local T_SUF_CHARGE = 10 -- suffix and charge e.g. 2+ from H2+
 local T_SUF_CHARGE2 = 12 -- suffix and (charge) e.g. 2(2+) from He2(2+)
 local T_SPECIAL = 14 -- starting with \ e.g. \d for double bond (=)
 local T_SPECIAL2 = 16 -- starting with \y{x} e.g. \i{12} for isotope with mass number 12
 local T_ARROW_R = 17 -- match: ->
 local T_ARROW_EQ = 18 -- match: <->
 local T_UNDERSCORE = 19 -- _{ ... }
 local T_CARET = 20 -- ^{ ... }
 local T_LINKOPEN = 21 -- Opening of link, always like "[[target|" even if the source wasn't
 local T_NOCHANGE = 30 -- Anything else like ☃

 function su(up, down)
	if up == "" then
		return ('<sub class="template-chem2-sub">%s</sub>'):format(down)
	end
	if down == "" then
		return ('<sup class="template-chem2-sup">%s</sup>'):format(up)
	end
 return ('<span class="template-chem2-su"><span>%s</span><span>%s</span></span>'):format(up, down)
 end

 function DotIt()
 return '&middot;'
 end

 function item(f) -- (iterator) returns one token (type, value) at a time from the formula 'f'
 local i = 1

 return function ()
 local t, x = nil, nil

 if (i == 1) and f:match('^[0-9]', i) then 
 x = f:match('^[%d.]+', i); t = T_NOCHANGE; i = i + x:len(); -- matching coefficient (need a space first)

 elseif i <= f:len() then
 x = f:match('^%s+[%d.]+', i); t = T_NOCHANGE; -- matching coefficient (need a space first)
 if not x then x = f:match('^%s[+]', i); t = T_NOCHANGE; end -- matching + (H2O + H2O)
 if not x then x = f:match('^%&%#[%w%d]+%;', i); t = T_NOCHANGE; end -- &#...;
 if not x then x = f:match('^%<%-%>', i); t = T_ARROW_EQ; end -- matching <->
 if not x then x = f:match('^%-%>', i); t = T_ARROW_R; end -- matching ->
 if not x then x = f:match('^%u%l*', i); t = T_ELEM; end -- matching symbols like Aaaaa
 if not x then x = f:match('^%d+[+-]', i); t = T_SUF_CHARGE; end -- matching x+, x-
 if not x then x = f:match('^%d+%(%d*[+-]%)', i); t = T_SUF_CHARGE2; end -- matching x(y+/-), x(+/-)
 if not x then x = f:match('^%(%d*[+-]%)', i); t = T_CHARGE; end -- matching (x+) (xx+), (x-) (xx-)
 if not x then x = f:match('^[%d.]+', i); t = T_NUM; end -- matching number
 if not x and (f:match('^%[%[%[[^[]', i) or f:match('^%[[^[]', i)) then
 	i = i + 1; return T_OPEN, '&#91;' end -- escape [[[X or [X (relevant to auto-linking)
 if not x and f:sub(i, i + 1) == '[[' then
 	x = f:match('^%[%[([^]|]*)', i) -- link target
 	local len = x:len() + 3
 	x = '[[' .. (groups[x] or am[x] or x) .. '|' -- override link target for common groups

 	if f:sub(len + i, len + i) == ']' then
 		-- We're going to read the link twice, once as target and once as
 		-- chemical markup, e.g. [[CH3]] => "[[CH3|", "CH3]]"
 		i = i + 2
 	else
 		i = i + len
 	end
 	return T_LINKOPEN, x
 end
 if not x then x = f:match('^[(|{|%[]', i); t = T_OPEN; end -- matching ({[
 if not x then x = f:match('^[)|}|%]]', i); t = T_CLOSE; end -- matching )}]
 if not x then x = f:match('^[+-]', i); t = T_PM_CHARGE; end -- matching + or -
 if not x then x = f:match('^%*[%d.]*H2O', i); t = T_WATER; end -- Crystal water
 if not x then x = f:match('^%*[%d.]*', i); t = T_CRYSTAL; end -- Crystal
 if not x then x = f:match('^[\\].{%d+}', i); t = T_SPECIAL2; end -- \y{x}
 if not x then x = f:match('^[\\].', i); t = T_SPECIAL; end -- \x
 if not x then x = f:match('^_{[^}]*}', i); t = T_UNDERSCORE; end -- _{...}
 if not x then x = f:match('^^{[^}]*}', i); t = T_CARET; end -- ^{...}
 if not x then x = f:match('^.', i); t = T_NOCHANGE; end --the rest - one by one
 if x then i = i + x:len(); else i = i + 999; error("Invalid character in formula! : "..f) end
 end
 return t, x
 end
 end

 function p._chem(args)
	
 local f = args[1] or ''

	f = mw.text.decode( f, true ) -- handle entity input (like &minus;): decode right away
 f = string.gsub(f, "–", "-") -- replace – with - (hyphen not ndash)
 f = string.gsub(f, "−", "-") -- replace – with - (hyphen not minus sign)

 local formula = ''
 local t, x

 local link = args['link'] or ""
 local auto = args['auto'] or ""
 local seen = {}
 local _debug = false

 if not (link == '') then formula = formula .. "[[" .. link .. "|"; end -- wikilink start [[link|
 
 for t, x in item(f) do 
 	if _debug then
 		formula = ("%s\n* %d %s"):format(formula, t, x)
 elseif t == T_ELEM then
 if (auto == '') or (not am[x]) or seen[x] then formula = formula .. x
 else formula = ("%s[[%s|%s]]"):format(formula, am[x], x); seen[x] = true
 end
 elseif t == T_COEFFICIENT then formula = formula .. x
 elseif t == T_NUM then formula = formula .. su("", x);
 elseif t == T_LINKOPEN then formula = formula .. x; -- [[Link|
 elseif t == T_OPEN then formula = formula .. x; -- ([{
 elseif t == T_CLOSE then formula = formula .. x; -- )]}
 elseif t == T_PM_CHARGE then formula = formula .. su(x:gsub("-", "−"), "");
 elseif t == T_SUF_CHARGE then 
 formula = formula .. su(x:match("[+-]"):gsub("-", "−"), x:match("%d+"), "");
 elseif t == T_SUF_CHARGE2 then 
 formula = formula .. su(x:match("%(%d*[+-]"):gsub("-", "−"):sub(2, -1), x:match("%d+"))
 elseif t == T_CHARGE then
 	formula = formula .. "<sup>"
 	if x:match("%d+") then formula = formula .. x:match("%d+"); end
 	formula = formula .. x:match("[%+-]"):gsub("-", "−") .. "</sup>";
 	-- Cannot concatenat a nil value from x:match("%d+");
 elseif t == T_CRYSTAL then formula = formula .. DotIt() .. string.gsub( x, "*", '', 1 );
 elseif t == T_SPECIAL then
 parameter = x:sub(2, 2) -- x fra \x 
 if parameter == "s" then formula = formula .. "−" -- single bond
 elseif parameter == "d" then formula = formula .. "=" -- double bond
 elseif parameter == "t" then formula = formula .. "≡" -- tripple bond
 elseif parameter == "q" then formula = formula .. "≣" -- Quadruple bond
 elseif parameter == "h" then formula = formula .. "η" -- η, hapticity
 elseif parameter == "*" then formula = formula .. "*" -- *, normal *
 elseif parameter == "-" then formula = formula .. "-" -- -
 elseif parameter == "\\" then formula = formula .. "\\" -- \
 elseif parameter == "\'" then formula = formula .. "&#39;" -- html-code for '
 end
 elseif t == T_SPECIAL2 then -- \y{x}
 parameter = x:sub(2, 2) -- y fra \y{x} 
 if parameter == "h" then --[[Hapticity]]
 if (auto == '') then formula = formula .. "η<sup>" .. x:match('%d+') .. "</sup>-"
 else
 formula = formula .. "[[Hapticity|η<sup>" .. x:match('%d+') .. "</sup>]]-"
 end
 elseif parameter == "m" then formula = formula .. "μ<sub>" .. x:match('%d+') .. "</sub>-" -- mu ([[bridging ligand]])
 end
 elseif t == T_WATER then 
 if x:match("^%*[%d.]") then 
 formula = formula .. DotIt() .. x:match("%f[%.%d]%d*%.?%d*%f[^%.%d%]]") .. "H<sub>2</sub>O";
 else
 formula = formula .. DotIt() .. "H<sub>2</sub>O";
 end
 elseif t == T_UNDERSCORE then formula = formula .. su("", x:gsub("-", "−"):sub(3, -2)) -- x contains _{string}
 elseif t == T_CARET then formula = formula .. su(x:gsub("-", "−"):sub(3, -2), "") -- x contains ^{string}
 elseif t == T_ARROW_R then formula = formula .. " → "
 elseif t == T_ARROW_EQ then formula = formula .. " ⇌ "
 elseif t == T_NOCHANGE then formula = formula .. x; -- The rest - everything which isn't captured by the regular expresions.
 else error('unreachable - ???') end -- in fact, unreachable
 end

 if not (link == nil or link == '') then formula = formula .. "]]"; end -- wikilink closing ]]
 formula = mw.getCurrentFrame():preprocess('<templatestyles src="Module:Chem2/styles.css"/>') ..
 '<span class="chemf nowrap">' .. formula .. '</span>'
 if args[2] or args[3] or args[4] then
 formula = formula .. require('Module:If preview')._warning{
 '&#123;&#123;chem2&#125;&#125; was called with multiple positional arguments. It should have just one, e.g. &#123;&#123;chem2&#124;H2O&#125;&#125;.'
 }
 end
 return formula
 end

 function p.chem(frame)
 local args = getArgs(frame)
 return p._chem(args)
 end

 -- PRIVATE function to generate documentation.
 function p._autodoc(frame)
	local TableTools = require('Module:TableTools') -- we don't want to load this on articles for no reason
	local result = {
		'===Elements and element-style symbols===\nThese may be automatically linked or used as if they were redirects.\n',
		'{| class="wikitable"\n! Symbol !! Link target\n'
	}
	for symbol, target in TableTools.sortedPairs(am) do
		result[#result + 1] = ('|-\n| %s || [[%s]]\n'):format(symbol, target)
	end
	result[#result + 1] = '|}\n===Groups===\nThese must be linked manually; they work as if they were redirects.\n'
	result[#result + 1] = '{| class="wikitable"\n! Symbol !! Link target\n'
	for symbol, target in TableTools.sortedPairs(groups) do
		result[#result + 1] = ('|-\n| %s || [[%s]]\n'):format(symbol, target)
	end
	result[#result + 1] = '|}'
	return table.concat(result)
 end

 return p

AltStyle によって変換されたページ (->オリジナル) /