Learning in public — this reference is being written in the open. Unfinished pages are excluded from search engines.
paged.IDML Reference
Scripting (paged.*)

Scripting with paged.*

The Boa-based scripting layer — a sandboxed ECMAScript surface for reading and authoring a paged document through the paged.* host API. The full surface is generated from the engine catalog.

Tier: IntermediateIntermediateIIexplanation

In short paged embeds a Boa ECMAScript engine and exposes a single global, paged.*, for inspecting and editing the open document. The same surface runs in the editor's script panel/REPL and headless via the paged-run CLI. This reference is generated from the engine's own catalog, so it always matches the running engine exactly.

How a script becomes pixels

scriptpaged.* sourceBoa sandboxbudgeted ECMAScriptOperation channelone undoable logapplyrebuild listrenderrepaintpaged.undo() / redo()budgets: 10M loops · depth 512 · ~2s

Your script. Plain ECMAScript calling paged.* — no modules, no I/O.

A paged.* script runs in a sandboxed Boa engine; every write flows through the same Operation channel as the UI, so it re-renders live and is fully undoable.

The shape of a script

A script is plain ECMAScript (no modules, no I/O — see constraints). It addresses elements by id, reads with paged.inspect / paged.get, and edits with paged.set and the structural authoring functions. Every property write returns a boolean so a script can branch on success.

Reads return JSON strings — parse them. paged.selection(), paged.tree(), paged.stories() and every other read return a JSON string, not a live value. Call JSON.parse(...) before you index into the result. The parsed elements are { kind, id } objects; address one as the string `${kind}:${id}` (e.g. textFrame:u3) when you pass it to paged.set / paged.inspect.

// Reads return JSON strings — parse them.
const [el] = JSON.parse(paged.selection());
if (el) {
  const ref = `${el.kind}:${el.id}`;            // e.g. "textFrame:u3"
  paged.set(ref, "frameFillColor", "Color/Red"); // a real settable path
  paged.set(ref, "frameRotationAngle", 12);      // rotate 12°
}

Try it

Edit the script and press Run — it executes in the real Paged editor on the right, and the canvas updates live. Console output appears below.

A first paged.* script — read the selection, then fill the frame red
Open ↗paged.* · seed: one-text-frame-selected
Loading editor…
Look for: The text frame on the page turns red and rotates 12°.
Console
Run a script to see console output here.

The playground runs against play.paged.media. It needs that app deployed with the editable-script bridge and a cross-origin-isolated (COOP/COEP) page — both are wired here; see constraints for the sandbox model.

What's here

  • Host functionsevery paged.* function, grouped by kind (read, write, author, history, console).
  • Settable pathsthe property names you can pass to paged.set, plus the id grammar for addressing elements.
  • Constraintsthe sandbox rules and execution budgets.
  • textFrame:<id> e.g. textFrame:u123A text frame. Same scheme: rectangle:/oval:/polygon:/graphicLine:/group:.
  • group:<id> e.g. group:u88A group. `paged.set("group:<id>", "groupTransform", [a,b,c,d,tx,ty])` moves it as a unit.
  • storyRange:<storyId>@<start>..<end> e.g. storyRange:Story/u1@0..6A character range within a story (half-open). storyId comes from paged.stories()[].selfId.

On this page