Defang / Refang — JavaScript source
Make URLs, IPs, and emails safe to paste by defanging indicators (https:// → hxxps[://], . → [.], @ → [@]) - and reverse refanged text back to its original form. Runs entirely in your browser, with a shareable link to your exact input and mode.
This is the JavaScript implementation — the same logic the interactive tool runs, in a shareable, citable form.
/**
* defang-refang - make URLs, IPs, and emails safe to paste (and reverse it).
*
* Language: JavaScript (ES2021+, runs unmodified in Node 16+ and modern
* browsers - `replaceAll` is the ES2021 primitive this port uses)
* Source: CosmoDev polyglot showcase port of the Defang/Refang tool, ported
* from src/lib/defang.ts (the canonical TypeScript implementation)
* and held in lock-step with cli/defang-refang/defang-refang.go.
* License: display source - part of CosmoDev's polyglot tool pages.
*
* Design goals:
* - Pure + deterministic; never throws.
* - Functionally equivalent to the TS / Go reference: same inputs -> same outputs.
* - Self-contained: stdlib only (no npm dependencies).
*
* Algorithm: `defang()` replaces `https://` / `http://` schemes with `hxxps[://]`
* / `hxxp[://]`, then brackets EVERY dot as `[.]` and every at-sign as `[@]` -
* the standard threat-intel indicator-defanging convention. `refang()` is its
* exact inverse: scheme markers are restored first, then `[.]` / `[@]` are
* unbracketed, so `refang(defang(x)) === x` for typical URLs, IPs, emails, and
* plain text.
*
* Ordering note: scheme replacements run BEFORE dot/at bracketing so the dots
* and colon inside the resulting `[://]` marker are not themselves re-bracketed
* (which would corrupt the scheme marker). Note that EVERY dot is bracketed, not
* just the domain separator - so defang is NOT idempotent by design: apply it
* once to fresh text. `String.prototype.replaceAll` with a string argument
* replaces every occurrence, matching the TS source one for one (this is the
* canonical TS lib's own implementation, mirrored here verbatim).
*/
'use strict';
/**
* Defang text so URLs, IPs, and emails are no longer clickable or auto-linked.
*
* Mirrors `defang()` in src/lib/defang.ts and `Defang()` in the Go twin, and
* must agree with both on every shared vector. Scheme replacements run first so
* the dots and colon inside the resulting `[://]` marker are not themselves
* re-bracketed. EVERY dot is bracketed, not just the domain separator. Empty
* input returns empty; text with no indicators passes through unchanged.
*
* @param {string} text
* @returns {string}
*/
function defang(text) {
return text
.replaceAll('https://', 'hxxps[://]')
.replaceAll('http://', 'hxxp[://]')
.replaceAll('.', '[.]')
.replaceAll('@', '[@]');
}
/**
* Reverse defanging - restore `hxxps[://]` / `hxxp[://]` to real schemes and
* unbracket `[.]` / `[@]`. Mirrors `refang()` in src/lib/defang.ts and
* `Refang()` in the Go twin: the exact inverse of `defang`.
*
* Scheme markers are restored before `[.]` / `[@]` are unbracketed, so a marker
* like `hxxps[://]` reassembles into `https://` rather than being split by an
* earlier dot/at substitution. Empty input returns empty.
*
* @param {string} text
* @returns {string}
*/
function refang(text) {
return text
.replaceAll('hxxps[://]', 'https://')
.replaceAll('hxxp[://]', 'http://')
.replaceAll('[.]', '.')
.replaceAll('[@]', '@');
}
// CommonJS export so the file is consumable from Node without a build step,
// while staying dependency-free and framework-agnostic.
module.exports = { defang, refang };
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →