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 🙏

© 2026 – Pkg Stats / Ryan Hefner

todotxt-utils

v0.1.1

Published

Helper functions for parsing todo.txt formatted tasks and performing common operations like sorting

Downloads

8

Readme

todotxt-utils

Utility functions for working with the todo.txt format. Provides simple helpers for parsing, inspecting, and modifying todo.txt task strings.

This package is plain ESM JavaScript — no dependencies, no frameworks.

Installation

npm install todotxt-utils

or with pnpm:

pnpm add todotxt-utils

Usage

import {
  getContexts,
  getProjects,
  getPriority,
  getCreationDate,
  getCompletionDate,
  getKeyValues,
  replaceSpan,
  formatReplacement
} from "todotxt-utils";

const task = "x 2025-01-01 2024-12-31 Fix bug +proj @home rid:1";

// Most helpers return *spans*, not just values:
const contexts = getContexts(task);
// → [{ value: "home", start: 43, end: 48, raw: " @home" }]

const projects = getProjects(task);
// → [{ value: "proj", start: 37, end: 42, raw: " +proj" }]

const priority = getPriority(task);
// → { value: "A", start: 15, end: 19, raw: " (A)" }

const creationDate = getCreationDate(task);
// → { value: "2024-12-31", start: 20, end: 30, raw: " 2024-12-31" }

const completionDate = getCompletionDate(task);
// → { value: "2025-01-01", start: 2, end: 12, raw: "2025-01-01" }

const keyValues = getKeyValues(task);
// → [{ key: "rid", value: "1", start: 49, end: 55, raw: " rid:1" }]

// You can replace spans without worrying about whitespace/keys:
const newTask = replaceSpan(
  task,
  creationDate,
  formatReplacement(creationDate, "2025-02-01")
);
// → "x 2025-01-01 (A) 2025-02-01 Fix bug +proj @home rid:1"
```

## API Design

Most parsing functions return spans, which include not only the extracted value but also information about where in the task string it came from.

A span has this shape:
```json
{
  value: string;   // the parsed logical value, e.g. "home" for "@home"
  start: number;   // inclusive index into the task string
  end: number;     // exclusive index into the task string
  raw: string;     // the exact substring matched, including whitespace/prefix
}
```
- `start` is the index of the first character in the raw match.
- `end` is the index immediately after the last character (exclusive).
- `raw` includes the leading/trailing whitespace or marker `+`, `@`, `key:`) so that replacements are easy.


This design makes it easy to:

- Remove spans (via `removeSpan`) without re-parsing.
- Replace spans using `replaceSpan` and `formatReplacement`.
- Track offsets precisely when manipulating tasks.


#### Example

```js
const task = "(A) 2025-01-01 Write docs +proj @home due:2025-02-01";

const project = getProjects(task)[0];
// → { value: "proj", start: 28, end: 34, raw: " +proj" }

const updated = replaceSpan(
  task,
  project,
  formatReplacement(project, "newproj")
);
// → "(A) 2025-01-01 Write docs +newproj @home due:2025-02-01"
```

## Philosophy

- **Plain text in, plain text out**: every function works on strings, not custom classes.
- **Small utilities**: each function does one thing.
- **Composable**: you can mix and match functions for your own workflows.

## To Do

- Add more utilities
- Make tests more robust