OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
 
master @ 74 LINES
 
[ HISTORY ]  [ UP ]
 

// Data-driven ASCII table shared by the markdown transform and the
// Table component.
import { G, checkGrid, len, pad, wrap, wrapHard, type PadSide } from "./ascii";

export type Cell = { text: string; align: PadSide };

export function buildAsciiTable(rows: Cell[][], headerRows: number, width: number)
: string {
  const nCols = Math.max(...rows.map((r) => r.length));
  const norm = rows.map((r) => {
    const out = [...r];
    while (out.length < nCols) out.push({ text: "", align: "end" });
    return out;
  });

  // Natural column widths, then shave the widest until the table fits.
  // Cells wrap to their final column width.
  const colW = Array.from({ length: nCols }, (_, i) =>
    Math.max(1, ...norm.map((r) => len(r[i].text))),
  );
  const total = () => 1 + colW.reduce((s, w) => s + w + 3, 0);
  const MIN_COL = 5;
  while (total() > width && colW.some((w) => w > MIN_COL)) {
    colW[colW.indexOf(Math.max(...colW))]--;
  }

  const edge = (l: string, m: string, r: string, h = G.H) =>
    l + colW.map((w) => h.repeat(w + 2)).join(m) + r;

  // When any row wraps, dashed separators between body rows keep the
  // logical rows readable; all-single-line tables stay compact.
  const cellLines = norm.map((row) => row.map((c, i) => wrap(c.text, colW[i]).spli
t("\n")));
  const anyWrapped = cellLines.some((row) => row.some((l) => l.length > 1));

  const out: string[] = [edge(G.TL, G.TJ, G.TR)];
  norm.forEach((row, ri) => {
    if (anyWrapped && ri > headerRows) out.push(edge(G.LJ, G.X, G.RJ, G.HD));
    const h = Math.max(...cellLines[ri].map((l) => l.length));
    for (let k = 0; k < h; k++) {
      out.push(
        G.V +
          row.map((c, i) => ` ${pad(cellLines[ri][i][k] ?? "", colW[i], c.align)} 
`).join(G.V) +
          G.V,
      );
    }
    if (ri === headerRows - 1) out.push(edge(G.LJ, G.X, G.RJ));
  });
  out.push(edge(G.BL, G.BJ, G.BR));
  return checkGrid(out.join("\n"), width, "table");
}

// A table too wide for its frame transposed: each body row becomes a
// key/value block keyed by the header row, so any column count fits.
export function buildTransposedTable(rows: Cell[][], headerRows: number, width: nu
mber): string {
  const keys = rows[headerRows - 1].map((c) => c.text);
  const body = rows.slice(headerRows);
  const inner = width - 4;
  const keyW = Math.min(Math.max(1, ...keys.map(len)), Math.max(1, Math.floor((inn
er - 2) / 2)));
  const valW = inner - keyW - 2;

  const out: string[] = [`${G.TL}${G.H.repeat(width - 2)}${G.TR}`];
  body.forEach((row, ri) => {
    if (ri) out.push(`${G.LJ}${G.HD.repeat(width - 2)}${G.RJ}`);
    keys.forEach((key, i) => {
      const kLines = wrapHard(key, keyW).split("\n");
      const vLines = wrapHard(row[i]?.text ?? "", valW).split("\n");
      for (let j = 0; j < Math.max(kLines.length, vLines.length); j++) {
        out.push(`${G.V} ${pad(kLines[j] ?? "", keyW)}  ${pad(vLines[j] ?? "", val
W)} ${G.V}`);
      }
    });
  });
  out.push(`${G.BL}${G.H.repeat(width - 2)}${G.BR}`);
  return checkGrid(out.join("\n"), width, "transposed table");
}

// Data-driven ASCII table shared by the mar
kdown transform and the
// Table component.
import { G, checkGrid, len, pad, wrap, wrapH
ard, type PadSide } from "./ascii";

export type Cell = { text: string; align: Pa
dSide };

export function buildAsciiTable(rows: Cell[]
[], headerRows: number, width: number): stri
ng {
  const nCols = Math.max(...rows.map((r) => 
r.length));
  const norm = rows.map((r) => {
    const out = [...r];
    while (out.length < nCols) out.push({ te
xt: "", align: "end" });
    return out;
  });

  // Natural column widths, then shave the w
idest until the table fits.
  // Cells wrap to their final column width.
  const colW = Array.from({ length: nCols },
 (_, i) =>
    Math.max(1, ...norm.map((r) => len(r[i].
text))),
  );
  const total = () => 1 + colW.reduce((s, w)
 => s + w + 3, 0);
  const MIN_COL = 5;
  while (total() > width && colW.some((w) =>
 w > MIN_COL)) {
    colW[colW.indexOf(Math.max(...colW))]--;
  }

  const edge = (l: string, m: string, r: str
ing, h = G.H) =>
    l + colW.map((w) => h.repeat(w + 2)).joi
n(m) + r;

  // When any row wraps, dashed separators b
etween body rows keep the
  // logical rows readable; all-single-line 
tables stay compact.
  const cellLines = norm.map((row) => row.ma
p((c, i) => wrap(c.text, colW[i]).split("\n"
)));
  const anyWrapped = cellLines.some((row) =>
 row.some((l) => l.length > 1));

  const out: string[] = [edge(G.TL, G.TJ, G.
TR)];
  norm.forEach((row, ri) => {
    if (anyWrapped && ri > headerRows) out.p
ush(edge(G.LJ, G.X, G.RJ, G.HD));
    const h = Math.max(...cellLines[ri].map(
(l) => l.length));
    for (let k = 0; k < h; k++) {
      out.push(
        G.V +
          row.map((c, i) => ` ${pad(cellLine
s[ri][i][k] ?? "", colW[i], c.align)} `).joi
n(G.V) +
          G.V,
      );
    }
    if (ri === headerRows - 1) out.push(edge
(G.LJ, G.X, G.RJ));
  });
  out.push(edge(G.BL, G.BJ, G.BR));
  return checkGrid(out.join("\n"), width, "t
able");
}

// A table too wide for its frame transposed
: each body row becomes a
// key/value block keyed by the header row, 
so any column count fits.
export function buildTransposedTable(rows: C
ell[][], headerRows: number, width: number):
 string {
  const keys = rows[headerRows - 1].map((c) 
=> c.text);
  const body = rows.slice(headerRows);
  const inner = width - 4;
  const keyW = Math.min(Math.max(1, ...keys.
map(len)), Math.max(1, Math.floor((inner - 2
) / 2)));
  const valW = inner - keyW - 2;

  const out: string[] = [`${G.TL}${G.H.repea
t(width - 2)}${G.TR}`];
  body.forEach((row, ri) => {
    if (ri) out.push(`${G.LJ}${G.HD.repeat(w
idth - 2)}${G.RJ}`);
    keys.forEach((key, i) => {
      const kLines = wrapHard(key, keyW).spl
it("\n");
      const vLines = wrapHard(row[i]?.text ?
? "", valW).split("\n");
      for (let j = 0; j < Math.max(kLines.le
ngth, vLines.length); j++) {
        out.push(`${G.V} ${pad(kLines[j] ?? 
"", keyW)}  ${pad(vLines[j] ?? "", valW)} ${
G.V}`);
      }
    });
  });
  out.push(`${G.BL}${G.H.repeat(width - 2)}$
{G.BR}`);
  return checkGrid(out.join("\n"), width, "t
ransposed table");
}
 
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET