Module:Chem2: Difference between revisions
Appearance
Content deleted Content added
Copy from sandbox Tag: Reverted |
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 = {} -- Elements with wiki links |
||
am.H="[[Hydrogen|H]]";am.He="[[Helium|He]]"; |
|||
local am = { |
|||
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]]"; |
|||
H = "[[Hydrogen|H]]", |
|||
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]]"; |
|||
He = "[[Helium|He]]", |
|||
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]]"; |
|||
Li = "[[Lithium|Li]]", |
|||
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]]"; |
|||
Be = "[[Beryllium|Be]]", |
|||
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]]"; |
|||
B = "[[Boron|B]]", |
|||
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]]"; |
|||
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_ELEM = 0 -- token types |
||
Line 140: | Line 27: | ||
local T_UNDERSCORE = 19 -- _{ ... } |
local T_UNDERSCORE = 19 -- _{ ... } |
||
local T_CARET = 20 -- ^{ ... } |
local T_CARET = 20 -- ^{ ... } |
||
local T_NOCHANGE = 30 -- Anything else like ☃ |
local T_NOCHANGE = 30 -- Anything else like ☃ |
||
function su(up, down) |
function su(up, down) -- like template:su |
||
if (down == "") then |
|||
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>"; |
|||
return ('<sub class="template-chem2-sub">%s</sub>'):format(down) |
|||
else |
|||
end |
|||
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>"; |
|||
if down == "" then |
|||
end |
|||
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 |
end |
||
function DotIt() |
function DotIt() |
||
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 first = "true"; |
|||
return function () |
|||
local t, x = nil, nil |
|||
if (first and f:match('^[0-9]', i)) then |
if (first == "true" 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) |
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) |
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 |
first = "false" |
||
return t, x |
|||
end |
|||
end |
end |
||
function p._chem(args) |
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 |
|||
if t == T_ELEM then |
|||
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; -- ) } |
|||
end |
|||
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_SUF_CHARGE then |
|||
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 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 == "d" then formula = formula .. "=" -- double bond |
||
elseif parameter == "t" then formula = formula .. "≡" -- tripple bond |
elseif parameter == "t" then formula = formula .. "≡" -- tripple bond |
||
Line 237: | Line 120: | ||
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 |
|||
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 |
|||
end |
|||
if not (link == nil or link == '') then formula = formula .. "]]"; end -- wikilink closing ]] |
|||
return '<span class="chemf nowrap">' .. formula .. '</span>' |
|||
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 |
end |
||
function p.chem(frame) |
function p.chem(frame) |
||
local args = getArgs(frame) |
|||
return p._chem(args) |
|||
end |
end |
||
Revision as of 11:53, 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
local am = {} -- Elements with wiki links
am.H="[[Hydrogen|H]]";am.He="[[Helium|He]]";
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]]";
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]]";
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]]";
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]]";
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]]";
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]]";
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) -- like template:su
if (down == "") then
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>";
else
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>";
end
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 == "true" 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 ]]
return '<span class="chemf nowrap">' .. formula .. '</span>'
end
function p.chem(frame)
local args = getArgs(frame)
return p._chem(args)
end
return p