I discovered today that the Footnote object provides —from the mists of time— a convertToText method, which “converts the footnote to part of the story text and places the converted text at the former location of the footnote marker in the text.” This is a strange thing, because I don't know where to access this Convert footnote to text feature from the user interface. (Maybe a future “obscure feature of the week-eek-eek” on InDesignSecrets podcast.)

The fact is that InDesign JavaScript can easily reinject a footnote into its parent story, at the exact place of the footnote reference number. It is pretty useful for writers or layout designers who want to readjust the contents coming from Word or RTF documents. It is also useful for convert/export/XML purposes. Note that, if you need to convert footnotes to endnotes, Peter Kahrel's “foot_to_end” script will be your friend. The famous Bob Bringhurst's “Endnotes in InDesign CS4” explains the trick.

For the present, here is a small script —UnFoot.js— allowing the user to reinject the footnotes into the text. It improves the Footnote.convertToText method in some ways. On the one hand, the reinjected text is embedded in a pair of opening/closing customizable markers (tweak the line UNFOOT_MARKS = ["<",">"];). On the other hand, the script can work on multiple footnotes at one go, according to the context: if nothing is selected in the active document, all the footnotes are converted. To target the footnotes of a specific story, select a textframe or leave the insertion point within. To convert a single footnote, put the insertion point inside the text of the note itself.

var UNFOOT_MARKS = ["<",">"];
 
/*arr*/ Object.prototype.getFootnotes = function()
//----------------------------------------------------------
{
if ( this.constructor.name == 'Footnote' )
    return([this]);
if ( 'footnotes' in this )
    return(this.footnotes.everyItem().getElements());
if ( 'stories' in this )
    return(this.stories.everyItem().
    footnotes.everyItem().getElements());
return([]);
}
 
/*void*/    Footnote.prototype.unFoot = function()
//----------------------------------------------------------
{
var txt = this.convertToText();
var p = txt.parent;
var iEnd = txt.insertionPoints.item(-1).index +
    UNFOOT_MARKS[0].length;
txt.insertionPoints.item(0).contents = UNFOOT_MARKS[0];
p.insertionPoints.item(iEnd).contents = UNFOOT_MARKS[1];
}
 
/*void*/    Application.prototype.main = function()
//----------------------------------------------------------
{
if ( this.documents.length <= 0 ) return;
var tg = this.selection[0] || this.activeDocument;
 
if ( 'appliedFont' in tg ) tg = tg.parent;
tg = tg.getFootnotes();
 
for ( var i = tg.length-1 ; i>=0 ; i-- )
    {
    tg[i].unFoot();
    }
}
 
app.doScript('app.main();', ScriptLanguage.javascript,
undefined, UndoModes.entireScript, app.activeScript.displayName);
 

As you may have noticed, the last instruction runs the app.main() procedure undirectly, using the doScript method. This way, we send the UndoModes.entireScript argument to the interpreter, making the whole script action undoable.

• See also: ReFoot.js.