Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

mf-parser

Package Overview
Dependencies
Maintainers
6
Versions
73
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mf-parser - npm Package Compare versions

Comparing version 0.8.0 to 0.9.1

13

package.json
{
"name": "mf-parser",
"version": "0.8.0",
"version": "0.9.1",
"description": "",

@@ -21,7 +21,10 @@ "main": "src/index.js",

"dependencies": {
"atom-sorter": "^0.8.0",
"chemical-elements": "^0.7.0",
"chemical-groups": "^0.8.0",
"mf-utilities": "^0.8.0"
"atom-sorter": "^0.9.1",
"chemical-elements": "^0.9.1",
"chemical-groups": "^0.9.1",
"mf-utilities": "^0.9.1"
},
"devDependencies": {
"jest-matcher-deep-close-to": "^1.3.0"
}
}
'use strict';
const toMatchCloseTo = require('jest-matcher-deep-close-to').toMatchCloseTo;
expect.extend({ toMatchCloseTo });

@@ -18,5 +19,5 @@

let result4 = new MF('C2 . 2C').getEA();
expect(result1).toEqual(result2);
expect(result1).toEqual(result3);
expect(result1).toEqual(result4);
expect(result1).toStrictEqual(result2);
expect(result1).toStrictEqual(result3);
expect(result1).toStrictEqual(result4);

