@datagrok/helm 2.1.15 → 2.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/helm",
3
3
  "friendlyName": "Helm",
4
- "version": "2.1.15",
4
+ "version": "2.1.17",
5
5
  "author": {
6
6
  "name": "Oleksandra Serhiienko",
7
7
  "email": "oserhiienko@datagrok.ai"
@@ -15,8 +15,8 @@
15
15
  "helm/JSDraw/Pistoia.HELM-uncompressed.js"
16
16
  ],
17
17
  "dependencies": {
18
- "@datagrok-libraries/bio": "^5.33.2",
19
- "@datagrok-libraries/utils": "^2.5.0",
18
+ "@datagrok-libraries/bio": "^5.38.0",
19
+ "@datagrok-libraries/utils": "^4.0.17",
20
20
  "cash-dom": "^8.1.1",
21
21
  "datagrok-api": "^1.10.2",
22
22
  "dayjs": "^1.10.6",
@@ -9,7 +9,6 @@ import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
9
9
 
10
10
  import {findMonomers, parseHelm} from './utils';
11
11
  import {HelmMonomerPlacer} from './helm-monomer-placer';
12
- import {TAGS as helmTAGS} from './constants';
13
12
 
14
13
  const enum tempTAGS {
15
14
  helmSumMaxLengthWords = 'helm-sum-maxLengthWords',
@@ -45,7 +44,7 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
45
44
  if (!tableCol) return;
46
45
 
47
46
  const helmPlacer = HelmMonomerPlacer.getOrCreate(tableCol);
48
- const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex);
47
+ const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex!);
49
48
 
50
49
  const maxIndex = Object.values(lengths).length - 1;
51
50
  const argsX = e.offsetX - gridCell.bounds.x;
@@ -61,11 +60,11 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
61
60
  if (argsX >= sumLengths[mid] && argsX <= sumLengths[mid + 1]) {
62
61
  left = mid;
63
62
  found = true;
64
- } else if (argsX < sumLengths[mid]) {
63
+ } else if (argsX < sumLengths[mid])
65
64
  right = mid - 1;
66
- } else if (argsX > sumLengths[mid + 1]) {
65
+ else if (argsX > sumLengths[mid + 1])
67
66
  left = mid + 1;
68
- }
67
+
69
68
  if (left == right)
70
69
  found = true;
71
70
 
@@ -74,7 +73,9 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
74
73
  }
75
74
  left = (argsX >= sumLengths[left]) ? left : left - 1; // correct left to between sumLengths
76
75
 
77
- const seq: string = gridCell.cell.value;
76
+ const seq: string = !gridCell.cell.value ? '' : gridCell.cell.value
77
+ .replaceAll(helmGapStartRe, '{').replaceAll(helmGapIntRe, '.').replaceAll(helmGapEndRe, '}')
78
+ .replace('{*}', '{}');
78
79
  const monomerList = parseHelm(seq);
79
80
  const monomers = new Set<string>(monomerList);
80
81
  const missedMonomers = findMonomers(monomerList);
