Long time ago, I wrote post about the same topic. The code used old version of rdkitjs and electron. Recently rdkitjs is maintained in official repository so I would like to re-test the approach. My old post is here.
To do the following approach, I installed node.js, electron and npm at first.
$ sudo apt install -y npm nodejs
$ mkdir electron_test
$ cd electron_test
$ npm -g install electron
Then init the directory and install required package.
$ npm init -y
$ npm i @rdkit/rdkit --save-dev
$ npm i electron-packager -g
After typing ‘npm init -y’, packages.json is generated and packages will be added when I installed package with npm i command. Here is a final version of the post.
// packages.json
{
"name": "electron_test",
"version": "1.0.0",
"description": "sample app",
"main": "main.js",
"scripts": {
"start": "electron-forge start",
"package": "electron-forge package",
"make": "electron-forge make"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@rdkit/rdkit": "^2021.9.3",
"electron-squirrel-startup": "^1.0.0",
"highcharts": "^9.3.2"
},
"devDependencies": {
"@electron-forge/cli": "^6.0.0-beta.61",
"@electron-forge/maker-deb": "^6.0.0-beta.61",
"@electron-forge/maker-rpm": "^6.0.0-beta.61",
"@electron-forge/maker-squirrel": "^6.0.0-beta.61",
"@electron-forge/maker-zip": "^6.0.0-beta.61",
"electron": "^16.0.5"
},
"config": {
"forge": {
"packagerConfig": {},
"makers": [
{
"name": "@electron-forge/maker-squirrel",
"config": {
"name": "electron_test"
}
},
{
"name": "@electron-forge/maker-zip",
"platforms": [
"darwin"
]
},
{
"name": "@electron-forge/maker-deb",
"config": {}
},
{
"name": "@electron-forge/maker-rpm",
"config": {}
}
]
}
}
}
Recent version of electron is required not only main.js but also preload.js which are shown below.
//main.js
const { app, BrowserWindow } = require('electron');
const path = require('path');
const createWindow = () => {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
}
})
mainWindow.loadFile('index.html')
//mainWindow.webContents.openDevTools()
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
// preload.js
const { contextBridge, ipcRenderer} = require("electron")
const fs = require('fs')
/**
contextBridge.exposeInMainWorld(
"reuires", {
Highcharts: require('highcharts'),
ipcRenderer : ipcRenderer,
getSetting : () => {
return fs.existsSync(setting_path) ? fs.readFileSync(setting_path, 'utf8') : '{}'
}
}
);
**/
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})
Next, let’s write index.html. RDKitjs is loaded in this file. It’s easy to make mol object from smiles, just calling get_mol. And also easy to convert mol to svg by calling get_svg ;).
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Electron chemoinfo</title>
<script src="./node_modules/@rdkit/rdkit/Code/MinimalLib/dist/RDKit_minimal.js"></script>
<script>
window.initRDKitModule()
.then(function(RDKit) {
console.log("RDKit version: " + RDKit.version());
window.RDKit = RDKit;
/**
* The RDKit module is now loaded.
* You can use it anywhere.
*/
})
.catch(() => {
// handle loading errors here...
});
</script>
<script> var drawmol = function() {
var smi = document.getElementById('smi').value;
console.log( smi );
var mol = RDKit.get_mol( smi );
var svg = mol.get_svg();
document.getElementById("drawer").innerHTML = svg;
};
</script>
</head>
<body>
<h1>Hello, electron!</h1>
<body>
<h1>Smiles parser</h1>
<p>This is simple smiles converter using RDKit js.</p>
<p>Input smiles to text box and push the button.</p>
<input id='smi' type='text' ><br>
<button type='button' onclick='drawmol()' >draw</button><br>
<div id='drawer'></div>
</body>
</body>
</html>
Now almost there, when type the command ‘$ npm start’, electron app will launch. And the app coverts SMILES to SVG image like below. Following SMIKES is CC1([C@@H]2[C@H]1[C@H](N(C2)C(=O)[C@H](C(C)(C)C)NC(=O)C(F)(F)F)C(=O)N[C@@H](C[C@@H]3CCNC3=O)C#N)C, Nirmatrelvir which is developed by Pfizer!

It works well but not desktop application. To make cross platform app, just call npx electron-packager.
$ npx electron-packager . electron-test --platform=all
After waiting few minutes, I could get all platform apps named, electron_test-darwin-x64, electron_test-linux-x64, electron_test-mas-x64 and electron_test-win32-x64.
After making these app, developer can provide these app to users and they can use it even if user don’t have rdkit environment.
In summary, it quite interesting for me to use electron to making chemoinformatics desktop applications. Today’s code is uploaded on my github repo.
I make a more general prof of concept that can be very useful to clean CAS / SMILES / NAMES errors in datasets …
https://github.com/thegodone/molparserjs