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

@youversion/usfm-references

v0.2.0

Published

A type-safe interface for parsing, validating, and generating USFM Bible reference strings (USFMRef, USFMRefRange), modelled after the URL() interface.

Readme

@youversion/usfm-references

Installation

yarn add @youversion/usfm-references

About

An attempt to have an interface to parsing and generating "USFM" strings, that we so commonly use around YouVersion.

Modelled after the URL() interface. Such that using the constructor directly to parse/validate a reference will throw an error, but using the exposed static .parse() method will quietly return null if the given string can't be parsed. See: https://developer.mozilla.org/en-US/docs/Web/API/URL.

Based on on our colloquial implementation of "USFM", which is based on https://ubsicap.github.io/usfm/identification/books.html and related standards.

For a more canonical specification of what is a "Valid USFM", and a suite of tests and validations, see https://github.com/youversion/usfm-references/blob/main/usfm_references/init.py and it's tests at https://github.com/youversion/usfm-references/blob/main/tests/test_valid.py.

Unfortunately, in an "offline" way, we can't possibly validate that a given Verse/Chapter is valid for a given Bible Version. So this parser is about ensuring a correct, specified format.

Quick start

import { USFMRef, USFMRefRange } from '@youversion/usfm-references';

// Chapters and Verses that are valid will give you an instance:
const validReference = new USFMRef('GEN.1.1')

// Instances have `.book` and `.chapter` and `.verse` properties, to get
// each distinct part of a valid USFM.
// They also directly convert to a canonical/normalized representation when
// cast to strings.
console.log(validReference.book) // "GEN"
console.log(validReference.verse) // "1"
console.log(validReference) // "GEN.1.1"

// Invalid references will throw a TypeError:
const thisLinesExplodes = new USFMRef('GEN.XYZ')

// If you don't want to deal with exceptions, use `.parse()`. It'll give you an
// instance if it's parseable, or `null` if not:
const maybeValid = USFMRef.parse(someValue)
if (maybeValid === null) {
    // ^ Was invalid / unable to parse.
}

// If you need to work with a range of verses, use `USFMRefRange()`:
const someRange = new USFMRefRange('GEN.1.1-5');
// Now, `someRange.verses` is an array of `USFMRef()` instances.
typeof someRange.verses[0] // USFM

// USFMRange has helpers to quickly get the first/last Verse:
console.log(someRange.first) // "GEN.1.1"
console.log(someRange.last.book) // "GEN"
console.log(someRange.last.verse) // "5"

// And when cast to string, provides a YV API canonical Plus Range representation:
console.log(someRange) // "GEN.1.1+GEN.1.2+GEN.1.3+GEN.1.4+GEN.1.5"

Usage

This library provides two classes for working with USFM references: USFMRef and USFMRefRange. Choosing the right class depends on whether you're working with a single verse reference or a range of verses.

USFMRef and USFMRefRange are distinct on purpose.

They can be relied on for type safety, and setting explicit expectations. (That said, USFMRef could represent a Verse OR a Chapter/Introduction. We can implement more granularity in the future if we need that kind of control.)

import { USFMRef, USFMRefRange } from '@youversion/usfm-references';

function processVerses(range: USFMRefRange) { /* ... */}

function expectsOnlySingleVerse(usfm: USFMRef) {
    if (usfm.verse === null) {
        throw new Error("Expected to receive a Verse, but got a Chapter instead.")
    }
}

function expectsOnlyChapterNoVerse(usfm: USFMRef) {
    if (usfm.verse) {
        throw new Error("Chapters only please!")
    }
}

USFMRef for Single Verse References

The USFMRef class is designed for representing and parsing single USFM verse references, like "GEN.1.1" or "EXO.3.15". Use this class when you need to work with individual verses.

Creating USFMRef Instances:

You can create a USFMRef instance by passing a valid USFM string to the constructor:

import { USFMRef } from '@youversion/usfm-references';

const gen11 = new USFMRef('GEN.1.1');
const exo315 = new USFMRef('EXO.3.15');
const john316 = new USFMRef('JHN.3.16');
const gen1 = new USFMRef('GEN.1'); // Chapter reference
const genIntro = new USFMRef('GEN.INTRO1'); // Intro chapter reference

Accessing Properties:

Once you have a USFMRef instance, you can access its properties:

// Continued from above example...

console.log(gen11.book);      // Output: "GEN"
console.log(gen11.chapter);   // Output: "1"
console.log(gen11.verse);     // Output: "1"

console.log(gen1.book);       // Output: "GEN"
console.log(gen1.chapter);    // Output: "1"
console.log(gen1.verse);      // Output: null

console.log(genIntro.book);  // Output: "GEN"
console.log(genIntro.chapter);  // Output: "INTRO1"
console.log(genIntro.verse);  // Output: null

Invalid USFM:

The USFMRef constructor will throw a TypeError if the input string is not a valid USFM reference. This helps catch errors early in your development process. Examples of invalid USFM include:

import { USFMRef } from '@youversion/usfm-references';

// Throws a TypeError:
new USFMRef('GEN.1.1.1'); // Too many parts
new USFMRef('gen.1.1');   // Book must be uppercase
new USFMRef('GEN.1.a');   // Verse must be a number
new USFMRef('GEN');       // Missing chapter
new USFMRef('GEN.1.1-2');   // Use USFMRange for ranges
new USFMRef('GEN.1.1+GEN.1.2');   // Use USFMRange for ranges