@@ -110,27 +111,31 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
110
111
  render(g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
111
112
  gridCell: DG.GridCell, cellStyle: DG.GridCellStyle
112
113
  ) {
113
- /* Can not do anything without tableColumn containing temp */
114
- let tableCol: DG.Column | null = null;
115
- try { tableCol = gridCell.tableColumn; } catch { }
116
- if (!tableCol) return;
117
-
118
114
  g.save();
119
115
  try {
116
+ /* Can not do anything without tableColumn containing temp */
117
+ let tableCol: DG.Column | null = null;
118
+ try { tableCol = gridCell.tableColumn; } catch { }
119
+ if (!tableCol) return;
120
+
120
121
  const grid = gridCell.gridRow !== -1 ? gridCell.grid : undefined;
121
122
  const missedColor = 'red';
122
123
  const monomerColor: string = '#404040';
123
124
  const frameColor: string = '#C0C0C0';
124
125
 
125
- const seq = gridCell.cell.value;
126
- const monomerList: string[] = parseHelm(seq);
126
+ const seq: string = !gridCell.cell.value ? '' : gridCell.cell.value
127
+ .replaceAll(helmGapStartRe, '{').replaceAll(helmGapIntRe, '.').replaceAll(helmGapEndRe, '}')
128
+ .replace('{*}', '{}');
129
+ const monomerList = parseHelm(seq);
127
130
  const monomers: Set<string> = new Set<string>(monomerList);
128
131
  const missedMonomers: Set<string> = findMonomers(monomerList);
132
+ const helmPlacer = HelmMonomerPlacer.getOrCreate(tableCol);
129
133
 
130
134
  if (missedMonomers.size == 0) {
135
+ helmPlacer.skipCell(gridCell.tableRowIndex!);
131
136
  const host = ui.div([], {style: {width: `${w}px`, height: `${h}px`}});
132
137
  host.setAttribute('dataformat', 'helm');
133
- host.setAttribute('data', gridCell.cell.value);
138
+ host.setAttribute('data', seq /* gaps skipped */);
134
139
  gridCell.element = host;
135
140
  //@ts-ignore
136
141
  const canvas = new JSDraw2.Editor(host, {width: w, height: h, skin: 'w8', viewonly: true});
@@ -153,8 +158,7 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
153
158
  g.transform(1, 0, 0, 1, x, y);
154
159
  g.font = '12px monospace';
155
160
  g.textBaseline = 'top';
156
- const helmPlacer = HelmMonomerPlacer.getOrCreate(tableCol);
157
- const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRow.idx);
161
+ const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex!);
158
162
 
159
163
  for (let i = 0; i < allParts.length; ++i) {
160
164
  const part: string = allParts[i];
@@ -167,11 +171,6 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
167
171
  printLeftOrCentered(sumLengths[i], 0, w, h, g, allParts[i], color, 0, true, 1.0);
168
172
  }
169
173
  }
170
- } catch (err: any) {
171
- const errMsg = err instanceof Error ? err.message : err.toString();
172
- const errStack = err instanceof Error ? err.stack : undefined;
173
- tableCol.setTag(helmTAGS.cellRendererRenderError, JSON.stringify({message: errMsg, stack: errStack}));
174
- throw err;
175
174
  } finally {
176
175
  g.restore();
177
176
  }
package/src/constants.ts CHANGED
@@ -1,27 +1,27 @@
1
1
  export const jsonSdfMonomerLibDict = {
2
- "monomerType": null,
3
- "smiles": null,
4
- "name": "MonomerName",
5
- "author": null,
6
- "molfile": "molecule",
7
- "naturalAnalog": "MonomerNaturalAnalogCode",
8
- "rgroups": "MonomerCaps",
9
- "createDate": null,
10
- "id": null,
11
- "polymerType": "MonomerType",
12
- "symbol": "MonomerCode"
13
- }
2
+ 'monomerType': null,
3
+ 'smiles': null,
4
+ 'name': 'MonomerName',
5
+ 'author': null,
6
+ 'molfile': 'molecule',
7
+ 'naturalAnalog': 'MonomerNaturalAnalogCode',
8
+ 'rgroups': 'MonomerCaps',
9
+ 'createDate': null,
10
+ 'id': null,
11
+ 'polymerType': 'MonomerType',
12
+ 'symbol': 'MonomerCode'
13
+ };
14
14
 
15
15
  export type WebEditorMonomer = {
16
- id: string, //symbol
17
- n: string, //name
18
- na: string, //natural analog
19
- type: string, //polymer type
20
- mt: string, //monomer type
21
- m: string, //molfile
22
- at: {[group: string]: string}, //substituents
23
- rs: number //number of substituents
24
- };
16
+ /** symbol */ id: string,
17
+ /** name */ n: string,
18
+ /** natural analog */ na?: string,
19
+ /** polymer type */type: string,
20
+ /** monomer type */ mt: string,
21
+ /** molfile */ m: string,
22
+ /** substituents */ at: { [group: string]: string },
23
+ /** number of substituents */ rs: number
24
+ };
25
25
 
26
26
  export const SMILES = 'smiles';
27
27
  export const RGROUPS = 'rgroups';
@@ -14,8 +14,8 @@ export const enum Temps {
14
14
  }
15
15
 
16
16
  export class HelmMonomerPlacer {
17
- private _allPartsList: string[][] = null;
18
- private _lengthsList: number[][] = null;
17
+ private _allPartsList: (string[] | null)[] | null = null;
18
+ private _lengthsList: (number[] | null) [] | null = null;
19
19
 
20
20
  private monomerLib: IMonomerLib;
21
21
 
@@ -25,15 +25,25 @@ export class HelmMonomerPlacer {
25
25
  constructor(public readonly col: DG.Column<string>) {
26
26
  this.col.dataFrame.onDataChanged.subscribe();
27
27
  this.monomerLib = getMonomerLib();
28
+ this.monomerLib.onChanged.subscribe(this.monomerLibOnChanged.bind(this));
29
+ }
30
+
31
+ public skipCell(rowIdx: number): void {
32
+ if (this._allPartsList === null)
33
+ this._allPartsList = new Array<string[] | null>(this.col.length).fill(null);
34
+ if (this._lengthsList === null)
35
+ this._lengthsList = new Array<number[] | null>(this.col.length).fill(null);
36
+
37
+ this._allPartsList[rowIdx] = [];
38
+ this._lengthsList[rowIdx] = [];
28
39
  }
29
40
 
30
41
  /** @param rowIdx Row index of the table {@link DG.DataFrame}, HelmMonomerPlacer is {@link DG.Column} based */
31
42
  public getCellAllPartsLengths(rowIdx: number): [string[], number[], number[]] {
32
43
  if (this._allPartsList === null)
33
- this._allPartsList = new Array<string[]>(this.col.length).fill(null);
34
-
44
+ this._allPartsList = new Array<string[] | null>(this.col.length).fill(null);
35
45
  if (this._lengthsList === null)
36
- this._lengthsList = new Array<number[]>(this.col.length).fill(null);
46
+ this._lengthsList = new Array<number[] | null>(this.col.length).fill(null);
37
47
 
38
48
  const [allParts, lengths] = this.getCellMonomerLengthsForSeq(rowIdx);
39
49
 
@@ -45,12 +55,17 @@ export class HelmMonomerPlacer {
45
55
  }
46
56
 
47
57
  private getCellMonomerLengthsForSeq(rowIdx: number): [string[], number[]] {
48
- const allParts: string[] = this._allPartsList[rowIdx] = this.getAllParts(rowIdx);
49
- const lengths: number[] = this._lengthsList[rowIdx] = new Array<number>(allParts.length);
50
-
51
- for (const [part, partI] of wu.enumerate(allParts)) {
52
- const partWidth: number = part.length * this.monomerCharWidth;
53
- lengths[partI] = partWidth;
58
+ let allParts: string[] | null = this._allPartsList![rowIdx];
59
+ if (allParts === null)
60
+ allParts = this._allPartsList![rowIdx] = this.getAllParts(rowIdx);
61
+
62
+ let lengths: number[] | null = this._lengthsList![rowIdx];
63
+ if (lengths === null) {
64
+ lengths = this._lengthsList![rowIdx] = new Array<number>(allParts.length);
65
+ for (const [part, partI] of wu.enumerate(allParts)) {
66
+ const partWidth: number = part.length * this.monomerCharWidth;
67
+ lengths[partI] = partWidth;
68
+ }
54
69
  }
55
70
 
56
71
  return [allParts, lengths];
@@ -58,17 +73,25 @@ export class HelmMonomerPlacer {
58
73
 
59
74
  getAllParts(rowIdx: number): string[] {
60
75
  const seq: string | null = this.col.get(rowIdx);
61
- const subParts: string[] = parseHelm(seq);
62
- return seq ? getParts(subParts, seq) : [];
76
+ const monomerList: string[] = seq ? parseHelm(seq) : [];
77
+ return seq ? getParts(monomerList, seq) : [];
63
78
  }
64
79
 
65
80
  getMonomer(monomerSymbol: any): Monomer | null {
66
- let res: Monomer = null;
81
+ let res: Monomer | null = null;
67
82
  for (const polymerType of this.monomerLib.getPolymerTypes()) {
68
83
  res = this.monomerLib.getMonomer(polymerType, monomerSymbol);
69
84
  if (res) break;
70
85
  }
71
- return res ?? null;
86
+ return res;
87
+ }
88
+
89
+ // -- Handle events --
90
+
91
+ private monomerLibOnChanged(_value: any): void {
92
+ this._lengthsList = null;
93
+ this._allPartsList = null;
94
+ // TODO: Invalidate all grids of this.col.dataFrame
72
95
  }
73
96
 
74
97
  public static getOrCreate(col: DG.Column<string>): HelmMonomerPlacer {
@@ -7,6 +7,7 @@ export class HelmWebEditor {
7
7
  editor: any;
8
8
  w = 200;
9
9
  h = 100;
10
+
10
11
  constructor() {
11
12
  this.host = ui.div([], {style: {width: `${this.w}px`, height: `${this.h}px`}});
12
13
  this.editor = new JSDraw2.Editor(this.host, {width: this.w, height: this.h, viewonly: true});
@@ -18,7 +19,9 @@ export class HelmWebEditor {
18
19
 
19
20
  createWebEditor(value: string) {
20
21
  const editorView = ui.div();
22
+ // @ts-ignore
21
23
  org.helm.webeditor.MolViewer.molscale = 0.8;
24
+ // @ts-ignore
22
25
  const webEditor = new scil.helm.App(editorView, {
23
26
  showabout: false,
24
27
  mexfontsize: '90%',
package/src/package.ts CHANGED
@@ -7,14 +7,15 @@ import {WebEditorMonomer, RGROUP_CAP_GROUP_NAME, RGROUP_LABEL, SMILES} from './c
7
7
  import {HelmWebEditor} from './helm-web-editor';
8
8
  import {HelmCellRenderer} from './cell-renderer';
9
9
  import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
10
- import {NotationConverter} from '@datagrok-libraries/bio/src/utils/notation-converter';
11
- import {findMonomers} from './utils';
10
+ import {GapSymbols, UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
11
+ import {findMonomers, parseHelm} from './utils';
12
12
  import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
13
13
  import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
14
14
 
15
- export const _package = new DG.Package();
16
15
  let monomerLib: IMonomerLib | null = null;
17
16
 
17
+ export const _package = new DG.Package();
18
+
18
19
  //tags: init
19
20
  export async function initHelm(): Promise<void> {
20
21
  return Promise.all([
@@ -24,17 +25,17 @@ export async function initHelm(): Promise<void> {
24
25
  }),
25
26
  grok.functions.call('Bio:getBioLib'),
26
27
  ])
27
- .then(([_, lib]: [void, IMonomerLib]) => {
28
+ .then(([_, lib]: [unknown, IMonomerLib]) => {
28
29
  monomerLib = lib;
29
30
  rewriteLibraries(); // initHelm()
30
31
  monomerLib.onChanged.subscribe((_) => {
31
32
  try {
32
33
  rewriteLibraries(); // initHelm()
33
34
 
34
- const monTypeList: string[] = monomerLib.getPolymerTypes();
35
+ const monTypeList: string[] = monomerLib!.getPolymerTypes();
35
36
  const msgStr: string = 'Monomer lib updated:<br />' + (
36
37
  monTypeList.length == 0 ? 'empty' : monTypeList.map((monType) => {
37
- return `${monType} ${monomerLib.getMonomerSymbolsByType(monType).length}`;
38
+ return `${monType} ${monomerLib!.getMonomerSymbolsByType(monType).length}`;
38
39
  }).join('<br />'));
39
40
 
40
41
  grok.shell.info(msgStr);
@@ -55,16 +56,17 @@ export async function initHelm(): Promise<void> {
55
56
  }
56
57
 
57
58
  export function getMonomerLib(): IMonomerLib {
58
- return monomerLib;
59
+ return monomerLib!;
59
60
  }
60
61
 
61
62
  function rewriteLibraries() {
63
+ // @ts-ignore
62
64
  org.helm.webeditor.Monomers.clear();
63
- monomerLib.getPolymerTypes().forEach((polymerType) => {
64
- const monomerSymbols = monomerLib.getMonomerSymbolsByType(polymerType);
65
+ monomerLib!.getPolymerTypes().forEach((polymerType) => {
66
+ const monomerSymbols = monomerLib!.getMonomerSymbolsByType(polymerType);
65
67
  monomerSymbols.forEach((monomerSymbol) => {
66
68
  let isBroken = false;
67
- const monomer: Monomer = monomerLib.getMonomer(polymerType, monomerSymbol);
69
+ const monomer: Monomer = monomerLib!.getMonomer(polymerType, monomerSymbol)!;
68
70
  const webEditorMonomer: WebEditorMonomer = {
69
71
  id: monomerSymbol,
70
72
  m: monomer.molfile,
@@ -78,7 +80,7 @@ function rewriteLibraries() {
78
80
 
79
81
  if (monomer.rgroups.length > 0) {
80
82
  webEditorMonomer.rs = monomer.rgroups.length;
81
- const at = {};
83
+ const at: { [prop: string]: any } = {};
82
84
  monomer.rgroups.forEach((it) => {
83
85
  at[it[RGROUP_LABEL]] = it[RGROUP_CAP_GROUP_NAME];
84
86
  });
@@ -86,12 +88,13 @@ function rewriteLibraries() {
86
88
  } else if (monomer[SMILES] != null) {
87
89
  webEditorMonomer.rs = Object.keys(getRS(monomer[SMILES].toString())).length;
88
90
  webEditorMonomer.at = getRS(monomer[SMILES].toString());
89
- } else {
91
+ } else
90
92
  isBroken = true;
91
- }
92
93
 
93
- if (!isBroken)
94
+ if (!isBroken) {
95
+ // @ts-ignore
94
96
  org.helm.webeditor.Monomers.addOneMonomer(webEditorMonomer);
97
+ }
95
98
  });
96
99
  });
97
100
 
@@ -110,10 +113,16 @@ export function helmCellRenderer(): HelmCellRenderer {
110
113
  }
111
114
 
112
115
  function checkMonomersAndOpenWebEditor(cell?: DG.Cell, value?: string, units?: string) {
113
- const cellValue = typeof units === 'undefined' ? cell.value : value;
114
- const monomers = findMonomers(cellValue);
115
- if (monomers.size == 0) { webEditor(cell, value, units); } else {
116
- grok.shell.warning(`Monomers ${Array.from(monomers).join(', ')} are absent! <br/>` +
116
+ const cellValue: string = !!cell && units === undefined ? cell.value : value;
117
+ const monomerList: string[] = parseHelm(cellValue);
118
+ const monomers = findMonomers(monomerList);
119
+ if (monomers.size === 0)
120
+ webEditor(cell, value, units);
121
+ else if (monomers.size === 1 && monomers.has(GapSymbols[NOTATION.HELM]))
122
+ grok.shell.warning(`WebEditor doesn't support Helm with gaps '${GapSymbols[NOTATION.HELM]}'.`);
123
+ else {
124
+ grok.shell.warning(
125
+ `Monomers ${Array.from(monomers).map((m) => `'${m}'`).join(', ')} are absent! <br/>` +
117
126
  `Please, upload the monomer library! <br/>` +
118
127
  `<a href="https://datagrok.ai/help/domains/bio/macromolecules" target="_blank">Learn more</a>`);
119
128
  }
@@ -133,13 +142,14 @@ export function editMoleculeCell(cell: DG.GridCell): void {
133
142
  //input: string mol { semType: Macromolecule }
134
143
  export function openEditor(mol: string): void {
135
144
  const df = grok.shell.tv.grid.dataFrame;
136
- const col = df.columns.bySemType('Macromolecule');
145
+ const col = df.columns.bySemType('Macromolecule')!;
146
+ const colUh = UnitsHandler.getOrCreate(col);
137
147
  const colUnits = col.getTag(DG.TAGS.UNITS);
138
148
  if (colUnits === NOTATION.HELM)
139
149
  checkMonomersAndOpenWebEditor(df.currentCell, undefined, undefined);
140
- const converter = new NotationConverter(col);
141
- const resStr = converter.convertStringToHelm(mol, '/');
142
- checkMonomersAndOpenWebEditor(df.currentCell, resStr, col.getTag(DG.TAGS.UNITS));
150
+ const convert = colUh.getConverter(NOTATION.HELM);
151
+ const helmMol = convert(mol);
152
+ checkMonomersAndOpenWebEditor(df.currentCell, helmMol, col.getTag(DG.TAGS.UNITS));
143
153
  }
144
154
 
145
155
  //name: Properties
@@ -148,7 +158,7 @@ export function openEditor(mol: string): void {
148
158
  //output: widget result
149
159
  export async function propertiesPanel(helmString: string) {
150
160
  const grid = grok.shell.tv.grid;
151
- const parent = grid.root.parentElement;
161
+ const parent = grid.root.parentElement!;
152
162
  const host = ui.div([]);
153
163
  parent.appendChild(host);
154
164
  const editor = new JSDraw2.Editor(host, {viewonly: true});
@@ -158,7 +168,7 @@ export async function propertiesPanel(helmString: string) {
158
168
  const formula = editor.getFormula(true);
159
169
  const molWeight = Math.round(editor.getMolWeight() * 100) / 100;
160
170
  const coef = Math.round(editor.getExtinctionCoefficient(true) * 100) / 100;
161
- parent.lastChild.remove();
171
+ parent.lastChild!.remove();
162
172
  return new DG.Widget(
163
173
  ui.tableFromMap({
164
174
  'formula': formula.replace(/<sub>/g, '').replace(/<\/sub>/g, ''),
@@ -171,8 +181,11 @@ export async function propertiesPanel(helmString: string) {
171
181
  function webEditor(cell?: DG.Cell, value?: string, units?: string) {
172
182
  const view = ui.div();
173
183
  const df = grok.shell.tv.grid.dataFrame;
174
- const converter = new NotationConverter(df.columns.bySemType('Macromolecule'));
184
+ const col = df.columns.bySemType('Macromolecule')!;
185
+ const uh = UnitsHandler.getOrCreate(col);
186
+ // @ts-ignore
175
187
  org.helm.webeditor.MolViewer.molscale = 0.8;
188
+ // @ts-ignore
176
189
  const app = new scil.helm.App(view, {
177
190
  showabout: false,
178
191
  mexfontsize: '90%',
@@ -196,7 +209,7 @@ function webEditor(cell?: DG.Cell, value?: string, units?: string) {
196
209
  app.structureview.resize(sizes.rightwidth, sizes.bottomheight + app.toolbarheight);
197
210
  app.mex.resize(sizes.topheight - 80);
198
211
  setTimeout(() => {
199
- if (typeof units === 'undefined')
212
+ if (!!cell && units === undefined)
200
213
  app.canvas.helm.setSequence(cell.value, 'HELM');
201
214
  else
202
215
  app.canvas.helm.setSequence(value, 'HELM');
@@ -207,31 +220,35 @@ function webEditor(cell?: DG.Cell, value?: string, units?: string) {
207
220
  .onOK(() => {
208
221
  const helmValue = app.canvas.getHelm(true).replace(/<\/span>/g, '')
209
222
  .replace(/<span style='background:#bbf;'>/g, '');
210
- if (typeof units === 'undefined') {
211
- cell.value = helmValue;
212
- } else {
213
- const convertedRes = converter.convertHelmToFastaSeparator(helmValue, units);
214
- cell.value = convertedRes;
223
+ if (!!cell) {
224
+ if (units === undefined)
225
+ cell.value = helmValue;
226
+ else {
227
+ const convertedRes = uh.convertHelmToFastaSeparator(helmValue, units!);
228
+ cell.value = convertedRes;
229
+ }
215
230
  }
216
231
  }).show({modal: true, fullScreen: true});
217
232
  }
218
233
 
219
234
  function getRS(smiles: string) {
220
235
  const newS = smiles.match(/(?<=\[)[^\][]*(?=])/gm);
221
- const res = {};
236
+ const res: { [name: string]: string } = {};
222
237
  let el = '';
223
238
  let digit;
224
- for (let i = 0; i < newS.length; i++) {
225
- if (newS[i] != null) {
226
- if (/\d/.test(newS[i])) {
227
- digit = newS[i][newS[i].length - 1];
228
- newS[i] = newS[i].replace(/[0-9]/g, '');
229
- for (let j = 0; j < newS[i].length; j++) {
230
- if (newS[i][j] != ':')
231
- el += newS[i][j];
239
+ if (!!newS) {
240
+ for (let i = 0; i < newS.length; i++) {
241
+ if (newS[i] != null) {
242
+ if (/\d/.test(newS[i])) {
243
+ digit = newS[i][newS[i].length - 1];
244
+ newS[i] = newS[i].replace(/[0-9]/g, '');
245
+ for (let j = 0; j < newS[i].length; j++) {
246
+ if (newS[i][j] != ':')
247
+ el += newS[i][j];
248
+ }
249
+ res['R' + digit] = el;
250
+ el = '';
232
251
  }
233
- res['R' + digit] = el;
234
- el = '';
235
252
  }
236
253
  }
237
254
  }
@@ -243,7 +260,7 @@ function getRS(smiles: string) {
243
260
  //output: column res
244
261
  export function getMolfiles(col: DG.Column): DG.Column {
245
262
  const grid = grok.shell.tv.grid;
246
- const parent = grid.root.parentElement;
263
+ const parent = grid.root.parentElement!;
247
264
  const res = DG.Column.string('mols', col.length);
248
265
  const host = ui.div([]);
249
266
  parent.appendChild(host);
@@ -255,7 +272,7 @@ export function getMolfiles(col: DG.Column): DG.Column {
255
272
  const mol = editor.getMolfile();
256
273
  return mol;
257
274
  });
258
- parent.lastChild.remove();
275
+ parent.lastChild!.remove();
259
276
  return res;
260
277
  }
261
278
 
package/src/utils.ts CHANGED
@@ -24,7 +24,7 @@ export function getParts(subParts: string[], s: string): string[] {
24
24
  return allParts;
25
25
  }
26
26
 
27
- export function parseHelm(s: string) {
27
+ export function parseHelm(s: string): string[] {
28
28
  const sections = split(s, '$');
29
29
  s = sections[0];
30
30
  const monomers = [];
@@ -181,8 +181,8 @@ function _detachAppendix(s: string, c: string) {
181
181
  }
182
182
  }
183
183
  if (tag != null)
184
- tag = tag.replace(new RegExp('\\' + c, 'g'), c);
185
- return {tag: unescape(tag), str: s};
184
+ tag = unescape(tag.replace(new RegExp('\\' + c, 'g'), c));
185
+ return {tag: tag, str: s};
186
186
  }
187
187
 
188
188
  function unescape(s: string) {
package/tsconfig.json CHANGED
@@ -25,7 +25,7 @@
25
25
  // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
26
26
 
27
27
  /* Strict Type-Checking Options */
28
- "strict": false, /* Enable all strict type-checking options. */
28
+ "strict": true, /* Enable all strict type-checking options. */
29
29
  // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
30
30
  // "strictNullChecks": true, /* Enable strict null checks. */
31
31
  // "strictFunctionTypes": true, /* Enable strict checking of function types. */
package/webpack.config.js CHANGED
@@ -13,11 +13,11 @@ module.exports = {
13
13
  },
14
14
  resolve: {
15
15
  fallback: {'url': false},
16
- extensions: ['.wasm', '.mjs', '.ts', '.js', '.json', '.tsx'],
16
+ extensions: ['.ts', '.tsx', '.js', '.wasm', '.mjs', '.json'],
17
17
  },
18
18
  module: {
19
19
  rules: [
20
- {test: /\.js$/, enforce: 'pre', use: ['source-map-loader']},
20
+ {test: /\.js$/, enforce: 'pre', use: ['source-map-loader'], exclude: /node_modules/},
21
21
  {test: /\.ts(x?)$/, use: 'ts-loader', exclude: /node_modules/},
22
22
  {test: /\.css$/, use: ['style-loader', 'css-loader'], exclude: /node_modules/},
23
23
  ],