Skip to content

Chemistry Metadata

Every SVG exported from the Export SVG dialog carries a machine-readable description of the structure (there is no longer a checkbox for it; older builds had an Embed chemistry metadata option). Molkit stamps it into the SVG itself: scalar attributes on the root element, data-mk-* attributes on every atom group and bond group, and a structured mk:chemistry block inside the file’s metadata element. Your page script can read the formula, walk the bond graph, or hand the embedded MOL block to a cheminformatics library without a server round trip. This page is the schema reference.

Reading conventions

  • Attribute values are strings. Numbers are plain decimals. Boolean flags are the literal "true" and are omitted when false; there is no "false" value except where noted.
  • Attributes marked “JSON” hold JSON text and need JSON.parse.
  • getAttribute returns null for an absent attribute. An absent attribute means “not applicable” or “not computed”, never zero.
  • Coordinates in data-mk-x, data-mk-y, the bond endpoint attributes, and data-mk-view-boxes are in the SVG’s own coordinate space (the root viewBox space, Y grows downward).

Root attributes

Scalar attributes on the svg root give you the identity of the structure without walking the tree. They are duplicated outside the metadata block so they survive HTML sanitizers that strip metadata elements.

AttributeWhen presentValue and meaning
data-mk-versionalwaysSchema version, currently 1.0
data-mk-species-typethe structure is a real species (no generic atoms)molecular, element, monatomic-ion, polyatomic-ion, or ionic (a salt drawn as separate charged ions). See species type
data-mk-slugthe molecule has a user-set nameKebab-case identity, e.g. carbon-monoxide
data-mk-formulaidentity is emitted (see below)Molecular formula. Ions carry a Unicode superscript charge, e.g. NO3⁻, CO3²⁻. Carbon compounds use Hill order; carbon-free compounds use the IUPAC element sequence (NH3, SO2, PF5). Isotope labels appear in the formula, e.g. D2O
data-mk-mwidentity is emittedMolecular weight in g/mol, rounded to three decimals
data-mk-smilesidentity is emitted and SMILES generation succeededSMILES string, built from computed formal charges
data-mk-canonical-smilesRDKit canonicalization ranCanonical SMILES
data-mk-inchiPubChem lookup succeeded with a full property matchInChI
data-mk-inchi-keysame as above27-character InChIKey
data-mk-cidPubChem lookup returned a compoundPubChem compound ID
data-mk-has-abbreviationsa condensed label such as CH3 or OEt was decomposed"true". See condensed labels
data-mk-has-generic-definitionsR-group definitions were exported"true". See mk:generic-definitions
data-mk-has-resonancea resonance set was exported"true"
data-mk-has-visual-setsa visual set (one species drawn in several views) was exported"true"
data-mk-viewswith data-mk-has-visual-setsComma-separated views in canonical order: lewis, vsepr, condensed, bondline, fischer, orbitals
data-mk-default-viewwith data-mk-has-visual-setsThe view the author chose to open on
data-mk-default-layoutthe Lewis view has two layoutsorthogonal or zigzag: the Lewis layout to open on
data-mk-view-boxeswith data-mk-has-visual-setsJSON object mapping a view (or view.layout when a view has two Lewis layouts) to an "x y w h" box in root viewBox space. Set the root viewBox to one box to show only that depiction

When identity is emitted. The formula, molecular weight, and SMILES attributes are written when the export holds exactly one covalently connected species, an ionic salt whose charges balance to zero, or a resonance set or visual set (one species drawn several times, reported from one depiction). They are never written when any atom is a generic placeholder. Non-covalent bonds (hydrogen bonds, order-0 coordination, dotted bonds) do not join two species into one.

The InChI, InChIKey, and CID attributes come from an online lookup at export time (see PubChem integration). If the export happened offline, or PubChem did not recognize the structure, they are absent. When a PubChem hit disagrees with the drawn formula (for example a radical that PubChem completes with hydrogen), Molkit falls back to a formula search, which returns only a CID and a name, so data-mk-cid can be present without data-mk-inchi.

Species type

data-mk-species-type (mirrored as mk:species-type) is derived from covalent components and their net formal charges:

