forked from DOSYCORPS/txtmode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
194 lines (188 loc) · 6.61 KB
/
index.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
<!DOCTYPE html>
<meta charset=utf-8>
<meta name=viewport content="width=device-width, initial-scale=1.0">
<title>txtmode | convert files to txt and back</title>
<script src=words.js></script>
<script src=b64order.js></script>
<script src=toWords.js></script>
<script src=fromWords.js></script>
<style>
:root {
font-size: 11pt;
}
body {
background: #eee;
}
main {
background: white;
display: table;
margin: 1rem auto;
border: 1px solid silver;
padding: 1rem;
}
button.cta {
font-size: 1.7rem;
color: white;
background: dodgerblue;
font-style: italic;
padding: 0.25rem;
}
.txcent {
text-align: center;
}
.consent {
font-size: 0.8rem;
font-style: italic;
}
.narrow {
width: 60%;
min-width: 150px;
display: inline-block;
}
header {
background: dodgerblue;
}
h1.banner {
font-family: monospace;
}
h1 {
font-family: sans-serif;
}
label {
-webkit-touch-callout: none;
-ms-user-select: none;
-moz-user-select: none;
user-select: none;
}
footer {
font-size: 0.67rem;
}
.warning:hover, .warning:active{
color: red;
}
.warning {
color: grey;
}
</style>
<script>
"use strict";
{
// function to size a file
const b64expand = ( b64size ) => Math.ceil( b64size / 3 ) * 4;
const humanize = ( size ) => (size / (1024*1024) ).toFixed(2) + 'Mb';
Object.assign( self, { sizeIt } );
function sizeIt( b64size ) {
return humanize( b64expand( b64size ) );
}
}
</script>
<main>
<header>
<h1 class=banner>txtmode — convert files to txt and back</h1>
</header>
<form>
<label>
<fieldset><legend>Add file</legend>
<p>
Add a file here to convert to txt
<br>
<input required type=file id=file name=file>
<br>
<i>Note: you can also add your txt files here to convert <strong>back to the original</strong></i>
<p>
<strong>This is a STATIC SITE. No thing is sent to any server. This is a GitHub pages site.</strong>
</fieldset>
</label>
<p class=txcent>
<label class="narrow consent">
<input required type=checkbox>
I agree this tool is provided as is, and I am responsible for my use of it.
The provider is not responsible for any damage incurred as a result of its use.
</label>
<p class=txcent>
<button class=cta>Process</button>
<script>
"use strict";
{
Object.assign(self, {processFile});
const form = document.currentScript.closest('form');
const file = form.querySelector('#file');
form.addEventListener('submit', e => processFile(e) );
function processFile(e) {
e.preventDefault();
const fileNode = file.files[0];
if ( fileNode.name.includes('_txtmode_') && fileNode.name.endsWith('.txt') ) {
return processTxt(fileNode);
}
if ( fileNode.size > 1000000 ) {
const proceed = confirm('Whoa slow down there. Sorry, that file is too big for us. Are you sure you want to proceed? Your browser may crash because it runs out of memory.');
if ( ! proceed ) {
throw new TypeError("File too big");
}
}
const reader = new FileReader();
form.querySelector('button').disabled = true;
form.querySelector('button').innerText = 'processing...';
reader.addEventListener('load', () => {
const [mimeDataPrefix, content] = reader.result.split(',');
const encodedName = toWords(btoa(unescape(encodeURIComponent(fileNode.name))));
const encodedMimeDataPrefix = toWords(btoa(mimeDataPrefix));
const encodedContent = toWords(content);
const fileContent = `${encodedName}\n\n${encodedMimeDataPrefix}\n\n${encodedContent}\n\n`;
const txtMode = `data:text/plain;base64,${btoa(fileContent)}`;
const anchor = document.createElement('a');
anchor.target = "_new";
anchor.download = `${fileNode.name}._txtmode_.txt`;
// name hiding
// anchor.download = `${+ new Date}._txtmode_.txt`;
anchor.innerText = `Download ${anchor.download} [${sizeIt(txtMode.length)}]`;
anchor.href = txtMode;
document.querySelector('section.downloads ol').insertAdjacentHTML('afterbegin','<li></li>');
document.querySelector('section.downloads ol li').insertAdjacentElement('afterbegin', anchor );
form.querySelector('button').disabled = false;
form.querySelector('button').innerText = 'Process';
});
reader.readAsDataURL(fileNode);
}
function processTxt(file) {
const reader = new FileReader();
form.querySelector('button').disabled = true;
form.querySelector('button').innerText = 'processing...';
reader.addEventListener('load', () => {
const [encodedName, encodedMimeDataPrefix, encodedContent] = reader.result.split('\n\n');
const name = decodeURIComponent(escape(atob(fromWords(encodedName))));
const mimeDataPrefix = atob(fromWords(encodedMimeDataPrefix));
const content = fromWords(encodedContent);
const originalMode = `${mimeDataPrefix},${content}`;
const anchor = document.createElement('a');
anchor.target = "_new";
anchor.download = `${name}`;
anchor.innerText = `Download ${anchor.download} [${sizeIt(originalMode.length)}]`;
anchor.href = originalMode;
document.querySelector('section.downloads ol').insertAdjacentHTML('afterbegin','<li></li>');
document.querySelector('section.downloads ol li').insertAdjacentElement('afterbegin', anchor );
form.querySelector('button').disabled = false;
form.querySelector('button').innerText = 'Process';
});
reader.readAsText(file);
}
}
</script>
</form>
<fieldset><legend>Download files</legend>
<section class=downloads>
<h1>Note: any files for download here will not persist beyond page reload.</h1>
<ol>
</ol>
<p>
<span class=nothing-yet>Upload a file to create more txt files to download.</span>
<br>
You can also upload your txt files to convert them back to the original.
</section>
</fieldset>
<footer>
<p class=warning>
<i>Note: files that are too big result in issues as the browser runs out of memory. For this reason
I have limited file size to 1Mb.</i>
</footer>
</main>