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

node-balanced

v0.0.14

Published

balanced string matching, and replacing.

Downloads

35,480

Readme

Balanced Build Status

balanced string matching, and replacing.

install

npm install node-balanced

example time

lets say you have

{
	@hello 1 {
		a {
		}
	}
	@hello 2 {
		a {
		}
	}
	@hello 3 {
		a {
		}
	}
}

and you would like to replace the @hello block easily, balanced allows you to do this

var balanced = require('node-balanced');

balanced.replacements({
	source: source,
	head: /@hello \d \{/, // optional (defalut: open)
	open: '{',
	close: '}',
	balance: false, // optional (default: false)
	exceptions: false, // optional (default: false)
	replace: function (source, head, tail) {
		return head + source + tail;
	}
});

this is a simple and efficient way to make balanced replacements, without a parser.

matching

you can get balanced matches by doing the following

var balanced = require('node-balanced');

balanced.matches({
	source: source,
	head: /@hello \d \{/, // optional (defalut: open)
	open: '{',
	close: '}',
	balance: false, // optional (default: false) when set to true it will return `null` when there is an error
	exceptions: false // optional (default: false),
	ignore: [] // array of ignore ranges/matches
});

multiple head/open/close

you can match multiple head/open/close efficiently by doing this

var isBalanced = balanced.matches({
	source: '{[({)]}}',
	open: ['{', '[', '('],
	close: ['}', ']', ')'],
	balance: true
});

ignore

ignore is supported by the matches and replacements methods, this is very useful for something like not matching inside of comments

var blockComments = balanced.matches({source: source, open: '/*', close: '*/'}),
	singleLineComments = balanced.getRangesForMatch(source, /^\s*\/\/.+$/gim);

balanced.matches({
	source: source,
	head: /@hello \d \{/,
	open: '{',
	close: '}',
	ignore: Array.prototype.concat.call([], blockComments, singleLineComments),
	replace: function (source, head, tail) {
		return head + source + tail;
	}
});

advanced

in this example we have code and we want to avoid replacing text thats inside of the multiline/singleline comments, and quotes

{
	@hello 1 {
		a {
		}
	}
/*
	@hello 2 {
		a {
		}
	}
*/
	@hello 3 {
		a {
		}
	}
// @hello 4 {}
}

var hello = "@hello 5 {}";

with balanced you can do this

	// returns quote ranges with option ignore filter
	function getQuoteRanges (string, ignore) {
		var quotes = balanced.getRangesForMatch(string, new RegExp('\'|"', 'g'));
		
		// filter out ingored ranges
		if (ignore) {
			quotes = balanced.rangesWithout(quotes, ignore);
		}

		var currect = null,
			ranges = [];
	
		quotes.forEach(function (quote) {
			if (currect && currect.match === quote.match) {
					ranges.push({
						index: currect.index,
						length: quote.index - currect.index + 1
					});
					currect = null;
			} else if (!currect) {
				currect = quote;
			}
		});

		return ranges;
	}

	var blockComments = balanced.matches({source: string, open: '/*', close: '*/'}),
		singleLineComments = balanced.getRangesForMatch(string, /^\s*\/\/.+$/gim),
		ignores = Array.prototype.concat.call([], blockComments, singleLineComments),
		quotes = getQuoteRanges(string, ignores);

	// remove ignores inside of quotes
	ignores = balanced.rangesWithout(ignores, quotes);

	// optional ignore code inside of quotes
	ignores = ignores.concat(quotes);
	
	// run your matches or replacements method
	balanced.matches({
		source: string,
		head: /@hello \d \{/,
		open: '{',
		close: '}',
		ignore: ignores
	});

as you can see by using these principles you can accomplish this kind of stuff easily