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

psr

v0.0.1

Published

Build realistic words and sentences based on a set of rules.

Downloads

13

Readme

Phrase Structure Rule Grammar

Do you ever need to generate some repetitive quip or interesting-enough phrase and get bored of the monotony of doing it over and over? Want to generate unique messages for spamming someone (please don't do that) or build words that appear to be in another language, but are really just gibberish?

Phrase structure rule (PSR) grammar is for you! Luckily you found this project, so most of the work is already done. It has been used to create letters to Santa, GUIDs, realistic names, probable addresses, legitimate phone numbers, Elvish words, magic items for D&D, passphrases, and much more.

Briefly, PSR will expand a rule into text. The text may refer to other rules and those are expanded, recursively. This approach is generally based on tree structures.

Command-Line Usage

Install the package with npm:

npm install -g psr

Now run it against your files

psr input_file.psr

There are example files distributed with this package to generate GUIDs, addresses, passphrases and more.

JavaScript Library Usage

Install the package as a dependency:

npm install --save psr

Then use the library.

var generator, Psr;

Psr = require('psr');

Now you have three ways to set up rules.

// Set up all rules at once
generator = new Psr(rulesInTextFormat);

// OR set up rules yourself
generator = new Psr()

// This would add rules and all values for a given rule,
// similar to having all the text initially.
arrayOfRuleText.forEach(function (ruleText) {
    generator.parse(ruleText);
});

// This would add a single value for a rule.  Here we have
// an object of rules and each property in the object is an array
// of values.
Object.keys(rules).forEach(function (ruleName) {
    rules[ruleName].forEach(function (value) {
        generator.addValue(ruleName, value);
        // There is an optional third parameter if you want to specify
        // a weight other than 1.
    });
});

Time to generate!

console.log(generator.generate());

Example

So what goes in the text blocks that the Psr instance needs?

Nothing really explains what's going on more than a clear example. The lines that start with * indicate rules. The first rule in the file is what's used for starting generation. Here's a file that would generate one phrase only: "Jack is going to the store."

* MAIN
Jack is going to the store.

The first rule is "MAIN" and so the generator starts with that. It randomly picks a line of text. In this case, there's only one option, so it picks the sentence with Jack in it. Let's make this a little more complex by changing the name and the destination.

* MAIN
[NAME] is going to the [PLACE].

* NAME
Timothy
Jack
Greg

* PLACE
library
store
shed

With the above rules, we can get "Timothy is going to the shed.", "Jack is going to the library.", "Greg is going to the shed." and others. In fact, by having 3 names and 3 destinations, we can get a total of 9 different sentences.

Let's make this a bit more interesting and add more description.

* MAIN
[NAME] is [JOINER] the [PLACE].
At the [PLACE], you will find [NAME].

* NAME
Timothy
Jack
Greg
Steve

* PLACE
library
store
shed

* JOINER
[WALK] [TO_FROM]
going to
coming from

* WALK
running
walking
skipping
hopping
hobbling
crawling

* TO_FROM
to
from
towards
away from
nearby

With this lengthy example, you can get a bunch of different possibilities. "Jack is coming from the shed." "Timothy is crawling nearby the library." "Steve is walking away from the store." You can see that we built a bunch of possibilities from just a few simple lines.

When you add more rules, you increase the amount of possibilities dramatically. With more possibilities you get more variance in what's generated and more flavor in the statements.

With the above example, you will notice that the JOINER only expands to three possible rules. The first rule, "[WALK] [TO_FROM]" can expand to many possibilities, but it only has a 1/3 chance of being picked if JOINER is used. To make the output look better, we should have the "[WALK] [TO_FROM]" rule get used more often.

# Lines starting with a pound or hash character are comments.
# Comments are ignored.

# This is just the JOINER rule of the above, larger file.

* JOINER
10:[WALK] [TO_FROM]
1:going to
1:coming from

With a JOINER rule like this, we give preference to the first rule. Essentially, we add the numbers on all of the rules. Then, we pick a random number, then check to see which rule gets it. 10 + 1 + 1 = 12. Picking a random number, 4, means that we use the first rule. If I pick 11 or 12, we use the boring "going to" or "coming from" rules. Essentially, the first rule is 10 times more likely to get picked than either of the "average" rules.

# This is a completely different example.
# Do not just add this to the above PSR rules

* NEW_EXAMPLE
Pick up [OBJECT].  [^OBJECT] is over there.

* OBJECT
the sword
an apple
a kitten

This example illustrates how you can capitalize the first letter in an expanded rule. The first rule picks two objects (they may be different or the same) and the second object has its first letter capitalized. "Pick up the sword. A kitten is over there." "Pick up an apple. An apple is over there." "Pick up a kitten. An apple is over there."

The file format also supports long lines -- just use something like this:

This is one really big line.  I continue it to \
the next line by having a single backslash at \
the end.

Lastly, if you have [[], []], [ ], [*], or [#] in your rules, it will convert that into just the [, ], a space, *, or # character, respectively. Newlines can be added by using \n.