function makePossibleRangesHTML(source, tokens, offset) {
		offset = offset || 0;
		var range = require('range');
		var result = [];
		var attrStart = -1, attrName = '', attrValue = '', attrValueRange, tagName;
		_.each(tokens, function(tok) {
			switch (tok.type) {
				case 'tag':
					tagName = source.substring(tok.start, tok.end);
					if (/^<[\w\:\-]/.test(tagName)) {
						// add tag name
						result.push(range.create({
							start: tok.start + 1, 
							end: tok.end
						}));
					}
					break;
				case 'attribute':
					attrStart = tok.start;
					attrName = source.substring(tok.start, tok.end);
					break;
					
				case 'string':
					// attribute value
					// push full attribute first
					 result.push(range.create(attrStart, tok.end - attrStart));
					 
					 attrValueRange = range.create(tok);
					 attrValue = attrValueRange.substring(source);
					 
					 // is this a quoted attribute?
					 if (isQuote(attrValue.charAt(0)))
						 attrValueRange.start++;
					 
					 if (isQuote(attrValue.charAt(attrValue.length - 1)))
						 attrValueRange.end--;
					 
					 result.push(attrValueRange);
					 
					 if (attrName == 'class') {
						 result = result.concat(classNameRanges(attrValueRange.substring(source), attrValueRange.start));
					 }
					 
					break;
			}
		});
		
		// offset ranges
		_.each(result, function(r) {
			r.shift(offset);
		});
		
		return _.chain(result)
			.filter(function(item) {        // remove empty
				return !!item.length();
			})
			.uniq(false, function(item) {   // remove duplicates
				return item.toString();
			})
			.value();
	}
function makePossibleRangesHTML(source, tokens, offset) {
		offset = offset || 0;
		var range = require('range');
		var result = [];
		var attrStart = -1, attrName = '', attrValue = '', attrValueRange, tagName;
		_.each(tokens, function(tok) {
			switch (tok.type) {
				case 'tag':
					tagName = source.substring(tok.start, tok.end);
					if (/^<[\w\:\-]/.test(tagName)) {
						
						result.push(range.create({
							start: tok.start + 1, 
							end: tok.end
						}));
					}
					break;
				case 'attribute':
					attrStart = tok.start;
					attrName = source.substring(tok.start, tok.end);
					break;
					
				case 'string':
					
					
					 result.push(range.create(attrStart, tok.end - attrStart));
					 
					 attrValueRange = range.create(tok);
					 attrValue = attrValueRange.substring(source);
					 
					 
					 if (isQuote(attrValue.charAt(0)))
						 attrValueRange.start++;
					 
					 if (isQuote(attrValue.charAt(attrValue.length - 1)))
						 attrValueRange.end--;
					 
					 result.push(attrValueRange);
					 
					 if (attrName == 'class') {
						 result = result.concat(classNameRanges(attrValueRange.substring(source), attrValueRange.start));
					 }
					 
					break;
			}
		});
		
		
		_.each(result, function(r) {
			r.shift(offset);
		});
		
		return _.chain(result)
			.filter(function(item) {        
				return !!item.length();
			})
			.uniq(false, function(item) {   
				return item.toString();
			})
			.value();
	}
function makePossibleRangesHTML ( source , tokens , offset ) { offset = offset || 0 ; var range = require ( 'range' ) ; var result = [ ] ; var attrStart = - 1 , attrName = '' , attrValue = '' , attrValueRange , tagName ; _ . each ( tokens , function ( tok ) { switch ( tok . type ) { case 'tag' : tagName = source . substring ( tok . start , tok . end ) ; if ( / ^<[\w\:\-] / . test ( tagName ) ) { // add tag name result . push ( range . create ( { start : tok . start + 1 , end : tok . end } ) ) ; } break ; case 'attribute' : attrStart = tok . start ; attrName = source . substring ( tok . start , tok . end ) ; break ; case 'string' : // attribute value // push full attribute first result . push ( range . create ( attrStart , tok . end - attrStart ) ) ; attrValueRange = range . create ( tok ) ; attrValue = attrValueRange . substring ( source ) ; // is this a quoted attribute? if ( isQuote ( attrValue . charAt ( 0 ) ) ) attrValueRange . start ++ ; if ( isQuote ( attrValue . charAt ( attrValue . length - 1 ) ) ) attrValueRange . end -- ; result . push ( attrValueRange ) ; if ( attrName == 'class' ) { result = result . concat ( classNameRanges ( attrValueRange . substring ( source ) , attrValueRange . start ) ) ; } break ; } } ) ; // offset ranges _ . each ( result , function ( r ) { r . shift ( offset ) ; } ) ; return _ . chain ( result ) . filter ( function ( item ) { // remove empty return ! ! item . length ( ) ; } ) . uniq ( false , function ( item ) { // remove duplicates return item . toString ( ) ; } ) . value ( ) ; }
Creates possible selection ranges for HTML tag
@param {String} source Original HTML source for tokens
@param {Array} tokens List of HTML tokens
@returns {Array}
Creates possible selection ranges for HTML tag