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

string-mutator

v0.2.0

Published

Perform mutation operations on text strings (or text files). Useful for (simple) automatic code refactorings f.ex in code generators

Downloads

22

Readme

Build Status

Perform mutation operations on text strings (or text files). Useful for (simple) automatic code refactorings f.ex in code generators.

Getting Started

Install the module with: npm install string-mutator

Install with cli command

$ npm install -g string-mutator
$ string-mutator --help
$ string-mutator --version

Browserify

$ npm run-script browser

Documentation

Quick start

var mutators = require('mutators');
var sm = mutators.string; // string mutator
var fm = mutators.file; // file mutator

var msg = "Peter has 8 dollars and Jane has 15"

// String mutator
sm.last('Jane has 15').remove().on(msg);

// using content
sm.content(msg).last(/\d+/g).replaceWith('32');


// File mutator - performing string mutations
fm.readFile('test/files/test.txt').perform(function() {
    return this.first(/\d+/).prepend('$');
  }).write();

console.log('wrote', written, res.lastWritten);
res.write(res.original);

String mutator API

The string mutation API uses chaining. To start a chain, use any of:

  • first(matchExpr)
  • last(matchExpr)
  • content(text)

first and last

The first and last functions each take a matching expression that can be a simple string or a regular expression.

The result can chained with any of:

  • append
  • prepend
  • replaceWith
  • remove

append and prepend

sm.first(matchExpr).append('<FOUND>', target);

chaining

Both append and prepend can be chained with to like this

sm.first(matchExpr).append("\nEND").to(target);

relaceWith and remove

sm.first(matchExpr).remove(target);

chaining

replace and remove can be chained with on like this:

sm.first(matchExpr).replaceWith(something).on(target);

first.prepend

var sm = require('string-mutator');

var msg = "Peter has 8 dollars and Jane has 15"
var res = sm.first(/\d+/g).prepend('$', msg);

// => "Peter has $8 dollars and Jane has 15"

The following pattern valid for any prepend/append action.

`(text).to(content)*``

append(text).to(content) or prepend(text).to(content)

var sm = require('../lib/string-mutator.js');

var msg = "Peter has 8 dollars and Jane has 15"
var res = sm.first(/\d+/g).prepend('$').to(msg);

// => "Peter has $8 dollars and Jane has 15"

first.append

var msg = "Peter has 8 dollars and Jane has 15"
var res = sm.first(/\d+/g).append('$', msg);
res = sm.first(/\d+/g).append('$').to(msg);

// => "Peter has 8$ dollars and Jane has 15"

last.prepend

var msg = "Peter has 8 dollars and Jane has 15"
var res = sm.last(/\d+/g).prepend('$', msg);
// res = sm.last(/\d+/g).prepend('$').to(msg);

// => "Peter has 8 dollars and Jane has $15");

last.append

var msg = "Peter has 8 dollars and Jane has 15$"
var res = sm.last(/\d+/g).append('$', msg);
// res = sm.last(/\d+/g).append('$').to(msg);

// => "Peter has 8 dollars and Jane has 15$");

replaceWith

var msg = "Peter has 8 dollars and Jane has 15$"
var res = sm.last(/\d+/g).replaceWith('42', msg);

res = sm.first(/\d+/g).replaceWith('42').on(msg);

// => "Peter has 8 dollars and Jane has 42");

remove

Replace match with empty content ;)

var msg = "Peter has 8 dollars and Jane has 15"
var res = sm.last('and Jane has 15').remove(msg);
sm.last(/\d+/g).remove().on(msg);

// => "Peter has 8 dollars");

Content

An alternative is to start off by wrapping the text in a content object

Content can be chained with any of the following:

  • first
  • last
  • before
  • after
  • between
  • prependTxt
  • appendTxt
var msg = "Peter has 8 dollars and Jane has 15"
sm.content(msg).last('Jane has 15').remove();

// => "Peter has 8 dollars");

Before

before is chained on a content object and returns a new content object with the text before a match. Optionally it can take a matcher indicator string, which can be set to 'first' or 'last' (effectively: "before first" or "before last")

var msg = "Peter has 15 dollars, Jane has 15 and Paul has 32"
sm.content(msg).before(/Jane/).last(/\d+/g).replaceWith('20');

// => Peter has 20 dollars, Jane has 15 and Paul has 32

chaining prependTxt on before prepends the text before the match.

msg = "Peter have 12 dollars, Paul"
var res = sm.content(msg).before(/Paul/).prependTxt('Tina has 7.').result;
// => Peter have 12 dollars, Tina has 7

Using `mergeRest()``

