Alexandre
Alexandre

Reputation: 55

How to search and replace a horizontal rule and linebreaks

I need to automatically delete all horizontal rules which are surrounded by 6 linebreaks (3 before and 3 after) on a google doc.

This piece of code seems to put in the logs the correct linebreaks I want to delete (that's a first step) :

function myFunction() {
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody().getText();
var pattern = /\s\s\s\s/g; 
  while (m=pattern.exec(body)) { Logger.log(m[0]); }
}

I have two questions :

Upvotes: 1

Views: 698

Answers (1)

Horizontal rule is an element inside a paragraph (or sometimes inside a list item). Since it is not text, it can not be found or replaced by means of a regular expression. We should search for objects which are specially arranged in the document body, and delete them if found.

Consider the following code example:

function deleteHR() {
  var body = DocumentApp.getActiveDocument().getBody();
  var hr = null, hrArray = [], countDeleted = 0;

  // Collect all horizontal rules in the Document
  while (true) {
    hr = body.findElement(DocumentApp.ElementType.HORIZONTAL_RULE, hr);
    if (hr == null) break;
    hrArray.push(hr);
  }

  hrArray.forEach(function(hr) {
    var p = hr.getElement().getParent();
    // Get empty paragraphs as siblings (if any)
    var prevSiblings = getSiblings(p, 3, true),
        nextSiblings = getSiblings(p, 3, false);
    // Define a short function for batch deleting items
    function remove(e) {
      e.removeFromParent();
    }
    // If empty paragraphs exist (3 before and 3 after)
    if (prevSiblings.length == 3 && nextSiblings.length == 3) {
      // then delete them as well as the rule itself
      hr.getElement().removeFromParent();
      prevSiblings.forEach(remove);
      nextSiblings.forEach(remove);
      countDeleted++;
    }
  });
  // Optional report
  Logger.log(countDeleted + ' rules deleted');
}


// Recursive search for empty paragraphs as siblings
function getSiblings(p, n, isPrevious) {
  if (n == 0) return [];
  if (isPrevious) {
    p = p.getPreviousSibling();
  } else {
    p = p.getNextSibling();
  }
  if (p == null) return [];
  if (p.getType() != DocumentApp.ElementType.PARAGRAPH) return [];
  if (p.asParagraph().getText().length > 0) return [];
  var siblings = getSiblings(p, n - 1, isPrevious);
  siblings.push(p);
  return siblings;
}

Main function deleteHR() does all the work. However it appears helpful to use another separate function getSiblings() for recursive search for empty paragraphs. May be, this way is not the only, but it works.

Upvotes: 2

Related Questions