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

writ

v0.1.0

Published

Light-weight Markdown-based literate programming

Downloads

76

Readme

writ

Thus, programs must be written for people to read, and only incidentally for machines to execute.

-- Hal Abelson, SICP

Writ is an attempt to enable a light-weight literate programming workflow.

How it works

You write Markdown files with your code in normal Markdown code blocks (indented or fenced) and then run the writ command to compile to source files your language's compiler or interpreter will understand.

Writ expects a one-to-one mapping between Markdown source files and source files in the target language, and uses a simple extension-based convention for generating the target files: a Markdown file named foo.js.md or foo.js.markdown will generate a foo.js file.

Installation and Usage

Writ is available on [npm][npm]. It requires Node v12.17 or higher.

npm install -g writ

To use it, just run writ from the command line, specifying which Markdown files you want to compile. By default, it compiles the output in the same directory, you can pass the --dir flag to specify a different destination directory:

writ "src/*.md" --dir build

Syntax

In the simplest case, if your code is completely straight-line, top-to-bottom, you don't need to know any syntax: writ will generate the target file by concatenating all the code blocks in the order they appear. This is exactly how literate CoffeeScript works.

For slightly more involved cases, writ supports syntax for:

  1. //!! .*[ !!//] for ignoring a code block
  2. //== name[ ==//] for naming a code block
  3. ##== name[ ==##] for naming a section
  4. //:: name[ :://] for including a code block

The // bits are configurable and are defaulted to the single-line comment token for your language.

The 'closing tags' (!!//, ==//, and :://) are optional, but must match the opening tag if present.

Ignoring Code Blocks

To keep a code block from being included in the generated output, start the code block with a line starting with:

//!! This is an ignored code block

//!! Also ignored !!//

Naming and Dereferencing Code Blocks

A named code block is any code block in the document that starts with a line of the form:

//== name[ ==//]

You can later (or earlier) include that code in another block by dereferencing it with //::.

So the following Markdown:

# Main code chunk

```js
//:: requires :://
```

```js
//== requires ==//

import marked from 'marked';
import fs     from 'fs';
```

Would compile to:

import marked from 'marked';
import fs     from 'fs';

A name for sections can have internal whitespace, but it obviously should match up exactly when dereferencing names.

A few things to note about named sections:

  1. Named sections that are never referenced by a 'top-level' code block won't show up in the compiled output.

  2. If a name is referenced that doesn't exist, that comment line will remain as-is in the compiled output.

  3. Named sections can refer to other named sections, and writ will whine if it has to recurse more than 50 times when compiling.

  4. If you have multiple named sections with the same name, they'll get concatenated together in the order they appear in the source.

Naming H2 Sections

I've found it useful to be able to be able to have entire chunks of a document be a named section, so you can also use the double-equals (==) syntax in an H2-level header to name all the sections "under" a specific heading.

So this...

```
//:: Utilities :://
```

##== Utilities

noop

    function noop() {}

add

    function add(x, y) { return x + y; }

mul

    function mul(x, y) { return x * y; }

Would compile to:

function noop() {}
function add(x, y) { return x + y; }
function mul(x, y) { return x * y; }

And you don't have to explicitly name each code block in the section.

Once any other H2 (named or not) is reached in the document, writ will return to processing as usual.

Libraries Built With Writ

  • This one, of course. See writ.js.md for the source.

If you build something using writ, send a pull request adding a link to your library.