npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

cl-paginator

v2.0.1

Published

Splits text in pages to show in console, waiting for user interaction to continue the code

Downloads

27

Readme

Cl-Paginator

Split and show your text in console with user interaction

This Node.js module allows you to split and fit the text in console, dividing it in pages which user can go through.
I decided to create this based on Inquirer paginator util used on some prompts, 'cause it's quite useful when creating a CLI. Lorem

Getting started

Installation

npm install cl-paginator

Usage

import { Paginator } from 'cl-paginator'
// const { Paginator } = require('cl-paginator')

var paginator = new Paginator(/* PageOptions */)

paginator.options({/* PageOptions */})
paginator.print(/* just text*/, /* PageOptions */)

Also, you can try it on Repl.it

How this works

paginator.print(text: string, options?: pageOptions)

Firstly, splits the given text to fit well in the console or the terminal option terminal: {cols, rows}, without intercalated words. Then, listens to data signals from a NodeJS.ReadStream like process.stdin (keyboard input) to check if Up or Down keys are pressed, then moving the current page.

Methods

Print

/**
 * Capture key arrows for moving the text UP and DOWN with a determinate PageSize.
 * Use Message option for show an static text above the text.
 * @param {string} text Defines the text to split up and fit in the console.
 * @param {pageOptions | undefined} options Defines the options.
 * @async Uses Promises, awaiting for the Return key pressed.
 * @returns Promise, resolving in Boolean True.
 */
async paginator.print(text: string, options?: pageOptions)

Options

interface pageOptions {
  /**
   * Defines the max number of lines to show in console. Use a positive integer
   * @default 5
   */
  page_size?: number;
  /**
   * Shows an static message above the text
   * @default "Paginated text:"
   */
  message?: string;
  /**
   * Shows a short suffix to help the user
   * @default "(Use arrow keys)"
   */
  suffix?: string;
  /**
   * Shows a message for help to continue executing the code
   * @default "Press return key to exit"
   */
  exit_message?: string;
  /**
   * Whether it's necessary to read all (going to bottom) or not to quit
   * @default true
   */
  read_to_return?: boolean;
  /**
   * The `NodeJS.WriteStream` to write on
   * @default process.stdout
   */
  writable?: NodeJS.WriteStream;
  /**
   * The `NodeJS.ReadStream` to read from
   * @default process.stdin
   */
  readable?: NodeJS.ReadStream;
  /**
   * Sets the maximum number of columns and rows.
   * @default { cols: 0, rows: 0 } // Automatic
   */
  terminal?: { cols?: number; rows?: number };
  /**
   * Sets the paginator style
   * @default { }
   */
  style?: { enum?: chalk.Chalk };
}

Also, you can define the default options to be used in every print.

paginator.options(options?: pageOptions): this
// or
var pagCustom = new Paginator(options?: pageOptions)

End

Stops the Paginator instance, without closing the program.

paginator.print('a') // a
paginator.end() // Stops the paginator inmediately, without closing the program with 'process.exit()'

Properties

Opts

Returns the Paginator instance options.

paginator.opts: pageOptions

Pages

Returns the Paginator instance total pages.

paginator.pages: number

Position

Returns or sets the actual position in Paginator instance.

paginator.position: number // Returns the position
paginator.position = 2 // Sets the position

Actual Text

Returns the actualText, the text that is writed on writable ReadStream.

paginator.actualText: string

Chaining

paginator.options(/* pageOptions */).print('Hello')

// `print` method is promise-based, therefore you would need to use `then` to chain next `print`s.
paginator.print('A').then(pag => pag.print('E')).then(pag => pag.print('I'))

Examples

Simple Lorem Ipsum

var text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...' // Just a big lorem ipsum
paginator.print(text, {page_size: 10}) // Shows 10 lines per page

lorem

Options

var text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...' // The same big lorem ipsum
paginator.print(lorem, {
  page_size: 10,
  exit_message: 'Please, press return to exit :D',
  message: 'A big lorem ipsum!',
  suffix: 'Use those arrows',
  read_to_return: false
})

options

Chalk integration

import chalk from 'chalk'
var text = chalk`Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod {bold.green tempor incididunt ut labore et dolore magna aliqua...}`
paginator.print(text, {
  page_size: 10,
  suffix: 'Use the arrows!',
  read_to_return: false
})

chalkie

Stream integration

var writable = new Writable() // new NodeJS.WriteStream
var readable = new Readable() // new NodeJS.ReadStream

readable.setRawMode(true)  // Allows Ansi Escaping
readable.resume()

var text = var text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...' // The same big lorem ipsum
paginator.print(text, {
  page_size: 10,
  writable: writable, // This allows to write on 'writable' WriteStream.
  readable: readable, // This allows to read the input on 'readable' ReadStream.
})
// Check the examples folder for more info.

Streams

Writable

This needs just a bit of configuration, unless you want to make it really useful, such as storing every chunk that is writed in the instance.
Recommendation: As this package is oriented to be used in a console, it uses Ansi Escapes to do a lot of things, like erasing the console or hiding/showing the cursor, I recommend you to use a filter that erases all your data when this kind of Ansi Escapes are writed.
Ansi-Escapes, Ansi-Regex

const clearAnsi = ['\x1B[0J', ansiEscapes.clearScreen, ansiEscapes.clearTerminal, /* and so on... */]

// This method is extended from 'WriteStream'. You need to put your code here to make it work, don't overwrite the 'write' method, use '_write' instead
public _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null | undefined) => void) {
    this.all += chunk // Saves the chunk in a permanent data
    this.data += chunk // Saves the chunk in a temporal data
    this.emit('writed', this.data) // Emits a 'writed' event with the temporal data, to make it versatille

    var reg = this.data.match(ansiRegex()) // Matchs every Ansi Escape
    var match = clearAnsi.some((val) => { return reg?.includes(val) })
    if (match) { this.clear() } // If matchs any Ansi Escape oriented to cleaning~ erase the temporal data
    callback()
  }

Readable

If you want to create an automated ReadStream with Cl-Paginator, you need to use ANSI escape codes, line \x0d or x1b[A.

Such as:

class Readable extends ReadStream {
  constructor() {
    super(0)
  }
  public emitKey(key: string) { // You could make an external function, instead
    this.emit('data', Buffer.from(data.split("").map((v) => v.charCodeAt(0))))
  }
}
// Then~
var readable = new Readable()
var paginator = new Paginator({ readable })
paginator.print(/* What you want~ */)
readable.emitKey("\x1b[B") // "Presses" the down key
readable.emitKey("\x0d") // "Presses" the return key
readable.emitKey("\x03") // Exits the program

Know issues

  • It's possible that Streams don't work properly.