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

spangle

v1.3.0

Published

decorate strings using formatted ranges

Downloads

827

Readme

Spangle

Add some ✨ razzle-dazzle ✨ to strings using formatted ranges.

What do you mean "formatted ranges"?

Specifying text as a combination of a string and formatted ranges is a way to allow clients to display formatted text in whichever way they see fit. This amounts to progressive enhancement or graceful degradation, depending on your point of view.

Backwards-compatibility is built in. If a certain type of formatting is unsupported or has some issue, it can be ignored without affecting the rest of the formatting. In the worst case, you can always display a plain string of text!

Shape of the Data

Formatted text is represented by one or more blocks, each of which has plain text string plus any number of formatting ranges that specify additional inline formatting. It is designed so that the interpreter can skip any formatting data that is unrecognized or unsupported without breaking the overall output.

{
  blocks: [
    // Plaintext
    {
      type: 'text',
      text: 'Hello world!',
    },
    // Text with inline formattin
    {
      type: 'text',
      text: 'This is your text.',
      formatting: [
        { start: 8, end: 12, type: 'emphasis' },
      ],
    },
  ],
}

If you were to render this to HTML, you might have output that looks something like this:

<p>Hello world!</p>
<p>This is <em>your</em> text.</p>

Suppose you wanted to render to Markdown instead. An implementation of that might have output that looks more like this:

Hello world!

This is _your_ text.

Usage

This repository contains a JavaScript implementation for the web, but you could also write interpreters for other languages and/or platforms as well!

The primary implementation is build on unified and rehype-dom. It can both parse and format HTML using an abstract syntax tree and the browser's DOM implementation. This is likely the version you'll need to use if you're building a WYSIWYG editor or something similar.

Parsing HTML

import { parseHtml } from 'spangle';

const output = parseHtml('<p>This is <em>your</em> text.</p>');

console.log(output);
// {
//   blocks: [{
//     type: "text",
//     text: "This is your text.",
//     formatting: [{ start: 8, end: 12, type: "emphasis" }]
//   }],
// }

Formatting HTML

import { formatHtml } from 'spangle';

const output = formatHtml({
  blocks: [{
    type: 'text',
    text: 'This is your text.',
    formatting: [
      { start: 8, end: 12, type: 'emphasis' },
    ],
  }],
});

console.log(output);
// "<p>This is <em>your</em> text.</p>"

Lite Verison

If you're concerned about bundle size or only need to interpret existing spangle-formatted data, you might consider using the "Lite" implementation instead. It does not support parsing!

It's smaller because it excludes the code for parsing HTML and uses a smaller (and less accurate) AST-to-HTML string implementation. Otherwise, the API is the same, so swap the import and you'll be good to go!

import { formatHtml } from 'spangle/lib/lite';

Markdown

This repository also includes an implementation that can parse and format a non-standard version of Markdown. This is probably an easier way to create spangle-formatted data reliably than parsing HTML or writing JSON manually.

Parsing Markdown

import { parseMarkdown } from 'spangle';

const output = parseMarkdown('This is [your]{#f00} text.');

console.log(output);
// {
//   blocks: [{
//     type: "text",
//     text: "This is your text.",
//     formatting: [{ start: 8, end: 12, type: "color", color: "#f00" }]
//   }],
// }

Formatting Markdown

import { formatMarkdown } from 'spangle';

const output = formatMarkdown({
  blocks: [{
    type: 'text',
    text: 'This is your text.',
    formatting: [
      { start: 8, end: 12, type: 'underline' },
    ],
  }],
});

console.log(output);
// "This is __your__ text."

Formatting Types

Check out the constants to see the types of formatting supported.

Note: Formatting ranges include start and end normally, but we're omitting them for the sake of brevity in this documentation.

* Formatting that uses non-standard Markdown is labeled with an asterisk.

Strikethrough / Delete

{ type: 'delete' }
<del>text</del>
~~text~~

Italics / Emphasis

{ type: 'emphasis' }
<em>text</em>
_text_

Inline code

{ type: 'inlineCode' }
<code>text</code>
`text`

Underlined*

{ type: 'underline' }
<span style="text-decoration: underline;">text</code>
__text__

Note: Standard markdown uses double-underscores for strong text.

Colors*

{ type: 'color', color: '#f00' }
<span style="color: #f00;">text</code>
[text]{#f00}

Note: Standard markdown does not support inline colors.

Anchor link

{ type: 'link', url: 'https://example.com' }
<a href="https://example.com">text</a>
[text](https://example.com)

Bold / Strong

{ type: 'strong' }
<strong>text</strong>
**text**