code: function(abbr, ctx, content, options) {
  			if (!ctx) {
  				// nothing to update
  				return null;
  			}
  
  			var tree = parser.parse(abbr, options || {});
  
  			// for this action some characters in abbreviation has special
  			// meaning. For example, `.-c2` means “remove `c2` class from
  			// element” and `.+c3` means “append class `c3` to exising one.
  			// 
  			// But `.+c3` abbreviation will actually produce two elements:
  			// <div class=""> and <c3>. Thus, we have to walk on each element
  			// of parsed tree and use their definitions to update current element
  			var tag = xmlEditTree.parse(ctx.match.open.range.substring(content), {
  				offset: ctx.match.outerRange.start
  			});
  
  			tree.children.forEach(function(node, i) {
  				updateAttributes(tag, node, i);
  			});
  
  			// if tag name was resolved by implicit tag name resolver,
  			// then user omitted it in abbreviation and wants to keep
  			// original tag name
  			var el = tree.children[0];
  			if (!el.data('nameResolved')) {
  				tag.name(el.name());
  			}
  
  			return tag;
  		}
docs: Returns XMLEditContainer node with updated tag structure
  of existing tag context.
  This data can be used to modify existing tag
  @param  {String} abbr    Abbreviation
  @param  {Object} ctx     Tag to be updated (captured with `htmlMatcher`)
  @param  {String} content Original editor content
  @return {XMLEditContainer}