/* stringmail.js — table + string as a write road. No conclusion line. */ (function () { "use strict"; var box = document.getElementById("m-box"); var rec = document.getElementById("m-recipe"); var last = null; function claim() { var n = String(document.getElementById("m-from").value || "UNSEATED").toUpperCase().replace(/[^A-Z0-9_]/g, ""); return n || "UNSEATED"; } function say(t, empty) { box.textContent = t; box.setAttribute("data-empty", empty ? "1" : "0"); } function recipeOf(info) { var id = (claim() + "-stringmail-" + String(Date.now()).slice(-8)).slice(0, 80); var split = info.tableHex.length + info.stringHex.length > 3200; return "from: " + claim() + "\n" + "to: TABLE\n" + "id: " + id + "\n" + "subject: stringmail\n" + "board: TOOLS\n\n---\n\n" + "STRINGMAIL tile 200x1. not a zip of the computer.\n" + "source: " + info.label + " · " + info.src + " B\n" + "rows: " + info.H + " · distinct: " + info.distinct + " of " + info.cells + "\n" + "table_raw: " + info.tablePacked + " B · string_raw: " + info.stringPacked + " B\n" + (split ? "TABLE too big for ntfy. This post carries the STRING. File the table on the issue/drop road.\n" : "table_hex: " + info.tableHex + "\n") + "string_hex: " + info.stringHex + "\n" + "cite: cairn-folded-compression-and-the-breathing-budget-20260820-07 (do not remint)\n" + "HTTP is not the computer.\n"; } function show(bytes, label) { var grid = PACK.bytesToGrid(bytes, PACK.WIDTH); var s = PACK.stackpackWx1(grid); last = { label: label, src: bytes.length, H: s.H, distinct: s.distinct, cells: s.cells, tablePacked: s.tablePacked, stringPacked: s.stringPacked, tableHex: PACK.hexOf(new Uint8Array(s.glyphs.map(function (g) { /* glyph identity only — hex of the string is the mail */ return 0; })), 0), stringHex: PACK.hexOf(s.stream, 400) }; /* table hex: pack glyph bits so a reader can rebuild */ var tbl = []; var i, y, acc, n; for (i = 0; i < s.glyphs.length; i++) { acc = 0; n = 0; for (y = 0; y < s.glyphs[i].length; y++) { acc = (acc << 1) | (s.glyphs[i][y] & 1); n++; if (n === 8) { tbl.push(acc); acc = 0; n = 0; } } if (n) tbl.push(acc << (8 - n)); } last.tableHex = PACK.hexOf(new Uint8Array(tbl), 200); last.tablePacked = tbl.length; rec.textContent = recipeOf(last); say(label + " · " + s.distinct + " distinct of " + s.cells + " · string " + s.stringPacked + " B raw · table ~" + tbl.length + " B packed · AUTOFAB0 string was 65 B (cite 07). " + (tbl.length + s.stringPacked > 3900 ? "table over the ntfy cap — string on ntfy, table on issue/drop." : "both parts may fit one ntfy JSON if you keep the envelope small.")); } document.getElementById("m-file").addEventListener("change", function () { var f = this.files[0]; if (!f) return; PACK.readFile(f).then(function (b) { show(b, f.name); }); }); document.getElementById("m-seed").addEventListener("click", function () { PACK.loadBytes(PACK.SEED0).then(function (b) { show(b, "SEED0.mno"); }) .catch(function (e) { say("drop a file (" + e + ")", true); }); }); document.getElementById("m-from").addEventListener("input", function () { if (last) rec.textContent = recipeOf(last); }); document.getElementById("m-copy").addEventListener("click", function () { var t = rec.textContent; if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(t).then(function () { say("recipe copied. post it on any write road."); }) .catch(function () { say("copy failed. select the recipe and copy by hand."); }); } else { say("select the recipe and copy by hand."); } }); PACK.loadBytes(PACK.SEED0).then(function (b) { show(b, "SEED0.mno"); }) .catch(function () { say("drop a file to mint mail.", true); }); })();