-
Notifications
You must be signed in to change notification settings - Fork 1
/
form.html
103 lines (100 loc) · 4.5 KB
/
form.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
---
layout: default
title: Interactive CQT Tool
---
<script src="cqt.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/index.umd.min.js"></script>
<script>
function el(id) {
return document.getElementById(id);
}
function hexHash(bytes) {
return Array.from(new Uint8Array(bytes)).map(b => b.toString(16).padStart(2, '0')).join('');
}
function reset() {
const encoder = new TextEncoder();
const utf8Bytes = encoder.encode(el('intext').value);
el('intextlen').textContent = utf8Bytes.length + ' bytes';
el('outtextlen').textContent = '? bytes';
el('outtext').value = '';
el('outtextlen').value = '';
el('blake3cesr').value = '';
el('blake3').value = '';
el('sha256cesr').value = '';
el('sha256').value = '';
}
async function cqt() {
intext = el('intext').value;
const canonical = algorithm_1_14(intext);
const decoder = new TextDecoder('utf-8');
outtext = decoder.decode(canonical);
el('outtext').value = outtext;
comp = (intext == outtext) ? " identical" : " different";
el('outtextlen').textContent = canonical.length + comp + ' bytes';
const sha256 = await crypto.subtle.digest('SHA-256', canonical);
const hsha256 = hexHash(sha256);
el('sha256').value = hsha256;
el('sha256cesr').value = cesrify(hsha256, 'I');
const blake3 = await hashwasm.blake3(canonical);
el('blake3').value = blake3;
el('blake3cesr').value = cesrify(blake3, 'E');
}
function cesrify(hexString, prefix) {
const byteArray = new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
let binary = '';
byteArray.forEach(byte => binary += String.fromCharCode(byte));
const base64String = btoa(binary);
const base64Url = base64String.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
return prefix + base64Url;
}
</script>
<label class="copier" for="intext">Input (arbitrary text)</label>
<textarea id="intext" rows="10" cols="80" placeholder="Enter text to canonicalize" maxlength="16384" oninput="reset()"></textarea>
<div style="display:flex">
<button onclick="cqt()">Canonicalize</button>
<div style="flex:1;text-align:right" id="intextlen">0 bytes</div>
</div>
<label class="copier" for="outtext">Output (canonicalized)</label>
<textarea id="outtext" rows="10" cols="80" placeholder="Canonicalized text will appear here" readonly></textarea>
<div style="text-align:right" id="outtextlen">? bytes</div>
<label class="copier" for="blake3cesr">Blake3 of output (<a href="https://trustoverip.github.io/tswg-cesr-specification" target="_cesr">CESR</a>)</label>
<textarea id="blake3cesr" rows="1" cols="80" placeholder="CESR-encoded Blake3 hash will appear here" readonly></textarea>
<label class="copier" for="blake3">Blake3 of output (hex)</label>
<textarea id="blake3" rows="1" cols="80" placeholder="Blake3 hash will appear here" readonly></textarea>
<label class="copier" for="sha256cesr">SHA2-256 of output (<a href="https://trustoverip.github.io/tswg-cesr-specification" target="_cesr">CESR</a>)</label>
<textarea id="sha256cesr" rows="1" cols="80" placeholder="CESR-encoded SHA256 hash will appear here" readonly></textarea>
<label class="copier" for="sha256">SHA2-256 of output (hex)</label>
<textarea id="sha256" rows="1" cols="80" placeholder="SHA256 hash will appear here" readonly></textarea>
<script>
function copyValue() {
// Did this occur where the copy icon is?
const rect = this.getBoundingClientRect();
const clickX = event.clientX - rect.left;
const isRightmost16Pixels = clickX >= rect.width - 20;
if (!isRightmost16Pixels) {
return;
}
// Copy the value of the element with the ID specified in the "for" attribute
const forAttr = this.getAttribute('for');
const target = el(forAttr);
const value = target.value;
navigator.clipboard.writeText(value).then(() => {
console.log('Value copied to clipboard:', value);
// Add the animation class to the textarea
target.classList.add('copied');
// Remove the animation class after the animation ends (0.5s in this case)
setTimeout(function() {
target.classList.remove('copied');
}, 500);
})
.catch((error) => {
console.error('Failed to copy value to clipboard:', error);
});
}
// Find each label in the DOM that has a "for" attribute
const labels = document.querySelectorAll('label[for]');
// Add event listener to each label
labels.forEach(label => {
label.addEventListener('click', copyValue);
});
</script>