ValueMeaningExample
molecularone neutral species of mixed elements, including zwitterions; also neutral mixtureswater, glycine
elementneutral species of one elementO2, S8
monatomic-ionone charged atomCl⁻
polyatomic-ionone charged multi-atom speciesNO3⁻
ionictwo or more components with at least one positive and one negativeNaCl, NH4NO3

Per-atom attributes

Every atom group (the element that carries the atom’s data-id, class atom-group) gets its own attribute set. Query atoms with [data-mk-element].

AttributeWhen presentValue and meaning
data-mk-elementalwaysElement symbol, e.g. N. * for a generic placeholder
data-mk-x, data-mk-ynon-generic atomsAtom position
data-mk-indexnon-generic atomsZero-based atom index. For a single molecule it matches the MOL block atom order
data-mk-formal-chargenon-generic atomsFormal charge computed from bonds and lone pairs; can be 0 or negative
data-mk-lone-pairsnon-generic atomsLone pair count
data-mk-domains-bondingnon-generic atomsBonding electron domains (VSEPR). Includes coordinate bonds to lone ions drawn around a core, so SF6 drawn as four S-F bonds plus two F⁻ reads 6
data-mk-domains-nonbondingnon-generic atomsNonbonding electron domains (VSEPR)
data-mk-implicit-hnon-generic atomsImplicit hydrogen count. Reads 0 when the omit-implicit-H export option was checked
data-mk-implicit-h-metaimplicit H count above 0JSON object describing each implicit H: element, bondedTo, bonds, lonePairs, hybridization (null), formalCharge, valenceElectrons, octet, oxidationState (1, or -1 when bonded to a less electronegative atom such as B or Si)
data-mk-octetthe octet is defined for this atomsatisfied, deficient, or expanded. Absent for generic placeholders, atoms in a three-center two-electron bridge (bridging H and its bridgeheads), and bare transition-metal ions
data-mk-valence-electronsnon-generic atomsValence electrons contributed by this atom
data-mk-radicalthe atom has unpaired electronsNumber of unpaired electrons, e.g. 1 on the N of NO2
data-mk-warningsnon-generic atomsJSON array of validator warning types: valence, charge, coincident. [] when clean. See the note below
data-mk-hybridizationthe domain count maps to a hybridizationsp, sp2, sp3, sp3d, or sp3d2
data-mk-lp-delocalizedwith data-mk-hybridization, when a lone pair is delocalized into an adjacent pi bond"true". The atom reports sp2 although it has four domains. See delocalized lone pairs
data-mk-geometrythe VSEPR geometry is knownGeometry name, e.g. trigonal planar, trigonal pyramidal, seesaw, square planar
data-mk-vsepr-angleswith data-mk-geometryJSON array of reference angles in degrees for that geometry, e.g. [120], [107] for ammonia, [134] for a centre with one unpaired electron and no lone pair (NO2)
data-mk-chiralfour distinct substituents detected"true". A heuristic (element and bond order of each neighbour), not a full CIP analysis
data-mk-isotopean isotope label is setMass number
data-mk-aromaticatom in an aromatic ring"true"
data-mk-ring-sizesatom in at least one ringJSON array of ring sizes, e.g. [6]
data-mk-oxidation-statecomputableOxidation state
data-mk-abbreviationthe atom is drawn with a custom labelThe displayed label, e.g. OEt or R
data-mk-abbreviation-headthe label was decomposed into mk:abbreviations"true". See condensed labels
data-mk-oxidation-state-ambiguousabbreviation heads only, when bonds to like atoms split electrons evenly"true"

Warnings on bracketed ions. An ion drawn with neutral atoms and its charge on the bracket does not get a charge warning when the bracket charge agrees with the electrons. The export applies the same bracket check as the app, so the warnings written to the file match what the canvas shows.

Delocalized lone pairs

An N or O with only single bonds, at least one lone pair, and a neighbour that carries a pi bond has its lone pair delocalized into that pi bond.

  • An amide nitrogen (neighbour is C=O or C=S) or a nitrogen with two pi-bearing neighbours (pyrrole) reports sp2, trigonal planar, and [120].
  • An oxygen next to a pi bond (acid, ester, phenol) reports sp2 but keeps its measured bent geometry and angle.

