Importers and exporters
Add a file format to Athanor's Export window with a plugin exporter, return text or binary files, and use 3D coordinates. Importers are reserved.
What an exporter is
An exporter adds a file format to Athanor's Export window. When the person picks it, Athanor asks your plugin for the file, and Athanor saves it. Your plugin never writes files itself and never chooses where they go.
Exporters appear in the Export window (Main menu › File › Export…, or Ctrl+Shift+E) under From plugins, each as "format label · plugin name". The format's notes show as its tooltip.
A minimal exporter
This is the Exporter template from New plugin: Exporter template…. It writes every structure's SMILES and name, one per line.
manifest.json:
{
"id": "local.smiles-list",
"name": "SMILES list",
"version": "0.1.0",
"api": "1.0.0",
"author": "You",
"description": "SMILES list, made from the exporter template.",
"main": "main.js",
"permissions": ["document.read"],
"contributes": {
"formats": [
{ "key": "smiles-list", "label": "SMILES list", "extensions": ["txt"], "mime": "text/plain", "export": true }
]
}
}main.js:
// @ts-check
/// <reference path="./athanor.d.ts" />
// An exporter: appears in Export under "From plugins". Return the file; Athanor saves it.
athanor.formats.onExport('smiles-list', async () => {
const page = await athanor.snapshot();
const lines = page.structures.map((s) => `${s.smiles}\t${s.name || s.formula}`);
return { filename: 'structures.txt', text: lines.join('\n') + '\n' };
});The first argument to onExport is the format's key from the manifest.
What the handler returns
| Field | Meaning |
|---|---|
filename |
The suggested file name. Cut at 120 characters; backslash, slash, colon, asterisk, question mark, double quote, angle brackets and the vertical bar become _. When missing, Athanor uses export.<first extension> |
text |
The file's contents as text, up to 50,000,000 characters |
base64 |
The file's contents as base64, for binary formats. Use text or base64, not both |
A handler that returns neither shows "Plugin returned no file." in the Export window.
Using 3D coordinates
athanor.conformer(structureId) gives a structure's 3D coordinates from Athanor's own engine, hydrogens included: { atoms: [{ element, x, y, z }] } in angstroms. It needs Read the open document.
This example plugin writes an XYZ file with every structure on the page, ten angstroms apart so none overlap:
async function all() {
const page = await athanor.snapshot();
const out = [];
for (const [k, s] of page.structures.entries()) {
const c = await athanor.conformer(s.id);
if (!c) continue;
// Each structure 10 angstroms along x from the last, so none overlap.
out.push({ name: s.name || s.formula, atoms: c.atoms.map((a) => ({ ...a, x: a.x + k * 10 })) });
}
return { title: page.title || 'Athanor export', mols: out };
}
const f = (v, w, d) => v.toFixed(d).padStart(w);
athanor.formats.onExport('xyz3d', async () => {
const { title, mols } = await all();
const atoms = mols.flatMap((m) => m.atoms);
const lines = [String(atoms.length), title.replace(/\s+/g, ' ').slice(0, 80)];
for (const a of atoms) lines.push(a.element.padEnd(3) + f(a.x, 12, 6) + f(a.y, 12, 6) + f(a.z, 12, 6));
return { filename: 'structures.xyz', text: lines.join('\n') + '\n' };
});Its manifest declares the format like this:
{ "key": "xyz3d", "label": "XYZ (3D)", "extensions": ["xyz"], "mime": "chemical/x-xyz", "export": true,
"notes": "3D coordinates in angstroms, hydrogens written out; structures 10 Å apart." }Rules and limits
- An exporter reads the document, so the manifest must hold
document.read. Without it the manifest is refused: "Exporters and checks read the document: add the "document.read" permission." - Up to 50 formats per plugin.
keyfollows the command key rule;labelis required, at most 40 characters. extensions: one to five, letters and digits only, up to 10 characters each, written without the dot (a leading dot is removed).mimedefaults toapplication/octet-stream.notesis optional, at most 200 characters.- A format must say
"export": true,"import": true, or both. - The handler gets the same time limit as any other code: 5 seconds of synchronous work (15 for official plugins).
Importers
The manifest accepts "import": true on a format, and the API has athanor.formats.onImport(key, fn) to register a handler. API 1 does not call import handlers yet: no file the person opens is passed to a plugin. Declare export only until a later API version says otherwise in the Changelog.
Is this helpful?
Last updated Nov 11, 2026
- Still stuck? Read the FAQ or contact support.
- Something wrong on this page? Tell us.
- For AI tools: llms.txt
