docs: function (wrapper) {
              var textNode = wrapper.element,
                renderer = this,
                forExport = renderer.forExport,
                textStr = pick(wrapper.textStr, '').toString(),
                hasMarkup = textStr.indexOf('<') !== -1,
                lines,
                childNodes = textNode.childNodes,
                styleRegex,
                hrefRegex,
                parentX = attr(textNode, 'x'),
                textStyles = wrapper.styles,
                width = wrapper.textWidth,
                textLineHeight = textStyles && textStyles.lineHeight,
                textStroke = textStyles && textStyles.HcTextStroke,
                i = childNodes.length,
                getLineHeight = function (tspan) {
                    return textLineHeight ?
                      pInt(textLineHeight) :
                      renderer.fontMetrics(
                        /(px|em)$/.test(tspan && tspan.style.fontSize) ?
                          tspan.style.fontSize :
                          ((textStyles && textStyles.fontSize) || renderer.style.fontSize || 12),
                        tspan
                      ).h;
                };
  
              /// remove old text
              while (i--) {
                  textNode.removeChild(childNodes[i]);
              }
  
              // Skip tspans, add text directly to text node. The forceTSpan is a hook
              // used in text outline hack.
              if (!hasMarkup && !textStroke && textStr.indexOf(' ') === -1) {
                  textNode.appendChild(doc.createTextNode(textStr));
                  return;
  
                  // Complex strings, add more logic
              } else {
  
                  styleRegex = /<.*style="([^"]+)".*>/;
                  hrefRegex = /<.*href="(http[^"]+)".*>/;
  
                  if (width && !wrapper.added) {
                      this.box.appendChild(textNode); // attach it to the DOM to read offset width
                  }
  
                  if (hasMarkup) {
                      lines = textStr
                        .replace(/<(b|strong)>/g, '<span style="font-weight:bold">')
                        .replace(/<(i|em)>/g, '<span style="font-style:italic">')
                        .replace(/<a/g, '<span')
                        .replace(/<\/(b|strong|i|em|a)>/g, '</span>')
                        .split(/<br.*?>/g);
  
                  } else {
                      lines = [textStr];
                  }
  
  
                  // remove empty line at end
                  if (lines[lines.length - 1] === '') {
                      lines.pop();
                  }
  
  
                  // build the lines
                  each(lines, function (line, lineNo) {
                      var spans, spanNo = 0;
  
                      line = line.replace(/<span/g, '|||<span').replace(/<\/span>/g, '</span>|||');
                      spans = line.split('|||');
  
                      each(spans, function (span) {
                          if (span !== '' || spans.length === 1) {
                              var attributes = {},
                                tspan = doc.createElementNS(SVG_NS, 'tspan'),
                                spanStyle; // #390
                              if (styleRegex.test(span)) {
                                  spanStyle = span.match(styleRegex)[1].replace(/(;| |^)color([ :])/, '$1fill$2');
                                  attr(tspan, 'style', spanStyle);
                              }
                              if (hrefRegex.test(span) && !forExport) { // Not for export - #1529
                                  attr(tspan, 'onclick', 'location.href=\"' + span.match(hrefRegex)[1] + '\"');
                                  css(tspan, { cursor: 'pointer' });
                              }
  
                              span = (span.replace(/<(.|\n)*?>/g, '') || ' ')
                                .replace(/&lt;/g, '<')
                                .replace(/&gt;/g, '>');
  
                              // Nested tags aren't supported, and cause crash in Safari (#1596)
                              if (span !== ' ') {
  
                                  // add the text node
                                  tspan.appendChild(doc.createTextNode(span));
  
                                  if (!spanNo) { // first span in a line, align it to the left
                                      if (lineNo && parentX !== null) {
                                          attributes.x = parentX;
                                      }
                                  } else {
                                      attributes.dx = 0; // #16
                                  }
  
                                  // add attributes
                                  attr(tspan, attributes);
  
                                  // Append it
                                  textNode.appendChild(tspan);
  
                                  // first span on subsequent line, add the line height
                                  if (!spanNo && lineNo) {
  
                                      // allow getting the right offset height in exporting in IE
                                      if (!hasSVG && forExport) {
                                          css(tspan, { display: 'block' });
                                      }
  
                                      // Set the line height based on the font size of either
                                      // the text element or the tspan element
                                      attr(
                                        tspan,
                                        'dy',
                                        getLineHeight(tspan)
                                      );
                                  }
  
                                  // check width and apply soft breaks
                                  if (width) {
                                      var words = span.replace(/([^\^])-/g, '$1- ').split(' '), // #1273
                                        hasWhiteSpace = spans.length > 1 || (words.length > 1 && textStyles.whiteSpace !== 'nowrap'),
                                        tooLong,
                                        actualWidth,
                                        hcHeight = textStyles.HcHeight,
                                        rest = [],
                                        dy = getLineHeight(tspan),
                                        softLineNo = 1,
                                        bBox;
  
                                      while (hasWhiteSpace && (words.length || rest.length)) {
                                          delete wrapper.bBox; // delete cache
                                          bBox = wrapper.getBBox();
                                          actualWidth = bBox.width;
  
                                          // Old IE cannot measure the actualWidth for SVG elements (#2314)
                                          if (!hasSVG && renderer.forExport) {
                                              actualWidth = renderer.measureSpanWidth(tspan.firstChild.data, wrapper.styles);
                                          }
  
                                          tooLong = actualWidth > width;
                                          if (!tooLong || words.length === 1) { // new line needed
                                              words = rest;
                                              rest = [];
                                              if (words.length) {
                                                  softLineNo++;
                                                  if (hcHeight && softLineNo * dy > hcHeight) {
                                                      words = ['...'];
                                                      wrapper.attr('title', wrapper.textStr);
                                                  } else {
  
                                                      tspan = doc.createElementNS(SVG_NS, 'tspan');
                                                      attr(tspan, {
                                                          dy: dy,
                                                          x: parentX
                                                      });
                                                      if (spanStyle) { // #390
                                                          attr(tspan, 'style', spanStyle);
                                                      }
                                                      textNode.appendChild(tspan);
                                                  }
                                              }
                                              if (actualWidth > width) { // a single word is pressing it out
                                                  width = actualWidth;
                                              }
                                          } else { // append to existing line tspan
                                              tspan.removeChild(tspan.firstChild);
                                              rest.unshift(words.pop());
                                          }
                                          if (words.length) {
                                              tspan.appendChild(doc.createTextNode(words.join(' ').replace(/- /g, '-')));
                                          }
                                      }
                                  }
  
                                  spanNo++;
                              }
                          }
                      });
                  });
              }
          }