Ovid
Ovid

Reputation: 11677

Replace text regex not matching and format applied over entire text

I have a Google Doc (only the type like Word, not spreadsheets or anything else) where I need to iterate over a series of rules (regular expressions) and style whatever matches the rules via an add on. The main body looks like this:

function showIssues() {
  var body = DocumentApp
             .getActiveDocument()
             .getBody();
  
  const rules = {
    fluff: {
      match: '\b(just|very)\b',
      color: '#FFDDDD'
    },
    adverbs: {
      match: '(\w+ly)\b',
      color: '#FF00FF'
    }
  };

  for (const [rule, definition] of Object.entries(rules)) {
    body.replaceText(definition.match, "<$1>")
        .asText()
        .setBackgroundColor(definition.color);
  }
}

However, not only does it not replace the matched text with <matched text>, but it also replaces the entire background, not just that of the replaced text.

I don't know Javascript well and I've never written a Google Docs add on before.

How do I match tiny snippets of text and set their attributes?

Unlike some other answers on this site, I'm not doing single replacements. Each rule might match against multiple elements in the document. Thus, I'm pretty sure I've messed this up :)

As an aside, some of these documents will be in the 100K word range, so they might be rather large.

Upvotes: 0

Views: 199

Answers (1)

Cooper
Cooper

Reputation: 64100

I changed your example a bit to match what I already had in a document.

Here's the code:

function showIssues() {
  var body = DocumentApp
             .getActiveDocument()
             .getBody();
  
  const rules = {
    one: {
      match: 'Recipe 1',
      color: '#00FF00'
    },
    two: {
      match: 'Recipe 2',
      color: '#FF0000'
    }
  };
  var style1={};
  style1[DocumentApp.Attribute.FOREGROUND_COLOR]='#ff0000';
  for (const [rule, definition] of Object.entries(rules)) {
    let re=body.findText(definition.match).getElement().asText().setAttributes(style1);
  }
}

Before:

enter image description here

After:

enter image description here

Update

I think this is a little closer to what you were attempting.

function showIssues() {
  var body = DocumentApp
             .getActiveDocument()
             .getBody();
  var style1={};
  var style2={};
  style1[DocumentApp.Attribute.FOREGROUND_COLOR]='#ff0000';
  style2[DocumentApp.Attribute.FOREGROUND_COLOR]='#00ff00';
  const rules = {
    one: {
      match: 'Recipe 1',
      color: style1
    },
    two: {
      match: 'Recipe 2',
      color: style2
    }
  };
  var style1={};
  
  for (const [rule, definition] of Object.entries(rules)) {
    let re=body.findText(definition.match).getElement().asText().setAttributes(definition.color);
  }
}

enter image description here

Upvotes: 1

Related Questions