A fast, zero-dependency string builder for Node.js with ESM, CommonJS, and TypeScript support. Collects string parts in an array and joins them on toString() — avoiding the cost of repeated string concatenation.
npm install string-builder
const StringBuilder = require("string-builder");
import StringBuilder from "string-builder";
import StringBuilder from "string-builder";
const users = [ { name: "Alice", role: "admin" }, { name: "Bob", role: "editor" }, { name: "Carol", role: "viewer" }, ]; const sb = new StringBuilder("User Report") .appendLine() .appendLine("============"); for (const user of users) { sb.appendFormat("- {name:U} ({role})", user).appendLine(); } sb.appendLine("============") .appendFormat("Total: {0} users", users.length); console.log(sb.toString()); // User Report // ============ // - ALICE (admin) // - BOB (editor) // - CAROL (viewer) // ============ // Total: 3 users
const items = ["Home", "About", "Contact"]; const sb = new StringBuilder("<ul>").appendLine(); for (const item of items) { sb.appendFormat(" <li>{0}</li>", item).appendLine(); } sb.append("</ul>"); console.log(sb.toString()); // <ul> // <li>Home</li> // <li>About</li> // <li>Contact</li> // </ul>
const headers = ["id", "name", "score"]; const rows = [ { id: 1, name: "Alice", score: 95.5 }, { id: 2, name: "Bob", score: 87.0 }, { id: 3, name: "Carol", score: 91.3 }, ]; const sb = new StringBuilder() .appendJoin(headers, ",") .appendLine(); for (const row of rows) { sb.appendFormat("{id},{name},{score}", row).appendLine(); } console.log(sb.toString()); // id,name,score // 1,Alice,95.5 // 2,Bob,87 // 3,Carol,91.3
function buildQuery({ table, fields, limit }) { return new StringBuilder("SELECT ") .appendJoin(fields, ", ") .appendFormat(" FROM {0}", table) .appendFormat(" LIMIT {0}", limit) .toString(); } console.log(buildQuery({ table: "users", fields: ["id", "name", "email"], limit: 10 })); // SELECT id, name, email FROM users LIMIT 10
const sb = new StringBuilder(); // :U — uppercase sb.appendFormat("Hello, {0:U}!", "world").appendLine(); // → Hello, WORLD! // :L — lowercase sb.appendFormat("Status: {0:L}", "ACTIVE").appendLine(); // → Status: active // :n — thousand separator sb.appendFormat("Revenue: {0:n}", 1234567.89).appendLine(); // → Revenue: 1,234,567.89 // combined with named placeholders sb.appendFormat("{name:U} earned {amount:n}", { name: "alice", amount: 95000 }); // → ALICE earned 95,000
const sb = new StringBuilder("world"); sb.prepend("hello "); console.log(sb.toString()); // hello world sb.replace("world", "there"); console.log(sb.toString()); // hello there sb.append(" and back again").replaceAll("a", "@"); console.log(sb.toString()); // hello there @nd b@ck @g@in
const sb = new StringBuilder(); console.log(sb.isEmpty); // true console.log(sb.length); // 0 sb.append("hello world"); console.log(sb.isEmpty); // false console.log(sb.length); // 11
const sb = new StringBuilder(); for (const id of [1, 2, 3]) { sb.appendFormat("Processing item {0}...", id); console.log(sb.toString()); sb.clear(); } // Processing item 1... // Processing item 2... // Processing item 3...
const buf = Buffer.from([0x41, 0x42, 0x43]); // "ABC" const result = new StringBuilder() .append("string: ").append("hello").appendLine() .append("number: ").append(42).appendLine() .append("float: ").append(3.14).appendLine() .append("bool: ").append(false).appendLine() .append("buffer: ").append(buf).appendLine() .append("zero: ").append(0) .toString(); console.log(result); // string: hello // number: 42 // float: 3.14 // bool: false // buffer: ABC // zero: 0
Creates a new instance. Optionally accepts an initial value.
const sb = new StringBuilder("initial");
Adds a value to the beginning of the buffer. null and undefined are ignored.
new StringBuilder("world").prepend("hello ").toString(); // "hello world"
Appends any value. null and undefined are silently ignored. Falsy values like 0, false, and "" are accepted.
sb.append("text").append(42).append(false).append(Buffer.from([0x30]));
Appends a newline (\n on Unix, \r\n on Windows), then the optional value.
sb.appendLine(); // just a newline sb.appendLine("hello"); // newline + "hello"
Positional {0}, {1} or named {key} placeholder interpolation. Supports format specifiers after a colon. Use {{...}} to escape braces.
| Specifier | Effect | Example |
|---|---|---|
:U |
uppercase | {0:U} → "HELLO" |
:L |
lowercase | {0:L} → "hello" |
:n |
thousand separator | {0:n} → "1,234,567" |
sb.appendFormat("{0} + {1} = {2}", 1, 2, 3); // positional sb.appendFormat("Hello, {name}!", { name: "world" }); // named sb.appendFormat("{0:U} earned {1:n}", "alice", 95000); // with specifiers sb.appendFormat("{{0}} is literal"); // escaped → {0}
Appends array elements joined by a separator. Default separator is "".
sb.appendJoin(["a", "b", "c"], ", "); // "a, b, c" sb.appendJoin([1, 2, 3], " + "); // "1 + 2 + 3"
Replaces the first occurrence of search (string or RegExp) in the buffer.
sb.replace("foo", "bar"); sb.replace(/\d+/, "0");
Replaces all occurrences of search in the buffer. Automatically adds the g flag to RegExp if missing.
sb.replaceAll("foo", "bar"); sb.replaceAll(/\s+/, "-");
Clears the internal buffer.
sb.clear(); sb.toString(); // ""
Returns the accumulated string by joining all collected parts.
sb.append("a").append("b").append("c").toString(); // "abc"
Returns the total character count of the current buffer without calling toString().
new StringBuilder("hello").length; // 5
Returns true if nothing has been appended yet or after clear().
new StringBuilder().isEmpty; // true new StringBuilder("x").isEmpty; // false new StringBuilder("x").clear().isEmpty; // true (after clear)
All methods except clear() return this:
const result = new StringBuilder() .prepend("START: ") .append("hello world") .replace("world", "there") .appendLine() .appendJoin(["a", "b", "c"], ", ") .toString();
MIT © 2014 Halil İbrahim ŞAFAK