#targetengine "session" function main() { // Guard if (app.documents.length === 0) { alert("No open document."); return; } var doc = app.activeDocument; var objectStyleName = "mh"; // ---- Helpers ---------------------------------------------------------- // Find the Object Style named "mh" (searches through groups as well) function findObjectStyleByName(d, styleName) { function collect(root, out) { var i, g; for (i = 0; i < root.objectStyles.length; i++) out.push(root.objectStyles[i]); for (g = 0; g < root.objectStyleGroups.length; g++) collect(root.objectStyleGroups[g], out); } var all = []; collect(d, all); for (var s = 0; s < all.length; s++) { if (all[s].name === styleName) return all[s]; } return null; } var objectStyle = findObjectStyleByName(doc, objectStyleName); if (!objectStyle) { alert("Object style '" + objectStyleName + "' not found."); return; } // Build a list of all text frames (to collect unique stories reliably) var allTextFrames = []; for (var i = 0; i < doc.textFrames.length; i++) { allTextFrames.push(doc.textFrames[i]); } // Collect unique parentStory objects var stories = []; for (var k = 0; k < allTextFrames.length; k++) { var st = allTextFrames[k].parentStory; var exists = false; for (var j = 0; j < stories.length; j++) { if (stories[j] === st) { exists = true; break; } } if (!exists) stories.push(st); } // ---- Main loop -------------------------------------------------------- for (var s = 0; s < stories.length; s++) { var story = stories[s]; var frames = story.textContainers; if (frames.length < 2) continue; for (var f = 0; f < frames.length - 1; f++) { var thisFrame = frames[f]; var nextFrame = frames[f + 1]; // First word in NEXT frame (avoid indexOf/trim; ExtendScript-safe) var nextText = nextFrame.contents; var firstWord = ""; for (var c = 0; c < nextText.length; c++) { var ch = nextText.charAt(c); if (ch === " " || ch === "\r" || ch === "\n" || ch === "\t") { break; } firstWord += ch; } if (firstWord.length === 0) continue; // ===== Create and align the small inserted frame ===== // Use SAME parent container (Page or Spread) to avoid origin mismatch var parentContainer = thisFrame.parent; if (!parentContainer) continue; // Dimensions of the small note frame var newW = 40; var newH = 15; // Align left edge to the **visible** left of the source (accounts for stroke) // and place it 1 pt below the **geometric** bottom var vb = thisFrame.visibleBounds; // [y1, x1, y2, x2] var gb = thisFrame.geometricBounds; // [y1, x1, y2, x2] var srcVisLeft = vb[1]; var newY = gb[2] + 1; // Create with zero stroke first to avoid initial visual shift var insertedFrame = parentContainer.textFrames.add({ geometricBounds: [newY, srcVisLeft, newY + newH, srcVisLeft + newW] }); try { insertedFrame.strokeWeight = 0; } catch (_se) {} // Mirror rotation/shear if any try { insertedFrame.rotationAngle = thisFrame.rotationAngle; insertedFrame.shearAngle = thisFrame.shearAngle; } catch (_tx) {} // Insert content var firstWordText = "First word in next textFrame is : " + "'" + firstWord + "'"; insertedFrame.contents = firstWordText; // Apply the object style insertedFrame.appliedObjectStyle = objectStyle; // After style application, re-align visible left edge EXACTLY to source try { var visLeftNow = insertedFrame.visibleBounds[1]; // current visible left var dx = visLeftNow - srcVisLeft; if (dx !== 0) { var b = insertedFrame.geometricBounds; // [y1, x1, y2, x2] b[1] -= dx; // shift x1 b[3] -= dx; // shift x2 insertedFrame.geometricBounds = b; } } catch (_realignErr) {} // ===== end create/align ===== } } } // Wrap for single undo step app.doScript( main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Insert First Word from Next Text Frame - Style 'mh'" );