sfbinpack 0.6.5

Library to read Stockfish Binpacks
Documentation
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>binpack inspector</title>
    <style>
      *,
      *::before,
      *::after {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }

      :root {
        --bg: #0e0e0f;
        --bg2: #161618;
        --bg3: #1e1e21;
        --border: rgba(255, 255, 255, 0.07);
        --border2: rgba(255, 255, 255, 0.12);
        --text: #e8e6e0;
        --text2: #888880;
        --text3: #555550;
        --green: #7ec98a;
        --red: #e0706b;
        --blue: #7aaddc;
      }

      body {
        font-family: "JetBrains Mono", "Fira Mono", "Cascadia Code", monospace;
        background: var(--bg);
        color: var(--text);
        min-height: 100vh;
        padding: 2.5rem 2rem;
      }

      .shell {
        max-width: 1100px;
        margin: 0 auto;
      }

      .header {
        display: flex;
        align-items: baseline;
        gap: 14px;
        margin-bottom: 2rem;
        border-bottom: 0.5px solid var(--border);
        padding-bottom: 1rem;
      }
      .header h1 {
        font-size: 13px;
        font-weight: 500;
        letter-spacing: 0.1em;
        text-transform: uppercase;
        color: var(--text);
      }
      .header span {
        font-size: 11px;
        color: var(--text3);
      }

      .controls {
        display: flex;
        align-items: center;
        gap: 10px;
        flex-wrap: wrap;
        margin-bottom: 1.25rem;
      }

      .file-label {
        display: inline-flex;
        align-items: center;
        gap: 8px;
        cursor: pointer;
        background: var(--bg2);
        border: 0.5px solid var(--border2);
        border-radius: 5px;
        padding: 7px 14px;
        font-family: inherit;
        font-size: 11px;
        color: var(--text2);
        transition:
          border-color 0.15s,
          color 0.15s;
        white-space: nowrap;
      }
      .file-label:hover {
        border-color: rgba(255, 255, 255, 0.25);
        color: var(--text);
      }
      #file-input {
        display: none;
      }

      #file-name-display {
        font-size: 11px;
        color: var(--text3);
      }



      #parse-button {
        font-family: inherit;
        font-size: 11px;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        padding: 7px 18px;
        cursor: pointer;
        background: var(--bg2);
        border: 0.5px solid var(--border2);
        border-radius: 5px;
        color: var(--text);
        transition:
          background 0.1s,
          border-color 0.15s;
      }
      #parse-button:hover {
        background: var(--bg3);
        border-color: rgba(255, 255, 255, 0.25);
      }
      #example-button {
        font-family: inherit;
        font-size: 11px;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        padding: 7px 18px;
        cursor: pointer;
        background: transparent;
        border: 0.5px solid var(--border2);
        border-radius: 5px;
        color: var(--blue);
        transition:
          background 0.1s,
          border-color 0.15s;
      }
      #example-button:hover {
        background: var(--bg3);
        border-color: rgba(255, 255, 255, 0.25);
      }
      #parse-button:disabled {
        opacity: 0.35;
        cursor: not-allowed;
      }
      #example-button:disabled {
        opacity: 0.35;
        cursor: not-allowed;
      }

      .hint-row {
        display: flex;
        gap: 12px;
        align-items: center;
        flex-wrap: wrap;
        margin-top: -0.4rem;
        margin-bottom: 1.1rem;
        font-size: 11px;
        color: var(--text3);
      }

      .hint-row a {
        color: var(--blue);
        text-decoration: none;
      }

      .hint-row a:hover {
        text-decoration: underline;
      }

      kbd {
        background: var(--bg2);
        border: 0.5px solid var(--border2);
        border-radius: 4px;
        padding: 2px 6px;
        font-size: 10px;
        font-family: inherit;
        color: var(--text);
      }

      .status-bar {
        font-size: 11px;
        color: var(--text3);
        letter-spacing: 0.02em;
        padding: 7px 0;
        border-top: 0.5px solid var(--border);
        border-bottom: 0.5px solid var(--border);
        margin-bottom: 1.5rem;
      }
      .status-bar.ok {
        color: var(--green);
      }
      .status-bar.err {
        color: var(--red);
      }

      .metrics {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 8px;
        margin-bottom: 1.5rem;
      }
      .metric {
        background: var(--bg2);
        border: 0.5px solid var(--border);
        border-radius: 6px;
        padding: 12px 14px;
      }
      .metric-label {
        font-size: 10px;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: var(--text3);
        margin-bottom: 5px;
      }
      .metric-value {
        font-size: 22px;
        font-weight: 500;
        color: var(--text);
      }

      .table-wrap {
        overflow-x: auto;
        border: 0.5px solid var(--border);
        border-radius: 6px;
      }
      table {
        width: 100%;
        border-collapse: collapse;
        font-size: 11px;
      }
      thead th {
        padding: 8px 10px;
        text-align: left;
        font-size: 10px;
        font-weight: 500;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: var(--text3);
        background: var(--bg2);
        border-bottom: 0.5px solid var(--border);
        white-space: nowrap;
      }
      tbody tr {
        border-bottom: 0.5px solid var(--border);
      }
      tbody tr:last-child {
        border-bottom: none;
      }
      tbody tr:hover {
        background: var(--bg2);
      }
      tbody td {
        padding: 7px 10px;
        color: var(--text);
        vertical-align: middle;
      }
      tbody td:first-child {
        color: var(--text3);
        font-size: 10px;
      }
      .fen-cell {
        max-width: 220px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        color: var(--text2) !important;
      }
      .score-cell {
        color: var(--blue) !important;
      }
      .result-cell {
        color: var(--green) !important;
      }

      .empty {
        padding: 3rem;
        text-align: center;
        font-size: 11px;
        color: var(--text3);
        letter-spacing: 0.04em;
      }
    </style>
  </head>
  <body>
    <div class="shell">
      <div class="header">
        <h1>binpack inspector</h1>
        <span>sfbinpack format</span>
      </div>

      <div class="controls">
        <label class="file-label" for="file-input">
          <svg width="12" height="12" viewBox="0 0 16 16" fill="none">
            <path
              d="M2 13V3C2 2.45 2.45 2 3 2H9L14 7V13C14 13.55 13.55 14 13 14H3C2.45 14 2 13.55 2 13Z"
              stroke="currentColor"
              stroke-width="1.2"
            />
            <polyline
              points="9,2 9,7 14,7"
              stroke="currentColor"
              stroke-width="1.2"
              fill="none"
            />
          </svg>
          choose .binpack
        </label>
        <input type="file" id="file-input" accept=".binpack,.bin" />
        <button id="open-file-button" class="file-label">
          <svg width="12" height="12" viewBox="0 0 16 16" fill="none">
            <path
              d="M2 13V3C2 2.45 2.45 2 3 2H9L14 7V13C14 13.55 13.55 14 13 14H3C2.45 14 2 13.55 2 13Z"
              stroke="currentColor"
              stroke-width="1.2"
            />
            <polyline
              points="9,2 9,7 14,7"
              stroke="currentColor"
              stroke-width="1.2"
              fill="none"
            />
          </svg>
          open (file system api)
        </button>
        <span id="file-name-display">no file selected</span>
        <button id="parse-button">parse</button>
        <button id="example-button">use example</button>
      </div>

      <div class="hint-row">
        <span>quick test:</span>
        <a href="./examples/ep1.binpack" download>download example binpack</a>
      </div>

      <div class="status-bar" id="status">awaiting wasm module...</div>

      <div class="status-bar">
        browser mode: reads one BINP chunk at a time with <code>File.slice()</code>
      </div>

      <div class="status-bar" id="navigation-hint" style="display: none; text-align: center;">
        <kbd></kbd> previous chunk &nbsp;|&nbsp; <kbd></kbd> next chunk &nbsp;|&nbsp; <kbd></kbd> previous &nbsp;|&nbsp; <kbd></kbd> next
      </div>

      <div class="metrics" id="metrics-row" style="display: none">
        <div class="metric">
          <div class="metric-label">bytes read</div>
          <div class="metric-value" id="m-bytes"></div>
        </div>
        <div class="metric">
          <div class="metric-label">entries read</div>
          <div class="metric-value" id="m-total"></div>
        </div>
        <div class="metric">
          <div class="metric-label">preview count</div>
          <div class="metric-value" id="m-preview"></div>
        </div>
      </div>

      <div class="table-wrap">
        <div class="empty" id="preview-empty">parse a file to see entries</div>
        <table id="preview-table" style="display: none">
          <thead>
            <tr>
              <th>#</th>
              <th>FEN</th>
              <th>UCI</th>
              <th>Score</th>
              <th>Ply</th>
              <th>Result</th>
              <th>Continuation</th>
              <th>Offset</th>
            </tr>
          </thead>
          <tbody id="preview-tbody"></tbody>
        </table>
      </div>
    </div>

    <script type="module" src="app.js"></script>
  </body>
</html>