msg = "Peter have 12 dollars, Paul"
var res = sm.content(msg).before(/Paul/).prependTxt('Tina has 7 and').mergeRest();
// => Peter have 12 dollars, Tina has 7 and Paul

before last

before (and after) also take an options hash for further control. The match: 'last' option can be used to find the last match within the scope.

msg = "Peter have 12 dollars, Paul is here Paul goes back"
var res = sm.content(msg).before(/Paul/, {include: true, match: 'last'}).prependTxt('Tina has 7 and').mergeRest();
// => Peter have 12 dollars, Paul is here Tina has 7 and Paul goes back

For convenience beforeLast and afterLast methods are also available.

`var res = sm.content(msg).beforeLast(/Paul/)``

After

Same as before but instead "after" ;)

If in doubt, see the test suite in the /test folder.

Between

between is chained on a content object and returns a new content object with the text between two matches.

var msg = "Peter has 15 dollars, Jane has 15 and Paul has 32 or 15"
sm.content(msg).between(/Peter/).and(/Paul/).last(/\d+/g).replaceWith('20');

// => Peter has 15 dollars, Jane has 20 and Paul has 32 or 15

inclusive

Both between, and are exclusive by default. You can now also use an options hash {include: true} to be inclusive. This option can also be used with before and after.

var msg = "Peter has 15 dollars, Jane has 15 and Paul has 32 or 15"
sm.content(msg).between(/Peter/, {include: true}).and(/Paul/, {include: true}).result;

// => Peter has 15 dollars, Jane has 20 and Paul

Shorthand inclusive:

`sm.content(msg).betweenIncl(/Peter/).andIncl(/Paul/)``

prependTxt

Adds text at beginning of content

`sm.content("Kristian").prependTxt('Hello, Sir ')``

appendTxt

Adds text at the end of content

sm.content("Paula").appendTxt(', says Goodbye')

Status

All tests pass :)

More advanced operations

For even more string manipulation, I recommend splitting a string into its multiple parts using a split function, then iterating through them and using this API on each part, then joining them back together.

You are most welcome to propose a nice API to facilitate this.

File mutator API

File mutation always starts with readFile

var fileMutateObj = fm.readFile('test/files/test.txt');

The result of readFile should always be chained with perform, which performs the string mutation on the content read.

perform wraps the read content in a content object (see: String mutator API) which becomes this in the context/scope of the function.

fm.readFile('test/files/test.txt').perform(function() {
    return this.first(/\d+/).prepend('$');
  })

The result of the perform mutation can be chained with any of:

  • write([newContent])
  • writeFile(fileName, [newContent])
  • read()
  • lastWritten
  • original

Complete example:

fm.readFile('test/files/test.txt').perform(function() {
    return this.first(/\d+/).prepend('$');
  }).write();

console.log('wrote', written, res.lastWritten);
res.write(res.original);

res.writeFile('another_file.txt');

TODO

Cleanup and Refactor!!! Lot's of duplication :(

Add more customizability than simply first/last. It would be sweet if user could pass a function that selects one or more matches to operate on/from.

Contributing

Add unit tests for any new or changed functionality. Lint and test your code using Grunt.

License

Copyright (c) 2014 Kristian Mandrup
Licensed under the MIT license.