如何修改InDesign脚本识别LaTeX格式的\footnote{}脚注?
LaTeX脚注转InDesign自动格式化脚本问题
我需要将LaTeX编写的文本在InDesign中格式化,主文本内的脚注均以\footnote{}标签包裹,示例文本如下:
This is my main text\footnote{with foonotes and sometimes with other braces inside footnotes such as\ref{section2}}, and I want to format it properly.
脚注数量多达数百个,希望通过脚本实现自动格式化,目前使用的脚本无法适配该格式,请问遗漏了什么?原脚本如下:
Application.prototype.main = function(){ if (this.documents.length <= 0) return; var tg = this.selection[0] || this.activeDocument; if ('appliedFont' in tg) tg = tg.parent; if (tg.constructor == TextFrame) { tg = tg.parentStory; } if (!('findGrep' in tg)) return; /* Here it is neecessary to choose a pattern for wrapping the note, we are not parsing here, hence the rough technique! */ var fnPatterns = ["(\\\\footnote\\{)([^\\}]+)(\\})"]; var count = 0; for(patterCounter = 0; patterCounter < fnPatterns.length; patterCounter++){ fnPattern = fnPatterns[patterCounter]; var fnFinds = (function(){ this.findGrepPreferences = this.changeGrepPreferences = null; this.findGrepPreferences.findWhat = fnPattern; var ret = tg.findGrep(); this.findGrepPreferences = this.changeGrepPreferences = null; return ret; }).call(this); var fnFind, fnPrefix,fnSuffix, rg = new RegExp(fnPattern), ip, fnParent, fn, count; while (fnFind = fnFinds.pop()){ fnPrefix = fnFind.contents.match(/^@[^@]+@/)[0]; fnSuffix = fnFind.contents.match(/@[^@]+@/)[0]; try { // add footnote fn = fnFind.footnotes.add(LocationOptions.AFTER, fnFind.insertionPoints[-1]); // duplicate the text fnFind.texts[0].characters.itemByRange(fnPrefix.length,fnFind.texts[0].characters.length-fnSuffix.length-1).duplicate(LocationOptions.AT_END, fn.texts[0]); // remove the original fnFind.characters.itemByRange(0,fnFind.characters.length-2).remove(); ++count; } catch(_){} } } alert((count)? (count+" footnote(s) successfully added."): "No footnote added. Make sure you use the relevant pattern."); } app.doScript('app.main();', ScriptLanguage.javascript, undefined, UndoModes.entireScript, app.activeScript.displayName);
原脚本的核心问题
正则无法处理嵌套大括号
原脚本的Grep模式(\\\\footnote\\{)([^\\}]+)(\\})中,[^\\}]+会在遇到第一个}时停止匹配,完全无法处理脚注内部嵌套的大括号(比如示例中的\ref{section2}),导致脚注内容截取不完整。错误的前缀/后缀匹配逻辑
脚本里的@[^@]+@匹配规则是针对用@包裹脚注的格式设计的,和\footnote{}的结构完全不兼容,这会直接触发匹配失败,脚注无法创建。文本处理逻辑错位
基于错误的前缀后缀匹配,后续的文本截取、复制、删除逻辑全部不适用于\footnote{}的结构,要么破坏原文本,要么无法正确提取脚注内容。
修正后的脚本
Application.prototype.main = function(){ if (this.documents.length <= 0) return; var tg = this.selection[0] || this.activeDocument; if ('appliedFont' in tg) tg = tg.parent; if (tg.constructor == TextFrame) { tg = tg.parentStory; } if (!('findGrep' in tg)) return; // 适配嵌套大括号的Grep模式:完整匹配\footnote{...},支持内部嵌套{} var fnPatterns = ["(\\\\footnote\\{)([^}]*+(?:\\{[^}]*+\\}[^}]*)*+)(\\})"]; var count = 0; for(let patterCounter = 0; patterCounter < fnPatterns.length; patterCounter++){ const fnPattern = fnPatterns[patterCounter]; const fnFinds = (function(){ this.findGrepPreferences = this.changeGrepPreferences = null; this.findGrepPreferences.findWhat = fnPattern; const ret = tg.findGrep(); this.findGrepPreferences = this.changeGrepPreferences = null; return ret; }).call(this); let fnFind, fn, match; const regex = new RegExp(fnPattern); while (fnFind = fnFinds.pop()){ match = fnFind.contents.match(regex); if (!match || match.length < 3) continue; try { // 在匹配文本末尾添加脚注 fn = fnFind.footnotes.add(LocationOptions.AFTER, fnFind.insertionPoints[-1]); // 将脚注内部内容(正则匹配组2)复制到新脚注 fn.contents = match[2]; // 删除原有的\footnote{...}文本 fnFind.remove(); ++count; } catch(err){ // 捕获单个脚注的处理错误,避免脚本中断 console.log(`处理脚注失败: ${err.message}`); } } } alert(count ? `${count} 个脚注已成功添加。` : "未添加任何脚注,请检查格式是否匹配。"); } app.doScript('app.main();', ScriptLanguage.javascript, undefined, UndoModes.entireScript, app.activeScript.displayName);
关键修改说明
- 嵌套大括号适配:使用的Grep模式能完整匹配包含多层嵌套
{}的脚注内容,确保脚注内部的LaTeX命令不会中断匹配。 - 移除无效匹配逻辑:直接通过正则捕获组提取
\footnote{}内部的文本,不再依赖错误的@前缀后缀规则。 - 简化处理流程:直接设置脚注内容并删除原标记,逻辑更清晰可靠,减少文本操作出错的概率。
- 错误日志优化:添加错误捕获并输出日志,方便排查单个脚注的处理问题。
内容的提问来源于stack exchange,提问作者Sulli
相关产品推荐
相关产品推荐

