docs: function parse_rpr(rpr, intro, outro) {
  		var font = {}, cp = 65001, align = "";
  		var pass = false;
  		var m = rpr.match(tagregex), i = 0;
  		if(m) for(;i!=m.length; ++i) {
  			var y = parsexmltag(m[i]);
  			switch(y[0].replace(/\w*:/g,"")) {
  				/* 18.8.12 condense CT_BooleanProperty */
  				/* ** not required . */
  				case '<condense': break;
  				/* 18.8.17 extend CT_BooleanProperty */
  				/* ** not required . */
  				case '<extend': break;
  				/* 18.8.36 shadow CT_BooleanProperty */
  				/* ** not required . */
  				case '<shadow':
  					if(!y.val) break;
  					/* falls through */
  				case '<shadow>':
  				case '<shadow/>': font.shadow = 1; break;
  				case '</shadow>': break;
  
  				/* 18.4.1 charset CT_IntProperty TODO */
  				case '<charset':
  					if(y.val == '1') break;
  					cp = CS2CP[parseInt(y.val, 10)];
  					break;
  
  				/* 18.4.2 outline CT_BooleanProperty TODO */
  				case '<outline':
  					if(!y.val) break;
  					/* falls through */
  				case '<outline>':
  				case '<outline/>': font.outline = 1; break;
  				case '</outline>': break;
  
  				/* 18.4.5 rFont CT_FontName */
  				case '<rFont': font.name = y.val; break;
  
  				/* 18.4.11 sz CT_FontSize */
  				case '<sz': font.sz = y.val; break;
  
  				/* 18.4.10 strike CT_BooleanProperty */
  				case '<strike':
  					if(!y.val) break;
  					/* falls through */
  				case '<strike>':
  				case '<strike/>': font.strike = 1; break;
  				case '</strike>': break;
  
  				/* 18.4.13 u CT_UnderlineProperty */
  				case '<u':
  					if(!y.val) break;
  					switch(y.val) {
  						case 'double': font.uval = "double"; break;
  						case 'singleAccounting': font.uval = "single-accounting"; break;
  						case 'doubleAccounting': font.uval = "double-accounting"; break;
  					}
  					/* falls through */
  				case '<u>':
  				case '<u/>': font.u = 1; break;
  				case '</u>': break;
  
  				/* 18.8.2 b */
  				case '<b':
  					if(y.val == '0') break;
  					/* falls through */
  				case '<b>':
  				case '<b/>': font.b = 1; break;
  				case '</b>': break;
  
  				/* 18.8.26 i */
  				case '<i':
  					if(y.val == '0') break;
  					/* falls through */
  				case '<i>':
  				case '<i/>': font.i = 1; break;
  				case '</i>': break;
  
  				/* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */
  				case '<color':
  					if(y.rgb) font.color = y.rgb.slice(2,8);
  					break;
  
  				/* 18.8.18 family ST_FontFamily */
  				case '<family': font.family = y.val; break;
  
  				/* 18.4.14 vertAlign CT_VerticalAlignFontProperty TODO */
  				case '<vertAlign': align = y.val; break;
  
  				/* 18.8.35 scheme CT_FontScheme TODO */
  				case '<scheme': break;
  
  				/* 18.2.10 extLst CT_ExtensionList ? */
  				case '<extLst': case '<extLst>': case '</extLst>': break;
  				case '<ext': pass = true; break;
  				case '</ext>': pass = false; break;
  				default:
  					if(y[0].charCodeAt(1) !== 47 && !pass) throw new Error('Unrecognized rich format ' + y[0]);
  			}
  		}
  		var style = [];
  
  		if(font.u) style.push("text-decoration: underline;");
  		if(font.uval) style.push("text-underline-style:" + font.uval + ";");
  		if(font.sz) style.push("font-size:" + font.sz + "pt;");
  		if(font.outline) style.push("text-effect: outline;");
  		if(font.shadow) style.push("text-shadow: auto;");
  		intro.push('<span style="' + style.join("") + '">');
  
  		if(font.b) { intro.push("<b>"); outro.push("</b>"); }
  		if(font.i) { intro.push("<i>"); outro.push("</i>"); }
  		if(font.strike) { intro.push("<s>"); outro.push("</s>"); }
  
  		if(align == "superscript") align = "sup";
  		else if(align == "subscript") align = "sub";
  		if(align != "") { intro.push("<" + align + ">"); outro.push("</" + align + ">"); }
  
  		outro.push("</span>");
  		return cp;
  	}