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 };
|