0.0.14 • Published 10 years ago

node-balanced v0.0.14

Weekly downloads
11,747
License
MIT
Repository
github
Last release
10 years ago

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