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

rtext-render

v0.1.0

Published

Rich Text library renderer

Downloads

6

Readme

Rich Text Renderer

rtext-render provides a pluggable renderer that deals with all complexities, so you just need to specify several hooks and it will be ready to render into any format you like.

interface RichTextRendererHooks<C, R> {
  onInit(): C;
  onEnter(annotation: RichTextAnnotation, parentContext: C): C;
  onExit(annotation: RichTextAnnotation, context: C, parentContext: C): void;
  onText(text: string, context: C): void;
  onResult(context: C): R;
}

function createRichTextRenderer<C, R>(
  priorities: { [key: string]: number },
  hooks: RichTextRendererHooks<C, R>,
): (richText: RichText) => R;

createRichTextRenderer() function is used to create a new renderers. It has two parameters, priorities to specify priorities for annotation types and hooks that will be invoked when renderer will process rich text.

Priorities

Priorities are used to resolve conflicts with overlapping annotations and to make sure that we can generate consistent HTML documents.

For example, when generating HTML anchors, they should have a precedence over b elements.

Just some random text with an anchor element
          [ bold         ]
                      [ link       ]

When converting this rich text to HTML we would like to get HTML like this:

Just some <b>random text </b><a><b>with</b> an anchor</a> element

Hooks

onInit() hook is used to initialize an internal state. It should return a root context.

onEnter() and onExit() hooks will be invoked each time renderer enters or exits an annotation. When renderer enters an annotation with a higher priority than annotations in the current context, it will always exit from annotations with lower priorities and then re-enter into them. onEnter() hook should return a data structure with a current context.

onText() hook will be invoked with a current context when text is rendered.

onResult() hook should return a result of a renderer from a root context.

Example

In this example we will render rich text into a colored output in a terminal with a chalk package.

import { createRichTextRenderer } from "rtext-render";
import * as chalk from "chalk";

const render = createRichTextRenderer(
  {
    "bold": 1,
    "underline": 2,
    "color": 3,
    "bgColor": 4,
  },
  {
    onInit: () => ({ chalk, result: "" }),
    onEnter: (a, c) => {
      let newChalk = c.chalk;
      switch (a.type) {
        case "bold":
          newChalk = newChalk.bold;
          break;
        case "underline":
          newChalk = newChalk.underline;
          break;
        case "color":
          newChalk = newChalk[a.data];
          break;
        case "bgColor":
          const color = `bg${a.data[0].toUpperCase()}${a.data.slice(1)}`;
          newChalk = newChalk[color];
          break;
      }
      return { chalk: newChalk, result: "" };
    },
    onExit: (a, c, p) => {
      p.result += c.result;
    },
    onText: (t, c) => { c.result += c.chalk(t); },
    onResult: (c) => c.result,
  },
);