# core/formatters/snapshot.formatter.ts

> 23 lines of code and 8 definitions.

Tree: Project Scripts
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/scripts#file-scripts-core-formatters-snapshot-formatter-ts
Source text: https://banes-lab.com/source/scripts/core/formatters/snapshot.formatter.ts.txt

Listed in [core/formatters](https://banes-lab.com/api/source/scripts/core/formatters.md), after [core/formatters/rate.formatter.ts](https://banes-lab.com/source/scripts/core/formatters/rate.formatter.ts.md) and before [core/formatters/viewport.formatter.ts](https://banes-lab.com/source/scripts/core/formatters/viewport.formatter.ts.md).

## Definitions

- `logLines` (lexical_declaration, line 8, exported)
- `Tally` (interface_declaration, line 3)
- `tally` (lexical_declaration, line 9, exported)
- `key` (lexical_declaration, line 11, exported)
- `held` (lexical_declaration, line 12, exported)
- `rows` (lexical_declaration, line 19, exported)
- `times` (lexical_declaration, line 20, exported)
- `where` (lexical_declaration, line 21, exported)

## Contained in

- [core/formatters](https://banes-lab.com/anatomy/scripts/folder-scripts-core-formatters.md)

## Used by

- [core/persistence/snapshot.persistence.ts](https://banes-lab.com/source/scripts/core/persistence/snapshot.persistence.ts.md)

## Linked from

- [core/persistence](https://banes-lab.com/anatomy/scripts/folder-scripts-core-persistence.md)

## Source

```typescript
import type { ConsoleRecord } from "@banes-lab/build-scripts/types/browser.types.ts";

interface Tally {
    readonly record: ConsoleRecord;
    count: number;
}

export const logLines = function logLines(records: readonly ConsoleRecord[]): string {
    const tally = new Map<string, Tally>();
    for (const record of records) {
        const key = `${record.level}|${record.text}|${record.source}`;
        const held = tally.get(key);
        if (held === undefined) {
            tally.set(key, { count: 1, record });
        } else {
            held.count += 1;
        }
    }
    const rows = [...tally.values()].map((entry) => {
        const times = entry.count === 1 ? "" : ` [x${String(entry.count)}]`;
        const where = entry.record.source.length === 0 ? "" : `  (${entry.record.source})`;
        return `${entry.record.level}: ${entry.record.text}${times}${where}`;
    });
    return `${rows.join("\n")}\n`;
};
```
