I've taken what Rubén has provided above and bits and pieces from elsewhere to come up with a reasonably flexible way to convert HTML styling on external text for insertion at the cursor position in a google document. The caveat is that you need to know precisely the HTML tags that are in the external text (in my case, I do). This code does the italics plus a few other tags, deals with nested and multiple tags, and deletes the HTML code. For fun, I've added in HREF handling. I'm sure it can be improved and/or made more efficient (e.g. I'd love to know how to get away with just the one regExp()
, for example) – how can it be improved?
var regexpItalics = RegExp(/(<em>)(.*?)(<\/em>)/, 'g');
var regexpBold = RegExp(/(<strong>)(.*?)(<\/strong>)/, 'g');
var regexpUnderline = RegExp(/(<span style="text-decoration: underline;">)(.*?)(<\/span>)/, 'g');
var regexpSub = RegExp(/(<sub>)(.*?)(<\/sub>)/, 'g');
var regexpSup = RegExp(/(<sup>)(.*?)(<\/sup>)/, 'g');
var regexpHref = RegExp(/(<a class="rLink" href=".*>)(.*?)(<\/a>)/, 'g');
var deleteArray = [];
var i;
var text = "some text with <em>itali<strong>cs</em> and bold</strong>";
var document = DocumentApp.getActiveDocument();
var cursor = document.getCursor();
var element = cursor.insertText(text);
var styles = ['italics', 'bold', 'underline', 'super', 'sub', 'href'];
for (i = 0; i < styles.length; i++) {
insertHtmlText(element, text, styles[i]);
}
deleteArray.sort(function (b, a) {
return a.end - b.end;
});
for(i = 0; i < deleteArray.length; i++) {
element.editAsText().deleteText(deleteArray[i].start, deleteArray[i].end);
}
function insertHtmlText(element, text, style) {
var i;
var matches = [];
var transformArray = [];
switch (style) {
case 'italics':
matches = [...text.matchAll(regexpItalics)];
transformArray = findTags(matches);
for(i = 0; i < transformArray.length; i++) {
element.editAsText().setItalic(transformArray[i].textStart, transformArray[i].textEnd, true);
}
break;
case 'bold':
matches = [...text.matchAll(regexpBold)];
transformArray = findTags(matches);
for(i = 0; i < transformArray.length; i++) {
element.editAsText().setBold(transformArray[i].textStart, transformArray[i].textEnd, true);
}
break;
case 'underline':
matches = [...text.matchAll(regexpUnderline)];
transformArray = findTags(matches);
for(i = 0; i < transformArray.length; i++) {
element.editAsText().setUnderline(transformArray[i].textStart, transformArray[i].textEnd, true);
}
break;
case 'super':
matches = [...text.matchAll(regexpSup)];
transformArray = findTags(matches);
for(i = 0; i < transformArray.length; i++) {
element.editAsText().setTextAlignment(transformArray[i].textStart, transformArray[i].textEnd, DocumentApp.TextAlignment.SUPERSCRIPT);
}
break;
case 'sub':
matches = [...text.matchAll(regexpSub)];
transformArray = findTags(matches);
for(i = 0; i < transformArray.length; i++) {
element.editAsText().setTextAlignment(transformArray[i].textStart, transformArray[i].textEnd, DocumentApp.TextAlignment.SUBSCRIPT);
}
break;
case 'href':
matches = [...text.matchAll(regexpHref)];
transformArray = findTags(matches);
for(i = 0; i < transformArray.length; i++) {
element.editAsText().setLinkUrl(transformArray[i].textStart, transformArray[i].textEnd, transformArray[i].capture);
}
break;
default:
break; // Missing format
}
}
function findTags(matches) {
var openTagStart, openTagEnd, textStart, textEnd, closeTagStart, closeTagEnd;
var transformArray = [];
for (let match of matches) {
openTagStart = match.index;
openTagEnd = openTagStart + match[1].length - 1;
textStart = openTagEnd + 1;
textEnd = textStart + match[2].length - 1;
closeTagStart = textEnd + 1;
closeTagEnd = closeTagStart + match[3].length -1;
transformArray.push({
openTagStart: openTagStart,
openTagEnd: openTagEnd,
textStart: textStart,
textEnd: textEnd,
closeTagStart: closeTagStart,
closeTagEnd: closeTagEnd,
capture: match[2]
});
deleteArray.push({start: openTagStart, end: openTagEnd});
deleteArray.push({start: closeTagStart, end: closeTagEnd});
}
return transformArray;
}