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

motif

v0.1.6

Published

pattern composition mini-language for javascript

Downloads

6

Readme

motif

Build Status

pattern composition mini-language for javascript

var assert = require('assert')
var motif = require('motif')

assert.deepEqual(
  motif('[a  b], [[[c d] [e], f]*3, g], h'),
  [['a', 'c', 'f', 'g', 'h'],
   ['d'],
   ['e'],
   [],
   ['c', 'f'],
   ['d'],
   ['b', 'e'],
   [],
   ['c', 'f'],
   ['d'],
   ['e'],
   []])

motif is heavily inspired by Tidal. The parser is generated via PEG.js.

docs

install

node:

$ npm install motif

browser:

$ bower install motif-js
<script src="/bower_components/motif-js/motif.js"></script>

api

motif(pattern[, lookup])

motif('a b')
// => [['a'], ['b']]

Compiles the given pattern string into a javascript object.

If a lookup object is given, the value of each symbol given in the lookup object will replace the symbol's occurences in the pattern.

motif('a b', {
  a: 23,
  b: 42,
})

// => [[23], [42]]

language

compilation result (buckets)

All motif patterns produce an array of 'bucket' arrays, where a bucket represents things that occur simultaneously. In the context of music, this would mean a series of notes played at the same time. In the example below, 'a' and 'c' are in the same bucket, so they would be played at the same time.

motif('a b, c')

// => [['a', 'c'], ['b']]

primitives

numbers

Numbers are a primitive type in the language. Like javascript, numbers can have an optional sign, an integer part, an optional fraction part and an optional exponent.

motif('23')
// => [[23]]

strings

Strings are another primitive type in the language. Strings can be any series of alphanumeric characters apart from cases containing only numbers.

motif('l3mon')
// => [['l3mon']]

If a corresponding symbol exists for the string in a lookup object given to motif, the string representation is replaced by the symbol.

motif('a b c', {
  a: 23,
  b: 42,
})

// => [[23], [42], ['c']]

rests

A rest produces an empty bucket. ~ is the symbol used for a rest. In the context of music, this would mean a time interval where no notes are played.

motif('a ~ b')
// => [['a'], [], ['b']]

operations

repitition

A repitition is an operation used to duplicate a pattern a number of times. Repititions can be any primitive, rest or group literal followed by a *, then an integer.

motif('[a b]*3')
// => [['a'], ['b'], ['a'], ['b'], ['a'], ['b']]

groups

Groups define pattern segments of the same 'length'. In the context of music, this would mean groups of things which should be played one after the other, each at an equivalent amount of time.

A group can be any combination of whitespace separated primitives, rests, operations, or group literals, where a group literal is a nested motif pattern enclosed inside square brackets ([ and ]).

Group literals and whitespace allow one to form multiple groups. In the example below, the following patterns are equivalent, where [a b], [c d] and [e f g] are the groups in each pattern.

motif('[a b] [c d] [e f g]')
motif('a b [c d] [e f g]')
motif('a b [c d] e f g')

In the example below, [a] has a rest added to it (it essentially becomes [a ~]) so that has the same length as [b c].

motif('[a] [b c]'),
// this simplifies to: '[a ~] [b c]'
// then simplifies to: '[a] [] [b] [c]'
// then compiles to: [['a'], [], ['b'], ['c']])

layers

Layers define pattern segments which should overlap. In the context of music, this would mean two different rhythms, possibly of different lengths, that are played simultaneously.

A layer is recognised as one or more groups. Multiple layers are recognised as layers separated by , characters (with any number of whitespace characters before and after).

In the example below, a and b would occur simulataneously.

motif('a, b'),
// => [['a', 'b']])

As is the case with groups, layers are simplified to be of the same 'length'. In the example below, a has a rest added to it to give it the same length as [b c]. From there, buckets are formed from the two layers, so a and b get played together, and c gets played alone ([a] is concatenated with [b] and [] is concatenated with [c]).

motif('[a], [b c]'),
// this simplifies to: '[a ~], [b c]'
// then simplifies to: '[a] [], [b] [c]'
// then compiles to: [['a', 'b'], ['c']]

install

You can use this library as the npm package motif:

npm i motif
# or
yarn add motif

It can be used in both es-module-aware and commonjs bundlers/environments.

// es module
import motif from 'motif'

// commonjs
const motif = require('motif')

It can also be used a <script>:

<script
  crossorigin
  src="https://unpkg.com/motif/dist/umd/motif.js"
></script>

<script>
motif('[a], [b c]')
</script>