DEV Community

Cover image for I made string-range-tokens (srTokens) — here’s what to use it for
FSCSS
FSCSS

Posted on Originally published at github.com

I made string-range-tokens (srTokens) — here’s what to use it for

A few days ago I had a simple, slightly weird idea:

What if every string was just an array of single letters… and I could rebuild words, paths, and API links by pointing at index ranges?

That experiment turned into string-range-tokens (srTokens).

It’s a tiny, zero-dependency ESM package that does one thing well:

Turn any string into a letter-per-index token array, then reassemble pieces of it with clean range calls.

No regex. No string slicing gymnastics. Just indexes.

The 30-second version

import { toTokens, sub, build } from 'string-range-tokens';

const t = toTokens('https://api.example.com/v1/users');

sub(t, 0, 4);                 // "https"
sub(t, 23, 25, [26, 31]);     // "/v1/users"
sub(t, -5, -1);               // "users"
build(t, [0, 4], [23, 25]);   // "https/v1"
Enter fullscreen mode Exit fullscreen mode

That’s the core. Everything else is built on top of it.


What you can actually use it for

1. Assemble API paths from a shared pool

Instead of hard-coding every endpoint, keep one master string and pull the parts you need:

const pool = toTokens('https://api.myapp.com/v1/users/orders/products/settings');

const users    = build(pool, [0, 22], [23, 27]);     // https://api.myapp.com/v1/users
const orders   = build(pool, [0, 22], [29, 34]);     // https://api.myapp.com/v1/orders
const products = build(pool, [0, 22], [36, 43]);     // https://api.myapp.com/v1/products
Enter fullscreen mode Exit fullscreen mode

Useful when you want a single source of truth for the base URL + version and then compose endpoints on the fly.

2. Build words from a letter pool (like a tiny anagram engine)

const letters = toTokens('the quick brown fox jumps over the lazy dog');

const ranges = plan(letters, 'fox jumps');
build(letters, ...ranges);   // "fox jumps"

plan(letters, 'lazy dog');   // finds the ranges
plan(letters, 'brown');      // finds "brown"
Enter fullscreen mode Exit fullscreen mode

plan() does a greedy longest-match search and returns the ranges that reconstruct the target. If a character is missing, it throws. Great for puzzles, teaching, or constrained string generation.

3. Negative indexes for “from the end” slicing

const t = toTokens('invoice-2026-10-09-final.pdf');

sub(t, -9, -1);     // "final.pdf"
sub(t, -14, -10);   // "10-09"
sub(t, 0, 6, [-9, -1]); // "invoice-final.pdf"
Enter fullscreen mode Exit fullscreen mode

Feels natural once you start thinking of the string as a fixed array.

4. Scatter & gather — deterministic scramble

Sometimes you want to shuffle a string in a repeatable way and still be able to put it back together:

const { pool, key } = scatter('/api/private/orders', 42);

console.log(pool.join(''));  
// something like "r/paeivtr/o/psordo" (order depends on seed)

gather(pool, key);  
// "/api/private/orders"  ← perfect round-trip
Enter fullscreen mode Exit fullscreen mode

Same seed always produces the same shuffle. Handy for demos, tests, or playful obfuscation (remember: this is not security).

5. Tiny templating from a fixed alphabet

const alphabet = toTokens('abcdefghijklmnopqrstuvwxyz0123456789-_.');

// build a fake ID
const id = build(alphabet, 
  [0, 0], [1, 1], [2, 2], [10, 10], [26, 26], [27, 27]
); // "abc k01" → wait, better with plan or explicit ranges

// or more expressively:
const ranges = plan(alphabet, 'user-42');
build(alphabet, ...ranges); // "user-42"
Enter fullscreen mode Exit fullscreen mode

You can keep a single character pool and generate many different strings from it.

6. Teaching indexing and ranges

Because everything is explicit indexes, it’s surprisingly good for explaining:

  • zero-based indexing
  • inclusive ranges
  • negative indexing
  • how Array.from handles Unicode
toTokens('a😳b');           // ['a', '😳', 'b']  — emoji is one token
sub(toTokens('hello'), 1, 3); // "ell"
Enter fullscreen mode Exit fullscreen mode

Students can see exactly which characters are being selected.


Full API at a glance

Function What it does
toTokens(str) String → array of single characters (Unicode-safe)
sub(tokens, s, e, …) Join one or more inclusive ranges
build(tokens, …ranges) Same idea, ranges-only style
plan(tokens, target) Find ranges that rebuild target
scatter(str, seed) Seeded shuffle → { pool, key }
gather(pool, key) Reconstruct original from scatter output

All functions are pure. Zero dependencies. Works in Node 18+, Deno, Bun, and modern browsers.

TypeScript types are included, and you can even import the .ts source directly if your runtime supports it.


Install

npm i string-range-tokens
Enter fullscreen mode Exit fullscreen mode

Or skip the install and just copy src/index.js — it’s a single file.

CDN:

import { toTokens, sub, build, plan, scatter, gather } 
  from 'https://cdn.jsdelivr.net/npm/string-range-tokens@1.0.0/src/index.js';
Enter fullscreen mode Exit fullscreen mode

Important note about “hiding” strings

This is string assembly, not encryption.

Anything that ends up in the browser can be read by the user. Never try to hide real API keys, tokens, or secrets with it. Keep those on the server (Node Functions services, Cloudflare Workers, etc.).

Use srTokens for clarity, composition, teaching, and fun — not for security theater.


Links

If you build something interesting with it — a path builder, a puzzle, a teaching demo, or something completely unexpected — I’d love to see it.

Happy ranging.

Top comments (0)