I am trying to replace text, matching a specific regex, by a footnote with this text.
I know how to find each occurrence of the regex (thanks to some other post here)
I know how to create footnotes using API (thanks to the question here)
I guess, I even know how to put the text into the footnote section corresponding to the created footnote
But I need an index of the position in the text and my search (done by script, not by request) returns some abstract starting position in the "Element", which is not the index from the start of the document's body( which is what the api wants).
Where can I get the index?
function makeRef() {
var body = DocumentApp.getActiveDocument().getBody()
const documentId = DocumentApp.getActiveDocument().getId();
var myRegEx = '\\([a-z,A-Z]+?.+?,.+?[12][0-9][0-9][0-9]\\)'
var foundElement = body.findText(myRegEx);
while (foundElement != null) {
// Get the text object from the element
var foundText = foundElement.getElement().asText();
// Where in the Element is the found text?
var start = foundElement.getStartOffset();
var end = foundElement.getEndOffsetInclusive();
var requests = [
{
createFootnote: {
location: {
index: start
}
}
}]
Docs.Documents.batchUpdate({requests:requests},documentId)
// Find the next match
foundElement = body.findText(myRegEx, foundElement);
}
}
The problem is: how do I get the index of the place where I need the footnote?
I believe your goal is as follows.
Harry Potter is a magical child (Rowling, 1996)
to Harry Potter is a magical child^1
and you want to put ^1 Rowling, 1996
as a footnote.In this case, how about the following sample script?
I thought that it might be difficult to directly obtain the index for using Docs API from your showing script. In this case, in order to obtain the index, how about using Docs API? In your situation, how about the following sample script?
Please copy and paste the following script to the script editor of Google Document and enable Docs API at Advanced Google services. Ref
function myFunction() {
const myRegEx = '\\([a-z,A-Z]+?.+?,.+?[12][0-9][0-9][0-9]\\)'; // This is from your script.
// Retrieve the initial object from Google Document.
const documentId = DocumentApp.getActiveDocument().getId();
const obj1 = Docs.Documents.get(documentId).body.content;
// Retrieving texts and creating footnotes.
const r = new RegExp(myRegEx, "g");
const { requests1, texts } = obj1.reduce((o, e) => {
if (e.paragraph) {
e.paragraph.elements.forEach(f => {
if (f.textRun) {
const m = [...f.textRun.content.matchAll(r)];
if (m.length > 0) {
m.forEach(c => {
o.texts.push(c[0]);
o.requests1.push({ createFootnote: { location: { index: f.startIndex + c.index - 1 } } });
o.requests1.push({ deleteContentRange: { range: { startIndex: f.startIndex + c.index, endIndex: f.startIndex + c.index + c[0].length } } });
});
}
}
});
}
return o;
}, { requests1: [], texts: [] });
const { replies } = Docs.Documents.batchUpdate({ requests: requests1.reverse() }, documentId);
const footnoteIds = replies.reduce((ar, e) => {
if (e && e.createFootnote && e.createFootnote.footnoteId) {
ar.push(e.createFootnote.footnoteId)
}
return ar;
}, []).reverse();
// Retrieve the object after footnotes were created.
const { footnotes } = Docs.Documents.get(documentId);
// Inserting texts to footnotes.
const requests2 = footnoteIds.reduce((ar, id, i) => {
const o = footnotes[id]
if (o) {
ar.push({ insertText: { location: { segmentId: id, index: o.content[0].endIndex - 1 }, text: texts[i].replace(/\(|\)/g, "") } });
}
return ar;
}, []);
Docs.Documents.batchUpdate({ requests: requests2 }, documentId);
}
When this script is run to your provided sample Google Document, the following result is obtained.