Search code examples
javascriptregexgoogle-apps-scriptgoogle-docs

Javascript/Apps Script what regex pattern should I use for a specific string containing special characters pulled from a Google Doc


Here is a minimal reproducable example.

Code.gs:

function doGet() {
  return HtmlService.createTemplateFromFile('index').evaluate();
}

function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename).getContent();
}

function sendTemplateEmail(replacements) {

  const template = DriveApp.getFileById('1boJRowTA90zy4CIn0DkK_9oERoEYk2iZRmuB7sSagKU');
  const copyFile = template.makeCopy('temp template')
  const copyDoc = DocumentApp.openById(copyFile.getId());
  const body = copyDoc.getBody();

  for(let i = 0; i < replacements.length; i++) {
    body.replaceText(replacements[i][0], replacements[i][1])
  }

  copyDoc.saveAndClose()

  let emailBody = docToHtml(copyFile.getId())
  copyFile.setTrashed(true);

  MailApp.sendEmail('nick@icarenetwork.com', 'testing', emailBody, {
    htmlBody: emailBody
  })
}

function docToHtml(docId) {
  // Downloads a Google Doc as an HTML string.
  let url = 'https://docs.google.com/feeds/download/documents/export/Export?id=' +
            docId + '&exportFormat=html';
  var param = {
    method: 'get',
    headers: {'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()},
    muteHttpExceptions: true,
  };
  let doc = UrlFetchApp.fetch(url, param).getContentText();
  return doc;
}

index.html:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">

    <?!= include('script')?>
  </head>
  <body>
    My webapp content
  </body>
</html>

script.html:

<script>

  let replacements = [
    ['<<[[]Sample \(text\) & more sample text[]]>>', 'replacement1'],
    ['Regex', 'replacement2']
  ]

  google.script.run.sendTemplateEmail(replacements);

</script>

Here is the link to the template document which is simplified: https://docs.google.com/document/d/1RTFbfaveI2C9kzzPqeKwuy33a5BuNXlQtCom9pYNt88/edit?usp=sharing

I included the whole GAS project because I'm not sure if there is a difference between how Apps Script uses the replaceText method and regex vs. how it would work in JS. Also, my array was acting weird when I tried to populate it with raw regexps.

What I want is to replace the second line in the template document, which is <<[Sample-text that I am using (i.e., this, that)]>> with a string (in this example it's 'replacement2'). I want to replace the entire thing, including the <<[]>>

Note: I need the regex to target the brackets and the exact text within them, not just all the characters and symbols within them. This is because I will have lots of other lines of text in the Doc that is surrounded by the <<[]>> brackets that I will also neet to target individually. So a regex that selects the brackets and everything in between them will not work.

This program is supposed to be an Apps Script version of App Sheet's way of sending an email with a template file. I need to use the same structure of including variables in the template as is used in App Sheet. That's why I'm using <<[]>>


Solution

  • I believe your goal is as follows.

    • In Google Document, you want to replace a value of a value enclosed by <<[ and ]>> like <<[Sample-text that I am using (i.e., this, that)]>> with replacement2.

    In this case, how about the following sample script?

    Sample script:

    const doc = DocumentApp.openById("###"); // Please set your document ID.
    doc.getBody().replaceText('<<\\[.*\\]>>', 'replacement2');
    
    • In this case, the searchPattern and replacement of replaceText(searchPattern, replacement) are <<\\[.*\\]>> and replacement2, respectively.

    Reference:

    Added:

    From your following added information,

    Note: I need the regex to target the brackets and the exact text within them, not just all the characters and symbols within them. This is because I will have lots of other lines of text in the Doc that is surrounded by the <<[]>> brackets that I will also neet to target individually. So a regex that selects the brackets and everything in between them will not work.

    When your provided sample Document is used, when you want to individually replace each text of <<[Sample (text) & more sample text]>> and <<[Sample-text that I am using (i.e., this, that)]>>, how about the following sample script?

    Sample script:

    const obj = [
      ["<<[Sample (text) & more sample text]>>", "replacement1"],
      ["<<[Sample-text that I am using  (i.e., this, that)]>>", "replacement2"]
    ];
    const doc = DocumentApp.getActiveDocument();
    obj.forEach(([from, to]) => doc.getBody().replaceText(from.replace(/[()-\/\\^$*+?.{}|\[\]]/g, "\\$&"), to));
    
    • In this sample script, the text is replaced by escaping the regex meta characters.
      • I reffered this thead. Ref