tapmach 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +115 -26
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -136,6 +136,9 @@ var main_default = `<!DOCTYPE html>
|
|
|
136
136
|
<head>
|
|
137
137
|
<meta charset="UTF-8">
|
|
138
138
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
139
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
140
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
141
|
+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap" rel="stylesheet">
|
|
139
142
|
<title>tapmach</title>
|
|
140
143
|
<script>
|
|
141
144
|
const sleep = (ms) => new Promise(res => setTimeout(res, ms));
|
|
@@ -194,11 +197,30 @@ var main_default = `<!DOCTYPE html>
|
|
|
194
197
|
font-size: 14pt;
|
|
195
198
|
font-family: "JetBrains Mono", monospace;
|
|
196
199
|
|
|
200
|
+
height: 43vh;
|
|
197
201
|
}
|
|
198
202
|
textarea:focus {
|
|
199
203
|
border-color: #444;
|
|
200
204
|
}
|
|
201
205
|
|
|
206
|
+
/* Controls Header */
|
|
207
|
+
.controls-header {
|
|
208
|
+
width: 100%;
|
|
209
|
+
display: flex;
|
|
210
|
+
flex-wrap: wrap;
|
|
211
|
+
align-items: center;
|
|
212
|
+
justify-content: flex-end;
|
|
213
|
+
gap: 20px;
|
|
214
|
+
padding: 10px 20px;
|
|
215
|
+
box-sizing: border-box;
|
|
216
|
+
}
|
|
217
|
+
@media (max-width: 600px) {
|
|
218
|
+
.controls-header {
|
|
219
|
+
justify-content: center;
|
|
220
|
+
gap: 10px;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
202
224
|
/* Run Button */
|
|
203
225
|
.run-btn {
|
|
204
226
|
background-color: var(--cell-bg);
|
|
@@ -219,9 +241,9 @@ var main_default = `<!DOCTYPE html>
|
|
|
219
241
|
gap: 8px;
|
|
220
242
|
transform-origin: center;
|
|
221
243
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
244
|
+
flex-shrink: 0;
|
|
245
|
+
position: static;
|
|
246
|
+
margin: 0;
|
|
225
247
|
}
|
|
226
248
|
.run-btn:hover {
|
|
227
249
|
background-color: #494d64;
|
|
@@ -233,13 +255,12 @@ var main_default = `<!DOCTYPE html>
|
|
|
233
255
|
|
|
234
256
|
/* Speed Control */
|
|
235
257
|
.speed-control {
|
|
236
|
-
position:
|
|
237
|
-
|
|
238
|
-
right: 60px;
|
|
258
|
+
position: static;
|
|
259
|
+
margin: 0;
|
|
239
260
|
display: flex;
|
|
240
261
|
align-items: center;
|
|
241
262
|
gap: 8px;
|
|
242
|
-
font-size:
|
|
263
|
+
font-size: 11pt;
|
|
243
264
|
color: var(--text);
|
|
244
265
|
}
|
|
245
266
|
.speed-control input {
|
|
@@ -258,27 +279,50 @@ var main_default = `<!DOCTYPE html>
|
|
|
258
279
|
margin: 0;
|
|
259
280
|
}
|
|
260
281
|
|
|
282
|
+
/* Lang Control */
|
|
283
|
+
.lang-control {
|
|
284
|
+
position: static;
|
|
285
|
+
margin: 0;
|
|
286
|
+
display: flex;
|
|
287
|
+
align-items: center;
|
|
288
|
+
gap: 8px;
|
|
289
|
+
font-size: 11pt;
|
|
290
|
+
color: var(--text);
|
|
291
|
+
}
|
|
292
|
+
.lang-control select {
|
|
293
|
+
background: var(--cell-bg);
|
|
294
|
+
color: var(--text);
|
|
295
|
+
border: 1px solid rgba(202, 211, 245, 0.1);
|
|
296
|
+
border-radius: 4px;
|
|
297
|
+
padding: 4px 8px;
|
|
298
|
+
font-family: "JetBrains Mono", monospace;
|
|
299
|
+
outline: none;
|
|
300
|
+
cursor: pointer;
|
|
301
|
+
appearance: none;
|
|
302
|
+
-webkit-appearance: none;
|
|
303
|
+
}
|
|
304
|
+
|
|
261
305
|
/* Scrolling Container */
|
|
262
306
|
#viewport {
|
|
263
307
|
width: 98vw;
|
|
264
308
|
max-height: 45vh;
|
|
265
309
|
height: 45vh;
|
|
266
|
-
margin-top:
|
|
310
|
+
margin-top: 1vh;
|
|
267
311
|
overflow-y: auto;
|
|
268
312
|
white-space: nowrap;
|
|
269
313
|
padding: 10px;
|
|
270
314
|
scroll-behavior: smooth;
|
|
271
315
|
background: rgba(0, 0, 0, 0.2);
|
|
272
316
|
border-radius: 4px;
|
|
317
|
+
flex-grow: 1;
|
|
273
318
|
}
|
|
274
319
|
#tape {
|
|
275
320
|
display: grid;
|
|
276
321
|
grid-template-columns: repeat(auto-fill, var(--size));
|
|
277
|
-
gap:
|
|
322
|
+
gap: 2px;
|
|
278
323
|
justify-content: center;
|
|
279
324
|
padding-left: 0;
|
|
280
325
|
padding-right: 0;
|
|
281
|
-
gap: 0;
|
|
282
326
|
}
|
|
283
327
|
|
|
284
328
|
/* Cell Styling */
|
|
@@ -286,7 +330,7 @@ var main_default = `<!DOCTYPE html>
|
|
|
286
330
|
width: var(--size);
|
|
287
331
|
height: var(--size);
|
|
288
332
|
background: var(--cell-bg);
|
|
289
|
-
border: 1px solid
|
|
333
|
+
border: 1px solid rgba(0, 0, 0, 0);
|
|
290
334
|
display: flex;
|
|
291
335
|
align-items: center;
|
|
292
336
|
justify-content: center;
|
|
@@ -295,7 +339,7 @@ var main_default = `<!DOCTYPE html>
|
|
|
295
339
|
flex-shrink: 0;
|
|
296
340
|
}
|
|
297
341
|
.cell.active {
|
|
298
|
-
border:
|
|
342
|
+
border: 2px solid #a6da95;
|
|
299
343
|
}
|
|
300
344
|
|
|
301
345
|
/* Animations */
|
|
@@ -346,22 +390,31 @@ var main_default = `<!DOCTYPE html>
|
|
|
346
390
|
</style>
|
|
347
391
|
</head>
|
|
348
392
|
<body>
|
|
349
|
-
<div class="
|
|
350
|
-
<
|
|
351
|
-
|
|
393
|
+
<div class="controls-header">
|
|
394
|
+
<div class="lang-control">
|
|
395
|
+
<label for="lang">Mode:</label>
|
|
396
|
+
<select id="lang">
|
|
397
|
+
<option value="default">Default</option>
|
|
398
|
+
<option value="shortcodes">Shortcodes</option>
|
|
399
|
+
</select>
|
|
400
|
+
</div>
|
|
401
|
+
<div class="speed-control">
|
|
402
|
+
<label for="speed">Interval (ms):</label>
|
|
403
|
+
<input type="number" id="speed" value="1000" min="0" step="100">
|
|
404
|
+
</div>
|
|
405
|
+
<button class="run-btn">
|
|
406
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
|
|
407
|
+
<path d="M8 5v14l11-7z"/>
|
|
408
|
+
</svg>
|
|
409
|
+
</button>
|
|
352
410
|
</div>
|
|
353
|
-
<button class="run-btn">
|
|
354
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
|
|
355
|
-
<path d="M8 5v14l11-7z"/>
|
|
356
|
-
</svg>
|
|
357
|
-
</button>
|
|
358
411
|
|
|
359
412
|
<div id="viewport">
|
|
360
413
|
<div id="tape"></div>
|
|
361
414
|
</div>
|
|
362
415
|
|
|
363
416
|
<div id="textarea">
|
|
364
|
-
<textarea name="main" id="main-textarea"
|
|
417
|
+
<textarea name="main" id="main-textarea" spellcheck="false" autocorrect="off" autofocus></textarea>
|
|
365
418
|
</div>
|
|
366
419
|
|
|
367
420
|
<script>
|
|
@@ -388,7 +441,7 @@ var main_default = `<!DOCTYPE html>
|
|
|
388
441
|
return tokens;
|
|
389
442
|
}
|
|
390
443
|
|
|
391
|
-
function
|
|
444
|
+
function tokenToCode_Default(code, currentToken, nextToken, speed) {
|
|
392
445
|
if (currentToken === 'create_cell') {
|
|
393
446
|
code.push('create_cell(');
|
|
394
447
|
} else if (currentToken === 'destroy_cell') {
|
|
@@ -410,10 +463,40 @@ var main_default = `<!DOCTYPE html>
|
|
|
410
463
|
}
|
|
411
464
|
}
|
|
412
465
|
|
|
413
|
-
function
|
|
466
|
+
function tokenToCode_Shortcodes(code, currentToken, nextToken, speed) {
|
|
467
|
+
if (currentToken === 'cc') {
|
|
468
|
+
code.push('create_cell(');
|
|
469
|
+
} else if (currentToken === 'dc') {
|
|
470
|
+
code.push('destroy_cell(');
|
|
471
|
+
} else if (currentToken === 'add') {
|
|
472
|
+
code.push('add(')
|
|
473
|
+
} else if (currentToken === 'mov') {
|
|
474
|
+
code.push('move(')
|
|
475
|
+
} else if (!isNaN(currentToken) && currentToken.trim() !== "") {
|
|
476
|
+
if (nextToken !== 'line_end') {
|
|
477
|
+
code.push(\`\${currentToken},\`)
|
|
478
|
+
} else {
|
|
479
|
+
code.push(\`\${currentToken}\`)
|
|
480
|
+
}
|
|
481
|
+
} else if (currentToken === 'line_end') {
|
|
482
|
+
code.push(\`); await sleep(\${speed});\`);
|
|
483
|
+
} else {
|
|
484
|
+
throw Error(\`Can't parse the code, wrong instruction: \${currentToken}\`);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function convertToCode(text, lang = 'default') {
|
|
414
489
|
let tokens = parse(text);
|
|
415
490
|
const speed = document.getElementById('speed').value || 1000;
|
|
416
491
|
let code = ['(async () => {'];
|
|
492
|
+
let tokenToCode = undefined;
|
|
493
|
+
if (lang === 'default') {
|
|
494
|
+
tokenToCode = tokenToCode_Default;
|
|
495
|
+
} else if (lang === 'shortcodes') {
|
|
496
|
+
tokenToCode = tokenToCode_Shortcodes;
|
|
497
|
+
} else {
|
|
498
|
+
tokenToCode = tokenToCode_Default;
|
|
499
|
+
}
|
|
417
500
|
|
|
418
501
|
for (let i = 0; i < tokens.length; i++) {
|
|
419
502
|
tokenToCode(code, tokens[i], tokens[i+1], speed);
|
|
@@ -450,15 +533,20 @@ var main_default = `<!DOCTYPE html>
|
|
|
450
533
|
</script>
|
|
451
534
|
<script>
|
|
452
535
|
const inputField = document.getElementById('speed');
|
|
536
|
+
const lang = document.getElementById('lang');
|
|
453
537
|
|
|
454
538
|
window.addEventListener("load", function() {
|
|
455
|
-
inputField.value = localStorage.getItem('speed');
|
|
539
|
+
inputField.value = localStorage.getItem('speed') || 1000;
|
|
540
|
+
lang.value = localStorage.getItem('selectedLang') || "default";
|
|
456
541
|
});
|
|
457
542
|
|
|
458
|
-
|
|
459
543
|
inputField.addEventListener('input', (e) => {
|
|
460
544
|
localStorage.setItem('speed', e.target.value);
|
|
461
545
|
})
|
|
546
|
+
|
|
547
|
+
lang.addEventListener('change', (e) => {
|
|
548
|
+
localStorage.setItem('selectedLang', e.target.value);
|
|
549
|
+
})
|
|
462
550
|
</script>
|
|
463
551
|
|
|
464
552
|
<script>
|
|
@@ -545,7 +633,8 @@ var main_default = `<!DOCTYPE html>
|
|
|
545
633
|
const button = document.querySelector('.run-btn');
|
|
546
634
|
button.addEventListener('click', async (e) => {
|
|
547
635
|
let text = localStorage.getItem('text-content');
|
|
548
|
-
|
|
636
|
+
let selectedLang = localStorage.getItem('selectedLang');
|
|
637
|
+
eval(convertToCode(text, selectedLang));
|
|
549
638
|
})
|
|
550
639
|
</script>
|
|
551
640
|
</body>
|