Parsing without Errors:

If you're unsure whether a string is a valid USFM reference, use the static USFMRef.parse() method. This method returns a USFMRef instance if the string is valid, or null if it's not. This prevents your code from throwing errors due to malformed input.

import { USFMRef } from '@youversion/usfm-references';

const usfmRef = USFMRef.parse('GEN.1.1'); // Returns a USFMRef instance
const invalidRef = USFMRef.parse('invalid-usfm'); // Returns null

if (usfmRef) {
  console.log(usfmRef.book); // Safe to access properties
}

if (invalidRef === null) {
    console.warn("Invalid USFM reference!");
}

USFMRefRange for Verse Ranges

The USFMRefRange class is used to represent and parse ranges of USFM verses, such as "GEN.1.1-5" or "EXO.3.15+EXO.3.16+EXO.3.17". Use this class when you need to work with multiple verses in a contiguous or explicitly listed sequence.

Creating USFMRefRange Instances:

You can create a USFMRefRange instance using a range string (dash or plus notation) or an array of USFM strings:

import { USFMRefRange } from '@youversion/usfm-references';

const range1 = new USFMRefRange('GEN.1.1-5'); // Dash range
const range2 = new USFMRefRange('EXO.3.15+EXO.3.16+EXO.3.17'); // Plus range
const range3 = new USFMRefRange(['GEN.1.1', 'GEN.1.2', 'GEN.1.3']); // Array of USFM strings

Accessing Verses:

The USFMRefRange class provides a verses property, which is an array of USFMRef instances representing the verses in the range:

// Continued from above example...

const verses = range1.verses;
verses.forEach(verse => {
  console.log(verse.book, verse.chapter, verse.verse);
});

console.log(range1.first.verse); // Output: "1" (first verse in the range)
console.log(range1.last.verse);  // Output: "5" (last verse in the range)
console.log(range2.first.verse); // Output: "15"
console.log(range2.last.verse); // Output: "17"

Invalid Ranges:

The USFMRefRange constructor will throw a TypeError for invalid range strings or arrays. Ensure that all verses in the range belong to the same book and chapter, and that the verses are contiguous (for dash ranges) or explicitly listed in the correct order (for plus ranges or arrays). Mixing range types in an array (e.g., dash and plus) is also not allowed.

import { USFMRefRange } from '@youversion/usfm-references';

// Throws a TypeError:
new USFMRefRange('GEN.1.1-5+GEN.1.7'); // Mixed range types
new USFMRefRange('GEN.1.1-GEN.2.1'); // Different chapters
new USFMRefRange('GEN.1.5-1'); // Invalid dash range order
new USFMRefRange(['GEN.1.1', 'GEN.2.1']); // Different chapters in array
new USFMRefRange(['GEN.1.1', 'GEN.1.2-3']); // Mixed range types in array
new USFMRefRange(['GEN.1.1', 123]); // Invalid type in array
new USFMRefRange([]); // Empty array
new USFMRefRange(123); // Invalid input type

Remember to use the USFMRef class for single verse references and the USFMRefRange class for ranges of verses. Using the correct class will help ensure that your code is clear, maintainable, and less prone to errors.

See the test suite for more usage examples.

Validation Helpers

This library also provides several helper functions to quickly validate different parts of a USFM reference. These can be useful for input validation or other checks within your application, when you don't need the granularity of using the classes directly.

validBook(maybeUsfmBook: string): boolean

Checks if a given string is a valid USFM book name (e.g., "GEN", "MAT", "1TI"). It only checks if the string is present in the list of valid book names; it doesn't validate the entire USFM string format.

import { validBook } from '@youversion/usfm-references';

console.log(validBook('GEN')); // true
console.log(validBook('gen')); // false (case-sensitive)
console.log(validBook('GEN.1')); // false (includes chapter)
console.log(validBook('ZZZ')); // false (invalid book name)

validVerse(maybeVerse: string): boolean

Checks if a given string is a valid USFM verse reference (e.g., "GEN.1.1"). It verifies that the string includes a book, chapter, and verse.

import { validVerse } from '@youversion/usfm-references';

console.log(validVerse('GEN.1.1')); // true
console.log(validVerse('GEN.1')); // false (chapter only)
console.log(validVerse('GEN.1.a')); // false (invalid verse number)
console.log(validVerse('GEN.1.1-2')); // false (range, not a single verse)

validChapter(maybeChapter: string): boolean

Checks if a given string is a valid USFM chapter reference (e.g., "GEN.1" or "1TI.INTRO01"). It confirms the string contains a book and chapter (or intro chapter), but not a verse.

import { validChapter } from '@youversion/usfm-references';

console.log(validChapter('GEN.1')); // true
console.log(validChapter('GEN.INTRO1')); // true (intro chapter)
console.log(validChapter('GEN.1.1')); // false (includes verse)
console.log(validChapter('GEN')); // false (book only)

These validation helpers provide a convenient way to perform quick checks on USFM strings in your code. They can be particularly helpful when dealing with user input or external data sources where the validity of USFM references might not be guaranteed.