Module:Chem2: Difference between revisions
Appearance
Content deleted Content added
Restored revision 1040345366 by El C (talk): Per Template talk:Chem2: no response after a week, restoring version before recent edits |
|||
Line 2: | Line 2: | ||
local p = {} -- module's table |
local p = {} -- module's table |
||
-- Elements with wiki links |
|||
local am = { |
|||
am.H="[[Hydrogen|H]]";am.He="[[Helium|He]]"; |
|||
H = "[[Hydrogen|H]]", |
|||
am.Li="[[Lithium|Li]]";am.Be="[[Beryllium|Be]]";am.B="[[Boron|B]]";am.C="[[Carbon|C]]";am.N="[[Nitrogen|N]]";am.O="[[Oxygen|O]]";am.F="[[Fluorine|F]]";am.Ne="[[Neon|Ne]]"; |
|||
He = "[[Helium|He]]", |
|||
am.Na="[[Sodium|Na]]";am.Mg="[[Magnesium|Mg]]";am.Al="[[Aluminium |Al]]";am.Si="[[Silicon|Si]]";am.P="[[Phosphorus|P]]";am.S="[[Sulfur|S]]";am.Cl="[[Chlorine|Cl]]";am.Ar="[[Argon|Ar]]"; |
|||
Li = "[[Lithium|Li]]", |
|||
am.K="[[Potassium|K]]";am.Ca="[[Calcium|Ca]]";am.Sc="[[Scandium|Sc]]";am.Ti="[[Titanium|Ti]]";am.V="[[Vanadium|V]]";am.Cr="[[Chromium|Cr]]";am.Mn="[[Manganese|Mn]]";am.Fe="[[Iron|Fe]]";am.Co="[[Cobalt|Co]]";am.Ni="[[Nickel|Ni]]";am.Cu="[[Copper|Cu]]";am.Zn="[[Zinc|Zn]]";am.Ga="[[Gallium|Ga]]";am.Ge="[[Germanium|Ge]]";am.As="[[Arsenic|As]]";am.Se="[[Selenium|Se]]";am.Br="[[Bromine|Br]]";am.Kr="[[Krypton|Kr]]";am.Rb="[[Rubidium|Rb]]"; |
|||
Be = "[[Beryllium|Be]]", |
|||
am.Sr="[[Strontium|Sr]]";am.Y="[[Yttrium|Y]]";am.Zr="[[Zirconium|Zr]]";am.Nb="[[Niobium|Nb]]";am.Mo="[[Molybdenum|Mo]]";am.Tc="[[Technetium|Tc]]";am.Ru="[[Ruthenium|Ru]]";am.Rh="[[Rhodium|Rh]]";am.Pd="[[Palladium|Pd]]";am.Ag="[[Silver|Ag]]";am.Cd="[[Cadmium|Cd]]";am.In="[[Indium|In]]";am.Sn="[[Tin|Sn]]";am.Sb="[[Antimony|Sb]]";am.Te="[[Tellurium|Te]]";am.I="[[Iodine|I]]";am.Xe="[[Xenon|Xe]]"; |
|||
B = "[[Boron|B]]", |
|||
am.Cs="[[Caesium|Cs]]";am.Ba="[[Barium|Ba]]";am.La="[[Lanthanum|La]]";am.Ce="[[Cerium|Ce]]";am.Pr="[[Praseodymium|Pr]]";am.Nd="[[Neodymium|Nd]]";am.Pm="[[Promethium|Pm]]";am.Sm="[[Samarium|Sm]]";am.Eu="[[Europium|Eu]]";am.Gd="[[Gadolinium|Gd]]";am.Tb="[[Terbium|Tb]]";am.Dy="[[Dysprosium|Dy]]";am.Ho="[[Holmium|Ho]]";am.Er="[[Erbium|Er]]";am.Tm="[[Thulium|Tm]]";am.Yb="[[Ytterbium|Yb]]";am.Lu="[[Lutetium|Lu]]";am.Hf="[[Hafnium|Hf]]";am.Ta="[[Tantalum|Ta]]";am.W="[[Tungsten|W]]";am.Re="[[Rhenium|Re]]";am.Os="[[Osmium|Os]]";am.Ir="[[Iridium|Ir]]";am.Pt="[[Platinum|Pt]]";am.Au="[[Gold|Au]]";am.Hg="[[Mercury (element)|Hg]]";am.Tl="[[Thallium|Tl]]";am.Pb="[[Lead|Pb]]";am.Bi="[[Bismuth|Bi]]";am.Po="[[Polonium|Po]]";am.At="[[Astatine|At]]";am.Rn="[[Radon|Rn]]"; |
|||
C = "[[Carbon|C]]", |
|||
am.Fr="[[Francium|Fr]]";am.Ra="[[Radium|Ra]]";am.Ac="[[Actinium|Ac]]";am.Th="[[Thorium|Th]]";am.Pa="[[Protactinium|Pa]]";am.U="[[Uranium|U]]";am.Np="[[Neptunium|Np]]";am.Pu="[[Plutonium|Pu]]";am.Am="[[Americium|Am]]";am.Cm="[[Curium|Cm]]";am.Bk="[[Berkelium|Bk]]";am.Cf="[[Californium|Cf]]";am.Es="[[Einsteinium|Es]]";am.Fm="[[Fermium|Fm]]";am.Md="[[Mendelevium|Md]]";am.No="[[Nobelium|No]]";am.Lr="[[Lawrencium|Lr]]";am.Rf="[[Rutherfordium|Rf]]";am.Db="[[Dubnium|Db]]";am.Sg="[[Seaborgium|Sg]]";am.Bh="[[Bohrium|Bh]]";am.Hs="[[Hassium|Hs]]";am.Mt="[[Meitnerium|Mt]]";am.Ds="[[Darmstadtium|Ds]]";am.Rg="[[Roentgenium|Rg]]";am.Cp="[[Copernicium|Cp]]";am.Nh="[[Nihonium|Nh]]";am.Fl="[[Flerovium|Fl]]";am.Mc="[[Moscovium|Mc]]";am.Lv="[[Livermorium|Lv]]";am.Ts="[[Tennessine|Ts]]";am.Og="[[Oganesson|Og]]"; |
|||
N = "[[Nitrogen|N]]", |
|||
O = "[[Oxygen|O]]", |
|||
F = "[[Fluorine|F]]", |
|||
Ne = "[[Neon|Ne]]", |
|||
Na = "[[Sodium|Na]]", |
|||
Mg = "[[Magnesium|Mg]]", |
|||
Al = "[[Aluminium |Al]]", |
|||
Si = "[[Silicon|Si]]", |
|||
P = "[[Phosphorus|P]]", |
|||
S = "[[Sulfur|S]]", |
|||
Cl = "[[Chlorine|Cl]]", |
|||
Ar = "[[Argon|Ar]]", |
|||
K = "[[Potassium|K]]", |
|||
Ca = "[[Calcium|Ca]]", |
|||
Sc = "[[Scandium|Sc]]", |
|||
Ti = "[[Titanium|Ti]]", |
|||
V = "[[Vanadium|V]]", |
|||
Cr = "[[Chromium|Cr]]", |
|||
Mn = "[[Manganese|Mn]]", |
|||
Fe = "[[Iron|Fe]]", |
|||
Co = "[[Cobalt|Co]]", |
|||
Ni = "[[Nickel|Ni]]", |
|||
Cu = "[[Copper|Cu]]", |
|||
Zn = "[[Zinc|Zn]]", |
|||
Ga = "[[Gallium|Ga]]", |
|||
Ge = "[[Germanium|Ge]]", |
|||
As = "[[Arsenic|As]]", |
|||
Se = "[[Selenium|Se]]", |
|||
Br = "[[Bromine|Br]]", |
|||
Kr = "[[Krypton|Kr]]", |
|||
Rb = "[[Rubidium|Rb]]", |
|||
Sr = "[[Strontium|Sr]]", |
|||
Y = "[[Yttrium|Y]]", |
|||
Zr = "[[Zirconium|Zr]]", |
|||
Nb = "[[Niobium|Nb]]", |
|||
Mo = "[[Molybdenum|Mo]]", |
|||
Tc = "[[Technetium|Tc]]", |
|||
Ru = "[[Ruthenium|Ru]]", |
|||
Rh = "[[Rhodium|Rh]]", |
|||
Pd = "[[Palladium|Pd]]", |
|||
Ag = "[[Silver|Ag]]", |
|||
Cd = "[[Cadmium|Cd]]", |
|||
In = "[[Indium|In]]", |
|||
Sn = "[[Tin|Sn]]", |
|||
Sb = "[[Antimony|Sb]]", |
|||
Te = "[[Tellurium|Te]]", |
|||
I = "[[Iodine|I]]", |
|||
Xe = "[[Xenon|Xe]]", |
|||
Cs = "[[Caesium|Cs]]", |
|||
Ba = "[[Barium|Ba]]", |
|||
La = "[[Lanthanum|La]]", |
|||
Ce = "[[Cerium|Ce]]", |
|||
Pr = "[[Praseodymium|Pr]]", |
|||
Nd = "[[Neodymium|Nd]]", |
|||
Pm = "[[Promethium|Pm]]", |
|||
Sm = "[[Samarium|Sm]]", |
|||
Eu = "[[Europium|Eu]]", |
|||
Gd = "[[Gadolinium|Gd]]", |
|||
Tb = "[[Terbium|Tb]]", |
|||
Dy = "[[Dysprosium|Dy]]", |
|||
Ho = "[[Holmium|Ho]]", |
|||
Er = "[[Erbium|Er]]", |
|||
Tm = "[[Thulium|Tm]]", |
|||
Yb = "[[Ytterbium|Yb]]", |
|||
Lu = "[[Lutetium|Lu]]", |
|||
Hf = "[[Hafnium|Hf]]", |
|||
Ta = "[[Tantalum|Ta]]", |
|||
W = "[[Tungsten|W]]", |
|||
Re = "[[Rhenium|Re]]", |
|||
Os = "[[Osmium|Os]]", |
|||
Ir = "[[Iridium|Ir]]", |
|||
Pt = "[[Platinum|Pt]]", |
|||
Au = "[[Gold|Au]]", |
|||
Hg = "[[Mercury (element)|Hg]]", |
|||
Tl = "[[Thallium|Tl]]", |
|||
Pb = "[[Lead|Pb]]", |
|||
Bi = "[[Bismuth|Bi]]", |
|||
Po = "[[Polonium|Po]]", |
|||
At = "[[Astatine|At]]", |
|||
Rn = "[[Radon|Rn]]", |
|||
Fr = "[[Francium|Fr]]", |
|||
Ra = "[[Radium|Ra]]", |
|||
Ac = "[[Actinium|Ac]]", |
|||
Th = "[[Thorium|Th]]", |
|||
Pa = "[[Protactinium|Pa]]", |
|||
U = "[[Uranium|U]]", |
|||
Np = "[[Neptunium|Np]]", |
|||
Pu = "[[Plutonium|Pu]]", |
|||
Am = "[[Americium|Am]]", |
|||
Cm = "[[Curium|Cm]]", |
|||
Bk = "[[Berkelium|Bk]]", |
|||
Cf = "[[Californium|Cf]]", |
|||
Es = "[[Einsteinium|Es]]", |
|||
Fm = "[[Fermium|Fm]]", |
|||
Md = "[[Mendelevium|Md]]", |
|||
No = "[[Nobelium|No]]", |
|||
Lr = "[[Lawrencium|Lr]]", |
|||
Rf = "[[Rutherfordium|Rf]]", |
|||
Db = "[[Dubnium|Db]]", |
|||
Sg = "[[Seaborgium|Sg]]", |
|||
Bh = "[[Bohrium|Bh]]", |
|||
Hs = "[[Hassium|Hs]]", |
|||
Mt = "[[Meitnerium|Mt]]", |
|||
Ds = "[[Darmstadtium|Ds]]", |
|||
Rg = "[[Roentgenium|Rg]]", |
|||
Cp = "[[Copernicium|Cp]]", |
|||
Nh = "[[Nihonium|Nh]]", |
|||
Fl = "[[Flerovium|Fl]]", |
|||
Mc = "[[Moscovium|Mc]]", |
|||
Lv = "[[Livermorium|Lv]]", |
|||
Ts = "[[Tennessine|Ts]]", |
|||
Og = "[[Oganesson|Og]]", |
|||
} |
|||
local T_ELEM = 0 -- token types |
local T_ELEM = 0 -- token types |
||
Line 27: | Line 140: | ||
local T_UNDERSCORE = 19 -- _{ ... } |
local T_UNDERSCORE = 19 -- _{ ... } |
||
local T_CARET = 20 -- ^{ ... } |
local T_CARET = 20 -- ^{ ... } |
||
local T_NOCHANGE = 30 |
local T_NOCHANGE = 30 -- Anything else like ☃ |
||
function su(up, down) |
function su(up, down) |
||
if up == "" then |
|||
return ('<sub class="template-chem2-sub">%s</sub>'):format(down) |
|||
return "<span style=\"display:inline-block; margin-bottom:-0.3em; vertical-align:0.8em; line-height:1.2em; font-size:70%; text-align:left;\">" .. up .. "<br /></span>"; |
|||
end |
|||
else |
|||
if down == "" then |
|||
return "<span style=\"display:inline-block; margin-bottom:-0.3em; vertical-align:-0.4em; line-height:1.2em; font-size:70%; text-align:left;\">" .. up .. "<br />" .. down .. "</span>"; |
|||
return ('<sup class="template-chem2-sup">%s</sup>'):format(up) |
|||
end |
|||
end |
|||
return ('<span class="template-chem2-su"><span>%s</span><span>%s</span></span>'):format(up, down) |
|||
end |
end |
||
function DotIt() |
function DotIt() |
||
return '·' |
return '·' |
||
end |
end |
||
function item(f) -- (iterator) returns one token (type, value) at a time from the formula 'f' |
function item(f) -- (iterator) returns one token (type, value) at a time from the formula 'f' |
||
local i = 1 |
local i = 1 |
||
local first = |
local first = true |
||
return function () |
return function () |
||
local t, x = nil, nil |
|||
if (first |
if (first 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 |
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 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 |
|||
first = |
first = false |
||
return t, x |
|||
end |
|||
end |
|||
function p._chem(args) |
function p._chem(args) |
||
local f = args[1] or '' |
|||
local f = args[1] or '' |
|||
f = string.gsub(f, "–", "-") -- replace – with - (hyphen not ndash) |
f = string.gsub(f, "–", "-") -- replace – with - (hyphen not ndash) |
||
f = string.gsub(f, "−", "-") -- replace – with - (hyphen not minus sign) |
f = string.gsub(f, "−", "-") -- replace – with - (hyphen not minus sign) |
||
local sumO = 0 |
local sumO = 0 |
||
local formula = '' |
local formula = '' |
||
local t, x |
local t, x |
||
local link = args['link'] or "" |
local link = args['link'] or "" |
||
local auto = args['auto'] or "" |
local auto = args['auto'] or "" |
||
if not (link == '') then formula = formula .. "[[" .. link .. "|"; end -- wikilink start [[link| |
if not (link == '') then formula = formula .. "[[" .. link .. "|"; end -- wikilink start [[link| |
||
for t, x in item(f) do |
for t, x in item(f) do |
||
if t == T_ELEM then |
|||
if (auto == '') then formula = formula .. x |
|||
elseif am[x] then formula = formula .. am[x]; am[x] = x |
|||
else formula = formula .. x |
|||
elseif t == T_COEFFICIENT then formula = formula .. x |
end |
||
elseif t == T_COEFFICIENT then formula = formula .. x |
|||
elseif t == T_NUM then formula = formula .. su("", x); |
elseif t == T_NUM then formula = formula .. su("", x); |
||
elseif t == T_OPEN then formula = formula .. x; sumO = sumO + 1; -- ( { |
elseif t == T_OPEN then formula = formula .. x; sumO = sumO + 1; -- ( { |
||
elseif t == T_CLOSE then formula = formula .. x; sumO = sumO -1; -- ) } |
elseif t == T_CLOSE then formula = formula .. x; sumO = sumO -1; -- ) } |
||
elseif t == T_PM_CHARGE then formula = formula .. su(string.gsub(x, "-", "−"), ""); |
elseif t == T_PM_CHARGE then formula = formula .. su(string.gsub(x, "-", "−"), ""); |
||
elseif t == T_SUF_CHARGE then |
elseif t == T_SUF_CHARGE then |
||
formula = formula .. su(string.gsub(string.match(x, "[+-]"), "-", "−"), string.match(x, "%d+"), ""); |
formula = formula .. su(string.gsub(string.match(x, "[+-]"), "-", "−"), string.match(x, "%d+"), ""); |
||
elseif t == T_SUF_CHARGE2 then |
elseif t == T_SUF_CHARGE2 then |
||
formula = formula .. su(string.sub(string.gsub(string.match(x, "%(%d*[+-]"), "-", "−"), 2, -1), string.match(x, "%d+")) |
formula = formula .. su(string.sub(string.gsub(string.match(x, "%(%d*[+-]"), "-", "−"), 2, -1), string.match(x, "%d+")) |
||
elseif t == T_CHARGE then formula = formula .. "<sup>"; if string.match(x, "%d+") then formula = formula .. string.match(x, "%d+"); end formula = formula .. string.gsub(string.match(x, "[%+-]"), "-", "−") .. "</sup>"; -- can not concatenat a nil value from string.match(x, "%d+"); |
elseif t == T_CHARGE then formula = formula .. "<sup>"; if string.match(x, "%d+") then formula = formula .. string.match(x, "%d+"); end formula = formula .. string.gsub(string.match(x, "[%+-]"), "-", "−") .. "</sup>"; -- can not concatenat a nil value from string.match(x, "%d+"); |
||
elseif t == T_CRYSTAL then formula = formula .. DotIt() .. string.gsub( x, "*", '', 1 ); |
elseif t == T_CRYSTAL then formula = formula .. DotIt() .. string.gsub( x, "*", '', 1 ); |
||
elseif t == T_SPECIAL then |
elseif t == T_SPECIAL then |
||
parameter = string.sub(x, 2, 2) -- x fra \x |
parameter = string.sub(x, 2, 2) -- x fra \x |
||
if parameter == "s" then formula = formula .. "−" -- single bond |
|||
elseif parameter == "d" then formula = formula .. "=" -- double bond |
elseif parameter == "d" then formula = formula .. "=" -- double bond |
||
elseif parameter == "t" then formula = formula .. "≡" -- tripple bond |
elseif parameter == "t" then formula = formula .. "≡" -- tripple bond |
||
Line 120: | Line 237: | ||
elseif parameter == "\\" then formula = formula .. "\\" -- \ |
elseif parameter == "\\" then formula = formula .. "\\" -- \ |
||
elseif parameter == "\'" then formula = formula .. "'" -- html-code for ' |
elseif parameter == "\'" then formula = formula .. "'" -- html-code for ' |
||
end |
end |
||
elseif t == T_SPECIAL2 then -- \y{x} |
elseif t == T_SPECIAL2 then -- \y{x} |
||
parameter = string.sub(x, 2, 2) -- y fra \y{x} |
parameter = string.sub(x, 2, 2) -- y fra \y{x} |
||
if parameter == "h" then --[[Hapticity]] |
if parameter == "h" then --[[Hapticity]] |
||
if (auto == '') then formula = formula .. "η<sup>" .. string.match(x, '%d+') .. "</sup>-" |
if (auto == '') then formula = formula .. "η<sup>" .. string.match(x, '%d+') .. "</sup>-" |
||
else |
else |
||
formula = formula .. "[[Hapticity|η<sup>" .. string.match(x, '%d+') .. "</sup>]]-" |
formula = formula .. "[[Hapticity|η<sup>" .. string.match(x, '%d+') .. "</sup>]]-" |
||
end |
end |
||
elseif parameter == "m" then formula = formula .. "μ<sub>" .. string.match(x, '%d+') .. "</sub>-" -- mu ([[bridging ligand]]) |
elseif parameter == "m" then formula = formula .. "μ<sub>" .. string.match(x, '%d+') .. "</sub>-" -- mu ([[bridging ligand]]) |
||
end |
end |
||
elseif t == T_WATER then |
elseif t == T_WATER then |
||
if string.match(x, "^%*[%d.]") then |
if string.match(x, "^%*[%d.]") then |
||
formula = formula .. DotIt() .. string.match(x, "%f[%.%d]%d*%.?%d*%f[^%.%d%]]") .. "H<sub>2</sub>O"; |
formula = formula .. DotIt() .. string.match(x, "%f[%.%d]%d*%.?%d*%f[^%.%d%]]") .. "H<sub>2</sub>O"; |
||
else |
else |
||
formula = formula .. DotIt() .. "H<sub>2</sub>O"; |
formula = formula .. DotIt() .. "H<sub>2</sub>O"; |
||
end |
end |
||
elseif t == T_UNDERSCORE then formula = formula .. su("", string.sub(x,3,-2)) -- x contains _{string} |
elseif t == T_UNDERSCORE then formula = formula .. su("", string.sub(x,3,-2)) -- x contains _{string} |
||
elseif t == T_CARET then formula = formula .. su(string.sub(x,3,-2), "") -- x contains ^{string} |
elseif t == T_CARET then formula = formula .. su(string.sub(x,3,-2), "") -- x contains ^{string} |
||
elseif t == T_ARROW_R then formula = formula .. " → " |
elseif t == T_ARROW_R then formula = formula .. " → " |
||
elseif t == T_ARROW_EQ 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. E.g. wikilinks and pipes |
elseif t == T_NOCHANGE then formula = formula .. x; -- The rest - everything which isn't captured by the regular expresions. E.g. wikilinks and pipes |
||
else error('unreachable - ???') end -- in fact, unreachable |
else error('unreachable - ???') end -- in fact, unreachable |
||
end |
|||
end |
|||
if not (link == nil or link == '') then formula = formula .. "]]"; end -- wikilink closing ]] |
|||
if not (link == nil or link == '') then formula = formula .. "]]"; end -- wikilink closing ]] |
|||
return '<span class="chemf nowrap">' .. formula .. '</span>' |
|||
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{ |
|||
'{{chem2}} was called with multiple positional arguments. It should have just one, e.g. {{chem2|H2O}}.' |
|||
} |
|||
end |
|||
return formula |
|||
end |
end |
||
function p.chem(frame) |
function p.chem(frame) |
||
local args = getArgs(frame) |
|||
return p._chem(args) |
|||
end |
end |
||
Revision as of 12:01, 12 December 2021
![]() | 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. |
![]() | 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. |
![]() | This Lua module is used on approximately 8,100 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 uses TemplateStyles: |
This module implements {{chem2}}. Please see its documentation for details.
local getArgs = require('Module:Arguments').getArgs
local p = {} -- module's table
-- Elements with wiki links
local am = {
H = "[[Hydrogen|H]]",
He = "[[Helium|He]]",
Li = "[[Lithium|Li]]",
Be = "[[Beryllium|Be]]",
B = "[[Boron|B]]",
C = "[[Carbon|C]]",
N = "[[Nitrogen|N]]",
O = "[[Oxygen|O]]",
F = "[[Fluorine|F]]",
Ne = "[[Neon|Ne]]",
Na = "[[Sodium|Na]]",
Mg = "[[Magnesium|Mg]]",
Al = "[[Aluminium |Al]]",
Si = "[[Silicon|Si]]",
P = "[[Phosphorus|P]]",
S = "[[Sulfur|S]]",
Cl = "[[Chlorine|Cl]]",
Ar = "[[Argon|Ar]]",
K = "[[Potassium|K]]",
Ca = "[[Calcium|Ca]]",
Sc = "[[Scandium|Sc]]",
Ti = "[[Titanium|Ti]]",
V = "[[Vanadium|V]]",
Cr = "[[Chromium|Cr]]",
Mn = "[[Manganese|Mn]]",
Fe = "[[Iron|Fe]]",
Co = "[[Cobalt|Co]]",
Ni = "[[Nickel|Ni]]",
Cu = "[[Copper|Cu]]",
Zn = "[[Zinc|Zn]]",
Ga = "[[Gallium|Ga]]",
Ge = "[[Germanium|Ge]]",
As = "[[Arsenic|As]]",
Se = "[[Selenium|Se]]",
Br = "[[Bromine|Br]]",
Kr = "[[Krypton|Kr]]",
Rb = "[[Rubidium|Rb]]",
Sr = "[[Strontium|Sr]]",
Y = "[[Yttrium|Y]]",
Zr = "[[Zirconium|Zr]]",
Nb = "[[Niobium|Nb]]",
Mo = "[[Molybdenum|Mo]]",
Tc = "[[Technetium|Tc]]",
Ru = "[[Ruthenium|Ru]]",
Rh = "[[Rhodium|Rh]]",
Pd = "[[Palladium|Pd]]",
Ag = "[[Silver|Ag]]",
Cd = "[[Cadmium|Cd]]",
In = "[[Indium|In]]",
Sn = "[[Tin|Sn]]",
Sb = "[[Antimony|Sb]]",
Te = "[[Tellurium|Te]]",
I = "[[Iodine|I]]",
Xe = "[[Xenon|Xe]]",
Cs = "[[Caesium|Cs]]",
Ba = "[[Barium|Ba]]",
La = "[[Lanthanum|La]]",
Ce = "[[Cerium|Ce]]",
Pr = "[[Praseodymium|Pr]]",
Nd = "[[Neodymium|Nd]]",
Pm = "[[Promethium|Pm]]",
Sm = "[[Samarium|Sm]]",
Eu = "[[Europium|Eu]]",
Gd = "[[Gadolinium|Gd]]",
Tb = "[[Terbium|Tb]]",
Dy = "[[Dysprosium|Dy]]",
Ho = "[[Holmium|Ho]]",
Er = "[[Erbium|Er]]",
Tm = "[[Thulium|Tm]]",
Yb = "[[Ytterbium|Yb]]",
Lu = "[[Lutetium|Lu]]",
Hf = "[[Hafnium|Hf]]",
Ta = "[[Tantalum|Ta]]",
W = "[[Tungsten|W]]",
Re = "[[Rhenium|Re]]",
Os = "[[Osmium|Os]]",
Ir = "[[Iridium|Ir]]",
Pt = "[[Platinum|Pt]]",
Au = "[[Gold|Au]]",
Hg = "[[Mercury (element)|Hg]]",
Tl = "[[Thallium|Tl]]",
Pb = "[[Lead|Pb]]",
Bi = "[[Bismuth|Bi]]",
Po = "[[Polonium|Po]]",
At = "[[Astatine|At]]",
Rn = "[[Radon|Rn]]",
Fr = "[[Francium|Fr]]",
Ra = "[[Radium|Ra]]",
Ac = "[[Actinium|Ac]]",
Th = "[[Thorium|Th]]",
Pa = "[[Protactinium|Pa]]",
U = "[[Uranium|U]]",
Np = "[[Neptunium|Np]]",
Pu = "[[Plutonium|Pu]]",
Am = "[[Americium|Am]]",
Cm = "[[Curium|Cm]]",
Bk = "[[Berkelium|Bk]]",
Cf = "[[Californium|Cf]]",
Es = "[[Einsteinium|Es]]",
Fm = "[[Fermium|Fm]]",
Md = "[[Mendelevium|Md]]",
No = "[[Nobelium|No]]",
Lr = "[[Lawrencium|Lr]]",
Rf = "[[Rutherfordium|Rf]]",
Db = "[[Dubnium|Db]]",
Sg = "[[Seaborgium|Sg]]",
Bh = "[[Bohrium|Bh]]",
Hs = "[[Hassium|Hs]]",
Mt = "[[Meitnerium|Mt]]",
Ds = "[[Darmstadtium|Ds]]",
Rg = "[[Roentgenium|Rg]]",
Cp = "[[Copernicium|Cp]]",
Nh = "[[Nihonium|Nh]]",
Fl = "[[Flerovium|Fl]]",
Mc = "[[Moscovium|Mc]]",
Lv = "[[Livermorium|Lv]]",
Ts = "[[Tennessine|Ts]]",
Og = "[[Oganesson|Og]]",
}
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_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 '·'
end
function item(f) -- (iterator) returns one token (type, value) at a time from the formula 'f'
local i = 1
local first = true
return function ()
local t, x = nil, nil
if (first 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 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
first = false
return t, x
end
end
function p._chem(args)
local f = args[1] or ''
f = string.gsub(f, "–", "-") -- replace – with - (hyphen not ndash)
f = string.gsub(f, "−", "-") -- replace – with - (hyphen not minus sign)
local sumO = 0
local formula = ''
local t, x
local link = args['link'] or ""
local auto = args['auto'] or ""
if not (link == '') then formula = formula .. "[[" .. link .. "|"; end -- wikilink start [[link|
for t, x in item(f) do
if t == T_ELEM then
if (auto == '') then formula = formula .. x
elseif am[x] then formula = formula .. am[x]; am[x] = x
else formula = formula .. x
end
elseif t == T_COEFFICIENT then formula = formula .. x
elseif t == T_NUM then formula = formula .. su("", x);
elseif t == T_OPEN then formula = formula .. x; sumO = sumO + 1; -- ( {
elseif t == T_CLOSE then formula = formula .. x; sumO = sumO -1; -- ) }
elseif t == T_PM_CHARGE then formula = formula .. su(string.gsub(x, "-", "−"), "");
elseif t == T_SUF_CHARGE then
formula = formula .. su(string.gsub(string.match(x, "[+-]"), "-", "−"), string.match(x, "%d+"), "");
elseif t == T_SUF_CHARGE2 then
formula = formula .. su(string.sub(string.gsub(string.match(x, "%(%d*[+-]"), "-", "−"), 2, -1), string.match(x, "%d+"))
elseif t == T_CHARGE then formula = formula .. "<sup>"; if string.match(x, "%d+") then formula = formula .. string.match(x, "%d+"); end formula = formula .. string.gsub(string.match(x, "[%+-]"), "-", "−") .. "</sup>"; -- can not concatenat a nil value from string.match(x, "%d+");
elseif t == T_CRYSTAL then formula = formula .. DotIt() .. string.gsub( x, "*", '', 1 );
elseif t == T_SPECIAL then
parameter = string.sub(x, 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 .. "'" -- html-code for '
end
elseif t == T_SPECIAL2 then -- \y{x}
parameter = string.sub(x, 2, 2) -- y fra \y{x}
if parameter == "h" then --[[Hapticity]]
if (auto == '') then formula = formula .. "η<sup>" .. string.match(x, '%d+') .. "</sup>-"
else
formula = formula .. "[[Hapticity|η<sup>" .. string.match(x, '%d+') .. "</sup>]]-"
end
elseif parameter == "m" then formula = formula .. "μ<sub>" .. string.match(x, '%d+') .. "</sub>-" -- mu ([[bridging ligand]])
end
elseif t == T_WATER then
if string.match(x, "^%*[%d.]") then
formula = formula .. DotIt() .. string.match(x, "%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("", string.sub(x,3,-2)) -- x contains _{string}
elseif t == T_CARET then formula = formula .. su(string.sub(x,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. E.g. wikilinks and pipes
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{
'{{chem2}} was called with multiple positional arguments. It should have just one, e.g. {{chem2|H2O}}.'
}
end
return formula
end
function p.chem(frame)
local args = getArgs(frame)
return p._chem(args)
end
return p