Cheminformatics toolkit built with TypeScript. Can be used to carry out some fairly sophisticated cheminformatics tasks on a contemporary web browser, such as rendering molecules for display, format conversions, calculations, interactive sketching, among other things. The library can be used within any JavaScript engine, including web browsers, NodeJS and Electron.
Copyright © 2010-2024 Molecular Materials Informatics, Inc.
All rights reserved.
The WebMolKit library is made available under the terms of the Apache License 2.0, which is a non-viral license. Until July 2022 it was generally available under the GPL 3 (the viral license), but this constraint has been lifted.
The framework is written in TypeScript. It requires the TypeScript compiler to cross-compile into JavaScript. All development has been done using Visual Studio Code.
Converting each of the source files (.ts
) into a JavaScript file (.js
and .d.ts
) is done by running the TypeScript compiler:
$ tsc
$ ls -lR dist/src
Converting these TypeScript outputs into something that can be executed on one of the many different JavaScript runtime engines involves webpack:
$ npm run build
$ ls -l dist
This process creates webmolkit.js
, which can be included into any web page, allowing functionality to be invoked. Incorporating WebMolKit into a more complex library is most easily done using the NodeJS Package Manager (npm), within a project that necessarily uses webpack to assemble all of its own libraries into a final build.
WebMolKit itself uses no dependencies, and runs on baseline JavaScript engines. The only exception is the need for a DOM in order to read/write XML files: for the DOM-less environments (node, web-worker) this must be stubbed in with a custom implementation.
The val
subdirectory includes a limited set of regression tests and interactive checks. These can be executed by running a dumb web server (e.g. http-server) and pointing your browser to each of the HTML files.
The easiest way to use WebMolKit
is to obtain the compiled bundle from GitHub: copy the file dist/webmolkit.js
to the appropriate location. A bare-bones web page that invokes the sketcher might look like:
<!DOCTYPE html>
<html>
<head>
<script src="webmolkit.js" type="text/javascript" charset="UTF-8"></script>
</head>
<body>
<p id="sketcher"></p>
<script>
let sketcher = new WebMolKit.Sketcher();
sketcher.setSize(800, 700);
let proxy = new WebMolKit.ClipboardProxyWeb();
let handler = new WebMolKit.ClipboardProxyHandler();
handler.copyEvent = (andCut, proxy) =>
{
sketcher.performCopySelection(andCut);
return true;
};
handler.pasteEvent = (proxy) =>
{
sketcher.pasteText(proxy.getString());
return true;
};
proxy.pushHandler(handler);
sketcher.defineClipboard(proxy);
sketcher.defineContext(new WebMolKit.MenuProxyWeb());
sketcher.setup(() => sketcher.render(document.getElementById('sketcher')));
</script>
</body>
</html>
Using WebMolKit as an incorporated library involves a few more steps. The following sequence can be used to bootstrap a new Electron project (whereby Electron is the desktop framework for JavaScript apps).
$ mkdir electron-wmk && cd-electron-wmk
$ npm init
In response to the NPM initialisation questions, enter main.js
for the entry point, and for everything else, the default choice is fine.
Add the development libraries and WebMolKit:
$ npm i --save-dev webpack electron raw-loader
$ npm i webmolkit
The bare minimum main.js
file creates the sketcher window:
const {app, BrowserWindow} = require('electron');
function createWindow()
{
const win = new BrowserWindow(
{
width: 900,
height: 780,
webPreferences: {nodeIntegration: true},
});
win.loadFile('index.html');
}
app.whenReady().then(() => createWindow());
The rendering task is implemented in index.js
:
import {Sketcher} from 'webmolkit/sketcher/Sketcher';
import {ClipboardProxyWeb, ClipboardProxyHandler} from 'webmolkit/ui/ClipboardProxy';
import {MenuProxyWeb} from 'webmolkit/ui/MenuProxy';
let sketcher = new Sketcher();
sketcher.setSize(800, 700);
let proxy = new ClipboardProxyWeb();
let handler = new ClipboardProxyHandler();
handler.copyEvent = (andCut, proxy) =>
{
sketcher.performCopySelection(andCut);
return true;
};
handler.pasteEvent = (proxy) =>
{
sketcher.pasteText(proxy.getString());
return true;
};
proxy.pushHandler(handler);
sketcher.defineClipboard(proxy);
sketcher.defineContext(new MenuProxyWeb());
sketcher.setup(() => sketcher.render(document.getElementById('sketcher')));
Note that the code uses ES6-style imports, with reference to the WebMolKit library imported via NPM. This does not actually execute in the Electron runtime, and so for this we need to bring in webpack
to tie everything together. Create the file webpack.config.js
:
const path = require('path');
module.exports =
{
entry: './index.js',
target: 'electron-main',
mode: 'development',
module:
{
rules:
[
{test: /\.svg$/, loader: 'raw-loader'},
{test: /\.ds$/, loader: 'raw-loader'},
{test: /\.onto$/, loader: 'raw-loader'},
],
},
performance:
{
hints: false,
maxEntrypointSize: 512000,
maxAssetSize: 512000
},
output:
{
path: path.resolve(__dirname, '.'),
filename: 'index-pack.js',
library: 'Main',
},
devtool: 'source-map',
};
This is a very vanilla configuration, which calls out to electron-main
as the target type, and transpiles index.js
to index-pack.js
, which incorporates all the necessary libraries and uses the module loading system desired by the target. Note specifically in the rules section above, that it invokes raw-loader
for files with several different extensions. This is necessary for asset bundling, which is used within the sketcher.
The package.json
file will mostly be filled in, but adding a couple of parts to the scripts section is useful for compiling and running:
{
"name": "electron-wmk",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"build": "webpack --config webpack.config.js",
"start": "electron ."
},
"author": "",
"license": "ISC",
"devDependencies": {
"electron": "^33.2.1",
"raw-loader": "^4.0.2",
"webpack": "^5.97.1",
"webpack-cli": "^6.0.1"
},
"dependencies": {
"webmolkit": "^2.0.0"
}
}
Rendering is done by index.html
:
<html>
<head>
<title>Electron/WebMolKit</title>
</head>
<body>
<div id="sketcher"></div>
<script src="index-pack.js" charset="UTF-8"></script>
</body>
</html>
And finally you can run the project with npm run start
which will fire up the Electron runtime and present a desktop window with a sketcher.
Documentation is mostly in the form of source comments and some example code. As of December 2024 the codebase had been very recently converted to using the new ES6 import syntax, as opposed to the legacy TypeScript namespace feature, so incorporating it into larger projects is more streamlined.
If you have any questions, comments or inquiries, feel free to write to [email protected]. Serious people welcome; trolls, spammers and haters not so much.