Socket
Socket
Sign inDemoInstall

@adraffy/ens-normalize

Package Overview
Dependencies
Maintainers
1
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@adraffy/ens-normalize - npm Package Compare versions

Comparing version 1.0.6 to 1.0.7

dist/ens-normalize.min.js

90

ens-normalize.js

@@ -30,31 +30,48 @@ class TableReader {

// from coder-v2.js
function bytes_from_base64(s) {
return Uint8Array.from(atob(s), c => c.charCodeAt(0));
}
function decode2(v) {
let buf = 0;
let n = 0;
let ret = [];
next: for (let x of v) {
buf = (buf << 8) | x;
n += 8;
while (n >= 3) {
switch ((buf >> (n - 2)) & 3) { // upper 2 bits
case 3:
if (n < 10) continue next;
ret.push((buf >> (n -= 10)) & 255);
continue;
case 2:
if (n < 6) continue next;
ret.push((buf >> (n -= 6)) & 15);
continue;
default:
ret.push((buf >> (n -= 3)) & 3);
}
}
}
return ret;
}
// compressed lookup tables
// Ignored/Disallowed/Mapped/Valid/Deviation [IdnaMappingTable.txt]
const TABLE_I = bytes_from_base64('gC0BgiEBlDsDAQGHewFUAQMB/wBeGxCAbwH/AD4gBP8LxNyAcA==');
const TABLE_D = bytes_from_base64('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');
const TABLE_N = bytes_from_base64('QRqAQmUXgH4BBzCCKQOE6gYRCAEJJFEDgA8AEIEqACA/gIEmgeKOIQacnogSK4W/AgNacwigqyIDhhZEA4ITBwQUCgM8gMkIuGAIBiAKCCAICCAIBiAaCECAhAa91wYKBwwEdoAbBIpKgqcJir1NGmAAGgCGljDXHoSHA7XZAAaA2gEDgNMBCgYAFYAwFAVrBwNYgFwDgCMDBRJ2Br74BAUoAgYUAAQO9/FQuh3O5AObCYKaBNPigEsK3zcHGmIGGgAqBuBSBAUoAgYUCwO/SQAGgNoBA4DTAQoGAwaAMAIGDAIGDAIDDAwEn7qDkyj/AUWwgAgkgOCAHAuA/gEPGAEHIIGjA/8BiGWERzP/AZaAi20gl4DVACD/ACvA5SAa/wJcfQAaAAAaAAAHAAESEAAaDwAaAA0EGgEICgAEIwMHDgELEAAaHQAaAAMEBgIIDAEHEgEaIwMEBgEFCgUHFAEaIwAaAAAaAAAaAAAaAAAaAAAaAAAaAAAaAAAaAAAaAAAaAAAaAAQRhiABByQBESMCBiYHESUBByQBESMCBiYHESUBByQBESMCBiYHESUBByQBESMCBiYHESUBByQBESMCBiYLCoanAAoAAAoAAAoAAAoAkIAi/wNSZIRoBP8DRj0cBABdAwIdAwCCAhqLRYomCmE=');
const TABLE_W = [
'gCqAQghdAQIChpIEhpUBfEaApAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQGDAIEAwYCBAIEBAgCBAIEAgQDBgIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAoBvAYB2AgQCBAKBlQKDQAGBHwIEAoEeAYEXAoEcAQIBgRUDgCIBgHgBBAGBEQKBHAEGAgwBAQGBHQSBLAEGAgYBgScCBAIEAoE2AYEvAoE2A4ErAoE2AYEvAoE0AQIBgS0CBAKBOAGBMQQIESICBAIEAgQCBAIEAgQCBAMGAgQCBAIEAgQCBAIEAgQCBAYMAoA/AVQBdAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAoCBAoCKAgQCBAIEAgQCBAIEAgQCBAjT5AHT0QKAwwHVGAPTxwKBAwGBkgEGAYAJAgQCBAIEAgRig00Bg3wBg3cBEAGDjgEEAQwBg5MBBCiDVAGDbQEOAQoBg7pcgFYBAgIkAoDMK4APAgQCgPMCgPwJgHgHgA0BhWkFhaoCAgECQBIBSQEMARoBEAEDAQkBCwIyAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAJpAQ4BBAIVAQUCgAYCaQFwZoBMAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQKFAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQDBgIEAgQCBAIEAgQCBAMGAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBAIEAgQCBIlekziBO7u4BgwvuCGLBJjTAQQBFAEGAQIBAAEQATIB/wDEUIAk/wDMUwGAigGAhwIEAQIBgnAKglsBgugBguUBBAEEAQIBBAErAYNeAQIBtOIBuL8BBAECAYNoAQQBAgGDaQIIAQQBgTwBgTcBg0oBtQQBAgG4zQEIAQIBuNABtNsBg3EBuN4Esj0BAgGGOwESAQYBAgGF+AECARwBCgECDoBsI4NVAYNdAYNkAYJJAYJYAYNrAYNyAQQBCAS1rAG1OwFf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',
'spbg2oAAFzZnRoAZ4HEhBsLiwsOAAQ=='
].map(bytes_from_base64);
const TABLE_I = decode2(bytes_from_base64('4DLTwWQnlM7ZPD72dULP/jXsbxDgNvP/jPsgk/+vxPc4DcM='));
const TABLE_D = decode2(bytes_from_base64('GWo1T41NjWTTmYyFngefm4DGmyZpSTih4DnTt5yZZkmc3oxuSbEcWPAaAcwWdrZbs7WYq844ia5cfp0o8BkJoSWLGclyKlJSUGRGVYymZpEsWM5RRSJlkSbM8hM+I1M0lnFjOUZVUWWjfIrJ5yzQksWM5RlVKSc7kRlWJVIzNmRokppt2SStmRGY3YrLaWcXOIKksyTotFSKqfFizi5qMqpLMk6mRkVRVtpZzMszSYgsaLOJPGDSSp2ZJiTRNUnZnUmO5KiTKcYJOLqUkzKpSZBpBySTJzkhvNuS8BkGTmUrgL1wG0GRTkmRZSZFkJkU5JkV5zkyLQ1kDxqbVlMuCBxx6zPi1OMU4pZaWVZmiyhVTVTTGc1zazPlcujVY+bJLJC8qUteWSY1NW8+WgnHVXNVNcsfzHTXl53SjPHe88nytV0ZXLwPLKZZMplQSSScfWamclszuRTSWysz3NTmxmiwk0PFSWa0piXWTJa8hvyHEWsrOoGiTgNQNq4HN8ZrxXFNC4XPnwG+rIDwHuy5aTKVnE6uximczmczmczmcznfsixo6zZwGrZXn51ZJbHLlZzM5UdUsxDROA/4yHED+GaPN6eA9zFOAzijgNLlRJlxjO3VNnFGjUWTbpXjz041yZCc3puVS2fGMcqmUympnM5zyTflVN1eSWYvJmPQcJwH3LasmnsllsNplJKKO+4hwFc3AdYs2nOQVLFCZVPiBU11RmMikNpJZJJJO/I2o1T41NjUmgnHnMplMm2WZ8RsONHEyjersi3uVyZa9YNrOX5dwCx15jfjkmSU49LlcuPHJZLsq4DHlVNkkmSSZRRmldhvM5RrN5nK0PgO3pxaqjGJjlRp0WZE5YUysXOkUU5hiZUuQvG5ToGcSYosyKloLOOpyVT0z6BkGTyWU5s8dWNy41PJZPqGk5vmduZz5dRVwHTY+cqLS07KKMqxbGsmxzFMXp06TJKc+MtuMz1TZqcSoyenYDileJHLNBnJMhvNc2dy1TSGhJYsZyjKakk0ZjLOp3LwFeuGXHtIoq4DJs2WTZFotdU1uJ51NVm2Nq+TF+AznPNk1OyhFUFHHilZTVo1Cy5V43pFGp26TwHD0nLTdVjryBYsbtJnKOWMlGmiqaYo5KUZp6uA7bGeAzc35lbweN7Nt5lr4DROJ8zY7eD6/j9R4Hx+hznge5nx81SaiapseU1WjVVGc4rLifBZhrey6XJnM+I6BLWruX3ijhNWyqnotnkM5R4Do8teIyUcDZxHCbXLa6Z6lRyPuZcsXp3TPOA3arJ1pVG4Yro3AY1ilmr04zwE+qnRykUlIbCTOdBMioM5xwyGUlzngPUXAdIuCz6+U38H6GP8BsM5xFTlGXgNVy13KqRcB4GP4jnUp4TYJzIUbzwGirEMp0ySqRcFyOiaZnvAaFIcbKJRNRkJJmMhJJLKJRJJJJKJUhnMhkJNRxGVmU4jmi4Djssk2Sy9Xm85LisuNcBJnGO25ZJTOrpuAxrg9YlxB2vdLNZnskN9kmcUVTZRRjyWncB6llylcrnpx11yzVVTUUT08BiZzfJauD4b/xk+wZBx/cz8Bry5ZXc52PF8/tBrPAZUc/OvnXuF2LkvL/+rbs14DcP/W/ch'));
const TABLE_N = decode2(bytes_from_base64('0HGuA0LZcX4DfjPmHBZS+E+qbEaDTkmovgLxiHA5UMgz/gOBybgfi47IZuc57iMSyvhe/T1rc6Og6vInw2LaI+CxOeTFKnnnAeTR3GwUTZBVRkFFGQUTZBjVGgcBwk3e+vNVPZJu3AY3JxWlcF09PFd7puNbAMaHDctmHr49wnDvtfZE3Ae0XwHpmqYYrwGYYpLtc71jgNcfAZG5cS3abvv4klyhTYoJLv3/HUO6x3zvkfN08FzUnp/FwGl1e/m8+NbFNjQyqb4NSklyhTYpW+/0kTcB7RfAemapnNwGYKaxTWJ2WSc/3XB8nlH/nRew4CjJOA+DgMcr4D/jfjBnyDgejf/niNl4TR8z/88twHF7bkHL8B6oyD/xlfgfLkGNf+tc30Y0BjQE4OJYgMavGNC2TGjRUJMjc9xrxAY1joxoOSZUWGfEjjWRuSYy1Sz4ocayMY0BjQGNAY0BjQGNAY0BjQGNAY0BjQGNCTEeGyAz5IcRyNTZNPiOSmfJDiORqbJp8RyUz5IcRyNTZNPiOSmfJDiORqbJp8RyUz5IcRyNTZNXVw3TioCoCoCochwGRf+9S2ThNok/96NnuOSDXWsdY4JY1xei8Vk1Ww8='));
const TABLE_W = [decode2(bytes_from_base64('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')), decode2(bytes_from_base64('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')), decode2(bytes_from_base64('4DPNi7/pu/58y9/03f9GV3/Rd/z/HZzz2+cAceWzcA8e5DO+g+QBzAcBtXfnHbsarpy7FeAt7/pu/5k19/03f8qr+/6bv+hJ7/pO/6Evv+m7/nTL3/Sd/zpff9F3/Ok9/0Hf86Z+/6bv+bJ7/nu/5s09/03f8uae/6Lv+XMvf893/Lk9/zXf8vJsQEmNYyJcex0TgCTGsZEuPY6Ltx7/qO/6HgMk8PcAHMBx/QeF/dGO7zs5/8admB/8adlo/8adlx/8adlq/8adli/8ab4uNYqqsQx/NPf/zgM0yFcBbwGPbGc1m4DFHwGI8BiW5nHeAyTNztNvAWPe+AVh4C3gLspWv51sU/AYvuWIya7wGLcBKa9w0E5bwGJZ7Joe4bGa9w1U37xwEsuVYrUbtV0BY1q23vINJ3ibK8oxR5jjtxsybTTlmZbmdC0TgJzoWjbys6x7RVlWWamck0LITj+hYisp3PgLjjOa4wcexrd6NqzDZTm2YZCaeAn4DInfluoSYzq9Vfwdaf/Gw8kf/Gw8eP/Gw8gf/Gw8ev/Gw8cf/Gw8fJ/42HjD/42Hj5v/Gw8Uf/Gw8fR/42HiD/42Hj6v/Gw8Mf/Gw8fZ/42HhD/42Hj7v/Gw8Ef/Gw8fiH/jYeAP/jYeNf/jYeSP/jYeNP/jYeQP/jYeNH/jYeOP/jYeNX/jYeMP/jYeNk/8bDxR/8bDkOIY60cikxvEt1OyYlud+wPFqTLkhxmnJDkqyQ14vkleMjdTsWKbqtyk3U7sNzOwYpua3CTczunheh4Xhu+rHTjE2OmzEsdORZDNkuITXuyeYqSV0CWXEvC77wvPOL+F9HhefVu5/8aX9R/8aX84/8aX9B/8aX86/8aX8x/8aX88n/jS/kP/jS/nm/8aX8R/8aX89H/jS/gP/jS/nq/8aX7x/8aX89n/jS/cP/jS/nu/8aX7R/8aX8+If+NL9g/+NL+V/+NL+o/+NL+U/+NL+g/+NL+Uf+NL+Y/+NL+Vf+NL+Q/+NL+WT/xpfxH/xpfyzf+NL+A/+NL+Wj/xpfvH/xpfy1f+NL9w/+NL+Wz/xpftH/xpfy3f+NL9g/+NL+OX/xpf1H/xpfxv/xpf0H/xpe914t/40fhKxMZRZlHFb1rNR1DWbOB0XgN8xyY5Dj0hyHIFrmmyZkc1mJcxLmzA5rRlxzXNsxLzbLzLm2Wl5ll5OZZeRmFRznMKDldZN1qNludHK8ky82ZJl5syTMTdkgOR5IDj94OIXg4hkAOQ25gchtzA5DfnhyvIstNmRZabMiByHIgcdxHODkt+XHHb8uON45l5xTHMvOKY4DjeOVHIcZzI4vjAOL4wDi+MUHHcWBxXFqjj+LUG/JcuM+S5cZZsvOVTAnLcwJy3OjXlucGnLwcwy8HMMry4nK8uJWXnLll5zDLycyy/MCMvzo05ijmGY5kRlrOZZblzGYyHMnmJzZgrMcwKzHODLmeZFZnmRWZ50ZTUZzQVSDVSDnNmcHP5M8OfyZ0c9ozg5/Rmxz3Nqjn+bUHOcyqOdrODnOZUHK6c2OT350crtzo5PiOdGvL88NaqIznOiM7zwimo0io3zVGfMc6N82XnLstzA4vjFRtkqM+Zo5hlucGvL8yLkBOX5kVmaJWdHOTnhpzHPDiNFR0OrOjbIDi+M5kcfyAHI6c4M+Z55lOU49wHOHgOfk4DnKOA7nHqv/Gp/P/7xbnsaxI5XjWKHLcaxY5fjWMHMcaxrWeAu4DJ8SPAYxwGU4keAxbgMnxQ8Bi3AZTinPfV/68PNfe8H3vEyT3vJFnAbl73efb2H29aT3e1d3s5Pebh3m2k+ttXrbOT/4Plf+D45Px/98f9k/+Lpv/FzJ8XEvFvJ+qb6n8=')), bytes_from_base64('n9e/5AAAAIB7v4G/pr+lARWADBkAABAaGQAAiBXDBAAAAIh0nG5eVmcBS4ASK2cBAoAiMW8CBE5QgAUED4AogCGAIgSAIXxLCgE5gAQFJAWAHXAKJAGAG3pVeAiAGXweXQQvIRZ4AmdmEoAFDEBYHwEGK2OAMmcKKnGAHlUGLHMWfAUbX3wMBCNpOFYBIzZnRgQBTQpGAwAiSyor7f6RtZ9p08gK/wByJQ8DFh8CwtDCw4ABHmLC5MLTB/8ASqyLADoABgE/ODUSASgvMCsBDB4VGAEnBCoHARUWDAUBAikiAgQngLaAyTo='), bytes_from_base64('sofg0CITgBplDjeAAHlyEQJlgAAEVwoCL3IRL1YBgAd4XS+AEgZvfGN2NwsdVoABcFUDGGMuHkYEK2eAEEsMAholFx+ACAIlUSB6IREZKndgGAMnFjNYIQwCDlUrgAJY4IEhBsLiwsM='), bytes_from_base64('spbg2oAAFzZnRoAZ4HEhBsLiwsOAAQ==')];
// CheckJoiners [DerivedGeneralCategory.txt]
const TABLE_M = bytes_from_base64('goBwgJMHgIctAQEBAgECAQFICzAVEAFlBwIGAgIBBCMBHhtbCzoJCQEYBAEJAQMBBSsDPAgqGAEhNgMBEgEHCgIdAzgBAQcCAgIDCQEKAhoBAgM4AQEFBAICAwMBHgIDAQsDOAEBCAEDAQMUAhYGAQM4AQEHAgICAwcDCgIeATsFAwMBBAkBKAU3AQEHAQMBBAcCCwIdAzgBAQcBAwEEBwILAhwENwIBBwEDAQQJAQoCHQNGAQQGAQEBCBICPQECBwwIYgECCQsGSgIbAQEBAQEEAjEUAQIFCwEkCQFkFBcEBAMBAwIHAwQNDAEBCgSCPwODMgQcAx0CHgJAIAkBLQMBAXUCIgF2DAQMgFsFOQoBHQIBMB8xBS8RJgkMAx4NOA4wFIAYAwEVBAEGAQIDgEZAglAhi34DgA0BYCCBqgZpAvVUBAEKIAJQAoCQAQMBBAEXBQQBUwIyEhoSDQEmCBkNLAQvDiQBQw4MAQgCLQMyAQEDAgIFAgEBKQUFAoBsCAECzrABgmEQEBCDTQGAYgGAFQWGBgMBAgUEKAMEAYAlAoG9BIEDAoAZCzEEegM1DykBAgIKBC0LBwE9AyQOEAIsAQwDMA4IBAECXAwGAYAgDBUENwIBBwICAgMJAQoCAgcDBYBAEhcBURSAawcCCRsCUhFqDWUPgIAPgHUGAQICBAEBAQKADQcCBwMBHAooBwEECAEJCy4QgRUIAQhSFgEOegYDAQECAQcBAUIFAQIBBYDbBMt5BTsHg5gBATcHBFEBCwLMKwKR4S4CF4GeBQMGCAgCBx4EgBQDhzs3BDIIAQ4BFgUBD4TQBwERAgcBAgEFgIUHgPcBPQSFYAdtB/8LmDWAcA==');
const TABLE_M = decode2(bytes_from_base64('4LgNw4Dk5+A4fLSSiidIrzDFcQOyzqZIyZGcexvW686ppOMSGksy5W88oyrGDkObM4kZ6ljrzgmdJOk1LGinnBMsiTZx5M1vOCaCy8UWLTF5wTOknO6ljxzuVsyUnKJc3JnLMk6rWOvOCZyzJOq1jkmbozlmSk1LHXoxkmJNGJLPSp7KNiKprm0pY2SSZFmOKFS1nJKTsmKYvJIy1O5LbCapOCz98HmUmOPHVjy0DIKTlrJ3VZEd2sks4DW5c5qOOo5hj+Yy5fiOTU2PHrc4uzDFOAxhnFZDMU+A0bQOC1DIeL358BadgyDgeqm2lfrqkhqyBaguA5AsyHF5ZDqazLEsaxK05NRjNuWSZfdkh0O6w0LLXmRLSlROUyyrgNsoK87sDwWw4hiGIcHpp4DYjwGKy8NMypZMoch4DJVwPeycC1wGM15jJvTzW/KSlVJltc5z15JdiCyw2PMLqJCtcsmPAZBZismbozpJ0mpKdy8BoGJYudRxTgNrnVONrUsR2q3Zb+A4C/gN1mKUhJXAWzqdnHKsonMlBpry7EOBxWg0alixu3qZkozk6FKUZeA9uTy95lzufg+YJzeeTUTWvMytcj8OXLF+B56VzUUKfHpOAxR8PnebyZlQbji0pv4T0JziKnKMvAcLPwH7nPZOF2CfbZ//r5jNeA3D'));
// CONTEXTJ [DerivedCombiningClass.txt, DerivedJoiningType.txt]
const TABLE_V = bytes_from_base64('iM2AAIAAgACAAIAAgACAAG4BEX1wgACASoA1AYZaAR+AHoIOgGRmAUcBkQz6ByaAGIAPbYC2gHfd0oWHKg86egGADHWANWOAdYAAgH2AAHd1gI6AhAGAIlQTUoEmgIUBUg==');
const TABLE_LD = bytes_from_base64('haABBQEBAQEFBA0BBwECIwIIEBImAQIJAQEBAQIoAwIBEgMFBAEJAQEBAQECHwsDDwIEAQECAwIGSiFWBQIBAQoBAQoBAQQCAR0BAgUSCgUCAgYBD46+ARhZDiIBAf8AEBUz4c0FCAEFCgEDCgSAEQEBAQMDAQIBAQIBHAKA0SIBAYGMAwERDAMcBAIMLgEBAgQBAgIBAgEBAgEFAv8AWbRE');
const TABLE_RD = bytes_from_base64('haABAR4BCiMCAQMBXwEBGAIKAwIBEAEBHh0zSiFVGQcBAQQBBAUTAwECBhENARuOvgEYWQ4iAQH\/ABAVMuHOBgEBAQIDCQEKAgEGBYAQEhcGgNIjgYwVDAQbEi4BAQUBCAEEBAL/AFm1RA==');
const TABLE_T = bytes_from_base64('gC0BgdJwgJMHgIctAQEBAgECAQFICwEBLhUQAWUHAgYCAgEEIQEBAR4bWws6CQkBGAQBCQEDAQUrAzwIKhgBIDcBAQEECAQBAwcKAh0BOgEEBAgBFAIaAQICOQEEAgQCAgMDAR4CAwELAjkBBAUBAgQBFAIWBgEBOgECAQEECAEHAgsCHgE9AQwBMgEDATcBAQMFAwEEBwILAh0BOgECAQYBBQIUAhwCOQIEBAgBFAIdAUgBBwMBAVoBAgcMCGIBAgkLBkoCGwEBAQEBNw4BBQECBQsBJAkBZgQBBgECAgIZAgQDEAQNAQICBgEPAYI\/A4MyAx0CHgIeAkACAQcIAQILCQEtAwEBdQIiAXYDBAIJAQYDgFsCAgE6AQEHAQEBAQIIBgoCATAfMQQwAQEFAQEFASgJDAIgBAICAQM4AQECAwEBAzoIAgKAGAMBDQEHBAEGAQMCgEZAgYsBAgIaBTEFBQZgIYt+A4ANAWAggaoEawL1VAQBCiACUAKAkAEDAQQBGQIFAYAXAhoSDQEmCBkLLgMwAQIEAgInAUMGAgICAgwBCAEvATMBAQMCAgUCAQEqAggBgG4BAgEEAc6wAYJhEBAQgE8BgHkDgYEBgGIBgBUFhgYDAQIFBCgDBAGAJQKBvQSBAwKAGQsxBHsBNg8pAQICCgMxBAICBwE9AyQFAQg+AQwCNAkKBAIBXwMCAQECBgGAIAEDCBUCOQIDASUHAwWAQwgCAwEBFwFUBgEBBAIBAoBuBAYCAQIbAlUIAgEBAmoBAQECBgEBZQMCBAEFgIMJAQKAgAIBAQQBgBAEAgIEASAKKAYCBAgBCQYCAy4NAQKBFgcBBgEBUhYCBwECAQJ6BgMBAQIBBwEBSAIDAQEBgNsClLsJtjcFOweDmAE\/BFEBzDgCAQSR3C4CF4GgAwkQAgceBIAUA4c7NwQyCAEOARYFAQ+E0AcBEQIHAQIBBYCFB4D3AT0EhWAHbQj\/C5c1AR5ggACAcA==');
const TABLE_LD = decode2(bytes_from_base64('4XoDKSTLJaZysjVGIYlkxVJJKyho4k5ZDSSSVj9bvUhKam0rIdWlRNRNRMiOOlS4lVKlMb+O744xrN2RE/+MQxXM/h82Wgy1F1ScBiJJbKJRxxcB6ORE8DxjOI2PHJFZlxKkKRRKMq/8az2miQ=='));
const TABLE_RD = decode2(bytes_from_base64('4XoCceNWRos6+TjCqaOIE49juZ6VkOq4zOTIZJcTZU2I2nG+O744xrN2RE/+MQxXMvh86Ykp0mpGaXgMQxLF5uA9LI+B4zFbJMbxLLiZTQZJF/41ntdE'));
const TABLE_T = decode2(bytes_from_base64('4DLTwPpbhwHJz8Bw+WklFE6RWTl2K4gdlnUyRkyEk49jet151TScYkNJZlyt55RlWMHIM3JMlEhc9Sx050ZJKDiixopZyZFIk2ceTNazkySlSHFFi0xOdFEyUGdVrHjnpsOZFnNyXKzJOq1jpzoozGVYoscWcqSSg4osdOkGdk60VPZRsRVNc2lLGySTm9xlKlrOSUnZpDMUljKkeISWlKY3ngs/fB5k8dWPLHloCM9BVdJy1k7qsiO7ORUmZ8BraRzomcklUTVI5hj+YyZgTKTKcopsWQSJF5wSmS86oS4DGGbTPIZi1wGjaBwPFlLGpcxllm2DIeL358BadgyDgeqk2tfrqkhqyBaguA5AsyHGVKeAxdY1iVpyajGa8ueYFSJZOdDmSSsNBy85mS0pUTlSoPAbcUZD53YHgthxDEMQ4DTzwG8vgeBPAbEeAxWXhpmVLJlDkPAZKuB72TgWuAxmvMZN7ObX5SUqnmMiU5z15JKaM+NizSmqRHX2iVMeAyAujFVnKZyWdy8BodCZOLnVJiZEVwG3STIrG1qtCJW1ElTE7K1IZeA4OkrgOARMh4DEJEpDkFWUTKSg0zJ5daVwOLTmYnUsWU5RW9TMlGcnSEyTwHtrlO7p7bN5c7n4PmDn8monzM4Rk5H3MuWL8D0DpxBT49JwGKPh87zeTMqDccWlN/CehOcRU5Rl4DhZ+A/c57JwuwT7bR/9fL5qce2DgBwG4Q=='));
// emoji-zwj-sequences.txt
const EMOJI = decode_zwnj_emoji('DAcV/wNpUAAAAAAAAAIAAAAAzkj/AxqIAAACAAD/AxqJAP8DGooAAP8DaZZJAgABAgBIAEkCAP8DaVADAAIBAAICAgUAAhAFBf8DaVAAAAAAAAAAAgAAAAAAAIpQzkj/AxqEAgACAAIA/wMaiQD/AxqEAgAEAIjo/wNpUAMAAgECAQICAgUAAgECilQUBQL/A3ZiAAAAAAAAAAAAAAAAAAAAAAAAAP8DaHYAAAACAAAAAgAAAAIAAAACAAAA/wN2ZAAAAAAAAAAAAAAAAAAAAAAAAAD/A2h4AgICBwQCAgcCBAIHAgIEBwICAl8JKv8DaVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIpQAAAAAAAAAAAAAAAAAAAAAAAAAP8DaHYAAAAAAgAAAAACAAAAAAIAAAAAAgAAAAAHAAAAAAAAAAAAAgAAAAAAAAAAAAIAAAAAAAAAAAACAAAAAAAAAAAAAgAAAAAAAAAAAAcAAAACAAAAAgAAAAIAAAACAAAAzkgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wNplgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/A2lQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAEAAAAAAgAAAAABAAAAAAIAAAAAAQAAAAACAAAAAAEAAAAAAgAAAACKUAAAAAAAAAAAAAAAAAAAAAAAAAD/A2h2AgICAgcCAgICBwICAgIHAgICAgcCAgICBwICAgIHAgICAgcCAgICBwICAgIHAgICAgcCAgICBwICAgIHAgICAgcCAgICBwICAgIFAgICBwQCAgcCBAIHAgIEBwICAoA0Bwr/A2lQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wNodgAAAAAAAAAAAgAAAAAAAAAAAgAAAAAAAAAAAgAAAAAAAAAAAgAAAAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAgAAAAAAAAAAAgAAAAAAAAAAAgAAAAAAAAAAAgAAAAAAAAAAzkgAAAAA/wMj8gAAAP8DI/EAAAAA/wMj8gAAAP8DI/EAAAAA/wMj8gAAAP8DI/EAAAAA/wMj8gAAAP8DI/EAAAAA/wMj8gAAAP8DI/EAAAAAAAAAAAD/AyPyAAAAAAAAAP8DI/EAAAAAAAAAAAD/AyPyAAAAAAAAAP8DI/EAAAAAAAAAAAD/AyPyAAAAAAAAAP8DI/EAAAAAAAAAAAD/AyPyAAAAAAAAAP8DI/EAAAAAAAAAAAD/AyPyAAAAAAAAAP8DI/EAAAD/AyPyAAAAAP8DI/EAAAD/AyPyAAAAAP8DI/EAAAD/AyPyAAAAAP8DI/EAAAD/AyPyAAAAAP8DI/EAAAD/AyPyAAAAAP8DaVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAABAAAAAgAAAAEAAAAAAgAAAAABAAAAAgAAAAEAAAAAAgAAAAABAAAAAgAAAAEAAAAAAgAAAAABAAAAAgAAAAEAAAAAAgAAAAABAAAAAgAAAIpQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/A2h2AgICAgUCAgIHAgICAgcEAgIHAgICAgcCBAIHAgICAgcCAgQHAgICAgcCAgIFAgICAgcCAgICBQICAgUCAgIHAgICAgcCAgICBwQCAgcEAgIHAgICAgcCAgICBwIEAgcCBAIHAgICAgcCAgICBwICBAcCAgQHAgICAgcCAgICBwICAgUCAgIDAgICBwICAgIHBAICBwICAgIHAgQCBwICAgIHAgIEBwICAgIHAgICBQICAgKAPwMB/wNpUAACAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAACKUAAAAAAAAAAAAAAAAAAAAAAAAAD/AyYvAP8DGhQAAgAMAAIAAgCAxAACAAIAAgAEAAgAFAACAAgAAgCBXACBIAACAAIACAAEAAIAgCoAIgACAAIAhGAAHgAEAAIAAgAGAAIAAgCAdAACACgAAgACAAoABAACAAIAAgACAAIAAgACAAIAAgCKbQAAAAIAAACKUAAAAP8DJVkA/wMZngACKBpMDINaDgKGtv8DaUwCAQL/AxwjAoBk/wMY7GoSLiIIgAYEgRwCgFYKgigkhboaAv8DJs8CgGT/AxjsahIuIgiABgSBHAKAVgqCKCSFuhoC/wMmzwKAZP8DGOxqEi4iCIAGBIEcAoBWCoIoJIW6GgL/Ayd5BAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwT/AydcAgICBQICAgUCAgKIm4oo/wMoI/8DGUL/AxpPiXb/Ax2+/wMla/8DHciB/waCf4AygsMEAv8DdCIAAAAAilEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAilAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AyYvAAAAAAAAAAAA/wMaFAAAAAAAAAAAAAIAAAAAAAAAAAAMAAAAAAAAAAAAAgAAAAAAAAAAAAIAAAAAAAAAAACAxAAAAAAAAAAAAAQAAAAAAAAAAAACAAAAAAAAAAAABAAAAAAAAAAAAAgAAAAAAAAAAAAUAAAAAAAAAAAAAgAAAAAAAAAAAAgAAAAAAAAAAAACAAAAAAAAAAAAgVwAAAAAAAAAAACBIAAAAAAAAAAAAAIAAAAAAAAAAAACAAAAAAAAAAAACAAAAAAAAAAAAAQAAAAAAAAAAAACAAAAAAAAAAAAgCoAAAAAAAAAAAAiAAAAAAAAAAAAAgAAAAAAAAAAAAIAAAAAAAAAAACEYAAAAAAAAAAAAB4AAAAAAAAAAAAEAAAAAAAAAAAAAgAAAAAAAAAAAAIAAAAAAAAAAAAIAAAAAAAAAAAAAgAAAAAAAAAAAIB0AAAAAAAAAAAAAgAAAAAAAAAAACgAAAAAAAAAAAACAAAAAAAAAAAAAgAAAAAAAAAAAAoAAAAAAAAAAAAEAAAAAAAAAAAAAgAAAAAAAAAAAAIAAAAAAAAAAAACAAAAAAAAAAAAAgAAAAAAAAAAAAIAAAAAAAAAAAACAAAAAAAAAAAAAgAAAAAAAAAAAIppAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAilAAAAAAAAAAAAAAAAAAAAAAAAAA/wNodgICAgIHAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAgACAAIAAgAHAAIAAgACAAIABwACAAIAAgACAAcAAAACAAAAAgAAAAIAAAACAAAABwAAAAIAAAACAAAAAgAAAAIAAAAHAAAAAgAAAAIAAAACAAAAAgAAAP8DZ4gAAAAA/wMaXQKAZP8DGOxqEi4iCIAGBIEcAoBWCoIoJIW6GgL/AybPAoBk/wMY7GoSLiIIgAYEgRwCgFYKgigkhboaAv8DJs8CgGT/AxjsahIuIgiABgSBHAKAVgqCKCSFuhoC/wMmzwKAZP8DGOxqEi4iCIAGBIEcAoBWCoIoJIW6GgL/AybPAoBk/wMY7GoSLiIIgAYEgRwCgFYKgigkhboaAv8DJs8CgGT/AxjsahIuIgiABgSBHAKAVgqCKCSFuhoC/wMmzwKAZP8DGOxqEi4iCIAGBIEcAoBWCoIoJIW6GgL/AybPAoBk/wMY7GoSLiIIgAYEgRwCgFYKgigkhboaAv8DJs8CgGT/AxjsahIuIgiABgSBHAKAVgqCKCSFuhoC/wMmzwKAZP8DGOxqEi4iCIAGBIEcAoBWCoIoJIW6GgL/AybPAoBk/wMY7GoSLiIIgAYEgRwCgFYKgigkhboaAv8DJs8CgGT/AxjsahIuIgiABgSBHAKAVgqCKCSFuhoC/wMmzwKAZP8DGOxqEi4iCIAGBIEcAoBWCoIoJIW6GgL/AybPAoBk/wMY7GoSLiIIgAYEgRwCgFYKgigkhboaAv8DJs8CgGT/AxjsahIuIgiABgSBHAKAVgqCKCSFuhoC/wMneQQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwT/AydcAgICBQICAgUCAgIFAgICBQICAgUCAgIFAgICBQICAgUCAgIFAgICBQICAgUCAgIFAgICBQICAgUCAgI=');
function decode_zwnj_emoji(s) {
let r = new TableReader(bytes_from_base64(s));
const ZWNJ_EMOJI = (() => {
let r = new TableReader(decode2(bytes_from_base64('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')));
let buckets = []; // stored by post-idna length

@@ -83,10 +100,13 @@ while (r.more) {

return buckets;
}
})();
export function upgrade_zwnj_emoji(v) {
// upgrade emoji to fully-qualified w/o FEOF
// expects list of code-points
// returns list of code-points
function upgrade_zwnj_emoji(v) {
let ret = [];
next_cp: for (let i = 0, n = v.length; i < n; i++) {
let cp0 = v[i];
next_bucket: for (let b = Math.min(n - i, EMOJI.length); b >= 1; b--) { // only consider emoji that fit
let bucket = EMOJI[b];
next_bucket: for (let b = Math.min(n - i, ZWNJ_EMOJI.length); b >= 1; b--) { // only consider emoji that fit
let bucket = ZWNJ_EMOJI[b];
if (!bucket) continue;

@@ -242,5 +262,5 @@ next_emoji: for (let emoji of bucket) { // todo: binary search

// warning: these should not be used directly
// expects code point (number)
// expects code-point (number)
// is_* returns boolean
// get_* returns list-of-code-points or undefined
// get_* returns number, list of numbers, or undefined (code-points)
export function is_disallowed(cp) {

@@ -267,3 +287,3 @@ return lookup_member_span(TABLE_D, cp);

// returns a string normalized according to IDNA 2008, according to UTS-46 (v14.0.0), +CONTEXTJ, +ZWJ EMOJI
export function idna(s) {
export function idna(s, ignore_disallowed = false) {
if (typeof s !== 'string') throw new TypeError('expected string');

@@ -273,3 +293,6 @@ let v = [...s].map(x => x.codePointAt(0)); // convert to code-points

return String.fromCodePoint(...upgrade_zwnj_emoji(v.map((cp, i) => {
if (is_disallowed(cp)) throw new Error(`disallowed: 0x${cp.toString(16).padStart(2, '0')}`);
if (is_disallowed(cp)) {
if (ignore_disallowed) return empty;
throw new Error(`disallowed: 0x${cp.toString(16).padStart(2, '0')}`);
}
if (is_ignored(cp)) return empty;

@@ -280,4 +303,4 @@ if (cp === 0x200C) { // https://datatracker.ietf.org/doc/html/rfc5892#appendix-A.1

if (i > 0 && lookup_member(TABLE_V, v[i - 1])) {
return cp; // allowed
}
return cp; // allowed
}
// rule 2: {L,D} + T* + cp + T* + {R,D}

@@ -295,3 +318,3 @@ // L,D,T,R = Joining_Type

}
}
}
return empty; // ignore

@@ -315,3 +338,3 @@ } else if (cp === 0x200D) { // https://datatracker.ietf.org/doc/html/rfc5892#appendix-A.2

// throws Error if not normalizable
export function ens_normalize(name) { // https://unicode.org/reports/tr46/#Processing
export function ens_normalize(name, ignore_disallowed = false) { // https://unicode.org/reports/tr46/#Processing
// idna() will:

@@ -321,6 +344,5 @@ // 1. map all full-stops to "." (see: Section 2.3 and Section 4.5)

// 3. apply Section 4 Processing Rule #1 (Map) and Rule #2 (Normalize)
return idna(name).split('.').map(label => { // Section 4 Processing Rule #3 (Break)
return idna(name, ignore_disallowed).split('.').map(label => { // Section 4 Processing Rule #3 (Break) + Section 4.1 Rule #4
if (label.startsWith('xn--')) { // Rule #4 (Convert)
label = puny_decode(label.slice(4));
if (idna(label) !== label) throw new Error(`puny-idna mismatch on label: ${label}`); // can this happen?
label = idna(puny_decode(label.slice(4)), ignore_disallowed);
}

@@ -327,0 +349,0 @@ // Section 4.1 Rule #1 (NFC) is already satisfied by idna()

{
"name": "@adraffy/ens-normalize",
"version": "1.0.6",
"version": "1.0.7",
"description": "Compact ES6 Ethereum Name Service (ENS) Name Normalizer",
"keywords": ["ENS", "Ethereum", "UTS-46", "IDNA2008"],
"keywords": ["ENS", "Ethereum", "UTS-46", "IDNA"],
"type": "module",

@@ -23,4 +23,6 @@ "main": "ens-normalize.js",

"scripts": {
"test": "node ./test/test.js"
"test": "node test/test-all.js",
"render": "node test/render.js",
"dist": "uglifyjs ens-normalize.js --mangle --toplevel --output dist/ens-normalize.min.js"
}
}
# ens-normalize.js
1-file, 0-dependancy Compact ES6 Ethereum Name Service (ENS) Name Normalizer.
This library is **5-10x smaller** than existing implementations.
* Uses latest specification: [UTS-46 v14.0.0](https://unicode.org/reports/tr46/)
* Handles [ZWNJ](https://datatracker.ietf.org/doc/html/rfc5892#appendix-A.2)/[ZWJ](https://datatracker.ietf.org/doc/html/rfc5892#appendix-A.2) in `ContextJ`
* Handles (and upgrades) [Emoji ZWJ Sequences](https://unicode.org/emoji/charts/emoji-zwj-sequences.html)
* Handles [Punycode](https://datatracker.ietf.org/doc/html/rfc3492), adapted from [mathiasbynens/punycode.js](https://github.com/mathiasbynens/punycode.js)
Reference: [UTS-46 v14.0.0](https://unicode.org/reports/tr46/)
[Demo](https://raffy.antistupid.com/eth/ens-resolver.html)
[Demo](https://raffy.antistupid.com/eth/ens-resolver.html) | [Emoji Test](https://raffy.antistupid.com/eth/ens-emoji.html)
```Javascript
import {ens_normalize} from '@adraffy/ens-normalize';
// browser:
// import {ens_normalize} from 'https://unpkg.com/@adraffy/ens-normalize@latest/ens-normalize.js';
// browser:
// 'https://unpkg.com/@adraffy/ens-normalize@latest/dist/ens-normalize.min.js'
// simple api:
// example:
let normalized = ens_normalize('🚴‍♂️.eth'); // throws if error
// this value is ready for hashing
// optional argument: ignore_disallowed (default: false)
// when truthy, disallowed characters are ignored
ens_normalize('_') // throws: disallowed
ens_normalize('_', true) // === ''
// errors:
// - contains disallowed character
// - not a string
// - contains disallowed character if !ignore_disallowed
// - puny decode failure
// - label not idna after puny decode
// - label has double-hyphen at [3:4]

@@ -29,2 +36,8 @@ // - label starts/ends with hyphen

Adapted **Puny Decode** from [mathiasbynens/punycode.js](https://github.com/mathiasbynens/punycode.js).
---
## Build Notes
* Clone the repo to access `test/`. These files are not included in the npm version.
* The actual source is in `test/ens-normalize.src.js`. Use `npm run render` after modification to build a new `ens-normalize.js`.
* Use `npm run dist` to build the minified version.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc