Google Apps Script search and replace URL truncates 1 character in rendered link

Viewed 44

I'm using the code below to search for URLs in a Google Doc and turn them into active links. It works beautifully, except that the link cuts off the last character of the URL (e.g. "https://link.com/123" gets linked as "https://link.com/12").

function updateLinks() {
  var linkRegex = "https?:\/\/[^\\s]*";

  //Open active doc
  var body = DocumentApp.getActiveDocument().getBody();
  //Find URLs
  var link = body.findText(linkRegex);

  //Loop through the body finding texts matching the search pattern
  while (link != null) {
    // Get the link as an object
    var linkElement = link.getElement().asText();
    // Get the positions of start and end
    var start = link.getStartOffset();
    var end = link.getEndOffsetInclusive();
    //slice only the link out of it
    var correctLink = linkElement.getText().slice(start, end);

    // Format link
    linkElement.setLinkUrl(start, end, correctLink);
    // Find next
    link = body.findText(linkRegex, link);
  }
}

I'm sure this is simple, but I'm a complete novice and would appreciate any advice. Thanks in advance!

2 Answers

Your code is working for me

What do your original files look like?

function updateLinks() {
  var linkRegex = "https?:\/\/[^\\s]*";
  var body = DocumentApp.getActiveDocument().getBody();
  var link = body.findText(linkRegex);
  while (link != null) {
    var linkElement = link.getElement().asText();
    var start = link.getStartOffset();
    var end = link.getEndOffsetInclusive();
    var correctLink = linkElement.getText().slice(start, end);
    linkElement.setLinkUrl(start, end, correctLink);
    link = body.findText(linkRegex, link);
  }
}

I thought that the reason of your issue is due to slice(start, end) of linkElement.getText().slice(start, end). In this case, it is required to be slice(start, end + 1). So, please modify it as follows and test it again.

From:

var correctLink = linkElement.getText().slice(start, end);

To:

var correctLink = linkElement.getText().slice(start, end + 1);

Or, when you want to use linkRegex, how about the following modification?

var correctLink = linkElement.getText().match(new RegExp(linkRegex))[0];

Note:

  • As additional information, when the multiple URLs are included in a paragraph, I think that the following modification might be useful. Of course, in this modification, even when a single URL is included in a paragraph, the script works.

    • From

        var start = link.getStartOffset();
        var end = link.getEndOffsetInclusive();
        //slice only the link out of it
        var correctLink = linkElement.getText().slice(start, end);
      
        // Format link
        linkElement.setLinkUrl(start, end, correctLink);
      
    • To

        var text = linkElement.getText();
        var correctLinks = [...text.matchAll(new RegExp(linkRegex, "g"))];
        correctLinks.forEach(obj => linkElement.setLinkUrl(obj.index, obj.index + obj[0].length - 1, obj[0]));
      

Reference:

Related