npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

smarts-validator

v1.1.0

Published

A standalone, zero-dependency JavaScript validator for SMARTS (SMiles ARbitrary Target Specification) patterns and reaction SMARTS

Downloads

25

Readme

SMARTS Validator

A standalone, zero-dependency JavaScript validator for SMARTS (SMiles ARbitrary Target Specification) patterns and reaction SMARTS. Works in browsers (CDN) and Node.js.

Installation

NPM

npm install smarts-validator

CDN (Browser)

<script src="https://unpkg.com/smarts-validator/src/smarts-validator.js"></script>

Quick Start

Browser (Global)

<script src="https://unpkg.com/smarts-validator/src/smarts-validator.js"></script>
<script>
  const result = SMARTSValidator.validateSMARTS("[#6][CX3](=O)");
  // result = { valid: true, kind: "pattern", errors: [] }

  const bad = SMARTSValidator.validateSMARTS("C1CC");
  // bad = { valid: false, kind: null, errors: ["Unclosed ring closure ..."] }
</script>

Node.js (CommonJS)

const { validateSMARTS } = require('smarts-validator');

const result = validateSMARTS("[#6][CX3](=O)");
console.log(result);

ES Modules

import { validateSMARTS } from 'smarts-validator';

const result = validateSMARTS("[#6][CX3](=O)");
console.log(result);

API

The library exports:

| Export | Description | |--------|-------------| | validateSMARTS(input) | Main entry point. Returns { valid, kind, errors } | | SMARTSParser | Parser class (for advanced usage) | | SMARTSParseError | Custom error class with position info | | splitTopLevelReaction(input) | Reaction SMARTS splitter |

Return Value

{
  valid: boolean,       // true if the input is valid SMARTS
  kind: string | null,  // "pattern", "reaction", or null (on error)
  errors: string[]      // empty on success, descriptive messages on failure
}

Features

Pattern Validation

  • Bare atoms: C, c, n, O, [OH], *, A, a
  • Bracket atoms: [C], [#6], [C@H], [N+1], [!#6], [$(C=O)]
  • Atom expression operators: !, &, ,, ; with correct precedence
  • Bond types: -, =, #, :, ~, /, \
  • Bond expression operators: !, &, ,, ;
  • Ring closures: 19, %10%99, %(100)%(99999)
  • Branches: (...)
  • Fragment separation: .
  • Recursive SMARTS: $(...)
  • Chirality: @, @@, @TH1@TH2, @AL1@AL2, @SP1@SP3, @TB1@TB20, @OH1@OH30
  • Hybridization (OpenEye extension): ^0^8
  • Isotopes: [12C], [2H] (range 1–999)
  • Atom maps: :1, :2, ...
  • Charges: +, ++, +2, -, --, -3, +0, -0

Reaction SMARTS

  • Two-part: reactants>>products
  • Three-part: reactants>agents>products (single > separators)
  • Multi-component: CCO.O>>CC=O.O
  • Atom-mapped: [C:1][OH:2]>>[C:1]=[O:2]

Error Reporting

Every error includes the exact position and a visual pointer:

Unclosed ring closure "1" at position 4
C1CC
    ^

Comparison with Other Toolkits

vs RDKit

| Behavior | RDKit | This Validator | |----------|-------|---------------| | Empty string "" | Returns empty molecule (valid) | Rejected — must be non-empty | | Whitespace C C | Accepted | Rejected | | [#0] (atomic number 0) | Accepted | Rejected — range 1–118 | | [#119] (atomic number 119) | Accepted | Rejected — range 1–118 | | [C:0] (atom map 0) | Accepted | Rejected — must be ≥ 1 | | [^9] (hybridization) | Rejected (unknown token) | Rejected — range 0–8 | | [+0] / [-0] (zero charge) | Rejected | Accepted — valid explicit zero charge | | Conflicting ring bonds C=1CCCCC#1 | Accepted | Rejected — bond mismatch | | @TH3, @SP4, @AL3, @OH31 | Accepted silently | Rejected — out-of-range chirality | | Error messages | Generic "Failed parsing SMARTS" | Specific — describes exact issue with position |

vs OpenBabel

| Behavior | OpenBabel | This Validator | |----------|-----------|---------------| | ^ (hybridization) | Not supported | Supported (OpenEye extension, ^0^8) | | >> reaction SMARTS | Not supported as input | Supported | | reactants>agents>products | Not supported | Supported | | Conflicting ring bonds C=1CCCCC#1 | Rejected | Rejected (same) | | [+0] / [-0] | Rejected | Accepted |

Stricter-than-standard validations

These are intentionally stricter than Daylight spec (where the spec is ambiguous or permissive):

  • Empty input is rejected
  • Whitespace is rejected
  • Atomic numbers are clamped to 1–118
  • Atom map numbers must be ≥ 1
  • Isotope numbers are clamped to 1–999
  • Chirality permutation indices are range-checked
  • Conflicting ring closure bond types are rejected
  • Hybridization indices are clamped to 0–8

Running Tests

npm test

Or in browser:

<script src="src/smarts-validator.js"></script>
<script src="test/test.js"></script>
<script>
  const result = SMARTSTestSuite.runTestSuite();
  console.log(`Passed: ${result.passed}/${result.total}`);
</script>

Test Coverage

  • 55 positive pattern cases from OpenBabel's SMARTS library (functional group patterns)
  • 6 positive reaction cases (oxidation, substitution, mapped reactions, agents)
  • 36 negative cases covering syntax errors, range violations, structural errors, and derived malformed variants of positive cases

Architecture

The parser is a hand-written recursive descent parser (no code generation, no dependencies), with:

  • Operator precedence for atom expressions: OR (,) > low-AND (;) > high-AND (&/implicit) > unary (!) > primary
  • Operator precedence for bond expressions: OR (,) > AND (&/;) > unary (!) > primary
  • Implicit conjunction: adjacent atom primitives inside [] are implicitly ANDed (e.g., [OH] = O&H)
  • Backtracking-free: all decisions are made with 1-character lookahead
  • Ring closure tracking: pending ring openings are tracked and validated for conflicts

Project Structure

smarts-validator/
├── src/
│   └── smarts-validator.js     # Source (UMD module)
├── test/
│   └── test.js                 # Test suite (97 cases)
├── example/
│   └── index.html              # Browser demo
├── package.json
├── LICENSE
└── README.md

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

Licensed under the Apache License 2.0.