In both cases data-mk-domains-bonding plus data-mk-domains-nonbonding still totals four, and data-mk-lp-delocalized="true" tells you why the hybridization does not follow the domain count. The atom is not flagged when it is part of a coordinate-bond core.

Generic placeholder atoms

Generic atoms (R, R’, X, Y, Z, A, E, Nu, LG, and the other labels in the generics palette) are stored with element *. The export writes only three attributes on them:

AttributeValue
data-mk-generic"true"
data-mk-element*
data-mk-abbreviationthe displayed label, e.g. R or X

No per-atom chemistry is written for a generic atom, because it is undefined by design. A is recognized alongside X and E, so a VSEPR template drawn as AX2E2 is exported as placeholders rather than as a carbon atom. Any generic atom in the export also suppresses the molecule-level identity: there is no formula, SMILES, species type, or MOL block, and mk:chemistry gains mk:indeterminate (text true) and mk:generic-labels (a JSON array of the labels).

Condensed labels

When an atom is drawn with a condensed label that Molkit can parse (CH3, CH2, OCH3, CO2H, and similar), the atom group gets data-mk-abbreviation-head="true", and its per-atom attributes are rewritten from the attach atom of the parsed group and its real bonds, so a CH3 carbon reads sp3 with zero lone pairs. data-mk-geometry and data-mk-vsepr-angles are removed from the head, because the group members carry the real shape. The decomposition itself is in mk:abbreviations.

Per-bond attributes

Bond groups carry the graph topology plus rendered geometry. Query bonds with [data-mk-order].

AttributeWhen presentValue and meaning
data-mk-orderalwaysBond order: 1, 2, 3, or 1.5
data-mk-atom1, data-mk-atom2alwaysdata-id of each endpoint atom
data-mk-x1, data-mk-y1, data-mk-x2, data-mk-y2geometry could be readRendered start and end points of the bond line
data-mk-stereonon-plain bondsDrawn bond style, e.g. wedge, dash, wavy, aromatic, dative
data-mk-polarityelectronegativity difference at or above 0.05Pauling electronegativity difference, two decimals
data-mk-polar-towardwith data-mk-polarityElement symbol of the more electronegative end
data-mk-conjugatedbond in a conjugated system"true"
data-mk-resonance-orderaromatic bonds1.5
data-mk-avg-bond-orderbonds in a resonance set whose forms share one skeletonAverage bond order over the non-minor forms, e.g. 1.33
data-mk-avg-bond-order-rangethe order varies across formsmin-max, e.g. 1-2

Resonance and visual-set tags

Resonance sets and visual sets draw one species several times in the same file. Each drawing’s atom groups, bond groups, and decorations (ion brackets, charge labels) are tagged so a consumer can show one drawing at a time.

AttributeAppears onValue and meaning
data-mk-resonance-setatoms, bonds, decorations of a resonance formSet id. In a visual set it is setId:view, extended with :layout and :octet when the set has more than one Lewis layout or mixes octet models
data-mk-resonance-indexsameForm index within the set, as a string
data-mk-resonance-arrowresonance arrows"true"
data-mk-visual-setatoms, bonds, decorations, arrows in a visual setVisual set id
data-mk-viewsame, and mk:conformer-3dSpace-separated list of views this drawing serves, e.g. lewis vsepr for a planar drawing that is both
data-mk-lewis-layoutLewis drawings in a set with two layouts, and matching conformersorthogonal or zigzag
data-mk-octet-modeldrawings in a set that mixes octet modelsexpanded or strict. Distinct from the per-atom data-mk-octet
data-mk-resonance-parenta convenience drawing that stands for several forms"true"
data-mk-resonance-parent-kindwith data-mk-resonance-parente.g. expanded-octet, aromatic
data-mk-resonance-notewith data-mk-resonance-parent, when the author wrote oneFree text

A drawing that is the only form in its view gets data-mk-visual-set and data-mk-view but no resonance tags. Resonance arrows in a visual set get only data-mk-visual-set, data-mk-view, and data-mk-lewis-layout, because they connect forms rather than belong to one.

