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

kdljs

v0.2.0

Published

KDL parser and serializer.

Downloads

2,617

Readme

KDL-JS

A JavaScript library for the KDL Document Language.

Install

npm install kdljs

Usage

Parsing

const { parse } = require('kdljs')
parse(`
// Nodes can be separated into multiple lines
title \
  "Some title"
`)

// [
//   {
//     name: 'title',
//     properties: {},
//     values: [ 'Some title' ],
//     children: [],
//     tags: {
//       name: undefined,
//       properties: {},
//       values: [ undefined ]
//     }
//   }
// ]

parse(`
// Files must be utf8 encoded!
smile "😁"
`)

// [
//   {
//     name: 'smile',
//     properties: {},
//     values: [ '😁' ],
//     children: [],
//     tags: {
//       name: undefined,
//       properties: {},
//       values: [ undefined ]
//     }
//   }
// ]

parse(`
// Instead of anonymous nodes, nodes and properties can be wrapped
// in "" for arbitrary node names.
"!@#$@$%Q#$%~@!40" "1.2.3" "!!!!!"=true
`)

// [
//   {
//     name: '!@#$@$%Q#$%~@!40',
//     properties: { '!!!!!': true },
//     values: [ '1.2.3' ],
//     children: [],
//     tags: {
//       name: undefined,
//       properties: { '!!!!!': undefined },
//       values: [ undefined ]
//     }
//   }
// ]

parse(`
// The following is a legal bare identifier:
foo123~!@#$%^&*.:'|/?+ "weeee"

// And you can also use unicode!
ノード お名前="☜(゚ヮ゚☜)"
`)

// [
//   {
//     name: "foo123~!@#$%^&*.:'|/?+",
//     properties: {},
//     values: [ 'weeee' ],
//     children: [],
//     tags: {
//       name: undefined,
//       properties: {},
//       values: [ undefined ]
//     }
//   },
//   {
//     name: 'ノード',
//     properties: { 'お名前': '☜(゚ヮ゚☜)' },
//     values: [],
//     children: [],
//     tags: {
//       name: undefined,
//       properties: {},
//       values: []
//     }
//   }
// ]

parse(`
// kdl specifically allows properties and values to be
// interspersed with each other, much like CLI commands.
foo bar=true "baz" quux=false 1 2 3
`)

// [
//   {
//     name: 'foo',
//     properties: { bar: true, quux: false },
//     values: [ 'baz', 1, 2, 3 ],
//     children: [],
//     tags: {
//       name: undefined,
//       properties: { bar: undefined, quux: undefined },
//       values: [ undefined, undefined, undefined, undefined ]
//     }
//   }
// ]

parse(`
// kdl also allows for annotationg values with types, and
// for denoting relations between nodes.
package {
  (author)person contact=(email)"[email protected]"
  (contributor)person homepage=(url)"https://example.org/example"
}

// [
//   {
//     name: 'package',
//     properties: {},
//     values: [],
//     children: [
//       {
//         name: 'person',
//         properties: { contact: '[email protected]' },
//         values: [],
//         children: [],
//         tags: {
//           name: 'author',
//           properties: { contact: 'email' },
//           values: []
//         }
//       },
//       {
//         name: 'person',
//         properties: { homepage: 'https://example.org/example' },
//         values: [],
//         children: [],
//         tags: {
//           name: 'contributor',
//           properties: { homepage: 'url' },
//           values: []
//         }
//       }
//     ]
//   }
// ]
`)

Querying

const { parse, query } = require('kdljs')

const { output: document } = parse(`package {
    name "foo"
    version "1.0.0"
    dependencies platform="windows" {
        winapi "1.0.0" path="./crates/my-winapi-fork"
    }
    dependencies {
        miette "2.0.0" dev=true
    }
}`)

query(document, 'package name') // or
query(document, 'top() > package name')

// [
//   {
//     name: 'name',
//     values: ['foo'],
//     ...
//   }
// ]

query(document, 'dependencies')

// [
//   {
//     name: 'dependencies',
//     properties: { platform: 'windows' },
//     ...
//   },
//   {
//     name: 'dependencies',
//     ...
//   }
// ]

query(document, 'dependencies[platform]') // or
query(document, 'dependencies[prop(platform)]')

// [
//   {
//     name: 'dependencies',
//     properties: { platform: 'windows' },
//     ...
//   }
// ]

query(document, 'dependencies > []')

// [
//   {
//     name: 'winapi',
//     properties: { path: './crates/my-winapi-fork' },
//     values: [ '1.0.0' ],
//     ...
//   },
//   {
//     name: 'miette',
//     properties: { dev: 'true' },
//     values: [ '2.0.0' ],
//     ...
//   }
// ]

// MAP OPERATOR
// ============

query(document, 'package name => val()')
// ['foo'].

query(document, 'dependencies[platform] => platform')
// ['windows']

query(document, 'dependencies > [] => (name(), val(), path)')
// [('winapi', '1.0.0', './crates/my-winapi-fork'), ('miette', '2.0.0', None)]

query(document, 'dependencies > [] => (name(), values(), props())')
// [('winapi', ['1.0.0'], {'platform': 'windows'}), ('miette', ['2.0.0'], {'dev': true})]

Formatting

const { format } = require('kdljs')

format([
  {
    name: 'title',
    properties: {},
    values: [ 'Some title' ],
    children: [],
    tags: { properties: {}, values: [] }
  },
  {
    name: 'smile',
    properties: {},
    values: [ '😁' ],
    children: [],
    tags: { properties: {}, values: [] }
  },
  {
    name: '!@#$@$%Q#$%~@!40',
    properties: { '!!!!!': true },
    values: [ '1.2.3' ],
    children: [],
    tags: { properties: {}, values: [] }
  },
  {
    name: "foo123~!@#$%^&*.:'|/?+",
    properties: {},
    values: [ 'weeee' ],
    children: [],
    tags: { properties: {}, values: [] }
  },
  {
    name: 'ノード',
    properties: { 'お名前': '☜(゚ヮ゚☜)' },
    values: [],
    children: [],
    tags: { properties: {}, values: [] }
  },
  {
    name: 'foo',
    properties: { bar: true, quux: false },
    values: [ 'baz', 1, 2, 3 ],
    children: [],
    tags: { properties: {}, values: [] }
  }
])

`title "Some title"
smile "😁"
"!@#$@$%Q#$%~@!40" "1.2.3" !!!!!=true
foo123~!@#$%^&*.:'|/?+ "weeee"
ノード お名前="☜(゚ヮ゚☜)"
foo "baz" 1 2 3 bar=true quux=false
`

License

The code is available under the MIT license. The example above is made available from https://github.com/kdl-org/kdl under Creative Commons Attribution-ShareAlike 4.0 International. The submodule in test/kdl4j is licensed according to its LICENSE.md file.