textregexdiff
Text Processing Tools for Developers
· Cosyslabs
Text processing is one of the most frequent developer tasks — transforming, comparing, analyzing, and encoding strings is central to building APIs, content management systems, data pipelines, and user interfaces. The right tool for each operation saves time and reduces bugs from manual string manipulation.
String Case Conversion
const str = "hello world example";
// camelCase
str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, idx) =>
idx === 0 ? word.toLowerCase() : word.toUpperCase()
).replace(/\s+/g, "");
// "helloWorldExample"
// PascalCase
str.replace(/(?:^\w|[A-Z]|\b\w)/g, w => w.toUpperCase()).replace(/\s+/g, "");
// "HelloWorldExample"
// snake_case
str.replace(/\s+/g, "_").toLowerCase();
// "hello_world_example"
// kebab-case
str.replace(/\s+/g, "-").toLowerCase();
// "hello-world-example"
// SCREAMING_SNAKE_CASE
str.replace(/\s+/g, "_").toUpperCase();
// "HELLO_WORLD_EXAMPLE"
// Converting between cases
"helloWorldExample"
.replace(/([A-Z])/g, " $1")
.trim()
.toLowerCase()
.replace(/\s+/g, "-");
// "hello-world-example"
Word and Character Count
const text = "Hello, world! This is a test.";
// Character count (including spaces)
text.length; // 30
// Character count (excluding spaces)
text.replace(/\s/g, "").length; // 25
// Word count
text.trim().split(/\s+/).length; // 6
// Better — handle multiple spaces and punctuation
text.trim().split(/\s+/).filter(w => w.length > 0).length;
// Sentence count
text.split(/[.!?]+/).filter(s => s.trim()).length; // 2
// Reading time (250 words/minute average)
const wordCount = text.trim().split(/\s+/).length;
const readingTimeMinutes = Math.ceil(wordCount / 250);
text = "Hello, world! This is a test."
len(text) # 30 — characters
len(text.replace(" ", "")) # 26 — without spaces
len(text.split()) # 6 — words
String Escaping
Different contexts require different escaping strategies:
HTML Escaping
function escapeHtml(str) {
const map = {
"&": "&",
"<": "<",
">": ">",
'"': """,
"'": "'",
};
return str.replace(/[&<>"']/g, char => map[char]);
}
escapeHtml('<script>alert("XSS")</script>');
// "<script>alert("XSS")</script>"
JSON String Escaping
// JSON.stringify handles this for you
JSON.stringify("He said \"hello\"\nNew line");
// '"He said \\"hello\\"\\nNew line"'
// For embedding JSON in HTML
JSON.stringify(data).replace(/</g, "\\u003c").replace(/>/g, "\\u003e");
SQL String Escaping
Never build SQL by concatenating strings — use parameterized queries:
// WRONG — SQL injection vulnerability
db.query(`SELECT * FROM users WHERE name = '${userInput}'`);
// RIGHT — parameterized query
db.query("SELECT * FROM users WHERE name = $1", [userInput]);
Regex Escaping
function escapeRegex(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\amp;");
}
// Use when turning user input into a regex pattern
const userSearch = "price: $10.00 (sale)";
const pattern = new RegExp(escapeRegex(userSearch), "i");
Shell Command Escaping
// Node.js — never pass user input directly to shell
// Wrong:
const { exec } = require("child_process");
exec(`grep ${userInput} /var/log/app.log`); // Shell injection!
// Right:
const { execFile } = require("child_process");
execFile("grep", [userInput, "/var/log/app.log"]);
Text Diff
// diff package
import { diffLines, diffWords, createPatch } from "diff";
const before = "Hello\nWorld\nFoo";
const after = "Hello\nEarth\nFoo\nBar";
// Line-by-line diff
const lineDiff = diffLines(before, after);
lineDiff.forEach(part => {
const prefix = part.added ? "+" : part.removed ? "-" : " ";
process.stdout.write(prefix + part.value);
});
// Word-level diff
const wordDiff = diffWords("the cat sat on the mat", "the cat sat on the floor");
// Create unified diff (Git-style)
const patch = createPatch("file.txt", before, after, "before", "after");
import difflib
before = "Hello\nWorld\nFoo\n"
after = "Hello\nEarth\nFoo\nBar\n"
# Unified diff
diff = list(difflib.unified_diff(
before.splitlines(keepends=True),
after.splitlines(keepends=True),
fromfile="before",
tofile="after"
))
# Sequence matcher
matcher = difflib.SequenceMatcher(None, before, after)
ratio = matcher.ratio() # similarity ratio 0-1
Markdown Processing
// marked — lightweight Markdown parser
import { marked } from "marked";
import DOMPurify from "dompurify";
const markdown = "# Hello\n\nThis is **bold** and _italic_.";
// Parse to HTML
const rawHtml = marked.parse(markdown);
// Sanitize before inserting into DOM (critical for user content)
const safeHtml = DOMPurify.sanitize(rawHtml);
document.getElementById("output").innerHTML = safeHtml;
import markdown
md = "# Hello\n\nThis is **bold** and _italic_."
html = markdown.markdown(md, extensions=["extra", "codehilite"])
Lorem Ipsum Generation
Lorem ipsum is placeholder text used in layouts when real content is not yet available:
// Simple generator
const words = [
"lorem", "ipsum", "dolor", "sit", "amet", "consectetur",
"adipiscing", "elit", "sed", "do", "eiusmod", "tempor",
"incididunt", "ut", "labore", "et", "dolore", "magna", "aliqua"
];
function generateLorem(wordCount = 50) {
const result = [];
for (let i = 0; i < wordCount; i++) {
result.push(words[Math.floor(Math.random() * words.length)]);
}
const sentence = result.join(" ");
return sentence.charAt(0).toUpperCase() + sentence.slice(1) + ".";
}
String Truncation
// Simple truncation
function truncate(str, maxLength, suffix = "...") {
if (str.length <= maxLength) return str;
return str.slice(0, maxLength - suffix.length) + suffix;
}
// Word-aware truncation (avoid cutting mid-word)
function truncateAtWord(str, maxLength, suffix = "...") {
if (str.length <= maxLength) return str;
const truncated = str.slice(0, maxLength - suffix.length);
const lastSpace = truncated.lastIndexOf(" ");
return (lastSpace > 0 ? truncated.slice(0, lastSpace) : truncated) + suffix;
}
// CSS-only truncation (single line)
// overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
// CSS multi-line truncation (WebKit)
// overflow: hidden; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
Unicode and Emoji Handling
// String length is wrong for emoji!
"Hello 👋".length; // 8 (but visually 7 characters)
[..."Hello 👋"].length; // 7 (correct — spread uses Unicode code points)
// Count code points correctly
function countChars(str) {
return [...str].length;
}
// Reverse string correctly
function reverseString(str) {
return [...str].reverse().join("");
}
// Check for emoji
const hasEmoji = /\p{Emoji}/u.test(str);
// Normalize Unicode (e.g., for search/comparison)
const normalized = str.normalize("NFC"); // or NFD, NFKC, NFKD
Slug Generation
function slugify(str) {
return str
.toLowerCase()
.normalize("NFD") // decompose accents
.replace(/[̀-ͯ]/g, "") // remove accent marks
.replace(/[^a-z0-9\s-]/g, "") // remove non-alphanumeric
.trim()
.replace(/[\s_-]+/g, "-") // spaces to hyphens
.replace(/^-+|-+$/g, ""); // trim leading/trailing hyphens
}
slugify("Héllo Wörld! How are you?");
// "hello-world-how-are-you"
Text Statistics
function analyzeText(text) {
const words = text.trim().split(/\s+/).filter(Boolean);
const sentences = text.split(/[.!?]+/).filter(s => s.trim());
const paragraphs = text.split(/\n\n+/).filter(p => p.trim());
return {
characters: text.length,
charactersNoSpaces: text.replace(/\s/g, "").length,
words: words.length,
sentences: sentences.length,
paragraphs: paragraphs.length,
avgWordsPerSentence: (words.length / sentences.length).toFixed(1),
readingTimeMinutes: Math.ceil(words.length / 250),
speakingTimeMinutes: Math.ceil(words.length / 130),
};
}
Tools
- Text Diff Tool — compare two texts with highlighted changes
- Regex Tester — test patterns with real-time match highlighting
- Word Counter — character, word, sentence, and reading time stats
- Markdown Preview — render Markdown to HTML instantly
- Lorem Ipsum Generator — generate placeholder text
- String Escaper — escape for HTML, JSON, SQL, regex, and shell
- Case Converter — convert between camelCase, snake_case, kebab-case, and more