The metadata element

Deeper data lives in the mk:chemistry element inside the SVG’s metadata element, in the namespace https://molkit.app/ns/chemistry/1.0. Children appear roughly in the order below (PubChem results are appended last), so match them by localName rather than position.

ElementWhen presentContent
mk:molkit-versionevery exportMolkit version that wrote the file
mk:createdevery exportISO 8601 timestamp
mk:urlevery exporthttps://molkit.com
mk:schema-orgevery exportJSON-LD. A Schema.org MolecularEntity when identity is emitted, otherwise a SoftwareApplication block describing Molkit
mk:authorthe document has an authorText
mk:common-namesuser-entered names, or PubChem synonymsComma-separated text as entered; replaced by a JSON array when PubChem synonyms are merged in
mk:indeterminate, mk:generic-labelsa generic atom is presenttrue; JSON array of labels
mk:species-typeas data-mk-species-typeSame value
mk:common-nameuser-set name, or the first PubChem synonymText
mk:pubchem-cid, mk:iupac-name, mk:inchi, mk:inchi-keyfrom a stored identity or the PubChem lookupText
mk:generic-definitionsR-group definitions existOne mk:def label atom per generic atom, each holding mk:member display smiles [source] children
mk:abbreviationscondensed labels were decomposedOne mk:group atom label resolved per labelled atom. A resolved group adds source, attach, mk:member i element x y lone-pairs implicit-h [formal-charge] children, and mk:bond from to order children
mk:formula, mk:molecular-weight, mk:smiles, mk:canonical-smilesidentity is emittedAs the root attributes
mk:formula-htmla single moleculeFormula with sub and sup markup
mk:exact-massa single moleculeMonoisotopic mass, four decimals
mk:atom-count, mk:bond-count, mk:total-valence-electrons, mk:degree-of-unsaturationa single moleculeNumbers; counts include implicit hydrogens
mk:element-compositiona single moleculeJSON object of element counts
mk:point-group, mk:point-group-confidencea single molecule, when determinableSchoenflies symbol and a confidence rating
mk:functional-groupsa single molecule with detected groupsJSON array of group names
mk:mol-blocka single moleculeV2000 molfile
mk:conformer-3d, mk:dipole3D conformer generation succeeded at exportSee 3D conformers and dipoles
mk:espa molecule in the export has a current electrostatic potential map, and the map was not left outSee electrostatic potential maps
mk:dipole-measuredthe species has a reference dipole on fileSee measured dipole
mk:resonancea resonance set was exportedSee resonance and visual-set blocks
mk:visual-seta visual set was exportedSame

“A single molecule” here means a genuine single species. For a resonance set or visual set, only the formula, molecular weight, SMILES, and JSON-LD are written, because the other counts would add up every drawing.

When the author ticks Include editable source, the export also puts an mk:source element next to mk:chemistry inside the metadata element. It carries Molkit’s editable document so the SVG can be reopened in Molkit. It is off by default, it is not chemistry data, and readers should not depend on it; everything a reader needs is in the attributes and elements above.

JSON-LD

The MolecularEntity payload, taken from a real export of ammonia:

mk:schema-org contents (ammonia.svg)
{
"@context": "https://schema.org",
"@type": "MolecularEntity",
"name": "NH3",
"molecularFormula": "NH3",
"molecularWeight": "17.031",
"smiles": "[H]N([H])[H]",
"hasRepresentation": {
"@type": "ImageObject",
"encodingFormat": "image/svg+xml",
"creator": {
"@type": "SoftwareApplication",
"name": "Molkit",
"url": "https://molkit.com"
}
}
}

When the PubChem lookup succeeds, name becomes the IUPAC name and iupacName, inChI, inChIKey, and identifier (CID:<number>) are added.

3D conformers and dipoles

SVG exports also embed 3D data. Conformer generation runs at export time and is best-effort: if it fails, the file has no conformer block and nothing else changes. When it succeeds, each non-generic species gets one mk:conformer-3d element with generated 3D coordinates, followed by its mk:dipole elements. A consumer can render the 3D model from these without any chemistry library.