@@ -23,0 +24,0 @@ expect(new MF('[13C]').getEA()).toMatchCloseTo(

@@ -6,23 +6,23 @@ 'use strict';

test('getIsotopesInfo from C{50,50}[13C]H2', () => {
var mf = new MF('[13C]3CC{50,50}((2+))2');
var info = mf.getIsotopesInfo();
var mf = new MF('[13C]3CC{50,50}((2+))2');
var info = mf.getIsotopesInfo();
expect(info.charge).toBe(4);
expect(info.isotopes[0].distribution).toEqual([{ x: 12, y: 0.9893 }, { x: 13.00335483507, y: 0.0107 }]);
expect(info.isotopes[1].distribution).toEqual([{ x: 13.00335483507, y: 1 }]);
expect(info.isotopes[2].distribution).toEqual([{ x: 12, y: 0.5 }, { x: 13.00335483507, y: 0.5 }]);
expect(info.charge).toBe(4);
expect(info.isotopes[0].distribution).toStrictEqual([{ x: 12, y: 0.9893 }, { x: 13.00335483507, y: 0.0107 }]);
expect(info.isotopes[1].distribution).toStrictEqual([{ x: 13.00335483507, y: 1 }]);
expect(info.isotopes[2].distribution).toStrictEqual([{ x: 12, y: 0.5 }, { x: 13.00335483507, y: 0.5 }]);
});
test('getIsotopesInfo from C.H', () => {
expect(() => {
var mf = new MF('C.H');
mf.getIsotopesInfo();
}).toThrow('getIsotopesInfo can not be applied on multipart MF');
expect(() => {
var mf = new MF('C.H');
mf.getIsotopesInfo();
}).toThrow('getIsotopesInfo can not be applied on multipart MF');
});
test('getIsotopesInfo from (CH3(+))2', () => {
var mf = new MF('(CH3(+))2');
var info = mf.getIsotopesInfo();
expect(info.charge).toBe(2);
var mf = new MF('(CH3(+))2');
var info = mf.getIsotopesInfo();
expect(info.charge).toBe(2);
});

@@ -6,4 +6,4 @@ 'use strict';

test('parseToHtml', () => {
var result = MFParser.parseToHtml('SO4(--)');
expect(result).toBe('SO<span style="flex-direction: column;display: inline-flex;justify-content: center;text-align: left;vertical-align: middle;"><sup style="line-height: 1; font-size: 70%">-2</sup><sub style="line-height: 1; font-size: 70%">4</sub></span>');
var result = MFParser.parseToHtml('SO4(--)');
expect(result).toBe('SO<span style="flex-direction: column;display: inline-flex;justify-content: center;text-align: left;vertical-align: middle;"><sup style="line-height: 1; font-size: 70%">-2</sup><sub style="line-height: 1; font-size: 70%">4</sub></span>');
});

@@ -9,3 +9,3 @@ 'use strict';

expect(parts).toEqual([[{kind: 'atom', value: 'C', multiplier: 1}]]);
expect(parts).toStrictEqual([[{ kind: 'atom', value: 'C', multiplier: 1 }]]);

@@ -22,3 +22,3 @@ var newMF = mf.toMF();

expect(info).toEqual({
expect(info).toStrictEqual({
monoisotopicMass: 12,

@@ -29,3 +29,3 @@ mass: 12.010735896735248,

mf: 'C',
atoms: {C: 1}
atoms: { C: 1 }
});

@@ -39,5 +39,5 @@ });

var info2H = mf2H.getInfo();
expect(infoD).toEqual(info2H);
expect(infoD).toEqual({
atoms: {H: 1},
expect(infoD).toStrictEqual(info2H);
expect(infoD).toStrictEqual({
atoms: { H: 1 },
charge: 0,

@@ -55,11 +55,11 @@ mass: 2.01410177812,

expect(parts).toEqual([
expect(parts).toStrictEqual([
[
{kind: 'atom', value: 'C', multiplier: 6},
{kind: 'atom', value: 'H', multiplier: 15},
{kind: 'atom', value: 'N', multiplier: 1}
{ kind: 'atom', value: 'C', multiplier: 6 },
{ kind: 'atom', value: 'H', multiplier: 15 },
{ kind: 'atom', value: 'N', multiplier: 1 }
],
[
{kind: 'atom', value: 'H', multiplier: 1},
{kind: 'atom', value: 'Cl', multiplier: 1}
{ kind: 'atom', value: 'H', multiplier: 1 },
{ kind: 'atom', value: 'Cl', multiplier: 1 }
]

@@ -77,3 +77,3 @@ ]);

let info = mf.getInfo();
expect(info).toEqual({
expect(info).toStrictEqual({
parts: [

@@ -86,3 +86,3 @@ {

unsaturation: 0,
atoms: {C: 6, H: 15, N: 1}
atoms: { C: 6, H: 15, N: 1 }
},

@@ -95,3 +95,3 @@ {

unsaturation: 0,
atoms: {H: 1, Cl: 1}
atoms: { H: 1, Cl: 1 }
}

@@ -108,10 +108,12 @@ ],

var mf = new MF('(Me2CH)3N');
var parts = mf.toParts({expand: false});
var parts = mf.toParts({ expand: false });
expect(parts).toEqual([[
{kind: 'atom', value: 'C', multiplier: 3},
{kind: 'atom', value: 'H', multiplier: 3},
{kind: 'atom', value: 'Me', multiplier: 6},
{kind: 'atom', value: 'N', multiplier: 1}
]]);
expect(parts).toStrictEqual([
[
{ kind: 'atom', value: 'C', multiplier: 3 },
{ kind: 'atom', value: 'H', multiplier: 3 },
{ kind: 'atom', value: 'Me', multiplier: 6 },
{ kind: 'atom', value: 'N', multiplier: 1 }
]
]);

@@ -122,3 +124,3 @@ var newMF = mf.toMF();

let info = mf.getInfo();
expect(info).toEqual({
expect(info).toStrictEqual({
mass: 143.27008211723435,

@@ -129,3 +131,3 @@ monoisotopicMass: 143.16739968126,

unsaturation: 0,
atoms: {C: 3, H: 3, Me: 6, N: 1}
atoms: { C: 3, H: 3, Me: 6, N: 1 }
});

@@ -136,9 +138,11 @@ });

var mf = new MF('(Me2CH)3N');
var parts = mf.toParts({expand: true});
var parts = mf.toParts({ expand: true });
expect(parts).toEqual([[
{kind: 'atom', value: 'C', multiplier: 9},
{kind: 'atom', value: 'H', multiplier: 21},
{kind: 'atom', value: 'N', multiplier: 1}
]]);
expect(parts).toStrictEqual([
[
{ kind: 'atom', value: 'C', multiplier: 9 },
{ kind: 'atom', value: 'H', multiplier: 21 },
{ kind: 'atom', value: 'N', multiplier: 1 }
]
]);

@@ -149,3 +153,3 @@ var newMF = mf.toMF();

let info = mf.getInfo();
expect(info).toEqual({
expect(info).toStrictEqual({
mass: 143.27008211723435,

@@ -156,3 +160,3 @@ monoisotopicMass: 143.16739968126,

unsaturation: 0,
atoms: {C: 9, H: 21, N: 1}
atoms: { C: 9, H: 21, N: 1 }
});

@@ -165,6 +169,9 @@ });

expect(parts).toEqual([[
{kind: 'atom', value: 'O', multiplier: 4},
{kind: 'atom', value: 'S', multiplier: 1}, {kind: 'charge', value: -2}
]]);
expect(parts).toStrictEqual([
[
{ kind: 'atom', value: 'O', multiplier: 4 },
{ kind: 'atom', value: 'S', multiplier: 1 },
{ kind: 'charge', value: -2 }
]
]);

@@ -174,4 +181,4 @@ var newMF = mf.toMF();

let info = mf.getInfo({customUnsaturations: {S: 4}});
expect(info).toEqual({
let info = mf.getInfo({ customUnsaturations: { S: 4 } });
expect(info).toStrictEqual({
monoisotopicMass: 95.95172965268,

@@ -183,3 +190,3 @@ mass: 96.06240710340018,

unsaturation: 4,
atoms: {O: 4, S: 1}
atoms: { O: 4, S: 1 }
});

@@ -197,2 +204,4 @@ });

expect(new MF('NH4+').getInfo().unsaturation).toBe(-1);
expect(new MF('H(+)').toHtml()).toBe('H<sup>+</sup>');
});

@@ -203,11 +212,13 @@

var parts = mf.toParts();
expect(parts).toEqual([[
{kind: 'atom', value: 'C', multiplier: 1},
{kind: 'isotope', value: {atom: 'C', isotope: 13}, multiplier: 1},
{kind: 'atom', value: 'N', multiplier: 4},
{kind: 'isotope', value: {atom: 'N', isotope: 15}, multiplier: 2}
]]);
expect(parts).toStrictEqual([
[
{ kind: 'atom', value: 'C', multiplier: 1 },
{ kind: 'isotope', value: { atom: 'C', isotope: 13 }, multiplier: 1 },
{ kind: 'atom', value: 'N', multiplier: 4 },
{ kind: 'isotope', value: { atom: 'N', isotope: 15 }, multiplier: 2 }
]
]);
let info = mf.getInfo();
expect(info).toEqual({
expect(info).toStrictEqual({
monoisotopicMass: 111.01586865055,

@@ -218,3 +229,3 @@ mass: 111.04112137534844,

unsaturation: 6,
atoms: {C: 2, N: 6}
atoms: { C: 2, N: 6 }
});

@@ -229,3 +240,3 @@

var info = mf.getInfo();
expect(info).toEqual({
expect(info).toStrictEqual({
mass: 1253.8043977028433,

@@ -235,3 +246,3 @@ monoisotopicMass: 1253.21310019311,

mf: 'C39H51N15O25P4',
atoms: {C: 39, H: 51, N: 15, O: 25, P: 4},
atoms: { C: 39, H: 51, N: 15, O: 25, P: 4 },
unsaturation: 24

@@ -244,3 +255,3 @@ });

var info = mf.getInfo();
expect(info).toEqual({
expect(info).toStrictEqual({
mass: 653.388021231099,

@@ -250,3 +261,3 @@ monoisotopicMass: 653.08838712715,

mf: 'C19H25N7O15P2',
atoms: {C: 19, H: 25, N: 7, O: 15, P: 2},
atoms: { C: 19, H: 25, N: 7, O: 15, P: 2 },
unsaturation: 12

@@ -259,7 +270,13 @@ });

var parts = mf.toParts();
expect(parts).toEqual([[
{kind: 'atom', value: 'C', multiplier: 1},
{kind: 'isotopeRatio', value: {atom: 'C', ratio: [50, 50]}, multiplier: 1},
{kind: 'atom', value: 'H', multiplier: 1}
]]);
expect(parts).toStrictEqual([
[
{ kind: 'atom', value: 'C', multiplier: 1 },
{
kind: 'isotopeRatio',
value: { atom: 'C', ratio: [50, 50] },
multiplier: 1
},
{ kind: 'atom', value: 'H', multiplier: 1 }
]
]);

@@ -270,3 +287,3 @@ var newMF = mf.toMF();

let info = mf.getInfo();
expect(info).toEqual({
expect(info).toStrictEqual({
monoisotopicMass: 25.00782503223,

@@ -277,3 +294,3 @@ mass: 25.520354068326025,

unsaturation: 2.5,
atoms: {C: 2, H: 1}
atoms: { C: 2, H: 1 }
});

@@ -289,4 +306,4 @@ });

let info = mf.getInfo();
expect(info).toEqual({
atoms: {H: 1},
expect(info).toStrictEqual({
atoms: { H: 1 },
charge: 0,

@@ -293,0 +310,0 @@ mass: 1.0079407540557772,

@@ -6,120 +6,156 @@ 'use strict';

var tests = {
C10: [{kind: 'atom', value: 'C'}, {kind: 'multiplier', value: 10}],
'C-1': [{kind: 'atom', value: 'C'}, {kind: 'multiplier', value: -1}],
C10: [{ kind: 'atom', value: 'C' }, { kind: 'multiplier', value: 10 }],
'C-1': [{ kind: 'atom', value: 'C' }, { kind: 'multiplier', value: -1 }],
'C1-10': [
{kind: 'atom', value: 'C'},
{kind: 'multiplierRange', value: {from: 1, to: 10}}
{ kind: 'atom', value: 'C' },
{ kind: 'multiplierRange', value: { from: 1, to: 10 } }
],
'2H': [{kind: 'preMultiplier', value: 2}, {kind: 'atom', value: 'H'}],
'[13C]': [{kind: 'isotope', value: {atom: 'C', isotope: 13}}],
'[2H]': [{kind: 'isotope', value: {atom: 'H', isotope: 2}}],
'C+': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: 1}],
'C-': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: -1}],
'2H': [{ kind: 'preMultiplier', value: 2 }, { kind: 'atom', value: 'H' }],
'[13C]': [{ kind: 'isotope', value: { atom: 'C', isotope: 13 } }],
'[2H]': [{ kind: 'isotope', value: { atom: 'H', isotope: 2 } }],
'C+': [{ kind: 'atom', value: 'C' }, { kind: 'charge', value: 1 }],
'C-': [{ kind: 'atom', value: 'C' }, { kind: 'charge', value: -1 }],
'C-H': [
{kind: 'atom', value: 'C'}, {kind: 'charge', value: -1},
{kind: 'atom', value: 'H'}
{ kind: 'atom', value: 'C' },
{ kind: 'charge', value: -1 },
{ kind: 'atom', value: 'H' }
],
'C++': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: 2}],
'C--': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: -2}],
'C++': [{ kind: 'atom', value: 'C' }, { kind: 'charge', value: 2 }],
'C--': [{ kind: 'atom', value: 'C' }, { kind: 'charge', value: -2 }],
'C2+': [
{kind: 'atom', value: 'C'}, {kind: 'multiplier', value: 2},
{kind: 'charge', value: 1}
{ kind: 'atom', value: 'C' },
{ kind: 'multiplier', value: 2 },
{ kind: 'charge', value: 1 }
],
'C(2+)': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: 2}],
'C(++)': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: 2}],
'C(+2)': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: 2}],
'C(2-)': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: -2}],
'C(-2)': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: -2}],
'C(--)': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: -2}],
'C(2+)': [{ kind: 'atom', value: 'C' }, { kind: 'charge', value: 2 }],
'C(++)': [{ kind: 'atom', value: 'C' }, { kind: 'charge', value: 2 }],
'C(+2)': [{ kind: 'atom', value: 'C' }, { kind: 'charge', value: 2 }],
'C(2-)': [{ kind: 'atom', value: 'C' }, { kind: 'charge', value: -2 }],
'C(-2)': [{ kind: 'atom', value: 'C' }, { kind: 'charge', value: -2 }],
'C(--)': [{ kind: 'atom', value: 'C' }, { kind: 'charge', value: -2 }],
'(H+)': [
{kind: 'openingParenthesis', value: '('}, {kind: 'atom', value: 'H'},
{kind: 'charge', value: 1}, {kind: 'closingParenthesis', value: ')'}
{ kind: 'openingParenthesis', value: '(' },
{ kind: 'atom', value: 'H' },
{ kind: 'charge', value: 1 },
{ kind: 'closingParenthesis', value: ')' }
],
C$ABC: [{kind: 'atom', value: 'C'}, {kind: 'comment', value: 'ABC'}],
C$ABC: [{ kind: 'atom', value: 'C' }, { kind: 'comment', value: 'ABC' }],
'C(-1)(-3)': [
{kind: 'atom', value: 'C'}, {kind: 'charge', value: -1},
{kind: 'charge', value: -3}
{ kind: 'atom', value: 'C' },
{ kind: 'charge', value: -1 },
{ kind: 'charge', value: -3 }
],
'C(-1)2(-3)3': [
{kind: 'atom', value: 'C'}, {kind: 'charge', value: -1},
{kind: 'multiplier', value: 2}, {kind: 'charge', value: -3},
{kind: 'multiplier', value: 3}
{ kind: 'atom', value: 'C' },
{ kind: 'charge', value: -1 },
{ kind: 'multiplier', value: 2 },
{ kind: 'charge', value: -3 },
{ kind: 'multiplier', value: 3 }
],
'C(H-2)': [
{kind: 'atom', value: 'C'}, {kind: 'openingParenthesis', value: '('},
{kind: 'atom', value: 'H'}, {kind: 'multiplier', value: -2},
{kind: 'closingParenthesis', value: ')'}
{ kind: 'atom', value: 'C' },
{ kind: 'openingParenthesis', value: '(' },
{ kind: 'atom', value: 'H' },
{ kind: 'multiplier', value: -2 },
{ kind: 'closingParenthesis', value: ')' }
],
'H.Cl': [
{kind: 'atom', value: 'H'}, {kind: 'salt', value: '.'},
{kind: 'atom', value: 'Cl'}
{ kind: 'atom', value: 'H' },
{ kind: 'salt', value: '.' },
{ kind: 'atom', value: 'Cl' }
],
'H{1,1}': [{kind: 'isotopeRatio', value: {atom: 'H', ratio: [1, 1]}}],
'H{1,1}': [{ kind: 'isotopeRatio', value: { atom: 'H', ratio: [1, 1] } }],
'C10 . H20': [
{kind: 'atom', value: 'C'}, {kind: 'multiplier', value: 10},
{kind: 'text', value: ' '}, {kind: 'salt', value: '.'},
{kind: 'text', value: ' '}, {kind: 'atom', value: 'H'},
{kind: 'multiplier', value: 20}
{ kind: 'atom', value: 'C' },
{ kind: 'multiplier', value: 10 },
{ kind: 'text', value: ' ' },
{ kind: 'salt', value: '.' },
{ kind: 'text', value: ' ' },
{ kind: 'atom', value: 'H' },
{ kind: 'multiplier', value: 20 }
],
'(CH(CH3)2)3N.2HCl': [
{kind: 'openingParenthesis', value: '('}, {kind: 'atom', value: 'C'},
{kind: 'atom', value: 'H'}, {kind: 'openingParenthesis', value: '('},
{kind: 'atom', value: 'C'}, {kind: 'atom', value: 'H'},
{kind: 'multiplier', value: 3}, {kind: 'closingParenthesis', value: ')'},
{kind: 'multiplier', value: 2}, {kind: 'closingParenthesis', value: ')'},
{kind: 'multiplier', value: 3}, {kind: 'atom', value: 'N'},
{kind: 'salt', value: '.'}, {kind: 'preMultiplier', value: 2},
{kind: 'atom', value: 'H'}, {kind: 'atom', value: 'Cl'}
{ kind: 'openingParenthesis', value: '(' },
{ kind: 'atom', value: 'C' },
{ kind: 'atom', value: 'H' },
{ kind: 'openingParenthesis', value: '(' },
{ kind: 'atom', value: 'C' },
{ kind: 'atom', value: 'H' },
{ kind: 'multiplier', value: 3 },
{ kind: 'closingParenthesis', value: ')' },
{ kind: 'multiplier', value: 2 },
{ kind: 'closingParenthesis', value: ')' },
{ kind: 'multiplier', value: 3 },
{ kind: 'atom', value: 'N' },
{ kind: 'salt', value: '.' },
{ kind: 'preMultiplier', value: 2 },
{ kind: 'atom', value: 'H' },
{ kind: 'atom', value: 'Cl' }
],
'C.C2.C3': [
{kind: 'atom', value: 'C'}, {kind: 'salt', value: '.'},
{kind: 'atom', value: 'C'}, {kind: 'multiplier', value: 2},
{kind: 'salt', value: '.'}, {kind: 'atom', value: 'C'},
{kind: 'multiplier', value: 3}
{ kind: 'atom', value: 'C' },
{ kind: 'salt', value: '.' },
{ kind: 'atom', value: 'C' },
{ kind: 'multiplier', value: 2 },
{ kind: 'salt', value: '.' },
{ kind: 'atom', value: 'C' },
{ kind: 'multiplier', value: 3 }
],
'C10.C20.C30': [
{kind: 'atom', value: 'C'}, {kind: 'multiplier', value: 10},
{kind: 'salt', value: '.'}, {kind: 'atom', value: 'C'},
{kind: 'multiplier', value: 20}, {kind: 'salt', value: '.'},
{kind: 'atom', value: 'C'}, {kind: 'multiplier', value: 30}
{ kind: 'atom', value: 'C' },
{ kind: 'multiplier', value: 10 },
{ kind: 'salt', value: '.' },
{ kind: 'atom', value: 'C' },
{ kind: 'multiplier', value: 20 },
{ kind: 'salt', value: '.' },
{ kind: 'atom', value: 'C' },
{ kind: 'multiplier', value: 30 }
],
'C.0.5H2O.0.6HCl': [
{kind: 'atom', value: 'C'}, {kind: 'salt', value: '.'},
{kind: 'preMultiplier', value: 0.5}, {kind: 'atom', value: 'H'},
{kind: 'multiplier', value: 2}, {kind: 'atom', value: 'O'},
{kind: 'salt', value: '.'}, {kind: 'preMultiplier', value: 0.6},
{kind: 'atom', value: 'H'}, {kind: 'atom', value: 'Cl'}
{ kind: 'atom', value: 'C' },
{ kind: 'salt', value: '.' },
{ kind: 'preMultiplier', value: 0.5 },
{ kind: 'atom', value: 'H' },
{ kind: 'multiplier', value: 2 },
{ kind: 'atom', value: 'O' },
{ kind: 'salt', value: '.' },
{ kind: 'preMultiplier', value: 0.6 },
{ kind: 'atom', value: 'H' },
{ kind: 'atom', value: 'Cl' }
],
'NH3 . 2HCl': [
{kind: 'atom', value: 'N'}, {kind: 'atom', value: 'H'},
{kind: 'multiplier', value: 3}, {kind: 'text', value: ' '},
{kind: 'salt', value: '.'}, {kind: 'text', value: ' '},
{kind: 'preMultiplier', value: 2}, {kind: 'atom', value: 'H'},
{kind: 'atom', value: 'Cl'}
{ kind: 'atom', value: 'N' },
{ kind: 'atom', value: 'H' },
{ kind: 'multiplier', value: 3 },
{ kind: 'text', value: ' ' },
{ kind: 'salt', value: '.' },
{ kind: 'text', value: ' ' },
{ kind: 'preMultiplier', value: 2 },
{ kind: 'atom', value: 'H' },
{ kind: 'atom', value: 'Cl' }
],
'2NH3 . 2HCl': [
{kind: 'preMultiplier', value: 2}, {kind: 'atom', value: 'N'},
{kind: 'atom', value: 'H'}, {kind: 'multiplier', value: 3},
{kind: 'text', value: ' '}, {kind: 'salt', value: '.'},
{kind: 'text', value: ' '}, {kind: 'preMultiplier', value: 2},
{kind: 'atom', value: 'H'}, {kind: 'atom', value: 'Cl'}
{ kind: 'preMultiplier', value: 2 },
{ kind: 'atom', value: 'N' },
{ kind: 'atom', value: 'H' },
{ kind: 'multiplier', value: 3 },
{ kind: 'text', value: ' ' },
{ kind: 'salt', value: '.' },
{ kind: 'text', value: ' ' },
{ kind: 'preMultiplier', value: 2 },
{ kind: 'atom', value: 'H' },
{ kind: 'atom', value: 'Cl' }
],
D: [{'kind': 'atom', 'value': 'D'}]
D: [{ kind: 'atom', value: 'D' }]
};
test('parse molecular formula', function() {
for (var key of Object.keys(tests)) {
checkMF(key, tests[key]);
}
test.each(Object.keys(tests))('parse molecular formula %s', function (key) {
let parsed = parse(key);
expect(parsed).toMatchObject(tests[key]);
});
test('not same opening and closing parenthesis', function() {
test('not same opening and closing parenthesis', function () {
expect(() => {
parse('C(');
}).toThrowError(/.*opening and closing.*/);
}).toThrow(/.*opening and closing.*/);
});
function checkMF(mf, result) {
let parsed = parse(mf);
expect(parsed).toMatchObject(result);
}

@@ -8,6 +8,6 @@ 'use strict';

module.exports = {
SUBSCRIPT: 'subscript',
SUPERSCRIPT: 'superscript',
SUPERIMPOSE: 'superimpose',
TEXT: 'text'
SUBSCRIPT: 'subscript',
SUPERSCRIPT: 'superscript',
SUPERIMPOSE: 'superimpose',
TEXT: 'text'
};

@@ -12,16 +12,16 @@ 'use strict';

function parseToHtml(mf) {
var parsed = parse(mf);
var display = toDisplay(parsed);
return toHtml(display);
var parsed = parse(mf);
var display = toDisplay(parsed);
return toHtml(display);
}
module.exports = {
Kind: require('./Kind'),
Format: require('./Format'),
Style: require('./Style'),
parse: require('./parse'),
toDisplay,
toHtml,
parseToHtml,
MF: require('./MF'),
Kind: require('./Kind'),
Format: require('./Format'),
Style: require('./Style'),
parse: require('./parse'),
toDisplay,
toHtml,
parseToHtml,
MF: require('./MF'),
};

@@ -7,15 +7,15 @@ 'use strict';

module.exports = {
BEGIN: 'begin',
ATOM: 'atom',
MULTIPLIER_RANGE: 'multiplierRange',
ISOTOPE: 'isotope',
ISOTOPE_RATIO: 'isotopeRatio',
CHARGE: 'charge',
SALT: 'salt',
OPENING_PARENTHESIS: 'openingParenthesis',
CLOSING_PARENTHESIS: 'closingParenthesis',
PRE_MULTIPLIER: 'preMultiplier',
MULTIPLIER: 'multiplier',
TEXT: 'text',
COMMENT: 'comment'
BEGIN: 'begin',
ATOM: 'atom',
MULTIPLIER_RANGE: 'multiplierRange',
ISOTOPE: 'isotope',
ISOTOPE_RATIO: 'isotopeRatio',
CHARGE: 'charge',
SALT: 'salt',
OPENING_PARENTHESIS: 'openingParenthesis',
CLOSING_PARENTHESIS: 'closingParenthesis',
PRE_MULTIPLIER: 'preMultiplier',
MULTIPLIER: 'multiplier',
TEXT: 'text',
COMMENT: 'comment'
};

@@ -13,196 +13,196 @@ 'use strict';

module.exports = function parse(mf) {
return new MFParser().parse(mf);
return new MFParser().parse(mf);
};
class MFParser {
parse(mf = '') {
this.mf = mf;
this.i = 0;
this.result = [];
parse(mf = '') {
this.mf = mf;
this.i = 0;
this.result = [];
let lastKind = Kind.BEGIN;
while (this.i < mf.length) {
if (this.result.length > 0 && this.result[this.result.length - 1].kind !== Kind.TEXT) {
lastKind = this.result[this.result.length - 1].kind;
}
let char = mf.charAt(this.i);
let ascii = mf.charCodeAt(this.i);
let nextAscii = 0;
if (this.i + 1 < mf.length) nextAscii = mf.charCodeAt(this.i + 1);
let lastKind = Kind.BEGIN;
while (this.i < mf.length) {
if (this.result.length > 0 && this.result[this.result.length - 1].kind !== Kind.TEXT) {
lastKind = this.result[this.result.length - 1].kind;
}
let char = mf.charAt(this.i);
let ascii = mf.charCodeAt(this.i);
let nextAscii = 0;
if (this.i + 1 < mf.length) nextAscii = mf.charCodeAt(this.i + 1);
if ((ascii > 47 && ascii < 58) || (char === '-' && nextAscii > 47 && nextAscii < 58)) { // a number
let value = this.getNumber(ascii);
if (lastKind === Kind.SALT || lastKind === Kind.BEGIN || lastKind === Kind.OPENING_PARENTHESIS) {
if (value.to) throw new MFError(this.mf, this.i, 'Premultiplier may not contain a -');
this.result.push({ kind: Kind.PRE_MULTIPLIER, value: value.from });
} else {
if (value.to) {
this.result.push({ kind: Kind.MULTIPLIER_RANGE, value });
} else {
this.result.push({ kind: Kind.MULTIPLIER, value: value.from });
}
}
continue;
} else if (char === '.') { // a point
this.result.push({ kind: Kind.SALT, value: char });
// it is not in a number otherwise it would have been taken before
// it must be in a salt
} else if (ascii > 64 && ascii < 91) { // an uppercase = new atom
let value = this.getAtom(ascii);
this.result.push({ kind: Kind.ATOM, value });
continue;
} else if (ascii > 96 && ascii < 123) { // a lowercase
throw new MFError(this.mf, this.i, 'found a lowercase not following an uppercase');
} else if (char === '(') {
let charge = this.getParenthesisCharge(ascii);
if (charge) {
this.result.push({ kind: Kind.CHARGE, value: charge });
} else {
this.result.push({ kind: Kind.OPENING_PARENTHESIS, value: '(' });
}
} else if (char === ')') {
this.result.push({ kind: Kind.CLOSING_PARENTHESIS, value: ')' });
} else if (char === '[') { // defines an isotope
let isotope = this.getIsotope(ascii);
this.result.push({ kind: Kind.ISOTOPE, value: isotope });
} else if (char === ']') {
throw new MFError(this.mf, this.i, 'should never meet an closing bracket not in isotopes');
} else if (char === '{') { // can define an exotic isotopic ratio or mixtures of groups
let isotopeRatio = this.getCurlyBracketIsotopeRatio(ascii);
if (lastKind === Kind.ATOM) {
let lastResult = this.result[this.result.length - 1];
lastResult.kind = Kind.ISOTOPE_RATIO;
lastResult.value = {
atom: lastResult.value,
ratio: isotopeRatio
};
} else {
throw new MFError(this.mf, this.i, 'isotopic composition has to follow an atom');
}
} else if (char === '}') {
throw new MFError(this.mf, this.i, 'found a unexpected closing curly bracket');
} else if (char === '+') { // charge not in parenthesis
let charge = this.getNonParenthesisCharge(ascii);
this.result.push({ kind: Kind.CHARGE, value: charge });
} else if (char === '-') { // charge not in parenthesis
let charge = this.getNonParenthesisCharge(ascii);
this.result.push({ kind: Kind.CHARGE, value: charge });
} else if (char === '$') { // it is a comment after
this.result.push({ kind: Kind.COMMENT, value: this.mf.substring(this.i + 1) });
break;
} else {
this.result.push({ kind: Kind.TEXT, value: char });
}
this.i++;
if ((ascii > 47 && ascii < 58) || (char === '-' && nextAscii > 47 && nextAscii < 58)) { // a number
let value = this.getNumber(ascii);
if (lastKind === Kind.SALT || lastKind === Kind.BEGIN || lastKind === Kind.OPENING_PARENTHESIS) {
if (value.to) throw new MFError(this.mf, this.i, 'Premultiplier may not contain a -');
this.result.push({ kind: Kind.PRE_MULTIPLIER, value: value.from });
} else {
if (value.to) {
this.result.push({ kind: Kind.MULTIPLIER_RANGE, value });
} else {
this.result.push({ kind: Kind.MULTIPLIER, value: value.from });
}
}
this.checkParenthesis();
return this.result;
}
checkParenthesis() {
let counter = 0;
for (let line of this.result) {
if (line.kind === Kind.OPENING_PARENTHESIS) counter++;
if (line.kind === Kind.CLOSING_PARENTHESIS) counter--;
continue;
} else if (char === '.') { // a point
this.result.push({ kind: Kind.SALT, value: char });
// it is not in a number otherwise it would have been taken before
// it must be in a salt
} else if (ascii > 64 && ascii < 91) { // an uppercase = new atom
let value = this.getAtom(ascii);
this.result.push({ kind: Kind.ATOM, value });
continue;
} else if (ascii > 96 && ascii < 123) { // a lowercase
throw new MFError(this.mf, this.i, 'found a lowercase not following an uppercase');
} else if (char === '(') {
let charge = this.getParenthesisCharge(ascii);
if (charge) {
this.result.push({ kind: Kind.CHARGE, value: charge });
} else {
this.result.push({ kind: Kind.OPENING_PARENTHESIS, value: '(' });
}
if (counter !== 0) {
throw new MFError(this.mf, this.i, 'number of opening and closing parenthesis not equal');
} else if (char === ')') {
this.result.push({ kind: Kind.CLOSING_PARENTHESIS, value: ')' });
} else if (char === '[') { // defines an isotope
let isotope = this.getIsotope(ascii);
this.result.push({ kind: Kind.ISOTOPE, value: isotope });
} else if (char === ']') {
throw new MFError(this.mf, this.i, 'should never meet an closing bracket not in isotopes');
} else if (char === '{') { // can define an exotic isotopic ratio or mixtures of groups
let isotopeRatio = this.getCurlyBracketIsotopeRatio(ascii);
if (lastKind === Kind.ATOM) {
let lastResult = this.result[this.result.length - 1];
lastResult.kind = Kind.ISOTOPE_RATIO;
lastResult.value = {
atom: lastResult.value,
ratio: isotopeRatio
};
} else {
throw new MFError(this.mf, this.i, 'isotopic composition has to follow an atom');
}
} else if (char === '}') {
throw new MFError(this.mf, this.i, 'found a unexpected closing curly bracket');
} else if (char === '+') { // charge not in parenthesis
let charge = this.getNonParenthesisCharge(ascii);
this.result.push({ kind: Kind.CHARGE, value: charge });
} else if (char === '-') { // charge not in parenthesis
let charge = this.getNonParenthesisCharge(ascii);
this.result.push({ kind: Kind.CHARGE, value: charge });
} else if (char === '$') { // it is a comment after
this.result.push({ kind: Kind.COMMENT, value: this.mf.substring(this.i + 1) });
break;
} else {
this.result.push({ kind: Kind.TEXT, value: char });
}
this.i++;
}
getNumber(ascii) {
let number = '';
let previous;
do {
previous = ascii;
number += String.fromCharCode(ascii);
this.i++;
ascii = this.mf.charCodeAt(this.i);
} while (ascii > 47 && ascii < 58 || ascii === 46 || ascii === 45); // number, . or -
// we need to deal with the case there is a from / to
if (previous === 46) this.i--;
let indexOfDash = number.indexOf('-', 1);
this.checkParenthesis();
return this.result;
}
if (indexOfDash > -1) {
return { from: Number(number.substr(0, indexOfDash)), to: Number(number.substr(indexOfDash + 1)) };
}
return { from: Number(number) };
checkParenthesis() {
let counter = 0;
for (let line of this.result) {
if (line.kind === Kind.OPENING_PARENTHESIS) counter++;
if (line.kind === Kind.CLOSING_PARENTHESIS) counter--;
}
getAtom(ascii) {
let atom = '';
do {
atom += String.fromCharCode(ascii);
this.i++;
ascii = this.mf.charCodeAt(this.i);
} while (ascii > 96 && ascii < 123);
return atom;
if (counter !== 0) {
throw new MFError(this.mf, this.i, 'number of opening and closing parenthesis not equal');
}
}
getIsotope(ascii) { // [13C]
let substring = '';
do {
substring += String.fromCharCode(ascii);
this.i++;
ascii = this.mf.charCodeAt(this.i);
} while (ascii !== 93 && this.i <= this.mf.length);
getNumber(ascii) {
let number = '';
let previous;
do {
previous = ascii;
number += String.fromCharCode(ascii);
this.i++;
ascii = this.mf.charCodeAt(this.i);
} while (ascii > 47 && ascii < 58 || ascii === 46 || ascii === 45); // number, . or -
// we need to deal with the case there is a from / to
if (previous === 46) this.i--;
let indexOfDash = number.indexOf('-', 1);
let atom = substring.replace(/[^a-zA-Z]/g, '');
let isotope = Number(substring.replace(/[^0-9]/g, ''));
return { atom, isotope };
if (indexOfDash > -1) {
return { from: Number(number.substr(0, indexOfDash)), to: Number(number.substr(indexOfDash + 1)) };
}
return { from: Number(number) };
}
getAtom(ascii) {
let atom = '';
do {
atom += String.fromCharCode(ascii);
this.i++;
ascii = this.mf.charCodeAt(this.i);
} while (ascii > 96 && ascii < 123);
return atom;
}
getCurlyBracketIsotopeRatio(ascii) {
let substring = '';
let first = true;
do {
if (!first) {
substring += String.fromCharCode(ascii);
} else {
first = false;
}
this.i++;
ascii = this.mf.charCodeAt(this.i);
} while (ascii !== 125 && this.i <= this.mf.length); // closing curly bracket
if (substring.match(/^[0-9,]+$/)) {
return substring.split(',').map((a) => Number(a));
}
throw new MFError(this.mf, this.i, 'Curly brackets should contain only number and comma');
getIsotope(ascii) { // [13C]
let substring = '';
do {
substring += String.fromCharCode(ascii);
this.i++;
ascii = this.mf.charCodeAt(this.i);
} while (ascii !== 93 && this.i <= this.mf.length);
let atom = substring.replace(/[^a-zA-Z]/g, '');
let isotope = Number(substring.replace(/[^0-9]/g, ''));
return { atom, isotope };
}
getCurlyBracketIsotopeRatio(ascii) {
let substring = '';
let first = true;
do {
if (!first) {
substring += String.fromCharCode(ascii);
} else {
first = false;
}
this.i++;
ascii = this.mf.charCodeAt(this.i);
} while (ascii !== 125 && this.i <= this.mf.length); // closing curly bracket
if (substring.match(/^[0-9,]+$/)) {
return substring.split(',').map((a) => Number(a));
}
throw new MFError(this.mf, this.i, 'Curly brackets should contain only number and comma');
}
getParenthesisCharge(ascii) {
let substring = '';
let begin = this.i;
do {
substring += String.fromCharCode(ascii);
this.i++;
ascii = this.mf.charCodeAt(this.i);
} while (ascii !== 41 && this.i <= this.mf.length); // closing parenthesis
if (substring.match(/^\([0-9+-]+$/)) {
return parseCharge(substring.substring(1));
} else {
this.i = begin;
return undefined;
}
getParenthesisCharge(ascii) {
let substring = '';
let begin = this.i;
do {
substring += String.fromCharCode(ascii);
this.i++;
ascii = this.mf.charCodeAt(this.i);
} while (ascii !== 41 && this.i <= this.mf.length); // closing parenthesis
if (substring.match(/^\([0-9+-]+$/)) {
return parseCharge(substring.substring(1));
} else {
this.i = begin;
return undefined;
}
}
getNonParenthesisCharge(ascii) {
let substring = '';
do {
substring += String.fromCharCode(ascii);
this.i++;
ascii = this.mf.charCodeAt(this.i);
} while (ascii === 43 || ascii === 45 || (ascii > 47 && ascii < 58));
this.i--;
return parseCharge(substring);
}
getNonParenthesisCharge(ascii) {
let substring = '';
do {
substring += String.fromCharCode(ascii);
this.i++;
ascii = this.mf.charCodeAt(this.i);
} while (ascii === 43 || ascii === 45 || (ascii > 47 && ascii < 58));
this.i--;
return parseCharge(substring);
}
}
class MFError extends SyntaxError {
constructor(mf, i, message) {
let text = `${message}\n\n${mf}\n${' '.repeat(i)}^`;
super(text);
}
constructor(mf, i, message) {
let text = `${message}\n\n${mf}\n${' '.repeat(i)}^`;
super(text);
}
}
'use strict';
module.exports = {
SUPERIMPOSE: 'flex-direction: column;display: inline-flex;justify-content: center;text-align: left;vertical-align: middle;',
SUPERIMPOSE_SUP_SUB: 'line-height: 1; font-size: 70%'
SUPERIMPOSE: 'flex-direction: column;display: inline-flex;justify-content: center;text-align: left;vertical-align: middle;',
SUPERIMPOSE_SUP_SUB: 'line-height: 1; font-size: 70%'
};

@@ -6,7 +6,7 @@ 'use strict';

test('formatCharge', function () {
expect(formatCharge(-2)).toBe('-2');
expect(formatCharge(-1)).toBe('-1');
expect(formatCharge(0)).toBe('');
expect(formatCharge(1)).toBe('+');
expect(formatCharge(2)).toBe('+2');
expect(formatCharge(-2)).toBe('-2');
expect(formatCharge(-1)).toBe('-1');
expect(formatCharge(0)).toBe('');
expect(formatCharge(1)).toBe('+');
expect(formatCharge(2)).toBe('+2');
});

@@ -6,9 +6,9 @@ 'use strict';

test('getCharge', function () {
expect(getCharge('---')).toBe(-3);
expect(getCharge('+++')).toBe(3);
expect(getCharge('---++')).toBe(-1);
expect(getCharge('(-3)')).toBe(-3);
expect(getCharge('(+1)')).toBe(1);
expect(getCharge('(---)')).toBe(-3);
expect(getCharge('(++)')).toBe(2);
expect(getCharge('---')).toBe(-3);
expect(getCharge('+++')).toBe(3);
expect(getCharge('---++')).toBe(-1);
expect(getCharge('(-3)')).toBe(-3);
expect(getCharge('(+1)')).toBe(1);
expect(getCharge('(---)')).toBe(-3);
expect(getCharge('(++)')).toBe(2);
});
'use strict';
var tests = [
{
mf: 'C10',
parsed: [{ kind: 'atom', value: 'C' }, { kind: 'multiplier', value: 10 }],
result: [{ kind: 'text', value: 'C' }, { kind: 'subscript', value: '10' }]
},
{
mf: 'C-1',
parsed: [{ kind: 'atom', value: 'C' }, { kind: 'multiplier', value: -1 }],
result: [{ kind: 'text', value: 'C' }, { kind: 'subscript', value: '-1' }]
},
{
mf: 'C1-10',
parsed: [{ kind: 'atom', value: 'C' }, { kind: 'multiplierRange', value: { from: 1, to: 10 } }],
result: [{ kind: 'text', value: 'C' }, { kind: 'subscript', value: '1-10' }]
},
{
mf: '2H',
parsed: [{ kind: 'preMultiplier', value: 2 }, { kind: 'atom', value: 'H' }],
result: [{ kind: 'text', value: '2H' }]
},
{
mf: '[13C]',
parsed: [{ kind: 'isotope', value: { atom: 'C', isotope: 13 } }],
result: [{ kind: 'superscript', value: 13 }, { kind: 'text', value: 'C' }]
},
{
mf: 'C++',
parsed: [{ kind: 'atom', value: 'C' }, { kind: 'charge', value: 2 }],
result: [{ kind: 'text', value: 'C' }, { kind: 'superscript', value: '+2' }]
},
{
mf: 'C2+',
parsed: [{ kind: 'atom', value: 'C' }, { kind: 'multiplier', value: 2 }, { kind: 'charge', value: 1 }],
result: [{ kind: 'text', value: 'C' }, { kind: 'superimpose', over: '+', under: '2' }]
},
{
mf: 'C(H-2)',
parsed: [{ kind: 'atom', value: 'C' }, { kind: 'openingParenthesis', value: '(' }, { kind: 'atom', value: 'H' }, { kind: 'multiplier', value: -2 }, { kind: 'closingParenthesis', value: ')' }],
result: [{ kind: 'text', value: 'C(H' }, { kind: 'subscript', value: '-2' }, { kind: 'text', value: ')' }]
},
{
mf: 'H.Cl',
parsed: [{ kind: 'atom', value: 'H' }, { kind: 'salt', value: '.' }, { kind: 'atom', value: 'Cl' }],
result: [{ kind: 'text', value: 'H•Cl' }]
},
{
mf: 'H{1,1}',
parsed: [{ kind: 'isotopeRatio', value: { atom: 'H', ratio: [1, 1] } }],
result: [{ kind: 'text', value: 'H' }, { kind: 'superscript', value: '{1,1}' }]
},
{
mf: 'C10',
parsed: [{ kind: 'atom', value: 'C' }, { kind: 'multiplier', value: 10 }],
result: [{ kind: 'text', value: 'C' }, { kind: 'subscript', value: '10' }]
},
{
mf: 'C-1',
parsed: [{ kind: 'atom', value: 'C' }, { kind: 'multiplier', value: -1 }],
result: [{ kind: 'text', value: 'C' }, { kind: 'subscript', value: '-1' }]
},
{
mf: 'C1-10',
parsed: [
{ kind: 'atom', value: 'C' },
{ kind: 'multiplierRange', value: { from: 1, to: 10 } }
],
result: [{ kind: 'text', value: 'C' }, { kind: 'subscript', value: '1-10' }]
},
{
mf: '2H',
parsed: [{ kind: 'preMultiplier', value: 2 }, { kind: 'atom', value: 'H' }],
result: [{ kind: 'text', value: '2H' }]
},
{
mf: '[13C]',
parsed: [{ kind: 'isotope', value: { atom: 'C', isotope: 13 } }],
result: [{ kind: 'superscript', value: 13 }, { kind: 'text', value: 'C' }]
},
{
mf: 'C++',
parsed: [{ kind: 'atom', value: 'C' }, { kind: 'charge', value: 2 }],
result: [{ kind: 'text', value: 'C' }, { kind: 'superscript', value: '+2' }]
},
{
mf: 'C2+',
parsed: [
{ kind: 'atom', value: 'C' },
{ kind: 'multiplier', value: 2 },
{ kind: 'charge', value: 1 }
],
result: [
{ kind: 'text', value: 'C' },
{ kind: 'superimpose', over: '+', under: '2' }
]
},
{
mf: 'C(H-2)',
parsed: [
{ kind: 'atom', value: 'C' },
{ kind: 'openingParenthesis', value: '(' },
{ kind: 'atom', value: 'H' },
{ kind: 'multiplier', value: -2 },
{ kind: 'closingParenthesis', value: ')' }
],
result: [
{ kind: 'text', value: 'C(H' },
{ kind: 'subscript', value: '-2' },
{ kind: 'text', value: ')' }
]
},
{
mf: 'H.Cl',
parsed: [
{ kind: 'atom', value: 'H' },
{ kind: 'salt', value: '.' },
{ kind: 'atom', value: 'Cl' }
],
result: [{ kind: 'text', value: 'H•Cl' }]
},
{
mf: 'H{1,1}',
parsed: [{ kind: 'isotopeRatio', value: { atom: 'H', ratio: [1, 1] } }],
result: [
{ kind: 'text', value: 'H' },
{ kind: 'superscript', value: '{1,1}' }
]
}
];
const toDisplay = require('../toDisplay');
test('toDisplay', function () {
for (let aTest of tests) {
checkMF(aTest.parsed, aTest.result);
}
test.each(tests)('toDisplay', function (aTest) {
var display = toDisplay(aTest.parsed);
expect(display).toMatchObject(aTest.result);
});
function checkMF(parsed, result) {
var display = toDisplay(parsed);
expect(display).toMatchObject(result);
}

@@ -6,12 +6,16 @@ 'use strict';

var tests = [
{mf: 'C', result: [[{kind: 'atom', value: 'C', multiplier: 1}]]},
{mf: 'C2', result: [[{kind: 'atom', value: 'C', multiplier: 2}]]},
{mf: 'CCC', result: [[{kind: 'atom', value: 'C', multiplier: 3}]]},
{mf: '2CCC', result: [[{kind: 'atom', value: 'C', multiplier: 6}]]},
{mf: '2C(C(C2)2)3', result: [[{kind: 'atom', value: 'C', multiplier: 32}]]}, {
{ mf: 'C', result: [[{ kind: 'atom', value: 'C', multiplier: 1 }]] },
{ mf: 'C2', result: [[{ kind: 'atom', value: 'C', multiplier: 2 }]] },
{ mf: 'CCC', result: [[{ kind: 'atom', value: 'C', multiplier: 3 }]] },
{ mf: '2CCC', result: [[{ kind: 'atom', value: 'C', multiplier: 6 }]] },
{
mf: '2C(C(C2)2)3',
result: [[{ kind: 'atom', value: 'C', multiplier: 32 }]]
},
{
mf: '3C.2C.C4',
result: [
[{kind: 'atom', value: 'C', multiplier: 3}],
[{kind: 'atom', value: 'C', multiplier: 2}],
[{kind: 'atom', value: 'C', multiplier: 4}]
[{ kind: 'atom', value: 'C', multiplier: 3 }],
[{ kind: 'atom', value: 'C', multiplier: 2 }],
[{ kind: 'atom', value: 'C', multiplier: 4 }]
]

@@ -23,9 +27,9 @@ },

[
{kind: 'atom', value: 'C', multiplier: 6},
{kind: 'atom', value: 'H', multiplier: 15},
{kind: 'atom', value: 'N', multiplier: 1}
{ kind: 'atom', value: 'C', multiplier: 6 },
{ kind: 'atom', value: 'H', multiplier: 15 },
{ kind: 'atom', value: 'N', multiplier: 1 }
],
[
{kind: 'atom', value: 'H', multiplier: 1},
{kind: 'atom', value: 'Cl', multiplier: 1}
{ kind: 'atom', value: 'H', multiplier: 1 },
{ kind: 'atom', value: 'Cl', multiplier: 1 }
]

@@ -36,11 +40,12 @@ ]

mf: '3[13C]2C',
result: [[
{kind: 'atom', value: 'C', multiplier: 3},
{kind: 'isotope', value: {atom: 'C', isotope: 13}, multiplier: 6}
]]
result: [
[
{ kind: 'atom', value: 'C', multiplier: 3 },
{ kind: 'isotope', value: { atom: 'C', isotope: 13 }, multiplier: 6 }
]
]
},
{
mf: 'D',
result:
[[{kind: 'isotope', value: {atom: 'H', isotope: 2}, multiplier: 1}]]
result: [[{ kind: 'isotope', value: { atom: 'H', isotope: 2 }, multiplier: 1 }]]
}

@@ -51,12 +56,6 @@ ];

test('toParts', function() {
for (let aTest of tests) {
checkMF(aTest.mf, aTest.result);
}
test.each(tests)('toParts %p', function (aTest) {
var parsed = parse(aTest.mf);
var parts = toParts(parsed);
expect(parts).toMatchObject(aTest.result);
});
function checkMF(mf, result) {
var parsed = parse(mf);
var parts = toParts(parsed);
expect(parts).toMatchObject(result);
}
'use strict';
module.exports = function formatCharge(charge) {
if (charge === 1) return '+';
if (charge > 1) return `+${charge}`;
if (charge < 0) return String(charge);
return '';
if (charge === 1) return '+';
if (charge > 1) return `+${charge}`;
if (charge < 0) return String(charge);
return '';
};
'use strict';
'use strict';
const elements = require('chemical-elements/src/elementsAndStableIsotopesObject.js');
const groups = require('chemical-groups/src/groupsObject.js');
const Kind = require('../Kind');

@@ -17,3 +16,3 @@

*/
module.exports = function getInfo(parts, options = {}) {
module.exports = function getInfo(parts) {
var results = {};

@@ -44,3 +43,3 @@ for (let part of parts) {

case Kind.ATOM:
case Kind.ATOM: {
let element = elements[line.value];

@@ -54,2 +53,4 @@ if (!element) {

break;
}
case Kind.CHARGE:

@@ -73,3 +74,3 @@ break;

eas.forEach(ea => {
eas.forEach((ea) => {
ea.ratio = ea.mass / sum;

@@ -76,0 +77,0 @@ });

'use strict';
const partToMF = require('./partToMF');
const elements = require('chemical-elements/src/elementsAndStableIsotopesObject.js');
const groups = require('chemical-groups/src/groupsObject.js');
const unsaturations = require('chemical-elements/src/unsaturationsObject.js');
const Kind = require('../Kind');
const { ELECTRON_MASS } = require('chemical-elements/src/constants');
const partToMF = require('./partToMF');
const partToAtoms = require('./partToAtoms');
const isotopes = require('./getIsotopesObject');

@@ -34,4 +36,4 @@ const getIsotopeRatioInfo = require('./getIsotopeRatioInfo');

result.charge = 0;
result.mf = result.parts.map(a => a.mf).join('.');
result.parts.forEach(a => {
result.mf = result.parts.map((a) => a.mf).join('.');
result.parts.forEach((a) => {
result.mass += a.mass;

@@ -130,2 +132,1 @@ result.monoisotopicMass += a.monoisotopicMass;

@@ -30,5 +30,5 @@ 'use strict';

let sum = array.reduce((prev, current) => prev + current, 0);
return array.map(a => a / sum);
return array.map((a) => a / sum);
}
module.exports = getIsotopeRatioInfo;
'use strict';
const elements = require('chemical-elements/src/elementsAndStableIsotopesObject.js');
const Kind = require('../Kind');

@@ -14,58 +15,55 @@

module.exports = function getIsotopesInfo(parts) {
if (parts.length === 0) return [];
if (parts.length > 1) throw new Error('getIsotopesInfo can not be applied on multipart MF');
if (parts.length === 0) return [];
if (parts.length > 1) throw new Error('getIsotopesInfo can not be applied on multipart MF');
return getProcessedPart(parts[0]);
return getProcessedPart(parts[0]);
};
function getProcessedPart(part) {
let result = {
charge: 0,
isotopes: []
};
for (let line of part) {
switch (line.kind) {
case Kind.ISOTOPE: {
let isotope = isotopes[line.value.isotope + line.value.atom];
if (!isotope) throw Error('unknown isotope:', line.value.atom, line.value.isotope);
result.isotopes.push({
atom: `[${line.value.isotope}${line.value.atom}]`,
number: line.multiplier,
distribution: [
{ x: isotope.mass, y: 1 }
]
});
break;
}
case Kind.ISOTOPE_RATIO: {
let element = elements[line.value.atom];
if (!element) throw new Error('unknown element:', line.value);
let result = {
charge: 0,
isotopes: []
};
for (let line of part) {
switch (line.kind) {
case Kind.ISOTOPE: {
let isotope = isotopes[line.value.isotope + line.value.atom];
if (!isotope) throw Error('unknown isotope:', line.value.atom, line.value.isotope);
result.isotopes.push({
atom: `[${line.value.isotope}${line.value.atom}]`,
number: line.multiplier,
distribution: [{ x: isotope.mass, y: 1 }]
});
break;
}
case Kind.ISOTOPE_RATIO: {
let element = elements[line.value.atom];
if (!element) throw new Error('unknown element:', line.value);
let distribution = getDistribution(element.isotopes, line.value.ratio);
result.isotopes.push({
atom: `${line.value.atom}{${line.value.ratio.join(',')}}`,
number: line.multiplier,
distribution
});
}
break;
case Kind.ATOM: {
let element = elements[line.value];
if (!element) throw new Error('unknown element:', line.value);
result.isotopes.push({
atom: line.value,
number: line.multiplier,
distribution: element.isotopes.map((e) => ({ x: e.mass, y: e.abundance }))
});
break;
}
case Kind.CHARGE:
result.charge += line.value;
break;
default:
throw new Error('partToMF unhandled Kind: ', line.kind);
}
let distribution = getDistribution(element.isotopes, line.value.ratio);
result.isotopes.push({
atom: `${line.value.atom}{${line.value.ratio.join(',')}}`,
number: line.multiplier,
distribution
});
}
break;
case Kind.ATOM: {
let element = elements[line.value];
if (!element) throw new Error('unknown element:', line.value);
result.isotopes.push({
atom: line.value,
number: line.multiplier,
distribution: element.isotopes.map((e) => ({ x: e.mass, y: e.abundance }))
});
break;
}
case Kind.CHARGE:
result.charge += line.value;
break;
default:
throw new Error('partToMF unhandled Kind: ', line.kind);
}
return result;
}
return result;
}

@@ -75,19 +73,19 @@

function getDistribution(isotopesArray, ratio) {
let ratios = normalize(ratio);
let result = [];
if (ratios.length > isotopesArray.length) {
throw new Error(`the number of specified ratios is bigger that the number of stable isotopes: ${isotopes}`);
}
for (let i = 0; i < ratios.length; i++) {
result.push({
x: isotopesArray[i].mass,
y: ratios[i]
});
}
return result;
let ratios = normalize(ratio);
let result = [];
if (ratios.length > isotopesArray.length) {
throw new Error(`the number of specified ratios is bigger that the number of stable isotopes: ${isotopes}`);
}
for (let i = 0; i < ratios.length; i++) {
result.push({
x: isotopesArray[i].mass,
y: ratios[i]
});
}
return result;
}
function normalize(array) {
let sum = array.reduce((prev, current) => prev + current, 0);
return array.map((a) => a / sum);
let sum = array.reduce((prev, current) => prev + current, 0);
return array.map((a) => a / sum);
}

@@ -7,9 +7,9 @@ 'use strict';

Object.keys(elements).forEach((key) => {
let e = elements[key];
e.isotopes.forEach((i) => {
isotopes[i.nominal + key] = {
abundance: i.abundance,
mass: i.mass
};
});
let e = elements[key];
e.isotopes.forEach((i) => {
isotopes[i.nominal + key] = {
abundance: i.abundance,
mass: i.mass
};
});
});

@@ -16,0 +16,0 @@

@@ -11,15 +11,15 @@ 'use strict';

module.exports = function parseCharge(charge) {
charge = charge.replace(/[()]/g, '');
var chargeNumber = 0;
if (charge.match(/^[+-]+$/)) {
for (var i = 0; i < charge.length; i++) {
if (charge.charAt(i) === '+') chargeNumber++;
else chargeNumber--;
}
} else if (charge.match(/^[0-9]+[+-]$/)) {
chargeNumber = Number(charge.charAt(charge.length - 1) + charge.substring(0, charge.length - 1));
} else {
chargeNumber = Number(charge);
charge = charge.replace(/[()]/g, '');
var chargeNumber = 0;
if (charge.match(/^[+-]+$/)) {
for (var i = 0; i < charge.length; i++) {
if (charge.charAt(i) === '+') chargeNumber++;
else chargeNumber--;
}
return chargeNumber;
} else if (charge.match(/^[0-9]+[+-]$/)) {
chargeNumber = Number(charge.charAt(charge.length - 1) + charge.substring(0, charge.length - 1));
} else {
chargeNumber = Number(charge);
}
return chargeNumber;
};
'use strict';
const Kind = require('../Kind');
const toDisplay = require('./toDisplay');

@@ -11,18 +12,17 @@ /**

module.exports = function partsToDisplay(parts) {
var lines = [];
for (let part of parts) {
if (lines.length > 0) lines.push({ kind: Kind.SALT, value: '•' });
for (let partLine of part) {
lines.push(partLine);
if (partLine.multiplier) {
lines.push({
kind: Kind.MULTIPLIER,
value: partLine.multiplier
});
}
}
var lines = [];
for (let part of parts) {
if (lines.length > 0) lines.push({ kind: Kind.SALT, value: '•' });
for (let partLine of part) {
lines.push(partLine);
if (partLine.multiplier) {
lines.push({
kind: Kind.MULTIPLIER,
value: partLine.multiplier
});
}
}
}
return toDisplay(lines);
return toDisplay(lines);
};

@@ -10,3 +10,3 @@ 'use strict';

case Kind.ISOTOPE:
if (line.multiplier !== 0)
if (line.multiplier !== 0) {
mf.push(

@@ -17,5 +17,6 @@ `[${line.value.isotope}${line.value.atom}]${

);
}
break;
case Kind.ISOTOPE_RATIO:
if (line.multiplier !== 0)
if (line.multiplier !== 0) {
mf.push(

@@ -26,6 +27,8 @@ `${line.value.atom}{${line.value.ratio.join(',')}}${

);
}
break;
case Kind.ATOM:
if (line.multiplier !== 0)
if (line.multiplier !== 0) {
mf.push(line.value + (line.multiplier !== 1 ? line.multiplier : ''));
}
break;

@@ -32,0 +35,0 @@ case Kind.CHARGE:

@@ -5,2 +5,3 @@ 'use strict';

const Format = require('../Format');
const formatCharge = require('./formatCharge');

@@ -14,91 +15,91 @@

module.exports = function convertForDisplay(lines) {
let results = [];
let result = {};
for (let line of lines) {
switch (line.kind) {
case Kind.MULTIPLIER:
if (line.value !== 1) {
result = {
kind: Format.SUBSCRIPT,
value: String(line.value)
};
results.push(result);
}
break;
case Kind.MULTIPLIER_RANGE:
result = {
kind: Format.SUBSCRIPT,
value: `${String(line.value.from)}-${line.value.to}`
};
results.push(result);
break;
case Kind.CHARGE:
if (result.kind === Format.SUBSCRIPT) {
result.kind = Format.SUPERIMPOSE;
result.over = formatCharge(line.value);
result.under = result.value;
result.value = undefined;
} else {
result = {
kind: Format.SUPERSCRIPT,
value: formatCharge(line.value)
};
results.push(result);
}
let results = [];
let result = {};
for (let line of lines) {
switch (line.kind) {
case Kind.MULTIPLIER:
if (line.value !== 1) {
result = {
kind: Format.SUBSCRIPT,
value: String(line.value)
};
results.push(result);
}
break;
case Kind.MULTIPLIER_RANGE:
result = {
kind: Format.SUBSCRIPT,
value: `${String(line.value.from)}-${line.value.to}`
};
results.push(result);
break;
case Kind.CHARGE:
if (result.kind === Format.SUBSCRIPT) {
result.kind = Format.SUPERIMPOSE;
result.over = formatCharge(line.value);
result.under = result.value;
result.value = undefined;
} else {
result = {
kind: Format.SUPERSCRIPT,
value: formatCharge(line.value)
};
results.push(result);
}
break;
break;
case Kind.ISOTOPE:
result = {
kind: Format.SUPERSCRIPT,
value: line.value.isotope
};
results.push(result);
result = {
kind: Format.TEXT,
value: line.value.atom
};
results.push(result);
break;
case Kind.ISOTOPE:
result = {
kind: Format.SUPERSCRIPT,
value: line.value.isotope
};
results.push(result);
result = {
kind: Format.TEXT,
value: line.value.atom
};
results.push(result);
break;
case Kind.ISOTOPE_RATIO:
if (result.kind === Format.TEXT) {
result.value += line.value.atom;
} else {
result = {
kind: Format.TEXT,
value: line.value.atom
};
results.push(result);
}
result = {
kind: Format.SUPERSCRIPT,
value: `{${line.value.ratio.join(',')}}`
};
results.push(result);
break;
case Kind.SALT:
if (result.kind === Format.TEXT) {
result.value += '•';
} else {
result = {
kind: Format.TEXT,
value: ' • '
};
results.push(result);
}
break;
default:
if (result.kind === Format.TEXT) {
result.value += line.value;
} else {
result = {
kind: Format.TEXT,
value: line.value
};
results.push(result);
}
case Kind.ISOTOPE_RATIO:
if (result.kind === Format.TEXT) {
result.value += line.value.atom;
} else {
result = {
kind: Format.TEXT,
value: line.value.atom
};
results.push(result);
}
result = {
kind: Format.SUPERSCRIPT,
value: `{${line.value.ratio.join(',')}}`
};
results.push(result);
break;
case Kind.SALT:
if (result.kind === Format.TEXT) {
result.value += '•';
} else {
result = {
kind: Format.TEXT,
value: ' • '
};
results.push(result);
}
break;
default:
if (result.kind === Format.TEXT) {
result.value += line.value;
} else {
result = {
kind: Format.TEXT,
value: line.value
};
results.push(result);
}
}
return results;
}
return results;
};
'use strict';
const Format = require('../Format');
const Style = require('../Style');
module.exports = function getHtml(lines) {
var html = [];
for (let line of lines) {
switch (line.kind) {
case Format.SUBSCRIPT:
html.push(`<sub>${line.value}</sub>`);
break;
case Format.SUPERSCRIPT:
html.push(`<sup>${line.value}</sup>`);
break;
case Format.SUPERIMPOSE:
html.push(`<span style="${Style.SUPERIMPOSE}">`);
html.push(`<sup style="${Style.SUPERIMPOSE_SUP_SUB}">${line.over}</sup>`);
html.push(`<sub style="${Style.SUPERIMPOSE_SUP_SUB}">${line.under}</sub>`);
html.push('</span>');
break;
default:
html.push(line.value);
}
var html = [];
for (let line of lines) {
switch (line.kind) {
case Format.SUBSCRIPT:
html.push(`<sub>${line.value}</sub>`);
break;
case Format.SUPERSCRIPT:
html.push(`<sup>${line.value}</sup>`);
break;
case Format.SUPERIMPOSE:
html.push(`<span style="${Style.SUPERIMPOSE}">`);
html.push(`<sup style="${Style.SUPERIMPOSE_SUP_SUB}">${line.over}</sup>`);
html.push(`<sub style="${Style.SUPERIMPOSE_SUP_SUB}">${line.under}</sub>`);
html.push('</span>');
break;
default:
html.push(line.value);
}
return html.join('');
}
return html.join('');
};
'use strict';
const Kind = require('../Kind');
const groups = require('chemical-groups/src/groupsObject.js');
const atomSorter = require('atom-sorter');
const Kind = require('../Kind');
/**

@@ -22,2 +23,8 @@ *

switch (line.kind) {
case Kind.ATOM:
case Kind.ISOTOPE_RATIO:
case Kind.ISOTOPE:
case Kind.CHARGE:
currentPart.lines.push(Object.assign({}, line, { multiplier: 1 }));
break;
case Kind.OPENING_PARENTHESIS:

@@ -40,8 +47,2 @@ openingParenthesis(currentPart);

break;
case Kind.ATOM:
case Kind.ISOTOPE_RATIO:
case Kind.ISOTOPE:
case Kind.CHARGE:
currentPart.lines.push(Object.assign({}, line, { multiplier: 1 }));
break;
case Kind.COMMENT: // we ignore comments to create the parts and canonized MF

@@ -146,3 +147,3 @@ break;

}
if (expanded) part.lines = part.lines.filter(a => a);
if (expanded) part.lines = part.lines.filter((a) => a);
}

@@ -149,0 +150,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc