smiles-js 2.0.3 → 2.2.0

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.
Files changed (49) hide show
  1. package/API.md +162 -0
  2. package/README.md +39 -0
  3. package/docs/MIRROR_PLAN.md +204 -0
  4. package/docs/smiles.peggy +215 -0
  5. package/package.json +1 -1
  6. package/scripts/coverage-summary.js +1 -1
  7. package/src/codegen/branch-crossing-ring.js +27 -6
  8. package/src/codegen/interleaved-fused-ring.js +24 -0
  9. package/src/decompiler.js +236 -51
  10. package/src/decompiler.test.js +232 -60
  11. package/src/fragment.test.js +7 -2
  12. package/src/manipulation.js +409 -4
  13. package/src/manipulation.test.js +359 -1
  14. package/src/method-attachers.js +37 -8
  15. package/src/node-creators.js +7 -0
  16. package/src/parser/ast-builder.js +23 -8
  17. package/src/parser/ring-group-builder.js +14 -2
  18. package/src/parser/ring-utils.js +28 -0
  19. package/test-integration/__snapshots__/acetaminophen.test.js.snap +20 -0
  20. package/test-integration/__snapshots__/adjuvant-analgesics.test.js.snap +63 -1
  21. package/test-integration/__snapshots__/cholesterol-drugs.test.js.snap +437 -0
  22. package/test-integration/__snapshots__/dexamethasone.test.js.snap +31 -0
  23. package/test-integration/__snapshots__/endocannabinoids.test.js.snap +79 -2
  24. package/test-integration/__snapshots__/endogenous-opioids.test.js.snap +1116 -0
  25. package/test-integration/__snapshots__/hypertension-medication.test.js.snap +70 -1
  26. package/test-integration/__snapshots__/local-anesthetics.test.js.snap +97 -0
  27. package/test-integration/__snapshots__/nsaids-otc.test.js.snap +61 -1
  28. package/test-integration/__snapshots__/nsaids-prescription.test.js.snap +115 -2
  29. package/test-integration/__snapshots__/opioids.test.js.snap +113 -4
  30. package/test-integration/__snapshots__/steroids.test.js.snap +381 -2
  31. package/test-integration/acetaminophen.test.js +15 -3
  32. package/test-integration/adjuvant-analgesics.test.js +43 -7
  33. package/test-integration/cholesterol-drugs.test.js +127 -20
  34. package/test-integration/cholesterol.test.js +112 -0
  35. package/test-integration/dexamethasone.test.js +8 -2
  36. package/test-integration/endocannabinoids.test.js +48 -12
  37. package/test-integration/endogenous-opioids.smiles.js +32 -0
  38. package/test-integration/endogenous-opioids.test.js +192 -0
  39. package/test-integration/hypertension-medication.test.js +32 -8
  40. package/test-integration/local-anesthetics.smiles.js +33 -0
  41. package/test-integration/local-anesthetics.test.js +64 -16
  42. package/test-integration/mirror.test.js +151 -0
  43. package/test-integration/nsaids-otc.test.js +40 -10
  44. package/test-integration/nsaids-prescription.test.js +72 -18
  45. package/test-integration/opioids.test.js +56 -14
  46. package/test-integration/polymer.test.js +148 -0
  47. package/test-integration/steroids.test.js +112 -28
  48. package/test-integration/utils.js +4 -2
  49. package/todo +2 -3
@@ -39,6 +39,12 @@ describe('Cortisone Integration Test', () => {
39
39
  expect(code).toMatchSnapshot();
40
40
  });
41
41
 
42
+ test('generates valid verbose code via toCode()', () => {
43
+ const ast = parse(CORTISONE_SMILES);
44
+ const code = ast.toCode('v', { verbose: true });
45
+ expect(code).toMatchSnapshot();
46
+ });
47
+
42
48
  test('generated code is valid JavaScript', () => {
43
49
  const ast = parse(CORTISONE_SMILES);
44
50
  const code = ast.toCode('v');
@@ -46,14 +52,14 @@ describe('Cortisone Integration Test', () => {
46
52
 
47
53
  let factory;
48
54
  expect(() => {
49
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
55
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
50
56
  }).not.toThrow();
51
57
  expect(typeof factory).toBe('function');
52
58
  });
53
59
 
54
60
  test('codegen round-trip: generated code produces valid SMILES', () => {
55
61
  const ast = parse(CORTISONE_SMILES);
56
- const code = ast.toCode('v');
62
+ const code = ast.toCode('v', { verbose: true });
57
63
  const executableCode = stripExports(code);
58
64
  const varMatch = code.match(/export const (v\d+) = /g);
59
65
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -80,6 +86,12 @@ describe('Hydrocortisone Integration Test', () => {
80
86
  expect(code).toMatchSnapshot();
81
87
  });
82
88
 
89
+ test('generates valid verbose code via toCode()', () => {
90
+ const ast = parse(HYDROCORTISONE_SMILES);
91
+ const code = ast.toCode('v', { verbose: true });
92
+ expect(code).toMatchSnapshot();
93
+ });
94
+
83
95
  test('generated code is valid JavaScript', () => {
84
96
  const ast = parse(HYDROCORTISONE_SMILES);
85
97
  const code = ast.toCode('v');
@@ -87,14 +99,14 @@ describe('Hydrocortisone Integration Test', () => {
87
99
 
88
100
  let factory;
89
101
  expect(() => {
90
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
102
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
91
103
  }).not.toThrow();
92
104
  expect(typeof factory).toBe('function');
93
105
  });
94
106
 
95
107
  test('codegen round-trip: generated code produces valid SMILES', () => {
96
108
  const ast = parse(HYDROCORTISONE_SMILES);
97
- const code = ast.toCode('v');
109
+ const code = ast.toCode('v', { verbose: true });
98
110
  const executableCode = stripExports(code);
99
111
  const varMatch = code.match(/export const (v\d+) = /g);
100
112
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -121,6 +133,12 @@ describe('Prednisone Integration Test', () => {
121
133
  expect(code).toMatchSnapshot();
122
134
  });
123
135
 
136
+ test('generates valid verbose code via toCode()', () => {
137
+ const ast = parse(PREDNISONE_SMILES);
138
+ const code = ast.toCode('v', { verbose: true });
139
+ expect(code).toMatchSnapshot();
140
+ });
141
+
124
142
  test('generated code is valid JavaScript', () => {
125
143
  const ast = parse(PREDNISONE_SMILES);
126
144
  const code = ast.toCode('v');
@@ -128,14 +146,14 @@ describe('Prednisone Integration Test', () => {
128
146
 
129
147
  let factory;
130
148
  expect(() => {
131
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
149
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
132
150
  }).not.toThrow();
133
151
  expect(typeof factory).toBe('function');
134
152
  });
135
153
 
136
154
  test('codegen round-trip: generated code produces valid SMILES', () => {
137
155
  const ast = parse(PREDNISONE_SMILES);
138
- const code = ast.toCode('v');
156
+ const code = ast.toCode('v', { verbose: true });
139
157
  const executableCode = stripExports(code);
140
158
  const varMatch = code.match(/export const (v\d+) = /g);
141
159
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -162,6 +180,12 @@ describe('Prednisolone Integration Test', () => {
162
180
  expect(code).toMatchSnapshot();
163
181
  });
164
182
 
183
+ test('generates valid verbose code via toCode()', () => {
184
+ const ast = parse(PREDNISOLONE_SMILES);
185
+ const code = ast.toCode('v', { verbose: true });
186
+ expect(code).toMatchSnapshot();
187
+ });
188
+
165
189
  test('generated code is valid JavaScript', () => {
166
190
  const ast = parse(PREDNISOLONE_SMILES);
167
191
  const code = ast.toCode('v');
@@ -169,14 +193,14 @@ describe('Prednisolone Integration Test', () => {
169
193
 
170
194
  let factory;
171
195
  expect(() => {
172
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
196
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
173
197
  }).not.toThrow();
174
198
  expect(typeof factory).toBe('function');
175
199
  });
176
200
 
177
201
  test('codegen round-trip: generated code produces valid SMILES', () => {
178
202
  const ast = parse(PREDNISOLONE_SMILES);
179
- const code = ast.toCode('v');
203
+ const code = ast.toCode('v', { verbose: true });
180
204
  const executableCode = stripExports(code);
181
205
  const varMatch = code.match(/export const (v\d+) = /g);
182
206
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -203,6 +227,12 @@ describe('Methylprednisolone Integration Test', () => {
203
227
  expect(code).toMatchSnapshot();
204
228
  });
205
229
 
230
+ test('generates valid verbose code via toCode()', () => {
231
+ const ast = parse(METHYLPREDNISOLONE_SMILES);
232
+ const code = ast.toCode('v', { verbose: true });
233
+ expect(code).toMatchSnapshot();
234
+ });
235
+
206
236
  test('generated code is valid JavaScript', () => {
207
237
  const ast = parse(METHYLPREDNISOLONE_SMILES);
208
238
  const code = ast.toCode('v');
@@ -210,14 +240,14 @@ describe('Methylprednisolone Integration Test', () => {
210
240
 
211
241
  let factory;
212
242
  expect(() => {
213
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
243
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
214
244
  }).not.toThrow();
215
245
  expect(typeof factory).toBe('function');
216
246
  });
217
247
 
218
248
  test('codegen round-trip: generated code produces valid SMILES', () => {
219
249
  const ast = parse(METHYLPREDNISOLONE_SMILES);
220
- const code = ast.toCode('v');
250
+ const code = ast.toCode('v', { verbose: true });
221
251
  const executableCode = stripExports(code);
222
252
  const varMatch = code.match(/export const (v\d+) = /g);
223
253
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -244,6 +274,12 @@ describe('Dexamethasone Integration Test', () => {
244
274
  expect(code).toMatchSnapshot();
245
275
  });
246
276
 
277
+ test('generates valid verbose code via toCode()', () => {
278
+ const ast = parse(DEXAMETHASONE_SMILES);
279
+ const code = ast.toCode('v', { verbose: true });
280
+ expect(code).toMatchSnapshot();
281
+ });
282
+
247
283
  test('generated code is valid JavaScript', () => {
248
284
  const ast = parse(DEXAMETHASONE_SMILES);
249
285
  const code = ast.toCode('v');
@@ -251,14 +287,14 @@ describe('Dexamethasone Integration Test', () => {
251
287
 
252
288
  let factory;
253
289
  expect(() => {
254
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
290
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
255
291
  }).not.toThrow();
256
292
  expect(typeof factory).toBe('function');
257
293
  });
258
294
 
259
295
  test('codegen round-trip: generated code produces valid SMILES', () => {
260
296
  const ast = parse(DEXAMETHASONE_SMILES);
261
- const code = ast.toCode('v');
297
+ const code = ast.toCode('v', { verbose: true });
262
298
  const executableCode = stripExports(code);
263
299
  const varMatch = code.match(/export const (v\d+) = /g);
264
300
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -285,6 +321,12 @@ describe('Triamcinolone Integration Test', () => {
285
321
  expect(code).toMatchSnapshot();
286
322
  });
287
323
 
324
+ test('generates valid verbose code via toCode()', () => {
325
+ const ast = parse(TRIAMCINOLONE_SMILES);
326
+ const code = ast.toCode('v', { verbose: true });
327
+ expect(code).toMatchSnapshot();
328
+ });
329
+
288
330
  test('generated code is valid JavaScript', () => {
289
331
  const ast = parse(TRIAMCINOLONE_SMILES);
290
332
  const code = ast.toCode('v');
@@ -292,14 +334,14 @@ describe('Triamcinolone Integration Test', () => {
292
334
 
293
335
  let factory;
294
336
  expect(() => {
295
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
337
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
296
338
  }).not.toThrow();
297
339
  expect(typeof factory).toBe('function');
298
340
  });
299
341
 
300
342
  test('codegen round-trip: generated code produces valid SMILES', () => {
301
343
  const ast = parse(TRIAMCINOLONE_SMILES);
302
- const code = ast.toCode('v');
344
+ const code = ast.toCode('v', { verbose: true });
303
345
  const executableCode = stripExports(code);
304
346
  const varMatch = code.match(/export const (v\d+) = /g);
305
347
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -326,6 +368,12 @@ describe('Budesonide Integration Test', () => {
326
368
  expect(code).toMatchSnapshot();
327
369
  });
328
370
 
371
+ test('generates valid verbose code via toCode()', () => {
372
+ const ast = parse(BUDESONIDE_SMILES);
373
+ const code = ast.toCode('v', { verbose: true });
374
+ expect(code).toMatchSnapshot();
375
+ });
376
+
329
377
  test('generated code is valid JavaScript', () => {
330
378
  const ast = parse(BUDESONIDE_SMILES);
331
379
  const code = ast.toCode('v');
@@ -333,14 +381,14 @@ describe('Budesonide Integration Test', () => {
333
381
 
334
382
  let factory;
335
383
  expect(() => {
336
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
384
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
337
385
  }).not.toThrow();
338
386
  expect(typeof factory).toBe('function');
339
387
  });
340
388
 
341
389
  test('codegen round-trip: generated code produces valid SMILES', () => {
342
390
  const ast = parse(BUDESONIDE_SMILES);
343
- const code = ast.toCode('v');
391
+ const code = ast.toCode('v', { verbose: true });
344
392
  const executableCode = stripExports(code);
345
393
  const varMatch = code.match(/export const (v\d+) = /g);
346
394
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -367,6 +415,12 @@ describe('Fluticasone Integration Test', () => {
367
415
  expect(code).toMatchSnapshot();
368
416
  });
369
417
 
418
+ test('generates valid verbose code via toCode()', () => {
419
+ const ast = parse(FLUTICASONE_SMILES);
420
+ const code = ast.toCode('v', { verbose: true });
421
+ expect(code).toMatchSnapshot();
422
+ });
423
+
370
424
  test('generated code is valid JavaScript', () => {
371
425
  const ast = parse(FLUTICASONE_SMILES);
372
426
  const code = ast.toCode('v');
@@ -374,14 +428,14 @@ describe('Fluticasone Integration Test', () => {
374
428
 
375
429
  let factory;
376
430
  expect(() => {
377
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
431
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
378
432
  }).not.toThrow();
379
433
  expect(typeof factory).toBe('function');
380
434
  });
381
435
 
382
436
  test('codegen round-trip: generated code produces valid SMILES', () => {
383
437
  const ast = parse(FLUTICASONE_SMILES);
384
- const code = ast.toCode('v');
438
+ const code = ast.toCode('v', { verbose: true });
385
439
  const executableCode = stripExports(code);
386
440
  const varMatch = code.match(/export const (v\d+) = /g);
387
441
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -408,6 +462,12 @@ describe('Beclomethasone Integration Test', () => {
408
462
  expect(code).toMatchSnapshot();
409
463
  });
410
464
 
465
+ test('generates valid verbose code via toCode()', () => {
466
+ const ast = parse(BECLOMETHASONE_SMILES);
467
+ const code = ast.toCode('v', { verbose: true });
468
+ expect(code).toMatchSnapshot();
469
+ });
470
+
411
471
  test('generated code is valid JavaScript', () => {
412
472
  const ast = parse(BECLOMETHASONE_SMILES);
413
473
  const code = ast.toCode('v');
@@ -415,14 +475,14 @@ describe('Beclomethasone Integration Test', () => {
415
475
 
416
476
  let factory;
417
477
  expect(() => {
418
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
478
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
419
479
  }).not.toThrow();
420
480
  expect(typeof factory).toBe('function');
421
481
  });
422
482
 
423
483
  test('codegen round-trip: generated code produces valid SMILES', () => {
424
484
  const ast = parse(BECLOMETHASONE_SMILES);
425
- const code = ast.toCode('v');
485
+ const code = ast.toCode('v', { verbose: true });
426
486
  const executableCode = stripExports(code);
427
487
  const varMatch = code.match(/export const (v\d+) = /g);
428
488
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -449,6 +509,12 @@ describe('Fludrocortisone Integration Test', () => {
449
509
  expect(code).toMatchSnapshot();
450
510
  });
451
511
 
512
+ test('generates valid verbose code via toCode()', () => {
513
+ const ast = parse(FLUDROCORTISONE_SMILES);
514
+ const code = ast.toCode('v', { verbose: true });
515
+ expect(code).toMatchSnapshot();
516
+ });
517
+
452
518
  test('generated code is valid JavaScript', () => {
453
519
  const ast = parse(FLUDROCORTISONE_SMILES);
454
520
  const code = ast.toCode('v');
@@ -456,14 +522,14 @@ describe('Fludrocortisone Integration Test', () => {
456
522
 
457
523
  let factory;
458
524
  expect(() => {
459
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
525
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
460
526
  }).not.toThrow();
461
527
  expect(typeof factory).toBe('function');
462
528
  });
463
529
 
464
530
  test('codegen round-trip: generated code produces valid SMILES', () => {
465
531
  const ast = parse(FLUDROCORTISONE_SMILES);
466
- const code = ast.toCode('v');
532
+ const code = ast.toCode('v', { verbose: true });
467
533
  const executableCode = stripExports(code);
468
534
  const varMatch = code.match(/export const (v\d+) = /g);
469
535
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -490,6 +556,12 @@ describe('Mometasone Integration Test', () => {
490
556
  expect(code).toMatchSnapshot();
491
557
  });
492
558
 
559
+ test('generates valid verbose code via toCode()', () => {
560
+ const ast = parse(MOMETASONE_SMILES);
561
+ const code = ast.toCode('v', { verbose: true });
562
+ expect(code).toMatchSnapshot();
563
+ });
564
+
493
565
  test('generated code is valid JavaScript', () => {
494
566
  const ast = parse(MOMETASONE_SMILES);
495
567
  const code = ast.toCode('v');
@@ -497,14 +569,14 @@ describe('Mometasone Integration Test', () => {
497
569
 
498
570
  let factory;
499
571
  expect(() => {
500
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
572
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
501
573
  }).not.toThrow();
502
574
  expect(typeof factory).toBe('function');
503
575
  });
504
576
 
505
577
  test('codegen round-trip: generated code produces valid SMILES', () => {
506
578
  const ast = parse(MOMETASONE_SMILES);
507
- const code = ast.toCode('v');
579
+ const code = ast.toCode('v', { verbose: true });
508
580
  const executableCode = stripExports(code);
509
581
  const varMatch = code.match(/export const (v\d+) = /g);
510
582
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -531,6 +603,12 @@ describe('Cortisol Integration Test', () => {
531
603
  expect(code).toMatchSnapshot();
532
604
  });
533
605
 
606
+ test('generates valid verbose code via toCode()', () => {
607
+ const ast = parse(CORTISOL_SMILES);
608
+ const code = ast.toCode('v', { verbose: true });
609
+ expect(code).toMatchSnapshot();
610
+ });
611
+
534
612
  test('generated code is valid JavaScript', () => {
535
613
  const ast = parse(CORTISOL_SMILES);
536
614
  const code = ast.toCode('v');
@@ -538,14 +616,14 @@ describe('Cortisol Integration Test', () => {
538
616
 
539
617
  let factory;
540
618
  expect(() => {
541
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
619
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
542
620
  }).not.toThrow();
543
621
  expect(typeof factory).toBe('function');
544
622
  });
545
623
 
546
624
  test('codegen round-trip: generated code produces valid SMILES', () => {
547
625
  const ast = parse(CORTISOL_SMILES);
548
- const code = ast.toCode('v');
626
+ const code = ast.toCode('v', { verbose: true });
549
627
  const executableCode = stripExports(code);
550
628
  const varMatch = code.match(/export const (v\d+) = /g);
551
629
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -572,6 +650,12 @@ describe('Betamethasone Integration Test', () => {
572
650
  expect(code).toMatchSnapshot();
573
651
  });
574
652
 
653
+ test('generates valid verbose code via toCode()', () => {
654
+ const ast = parse(BETAMETHASONE_SMILES);
655
+ const code = ast.toCode('v', { verbose: true });
656
+ expect(code).toMatchSnapshot();
657
+ });
658
+
575
659
  test('generated code is valid JavaScript', () => {
576
660
  const ast = parse(BETAMETHASONE_SMILES);
577
661
  const code = ast.toCode('v');
@@ -579,14 +663,14 @@ describe('Betamethasone Integration Test', () => {
579
663
 
580
664
  let factory;
581
665
  expect(() => {
582
- factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', executableCode);
666
+ factory = createFunction('Ring', 'Linear', 'FusedRing', 'Molecule', 'RawFragment', 'Fragment', executableCode);
583
667
  }).not.toThrow();
584
668
  expect(typeof factory).toBe('function');
585
669
  });
586
670
 
587
671
  test('codegen round-trip: generated code produces valid SMILES', () => {
588
672
  const ast = parse(BETAMETHASONE_SMILES);
589
- const code = ast.toCode('v');
673
+ const code = ast.toCode('v', { verbose: true });
590
674
  const executableCode = stripExports(code);
591
675
  const varMatch = code.match(/export const (v\d+) = /g);
592
676
  const lastVar = varMatch[varMatch.length - 1].match(/export const (v\d+)/)[1];
@@ -2,6 +2,7 @@ import { parse } from '../src/parser/index.js';
2
2
  import {
3
3
  Ring, Linear, FusedRing, Molecule, RawFragment,
4
4
  } from '../src/constructors.js';
5
+ import { Fragment } from '../src/fragment.js';
5
6
 
6
7
  // Use indirect Function constructor access to satisfy linter
7
8
  // This is a legitimate use case for testing code generation
@@ -38,9 +39,10 @@ export function executeCode(code, returnVar) {
38
39
  'FusedRing',
39
40
  'Molecule',
40
41
  'RawFragment',
42
+ 'Fragment',
41
43
  `${code}\nreturn ${returnVar};`,
42
44
  );
43
- return factory(Ring, Linear, FusedRing, Molecule, RawFragment);
45
+ return factory(Ring, Linear, FusedRing, Molecule, RawFragment, Fragment);
44
46
  }
45
47
 
46
48
  /**
@@ -51,7 +53,7 @@ export function executeCode(code, returnVar) {
51
53
  */
52
54
  export function codegenRoundTrip(smiles) {
53
55
  const ast = parse(smiles);
54
- const code = ast.toCode('v');
56
+ const code = ast.toCode('v', { verbose: true });
55
57
 
56
58
  // Find the last variable name in the generated code
57
59
  const varMatches = code.match(/export (?:const|let) (v\d+)/g);
package/todo CHANGED
@@ -1,4 +1,3 @@
1
- repeat
2
- mirror
3
- HOSE integration
4
1
  Bile acid sequestrants
2
+ SSRI
3
+ Reactions