from a real export of carbon monoxide
<mk:conformer-3d component="0" source="openchemlib" added-h="false" units="angstrom"
frame="drawing-aligned" scope="molecule" data-mk-view="lewis" data-mk-conformer-primary="true">
<mk:atoms>C:-0.6980,-0.0000,-0.0000; O:0.6980,-0.0000,-0.0000</mk:atoms>
<mk:bonds>0-1:3</mk:bonds>
</mk:conformer-3d>
<mk:dipole component="0" method="bond-sum" units="relative" magnitude="0.89" dir="-1,0,0"/>

mk:conformer-3d attributes:

AttributeValue and meaning
componentIndex that pairs this conformer with the mk:dipole elements carrying the same component. Numbers can skip
sourceCoordinate generator, openchemlib, or adopted when the author made the geometry of an electrostatic potential map the molecule’s 3D structure (exported as it is, with no idealized shape applied). Shapes for a single central atom with bonds and lone pairs (linear, trigonal planar, T-shaped, seesaw, square planar, square pyramidal, octahedral) are the ideal VSEPR shapes
added-htrue when hydrogens not drawn in 2D were added for the 3D model
unitsangstrom
framedrawing-aligned: rotated so the model matches the 2D drawing, x right and y up
scopemolecule
data-mk-view, data-mk-lewis-layoutIn a visual set, the depiction this conformer was aligned to
data-mk-conformer-primary"true" on the conformer whose drawing gives the clearest 3D view (VSEPR first, then angled Lewis, bond-line, square Lewis, condensed, Fischer). Use this one when you show a single 3D model

mk:atoms is a ; -separated list of Element:x,y,z entries. Drawn atoms come first in drawing order, then any added hydrogens. mk:bonds is a ; -separated list of i-j:order entries using zero-based indexes into mk:atoms, with optional trailing flags: :c marks a coordinate bond (draw it dashed) and :d marks a bond whose order varies across resonance forms (draw it as a partial bond). Parse the order with parseInt and read flags from the remainder.

A resonance form has no separate 3D shape, so a resonance set carries one conformer for the species rather than one per form. In a visual set, conformers aligned to resonance forms are dropped when a non-resonant depiction has one; otherwise the first form of each view keeps its conformer.

mk:dipole attributes:

AttributeValue and meaning
componentMatches a mk:conformer-3d
methodbond-sum (vector sum of bond dipoles from electronegativity differences) or gasteiger (from Gasteiger partial charges)
unitsrelative for bond-sum (electronegativity units, not debye); debye for gasteiger
magnitudeThree decimals. 0 when below 0.05
dirUnit vector x,y,z in the drawing frame (x right, y down, z out of the page) pointing toward the negative end. 0,0,0 when the magnitude is 0

If no bond is polar, no bond-sum element is written for that component, which means a prediction of exactly zero. For carbon monoxide and nitric oxide the direction follows the measured moment (negative end on C and on N), not the electronegativity rule; the matching mk:dipole-measured says so.

Measured dipole

mk:dipole-measured holds the measured gas-phase dipole moment for species in Molkit’s reference table (79 entries, keyed by InChIKey). It appears at most once per file. Its absence means no reference value is on file, not that the moment is zero.

AttributeWhen presentValue and meaning
mualwaysMoment in debye
unitsalwaysdebye
kindalwaysexperimental, or symmetry for an exact zero by symmetry with no primary measurement (SF6, Br2, I2, anti-butane). Do not present symmetry values as measurements
yearknownMeasurement year. For entries from the 1967 NSRDS-NBS10 compilation this is an upper bound
speciesalwaysSpecies name
keyalwaysInChIKey of the reference entry
matched-byalwaysinchi-key (canonical) or name (name match checked against the drawn formula)
source, doiknownCitation and DOI
notethe entry has oneFree text caveat
negative-endthe measured direction contradicts the electronegativity ruleElement symbol at the negative end: C for carbon monoxide, N for nitric oxide
departurewith negative-endSentence explaining the departure from the rule of thumb

