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

mu-format

v0.6.8

Published

A tool for formatting MUSHCode into something you can quote into your client.

Downloads

13

Readme

Mu-Format

A Program that turns pretty formatted MUSHCode into something you can quote to your client, mixed with a few extras to speed up your coding flow.

Installation

npm i mu-format

Usage

There are just a few steps in setting up the formatter.

// Create your app
const Formatter = require('mu-formatter');

const app = new Formatter({
  plugins: [
    './extras/plugins/plugin1',
    './another/place/plugin2'
  ]
});

// Setup some event listeners
app.on('log', log => console.log(log));
app.on('error', error => app.logger(error.stack));
app.on('done', results => console.log(results[0].contents));

// Now run the formatter! If you run a file from the directory
// level, or from a github repo, it will look for a file called
// `installer.mu`.
app.format('./code/codefile.mu'); // or
app.format('./code/');            // or
app.format('github:user/repo');    

The Queue and Jobs

At it's heart, Mu-Format is a middleware driven program that runs lists, or queues of functions, or jobs. The majority of the work happens in in the render (or pre-render) and compress (or pre-compress) queues.

The Data Object

Each job is passed a data object, containing information about the document currently, as well as a few helper functions to trigger formatter events.

//Some functionality removed for simplification.
const data = {
  path: './code/installer.mu',
  baseDir: './code/',
  
  // The working text of the format file.  
  // All of the #includes are combined into this 
  // attribute, and modify it through out the format
  // process.
  txt: '...',
  
  // A copy of the composited document before rendering 
  // and compressing.
  raw: '...',

  // vars is a unified place to save working data.
  vars: {
    headers: [
      {
        name: 'Foo',
        value: 'bar'
      },
      {
        name: 'Something',
        value: 'important'
      }
    ]
  },

  // The options passed to mu-format at instantiation
  options: {
    plugins: [
      'plugin1',
      '/path/to/plugin2'
    ]
  }
}

Helper Functions

data.emit('Event',[data]) Trigger a custom event on the formatter object.

data.log(message) Trigger a 'log' event on the formatter object, and also save the message in the result object log.

data.error(error) Trigger an 'error' event on theformatter object. Error must be an error object.

Defining Queues and Jobs


module.exports = app => {
  // First, create a queue.  When you call the queue command,
  // it will either create the queue if it doesn't exist - or
  // load an existing queue object. We can link our methods 
  // through chaining. The job function is passed a single 
  // parameter, data.
  app.queue('render')

    .addJob('someJob', data => {
      // actions on the data object. Normally you'll be working 
      // on data.txt where the document contents are stored
      // - but there are other things the data object can do.
      data.log('Log message!')
    })
}
// to run a single job from a queue:
app.queue('name').job('jobName')(data)

Creating plugins

Creating a plugin for the system is pretty straight forward. Make a module that exports a function.

/* .plugins/plugin.js */

module.exports = app => {
  app.queue('pre-render')
    .addJob('custom-job' data => {
      // Do whatever processing you need to do on the current
      // document (data.txt).        
    })
}

 /* index.js */

// after your app is declared.
app.plugins(['./plugins/plugin.js'])

// Or you can declare plugins at runtime.
app.format('github:user/repo',{
  plugins:['./plugins/plugin.js']
})

// You can even just require the file:
require('./plugins/plugin.js')(app)

Formatting Rules

The rules for formatting .mu documents is pretty simple! First, You can format your code however you'd like. I suggest adopting an easy to read style using indentations and spacing to make your code digestable. MU-Format looks for [&+@-] in the first position of the current line to designate the start of a new command, attribute, or spacer. You can add comments in your code in either /* ... */ block style or // inline style comments. A spacer, or dash - is a purely cosmetic mark for formatting the program output. During the compression phase blank lines are removed. Dashes become newlines making the processed code a little easier to process through.

/*
------------------------------------------
--- Commands: +things & +stuff -----------
*/
@@ A comment for someone reading your minified code.
-

&cmd.mycommand me = $+Stuff *:
  @pemit %#=You entered things and %0.

// Another command that does things
&cmd.mycommandtwo me = $+things *=*:
  
  // Sets an attribute on myself!
  &_things me=%0-%1;
  think Things %0 %1! // Wut?

When we format this block of code, it turns into:

@@ A comment for someone reading your minified code.

&cmd_mycommand me = $+Stuff *: @pemit %#=You entered things and %0.
&cmd_mycommandtwo me = $+things *=*: &_things me=%0-%1; think Things %0 %1!

Simple!

The real power of Mu-Format comes in it's #meta tag system. #metas are, when the code is processed, translated into MU friendly output. They are honestly a good way to save a few keystrokes and even organize your code projects. Lets take a look at the few that exist right now:

#include /path/to/file.mu

this #meta allows you to import a file (or entire Github repository) into the current file. #include accepts three kinds of files right now:

  • Local File You can designate a local file to include, entering the ./path/to/file.mu format.
  • Local Directory If you list a directory, Mu-Format will look for a file called installer.mu and kick off the #include from there.
  • Github Archive This is the same as installing from a local directory, instead you'll you'll enter github:user/repo. If you start hitting errors while compiling from Github, try adding Github authorization when you create a new Formatter object.
app = new Formatter({
  gitUser: 'user',
  gitPass: '123Secret!'
})

Example

&cmd.command #123 = $foo *:
  think me Foo %0.

// Include the rest of the library.
#include ./path/to/file2.mu

#esc|#file [file[|string]]

Honestly #esc (or #file) works list like #include, except it escapes each line of text with a MUSH null string @@ so they don't get quoted to the Game. This is great for things like license files, and other custom comments text.

@@ Legal Stuff
@@ Bla bla, yadda
@@
@@ Instructions
@@ ----------------
@@ 1. Things and
@@ 2. Stuff

#header or #footer key=value

Add key/value information to be listed at the very top or bottom of the resulting file. #header version=1.0.0 escapes into: @@ version 1.0.0 at the top of the resulting document.

#def string|regex

Roll your own edits! I wanted to keep the system as open to modification as I could. #def #metas are are a way to replace tags with code at processing time. I find them really useful for code snippets that I'm going to use more than once or twice. Remember! a @&-+ at the beginning of a line results in a new command or attribute being defined.

#def #check-wiz
  @assert hasflag(%#,Wizard) = {@pemit %#=Permission denied.}
#enddef

Then later in your code:

&cmd.wizcode #1234=$+cmd foobar:
  #wiz-check
  // Rest of your code ...

You can also make a #def that uses a regular expression string (you don't need to provide the beginning and end of the search //). Any group matches can represented in your code in the variables $0 - $9 Remember! $0 is the entire match.

#def #create\s+(.*)\s*=\s*(.*)
@if [locate(me,$1,*)] = {
  @create $1;
  &$2 me = [locate(me,$1,*)];
},{
  &$2 me = [locate(me,$1,*)];
}
#enddef