A combinatorial string generation library that creates all possible combinations from templates with variable elements.
npm install spintax
import parse from "spintax";
You can also import the library directly in your HTML file using a CDN:
<script type="module">
import parse from "https://cdn.jsdelivr.net/npm/spintax@1.1.2/src/index.mjs";
</script>
Note that https://ga.jspm.io/npm:spintax@1.1.2/src/index.mjs
is also available.
- String pattern parsing: Create string variations using intuitive pattern syntax
- Combinatorial expansion: Generate all possible combinations of variable elements
- Memory-efficient: Uses JavaScript iterators for lazy evaluation
- Multiple variable types: Choose from predefined options or numerical ranges
Spintax is a JavaScript library for generating all possible combinations of template strings with variable elements. It uses a simple, intuitive pattern syntax ({...}
) to define variables within templates.
import parse from "spintax";
// Basic usage with choices
const variations = parse("Hello, {world|friend|universe}!");
// Iterate through all combinations
for (const variation of variations) {
console.log(variation);
}
// Output:
// Hello, world!
// Hello, friend!
// Hello, universe!
// With numerical ranges
const counts = parse("Count: {1,5}");
// Generates: "Count: 1", "Count: 2", "Count: 3", "Count: 4", "Count: 5"
// Multiple variables
const products = parse("{Product|Service} #{1,3} ({Standard|Premium})");
// Generates all combinations: "Product #1 (Standard)", "Product #1 (Premium)", etc.
// Back references
const associations = parse(
"The {blue|straw|rasp}berries taste like {$0}berries)"
);
// Generates all combinations with back references: "The blueberries taste like blueberries", "The strawberries taste like strawberries", "The raspberries taste like raspberries", etc.
Define choices with the pipe (|
) separator:
parse("Color: {red|green|blue}");
// Generates: "Color: red", "Color: green", "Color: blue"
Define ranges with comma-separated numbers:
parse("Value: {1,5}");
// Generates: "Value: 1", "Value: 2", "Value: 3", "Value: 4", "Value: 5"
// With step value
parse("Value: {0,10,2}");
// Generates: "Value: 0", "Value: 2", "Value: 4", "Value: 6", "Value: 8", "Value: 10"
Multiple patterns in a template will generate all possible combinations:
parse("{small|large} {box|circle} in {red|blue}");
// Generates 8 combinations of size, shape and color
- In range patterns (containing numbers and commas), all whitespace is ignored
{1,5}
is the same as{ 1, 5 }
- In choices patterns (with
|
separators), whitespace is preserved as part of the option{option1|option2}
is different from{option1 |option2}
- In the second case, the first option is "option1 " (with a trailing space)
parse("https://example.com/{products|users}/{1,5}");
// Generates:
// https://example.com/products/1
// https://example.com/products/2
// ...
// https://example.com/users/5
parse("/api/v{1,3}/{users|items}/{1,100,10}");
// Generates:
// /api/v1/users/1
// /api/v1/users/11
// ...
// /api/v3/items/91
parse(
'{"timeout": {1000,5000,1000}, "retries": {1,3}, "mode": "{strict|lenient}"}'
);
// Generates valid JSON strings with all combinations of parameters
When multiple patterns are in a template, combinations are generated by iterating through the rightmost pattern first (inner loop), then the next one to the left, and so on:
parse("The color is {red|green|blue}. The letter is {A|B|C}");
// Produces:
// The color is red. The letter is A
// The color is red. The letter is B
// The color is red. The letter is C
// The color is green. The letter is A
// The color is green. The letter is B
// The color is green. The letter is C
// The color is blue. The letter is A
// The color is blue. The letter is B
// The color is blue. The letter is C
Be cautious when creating templates with many variable parts, as the number of combinations can grow exponentially:
- 3 variables with 4 options each: 4³ = 64 combinations
- 5 variables with 4 options each: 4⁵ = 1,024 combinations
- 10 variables with 4 options each: 4¹⁰ = 1,048,576 combinations
When dealing with extremely large sets of combinations, consider processing them in chunks:
const template = parse("..."); // Large combination space
const iterator = template[Symbol.iterator]();
const chunkSize = 1000;
function processNextChunk() {
let count = 0;
let result;
while (count < chunkSize && !(result = iterator.next()).done) {
process(result.value);
count++;
}
if (!result.done) {
// Schedule next chunk processing
setTimeout(processNextChunk, 0);
}
}
processNextChunk();
- Limit Pattern Count: Keep the number of variable patterns reasonable to avoid combinatorial explosion
- Use Meaningful Options: Create patterns that produce meaningful variations
- Process Lazily: Process combinations lazily when dealing with large result sets
While parse
is the primary function exported from the library, there are additional utility functions available for more advanced use cases:
import { compile, range, count } from "spintax";
For programmatic template creation with JavaScript expressions:
compile`Hello ${["world", "universe"]}!`;
Creates a numerical range generator:
range(1, 5); // 1, 2, 3, 4, 5
range(0, 10, 2); // 0, 2, 4, 6, 8, 10
Counts the number of combinations a template would generate:
count("Hello!"); // 1
count("Hello {world|people|nurse}!"); // 3
Produces a function that yields specific combinations based on the indexs passed to it:
const gen = choose("Hello {world|nurse}!");
gen(0); // "Hello world!"
gen(1); // "Hello nurse!"
Omitting the index returns a random combination:
gen(); // "Hello world!" or "Hello nurse!"
The library uses modern JavaScript features:
- Template literals
- Generator functions
- Iterable protocol
If you are migrating from version 0.0.x to 1.0.0, please note that the API has changed significantly.
- The
unspin
function has been replaced withchoose
.
Old:
import spintax from "spintax";
const result = spintax.unspin("{Hello|Hi} John!");
console.log(result); // "Hello John!" or "Hi John"
Current:
import { choose } from "spintax";
const result = choose("{Hello|Hi} John!");
console.log(result()); // "Hello John!" or "Hi John"
- The
countVariations
function has been replaced withcount
.
Old:
import spintax from "spintax";
const count = spintax.countVariations("{Hello|Hi} John!");
console.log(count); // 2
Current:
import { count } from "spintax";
const count = count("{Hello|Hi} John!");
console.log(count); // 2
MIT