Only mu === 0 means zero by symmetry. Small nonzero values (propane, 0.084 D) are real.

Electrostatic potential maps

A molecule with an electrostatic potential map gets one mk:esp element next to its mk:conformer-3d, with the same component. The author chooses in the Export SVG dialog whether the map data goes inside the SVG or into a separate .esp file; the description is in the SVG either way. An out-of-date map is never exported.

mk:esp attributes (absent when unknown):

AttributeValue and meaning
componentMatches a mk:conformer-3d
format1
program, program-versionThe program that computed the potential, e.g. OCC
method, basisLevel of theory split at the first /: B3LYP and def2-SVP. GFN2-xTB has no basis
charge, unpairedNet charge and number of unpaired electrons of the calculation
phasegas
geometrybuilt (Molkit’s idealized geometry), relaxed, or imported (from cube files)
geometry-method, geometry-mediumFor relaxed: the relax method and program, and gas or water
dateDate of the calculation, YYYY-MM-DD
surfaceelectron density 0.002 e/bohr^3
density-sourcecalculated or free-atom densities
unitsatomic units (hartree per elementary charge)
grid-stepGrid spacing in angstrom
fingerprint8 hex digits identifying the geometry the map belongs to
surface-min, surface-maxLowest and highest potential on the surface, atomic units

Children:

ElementContent
mk:esp-captionOne sentence describing the map, for a caption or a screen reader
mk:esp-noteNotes from the calculation, when there were any
mk:esp-citationOne per reference for the program and method
mk:esp-chargesPer-atom charges in mk:conformer-3d atom order, space-separated, with a kind attribute (CHELPG from OCC). The widget does not show them
mk:esp-displayThe author’s display settings as attributes (scheme, range-mode, fixed, opacity, iso, view, plane, plane-offset, contours), and view-q, the camera rotation as a quaternion x y z w when the map was on in the 3D viewer at export. Starting values only; treat them as untrusted and clamp them
mk:esp-dataThe map file as base64, with encoding="base64", bytes and checksum
mk:esp-fileInstead of mk:esp-data: href (a relative path, by default esp/<name>-<fingerprint>.esp), bytes and checksum

The .esp file (embedded or separate) starts with the line MKESP 1, then one line of JSON (the record above, the atoms and the grid shapes), a newline, and the grid data as 16-bit values. checksum is an FNV-1a hash of the whole file in 8 hex digits; a reader must show no map when it does not match. Files are named by content, so a changed geometry gets a new name.

Resonance and visual-set blocks

mk:resonance has attributes set, optional equivalent="true", and optional arrow-ids (comma-separated). It contains one mk:form per form, with index, weight (equivalent, major, or minor), optional dominant="true" (a display flag; it does not change the average), and optional caption.

mk:visual-set has attributes id, default (the default view), views (comma-separated), optional planar="true", and optional primary (view:index or view:parent). It contains one mk:depiction per drawing, with view, optional views (when one drawing serves several views), lewis-layout, octet, index, is-parent, parent-kind, weight, dominant, caption, and provenance attributes generated-by, edited, source-view, source-index, source-layout.

A depiction in the orbitals view is an orbital picture. A group can hold several, and each always has a caption: the author’s own, or All orbitals or Pi system written from the picture’s settings. It also has a box attribute, "x y w h" in root viewBox space, because the lobes reach past the atoms and data-mk-view-boxes holds only the union of all pictures.

Both blocks can contain mk:bond-order summaries, one per bond type, when the forms share one skeleton: elements (space-separated pair, e.g. N O), order (average), optional range (min-max), basis (non-minor or all), and in a visual set group (the view key the average belongs to).

Extracting the MOL block

The mk:mol-block element holds a complete V2000 molfile as text, ready for RDKit.js, OpenBabel, or any MOL-aware tool. Y coordinates are flipped relative to the SVG (chemistry convention is Y-up, SVG is Y-down). Match metadata children by localName, which ignores the namespace prefix and works in every browser:

get-mol-block.js
function getMolBlock(svg) {
const meta = svg.querySelector('metadata');
if (!meta) return null;
const chem = [...meta.children].find(el => el.localName === 'chemistry');
const mol = chem && [...chem.children].find(el => el.localName === 'mol-block');
return mol ? mol.textContent : null;
}

