A Regex Cheatsheet Where Every Entry Has Its Own Live Tester
Most regex cheatsheets show syntax but make you go to regex101 to actually test anything. In this one, every entry card has an editable pattern input, a test string textarea, and real-time match highlighting. 45 syntax entries across 9 categories plus 20 ready-made patterns (email, URL, IPv4, JP phone numbers, UUID, etc.).
Regex is the kind of thing you look up constantly and still get wrong. Is it \d or \D for non-digit? Does . match newlines? Is {3,} the same as {3} plus +? A cheatsheet that lets you test each construct immediately, on your own input, is much more useful than a static table.
🔗 Live demo: https://sen.ltd/portfolio/regex-cheatsheet/
📦 GitHub: https://github.com/sen-ltd/regex-cheatsheet
Features:
- 45 syntax entries in 9 categories
- 20 common patterns (email, URL, phone JP/intl, UUID, hex color, IPv4, etc.)
- Live tester on every entry (edit pattern and test text)
- Match highlighting with match count
- Flag validation
- One-click copy
- Japanese / English UI
- Zero dependencies, 47 tests
Safe regex compilation
User input is unpredictable. A syntactically invalid regex crashes new RegExp(), so all compilation goes through a wrapper:
export function safeCompile(pattern, flags = '') {
try {
return { regex: new RegExp(pattern, flags), error: null };
} catch (e) {
return { regex: null, error: e.message };
}
}
The UI checks result.error and shows a red message instead of crashing.
Finding and highlighting matches
export function findMatches(regex, text) {
const matches = [];
if (!regex) return matches;
const flags = regex.flags.includes('g') ? regex.flags : regex.flags + 'g';
const r = new RegExp(regex.source, flags);
let m;
while ((m = r.exec(text)) !== null) {
matches.push({
start: m.index,
end: m.index + m[0].length,
match: m[0],
groups: m.slice(1),
});
if (m[0].length === 0) r.lastIndex++; // avoid infinite loop on zero-width matches
}
return matches;
}
Two subtleties:
- The
gflag is forced soexecadvances. Without it, the loop runs forever on the first match. - Zero-width matches (like
^or\b) don't advancelastIndexautomatically, so we bump it manually.
Highlighting as segments
To render matches, we split the text into alternating "match" and "non-match" segments:
export function highlightMatches(text, matches) {
const segments = [];
let cursor = 0;
for (const m of matches) {
if (cursor < m.start) {
segments.push({ text: text.slice(cursor, m.start), isMatch: false });
}
segments.push({ text: m.match, isMatch: true });
cursor = m.end;
}
if (cursor < text.length) {
segments.push({ text: text.slice(cursor), isMatch: false });
}
return segments;
}
The UI renders each segment as a span with optional highlight class. This gives exact visual placement of every match without needing to escape HTML manually.
Common patterns
20 patterns covering the cases developers look up weekly:
-
Email:
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ -
JP Phone:
^0\d{1,4}-?\d{1,4}-?\d{4}$ -
IPv4:
^(\d{1,3}\.){3}\d{1,3}$ -
UUID:
^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ -
Hex color:
^#(?:[0-9a-fA-F]{3}){1,2}$ -
YYYY-MM-DD:
^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$
Each has an example string to try it on, so you can see it working before copying.
Series
This is entry #48 in my 100+ public portfolio series.
- 📦 Repo: https://github.com/sen-ltd/regex-cheatsheet
- 🌐 Live: https://sen.ltd/portfolio/regex-cheatsheet/
- 🏢 Company: https://sen.ltd/

Top comments (0)