voici.js

repository·main·Indexed 19 days ago

https://github.com/larswaechter/voici.js

A Node.js library written in TypeScript for displaying datasets in tabular form within the terminal. Version 3.0.0 supports features such as text/column/row styling, highlighting, filtering, dynamic columns, sorting, and table export. It includes a Table class for rendering and a set of AccumulationFunctions for statistical calculations like MEAN, MEDIAN, SUM, and STD.

Tokens
3.9K
Snippets
19
Records
20
Agent score
65%

What's inside voici.js

  1. Display datasets in a table using the Table class

    main

    To display data in a tabular format in the terminal, import the Table class from voici.js, instantiate it with your dataset (an array of objects), and call the .print() method.

    voici.js supports various features such as text/column/row styling, highlighting, filtering, dynamic columns, column sizing, accumulation, table export, and sorting.

    import { Table } from 'voici.js';
    
    const data = [
      { firstname: 'Homer', lastname: 'Simpson', age: 39 },
      { firstname: 'Marge', lastname: 'Simpson', age: 36 },
      { firstname: 'Bart', lastname: 'Simpson', age: 10 },
      { firstname: 'Lisa', lastname: 'Simpson', age: 8 },
      { firstname: 'Maggie', lastname: 'Simpson', age: 1 }
    ];
    
    const table = new Table(data);
    table.print();
  2. How dynamic columns work in Table

    main

    Dynamic columns allow you to inject new data into every row based on the existing row content. This is configured via the header.dynamic property in the Config object. Each key in the dynamic object represents a new column name, and its value is a function that takes the current row and its index to compute the cell value.

    When a dynamic column is defined, the Table class automatically merges these computed values into the dataset during construction.

    const dataset = [{ price: 10 }, { price: 20 }];
    
    const table = new Table(dataset, {
      header: {
        dynamic: {
          // 'tax' is the new column name
          tax: (row) => row.price * 0.2
        }
      }
    });
  3. How accumulation (totals) works in Table

    main

    The accumulation feature allows you to add a summary row (e.g., totals, averages) at the bottom of your table. You configure this in body.accumulation.columns. For each specified column, you provide a calculation method. The Table class will compute these values and render them in a special row at the end of the body, often styled differently.

    // Example configuration for an accumulation row
    const table = new Table(dataset, {
      body: {
        accumulation: {
          columns: {
            age: (values) => values.reduce((a, b) => a + b, 0) / values.length, // Average age
            price: (values) => values.reduce((a, b) => a + b, 0) // Total price
          },
          separator: '─' // Separator between body and accumulation row
        }
      }
    });
  4. Configure the Voici.js table via the Config type

    main

    The Config type allows you to customize the appearance and behavior of a table. It is divided into several main sections: align, bgColorColumns, body, border, header, sort, and padding.

    Key configuration areas include:

    • header: Controls visibility, ordering, display names, and styling (bold, italic, case) of columns. You can define dynamic columns and specify which columns to include or exclude.
    • body: Manages row-level styling like striped rows, precision for numbers, fillEmpty logic, and highlightRow/highlightCell functions.
    • sort: Defines the sorting order using columns and directions ('asc' | 'desc').
    • border: Configures the visual style of table borders.
    • padding: Sets the character and size used for padding.
    // Example of a partial Config object
    const myConfig: Partial<Config<MyRowType, MyDynamicColumns>> = {
      align: 'CENTER',
      header: {
        visible: true,
        bold: true,
        displayNames: { name: 'Full Name', age: 'Years' }
      },
      body: {
        striped: true,
        precision: 2
      }
    };
  5. Calculate statistical accumulations with calculateAccumulation()

    main

    The calculateAccumulation function is the primary entry point for computing a statistic from a dataset. It takes an array of data and an AccumulationFunction and returns the computed value. If the dataset is empty, it returns null.

    import { calculateAccumulation, AccumulationFunction } from './accumulation';
    
    const data = [10, 20, 30, 40];
    const mean = calculateAccumulation(data, AccumulationFunction.MEAN);
    const sum = calculateAccumulation(data, AccumulationFunction.SUM);
    const max = calculateAccumulation(data, AccumulationFunction.MAX);
  6. Define dynamic columns using DynamicColumnOption

    main

    Dynamic columns allow you to generate column data on the fly based on the row data. You provide a DynamicColumnOption object where each key corresponds to a column in your TDColumns interface, and the value is a function that calculates the cell content.

    The function signature is: (row: TRow, index: number) => TDColumns[keyof TDColumns].

    type MyRow = { name: string; score: number };
    type MyDynamic = { status: string };
    
    const dynamicConfig: DynamicColumnOption<MyRow, MyDynamic> = {
      status: (row, index) => (row.score > 50 ? 'Pass' : 'Fail')
    };
  7. Configure tables with Config, DynamicColumn, and Sort

    main

    Manage table behavior and structure using the following configuration types:

    • Config: The primary configuration object for table settings.
    • DynamicColumn: (exported as DynamicColumnOption) Defines options for columns that may change or be generated dynamically.
    • Sort: Defines sorting logic and direction for table columns.
    import { Config, DynamicColumn, Sort } from 'voici.js';
    
    const config: Config = {
      // configuration properties
    };
  8. Apply row highlighting with highlightRow

    main

    You can highlight entire rows based on custom logic using the highlightRow property within the body configuration. This property accepts a bgColor and a func.

    The func receives the full DatasetRow and the row index. If the function returns true, the row's background color is applied.

    const bodyConfig = {
      highlightRow: {
        bgColor: '#FF0000',
        func: (row, index) => row.score < 10
      }
    };
  9. Apply cell highlighting with highlightCell

    main

    You can highlight individual cells using the highlightCell property within the body configuration. This allows for granular control over styling like bold, italic, underline, textColor, and a custom func.

    The func signature is: (content: unknown, row: number, col: InferAttributes<TRow, TDColumns>) => boolean.

    const bodyConfig = {
      highlightCell: {
        bold: true,
        func: (content, row, col) => typeof content === 'number' && content > 100
      }
    };
  10. Create a terminal table with the Table class

    main

    The Table class is the primary interface for creating and configuring terminal-based data tables. You instantiate it by providing a dataset (an array of objects or arrays) and an optional configuration object. The table automatically infers columns from the first item in the dataset and supports advanced features like dynamic columns, sorting, accumulation (totals/averages), and conditional styling.

    import { Table } from './table';
    
    const dataset = [
      { firstname: 'John', lastname: 'Doe', age: 30 },
      { firstname: 'Jane', lastname: 'Smith', age: 25 }
    ];
    
    // Basic usage
    const table = new Table(dataset);
    
    // Print to console
    table.print();