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

snippin

v0.5.1

Published

re-use snippets from text files in other contexts

Downloads

6

Readme

Snippin lets you re-use snippets from text files in other contexts.

Like say you're writing some documentation for your code and you want to show some examples of how it behaves. You figure you'll grab the examples from your test suite, because 1. they're already written and 2. they're guaranteed to work --it's so annoying to find bugs in sample code! But there's some boring boilerplate at the top of your test file, and there are some tests that go into too much detail to serve as good examples, so you don't want to just include the whole file in your documentation. With Snippin, you can identify just the specific parts you're interested in:

// test.js
const tap = require('tap')

// #snip "example"
tap.equals(1 + 1, 2)
// #snip

Now you can load them with Snippin and use them however you need:

const snippin = new Snippin()
tap.same(snippin.getSnippetsSync('test.js'), {
  'example': 'tap.equals(1 + 1, 2)\n'
})

Writing snippets

Start a snippet by writing #snip <snippet name> by itself on a line. The snippet name must be a valid JSON string, e.g.

#snip "example snippet"

End a snippet by writing just "#snip" by itself on a line:

#snip

You're allowed as much whitespace as you need before "#snip", and you can also have comment markers on the same line. For example,

// prefixed.js
// #snip "inside a comment"
//
// That "// " at the start of these lines
// won't be part of the snippet
// #snip
tap.same(snippin.getSnippetsSync('prefixed.js'), {
  'inside a comment': `
That "// " at the start of these lines
won't be part of the snippet
` })

Specifically, here are the regex components that match whitespace and comment markers:

  • prefix: /^\s*(?://|\*|/\*)?\s*/
  • suffix: /\s*$/

Snippets can be nested. For example,

// nested.txt
#snip "outer"
Outer snippet
#snip "inner"
Inner snippet
#snip
Still outer snippet
#snip
tap.same(snippin.getSnippetsSync('nested.txt'), {
  'outer': 'Outer snippet\nInner snippet\nStill outer snippet\n',
  'inner': 'Inner snippet\n'
})

You can escape "#snip" directives by prefixing them with a "\". And of course if you need a literal "\#snip" you can write "\\#snip":

// escaped.txt
#snip "snippet"
\#snip "literal #snip"
\#snip
// \\#snip "literal backslash"
#snip
tap.same(snippin.getSnippetsSync('escaped.txt'), {
  'snippet': '#snip "literal #snip"\n#snip\n// \\#snip "literal backslash"\n'
})

API

new Snippin([options, [streamOptions]])

  • refDir string The directory relative to which snippets are loaded. Default: '.'.
  • errorLogger Function Function to use to log warnings; it will be called with a single argument: an error message string. Default: console.warn.

snippin.getSnippets(file)

  • file string The name of the file for which to get snippets.
  • Returns Promise Resolves to an object containing the snippets found in file; keys are the snippet names, values are their contents.

Gets snippets from the given file. Throws if file doesn't exist.

snippin.getSnippetsSync(file)

  • file string The name of the file for which to get snippets.
  • Returns Object The snippets found in file; keys are the snippet names, values are their contents.

Gets snippets from the given file synchronously. Throws Error if file doesn't exist.

snippin.setSnippets(file, snippets)

  • file string The name of the file for which to set snippets. This can be a path to a real file, or just a name.
  • snippets Object The snippets to set; properties are snippet names, and their value is the snippet contents.

Snippets set this way take precedence over snippets loaded from files. This function operates on the entire set of snippets for a file; it will replace the set of snippets for the given file if it's already been loaded, or prevent it from being loaded if it hasn't yet.

Including snippets

Once you've loaded your snippets, you can include them into your text by using any of the popular templating libraries, or template literals, or whatever.

Snippin also ships with a stream transform that can process "#pin" directives and render them as the named snippet. Include a snippet by writing #pin file snippet-name by itself on a line. Both the file and snippet name must be valid JSON strings.

Continuing the first example above, we can do

const doc = `We all know that one and one make two:
  #pin "test.js" "example"`
let output = ''
const pinTx = new PinTx()
pinTx.on('data', chunk => { output += chunk })
pinTx.on('end', () => t.equals(output,
  'We all know that one and one make two:\ntap.equals(1 + 1, 2)\n'))
pinTx.end(doc)

new PinTx([options, [streamOptions]])

  • options Object
    • refDir string The directory relative to which snippets are loaded. Default: '.'.
    • errorLogger Function Function to use to log warnings; it will be called with a single argument: an error message string. Default: console.warn.
  • streamOptions Object Passed as-is to stream.Transform's constructor. Default: {}.

This transform replaces each #pin directive with the snippet it references.

If a #pin directive is malformed or references a snippet which can't be loaded, a warning is logged, and the directive is output as-is.

Command line

There's a command line interface to the stream transform.

Usage: snippin [-d REFDIR] [-o OUTFILE] [--] [INFILE]

Print standard input (or INFILE) to standard output (or OUTFILE)
with #pins expanded relative to the current working directory
(or INFILE's directory, or REFDIR).

Options:

    -d, --refdir=DIRECTORY  load snippets relative to DIRECTORY
    -o, --outfile=FILE      write output to FILE
    -h, --help              show this usage message

Contributing

This project is deliberately left imperfect to encourage you to participate in its development. If you make a Pull Request that

  • explains and solves a problem,
  • follows standard style, and
  • maintains 100% test coverage

it will be merged: this project follows the C4 process.

To make sure your commits follow the style guide and pass all tests, you can add

./.pre-commit

to your git pre-commit hook.