Reading the molecule graph

The atom and bond attributes together form a complete graph. This parser builds an adjacency structure for highlighting, tooltips, or analysis. It works against an inlined export (see embedding):

parse-graph.js
function parseGraph(svg) {
const atoms = new Map();
const int = (g, name) => {
const v = g.getAttribute(name);
return v == null ? null : parseInt(v, 10);
};
for (const g of svg.querySelectorAll('[data-mk-element]')) {
const id = g.getAttribute('data-id');
const generic = g.getAttribute('data-mk-generic') === 'true';
atoms.set(id, {
id,
generic,
element: g.getAttribute('data-mk-element'), // "*" for a generic
label: g.getAttribute('data-mk-abbreviation'), // "R", "OEt", or null
charge: int(g, 'data-mk-formal-charge'), // null on generics
lonePairs: int(g, 'data-mk-lone-pairs'),
implicitH: int(g, 'data-mk-implicit-h'),
hybridization: g.getAttribute('data-mk-hybridization'),
ringSizes: JSON.parse(g.getAttribute('data-mk-ring-sizes') ?? '[]'),
neighbors: [],
node: g, // keep the live element for styling
});
}
const bonds = [];
for (const g of svg.querySelectorAll('[data-mk-order]')) {
const bond = {
order: parseFloat(g.getAttribute('data-mk-order')),
atom1: g.getAttribute('data-mk-atom1'),
atom2: g.getAttribute('data-mk-atom2'),
stereo: g.getAttribute('data-mk-stereo'), // null for plain bonds
node: g,
};
bonds.push(bond);
atoms.get(bond.atom1)?.neighbors.push(bond.atom2);
atoms.get(bond.atom2)?.neighbors.push(bond.atom1);
}
return { atoms, bonds };
}

In a resonance set or visual set the same species appears once per drawing, so the graph has several disconnected copies. Filter by data-mk-resonance-index or data-mk-view to work with one.

Gotchas

  • Conditional attributes need null-guards. Decide on a default before parsing. data-mk-octet in particular is absent where the octet is undefined; do not read absence as satisfied.
  • Never use logical-or fallbacks on numeric reads. Zero is a valid value for data-mk-formal-charge, data-mk-lone-pairs, data-mk-implicit-h, and data-mk-oxidation-state. Use ?? after parsing, not ||.
  • Generic atoms carry almost nothing. Check data-mk-generic before reading coordinates, charge, or index; they are absent on generics.
  • JSON attributes need JSON.parse. data-mk-vsepr-angles, data-mk-ring-sizes, data-mk-warnings, data-mk-implicit-h-meta, and data-mk-view-boxes.
  • Hybridization does not always follow the domain count. Check data-mk-lp-delocalized before explaining sp2 from four domains.
  • Identity fields can be missing on a valid export. Multi-species drawings, unbalanced ion mixtures, and anything with a generic atom have no formula, SMILES, or MOL block. Per-atom and per-bond attributes are still present.
  • Atom IDs are opaque strings. Do not parse them. Match bonds to atoms by comparing data-mk-atom1 and data-mk-atom2 against each atom group’s data-id.
  • The bond-sum dipole is not in debye. Use mk:dipole-measured for a number in debye; the gasteiger record is in debye but is a model value.
  • PubChem fields are best-effort. data-mk-inchi, data-mk-inchi-key, data-mk-cid, and the IUPAC name exist only when the lookup succeeded online.
  • The omit-implicit-H export option only blanks one attribute. With it checked, every data-mk-implicit-h reads 0 and data-mk-implicit-h-meta is dropped. Formula, molecular weight, atom count, and total valence electrons always include implicit hydrogens.
  • Re-export files made with older builds. Earlier exporters wrote data-mk-octet="expanded" on generics and bridging hydrogens, stamped charge warnings on correctly bracketed ions, wrote dipole directions that depended on how a free O-H was drawn, and had implicit-hydrogen accounting bugs. Treat old files as suspect and re-export.

See also