Review round 4 (reddit, 6 October 2026): eight personas, 2 fatal, 11 serious, 9 minor; the believe-list; site/ledger.html drafted from the ledger (167 entries) with its generator; six public-text fixes
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
ebdd42ea62
commit
02d984cc75
5 changed files with 1504 additions and 6 deletions
|
|
@ -369,7 +369,7 @@ pre{margin:0;font-family:var(--f-mono);font-size:13px;line-height:1.6;color:var(
|
|||
<div class="livestrip" id="livestrip" aria-live="off">
|
||||
<div class="livestrip-head"><span class="dot"></span><a href="/live">live devnet</a></div>
|
||||
<div class="livestrip-grid">
|
||||
<div class="tile"><div class="v" id="ls-miners">0</div><div class="k">miners active</div></div>
|
||||
<div class="tile"><div class="v" id="ls-miners">0</div><div class="k">vote keys active in 10 min (a card runs several)</div></div>
|
||||
<div class="tile"><div class="v" id="ls-bps">0.0</div><div class="k">blocks / s</div></div>
|
||||
<div class="tile"><div class="v" id="ls-hash">0.0 MH/s</div><div class="k">hash rate</div></div>
|
||||
<div class="tile"><div class="v" id="ls-blocks">0</div><div class="k">devnet blocks</div></div>
|
||||
|
|
@ -489,7 +489,7 @@ pre{margin:0;font-family:var(--f-mono);font-size:13px;line-height:1.6;color:var(
|
|||
<figure class="frame" style="margin:0">
|
||||
<div class="bar"><i></i><i></i><i></i><b><span data-product="app">Igneum Miner</span></b></div>
|
||||
<img src="/img/miner-dashboard.webp" width="2360" height="1480" alt="The miner dashboard: hash rate, blocks found, node synced, a countdown to the next program, the block chart, the Apple M5 Max card mining, node and finality panels" loading="lazy" decoding="async">
|
||||
<figcaption><span data-product="caption">Igneum Ember (the app is still labelled Igneum Miner until 0.3.6)</span> on an Apple M5 Max, live devnet, 5 Oct 2026.</figcaption>
|
||||
<figcaption><span data-product="caption">Igneum Ember (the app window still says Igneum Miner at 0.3.13)</span> on an Apple M5 Max, live devnet, 5 Oct 2026.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div class="split-copy reveal">
|
||||
|
|
|
|||
1285
site/ledger.html
Normal file
1285
site/ledger.html
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -393,11 +393,11 @@ body.all .pager{display:none}
|
|||
<thead><tr><th>Layer</th><th>State</th><th>Since</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>Mining lottery</td><td>A new program every hour on Apple, NVIDIA and AMD cards, compiled ahead, no pause and no rejected block at the boundary</td><td class="num">4 Oct 2026, first live swap</td></tr>
|
||||
<tr><td>Blocks</td><td>About one a second</td><td class="num">genesis, 3 Oct 2026</td></tr>
|
||||
<tr><td>Blocks</td><td>About one a second with the full fleet; 0.65 a second over the hour to 16:00 UTC on 6 Oct 2026 with one PC off (the live page's hour count, 2,325 blocks)</td><td class="num">genesis, 3 Oct 2026</td></tr>
|
||||
<tr><td>Difficulty</td><td>Rule v2, a 600-second reference window, switched on by height under the running chain with no fork and no restart of the chain</td><td class="num">DAA 33,000, 4 Oct 2026</td></tr>
|
||||
<tr><td>Finality</td><td>Rule v2: a checkpoint every 30 s of chain, locked at two thirds of all 30-day weight. First live lock: checkpoint 242 at 77.4% of all weight, 17 vote keys</td><td class="num">4 Oct 2026</td></tr>
|
||||
<tr><td>Proving</td><td>v0 active: shards are assigned to miners' keys, proven on their cards, and the records are carried in blocks</td><td class="num">DAA 84,100, 5 Oct 2026</td></tr>
|
||||
<tr><td>Ember</td><td>The one-click miner on the fleet, version 0.3.5; 0.3.6 staged</td><td class="num">4 Oct 2026, first install</td></tr>
|
||||
<tr><td>Ember</td><td>The one-click miner on the fleet, version 0.3.13 (6 Oct 2026); the app window still says Igneum Miner</td><td class="num">4 Oct 2026, first install</td></tr>
|
||||
<tr><td>Wallet</td><td>Igneum Wallet 0.1.1 on macOS</td><td class="num">5 Oct 2026</td></tr>
|
||||
</tbody>
|
||||
</table></div>
|
||||
|
|
@ -656,7 +656,7 @@ body.all .pager{display:none}
|
|||
<li><strong>Nothing needs a scheduled upgrade.</strong> The mining program, the dataset and the finality rules run themselves for ever. If the community ever ships an improvement, a better proof system or a block-rate step, it is published with test vectors at least three months ahead and activates only when 90% of blocks signal readiness. Developers can write code. Only miners can turn it on.</li>
|
||||
<li><strong>Miners set what genesis leaves open.</strong> A parameter that the genesis rules leave to miners is set by signalling: a proposal passes or fails on 60% of hashrate over two weeks. There is no fund to vote on and no fee to any team, foundation or fund.</li>
|
||||
<li><strong>Pools can be bypassed on transaction choice.</strong> Igneum ships Stratum v2 job declaration from day one, so a miner chooses its own transactions when its pool supports it. Pools can decline, and vote keys stay with the pool. Designed: the pool protocol is specification section 9, not yet run by any pool.</li>
|
||||
<li><strong>There are no admin keys in consensus.</strong> Nothing in consensus can be paused, upgraded or reversed by any key. There is no foundation allocation to vote with and no stake to buy. The genesis apps are contracts, and each publishes its own upgrade and key policy before launch; the bridge's is the one to read. Designed, open item O-5.4.</li>
|
||||
<li><strong>There are no admin keys in consensus.</strong> Nothing in consensus can be paused, upgraded or reversed by any key. There is no foundation allocation to vote with and no stake to buy. The genesis apps are contracts, and each publishes its own upgrade and key policy before launch; the bridge's is the one to read. Designed, open item O-5.4. On the devnet the activation heights and one execution-state restart (6 October 2026) reach every node through the signed update manifest, so on the devnet the release key acts as the operator; the sentence above holds for mainnet consensus only once that path is closed, and the public testnet terms will say which parameters still travel that way.</li>
|
||||
<li><strong>The chain runs without its founders.</strong> Blocks, proofs and finality need no one. A second independent node client is the first priority after launch, and anyone can build it.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ pre b{color:var(--molten);font-weight:500}
|
|||
<figure class="frame" style="margin:0">
|
||||
<div class="bar"><i></i><i></i><i></i><b><span data-product="app">Igneum Miner</span></b></div>
|
||||
<img src="/img/miner-dashboard.webp" width="2360" height="1540" alt="The miner dashboard: hash rate, blocks found, node synced, a countdown to the next program, the block chart, the Apple M5 Max card mining, node and finality panels" fetchpriority="high" decoding="async">
|
||||
<figcaption><span data-product="caption">Igneum Ember (the app is still labelled Igneum Miner until 0.3.6)</span> on an Apple M5 Max, live devnet, 5 Oct 2026.</figcaption>
|
||||
<figcaption><span data-product="caption">Igneum Ember (the app window still says Igneum Miner at 0.3.13)</span> on an Apple M5 Max, live devnet, 5 Oct 2026.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
213
tools/ledger-page.mjs
Normal file
213
tools/ledger-page.mjs
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
#!/usr/bin/env node
|
||||
// Renders docs/fud-ledger.md as the public page site/ledger.html: every entry, the critic's words, what was done, the
|
||||
// status and the date, with the count table on top. Nothing is dropped and nothing is softened; the only rewrites are
|
||||
// the identity and provider terms of site/forbidden-strings.txt (the tree's public-export rule), applied in place.
|
||||
// Usage: node tools/ledger-page.mjs [docs/fud-ledger.md] [site/ledger.html]
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
import { join, dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url));
|
||||
const root = join(here, '..');
|
||||
const src = process.argv[2] || join(root, 'docs', 'fud-ledger.md');
|
||||
const out = process.argv[3] || join(root, 'site', 'ledger.html');
|
||||
|
||||
const esc = s => s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
|
||||
// Identity and provider terms. The criticism keeps its force; the operational name goes.
|
||||
const SCRUB = [
|
||||
[/\bJosh's\b/g, "the owner's"], [/\bJosh\b/g, 'the owner'],
|
||||
[/\bHetzner\b/g, 'the cloud provider'], [/\bGoDaddy\b/g, 'the US registrar'], [/\bVercel\b/g, 'the host'],
|
||||
[/CLAUDE\.md/g, 'the project rules file'], [/\.claude\/agents\/?/g, 'the agent files '],
|
||||
[/\/opt\/igneum[^\s`,;)]*/g, 'the prover host directory'], [/dl\.igneum\.network/g, 'the downloads host'],
|
||||
[/log[-_]intake[-_]?key|LOG_INTAKE_KEY|intake[_-]?key/gi, 'the log key'], [/log-intake|LOG_INTAKE/g, 'the log intake'],
|
||||
[/\bintake id\b/g, 'the upload id'], [/\+0100/g, 'a local-time offset'], [/\bBST\b/g, 'local time'],
|
||||
[/\bTailscale\b|\bts\.net\b/g, 'the private network'], [/DESKTOP-[A-Z0-9]{7}/g, 'the PC'], [/MacBook/g, 'the laptop'],
|
||||
[/\bhcloud\b/g, 'the cloud CLI'], [/igneum-seed[0-9]*/g, 'the seed node'], [/\/root\//g, '/<home>/'],
|
||||
[/\/Users\/[^\s/`]+/g, '~'], [/C:\\Users\\[^\s\\`]+/g, '%USERPROFILE%'], [/~\/Desktop/g, '~/<folder>'],
|
||||
[/192\.168\.\d+\.\d+/g, '<lan address>'], [/100\.\d+\.\d+\.\d+/g, '<private address>'],
|
||||
];
|
||||
const scrub = s => SCRUB.reduce((t, [re, r]) => t.replace(re, r), s);
|
||||
|
||||
// Inline markdown: code spans and links only; the ledger uses nothing else inside a status line.
|
||||
function inline(s) {
|
||||
let t = esc(s);
|
||||
t = t.replace(/`([^`]+)`/g, (m, c) => `<code>${c}</code>`);
|
||||
t = t.replace(/\[([^\]]+)\]\((https?:[^)]+)\)/g, (m, a, u) => `<a href="${u}" rel="noopener">${a}</a>`);
|
||||
return t;
|
||||
}
|
||||
|
||||
const lines = readFileSync(src, 'utf8').split('\n');
|
||||
const entries = [];
|
||||
let cur = null;
|
||||
for (const l of lines) {
|
||||
const m = /^### ([A-Z]\d+)\. (.*)$/.exec(l);
|
||||
if (m) { cur = { id: m[1], title: m[2].trim(), quote: '', status: '', answer: '' }; entries.push(cur); continue; }
|
||||
if (!cur) continue;
|
||||
const s = l.trim();
|
||||
if (!cur.quote && s.startsWith('"')) cur.quote = s.replace(/^"|"$/g, '');
|
||||
else if (!cur.status && s.startsWith('Status:')) cur.status = s.slice(7).trim();
|
||||
else if (!cur.answer && s.startsWith('Answer:')) cur.answer = s.slice(7).trim();
|
||||
}
|
||||
|
||||
const SECTION = { M: 'Mining and chips', F: 'Finality and attacks', P: 'Proving and the zkEVM', E: 'Economics and the coin', G: 'Governance and the founders', C: 'Comparisons', L: 'Legal and regulatory', X: 'Launch and operations', D: 'Builders' };
|
||||
|
||||
function bucket(status) {
|
||||
const s = status.toLowerCase();
|
||||
if (/^(fixed|rolled out|rule fixed|spec fixed|rule implemented|rule written|written|designed)/.test(s)) return 'Fixed or built';
|
||||
if (s.startsWith('conceded')) return 'Conceded';
|
||||
if (s.startsWith('answered by design')) return 'Answered by design';
|
||||
if (/^(answered with evidence|measured|simulation half)/.test(s)) return 'Answered with evidence';
|
||||
if (/^(closed|decided)/.test(s)) return 'Closed by rule or decided';
|
||||
if (s.startsWith('open')) return 'Open';
|
||||
return 'Other';
|
||||
}
|
||||
function statusWord(status) {
|
||||
const m = /^([^(:.]+?)(?=\s*[(:.]|$)/.exec(status);
|
||||
return (m ? m[1] : status).trim();
|
||||
}
|
||||
function dateOf(status) {
|
||||
const m = /(\d{1,2} October 2026)/.exec(status);
|
||||
return m ? m[1] : '3 October 2026';
|
||||
}
|
||||
|
||||
const ORDER = ['Open', 'Conceded', 'Fixed or built', 'Closed by rule or decided', 'Answered with evidence', 'Answered by design', 'Other'];
|
||||
const MEANING = {
|
||||
'Open': 'Nothing has settled it yet. The entry names what will',
|
||||
'Conceded': 'The critic is right. "Stated" means the public text says so; "not yet stated" means it does not yet',
|
||||
'Fixed or built': 'A code, spec or text change answers it, with the commit or the page named',
|
||||
'Closed by rule or decided': 'A consensus rule or a decision by the owner answers it, dated',
|
||||
'Answered with evidence': 'A measurement or a simulation exists and is named',
|
||||
'Answered by design': 'A design rule answers it; no measurement is possible yet',
|
||||
'Other': 'A status outside the six above, read the line',
|
||||
};
|
||||
const counts = {};
|
||||
for (const e of entries) { const b = bucket(e.status); counts[b] = (counts[b] || 0) + 1; }
|
||||
|
||||
const partial = name => readFileSync(join(root, 'site', 'partials', name), 'utf8').trim();
|
||||
const HEAD = partial('head.html'), NAV = partial('nav.html'), FOOT = partial('footer.html');
|
||||
|
||||
const intro = `This is every criticism the project expects, in the critic's words, with what was done about it and the date. ${entries.length} entries since 3 October 2026. Entries are never deleted; a status that changes keeps its history on the line. Where the critic was right the entry says Conceded. Where nothing has been done it says Open and names what settles it. The founder mined through the GPU years. Ethereum's move to proof of stake in September 2022 ended that income and the miners' place in that chain. This is one person building, with AI systems doing the engineering, the coin he wanted to exist for miners: GPU-mined, the miners are the provers, no founder allocation, every cost stated. Help is welcome and a team is wanted: cryptographers, node engineers, miners who will test. This ledger is the application form: pick an open row and write to <a href="mailto:hello@igneum.network">hello@igneum.network</a> with its id.`;
|
||||
|
||||
const countRows = ORDER.filter(b => counts[b]).map(b => `<tr><td class="num">${counts[b]}</td><td><button type="button" class="chip" data-filter="${esc(b)}">${esc(b)}</button></td><td>${esc(MEANING[b])}</td></tr>`).join('\n');
|
||||
|
||||
let body = '';
|
||||
let lastSec = '';
|
||||
for (const e of entries) {
|
||||
const sec = SECTION[e.id[0]] || e.id[0];
|
||||
if (sec !== lastSec) { body += `<h2 id="${e.id[0].toLowerCase()}">${esc(sec)}</h2>\n`; lastSec = sec; }
|
||||
const b = bucket(e.status);
|
||||
const word = statusWord(scrub(e.status));
|
||||
const rest = scrub(e.status).slice(word.length).replace(/^[\s(:.]+/, '').trim();
|
||||
body += `<article class="entry" id="${e.id}" data-bucket="${esc(b)}">
|
||||
<div class="head"><span class="id">${e.id}</span><h3>${inline(scrub(e.title))}</h3><span class="date">${esc(dateOf(e.status))}</span></div>
|
||||
<blockquote>${inline(scrub(e.quote))}</blockquote>
|
||||
<div class="status"><span class="badge b-${b.toLowerCase().replace(/[^a-z]+/g, '-')}">${esc(word)}</span>${rest ? ` <span class="did">${inline(rest)}</span>` : ''}</div>
|
||||
${e.answer ? `<details><summary>The answer as first written</summary><p>${inline(scrub(e.answer))}</p></details>` : ''}
|
||||
</article>\n`;
|
||||
}
|
||||
|
||||
const html = `<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<title>Igneum ledger: every criticism, answered</title>
|
||||
<meta name="description" content="Every criticism Igneum expects, in the critic's words, with what was done, the status and the date. ${entries.length} entries. Nothing deleted, nothing softened.">
|
||||
<link rel="canonical" href="https://igneum.network/ledger">
|
||||
<meta name="theme-color" content="#0C0C0E">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:site_name" content="Igneum">
|
||||
<meta property="og:title" content="Igneum ledger: every criticism, answered">
|
||||
<meta property="og:description" content="${entries.length} criticisms in the critic's words, with what was done, the status and the date.">
|
||||
<meta property="og:url" content="https://igneum.network/ledger">
|
||||
<meta property="og:image" content="https://igneum.network/og-small.png?v=3">
|
||||
<meta property="og:image:width" content="256">
|
||||
<meta property="og:image:height" content="256">
|
||||
<meta property="og:image:alt" content="Igneum. Mined by GPUs. Proven by fire.">
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:title" content="Igneum ledger: every criticism, answered">
|
||||
<meta name="twitter:description" content="${entries.length} criticisms in the critic's words, with what was done, the status and the date.">
|
||||
<meta name="twitter:image" content="https://igneum.network/og-small.png?v=3">
|
||||
<meta name="twitter:image:alt" content="Igneum. Mined by GPUs. Proven by fire.">
|
||||
<link rel="icon" href="/favicon.ico" sizes="48x48">
|
||||
<link rel="icon" href="/favicon-32.png" type="image/png" sizes="32x32">
|
||||
<link rel="icon" href="/icon-192.png" type="image/png" sizes="192x192">
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="manifest" href="/site.webmanifest">
|
||||
<!-- head:start -->
|
||||
${HEAD}
|
||||
<!-- head:end -->
|
||||
<style>
|
||||
:root{--obsidian:#0C0C0E;--graphite:#16161A;--line:#2A2A30;--line-2:#3A3A42;--ember:#F2541B;--molten:#FFB35C;--bone:#F4F1EC;--ash:#9A9A9E;--ink-2:#C9C7C2;--max:1200px;--gutter:clamp(16px,4vw,32px);--sec:clamp(40px,6vw,72px)}
|
||||
*{box-sizing:border-box}
|
||||
body{margin:0;background:var(--obsidian);color:var(--bone);font-family:var(--f-sans);font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased;overflow-x:hidden}
|
||||
a{color:var(--ember);text-decoration:none}a:hover{color:var(--molten)}
|
||||
.wrap{max-width:var(--max);margin:0 auto;padding-inline:var(--gutter)}
|
||||
.eyebrow{font-family:var(--f-mono);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--ash)}
|
||||
h1{font-family:var(--f-display);font-weight:900;font-size:clamp(30px,5vw,52px);line-height:1.08;margin:10px 0 18px}
|
||||
h2{font-family:var(--f-display);font-weight:700;font-size:clamp(22px,3vw,30px);margin:var(--sec) 0 16px;padding-top:8px;border-top:1px solid var(--line);scroll-margin-top:84px}
|
||||
h3{font-family:var(--f-sans);font-weight:600;font-size:17px;margin:0;flex:1 1 auto;min-width:0}
|
||||
.intro{font-size:17px;color:var(--ink-2);max-width:76ch;margin:0 0 24px}
|
||||
.tbl{overflow-x:auto;border:1px solid var(--line);border-radius:16px;background:var(--graphite);margin:0 0 20px}
|
||||
table{border-collapse:collapse;width:100%;font-size:15px;min-width:520px}
|
||||
th,td{padding:11px 14px;text-align:left;vertical-align:top;border-bottom:1px solid var(--line)}
|
||||
th{font-family:var(--f-mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--ash);font-weight:500}
|
||||
tr:last-child td{border-bottom:0}
|
||||
td.num{font-family:var(--f-display);font-weight:700;font-size:22px;color:var(--ember);white-space:nowrap}
|
||||
.chip{background:none;border:1px solid var(--line-2);color:var(--bone);border-radius:999px;padding:6px 12px;font:inherit;font-size:14px;cursor:pointer}
|
||||
.chip:hover,.chip.on{border-color:var(--ember);color:var(--molten)}
|
||||
.toolbar{display:flex;flex-wrap:wrap;gap:8px 14px;align-items:center;margin:0 0 8px;font-size:14px;color:var(--ash)}
|
||||
.toolbar input{background:var(--graphite);border:1px solid var(--line-2);color:var(--bone);border-radius:10px;padding:8px 12px;font:inherit;font-size:14px;min-width:220px}
|
||||
.sections{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:14px;margin:0 0 8px}
|
||||
.entry{border:1px solid var(--line);border-radius:14px;background:var(--graphite);padding:16px 18px;margin:0 0 12px;scroll-margin-top:84px}
|
||||
.entry.hide{display:none}
|
||||
.head{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 12px}
|
||||
.id{font-family:var(--f-mono);font-size:13px;color:var(--molten);flex:0 0 auto}
|
||||
.date{font-family:var(--f-mono);font-size:12px;color:var(--ash);flex:0 0 auto}
|
||||
blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);color:var(--ink-2);font-style:italic}
|
||||
.status{font-size:15px;color:var(--ink-2)}
|
||||
.badge{display:inline-block;font-family:var(--f-mono);font-size:12px;letter-spacing:.06em;text-transform:uppercase;padding:3px 8px;border-radius:6px;border:1px solid var(--line-2);color:var(--bone);margin-right:6px;vertical-align:middle}
|
||||
.b-open{border-color:var(--ember);color:var(--ember)}.b-conceded{border-color:var(--molten);color:var(--molten)}.b-fixed-or-built{border-color:#5cb85c;color:#8fd48f}
|
||||
code{font-family:var(--f-mono);font-size:13px;color:var(--bone);background:#0C0C0E;padding:1px 5px;border-radius:5px}
|
||||
details{margin-top:8px;font-size:14px;color:var(--ash)}summary{cursor:pointer;color:var(--ash)}details p{margin:8px 0 0;color:var(--ink-2)}
|
||||
.foot{margin-top:var(--sec)}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- nav:start -->
|
||||
${NAV}
|
||||
<!-- nav:end -->
|
||||
<main id="main" class="wrap">
|
||||
<header style="padding-block:clamp(40px,6vw,72px) 8px">
|
||||
<div class="eyebrow">Ledger · ${entries.length} entries · regenerated from the repository</div>
|
||||
<h1>Every criticism, answered or conceded</h1>
|
||||
<p class="intro">${intro}</p>
|
||||
</header>
|
||||
<div class="tbl"><table>
|
||||
<thead><tr><th>Count</th><th>Status</th><th>Meaning</th></tr></thead>
|
||||
<tbody>
|
||||
${countRows}
|
||||
<tr><td class="num">${entries.length}</td><td><button type="button" class="chip" data-filter="">All</button></td><td>Every entry. The sections: ${Object.entries(SECTION).map(([k, v]) => `<a href="#${k.toLowerCase()}">${esc(v)}</a>`).join(', ')}</td></tr>
|
||||
</tbody></table></div>
|
||||
<div class="toolbar"><input type="search" id="q" placeholder="Search the ledger" aria-label="Search the ledger"><span id="shown"></span></div>
|
||||
${body}
|
||||
<p class="intro" style="margin-top:var(--sec)">Source: <code>docs/fud-ledger.md</code> in the repository, rendered by <code>tools/ledger-page.mjs</code>. A criticism that is not here, or that shows an entry is wrong, is added with credit if wanted: <a href="mailto:hello@igneum.network">hello@igneum.network</a> or <a href="https://github.com/igneum-network/spec/issues" rel="noopener">an issue on the specification repository</a>.</p>
|
||||
</main>
|
||||
<!-- footer:start -->
|
||||
${FOOT}
|
||||
<!-- footer:end -->
|
||||
<script>
|
||||
(function(){
|
||||
var chips=document.querySelectorAll('.chip'),entries=document.querySelectorAll('.entry'),q=document.getElementById('q'),shown=document.getElementById('shown'),f='';
|
||||
function apply(){var t=(q.value||'').toLowerCase(),n=0;entries.forEach(function(e){var ok=(!f||e.getAttribute('data-bucket')===f)&&(!t||e.textContent.toLowerCase().indexOf(t)>=0);e.classList.toggle('hide',!ok);if(ok)n++;});shown.textContent=n+' of '+entries.length+' shown';chips.forEach(function(c){c.classList.toggle('on',c.getAttribute('data-filter')===f);});}
|
||||
chips.forEach(function(c){c.addEventListener('click',function(){f=c.getAttribute('data-filter')||'';apply();});});
|
||||
q.addEventListener('input',apply);apply();
|
||||
if(location.hash){var el=document.getElementById(location.hash.slice(1));if(el)el.scrollIntoView();}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
writeFileSync(out, html);
|
||||
console.log(`${out}: ${entries.length} entries, counts ${JSON.stringify(counts)}`);
|
||||
Loading…
Reference in a new issue