|
|
|
@ -55,7 +55,7 @@
|
|
|
|
|
<a href="https://git.fwdekker.com/FWDekker/converter/src/branch/master/LICENSE">MIT License</a>. |
|
|
|
|
Source code available on <a href="https://git.fwdekker.com/FWDekker/converter/">git</a>. |
|
|
|
|
|
|
|
|
|
<div style="float: right;">v1.4.4</div> |
|
|
|
|
<div style="float: right;">v1.4.5</div> |
|
|
|
|
</section> |
|
|
|
|
</footer> |
|
|
|
|
</main> |
|
|
|
@ -66,11 +66,40 @@
|
|
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/big-integer/1.6.44/BigInteger.min.js" |
|
|
|
|
integrity="sha256-es+ex6Oj344uak+VnCPyaHY2nzQkqhr7ByWVQgdjATA=" crossorigin="anonymous"></script> |
|
|
|
|
<script> |
|
|
|
|
const stringReplaceAt = |
|
|
|
|
(str, index, replacement) => str.substr(0, index) + replacement + str.substr(index + replacement.length); |
|
|
|
|
|
|
|
|
|
const stringReplaceAll = |
|
|
|
|
(str, target, replacement) => str.split(target).join(replacement); |
|
|
|
|
/** |
|
|
|
|
* Replaces the character at the given index with the given replacement. |
|
|
|
|
* |
|
|
|
|
* @param str the string to replace in |
|
|
|
|
* @param index the index in the given string to replace at |
|
|
|
|
* @param replacement the replacement to insert into the string |
|
|
|
|
* @returns {string} the input string with one character replaced |
|
|
|
|
*/ |
|
|
|
|
const stringReplaceAt = (str, index, replacement) => |
|
|
|
|
str.substr(0, index) + replacement + str.substr(index + replacement.length); |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Replaces all instances of the target with the replacement. |
|
|
|
|
* |
|
|
|
|
* @param str the string to replace in |
|
|
|
|
* @param target the character to replace |
|
|
|
|
* @param replacement the replacement to insert into the string |
|
|
|
|
* @returns {string} the input string with all instances of the target replaced |
|
|
|
|
*/ |
|
|
|
|
const stringReplaceAll = (str, target, replacement) => |
|
|
|
|
str.split(target).join(replacement); |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Runs `stringReplaceAll` for each character in `targets` and `replacements`. |
|
|
|
|
* |
|
|
|
|
* @param str the string to replace in |
|
|
|
|
* @param targets the characters to replace |
|
|
|
|
* @param replacements the replacements to insert into the string; each character here corresponds to a character |
|
|
|
|
* in the targets string |
|
|
|
|
* @returns {string} the input string with all instances of the targets replaced |
|
|
|
|
*/ |
|
|
|
|
const stringReplaceAlls = (str, targets, replacements) => |
|
|
|
|
Array.from(targets).reduce((output, target, index) => |
|
|
|
|
stringReplaceAll(output, target, replacements[index]), str); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NumeralSystem { |
|
|
|
@ -117,7 +146,7 @@
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
this.textarea.value = this.numeralSystem.filterBaseString(this.textarea.value); |
|
|
|
|
updateAllInputs(this.numeralSystem.baseToDecimal(this.textarea.value)); |
|
|
|
|
updateAllInputs(this, this.numeralSystem.baseToDecimal(this.textarea.value)); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -133,6 +162,17 @@
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class Base64NumeralSystem extends NumeralSystem { |
|
|
|
|
// TODO Convert static methods to static properties once supported by Firefox |
|
|
|
|
static defaultAlphabet() { |
|
|
|
|
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Constructs a new base 64 numeral system. |
|
|
|
|
* |
|
|
|
|
* @param alphabet the 64 characters to encode numbers with, and the padding character at the end |
|
|
|
|
*/ |
|
|
|
|
constructor(alphabet) { |
|
|
|
|
super(64, alphabet, true); |
|
|
|
|
} |
|
|
|
@ -148,11 +188,14 @@
|
|
|
|
|
.map(pair => String.fromCharCode(parseInt(pair.join(""), 16))) |
|
|
|
|
.join(""); |
|
|
|
|
|
|
|
|
|
return btoa(b64); |
|
|
|
|
return stringReplaceAlls(btoa(b64), Base64NumeralSystem.defaultAlphabet(), this.alphabet); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
baseToDecimal(baseString) { |
|
|
|
|
const hex = Array.from(atob(baseString)) |
|
|
|
|
if (baseString.length % 4 === 1) throw new Error("Invalid input string length."); |
|
|
|
|
|
|
|
|
|
const normalBaseString = stringReplaceAlls(baseString, this.alphabet, Base64NumeralSystem.defaultAlphabet()); |
|
|
|
|
const hex = Array.from(atob(normalBaseString)) |
|
|
|
|
.map(char => char.charCodeAt(0).toString(16).padStart(2, "0")).join(""); |
|
|
|
|
return bigInt(hex, 16); |
|
|
|
|
} |
|
|
|
@ -160,17 +203,13 @@
|
|
|
|
|
|
|
|
|
|
class Base64NumeralSystemInput extends NumeralSystemInput { |
|
|
|
|
// TODO Convert static methods to static properties once supported by Firefox |
|
|
|
|
static defaultAlphabet() { |
|
|
|
|
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static dropdownOptions() { |
|
|
|
|
return {"Standard": ['+', '/'], "Filename": ['-', '_'], "IMAP": ['+', ',']}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor(name) { |
|
|
|
|
super(name, new Base64NumeralSystem(Base64NumeralSystemInput.defaultAlphabet())); |
|
|
|
|
super(name, new Base64NumeralSystem(Base64NumeralSystem.defaultAlphabet())); |
|
|
|
|
|
|
|
|
|
this.dropdownLabel = document.createElement("label"); |
|
|
|
|
this.dropdownLabel.setAttribute("for", `${this.name}Dropdown`); |
|
|
|
@ -236,9 +275,10 @@
|
|
|
|
|
), |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
const updateAllInputs = newValue => { |
|
|
|
|
const updateAllInputs = (source, newValue) => { |
|
|
|
|
for (const input of inputs) |
|
|
|
|
input.update(newValue); |
|
|
|
|
if (input !== source) |
|
|
|
|
input.update(newValue); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -248,7 +288,7 @@
|
|
|
|
|
for (const input of inputs) |
|
|
|
|
input.addToParent(inputParent); |
|
|
|
|
|
|
|
|
|
updateAllInputs(bigInt(42)); |
|
|
|
|
updateAllInputs(undefined, bigInt(42)); |
|
|
|
|
inputs[0].textarea.focus(); |
|
|
|
|
}); |
|
|
|
|
</script> |
|
|
|
|