shann_

Password Generator Bookmarklet

Secret / Password / Passphrase Generator

Create a bookmarklet (bookmark) in your Chrome browser to see a simple secret / password / passphrase generator

What is a Password Generator

Per Wikipedia, a password generator is a software program or hardware device that takes input from a random or pseudo-random number generator and automatically generates a password. While there are many examples of "random" password generator programs available on the Internet, generating randomness can be tricky, and many programs do not generate random characters in a way that ensures strong security.

The Password Generator Bookmarklet

The Password Generator Bookmarklet

Password Generator Features

Features Description
Password & passphrase Generation Choose between your preferred secret type: passwords (e.g. I%[yojmY6D&cSLJU) or passphrases (e.g. de3d-sing-sh1p-gl@$s)
Secret complexity & configuration Easily choose the length and complexity features of the generated secret across length, and numerous included character sets
Easy copy and paste One-click copy functionality so that you can use the generated secret quickly
Regenerate as much as you like Don't like the look of a randomly generated secret? Simply click a button to generate a new one.
Dynamic theming The password generator will sync with your operating system's preference of light and dark mode to seamlessly integrate with your preferences
Cryptographically secure The generated passwords use state of the art cryptographic capabilities via the browser's built in security features
Secret strength indicator Know and trust that your password or passphrase is demonstrably secure via our in-built strength indicator

Dependencies

  • This snippet is currently functional and tested in versions of Chrome v128 and onwards
  • If you want to try it in other browsers or versions please do - and let me know how it goes. I'll update the supported browsers and versions for the benefit of others

Install the Password Generator

Step Description
Chrome's Bookmark Manager Open Chrome's Bookmark manager in one of the following ways: Enter chrome://bookmarks in the address field OR click on Bookmarks and then choose Bookmark Manager in the menubar. You should see something like the image on the left.
start-new-bookmark.png Click on the three dots in the top right of the screen and then click Add new Bookmark
Create your password generator bookmark Enter Password Generator in the Name field. Then click on Copy Code above the code section below this table and paste it into the URL box in the new bookmark window. Click Save to finish creating the bookmark.
Select the bookmark you just created Now that you have a new Password Generator bookmark it's time to use it. The new bookmark should appear in the Bookmarks Bar underneath the address bar, as shown. Click on it to open the Password Generator.
Click the bookmark to open the password generator You should now see the Password Generator in all of it's glory.
Copy your password and get back to business Generate a secret, use it as required, close out the password generator and get back to business.

Code

js
javascript:(()=>{!function(n,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("PasswordGeneratorWidget",[],e):"object"==typeof exports?exports.PasswordGeneratorWidget=e():n.PasswordGeneratorWidget=e()}(window,(()=>(()=>{"use strict";var n={d:(e,t)=>{for(var o in t)n.o(t,o)&&!n.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},o:(n,e)=>({}.hasOwnProperty.call(n,e))},e={};n.d(e,{default:()=>m});const t=["bear","bird","bull","kitten","deer","doggy","dove","duck","eagle","fish","foxes","frog","goat","hawk","lion","mouse","owlet","panda","seal","shark","amber","azure","beige","black","blue","brown","coral","cyan","green","grey","ivory","jade","navy","olive","pink","rose","ruby","teal","white","yellow","beach","cave","cliff","cloud","coast","dusk","earth","field","fire","flame","flood","frost","glade","grass","hill","lake","leaf","moon","moss","ocean","rain","reef","river","rock","sand","snow","storm","tree","wave","wind","wood","apple","bread","cake","candy","chai","cream","fruit","grape","honey","juice","lemon","lime","meat","milk","mint","pear","plum","salt","seed","soup","spice","wine","bell","book","bowl","boxes","brick","card","chair","clock","coin","desk","door","drum","flag","flask","fork","game","gear","gift","glass","keys","knife","lamp","lock","mail","maps","mask","page","ring","rope","ship","shoe","sign","sword","tool","toys","watch","wheel","wire","arts","beat","blur","bond","calm","code","core","dark","data","dawn","deed","dream","edge","fact","fate","flow","form","gain","goal","good","grip","grow","hope","idea","join","jump","kind","life","link","love","luck","mind","move","name","need","path","peak","plan","play","plot","rule","safe","self","soul","star","tale","task","time","tone","true","view","wild","wise","wish","word","work","zone","breeze","draft","hail","heat","sleet","smog","sunny","windy","date","hour","month","night","noon","week","year","band","bass","chord","jazz","note","song","tune","voice","anger","bliss","care","cheer","fear","grief","happy","rage","smile","worry","build","catch","climb","dance","dive","draw","drink","float","laugh","read","sail","sing","skip","swim","walk","brass","clay","cloth","cork","denim","iron","metal","paper","silk","steel","stone","wool","bush","fern","flora","herb","iris","lily","pine","sage","stem","weed"];function o(n={length:16,uppercase:!0,lowercase:!0,numbers:!0,symbols:!0,excludedChars:"",usePassphrase:!1}){const e=function(n){const e={length:16,uppercase:!0,lowercase:!0,numbers:!0,symbols:!0,excludedChars:"",usePassphrase:!1,...n};if(!(e.usePassphrase||e.uppercase||e.lowercase||e.numbers||e.symbols))throw Error("At least one character type must be enabled");return e.usePassphrase||(e.length=Math.max(8,Math.min(64,parseInt(e.length)||18))),e.usePassphrase&&(e.wordsCount=Math.max(3,Math.min(8,parseInt(e.wordsCount)||4))),e.excludedChars=(e.excludedChars||"").replace(/[^a-zA-Z0-9!@#$%^&*()_+\-=[\]{};:,.<>?]/g,""),e}(n);return e.usePassphrase?function(n){const e=[],t=n.wordsCount||3;for(let n=0;n<t;n++){const o=a();n!==t-1||e.some((n=>/[0-9@$]/.test(n)))?e.push(i(o)):e.push(r(o))}return e.join("-")}(e):function(n){const e=function(n){const e={uppercase:"ABCDEFGHIJKLMNOPQRSTUVWXYZ",lowercase:"abcdefghijklmnopqrstuvwxyz",numbers:"0123456789",symbols:"-!@#$%^&*()_+[]{}|;:,.<>?"};let t="";return Object.keys(e).forEach((o=>{n[o]&&(t+=e[o])})),t.split("").filter((e=>!n.excludedChars.includes(e))).join("")}(n);if(0===e.length)throw Error("No valid characters available for password generation");let t,o=0;do{t=p(e,n.length),o++}while(!s(t,n)&&o<100);if(o>=100)throw Error("Could not generate password meeting requirements");return t}(e)}function r(n){const e={a:"@",e:"3",i:"1",o:"0",s:"$"};for(let t=0;t<n.length;t++)if(e[n[t]])return n.substring(0,t)+e[n[t]]+n.substring(t+1);return n}function a(){const n=Math.floor(crypto.getRandomValues(new Uint32Array(1))[0]/4294967296*t.length);return t[n]}function i(n){const e={a:"@",e:"3",i:"1",o:"0",s:"$"};return n.split("").map((n=>e[n]&&Math.random()<.3?e[n]:n)).join("")}function s(n,e){return!(e.uppercase&&!/[A-Z]/.test(n)&&!e.excludedChars.includes("ABCDEFGHIJKLMNOPQRSTUVWXYZ")||e.lowercase&&!/[a-z]/.test(n)&&!e.excludedChars.includes("abcdefghijklmnopqrstuvwxyz")||e.numbers&&!/[0-9]/.test(n)&&!e.excludedChars.includes("0123456789")||e.symbols&&!/[-!@#$%^&*()_+[\]{};:,.<>?]/.test(n)&&!e.excludedChars.includes("-!@#$%^&*()_+[]{};:,.<>?"))}function p(n,e){const t=new Uint32Array(e);return crypto.getRandomValues(t),Array.from(t).map((e=>n[e%n.length])).join("")}(()=>{if(t.filter((n=>!n.match(/^[a-z]{4,8}$/))).length>0)throw Error("Word list contains invalid words");if(new Set(t).size!==t.length)throw Error("Word list contains duplicates")})();const l='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>',d={settings:{length:16,wordsCount:4,uppercase:!0,lowercase:!0,numbers:!0,symbols:!0,excludedChars:"",usePassphrase:!1},observers:[],subscribe(n){this.observers.push(n)},notify(){this.observers.forEach((n=>n(this.settings)))},updateSettings(n){this.settings={...this.settings,...n},this.notify()},getSettings(){return{...this.settings}}};function g(n){return n<40?"Very Weak":n<60?"Weak":n<80?"Moderate":n<90?"Strong":"Very Strong"}function c(n){return n<40?"#ff4444":n<60?"#ffaa00":n<80?"#ffdd00":n<90?"#00cc00":"#00aa00"}function w(n,e,t,o){const r=[];return n.length<12&&r.push("Consider using a longer password"),t<.75&&r.push("Mix uppercase, lowercase, numbers, and symbols"),o<.7&&r.push("Avoid repeating characters"),e<50&&r.push("Password is too predictable"),/(.)\1{2,}/.test(n)&&r.push("Avoid character repetition"),/^[A-Za-z]+$/.test(n)&&r.push("Add numbers or symbols"),/^[0-9]+$/.test(n)&&r.push("Add letters or symbols"),r}function h(n,e){const t=function(n){const e=function(n){let e=0;return/[A-Z]/.test(n)&&(e+=26),/[a-z]/.test(n)&&(e+=26),/[0-9]/.test(n)&&(e+=10),/[^A-Za-z0-9]/.test(n)&&(e+=33),Math.log2(Math.pow(e,n.length))}(n),t=function(n){let e=0;return/[A-Z]/.test(n)&&(e+=.25),/[a-z]/.test(n)&&(e+=.25),/[0-9]/.test(n)&&(e+=.25),/[^A-Za-z0-9]/.test(n)&&(e+=.25),e}(n),o=function(n){return new Set(n).size/n.length}(n),r=Math.min(100,Math.floor(.5*e+30*t+20*o));return{score:r,entropy:Math.floor(e),label:g(r),color:c(r),feedback:w(n,e,t,o)}}(n);e.innerHTML=`\n <div class="pgw-strength-bar"></div>\n <div class="pgw-strength-details">\n <span class="pgw-strength-label">${t.label}</span>\n <span class="pgw-strength-entropy">${t.entropy} bits</span>\n </div>\n `;const o=e.querySelector(".pgw-strength-bar");o.style.setProperty("--strength-width",t.score+"%"),o.style.setProperty("--strength-color",t.color)}function u(n,e=!0){const t=n.querySelector(".pgw-feedback"),o=n.querySelector(".pgw-copy");t.textContent=e?"Copied!":"Failed to copy",t.className="pgw-feedback "+(e?"success":"error"),o.disabled=!0,setTimeout((()=>{t.textContent="",t.className="pgw-feedback",o.disabled=!1}),2e3)}function b(n){const e=n.querySelector(".pgw-password-display input"),t=o(d.getSettings());e.value=t,h(t,n.querySelector(".pgw-strength"))}function f(n){const e=window.matchMedia("(prefers-color-scheme: dark)").matches,t=n.documentElement;e?(t.style.setProperty("--pgw-bg","#1a2133"),t.style.setProperty("--pgw-text","#ffffff"),t.style.setProperty("--pgw-header-bg","#232d42"),t.style.setProperty("--pgw-border","#2d3850"),t.style.setProperty("--pgw-button-bg","#232d42"),t.style.setProperty("--pgw-button-hover","#ff7b2c"),t.style.setProperty("--pgw-input-bg","#232d42")):(t.style.setProperty("--pgw-bg","#f0f4f8"),t.style.setProperty("--pgw-text","#1a2133"),t.style.setProperty("--pgw-header-bg","#e6eef9"),t.style.setProperty("--pgw-border","#d0e1f9"),t.style.setProperty("--pgw-button-bg","#e6eef9"),t.style.setProperty("--pgw-button-hover","#ffa366"),t.style.setProperty("--pgw-input-bg","#ffffff"))}const m=function(){if(document.querySelector("#pgw-container"))return;const n=document.createElement("iframe");n.id="pgw-container",n.style.cssText="\n position: fixed;\n top: 20px;\n right: 20px;\n border: none;\n background: transparent;\n z-index: 2147483647;\n width: 400px;\n visibility: hidden;\n height: auto;\n min-height: max-content;\n ",document.body.appendChild(n);const e=n.contentDocument||n.contentWindow?.document;e.open(),e.write("\n <html>\n <head>\n <style>\n html, body {\n margin: 0;\n padding: 0;\n height: auto !important;\n overflow: visible !important;\n }\n </style>\n </head>\n <body></body>\n </html>\n "),e.close();const t=document.createElement("style");var r;t.textContent='html, body {\n margin: 0;\n padding: 0;\n height: auto;\n overflow: hidden;\n}\n\nbody {\n \n}\n\n.pgw-widget {\n font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n background: var(--pgw-bg, #f0f4f8);\n color: var(--pgw-text, #1a2133);\n border-radius: 8px;\n \n width: 100%;\n height: auto;\n min-height: min-content;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n --pgw-border: #d0e1f9;\n}\n\n/* Dark mode */\n@media (prefers-color-scheme: dark) {\n .pgw-widget {\n --pgw-bg: #1a2133;\n --pgw-text: #ffffff;\n --pgw-header-bg: #232d42;\n --pgw-border: #2d3850;\n --pgw-button-bg: #232d42;\n --pgw-button-hover: #ff7b2c;\n --pgw-input-bg: #232d42;\n }\n}\n\n.pgw-header {\n padding: 12px;\n background: var(--pgw-header-bg, #e6eef9);\n border-bottom: 1px solid var(--pgw-border, #d0e1f9);\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-top-left-radius: 8px;\n border-top-right-radius: 8px;\n}\n\n.pgw-header h1 {\n margin: 0;\n font-size: 18px;\n font-weight: 500;\n}\n\n.pgw-header button {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: inherit;\n}\n\n.pgw-content {\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n height: auto;\n position: relative;\n}\n\n.pgw-password-display {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n width: 100%;\n}\n\n.pgw-password-container {\n position: relative;\n}\n\n.pgw-password-display input {\n width: 280px;\n min-width: 0;\n flex: 0 1 auto;\n padding: 8px;\n padding-right: 36px;\n border: 1px solid var(--pgw-border);\n border-radius: 4px;\n font-family: monospace;\n font-size: 16px;\n background: var(--pgw-input-bg);\n color: inherit;\n}\n\n.pgw-toggle-mask {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: inherit;\n z-index: 1;\n}\n\n.pgw-actions {\n display: flex;\n gap: 8px;\n margin-bottom: 0;\n margin-left: auto;\n flex: 0 0 auto;\n}\n\n.pgw-actions button {\n padding: 6px;\n border: 1px solid var(--pgw-border);\n border-radius: 4px;\n background: var(--pgw-button-bg);\n cursor: pointer;\n transition: background-color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n color: inherit;\n}\n\n.pgw-actions button:hover {\n background: var(--pgw-button-hover, #ffa366);\n}\n\n.pgw-actions svg {\n stroke: currentColor;\n fill: none;\n}\n\n.pgw-settings {\n border-top: 1px solid var(--pgw-border, #d0e1f9);\n padding-top: 16px;\n}\n\n.pgw-length {\n margin-bottom: 16px;\n}\n\n.pgw-length input[type="range"] {\n -webkit-appearance: none;\n width: 100%;\n height: 4px;\n border-radius: 2px;\n background: var(--pgw-border);\n margin: 1em 0;\n outline: none;\n}\n\n.pgw-length input[type="range"]::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--pgw-button-hover);\n cursor: pointer;\n transition: background-color 0.2s;\n}\n\n.pgw-length input[type="range"]::-moz-range-thumb {\n width: 16px;\n height: 16px;\n border: none;\n border-radius: 50%;\n background: var(--pgw-button-hover);\n cursor: pointer;\n transition: background-color 0.2s;\n}\n\n.pgw-length input[type="range"]::-webkit-slider-thumb:hover {\n background: #ff7b2c;\n}\n\n.pgw-length input[type="range"]::-moz-range-thumb:hover {\n background: #ff7b2c;\n}\n\n.pgw-options {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 8px;\n}\n\n.pgw-options label {\n display: flex;\n align-items: center;\n gap: 4px;\n cursor: pointer;\n}\n\n.pgw-options input[type="checkbox"] {\n margin: 0;\n}\n\n.pgw-feedback {\n position: absolute;\n top: 12px;\n right: 45px;\n padding: 8px 16px;\n border-radius: 4px;\n font-size: 14px;\n opacity: 0;\n transition: opacity 0.3s ease;\n z-index: 1;\n}\n\n.pgw-feedback.success {\n background-color: #4caf50;\n color: white;\n opacity: 1;\n}\n\n.pgw-feedback.error {\n background-color: #ff7b2c;\n color: white;\n opacity: 1;\n}\n\n.pgw-strength {\n \n position: relative;\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 4px;\n}\n\n.pgw-strength-bar {\n position: relative;\n height: 4px;\n width: 100%;\n background-color: #eee;\n border-radius: 2px;\n overflow: hidden;\n}\n\n.pgw-strength-bar::after {\n content: \'\';\n position: absolute;\n height: 100%;\n left: 0;\n top: 0;\n transition: width 0.3s ease, background-color 0.3s ease;\n width: clamp(0%, var(--strength-width, 0%), 100%);\n background-color: var(--strength-color, #ddd);\n}\n\n.pgw-strength-details {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.pgw-strength-label {\n font-size: 14px;\n font-weight: 500;\n}\n\n.pgw-strength-entropy {\n font-size: 12px;\n opacity: 0.7;\n}\n\n.pgw-strength-feedback {\n margin-top: 8px;\n font-size: 12px;\n color: var(--pgw-text-secondary, #666);\n}\n\n.pgw-feedback-item {\n margin: 2px 0;\n padding-left: 12px;\n position: relative;\n}\n\n.pgw-feedback-item::before {\n content: "•";\n position: absolute;\n left: 0;\n}\n\n.pgw-mode {\n margin-bottom: 16px;\n}\n\n.pgw-switch {\n position: relative;\n display: inline-flex;\n align-items: center;\n cursor: pointer;\n}\n\n.pgw-switch input {\n opacity: 0;\n width: 0;\n height: 0;\n}\n\n.pgw-slider {\n position: relative;\n display: inline-block;\n width: 48px;\n height: 24px;\n background-color: var(--pgw-button-bg, #ccc);\n border-radius: 24px;\n margin-right: 8px;\n transition: .4s;\n}\n\n.pgw-slider:before {\n position: absolute;\n content: "";\n height: 16px;\n width: 16px;\n left: 4px;\n bottom: 4px;\n background-color: white;\n border-radius: 50%;\n transition: .4s;\n}\n\n.pgw-switch input:checked + .pgw-slider {\n background-color: var(--pgw-button-hover);\n}\n\n.pgw-switch input:checked + .pgw-slider:before {\n transform: translateX(24px);\n}\n\n.pgw-mode-label {\n font-size: 14px;\n} ',e.head.appendChild(t),function(n){const e=n.createElement("div");e.className="pgw-widget",e.innerHTML=`\n <div class="pgw-header">\n <h1>Password Generator</h1>\n <button class="pgw-close" aria-label="Close"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg></button>\n <div class="pgw-feedback" aria-live="polite"></div>\n </div>\n \n <div class="pgw-content">\n <div class="pgw-password-display">\n <div class="pgw-password-container">\n <input type="password" readonly value="${o()}" aria-label="Generated password" />\n <button class="pgw-toggle-mask" aria-label="Toggle password visibility">${l}</button>\n </div>\n <div class="pgw-actions">\n <button class="pgw-copy" aria-label="Copy to clipboard"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg></button>\n <button class="pgw-regenerate" aria-label="Generate new password"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 4v6h-6"></path><path d="M1 20v-6h6"></path><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path></svg></button>\n </div>\n </div>\n \n <div class="pgw-strength" role="status" aria-live="polite"></div>\n \n <div class="pgw-settings">\n <div class="pgw-mode">\n <label class="pgw-switch">\n <input type="checkbox" name="usePassphrase">\n <span class="pgw-slider"></span>\n <span class="pgw-mode-label">Use Passphrase</span>\n </label>\n </div>\n\n <div class="pgw-length">\n <label>\n <span class="pgw-length-label">Length: </span>\n <span class="pgw-length-value">${d.getSettings().length}</span>\n </label>\n <input type="range" min="8" max="64" value="${d.getSettings().length}" class="pgw-length-slider" aria-label="Password length" />\n <input type="range" min="3" max="8" value="${d.getSettings().wordsCount}" class="pgw-words-slider" aria-label="Number of words" style="display: none" />\n </div>\n \n <div class="pgw-options">\n <label><input type="checkbox" checked name="uppercase"> Uppercase</label>\n <label><input type="checkbox" checked name="lowercase"> Lowercase</label>\n <label><input type="checkbox" checked name="numbers"> Numbers</label>\n <label><input type="checkbox" checked name="symbols"> Symbols</label>\n </div>\n </div>\n </div>\n `;const t=e.querySelector(".pgw-password-display input"),r=e.querySelector(".pgw-strength");h(t.value,r),function(n){n.querySelector(".pgw-close").addEventListener("click",(()=>{const n=document.querySelector("#pgw-container");n&&n.remove()})),n.querySelector(".pgw-copy").addEventListener("click",(async()=>{const e=n.querySelector(".pgw-password-display input").value;try{await navigator.clipboard.writeText(e),u(n,!0)}catch(e){u(n,!1)}})),n.querySelector(".pgw-regenerate").addEventListener("click",(()=>{const e=n.querySelector(".pgw-password-display input");e.value=o(d.getSettings()),h(e.value,n.querySelector(".pgw-strength"))}));const e=n.querySelector('input[name="usePassphrase"]'),t=n.querySelector(".pgw-length-slider"),r=n.querySelector(".pgw-words-slider"),a=n.querySelector(".pgw-length-label"),i=n.querySelector(".pgw-options");e.addEventListener("change",(e=>{const o=e.target.checked;d.updateSettings({usePassphrase:o}),t.style.display=o?"none":"block",r.style.display=o?"block":"none",a.textContent=o?"Words: ":"Length: ",i.style.display=o?"none":"grid",n.querySelector(".pgw-length-value").textContent=o?d.getSettings().wordsCount:d.getSettings().length,b(n)})),t.addEventListener("input",(e=>{d.updateSettings({length:e.target.value}),n.querySelector(".pgw-length-value").textContent=e.target.value,b(n)})),r.addEventListener("input",(e=>{d.updateSettings({wordsCount:e.target.value}),n.querySelector(".pgw-length-value").textContent=e.target.value,b(n)})),n.querySelector(".pgw-toggle-mask").addEventListener("click",(e=>{const t=n.querySelector(".pgw-password-display input"),o="text"===t.type;t.type=o?"password":"text",e.currentTarget.innerHTML=o?l:'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>'}));const s=n.querySelector(".pgw-password-display input"),p=n.querySelector(".pgw-strength");s.addEventListener("input",(()=>{var n;n=calculatePasswordStrength(s.value),p.innerHTML=`\n <div class="pgw-strength-bar" style="width: ${n.score}%; background-color: ${n.color}"></div>\n <div class="pgw-strength-details">\n <span class="pgw-strength-label">${n.label}</span>\n <span class="pgw-strength-entropy">${n.entropy} bits</span>\n </div>\n ${n.feedback.length?`\n <div class="pgw-strength-feedback">\n ${n.feedback.map((n=>`<div class="pgw-feedback-item">${n}</div>`)).join("")}\n </div>\n `:""}\n `})),n.querySelectorAll('.pgw-options input[type="checkbox"]').forEach((e=>{e.addEventListener("change",(e=>{d.updateSettings({[e.target.name]:e.target.checked}),b(n)}))}))}(e),function(n){const e=n.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'),t=e[0],o=e[e.length-1];n.addEventListener("keydown",(n=>{if("Escape"!==n.key)"Tab"===n.key&&(n.shiftKey?document.activeElement===t&&(n.preventDefault(),o.focus()):document.activeElement===o&&(n.preventDefault(),t.focus()));else{const n=document.querySelector("#pgw-container");n&&n.remove()}})),t.focus()}(e),n.body.appendChild(e)}(e),f(r=e),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",(()=>f(r))),requestAnimationFrame((()=>{const t=e.querySelector(".pgw-widget").offsetHeight;n.style.height=t+"px",n.style.visibility="visible"})),new MutationObserver((()=>{const t=e.querySelector(".pgw-widget").offsetHeight;n.style.height=t+"px"})).observe(e.querySelector(".pgw-widget"),{childList:!0,subtree:!0,attributes:!0,characterData:!0})};return e.default})()));PasswordGeneratorWidget();})();
Tags:
  • secret,
  • bookmarklet,
  • passphrase,
  • password