keeweb/app/scripts/util/formatting/password-presenter.js

80 lines
2.3 KiB
JavaScript
Raw Normal View History

2020-03-21 12:24:21 +01:00
import 'util/kdbxweb/protected-value-ex';
2019-09-27 07:37:26 +02:00
import { shuffle } from 'util/fn';
class RandomNameGenerator {
usedNames = {};
randomCharCode() {
return 97 + Math.floor(Math.random() * 26);
}
randomElementName() {
for (let i = 0; i < 1000; i++) {
let result = '';
const length = 3 + Math.floor(Math.random() * 3);
for (let i = 0; i < length; i++) {
result += String.fromCharCode(this.randomCharCode());
}
if (!this.usedNames[result]) {
this.usedNames[result] = true;
return result;
}
}
throw new Error('Failed to generate a random name');
}
}
function charCodeToHtml(char) {
return Math.random() < 0.2 ? String.fromCharCode(char) : `&#x${char.toString(16)};`;
}
const PasswordPresenter = {
present(length) {
return new Array(length + 1).join('•');
},
presentValueWithLineBreaks(value) {
if (!value) {
return '';
}
let result = '';
value.forEachChar(ch => {
result += ch === 10 ? '\n' : '•';
});
return result;
},
asHtml(value) {
const html = [];
const style = [];
const gen = new RandomNameGenerator();
const wrapperClass = gen.randomElementName();
let ix = 0;
value.forEachChar(char => {
const className = gen.randomElementName();
const charHtml = charCodeToHtml(char);
html.push(`<span class="${className}">${charHtml}</span>`);
style.push(`.${className}{order:${ix}}`);
if (Math.random() > 0.5) {
const fakeClassName = gen.randomElementName();
const fakeChar = gen.randomCharCode();
const fakeCharHtml = charCodeToHtml(fakeChar);
html.push(`<span class="${fakeClassName}">${fakeCharHtml}</span>`);
style.push(`.${wrapperClass} .${fakeClassName}{display:none}`);
}
ix++;
});
const everything = html.concat(style.map(s => `<style>${s}</style>`));
const innerHtml = shuffle(everything).join('');
return `<div class="${wrapperClass}" style="display: flex">${innerHtml}</div>`;
}
};
export { PasswordPresenter };