← WebMCP Directory

Tool tree

postext.dev

Developer ToolsTools verified
Website
Try the Postext typesetting engine live: edit markdown, manage figures and tables, tune Knuth-Plass justification, and export print-ready PDF and EPUB — in the browser.
Explore capabilities
    sandbox_get_stateAnswer

    The book open in the Postext Sandbox and how it is shown: its chapters with their page ranges, the chapter and page on screen, the viewer tab and its display settings, the open side panel, the interface language, the selection (or the caret) of the Manuscript editor, the resource open in the Resources panel, how many warnings the layout has, and the change sandbox_undo would take back and the one it would put back (history). What needs attention is added when there is any: waitingFor (why ready is false), notice (the Books panel's message, cleared with sandbox_answer), status (an operation on the books that is busy or failed), sampleUpdated (the sample on screen was reloaded because its source changed), sampleStale (its source changed but the reader's edits were kept; sandbox_reset_to_original loads the new version) and question (a dialog asking the reader something, answered with sandbox_answer). Start here, and call it again to see where things stand.

    View tool JSON
    {
      "name": "sandbox_get_state",
      "kind": "answer",
      "impl": "imperative",
      "description": "The book open in the Postext Sandbox and how it is shown: its chapters with their page ranges, the chapter and page on screen, the viewer tab and its display settings, the open side panel, the interface language, the selection (or the caret) of the Manuscript editor, the resource open in the Resources panel, how many warnings the layout has, and the change sandbox_undo would take back and the one it would put back (history). What needs attention is added when there is any: waitingFor (why ready is false), notice (the Books panel's message, cleared with sandbox_answer), status (an operation on the books that is busy or failed), sampleUpdated (the sample on screen was reloaded because its source changed), sampleStale (its source changed but the reader's edits were kept; sandbox_reset_to_original loads the new version) and question (a dialog asking the reader something, answered with sandbox_answer). Start here, and call it again to see where things stand.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_render_pageAction

    A picture of a page of the book as it is laid out now — the way to see the effect of a change. It waits for the layout to follow the last change, so it can be called right after one. Without a page it gives the one on screen; count gives the pages after it too (2 for a spread). crop magnifies a part of the page for a close look at type and spacing. The picture shows what the settings draw on the page (baseline grid, crop marks), not the caret or the selection. The result is a list of content parts: a JSON text describing each page, then one image per page.

    View tool JSON
    {
      "name": "sandbox_render_page",
      "kind": "act",
      "impl": "imperative",
      "description": "A picture of a page of the book as it is laid out now — the way to see the effect of a change. It waits for the layout to follow the last change, so it can be called right after one. Without a page it gives the one on screen; count gives the pages after it too (2 for a spread). crop magnifies a part of the page for a close look at type and spacing. The picture shows what the settings draw on the page (baseline grid, crop marks), not the caret or the selection. The result is a list of content parts: a JSON text describing each page, then one image per page.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter: its position in the book (from 1), its title or its id. The chapter the reader is at when left out."
          },
          "page": {
            "type": "integer",
            "description": "The page number as printed on the page and shown in the viewer's page field."
          },
          "position": {
            "type": "integer",
            "minimum": 1,
            "description": "The page by its position among the chapter's pages (from 1)."
          },
          "count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 6,
            "description": "How many consecutive pages, from that one (default 1, at most 6)."
          },
          "width": {
            "type": "integer",
            "minimum": 160,
            "maximum": 2400,
            "description": "Width of each picture in pixels (default 900). A crop is given at this width too, so it shows more detail."
          },
          "format": {
            "type": "string",
            "enum": [
              "jpeg",
              "png",
              "webp"
            ],
            "description": "Default jpeg."
          },
          "quality": {
            "type": "number",
            "minimum": 0.3,
            "maximum": 1,
            "description": "JPEG or WebP quality (default 0.82)."
          },
          "crop": {
            "type": "object",
            "description": "A part of the page, as fractions of its width and height from the top left corner: { x: 0, y: 0, width: 1, height: 0.5 } is the top half.",
            "properties": {
              "x": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "y": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "width": {
                "type": "number",
                "minimum": 0.02,
                "maximum": 1
              },
              "height": {
                "type": "number",
                "minimum": 0.02,
                "maximum": 1
              }
            },
            "required": [
              "x",
              "y",
              "width",
              "height"
            ],
            "additionalProperties": false
          },
          "trimmed": {
            "type": "boolean",
            "description": "Leave out the margin with the bleed and crop marks, when the layout has cut lines."
          },
          "printPreview": {
            "type": "boolean",
            "description": "Paint the soft proof of the print output profile, with the trim, bleed and safe-zone guides and the preflight marks."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_inspect_pagesAction

    What the layout engine put on the pages of a chapter, as data. Without a page: one line per page of the chapter (its number, whether it is blank, how many lines and figures, how it starts) — the map to pick pages from. With a page: every block on it with its text, column, number of lines, hyphenated lines, loose justified lines and how wide their spaces are, where it sits on the page, plus how full each column is; on a composed page, its template and what the layout moved, grew or scaled so the content fits ("dinero grew 8.2 mm", "gasto moved down 8.2 mm"). It waits for the layout to follow the last change.

    View tool JSON
    {
      "name": "sandbox_inspect_pages",
      "kind": "act",
      "impl": "imperative",
      "description": "What the layout engine put on the pages of a chapter, as data. Without a page: one line per page of the chapter (its number, whether it is blank, how many lines and figures, how it starts) — the map to pick pages from. With a page: every block on it with its text, column, number of lines, hyphenated lines, loose justified lines and how wide their spaces are, where it sits on the page, plus how full each column is; on a composed page, its template and what the layout moved, grew or scaled so the content fits (\"dinero grew 8.2 mm\", \"gasto moved down 8.2 mm\"). It waits for the layout to follow the last change.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter: its position in the book (from 1), its title or its id. The chapter the reader is at when left out."
          },
          "page": {
            "type": "integer",
            "description": "The page number as printed on the page."
          },
          "position": {
            "type": "integer",
            "minimum": 1,
            "description": "The page by its position among the chapter's pages (from 1)."
          },
          "count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 12,
            "description": "How many consecutive pages to detail, from that one (default 1)."
          },
          "textLength": {
            "type": "integer",
            "minimum": 0,
            "maximum": 4000,
            "description": "Characters of each block's text to give (default 240)."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_inspect_pointAction

    What lies at a point of a page and what a click there does in the Canvas: the block, the place in the chapter's Markdown source (line, column, offset and the word there), a link and the page it leads to (a :ref, a footnote marker, an index page number, a row of the contents) or its URL, the resource (a table cell, a caption, a note, a text of an SVG figure, a picture a design draws, a comic panel's art) and the part of a comic. x and y are fractions of the page from its top left corner, the space of sandbox_render_page's crop, so a spot seen in a picture can be asked about (pass trimmed as it was passed there). select also does what the click does short of following a link: it opens the Manuscript panel with the caret there (word: the word there selected, as a double click; to: a selection dragged to a second point), or the Resources panel on the resource, with the caret in its text. elements lists what lies at the point, innermost first, as a click picks it and each further click or Esc climbs (a glyph, its paragraph, the box round it, the frame of a composed page, its group, the page and its template; or a design element and its slot), each with its stable id, its source (Markdown range, config path, attribute, resource) and its name in the path the Sandbox shows (path); select with level picks one of them. sandbox_inspect_pages lists every block of a page; sandbox_go_to_page with anchor goes where a link leads.

    View tool JSON
    {
      "name": "sandbox_inspect_point",
      "kind": "act",
      "impl": "imperative",
      "description": "What lies at a point of a page and what a click there does in the Canvas: the block, the place in the chapter's Markdown source (line, column, offset and the word there), a link and the page it leads to (a :ref, a footnote marker, an index page number, a row of the contents) or its URL, the resource (a table cell, a caption, a note, a text of an SVG figure, a picture a design draws, a comic panel's art) and the part of a comic. x and y are fractions of the page from its top left corner, the space of sandbox_render_page's crop, so a spot seen in a picture can be asked about (pass trimmed as it was passed there). select also does what the click does short of following a link: it opens the Manuscript panel with the caret there (word: the word there selected, as a double click; to: a selection dragged to a second point), or the Resources panel on the resource, with the caret in its text. elements lists what lies at the point, innermost first, as a click picks it and each further click or Esc climbs (a glyph, its paragraph, the box round it, the frame of a composed page, its group, the page and its template; or a design element and its slot), each with its stable id, its source (Markdown range, config path, attribute, resource) and its name in the path the Sandbox shows (path); select with level picks one of them. sandbox_inspect_pages lists every block of a page; sandbox_go_to_page with anchor goes where a link leads.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter: its position in the book (from 1), its title or its id. The chapter the reader is at when left out."
          },
          "page": {
            "type": "integer",
            "description": "The page number as printed on the page."
          },
          "position": {
            "type": "integer",
            "minimum": 1,
            "description": "The page by its position among the chapter's pages (from 1). The page on screen when neither is given."
          },
          "x": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "Across the page, from its left edge (0) to its right edge (1)."
          },
          "y": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "Down the page, from its top edge (0) to its bottom edge (1)."
          },
          "trimmed": {
            "type": "boolean",
            "description": "x and y are fractions of the page without its margin of bleed and crop marks, as in a picture rendered with trimmed."
          },
          "select": {
            "type": "boolean",
            "description": "Also put the caret (or the selection) there in the Manuscript panel, or open the resource in the Resources panel."
          },
          "word": {
            "type": "boolean",
            "description": "With select: select the word at the point, as a double click does."
          },
          "level": {
            "type": "string",
            "enum": [
              "text",
              "attr",
              "label",
              "resource",
              "block",
              "box",
              "frame",
              "group",
              "design",
              "slot",
              "template"
            ],
            "description": "With select: pick the element of that level at the point (the path lists them), as clicking again on the spot or pressing Esc climbs to it: block the paragraph, frame the frame of a composed page, template the page and its template, design an element of a running head, a folio or the decoration. Content mode then selects its Markdown; Design mode opens its frame, style or template; a design element opens its settings in either mode."
          },
          "to": {
            "type": "object",
            "description": "With select: a second point of the same page; the text from the first point to this one is selected, as a drag does.",
            "properties": {
              "x": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "y": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              }
            },
            "required": [
              "x",
              "y"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "x",
          "y"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_read_textAction

    A chapter's Markdown source, each line behind its number. Postext's Markdown has its own extensions (directives such as ::resource, :ref, :::callout, front matter on the first chapter): the format is documented at /docs/document-format. Long chapters can be read in parts with fromLine and toLine.

    View tool JSON
    {
      "name": "sandbox_read_text",
      "kind": "act",
      "impl": "imperative",
      "description": "A chapter's Markdown source, each line behind its number. Postext's Markdown has its own extensions (directives such as ::resource, :ref, :::callout, front matter on the first chapter): the format is documented at /docs/document-format. Long chapters can be read in parts with fromLine and toLine.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter: its position in the book (from 1), its title or its id. The chapter on screen when left out."
          },
          "fromLine": {
            "type": "integer",
            "minimum": 1,
            "description": "First line to read (from 1)."
          },
          "toLine": {
            "type": "integer",
            "minimum": 1,
            "description": "Last line to read, inclusive."
          },
          "plain": {
            "type": "boolean",
            "description": "Give the text as it is, without line numbers."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_write_textAction

    Replace a chapter's whole Markdown source with new text, given here (markdown) or read from a Markdown file (file, as the Manuscript panel's import does). For a change to part of a chapter, sandbox_edit_text keeps the rest untouched; a Word document goes through sandbox_import_word. The text it replaces comes back with sandbox_undo_text.

    View tool JSON
    {
      "name": "sandbox_write_text",
      "kind": "act",
      "impl": "imperative",
      "description": "Replace a chapter's whole Markdown source with new text, given here (markdown) or read from a Markdown file (file, as the Manuscript panel's import does). For a change to part of a chapter, sandbox_edit_text keeps the rest untouched; a Word document goes through sandbox_import_word. The text it replaces comes back with sandbox_undo_text.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter: its position in the book (from 1), its title or its id. The chapter on screen when left out."
          },
          "markdown": {
            "type": "string",
            "description": "The chapter's new Markdown source. Give this or file, not both."
          },
          "file": {
            "type": "object",
            "description": "A Markdown file (.md) whose text becomes the chapter's source: where to fetch it (url) or its bytes (base64). Give this or markdown, not both.",
            "properties": {
              "url": {
                "type": "string",
                "description": "An http(s) or data: URL the page can fetch."
              },
              "base64": {
                "type": "string",
                "description": "The bytes, base64-encoded."
              },
              "mimeType": {
                "type": "string",
                "description": "Its media type. Read from the response or the file name when left out."
              },
              "fileName": {
                "type": "string",
                "description": "Its file name, with its extension."
              }
            },
            "additionalProperties": false
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again and answer with the pages each chapter came to (default true). False answers at once."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_edit_textAction

    Change passages of a chapter's Markdown source: each edit finds an exact passage and puts another in its place. The passage must match the source exactly and occur once (or set all to change every occurrence). Edits apply in order. Nothing is changed unless every edit applies. The call is one step for sandbox_undo_text, which takes it back whole.

    View tool JSON
    {
      "name": "sandbox_edit_text",
      "kind": "act",
      "impl": "imperative",
      "description": "Change passages of a chapter's Markdown source: each edit finds an exact passage and puts another in its place. The passage must match the source exactly and occur once (or set all to change every occurrence). Edits apply in order. Nothing is changed unless every edit applies. The call is one step for sandbox_undo_text, which takes it back whole.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter: its position in the book (from 1), its title or its id. The chapter on screen when left out."
          },
          "edits": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "properties": {
                "find": {
                  "type": "string",
                  "description": "The exact text to replace, as it is in the source."
                },
                "replace": {
                  "type": "string",
                  "description": "The text that takes its place (empty to delete)."
                },
                "all": {
                  "type": "boolean",
                  "description": "Replace every occurrence."
                }
              },
              "required": [
                "find",
                "replace"
              ],
              "additionalProperties": false
            }
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again and answer with the pages each chapter came to (default true). False answers at once."
          }
        },
        "required": [
          "edits"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_undo_textAction

    Take back the last change when it is an edit to a chapter's text, or with redo put back the last one taken back. The Sandbox keeps one history of text and design, in the order the changes were made (the one Cmd/Ctrl+Z undoes): text typed in the Manuscript editor, the edits the reader made on the previews (a comic panel resized, a frame's text), and what sandbox_write_text, sandbox_edit_text and sandbox_import_word (into a chapter) changed, one call at a time, latest first whatever the chapter. When the last change was to the design it is refused, with the settings it touched: sandbox_undo takes back the last change whatever it is. Chapters added, removed, split, merged or moved, resources and fonts are not in the history, and opening another book empties it. An edit is taken back over the changes made to the chapter since by other means, which stay. The history is kept for this visit: it is empty after the page is reloaded.

    View tool JSON
    {
      "name": "sandbox_undo_text",
      "kind": "act",
      "impl": "imperative",
      "description": "Take back the last change when it is an edit to a chapter's text, or with redo put back the last one taken back. The Sandbox keeps one history of text and design, in the order the changes were made (the one Cmd/Ctrl+Z undoes): text typed in the Manuscript editor, the edits the reader made on the previews (a comic panel resized, a frame's text), and what sandbox_write_text, sandbox_edit_text and sandbox_import_word (into a chapter) changed, one call at a time, latest first whatever the chapter. When the last change was to the design it is refused, with the settings it touched: sandbox_undo takes back the last change whatever it is. Chapters added, removed, split, merged or moved, resources and fonts are not in the history, and opening another book empties it. An edit is taken back over the changes made to the chapter since by other means, which stay. The history is kept for this visit: it is empty after the page is reloaded.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "redo": {
            "type": "boolean",
            "description": "Put back the last edit taken back, instead of taking one back."
          },
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "Only when the edit is to this chapter (position from 1, title or id): an edit to another one is refused, with where it is. Whatever chapter when left out."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again and answer with the pages each chapter came to (default true). False answers at once."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_select_textAction

    Place the caret of the Manuscript editor, or select a stretch of a chapter's source, as a click on a finding of the Checks panel does: the chapter is shown, the Manuscript panel opened, and the editor scrolls to the place and takes the keyboard. Say where with one of: text (an exact passage, selected), line (the caret at its start; with toLine, those lines selected whole) or offset (a caret; with toOffset, a selection). Answers with the selection or the caret as sandbox_get_state reports it. To show a printed page instead, sandbox_go_to_page; to change the text, sandbox_edit_text.

    View tool JSON
    {
      "name": "sandbox_select_text",
      "kind": "act",
      "impl": "imperative",
      "description": "Place the caret of the Manuscript editor, or select a stretch of a chapter's source, as a click on a finding of the Checks panel does: the chapter is shown, the Manuscript panel opened, and the editor scrolls to the place and takes the keyboard. Say where with one of: text (an exact passage, selected), line (the caret at its start; with toLine, those lines selected whole) or offset (a caret; with toOffset, a selection). Answers with the selection or the caret as sandbox_get_state reports it. To show a printed page instead, sandbox_go_to_page; to change the text, sandbox_edit_text.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter: its position in the book (from 1), its title or its id. The chapter on screen when left out."
          },
          "text": {
            "type": "string",
            "description": "An exact passage of the source to select. It must occur once in the chapter, unless occurrence says which."
          },
          "occurrence": {
            "type": "integer",
            "minimum": 1,
            "description": "text: which occurrence of the passage (from 1), when it occurs more than once."
          },
          "line": {
            "type": "integer",
            "minimum": 1,
            "description": "A line of the source (from 1, as sandbox_read_text numbers them): the caret goes to its start."
          },
          "toLine": {
            "type": "integer",
            "minimum": 1,
            "description": "line: select from that line to this one, both whole."
          },
          "offset": {
            "type": "integer",
            "minimum": 0,
            "description": "A place in the source counted in characters from its start: the caret goes there."
          },
          "toOffset": {
            "type": "integer",
            "minimum": 0,
            "description": "offset: select from that offset up to this one."
          },
          "openPanel": {
            "type": "boolean",
            "description": "Open the Manuscript panel so the editor shows the place (default true). False leaves the side panel as it is: the caret is then placed when the panel is next opened."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_search_textAction

    Where a word or passage occurs in the Markdown source: the chapter, the line and the line itself, and, with pages set, the page each occurrence is set on (the chapters that hold one are laid out for it).

    View tool JSON
    {
      "name": "sandbox_search_text",
      "kind": "act",
      "impl": "imperative",
      "description": "Where a word or passage occurs in the Markdown source: the chapter, the line and the line itself, and, with pages set, the page each occurrence is set on (the chapters that hold one are laid out for it).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "description": "The text to look for."
          },
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "Search this chapter only (position from 1, title or id). Every chapter when left out."
          },
          "matchCase": {
            "type": "boolean"
          },
          "pages": {
            "type": "boolean",
            "description": "Also say which page each occurrence is set on."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 200,
            "description": "Most occurrences to list (default 40)."
          }
        },
        "required": [
          "query"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_manage_chaptersAction

    Add a chapter, rename one, move one to another position, split one in two (at a passage, or at every level-1 heading), merge one into the chapter before it, or show one on screen. A chapter's title is its name in the interface, not text of the book.

    View tool JSON
    {
      "name": "sandbox_manage_chapters",
      "kind": "act",
      "impl": "imperative",
      "description": "Add a chapter, rename one, move one to another position, split one in two (at a passage, or at every level-1 heading), merge one into the chapter before it, or show one on screen. A chapter's title is its name in the interface, not text of the book.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "add",
              "rename",
              "move",
              "split",
              "split_at_headings",
              "merge_with_previous",
              "show"
            ]
          },
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter: its position in the book (from 1), its title or its id. The chapter on screen when left out."
          },
          "title": {
            "type": "string",
            "description": "add, rename: the title."
          },
          "markdown": {
            "type": "string",
            "description": "add: the new chapter's Markdown source."
          },
          "position": {
            "type": "integer",
            "minimum": 1,
            "description": "add, move: where in the book (from 1). add puts the chapter after the one on screen when left out."
          },
          "before": {
            "type": "string",
            "description": "split: the exact passage the second chapter starts with; it must occur once in the chapter."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again and answer with the pages each chapter came to (default true). False answers at once."
          }
        },
        "required": [
          "action"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_remove_chapterAction

    Delete a chapter and its text from the book. It cannot be undone; a book keeps at least one chapter.

    View tool JSON
    {
      "name": "sandbox_remove_chapter",
      "kind": "act",
      "impl": "imperative",
      "description": "Delete a chapter and its text from the book. It cannot be undone; a book keeps at least one chapter.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter to delete: its position in the book (from 1), its title or its id."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again and answer with the pages each chapter came to (default true). False answers at once."
          }
        },
        "required": [
          "chapter"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_get_configAnswer

    The book's configuration — page size and margins, columns, body text, headings, lists, figures, running heads, notes, colours, print and so on. A book stores only what departs from the defaults: "set" is what it stores at the path, "effective" what the setting comes to with the defaults filled in (which also shows every setting that exists there). Paths look like page.margins.top, bodyText.hyphenation, headings.levels[level=2].fontSize, header.elements[id=titleOdd], calloutStyles[id=note].title; an item of a list can also be named by its position in the effective list ([0]), and the answer gives the path by what tells the item apart. Without a path: everything the book sets, and the names of the top-level sections. The settings are documented at /docs/configuration.

    View tool JSON
    {
      "name": "sandbox_get_config",
      "kind": "answer",
      "impl": "imperative",
      "description": "The book's configuration — page size and margins, columns, body text, headings, lists, figures, running heads, notes, colours, print and so on. A book stores only what departs from the defaults: \"set\" is what it stores at the path, \"effective\" what the setting comes to with the defaults filled in (which also shows every setting that exists there). Paths look like page.margins.top, bodyText.hyphenation, headings.levels[level=2].fontSize, header.elements[id=titleOdd], calloutStyles[id=note].title; an item of a list can also be named by its position in the effective list ([0]), and the answer gives the path by what tells the item apart. Without a path: everything the book sets, and the names of the top-level sections. The settings are documented at /docs/configuration.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string",
            "description": "The setting, or the section, to read."
          },
          "effective": {
            "type": "boolean",
            "description": "Include the value with defaults filled in (default true when a path is given)."
          },
          "scope": {
            "type": "string",
            "enum": [
              "all",
              "edition"
            ],
            "description": "A book in several languages: all reads the general settings every edition reads, edition the edition on screen (its own fields over the general ones). Default: the scope the Design panel is in."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_set_configAction

    Change the book's configuration, then lay the book out again. changes sets one value per path, any path sandbox_get_config or sandbox_find_setting gives (page.margins.top, bodyText.fontSize, headings.levels[level=2].fontSize, header.elements[id=titleOdd].fontSize, calloutStyles[id=note].title); a null value removes the setting, which brings its default back. patch merges an object into the configuration (objects merge, null removes, lists are replaced whole). replace puts a whole configuration in place of the book's (a postext-config.json export, or a configuration object). A length is { "value": 2, "unit": "cm" }, a number in the setting's unit, or "2cm"; a colour is "#1f3a5f" or { "hex", "model" }. A value of the wrong shape is refused, and so is a configuration the engine cannot resolve: nothing is changed then. Answers with each setting's stored value before and after — which is how to take a change back — and what it resolves to, a note when the engine resolved something else than what was asked (a limit, a setting that depends on another), the other settings that followed, any warning the new values raise, and the pages every chapter came to before and after.

    View tool JSON
    {
      "name": "sandbox_set_config",
      "kind": "act",
      "impl": "imperative",
      "description": "Change the book's configuration, then lay the book out again. changes sets one value per path, any path sandbox_get_config or sandbox_find_setting gives (page.margins.top, bodyText.fontSize, headings.levels[level=2].fontSize, header.elements[id=titleOdd].fontSize, calloutStyles[id=note].title); a null value removes the setting, which brings its default back. patch merges an object into the configuration (objects merge, null removes, lists are replaced whole). replace puts a whole configuration in place of the book's (a postext-config.json export, or a configuration object). A length is { \"value\": 2, \"unit\": \"cm\" }, a number in the setting's unit, or \"2cm\"; a colour is \"#1f3a5f\" or { \"hex\", \"model\" }. A value of the wrong shape is refused, and so is a configuration the engine cannot resolve: nothing is changed then. Answers with each setting's stored value before and after — which is how to take a change back — and what it resolves to, a note when the engine resolved something else than what was asked (a limit, a setting that depends on another), the other settings that followed, any warning the new values raise, and the pages every chapter came to before and after.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "changes": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string",
                  "description": "The setting, as a path from the top of the configuration."
                },
                "value": {
                  "description": "Its new value; null (or left out) removes the setting."
                }
              },
              "required": [
                "path"
              ],
              "additionalProperties": false
            }
          },
          "patch": {
            "type": "object",
            "description": "An object merged into the configuration."
          },
          "replace": {
            "type": "object",
            "description": "A whole configuration (or a postext-config.json export) that takes the place of the book's. Not with changes or patch."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again and answer with its pages (default true)."
          },
          "scope": {
            "type": "string",
            "enum": [
              "all",
              "edition"
            ],
            "description": "A book in several languages: all writes the general settings every edition reads (an edition that sets the field itself keeps its value, and the answer names it in keptBy); edition writes the edition on screen only, as a value of its own. Default: the scope the Design panel is in. A book in one language has only its own settings."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_find_settingAnswer

    Find where a design setting lives from a few words ("orphans", "margin", "drop cap", "baseline grid"): the configuration paths whose names match, with their current effective values, and the sections of the Design panel that mention the words, with the top-level configuration keys each one edits. The words are matched against the setting names (English, camelCase) and against the panel in the language of the interface.

    View tool JSON
    {
      "name": "sandbox_find_setting",
      "kind": "answer",
      "impl": "imperative",
      "description": "Find where a design setting lives from a few words (\"orphans\", \"margin\", \"drop cap\", \"baseline grid\"): the configuration paths whose names match, with their current effective values, and the sections of the Design panel that mention the words, with the top-level configuration keys each one edits. The words are matched against the setting names (English, camelCase) and against the panel in the language of the interface.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "description": "One or more words describing the setting."
          }
        },
        "required": [
          "query"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_reset_to_originalAction

    Put back what the book started from — the sample it is, or the sample a project was made from: its design settings only (config), its text and resources (document), its resources only, or all of it. With sample, another sample than the one on screen is put back whole, in every language the reader edited it in. The reader's edits to that part are discarded and cannot be recovered. One setting or one section goes back to the design's with a null value in sandbox_set_config.

    View tool JSON
    {
      "name": "sandbox_reset_to_original",
      "kind": "act",
      "impl": "imperative",
      "description": "Put back what the book started from — the sample it is, or the sample a project was made from: its design settings only (config), its text and resources (document), its resources only, or all of it. With sample, another sample than the one on screen is put back whole, in every language the reader edited it in. The reader's edits to that part are discarded and cannot be recovered. One setting or one section goes back to the design's with a null value in sandbox_set_config.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "part": {
            "type": "string",
            "enum": [
              "config",
              "document",
              "resources",
              "all"
            ],
            "description": "What to put back."
          },
          "sample": {
            "type": "string",
            "description": "With part \"all\": the sample to put back (its id, as sandbox_list_books gives it) instead of the book on screen. It need not be open."
          }
        },
        "required": [
          "part"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_rename_design_itemAction

    Give a named item of the design another id, and everything that names it the new one, as the Settings panel does: calloutStyles (the :::callout{type} fences, template frames, styles based on it and the box, bank.box and solutions.box of the exercise styles), labelStyles (picture anchors and ::label lines), tableStyles and scoreStyles (the table and score resources that use it), frameLooks (the pieces that name the look), pageTemplates (the ::::page fences; a module: its :::module blocks), templateFrames (a frame or group of template: the slot names of the pages, and the editions a local book keeps aside), comics.balloonStyles (the cast members who speak in it); exerciseStyles (the :::exercise{style} fences and the styles based on it); paragraphStyles, headingStyles, chipStyles, markStyles, comics.panelStyles and comics.cast rename the item only. Through sandbox_set_config the uses would be left naming an item that is gone. The new id is made safe the way the panel makes it (lowercase letters, digits, _ and -). Answers what was rewritten and undoSteps (sandbox_undo that many times takes it back).

    View tool JSON
    {
      "name": "sandbox_rename_design_item",
      "kind": "act",
      "impl": "imperative",
      "description": "Give a named item of the design another id, and everything that names it the new one, as the Settings panel does: calloutStyles (the :::callout{type} fences, template frames, styles based on it and the box, bank.box and solutions.box of the exercise styles), labelStyles (picture anchors and ::label lines), tableStyles and scoreStyles (the table and score resources that use it), frameLooks (the pieces that name the look), pageTemplates (the ::::page fences; a module: its :::module blocks), templateFrames (a frame or group of template: the slot names of the pages, and the editions a local book keeps aside), comics.balloonStyles (the cast members who speak in it); exerciseStyles (the :::exercise{style} fences and the styles based on it); paragraphStyles, headingStyles, chipStyles, markStyles, comics.panelStyles and comics.cast rename the item only. Through sandbox_set_config the uses would be left naming an item that is gone. The new id is made safe the way the panel makes it (lowercase letters, digits, _ and -). Answers what was rewritten and undoSteps (sandbox_undo that many times takes it back).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "list": {
            "type": "string",
            "enum": [
              "calloutStyles",
              "labelStyles",
              "tableStyles",
              "scoreStyles",
              "paragraphStyles",
              "headingStyles",
              "chipStyles",
              "markStyles",
              "frameLooks",
              "colorPalette",
              "pageTemplates",
              "templateFrames",
              "comics.balloonStyles",
              "comics.panelStyles",
              "comics.cast",
              "exerciseStyles"
            ],
            "description": "The list the item is in. colorPalette entries keep their id (rename them with sandbox_set_config colorPalette[id=…].name)."
          },
          "id": {
            "type": "string",
            "description": "The item's id (for templateFrames: the frame or group name)."
          },
          "to": {
            "type": "string",
            "description": "The new id."
          },
          "template": {
            "type": "string",
            "description": "For templateFrames: the page template the frame or group belongs to."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again and answer with the pages each chapter came to (default true). False answers at once."
          }
        },
        "required": [
          "list",
          "id",
          "to"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_remove_design_itemAction

    Take an item out of a named list of the design, with what the Settings panel does to its uses: a callout style's children take its look over (and its parent, if it had one), so no box changes; a palette colour's settings keep the colour it gave them, no longer linked to the palette; a comics balloon style leaves the cast members who spoke in it with the default balloon. The other lists (labelStyles, tableStyles, scoreStyles, paragraphStyles, headingStyles, chipStyles, markStyles, frameLooks, exerciseStyles, comics.panelStyles, comics.cast) lose the item only: what names it falls back as the panel says. Page templates, frames and groups are removed with sandbox_set_config (a null value). One step for sandbox_undo.

    View tool JSON
    {
      "name": "sandbox_remove_design_item",
      "kind": "act",
      "impl": "imperative",
      "description": "Take an item out of a named list of the design, with what the Settings panel does to its uses: a callout style's children take its look over (and its parent, if it had one), so no box changes; a palette colour's settings keep the colour it gave them, no longer linked to the palette; a comics balloon style leaves the cast members who spoke in it with the default balloon. The other lists (labelStyles, tableStyles, scoreStyles, paragraphStyles, headingStyles, chipStyles, markStyles, frameLooks, exerciseStyles, comics.panelStyles, comics.cast) lose the item only: what names it falls back as the panel says. Page templates, frames and groups are removed with sandbox_set_config (a null value). One step for sandbox_undo.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "list": {
            "type": "string",
            "enum": [
              "calloutStyles",
              "labelStyles",
              "tableStyles",
              "scoreStyles",
              "paragraphStyles",
              "headingStyles",
              "chipStyles",
              "markStyles",
              "frameLooks",
              "colorPalette",
              "pageTemplates",
              "templateFrames",
              "comics.balloonStyles",
              "comics.panelStyles",
              "comics.cast",
              "exerciseStyles"
            ],
            "description": "The list the item is in (not pageTemplates or templateFrames)."
          },
          "id": {
            "type": "string",
            "description": "The item's id."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again and answer with the pages each chapter came to (default true). False answers at once."
          }
        },
        "required": [
          "list",
          "id"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_language_defaultsAction

    The list the Body text section offers a Chinese, Japanese or Arabic book (Design › Text › Language): the settings such a book is usually set with — document language, writing mode and binding, typefaces, alignment, indent, notes, chapter numbering, punctuation rules — each with the value it has and the one it would take. Without apply it only lists them: required rows always apply; optional ones apply unless the author set a value of their own (customised), and include names exactly the optional rows to apply. With apply: true the rows are written as one step (sandbox_undo takes it back). chinese takes locale (zh-Hans, zh-Hant, zh-HK…) and vertical; japanese takes book (vertical: a bunko or tankōbon novel; horizontal: a technical book); arabic takes faces (classical or modern) and the document language must be in the Arabic script.

    View tool JSON
    {
      "name": "sandbox_language_defaults",
      "kind": "act",
      "impl": "imperative",
      "description": "The list the Body text section offers a Chinese, Japanese or Arabic book (Design › Text › Language): the settings such a book is usually set with — document language, writing mode and binding, typefaces, alignment, indent, notes, chapter numbering, punctuation rules — each with the value it has and the one it would take. Without apply it only lists them: required rows always apply; optional ones apply unless the author set a value of their own (customised), and include names exactly the optional rows to apply. With apply: true the rows are written as one step (sandbox_undo takes it back). chinese takes locale (zh-Hans, zh-Hant, zh-HK…) and vertical; japanese takes book (vertical: a bunko or tankōbon novel; horizontal: a technical book); arabic takes faces (classical or modern) and the document language must be in the Arabic script.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "language": {
            "type": "string",
            "enum": [
              "chinese",
              "japanese",
              "arabic"
            ]
          },
          "locale": {
            "type": "string",
            "description": "chinese: zh-Hans or zh-Hant (any Chinese tag; default the book's, else zh-Hans). arabic: an Arabic-script tag (default the book's)."
          },
          "vertical": {
            "type": "boolean",
            "description": "chinese: vertical lines bound on the right, or horizontal (default: the direction a Chinese book has, else vertical for Traditional)."
          },
          "book": {
            "type": "string",
            "enum": [
              "vertical",
              "horizontal"
            ],
            "description": "japanese: default vertical."
          },
          "faces": {
            "type": "string",
            "enum": [
              "classical",
              "modern"
            ],
            "description": "arabic: default classical."
          },
          "include": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The optional rows to apply, by id (default: every row the author has not customised)."
          },
          "apply": {
            "type": "boolean",
            "description": "Write the rows (default false: list them)."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again and answer with the pages each chapter came to (default true). False answers at once."
          }
        },
        "required": [
          "language"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_print_profileAction

    The Print section's own output condition: an ICC profile file (a CMYK output profile, .icc or .icm) the PDF/X export converts colours with and names as its output intent. Upload one (file, by url or base64): it is stored with the book and print.outputProfile becomes "custom"; name gives it another name than the one it states. remove: true takes it away (back to the default condition). The registry name and the other print settings are set with sandbox_set_config (print.customProfile.registryName).

    View tool JSON
    {
      "name": "sandbox_print_profile",
      "kind": "act",
      "impl": "imperative",
      "description": "The Print section's own output condition: an ICC profile file (a CMYK output profile, .icc or .icm) the PDF/X export converts colours with and names as its output intent. Upload one (file, by url or base64): it is stored with the book and print.outputProfile becomes \"custom\"; name gives it another name than the one it states. remove: true takes it away (back to the default condition). The registry name and the other print settings are set with sandbox_set_config (print.customProfile.registryName).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "file": {
            "type": "object",
            "description": "A file: where to fetch it (url) or its bytes (base64).",
            "properties": {
              "url": {
                "type": "string",
                "description": "An http(s) or data: URL the page can fetch."
              },
              "base64": {
                "type": "string",
                "description": "The bytes, base64-encoded."
              },
              "mimeType": {
                "type": "string",
                "description": "Its media type, e.g. image/png. Read from the response or the file name when left out."
              },
              "fileName": {
                "type": "string",
                "description": "Its file name, with its extension."
              }
            },
            "additionalProperties": false
          },
          "name": {
            "type": "string"
          },
          "remove": {
            "type": "boolean"
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again and answer with the pages each chapter came to (default true). False answers at once."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_save_layout_as_templateAction

    The Page templates section's «Save layout as template»: a new page template whose frames stand where they stand on a laid composed page, at fixed sizes in millimetres, with the rest of each frame, the decoration, the running heads and the area of the page's template. page is the page's position in the chapter (1-based) or its folio (number); default: the chapter's first composed page. Answers the new template's id. One step for sandbox_undo.

    View tool JSON
    {
      "name": "sandbox_save_layout_as_template",
      "kind": "act",
      "impl": "imperative",
      "description": "The Page templates section's «Save layout as template»: a new page template whose frames stand where they stand on a laid composed page, at fixed sizes in millimetres, with the rest of each frame, the decoration, the running heads and the area of the page's template. page is the page's position in the chapter (1-based) or its folio (number); default: the chapter's first composed page. Answers the new template's id. One step for sandbox_undo.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter: its position in the book (from 1), its title or its id. The chapter on screen when left out."
          },
          "page": {
            "type": "integer",
            "description": "The page's position in the chapter, from 1."
          },
          "number": {
            "type": "integer",
            "description": "The page's folio, in place of page."
          },
          "name": {
            "type": "string",
            "description": "The template's name (default: «<template> layout»)."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_undoAction

    Take back the last change to the book, whatever it was, as Cmd/Ctrl+Z and the Undo button do; with redo put back the last one taken back. The Sandbox keeps one history of the text and the design in the order the changes were made: text typed in the Manuscript editor or edited by a tool or on the previews, and every change to the configuration (a setting set by sandbox_set_config or in the Design panel, a frame dragged in Design mode, a page template added). A setting dragged or typed digit by digit is one change. Answers with what was taken back: kind text with its chapter, or kind design with the settings it touched; then whether there is more to undo or redo. The chapter on screen stays the one on screen. The marks of a picture (its label anchors, safe area and lettering zones) saved in the Resources panel, set by sandbox_save_resource with marks, or an anchor dragged on a page are kind resource with the resource id. Chapters added, removed, split, merged or moved, other resource changes and fonts are not in the history, and opening another book empties it. For text only, sandbox_undo_text.

    View tool JSON
    {
      "name": "sandbox_undo",
      "kind": "act",
      "impl": "imperative",
      "description": "Take back the last change to the book, whatever it was, as Cmd/Ctrl+Z and the Undo button do; with redo put back the last one taken back. The Sandbox keeps one history of the text and the design in the order the changes were made: text typed in the Manuscript editor or edited by a tool or on the previews, and every change to the configuration (a setting set by sandbox_set_config or in the Design panel, a frame dragged in Design mode, a page template added). A setting dragged or typed digit by digit is one change. Answers with what was taken back: kind text with its chapter, or kind design with the settings it touched; then whether there is more to undo or redo. The chapter on screen stays the one on screen. The marks of a picture (its label anchors, safe area and lettering zones) saved in the Resources panel, set by sandbox_save_resource with marks, or an anchor dragged on a page are kind resource with the resource id. Chapters added, removed, split, merged or moved, other resource changes and fonts are not in the history, and opening another book empties it. For text only, sandbox_undo_text.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "redo": {
            "type": "boolean",
            "description": "Put back the last change taken back, instead of taking one back."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again and answer with the pages each chapter came to (default true). False answers at once."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_frame_stylesAction

    The callout styles of the book (they also dress the frames of page templates) with where each is used: the template frames that name it, the composed pages laid with those templates and the :::callout fences of each chapter (by chapter position, 1-based). Also the merges the Frame styles section suggests for near-identical styles: lengths within 0.5 mm and colours within ΔE 2 are equal, at most maxFields settings may differ. A style that differs from another only in colours is a variant, not a duplicate: it is left out of the suggestions and listed in kinds with the style that extends or most resembles it. Merge with sandbox_merge_styles.

    View tool JSON
    {
      "name": "sandbox_frame_styles",
      "kind": "act",
      "impl": "imperative",
      "description": "The callout styles of the book (they also dress the frames of page templates) with where each is used: the template frames that name it, the composed pages laid with those templates and the :::callout fences of each chapter (by chapter position, 1-based). Also the merges the Frame styles section suggests for near-identical styles: lengths within 0.5 mm and colours within ΔE 2 are equal, at most maxFields settings may differ. A style that differs from another only in colours is a variant, not a duplicate: it is left out of the suggestions and listed in kinds with the style that extends or most resembles it. Merge with sandbox_merge_styles.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "maxFields": {
            "type": "number",
            "description": "Most settings two styles may differ in and still be suggested (default 2; the four sides of a padding count once)."
          },
          "lookOnly": {
            "type": "boolean",
            "description": "Also compare styles whose :::callout boxes stand at different places, on their look alone; merging those moves the boxes (default false)."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_merge_stylesAction

    Merge callout styles into the one kept: every template frame style and every :::callout{type} fence of every chapter naming a merged style is rewritten to the kept one, and the merged styles leave the list. Give groups ({ keep, merge: [ids] }), or all: true for every suggestion sandbox_frame_styles makes with the same maxFields / lookOnly. It enters the undo history as one step per chapter rewritten and one for the styles (undoSteps): sandbox_undo that many times puts the book back.

    View tool JSON
    {
      "name": "sandbox_merge_styles",
      "kind": "act",
      "impl": "imperative",
      "description": "Merge callout styles into the one kept: every template frame style and every :::callout{type} fence of every chapter naming a merged style is rewritten to the kept one, and the merged styles leave the list. Give groups ({ keep, merge: [ids] }), or all: true for every suggestion sandbox_frame_styles makes with the same maxFields / lookOnly. It enters the undo history as one step per chapter rewritten and one for the styles (undoSteps): sandbox_undo that many times puts the book back.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "groups": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "keep": {
                  "type": "string"
                },
                "merge": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              },
              "required": [
                "keep",
                "merge"
              ],
              "additionalProperties": false
            }
          },
          "all": {
            "type": "boolean",
            "description": "Take every suggestion."
          },
          "maxFields": {
            "type": "number",
            "description": "Most settings two styles may differ in and still be suggested (default 2; the four sides of a padding count once)."
          },
          "lookOnly": {
            "type": "boolean",
            "description": "Also compare styles whose :::callout boxes stand at different places, on their look alone; merging those moves the boxes (default false)."
          },
          "keepPlaces": {
            "type": "boolean",
            "description": "With lookOnly: a style whose :::callout boxes stand elsewhere than the kept style's is not merged away but stays with only its place, based on the kept style (extends), so no box moves (default true)."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again (default true)."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_modulesAction

    The book's module templates (pageTemplates entries with role "module", stacked in a page by :::module{template="…"} blocks inside a ::::page fence) with their frames and groups, and where they are used: blocks, composed pages and chapters (1-based); and the page templates with the group that takes modules (modules: true). Create one with sandbox_create_module, write one into a page with sandbox_insert_module, rename with sandbox_rename_module, make one from a page's frames with sandbox_extract_module.

    View tool JSON
    {
      "name": "sandbox_modules",
      "kind": "act",
      "impl": "imperative",
      "description": "The book's module templates (pageTemplates entries with role \"module\", stacked in a page by :::module{template=\"…\"} blocks inside a ::::page fence) with their frames and groups, and where they are used: blocks, composed pages and chapters (1-based); and the page templates with the group that takes modules (modules: true). Create one with sandbox_create_module, write one into a page with sandbox_insert_module, rename with sandbox_rename_module, make one from a page's frames with sandbox_extract_module.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_create_moduleAction

    Add a module template (role "module") with one text frame, named from name (its id made from it). Shape it with sandbox_set_config at pageTemplates[id=…], or reshape a page's frames into one with sandbox_extract_module. One step of the undo history.

    View tool JSON
    {
      "name": "sandbox_create_module",
      "kind": "act",
      "impl": "imperative",
      "description": "Add a module template (role \"module\") with one text frame, named from name (its id made from it). Shape it with sandbox_set_config at pageTemplates[id=…], or reshape a page's frames into one with sandbox_extract_module. One step of the undo history.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_rename_moduleAction

    Give module template module the id to, with every use: the :::module{template} blocks of every chapter and the templates that extend it. One step per chapter rewritten and one for the design (undoSteps).

    View tool JSON
    {
      "name": "sandbox_rename_module",
      "kind": "act",
      "impl": "imperative",
      "description": "Give module template module the id to, with every use: the :::module{template} blocks of every chapter and the templates that extend it. One step per chapter rewritten and one for the design (undoSteps).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "module": {
            "type": "string"
          },
          "to": {
            "type": "string"
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again (default true)."
          }
        },
        "required": [
          "module",
          "to"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_insert_moduleAction

    Write a :::module{template="module"} block into a composed page of a chapter, before its closing fence, with an empty :::frame{slot} for each of the module's frames to write in (the text stays in the Markdown). page is the ::::page fence's ordinal in the chapter (1-based; default 1). When the page's template has no group that takes modules, one is added (groupAdded): under its last frame, as wide as the area. Steps for sandbox_undo: the text, and the design when a group was added.

    View tool JSON
    {
      "name": "sandbox_insert_module",
      "kind": "act",
      "impl": "imperative",
      "description": "Write a :::module{template=\"module\"} block into a composed page of a chapter, before its closing fence, with an empty :::frame{slot} for each of the module's frames to write in (the text stays in the Markdown). page is the ::::page fence's ordinal in the chapter (1-based; default 1). When the page's template has no group that takes modules, one is added (groupAdded): under its last frame, as wide as the area. Steps for sandbox_undo: the text, and the design when a group was added.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "module": {
            "type": "string"
          },
          "chapter": {
            "type": [
              "number",
              "string"
            ]
          },
          "page": {
            "type": "number"
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again (default true)."
          }
        },
        "required": [
          "module"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_frames_to_gridAction

    Turn frames of a page template that stand on a lattice (cards of one width in rows and columns, each maybe with frames hanging from it: foto1, pie1, foto2, pie2…) into one grid group that repeats the first card's frames (kind "grid", columns, gaps, repeat). The lattice is read off a laid page set with the template; every page set with it gets its pieces renamed into the grid's items in reading order, so the pages look as they did. Answers the grid, its names, and instances (old frame name → instance name, foto2 → foto[2]). Steps for sandbox_undo: one per chapter rewritten and one for the design (undoSteps).

    View tool JSON
    {
      "name": "sandbox_frames_to_grid",
      "kind": "act",
      "impl": "imperative",
      "description": "Turn frames of a page template that stand on a lattice (cards of one width in rows and columns, each maybe with frames hanging from it: foto1, pie1, foto2, pie2…) into one grid group that repeats the first card's frames (kind \"grid\", columns, gaps, repeat). The lattice is read off a laid page set with the template; every page set with it gets its pieces renamed into the grid's items in reading order, so the pages look as they did. Answers the grid, its names, and instances (old frame name → instance name, foto2 → foto[2]). Steps for sandbox_undo: one per chapter rewritten and one for the design (undoSteps).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "template": {
            "type": "string"
          },
          "frames": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "chapter": {
            "type": [
              "number",
              "string"
            ],
            "description": "Chapter (1-based position, id or title) whose pages are read for the frames' boxes; default: the first chapter with a page set with the template."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again (default true)."
          }
        },
        "required": [
          "template",
          "frames"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_extract_moduleAction

    Move frames of a page template (and the decoration hanging from them, and a grid or group all of whose frames move) into a new module template named name; the page template gets a modules group where they stood (a box as wide as they were), and every page set with it gets the pieces for those frames wrapped in a :::module{template} block, so the pages look as they did. Frames that hung from a moved frame hang from the modules group, shifted to stay where they were. Answers the module id, the group and names (frame on the page before → after: nota → caja[1].nota). Steps for sandbox_undo: one per chapter rewritten and one for the design.

    View tool JSON
    {
      "name": "sandbox_extract_module",
      "kind": "act",
      "impl": "imperative",
      "description": "Move frames of a page template (and the decoration hanging from them, and a grid or group all of whose frames move) into a new module template named name; the page template gets a modules group where they stood (a box as wide as they were), and every page set with it gets the pieces for those frames wrapped in a :::module{template} block, so the pages look as they did. Frames that hung from a moved frame hang from the modules group, shifted to stay where they were. Answers the module id, the group and names (frame on the page before → after: nota → caja[1].nota). Steps for sandbox_undo: one per chapter rewritten and one for the design.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "template": {
            "type": "string"
          },
          "frames": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "name": {
            "type": "string"
          },
          "chapter": {
            "type": [
              "number",
              "string"
            ],
            "description": "Chapter (1-based position, id or title) whose pages are read for the frames' boxes; default: the first chapter with a page set with the template."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again (default true)."
          }
        },
        "required": [
          "template",
          "frames",
          "name"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_edit_labelsAction

    What the anchor editor, the text editor's symbol picker and a frame's pointers do. action "leader": write the own leader attribute of the ::label / :::label lines of a picture (resource) at an anchor or with a text: on (leader), off (leader="none") or anchor (none written: the anchor and the label style decide). action "icon": write an inline symbol :icon[alt]{…} at the start or end of those labels' text (a picture resource, a glyph with an optional font, or a line sample solid/dashed/dotted; color a hex or palette id, size in ems), as a map's key row. action "pointer": a line from frame `from` of page template `template` to anchor `anchor` of the picture frame `toFrame` holds (a connector of the template's decoration ending at that anchor, painted over the frames); with id, that pointer is changed; with remove: true and id, taken off. Where a label stands away from its point (labelAt) and an anchor's leader are the picture's marks (sandbox_save_resource); a style's leader look is labelStyles[id=…].leader (sandbox_set_config). Every change is one step of the undo history.

    View tool JSON
    {
      "name": "sandbox_edit_labels",
      "kind": "act",
      "impl": "imperative",
      "description": "What the anchor editor, the text editor's symbol picker and a frame's pointers do. action \"leader\": write the own leader attribute of the ::label / :::label lines of a picture (resource) at an anchor or with a text: on (leader), off (leader=\"none\") or anchor (none written: the anchor and the label style decide). action \"icon\": write an inline symbol :icon[alt]{…} at the start or end of those labels' text (a picture resource, a glyph with an optional font, or a line sample solid/dashed/dotted; color a hex or palette id, size in ems), as a map's key row. action \"pointer\": a line from frame `from` of page template `template` to anchor `anchor` of the picture frame `toFrame` holds (a connector of the template's decoration ending at that anchor, painted over the frames); with id, that pointer is changed; with remove: true and id, taken off. Where a label stands away from its point (labelAt) and an anchor's leader are the picture's marks (sandbox_save_resource); a style's leader look is labelStyles[id=…].leader (sandbox_set_config). Every change is one step of the undo history.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "leader",
              "icon",
              "pointer"
            ]
          },
          "resource": {
            "type": "string",
            "description": "leader, icon: the picture the labels belong to."
          },
          "anchor": {
            "type": "string",
            "description": "leader, icon: the anchor the labels stand at. pointer: the anchor of the picture in toFrame."
          },
          "text": {
            "type": "string",
            "description": "leader, icon: the labels whose text is this."
          },
          "leader": {
            "type": "string",
            "enum": [
              "anchor",
              "on",
              "off"
            ],
            "description": "leader: on, off or anchor."
          },
          "icon": {
            "type": "object",
            "description": "icon: the symbol.",
            "properties": {
              "resource": {
                "type": "string"
              },
              "glyph": {
                "type": "string"
              },
              "font": {
                "type": "string"
              },
              "line": {
                "type": "string",
                "enum": [
                  "solid",
                  "dashed",
                  "dotted"
                ]
              }
            },
            "additionalProperties": false
          },
          "alt": {
            "type": "string",
            "description": "icon: what a reader hears for the symbol (default empty: read as nothing)."
          },
          "color": {
            "type": "string",
            "description": "icon: its colour, a hex or a palette id."
          },
          "size": {
            "type": "number",
            "description": "icon: its height in ems (default 0.75, the cap height; beside a shaped number, the shape's height)."
          },
          "position": {
            "type": "string",
            "enum": [
              "start",
              "end"
            ],
            "description": "icon: before the label's words (default, a key's row) or after them."
          },
          "template": {
            "type": "string",
            "description": "pointer: the page template id."
          },
          "from": {
            "type": "string",
            "description": "pointer: the frame the line leaves (a note)."
          },
          "toFrame": {
            "type": "string",
            "description": "pointer: the frame holding the picture."
          },
          "id": {
            "type": "string",
            "description": "pointer: the pointer (connector id) to change or remove."
          },
          "remove": {
            "type": "boolean",
            "description": "pointer: take the pointer id off."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again (default true)."
          }
        },
        "required": [
          "action"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_set_viewAction

    Change what the reader sees of the Sandbox, any number of settings at once: the viewer tab (canvas, pdf, folio, html, epub, scorm), the Content or Design mode, the side panel and the resource open in it, the Design panel's group, explanations and changed-only filter, whether a viewer shows the chapter or the whole book, the EPUB rendition, the content, version and chapters and sections of the SCORM package, the Canvas magnification, fit and facing pages, the type size and columns of the HTML and EPUB readers, the Folio pointer mode, view and magnifying glass, the print preview, the fit marks drawn over composed pages, pinned toolbars, large touch targets, and the guides drawn on the pages (baseline grid, character grid, loose-line highlight, pages in negative). Answers with the view as it stands afterwards, the status of the viewer on screen included (its page, what it is writing, an EPUB's contents and warnings, the videos of its pages). sandbox_go_to_page turns the pages; sandbox_run_viewer presses a viewer's buttons (regenerate, print, download, play a video).

    View tool JSON
    {
      "name": "sandbox_set_view",
      "kind": "act",
      "impl": "imperative",
      "description": "Change what the reader sees of the Sandbox, any number of settings at once: the viewer tab (canvas, pdf, folio, html, epub, scorm), the Content or Design mode, the side panel and the resource open in it, the Design panel's group, explanations and changed-only filter, whether a viewer shows the chapter or the whole book, the EPUB rendition, the content, version and chapters and sections of the SCORM package, the Canvas magnification, fit and facing pages, the type size and columns of the HTML and EPUB readers, the Folio pointer mode, view and magnifying glass, the print preview, the fit marks drawn over composed pages, pinned toolbars, large touch targets, and the guides drawn on the pages (baseline grid, character grid, loose-line highlight, pages in negative). Answers with the view as it stands afterwards, the status of the viewer on screen included (its page, what it is writing, an EPUB's contents and warnings, the videos of its pages). sandbox_go_to_page turns the pages; sandbox_run_viewer presses a viewer's buttons (regenerate, print, download, play a video).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "viewer": {
            "type": "string",
            "enum": [
              "canvas",
              "pdf",
              "folio",
              "html",
              "epub",
              "scorm"
            ],
            "description": "The viewer tab to show."
          },
          "mode": {
            "type": "string",
            "enum": [
              "content",
              "design"
            ],
            "description": "content: the text is edited (the editor, the frames of composed pages on the page); design: page templates and styles are edited and the text is read only. The person switches with Alt+Shift+M."
          },
          "panel": {
            "type": "string",
            "enum": [
              "projects",
              "chapters",
              "markdown",
              "resources",
              "fonts",
              "config",
              "warnings",
              "none"
            ],
            "description": "The side panel to open (projects = Books, markdown = Text, config = Design, warnings = Checks), or none to close it."
          },
          "sidebarWidth": {
            "type": "number",
            "minimum": 5,
            "maximum": 80,
            "description": "Width of the side panel, as a percentage of the window."
          },
          "settingsGroup": {
            "type": "string",
            "enum": [
              "page",
              "writing",
              "colors",
              "text",
              "headings",
              "lists",
              "figures",
              "callouts",
              "exercises",
              "comics",
              "running",
              "parts",
              "output",
              "folio",
              "advanced"
            ],
            "description": "Open the Design panel on this group of settings."
          },
          "settingsHelp": {
            "type": "boolean",
            "description": "Design panel: show the explanation under each setting. Kept for the next time the panel opens."
          },
          "settingsChangedOnly": {
            "type": "boolean",
            "description": "Design panel: list only the settings the book changed. Turning it on opens the panel; the filter goes when the panel closes."
          },
          "resource": {
            "type": [
              "string",
              "null"
            ],
            "description": "Open the Resources panel on the resource with this id; null closes the resource that is open and goes back to the list."
          },
          "scope": {
            "type": "string",
            "enum": [
              "chapter",
              "book"
            ],
            "description": "What the viewer lays out: the chapter on screen or the whole book. Applies to the PDF when that is the viewer, to Canvas, Folio and HTML otherwise."
          },
          "epubLayout": {
            "type": "string",
            "enum": [
              "reflowable",
              "fixed"
            ],
            "description": "The EPUB rendition: text that reflows, or the printed pages kept."
          },
          "scormLayout": {
            "type": "string",
            "enum": [
              "fixed",
              "reflowable"
            ],
            "description": "The SCORM package's content: the printed pages, or text that reflows."
          },
          "scormVersion": {
            "type": "string",
            "enum": [
              "1.2",
              "2004"
            ],
            "description": "The SCORM data model of the package: 1.2 (every LMS) or 2004 4th edition."
          },
          "scormPick": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "SCORM: the ids of the tree nodes (chapters and headings, the status's contents[].href) the package takes, each one whole; every other node is left out. A chapter or section ticked whole is one SCO."
          },
          "zoom": {
            "type": "number",
            "minimum": 0.25,
            "maximum": 4,
            "description": "Canvas: magnification (1 = 100%). Turns the fit off unless fit is given too."
          },
          "fit": {
            "type": "string",
            "enum": [
              "width",
              "height",
              "none"
            ],
            "description": "Canvas: fit the page to the width or height of the viewer."
          },
          "pages": {
            "type": "string",
            "enum": [
              "single",
              "spread"
            ],
            "description": "Canvas: one page per row, or facing pages."
          },
          "fontScale": {
            "type": "number",
            "minimum": 0.6,
            "maximum": 2.5,
            "description": "HTML and reflowable EPUB: the reader's type size (1 = as designed)."
          },
          "columns": {
            "type": "string",
            "enum": [
              "single",
              "multi"
            ],
            "description": "HTML: one scrolling column, or columns paged sideways."
          },
          "interaction": {
            "type": "string",
            "enum": [
              "hand",
              "orbit",
              "select",
              "magnify"
            ],
            "description": "Folio: what the pointer does on the 3D book."
          },
          "folioView": {
            "type": "string",
            "enum": [
              "reset",
              "save"
            ],
            "description": "Folio: ease the camera back to the configured view, or keep the view on screen as the book's. The viewer has no way to set the camera to a given angle: to look from one, set folio.tilt and folio.yaw with sandbox_set_config, then reset. The status gives the view on screen."
          },
          "magnification": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 1.5,
            "maximum": 10,
            "description": "Folio: hold the magnifying glass over the middle of the open spread, magnifying this many times; null puts it away. The glass belongs to the magnify pointer mode, which the viewer is switched to."
          },
          "toolbarPinned": {
            "type": "boolean",
            "description": "Keep the viewer's floating toolbar on screen."
          },
          "printPreview": {
            "type": "boolean",
            "description": "Canvas and Folio: the soft proof of the output profile with trim, bleed and safe-zone guides."
          },
          "fitMarks": {
            "type": "string",
            "enum": [
              "all",
              "problems",
              "none",
              "book"
            ],
            "description": "Canvas: the marks of how composed frames fit — all (scaled text and pictures too), problems (frames that do not fit, unknown looks) or none. Kept as the reader's choice in this browser, over the book's debug.fitMarks (problems unless the book sets another); book forgets the choice and follows the book again. Never drawn in the PDF, HTML, EPUB or Folio."
          },
          "largeTargets": {
            "type": "boolean",
            "description": "Controls at least 44 px, for touch."
          },
          "guides": {
            "type": "object",
            "description": "Guides drawn on the pages; they are settings of the book (debug.*, page.baselineGrid, cjk.grid).",
            "properties": {
              "baselineGrid": {
                "type": "boolean"
              },
              "characterGrid": {
                "type": "boolean",
                "description": "The CJK character grid."
              },
              "looseLines": {
                "type": "boolean",
                "description": "Highlight justified lines with wide word spaces."
              },
              "looseLineThreshold": {
                "type": "number",
                "minimum": 1,
                "maximum": 5,
                "description": "How wide the spaces are, as a multiple of the normal space, before a line is highlighted."
              },
              "pageNegative": {
                "type": "boolean",
                "description": "Pages light on dark."
              },
              "cursorSync": {
                "type": "boolean",
                "description": "Show the editor's caret on the page."
              },
              "selectionSync": {
                "type": "boolean",
                "description": "Show the editor's selection on the page."
              }
            },
            "additionalProperties": false
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_go_to_pageAction

    Show a page of the book in the viewer on screen: the next or previous one, the first or the last, a page by the number printed on it or by its position in a chapter, the first page of a chapter, the page where a passage of the text is set (which also places the selection there when the Manuscript panel is open), or the page where a resource, a heading's id, an anchor or a footnote's note is set (anchor: where a link to it leads). The EPUB reader goes by its own file: position is a document of its reading order (a page, in the fixed layout), contents an entry of its table of contents. Give one way of naming the page per call.

    View tool JSON
    {
      "name": "sandbox_go_to_page",
      "kind": "act",
      "impl": "imperative",
      "description": "Show a page of the book in the viewer on screen: the next or previous one, the first or the last, a page by the number printed on it or by its position in a chapter, the first page of a chapter, the page where a passage of the text is set (which also places the selection there when the Manuscript panel is open), or the page where a resource, a heading's id, an anchor or a footnote's note is set (anchor: where a link to it leads). The EPUB reader goes by its own file: position is a document of its reading order (a page, in the fixed layout), contents an entry of its table of contents. Give one way of naming the page per call.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "step": {
            "type": "string",
            "enum": [
              "next",
              "previous",
              "first",
              "last"
            ],
            "description": "Turn one page (or spread, column or EPUB document) forward or back, or go to the first or the last page of what the viewer shows."
          },
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter: its position in the book (from 1), its title or its id. The chapter on screen when left out."
          },
          "page": {
            "type": "integer",
            "description": "The page number as printed on the page and shown in the viewer's page field."
          },
          "position": {
            "type": "integer",
            "minimum": 1,
            "description": "The page by its position among the chapter's pages (from 1); for pages whose number repeats or that carry none. In the EPUB viewer: the document of the reading order (from 1), as its page field takes it."
          },
          "text": {
            "type": "string",
            "description": "Go to where this passage of the Markdown source is set."
          },
          "anchor": {
            "type": "string",
            "description": "Go to where this id is set: a resource placed in the text (::resource{id=\"…\"}), a heading or anchor id ({#id}), or a footnote ([^id]). Looked for in the chapter named, or else in the chapter on screen and then in the others that mention it."
          },
          "contents": {
            "type": "string",
            "description": "EPUB viewer: go to the entry of the table of contents with this title (or this href, as the status lists them)."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_run_viewerAction

    Press a button of a viewer's toolbar, or play a video on its pages. regenerate lays the pages of the Canvas, Folio or HTML viewer out again, or writes the PDF, the EPUB or the SCORM package again, and waits for it: the answer carries the viewer's status (pages, file size, an EPUB's warnings). print opens the browser's print dialog on the PDF on screen, for the reader to confirm. download saves the PDF or EPUB on screen through the browser, as it is, even when the book has changed since (sandbox_export writes a fresh file and can hand its bytes back). On the SCORM tab, download writes the package of the chapters and sections ticked and saves it. play_video plays a video of the pages in the Folio (on the open spread) or the HTML viewer, as a click on it does: the one of a resource, on a page or at a point, or the first one on show; stop_video stops them. A viewer other than the one on screen is switched to first. sandbox_set_view changes a viewer's settings; sandbox_go_to_page turns its pages.

    View tool JSON
    {
      "name": "sandbox_run_viewer",
      "kind": "act",
      "impl": "imperative",
      "description": "Press a button of a viewer's toolbar, or play a video on its pages. regenerate lays the pages of the Canvas, Folio or HTML viewer out again, or writes the PDF, the EPUB or the SCORM package again, and waits for it: the answer carries the viewer's status (pages, file size, an EPUB's warnings). print opens the browser's print dialog on the PDF on screen, for the reader to confirm. download saves the PDF or EPUB on screen through the browser, as it is, even when the book has changed since (sandbox_export writes a fresh file and can hand its bytes back). On the SCORM tab, download writes the package of the chapters and sections ticked and saves it. play_video plays a video of the pages in the Folio (on the open spread) or the HTML viewer, as a click on it does: the one of a resource, on a page or at a point, or the first one on show; stop_video stops them. A viewer other than the one on screen is switched to first. sandbox_set_view changes a viewer's settings; sandbox_go_to_page turns its pages.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "viewer": {
            "type": "string",
            "enum": [
              "canvas",
              "pdf",
              "folio",
              "html",
              "epub",
              "scorm"
            ],
            "description": "The viewer tab to act in; the one on screen when left out. Another one is switched to."
          },
          "action": {
            "type": "string",
            "enum": [
              "regenerate",
              "print",
              "download",
              "play_video",
              "stop_video"
            ],
            "description": "regenerate: every viewer. print: pdf. download: pdf, epub, scorm. play_video, stop_video: folio, html."
          },
          "wait": {
            "type": "boolean",
            "description": "regenerate: wait until the pages are laid out or the file is written (default true; a PDF or an EPUB of a long book takes minutes). false answers at once, with the status as the work starts."
          },
          "resource": {
            "type": "string",
            "description": "play_video: the id of the video resource to play."
          },
          "page": {
            "type": "integer",
            "description": "play_video: the page the video is on, by the number printed on it."
          },
          "x": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "play_video: with y, a point on the video, as fractions of its page (as bound, without the margin of bleed) from the top left corner."
          },
          "y": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": [
          "action"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_list_resourcesAnswer

    The pictures, diagrams, tables, videos and music examples of the book, which the text places with ::resource{id="…"} and cites with :ref{id="…"}: each one's id, kind, type, caption, size and how often the text uses it. With an id: that resource in full — its record (a table's cells with their formatting under resource.table.model.rows, which sandbox_save_resource takes back as table.cells; a picture's marks; a video's source and player), the source of an SVG and what became of the fonts its text names, the texts of a table's cells as rows.

    View tool JSON
    {
      "name": "sandbox_list_resources",
      "kind": "answer",
      "impl": "imperative",
      "description": "The pictures, diagrams, tables, videos and music examples of the book, which the text places with ::resource{id=\"…\"} and cites with :ref{id=\"…\"}: each one's id, kind, type, caption, size and how often the text uses it. With an id: that resource in full — its record (a table's cells with their formatting under resource.table.model.rows, which sandbox_save_resource takes back as table.cells; a picture's marks; a video's source and player), the source of an SVG and what became of the fonts its text names, the texts of a table's cells as rows.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Give this resource in full."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_save_resourceAction

    Add a resource to the book or change one, as the Resources panel does. A new resource takes a picture file (PNG, JPEG, WebP, GIF or SVG, by url or base64), the source of an SVG, a table, a video (a YouTube or Vimeo link, a video file, or the address of one), or a music score (notation in ABC, MusicXML, MEI or Humdrum). An existing id changes what is given and keeps the rest: its content (a replaced picture keeps its declared resolution, its print master and its marks; an edited svg source detaches the print master, which was made for the old drawing), its caption, note, alternative text, type and placement, a bitmap's resolution, an SVG's print master and fonts, a table's cells and style, a picture's safe area and lettering marks, a video's poster, range and player, and its id (newId, which also renames it where the book refers to it). The text places it with ::resource{id="…"}. Answers with the stored record and the pages the book came to.

    View tool JSON
    {
      "name": "sandbox_save_resource",
      "kind": "act",
      "impl": "imperative",
      "description": "Add a resource to the book or change one, as the Resources panel does. A new resource takes a picture file (PNG, JPEG, WebP, GIF or SVG, by url or base64), the source of an SVG, a table, a video (a YouTube or Vimeo link, a video file, or the address of one), or a music score (notation in ABC, MusicXML, MEI or Humdrum). An existing id changes what is given and keeps the rest: its content (a replaced picture keeps its declared resolution, its print master and its marks; an edited svg source detaches the print master, which was made for the old drawing), its caption, note, alternative text, type and placement, a bitmap's resolution, an SVG's print master and fonts, a table's cells and style, a picture's safe area and lettering marks, a video's poster, range and player, and its id (newId, which also renames it where the book refers to it). The text places it with ::resource{id=\"…\"}. Answers with the stored record and the pages the book came to.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The resource to change, or the id to give a new one (letters, digits, hyphens). A new resource without one is named after its file or caption."
          },
          "newId": {
            "type": "string",
            "description": "Another id for the resource named by id (letters, digits, hyphens; it is written as a slug)."
          },
          "updateReferences": {
            "type": "boolean",
            "description": "With newId: also rewrite the id where the book refers to it — ::resource, :ref and \\ref marks and comic panels (art=) in every chapter, :ref marks in the other resources' captions, notes and table cells, and the table cells that show it (default true). The Resources panel renames without it. Settings of the design that name the id are listed in the answer, not changed."
          },
          "type": {
            "type": "string",
            "description": "The resource type id (figure, table, video, or one the book defines); it decides the numbering and the caption label."
          },
          "caption": {
            "type": "string"
          },
          "note": {
            "type": "string",
            "description": "A note set under the caption (a source, a credit)."
          },
          "altText": {
            "type": "string",
            "description": "What the picture shows, for readers who cannot see it."
          },
          "image": {
            "type": "object",
            "description": "A picture file (PNG, JPEG, WebP, GIF or SVG): where to fetch it (url) or its bytes (base64).",
            "properties": {
              "url": {
                "type": "string",
                "description": "An http(s) or data: URL the page can fetch."
              },
              "base64": {
                "type": "string",
                "description": "The bytes, base64-encoded."
              },
              "mimeType": {
                "type": "string",
                "description": "Its media type, e.g. image/png. Read from the response or the file name when left out."
              },
              "fileName": {
                "type": "string",
                "description": "Its file name, with its extension."
              }
            },
            "additionalProperties": false
          },
          "svg": {
            "type": "string",
            "description": "The source of an SVG drawing. On an SVG resource it is an edit of its source."
          },
          "table": {
            "type": "object",
            "description": "A table. Its content as rows of cell texts, as tsv text, or as cells (the rows of cell objects sandbox_list_resources gives for a table under resource.table.model.rows, which is the way to set formatting: merges, header cells, alignment, fills, pictures). rows and tsv on a table that exists change its texts and its size and keep the formatting of the cells that stay; cells restates the table. Without content, the other members change the table as it is.",
            "properties": {
              "rows": {
                "type": "array",
                "description": "Rows of cell texts (Markdown inline marks allowed).",
                "items": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              },
              "tsv": {
                "type": "string",
                "description": "Tab-separated values, one row per line."
              },
              "cells": {
                "type": "array",
                "description": "Rows of cells, every row with a cell for every column.",
                "items": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "content": {
                        "type": "string",
                        "description": "The cell's text (Markdown inline marks allowed; a newline or \\\\ starts a new paragraph)."
                      },
                      "isHeader": {
                        "type": "boolean",
                        "description": "A header cell: of a header row, or of a header column."
                      },
                      "colSpan": {
                        "type": "integer",
                        "minimum": 1,
                        "description": "Columns this cell takes, merged to its right. The cells it covers stay in their rows (they are hidden)."
                      },
                      "rowSpan": {
                        "type": "integer",
                        "minimum": 1,
                        "description": "Rows this cell takes, merged downwards."
                      },
                      "align": {
                        "type": "string",
                        "enum": [
                          "left",
                          "center",
                          "right",
                          "start",
                          "end"
                        ]
                      },
                      "verticalAlign": {
                        "type": "string",
                        "enum": [
                          "top",
                          "middle",
                          "bottom"
                        ]
                      },
                      "background": {
                        "type": [
                          "string",
                          "object"
                        ],
                        "description": "The cell's fill: a hex colour (\"#f4e9d8\"), or { hex, model, paletteId } as the design stores a colour; { paletteId } alone follows that colour of the palette."
                      },
                      "image": {
                        "type": "object",
                        "description": "A picture set in the cell above its text: a bitmap or SVG resource of the book.",
                        "properties": {
                          "resourceId": {
                            "type": "string"
                          },
                          "width": {
                            "type": "number",
                            "description": "The share of the cell's inner width it takes, above 0 and up to 1 (default 1)."
                          }
                        },
                        "required": [
                          "resourceId"
                        ],
                        "additionalProperties": false
                      },
                      "hiddenBy": {
                        "type": "object",
                        "properties": {
                          "row": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "col": {
                            "type": "integer",
                            "minimum": 0
                          }
                        },
                        "required": [
                          "row",
                          "col"
                        ],
                        "additionalProperties": false,
                        "description": "As read back from a merged table: the merged cell (row and col from 0) that covers this one. It may be left out; colSpan and rowSpan decide."
                      }
                    },
                    "additionalProperties": false
                  }
                }
              },
              "headerRows": {
                "type": "integer",
                "minimum": 0,
                "description": "Rows at the top that are headers, repeated when the table continues on another page. A new table from rows or tsv has 1; one from cells, its leading rows of header cells."
              },
              "headerColumns": {
                "type": "integer",
                "minimum": 0,
                "description": "Columns at the start whose cells are headers; the cells of the other columns then are not (header rows aside)."
              },
              "columnWidths": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "Relative widths, one per column ([2, 1, 1] gives the first column half the table). null: equal widths.",
                "items": {
                  "type": "number"
                }
              },
              "style": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The id of one of the book's named table styles (the tableStyles setting). null: the document's table style."
              },
              "direction": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "ltr",
                  "rtl",
                  null
                ],
                "description": "The direction the table runs in when it is not the document's. null: with the document."
              }
            },
            "additionalProperties": false
          },
          "video": {
            "type": "object",
            "description": "A video: a new video resource, or changes to the one named by id. It is printed as its poster (with a QR code or a link, as the book's Video style says) and played by the HTML, EPUB and Folio outputs.",
            "properties": {
              "source": {
                "type": "string",
                "enum": [
                  "youtube",
                  "vimeo",
                  "file"
                ],
                "description": "Where it plays from: a YouTube or Vimeo page, or a self-hosted file (an uploaded file, or one at a web address). Read from url or file when left out. Changing it drops the link or the file of the other source."
              },
              "url": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "YouTube or Vimeo: the video's link (a watch, short or embed link); a new video's poster, frame size and title are fetched from the platform. A self-hosted file: its production address, where the published book finds it; without a file it is the source itself (an MP4 or WebM on a server, or an .m3u8 HLS stream). null removes it."
              },
              "file": {
                "type": "object",
                "description": "A video file (MP4, WebM, OGV or MOV) stored in the book, by url or base64: its frame size, length and a first poster are read from it.",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "An http(s) or data: URL the page can fetch."
                  },
                  "base64": {
                    "type": "string",
                    "description": "The bytes, base64-encoded."
                  },
                  "mimeType": {
                    "type": "string",
                    "description": "Its media type, e.g. image/png. Read from the response or the file name when left out."
                  },
                  "fileName": {
                    "type": "string",
                    "description": "Its file name, with its extension."
                  }
                },
                "additionalProperties": false
              },
              "poster": {
                "type": "object",
                "description": "A picture (PNG, JPEG, WebP or GIF) to print as the poster in place of a frame.",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "An http(s) or data: URL the page can fetch."
                  },
                  "base64": {
                    "type": "string",
                    "description": "The bytes, base64-encoded."
                  },
                  "mimeType": {
                    "type": "string",
                    "description": "Its media type, e.g. image/png. Read from the response or the file name when left out."
                  },
                  "fileName": {
                    "type": "string",
                    "description": "Its file name, with its extension."
                  }
                },
                "additionalProperties": false
              },
              "posterTime": {
                "type": "number",
                "minimum": 0,
                "description": "A self-hosted video: take the frame at this second as the poster."
              },
              "fetchPoster": {
                "type": "boolean",
                "description": "YouTube or Vimeo: fetch the poster and frame size from the platform again."
              },
              "start": {
                "type": [
                  "number",
                  "null"
                ],
                "minimum": 0,
                "maximum": 86400,
                "description": "Play from this second (the printed link starts there too). null or 0: from the beginning."
              },
              "end": {
                "type": [
                  "number",
                  "null"
                ],
                "minimum": 0,
                "maximum": 86400,
                "description": "Play up to this second. null or 0: to the end."
              },
              "player": {
                "type": "object",
                "description": "This video's player options, over the book's Video style; null leaves an option to the style. A YouTube player honours controls, fullscreen, autoplay, muted, loop and privacy; Vimeo those and playbackRate and pictureInPicture; a self-hosted file all but privacy.",
                "properties": {
                  "controls": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "download": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "fullscreen": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "playbackRate": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "pictureInPicture": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "remotePlayback": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "autoplay": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "muted": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "loop": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "privacy": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "exclusive": {
                    "type": [
                      "boolean",
                      "null"
                    ],
                    "description": "false lets it play alongside the other videos on show."
                  },
                  "preload": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "none",
                      "metadata",
                      "auto",
                      null
                    ]
                  }
                },
                "additionalProperties": false
              }
            },
            "additionalProperties": false
          },
          "score": {
            "type": "object",
            "description": "A music example (#1172): its notation, typed (source and format) or read from a file (.abc, .musicxml, .mei, .krn), and the named score style it is set in. A new score gets the Example type unless \"type\" names another. On a score resource, what is given changes and the rest is kept.",
            "properties": {
              "format": {
                "type": "string",
                "enum": [
                  "abc",
                  "musicxml",
                  "mei",
                  "humdrum"
                ],
                "description": "The notation format (read from the file name when a file is given)."
              },
              "source": {
                "type": "string",
                "description": "The notation."
              },
              "file": {
                "type": "object",
                "description": "A notation file whose text becomes the source: where to fetch it (url) or its bytes (base64).",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "An http(s) or data: URL the page can fetch."
                  },
                  "base64": {
                    "type": "string",
                    "description": "The bytes, base64-encoded."
                  },
                  "mimeType": {
                    "type": "string",
                    "description": "Its media type, e.g. image/png. Read from the response or the file name when left out."
                  },
                  "fileName": {
                    "type": "string",
                    "description": "Its file name, with its extension."
                  }
                },
                "additionalProperties": false
              },
              "styleId": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "A score style of the book (scoreStyles); null sets it in the document score style."
              }
            },
            "additionalProperties": false
          },
          "placement": {
            "type": "object",
            "description": "Where it goes on the page, merged into its placement key by key. A key set to null goes back to its resource type's default.",
            "properties": {
              "position": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "auto",
                  "top",
                  "bottom",
                  "here",
                  null
                ],
                "description": "A float at the head or the foot of a page or column near its first reference (auto lets the layout choose), or here: set in the text where its ::resource line stands."
              },
              "span": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "column",
                  "page",
                  "side",
                  null
                ],
                "description": "A float as wide as its column, as the page, or in the side column of a column-and-a-half layout."
              },
              "rotate": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "none",
                  "ccw",
                  "cw",
                  null
                ],
                "description": "Turned a quarter turn on a page of its own (a landscape table in a portrait book)."
              },
              "width": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The share of the column (or page) it takes, above 0 and up to 1."
              },
              "align": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "left",
                  "center",
                  "right",
                  "start",
                  "end",
                  null
                ],
                "description": "Where a resource narrower than its slot sits."
              },
              "columns": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 1,
                "description": "How many adjacent columns a column float takes."
              },
              "citingPage": {
                "type": [
                  "boolean",
                  "null"
                ],
                "description": "Head the page or column where the line that first cites it lands."
              },
              "captionSide": {
                "type": [
                  "boolean",
                  "string",
                  "null"
                ],
                "enum": [
                  true,
                  false,
                  "inside",
                  null
                ],
                "description": "Set the caption beside it: true puts it in the side column of a column-and-a-half layout; \"inside\" sets it beside a picture within the picture's own slot, the picture taking width of the slot (0.5 by default)."
              },
              "wrap": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "none",
                  "left",
                  "right",
                  "start",
                  "end",
                  "contour",
                  null
                ],
                "description": "Run the text beside it, at this side of its column; \"contour\" runs it round the picture's own shape (its alpha channel, or a polygon in the record's contour.points, set through fields), at the side its align names."
              },
              "wrapGap": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "The space between it and the text beside it, as { value, unit }."
              },
              "shrink": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "never",
                  "page",
                  "slot",
                  null
                ],
                "description": "Scale a floated picture down to the room of its slot instead of moving it on."
              },
              "minScale": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The smallest scale shrink sets it at, above 0 and up to 1."
              },
              "captionMeasure": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "slot",
                  "body",
                  null
                ],
                "description": "A narrower picture's caption at the slot's measure, or as wide as the picture."
              }
            },
            "additionalProperties": false
          },
          "resolution": {
            "type": [
              "number",
              "string",
              "null"
            ],
            "description": "A bitmap's resolution in pixels per inch, which sets its natural print size: a number (1 to 4800), \"file\" for the one its file states, or null to leave it to the book's layout.bitmapResolution setting."
          },
          "embedFonts": {
            "type": "boolean",
            "description": "An SVG: embed the fonts its text names when the picture is shown or exported, as the book's diagramStyle.inlineFonts says (true, the default), or keep its markup as it is (false)."
          },
          "printMaster": {
            "type": [
              "object",
              "null"
            ],
            "description": "An SVG's print master: a single-page PDF of the same figure, which the PDF export embeds in place of the SVG (url or base64). null removes it.",
            "properties": {
              "url": {
                "type": "string",
                "description": "An http(s) or data: URL the page can fetch."
              },
              "base64": {
                "type": "string",
                "description": "The bytes, base64-encoded."
              },
              "mimeType": {
                "type": "string",
                "description": "Its media type, e.g. image/png. Read from the response or the file name when left out."
              },
              "fileName": {
                "type": "string",
                "description": "Its file name, with its extension."
              }
            },
            "additionalProperties": false
          },
          "marks": {
            "type": "object",
            "description": "The marks drawn over a picture, in fractions of it (0 to 1 from its top left corner; a rectangle is { x, y, width, height }). Each member given replaces that kind of mark whole, null removes it, one left out stays.",
            "properties": {
              "safeArea": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "x": {
                    "type": "number"
                  },
                  "y": {
                    "type": "number"
                  },
                  "width": {
                    "type": "number"
                  },
                  "height": {
                    "type": "number"
                  }
                },
                "required": [
                  "x",
                  "y",
                  "width",
                  "height"
                ],
                "additionalProperties": false,
                "description": "The part of the picture that must stay in view: the layout may crop what lies outside it to fit the page. null: the picture always shows whole. For a bitmap, an SVG or a video's poster."
              },
              "anchors": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "The named points of the picture. For a map or a diagram, the anchors its labels stand at: a :::figure{resource=\"…\"} sets ::label[TEXT]{at=\"id\"} at the anchor with that id, and the anchor's label fields (style, align, verticalAlign, rotate, width, writingMode, overlap) are what such a label takes unless it says otherwise. For a comic panel, the speakers: id is the key the script names (as in \"ana: Hello\"), x and y the mouth a speech balloon's tail points at, and optionally head (where a thought balloon points) and face (a rectangle no balloon covers).",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "x": {
                      "type": "number"
                    },
                    "y": {
                      "type": "number"
                    },
                    "head": {
                      "type": "object",
                      "properties": {
                        "x": {
                          "type": "number"
                        },
                        "y": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "x",
                        "y"
                      ],
                      "additionalProperties": false
                    },
                    "face": {
                      "type": "object",
                      "properties": {
                        "x": {
                          "type": "number"
                        },
                        "y": {
                          "type": "number"
                        },
                        "width": {
                          "type": "number"
                        },
                        "height": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "x",
                        "y",
                        "width",
                        "height"
                      ],
                      "additionalProperties": false
                    },
                    "style": {
                      "type": "string",
                      "description": "A label style id of the design (labelStyles) for the label set here."
                    },
                    "align": {
                      "type": "string",
                      "enum": [
                        "start",
                        "center",
                        "end"
                      ],
                      "description": "Which side of the label stands at the point, in the label's direction (default center)."
                    },
                    "verticalAlign": {
                      "type": "string",
                      "enum": [
                        "top",
                        "middle",
                        "bottom"
                      ],
                      "description": "Which edge of the label stands at the point (default middle)."
                    },
                    "rotate": {
                      "type": "number",
                      "description": "Degrees, clockwise, about the point (default 0)."
                    },
                    "width": {
                      "type": "number",
                      "description": "The label's measure as a fraction of the picture's width (0 to 1; of its height for a vertical label); the label wraps within it. Unset: its natural width."
                    },
                    "writingMode": {
                      "type": "string",
                      "enum": [
                        "horizontal-tb",
                        "vertical-rl"
                      ],
                      "description": "vertical-rl sets the label in vertical writing, characters upright in columns from right to left (default horizontal-tb)."
                    },
                    "overlap": {
                      "type": "string",
                      "enum": [
                        "check",
                        "allow"
                      ],
                      "description": "allow leaves the label set here out of the labelOverlap check: the source prints it touching its neighbours (a dense map). Default check."
                    },
                    "gutter": {
                      "type": "string",
                      "enum": [
                        "keep",
                        "cross"
                      ],
                      "description": "On a figure across the spine of a spread: keep slides the label off the binding band, to the side its point lies on (default); cross leaves it where the point puts it, a title set across both pages."
                    },
                    "labelAt": {
                      "type": "object",
                      "properties": {
                        "x": {
                          "type": "number"
                        },
                        "y": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "x",
                        "y"
                      ],
                      "additionalProperties": false,
                      "description": "Where the label set here stands, away from its point (fractions of the picture): align, verticalAlign and rotate place the label about this point; a leader and a pointer still end at x, y. Unset: the label stands at its point."
                    },
                    "leader": {
                      "type": [
                        "boolean",
                        "object"
                      ],
                      "description": "A line from the label to its point: true in the label style's leader look, an object over that look field by field, false none. Unset: a leader when the label stands away (labelAt) and its style has a leader. A label's own leader attribute (sandbox_edit_labels) wins.",
                      "properties": {
                        "color": {
                          "description": "A colour value ({ hex, model } or a palette link), default the label's text colour."
                        },
                        "width": {
                          "description": "A length ({ value, unit }), default 0.75pt."
                        },
                        "dash": {
                          "type": "array",
                          "description": "Dash lengths (on, off, …)."
                        },
                        "startCap": {
                          "type": "string",
                          "enum": [
                            "none",
                            "dot",
                            "arrow"
                          ]
                        },
                        "endCap": {
                          "type": "string",
                          "enum": [
                            "none",
                            "dot",
                            "arrow"
                          ]
                        },
                        "capSize": {
                          "description": "A length, default three times the width."
                        },
                        "routing": {
                          "type": "string",
                          "enum": [
                            "straight",
                            "elbow"
                          ]
                        }
                      },
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "x",
                    "y"
                  ],
                  "additionalProperties": false
                }
              },
              "avoid": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "Zones of a comic panel's picture the balloons keep clear of (a hand, a key object).",
                "items": {
                  "type": "object",
                  "properties": {
                    "x": {
                      "type": "number"
                    },
                    "y": {
                      "type": "number"
                    },
                    "width": {
                      "type": "number"
                    },
                    "height": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "x",
                    "y",
                    "width",
                    "height"
                  ],
                  "additionalProperties": false
                }
              },
              "svgSymbols": {
                "type": "object",
                "description": "For an SVG map: add an avoid zone over each element of the drawing named by idPrefix (its id starts with it) or className (its class list holds it) — the dots and icons labels should keep clear of. The zones already there stay; ones that cover an old zone are not added twice. Measured in the browser, as the marks dialog does.",
                "properties": {
                  "idPrefix": {
                    "type": "string"
                  },
                  "className": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              },
              "faces": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "The faces of people in a comic panel's picture who do not speak: no balloon covers them.",
                "items": {
                  "type": "object",
                  "properties": {
                    "x": {
                      "type": "number"
                    },
                    "y": {
                      "type": "number"
                    },
                    "width": {
                      "type": "number"
                    },
                    "height": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "x",
                    "y",
                    "width",
                    "height"
                  ],
                  "additionalProperties": false
                }
              }
            },
            "additionalProperties": false
          },
          "fields": {
            "type": "object",
            "description": "Any other fields of the resource record, merged in member by member (objects merge, null removes a member, anything else replaces): one field of bitmap, svg, video or table can be set without restating the rest. Not checked; id, kind and createdAt are never changed."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again (default true)."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_delete_resourceSensitive Action

    Delete a resource and its file from the book. It cannot be undone; places in the text that use it are left pointing at nothing and show up as warnings.

    View tool JSON
    {
      "name": "sandbox_delete_resource",
      "kind": "transact",
      "impl": "imperative",
      "description": "Delete a resource and its file from the book. It cannot be undone; places in the text that use it are left pointing at nothing and show up as warnings.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again (default true)."
          }
        },
        "required": [
          "id"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_list_fontsAction

    The font families the book sets its text in — each with what it sets (body, headings, other) and where it comes from: custom (files uploaded into the book), google or fontsource (the open-font catalogue), or missing (no service has it, or its files were removed) —, the families uploaded into the book with their faces (weight, style, file), and, with search, families of the catalogue whose name matches. A family is put to use by writing its name into a fontFamily setting (bodyText.fontFamily, a heading style's, a paragraph style's) with sandbox_set_config; catalogue families load on demand.

    View tool JSON
    {
      "name": "sandbox_list_fonts",
      "kind": "act",
      "impl": "imperative",
      "description": "The font families the book sets its text in — each with what it sets (body, headings, other) and where it comes from: custom (files uploaded into the book), google or fontsource (the open-font catalogue), or missing (no service has it, or its files were removed) —, the families uploaded into the book with their faces (weight, style, file), and, with search, families of the catalogue whose name matches. A family is put to use by writing its name into a fontFamily setting (bodyText.fontFamily, a heading style's, a paragraph style's) with sandbox_set_config; catalogue families load on demand.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "search": {
            "type": "string",
            "description": "Part of a family name to look up in the catalogue."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_save_fontSensitive Action

    The book's own fonts, as the Fonts panel keeps them. add: upload a font file (WOFF2, WOFF, TTF or OTF, by url or base64) as one face — a weight and a style — of a custom family; a face of that weight and style already there is replaced, and the answer says so. update_face: give a face another weight or style. rename_family: give a family another name; the fontFamily settings that name the old one are listed, not changed. remove: take away a family, or its faces of a weight, a style or a file name. remove_all: take away every custom font. A removed face's file is deleted and cannot be brought back. A family's name is used like any other in a fontFamily setting, and travels with the book in its .postext file.

    View tool JSON
    {
      "name": "sandbox_save_font",
      "kind": "transact",
      "impl": "imperative",
      "description": "The book's own fonts, as the Fonts panel keeps them. add: upload a font file (WOFF2, WOFF, TTF or OTF, by url or base64) as one face — a weight and a style — of a custom family; a face of that weight and style already there is replaced, and the answer says so. update_face: give a face another weight or style. rename_family: give a family another name; the fontFamily settings that name the old one are listed, not changed. remove: take away a family, or its faces of a weight, a style or a file name. remove_all: take away every custom font. A removed face's file is deleted and cannot be brought back. A family's name is used like any other in a fontFamily setting, and travels with the book in its .postext file.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "add",
              "update_face",
              "rename_family",
              "remove",
              "remove_all"
            ]
          },
          "family": {
            "type": "string",
            "description": "The family name (every action but remove_all)."
          },
          "weight": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000,
            "description": "add: the face's weight (default 400). update_face, remove: the faces of this weight."
          },
          "style": {
            "type": "string",
            "enum": [
              "normal",
              "italic"
            ],
            "description": "add: the face's style (default normal). update_face, remove: the faces of this style."
          },
          "fileName": {
            "type": "string",
            "description": "update_face, remove: the face uploaded under this file name, as sandbox_list_fonts gives it."
          },
          "file": {
            "type": "object",
            "description": "A file: where to fetch it (url) or its bytes (base64).",
            "properties": {
              "url": {
                "type": "string",
                "description": "An http(s) or data: URL the page can fetch."
              },
              "base64": {
                "type": "string",
                "description": "The bytes, base64-encoded."
              },
              "mimeType": {
                "type": "string",
                "description": "Its media type, e.g. image/png. Read from the response or the file name when left out."
              },
              "fileName": {
                "type": "string",
                "description": "Its file name, with its extension."
              }
            },
            "additionalProperties": false
          },
          "newFamily": {
            "type": "string",
            "description": "rename_family: the family's new name."
          },
          "newWeight": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000,
            "description": "update_face: the weight the face is declared at."
          },
          "newStyle": {
            "type": "string",
            "enum": [
              "normal",
              "italic"
            ],
            "description": "update_face: the style the face is declared as."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again (default true)."
          }
        },
        "required": [
          "action"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_inspect_comicAnswer

    The comic pages and strips of a chapter (:::page and :::strip blocks) as data: where their panels, the split lines between them and their balloons lie on the page, which is what a person grabs with the pointer in the viewers. Without a page or a comic: the chapter's comics, one line each (number, first source line, pages, split, how many panels, split lines and balloons). With page, position or comic: each comic in full, with every panel (its box, its picture, whether it can be split or merged with the next), every split line (where it is, the range it may move in) and every balloon, caption and sound effect (its script line and line number, kind, speaker, box, pin, tail, rotation). Their numbers, from 1, are the ones sandbox_edit_comic takes. Spaces: box, picture, frame, outline, from, to and tail.tip are fractions of the page from its top left corner, as the crop of sandbox_render_page (a box can be handed to it as it is); picture is where a panel's whole picture lies, past the panel where it is cropped; inComic is a panel's box in fractions of the comic's frame; a split line's start, end and range are percent of the cell it cuts, as the fence's split writes them (from the top for axis "rows", from the side the page is read from for "columns"); a balloon's centre, at and tail.to are percent of its panel's picture as stored (of the panel's box when it has no picture), as the script writes at="x% y%". It waits for the layout to follow the last change. sandbox_inspect_pages puts the rest of a page into words; sandbox_read_text gives the script.

    View tool JSON
    {
      "name": "sandbox_inspect_comic",
      "kind": "answer",
      "impl": "imperative",
      "description": "The comic pages and strips of a chapter (:::page and :::strip blocks) as data: where their panels, the split lines between them and their balloons lie on the page, which is what a person grabs with the pointer in the viewers. Without a page or a comic: the chapter's comics, one line each (number, first source line, pages, split, how many panels, split lines and balloons). With page, position or comic: each comic in full, with every panel (its box, its picture, whether it can be split or merged with the next), every split line (where it is, the range it may move in) and every balloon, caption and sound effect (its script line and line number, kind, speaker, box, pin, tail, rotation). Their numbers, from 1, are the ones sandbox_edit_comic takes. Spaces: box, picture, frame, outline, from, to and tail.tip are fractions of the page from its top left corner, as the crop of sandbox_render_page (a box can be handed to it as it is); picture is where a panel's whole picture lies, past the panel where it is cropped; inComic is a panel's box in fractions of the comic's frame; a split line's start, end and range are percent of the cell it cuts, as the fence's split writes them (from the top for axis \"rows\", from the side the page is read from for \"columns\"); a balloon's centre, at and tail.to are percent of its panel's picture as stored (of the panel's box when it has no picture), as the script writes at=\"x% y%\". It waits for the layout to follow the last change. sandbox_inspect_pages puts the rest of a page into words; sandbox_read_text gives the script.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter: its position in the book (from 1), its title or its id. The chapter the reader is at when left out."
          },
          "page": {
            "type": "integer",
            "description": "The comics on the page with this number, as printed on the page."
          },
          "position": {
            "type": "integer",
            "minimum": 1,
            "description": "The comics on the page at this position among the chapter's pages (from 1)."
          },
          "comic": {
            "type": "integer",
            "minimum": 1,
            "description": "One comic by its number in the chapter (from 1), whatever page it is on."
          },
          "textLength": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2000,
            "description": "Characters of each balloon's script line to give (default 160)."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_edit_comicAction

    One edit of a comic page or strip, as a person makes it with the pointer in the viewers: it is written into the chapter's source (the fence's split, an attribute of a script line) and the reader can undo it with Ctrl/Cmd+Z over the pages. The comic and its panel, split line or balloon are named by their numbers in sandbox_inspect_comic. Actions: move_splitter moves a split line to start, in percent of the cell it cuts (the line keeps its slant), or each of its ends with end too (a slanted line), within the range that leaves every cell 5 %; split_panel cuts a panel in two (direction "rows": one above the other; "columns": side by side) and adds an empty ::panel after it; merge_panel merges a panel with the next one of its row or column, keeping the first one's picture and both scripts; move_balloon pins a balloon with its centre at a point (at="x% y%" on its line), kept inside its panel, and balloons joined in one outline move together, the pin written on the first; unpin_balloon takes the pin off, so the engine places the balloon again; rotate turns a sound effect to degrees (clockwise, 0 upright); move_tail points a balloon's tail at a point (to="x% y%"); reset_tail points it back at its speaker. A point (at, to) is in percent of the panel's picture as the script writes it (0 0 its top left corner, 100 100 its bottom right; of the panel's box when it has no picture) or, with space "page", in fractions of the page from its top left corner, as read off a picture from sandbox_render_page. It answers with the source lines as they are now, the position written, clamped when it was held back, issues when a balloon lands on a face or on a part of the picture kept clear or runs out of its panel, letterboxed with the panels whose picture no longer fills its cell with the line there, and the pages the book came to. Nothing is written when the comic already is as asked (changed: false). To rewrite the script or the split by hand, sandbox_edit_text.

    View tool JSON
    {
      "name": "sandbox_edit_comic",
      "kind": "act",
      "impl": "imperative",
      "description": "One edit of a comic page or strip, as a person makes it with the pointer in the viewers: it is written into the chapter's source (the fence's split, an attribute of a script line) and the reader can undo it with Ctrl/Cmd+Z over the pages. The comic and its panel, split line or balloon are named by their numbers in sandbox_inspect_comic. Actions: move_splitter moves a split line to start, in percent of the cell it cuts (the line keeps its slant), or each of its ends with end too (a slanted line), within the range that leaves every cell 5 %; split_panel cuts a panel in two (direction \"rows\": one above the other; \"columns\": side by side) and adds an empty ::panel after it; merge_panel merges a panel with the next one of its row or column, keeping the first one's picture and both scripts; move_balloon pins a balloon with its centre at a point (at=\"x% y%\" on its line), kept inside its panel, and balloons joined in one outline move together, the pin written on the first; unpin_balloon takes the pin off, so the engine places the balloon again; rotate turns a sound effect to degrees (clockwise, 0 upright); move_tail points a balloon's tail at a point (to=\"x% y%\"); reset_tail points it back at its speaker. A point (at, to) is in percent of the panel's picture as the script writes it (0 0 its top left corner, 100 100 its bottom right; of the panel's box when it has no picture) or, with space \"page\", in fractions of the page from its top left corner, as read off a picture from sandbox_render_page. It answers with the source lines as they are now, the position written, clamped when it was held back, issues when a balloon lands on a face or on a part of the picture kept clear or runs out of its panel, letterboxed with the panels whose picture no longer fills its cell with the line there, and the pages the book came to. Nothing is written when the comic already is as asked (changed: false). To rewrite the script or the split by hand, sandbox_edit_text.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter: its position in the book (from 1), its title or its id. The chapter the reader is at when left out."
          },
          "comic": {
            "type": "integer",
            "minimum": 1,
            "description": "The comic by its number in the chapter (from 1), as sandbox_inspect_comic gives it."
          },
          "action": {
            "type": "string",
            "enum": [
              "move_splitter",
              "split_panel",
              "merge_panel",
              "move_balloon",
              "unpin_balloon",
              "rotate",
              "move_tail",
              "reset_tail"
            ]
          },
          "splitter": {
            "type": "integer",
            "minimum": 1,
            "description": "move_splitter: the split line (from 1)."
          },
          "start": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "move_splitter: where the line goes, in percent of the cell it cuts (its start end, when end is given too)."
          },
          "end": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "move_splitter: where the far end of the line goes, for a slanted line. Left out, the line moves whole and keeps its slant."
          },
          "panel": {
            "type": "integer",
            "minimum": 1,
            "description": "split_panel, merge_panel: the panel (from 1, in reading order)."
          },
          "direction": {
            "type": "string",
            "enum": [
              "rows",
              "columns"
            ],
            "description": "split_panel: \"rows\" cuts with a horizontal line (one panel above the other), \"columns\" with a vertical one."
          },
          "balloon": {
            "type": "integer",
            "minimum": 1,
            "description": "move_balloon, unpin_balloon, rotate, move_tail, reset_tail: the balloon, caption or sound effect (from 1, in reading order)."
          },
          "at": {
            "type": "object",
            "properties": {
              "x": {
                "type": "number"
              },
              "y": {
                "type": "number"
              }
            },
            "required": [
              "x",
              "y"
            ],
            "additionalProperties": false,
            "description": "move_balloon: where the centre of the balloon goes."
          },
          "to": {
            "type": "object",
            "properties": {
              "x": {
                "type": "number"
              },
              "y": {
                "type": "number"
              }
            },
            "required": [
              "x",
              "y"
            ],
            "additionalProperties": false,
            "description": "move_tail: the point the tail aims at."
          },
          "space": {
            "type": "string",
            "enum": [
              "picture",
              "page"
            ],
            "description": "What at and to are measured in: \"picture\" (default), percent of the panel's picture (of its box when it has none); \"page\", fractions (0 to 1) of the page the balloon is on, from its top left corner."
          },
          "degrees": {
            "type": "number",
            "minimum": -360,
            "maximum": 360,
            "description": "rotate: the angle, clockwise."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again and answer with the pages each chapter came to (default true). False answers at once."
          }
        },
        "required": [
          "comic",
          "action"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_list_booksAction

    The books the Sandbox can open: the samples it ships (each in one or more languages; one the reader edited keeps their version, and editedLanguages says in which languages) and the reader's own projects, stored in this browser (cover: true on those with a cover picture; languages on those that keep a book in several languages, language being the one that opens). Says which one is on screen.

    View tool JSON
    {
      "name": "sandbox_list_books",
      "kind": "act",
      "impl": "imperative",
      "description": "The books the Sandbox can open: the samples it ships (each in one or more languages; one the reader edited keeps their version, and editedLanguages says in which languages) and the reader's own projects, stored in this browser (cover: true on those with a cover picture; languages on those that keep a book in several languages, language being the one that opens). Says which one is on screen.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_open_bookAction

    Open another book in the Sandbox: a sample (in one of its languages) or one of the reader's projects. The book on screen is saved first. Answers once the new book is laid out, with its chapters and pages.

    View tool JSON
    {
      "name": "sandbox_open_book",
      "kind": "act",
      "impl": "imperative",
      "description": "Open another book in the Sandbox: a sample (in one of its languages) or one of the reader's projects. The book on screen is saved first. Answers once the new book is laid out, with its chapters and pages.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "sample",
              "project"
            ]
          },
          "id": {
            "type": "string",
            "description": "The id, as sandbox_list_books gives it."
          },
          "language": {
            "type": "string",
            "description": "A sample or project in several languages: the one to open (en, es, zh-Hans…). A sample opens in the language of the interface when left out; a project in the language it was left in."
          }
        },
        "required": [
          "kind",
          "id"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_save_bookSensitive Action

    Make a project — the reader's own book, kept in this browser — or tend the list of books: new_blank starts an empty book; copy_current keeps the book on screen as a new project (how a sample becomes the reader's own); duplicate copies a sample or a project without opening the original (a sample the reader edited is copied with their edits, unless from says original); rename changes a project's name or description (on a book in several languages the name is the book's in every language, unless thisLanguageOnly); add_language adds a language to a project: the edition on screen is copied into a new edition whose document language is the one in the language field, and that edition is opened, still in the old language's words until translated; set_cover gives a project a cover picture and remove_cover takes it away; hide_sample and show_sample take a sample off the list and put it back. A new book is opened at once.

    View tool JSON
    {
      "name": "sandbox_save_book",
      "kind": "transact",
      "impl": "imperative",
      "description": "Make a project — the reader's own book, kept in this browser — or tend the list of books: new_blank starts an empty book; copy_current keeps the book on screen as a new project (how a sample becomes the reader's own); duplicate copies a sample or a project without opening the original (a sample the reader edited is copied with their edits, unless from says original); rename changes a project's name or description (on a book in several languages the name is the book's in every language, unless thisLanguageOnly); add_language adds a language to a project: the edition on screen is copied into a new edition whose document language is the one in the language field, and that edition is opened, still in the old language's words until translated; set_cover gives a project a cover picture and remove_cover takes it away; hide_sample and show_sample take a sample off the list and put it back. A new book is opened at once.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "new_blank",
              "copy_current",
              "duplicate",
              "rename",
              "add_language",
              "set_cover",
              "remove_cover",
              "hide_sample",
              "show_sample"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "sample",
              "project"
            ],
            "description": "duplicate: what the id names."
          },
          "id": {
            "type": "string",
            "description": "duplicate, rename, hide_sample, show_sample: the book. add_language, set_cover, remove_cover: the project (the one on screen when left out)."
          },
          "thisLanguageOnly": {
            "type": "boolean",
            "description": "rename a project in several languages: give the name and description to the language on screen only; the others keep the title they show."
          },
          "language": {
            "type": "string",
            "description": "add_language: the tag of the new language (en, es, fr, zh-Hant, ar…), one the book does not have. duplicate a sample: the language to copy. Left out, the one a click on the sample would open: the one on screen, else the interface language, else the language the reader last edited."
          },
          "from": {
            "type": "string",
            "enum": [
              "edited",
              "original"
            ],
            "description": "duplicate a sample: copy the reader's edited version in that language (edited; refused when there is none) or the sample as it ships (original). Left out, the edited version when there is one, as the Books panel does."
          },
          "name": {
            "type": "string",
            "description": "new_blank, copy_current, rename: the name."
          },
          "description": {
            "type": "string",
            "description": "rename: the description (empty clears it)."
          },
          "file": {
            "type": "object",
            "description": "set_cover: the picture (PNG, JPEG, WebP, GIF or SVG): where to fetch it (url) or its bytes (base64).",
            "properties": {
              "url": {
                "type": "string",
                "description": "An http(s) or data: URL the page can fetch."
              },
              "base64": {
                "type": "string",
                "description": "The bytes, base64-encoded."
              },
              "mimeType": {
                "type": "string",
                "description": "Its media type. Read from the response or the file name when left out."
              },
              "fileName": {
                "type": "string",
                "description": "Its file name, with its extension."
              }
            },
            "additionalProperties": false
          }
        },
        "required": [
          "action"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_delete_bookSensitive Action

    Delete one of the reader's projects from this browser, with its chapters, resources and fonts. It cannot be undone (export it first to keep a copy). A sample cannot be deleted, only hidden.

    View tool JSON
    {
      "name": "sandbox_delete_book",
      "kind": "transact",
      "impl": "imperative",
      "description": "Delete one of the reader's projects from this browser, with its chapters, resources and fonts. It cannot be undone (export it first to keep a copy). A sample cannot be deleted, only hidden.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The project's id."
          }
        },
        "required": [
          "id"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_import_bookSensitive Action

    Import a .postext file (a book with its chapters, design, resources and fonts in one archive) as a new project, and open it. A file may carry the book in several languages: the project keeps every one of them (the checks, the language switcher and the side-by-side view of composed pages work on it), and language says which opens first. inspect: true reads the file and answers with them without importing.

    View tool JSON
    {
      "name": "sandbox_import_book",
      "kind": "transact",
      "impl": "imperative",
      "description": "Import a .postext file (a book with its chapters, design, resources and fonts in one archive) as a new project, and open it. A file may carry the book in several languages: the project keeps every one of them (the checks, the language switcher and the side-by-side view of composed pages work on it), and language says which opens first. inspect: true reads the file and answers with them without importing.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "file": {
            "type": "object",
            "description": "The .postext file: where to fetch it (url) or its bytes (base64).",
            "properties": {
              "url": {
                "type": "string"
              },
              "base64": {
                "type": "string"
              },
              "fileName": {
                "type": "string"
              }
            },
            "additionalProperties": false
          },
          "language": {
            "type": "string",
            "description": "A file in several languages: the one to open first (all are kept). The interface language when left out."
          },
          "inspect": {
            "type": "boolean",
            "description": "Read the file and answer with its name and the languages it carries, without importing it."
          }
        },
        "required": [
          "file"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_exportAction

    Write the book on screen to a file: pdf (the chapter on screen or the whole book, print-ready), epub (reflowable, or fixed to the printed pages), postext (the whole project in one archive, to open again or hand to the postext command line), docx (Word, with a saved Word template when one is named), markdown (the chapter's source) or config (the design settings as JSON). A postext archive can also be written of a book that is not on screen (book): a project as it was last saved, or a sample as it ships, in one of its languages. The file is downloaded by the reader's browser, or — pdf and epub — handed back base64-encoded with deliver: "data". Exporting a pdf or an epub shows that viewer tab.

    View tool JSON
    {
      "name": "sandbox_export",
      "kind": "act",
      "impl": "imperative",
      "description": "Write the book on screen to a file: pdf (the chapter on screen or the whole book, print-ready), epub (reflowable, or fixed to the printed pages), postext (the whole project in one archive, to open again or hand to the postext command line), docx (Word, with a saved Word template when one is named), markdown (the chapter's source) or config (the design settings as JSON). A postext archive can also be written of a book that is not on screen (book): a project as it was last saved, or a sample as it ships, in one of its languages. The file is downloaded by the reader's browser, or — pdf and epub — handed back base64-encoded with deliver: \"data\". Exporting a pdf or an epub shows that viewer tab.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "format": {
            "type": "string",
            "enum": [
              "pdf",
              "epub",
              "postext",
              "docx",
              "markdown",
              "config"
            ]
          },
          "scope": {
            "type": "string",
            "enum": [
              "chapter",
              "book"
            ],
            "description": "pdf, docx: the chapter on screen or the whole book (default: as the PDF tab stands; docx: book)."
          },
          "epubLayout": {
            "type": "string",
            "enum": [
              "reflowable",
              "fixed"
            ],
            "description": "epub: the rendition (default: as the EPUB tab stands)."
          },
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "markdown: the chapter (position from 1, title or id); the one on screen when left out."
          },
          "deliver": {
            "type": "string",
            "enum": [
              "download",
              "data"
            ],
            "description": "download (default) saves the file through the browser; data hands a pdf or an epub back in the result."
          },
          "book": {
            "type": "object",
            "description": "postext: another book than the one on screen, exported without opening it, as its row of the Books panel does. A sample is exported as it ships, not with the reader's edits (open it, or duplicate it, to export those).",
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "sample",
                  "project"
                ]
              },
              "id": {
                "type": "string",
                "description": "The id, as sandbox_list_books gives it."
              },
              "language": {
                "type": "string",
                "description": "A sample in several languages: the one to export. The one on screen when the sample is on screen, else the interface language."
              }
            },
            "required": [
              "kind",
              "id"
            ],
            "additionalProperties": false
          },
          "template": {
            "type": "string",
            "description": "docx: the id of a saved Word template (sandbox_word_templates lists them), whose mapping names the Word styles and travels in the file for the way back, or \"none\". Left out, the template last used when it is still saved, as the export dialog opens."
          }
        },
        "required": [
          "format"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_import_wordAction

    Bring a Word manuscript (.docx) into the book, as the Manuscript panel's Word import does: each Word style becomes a Postext construct (headings, paragraph styles, callouts, quotes, verse, captions; bold, italic, chips…), lists and footnotes are kept, pictures and tables become resources placed where they were. Run it first with dryRun: true — it changes nothing and answers with the quality report of the document, every style it uses with what each would become, the chapters and resources it would make, and the start of the Markdown; then correct what a style becomes with mapping, or the options, and run it for real. destination says where the text goes: chapter replaces a chapter's text (taken back with sandbox_undo_text), append adds new chapters after a chapter, book replaces every chapter of the book, which cannot be undone. Left out, the destination is book for a document the Sandbox exported as a whole book and chapter otherwise. For Markdown text, sandbox_write_text; for a .postext book, sandbox_import_book.

    View tool JSON
    {
      "name": "sandbox_import_word",
      "kind": "act",
      "impl": "imperative",
      "description": "Bring a Word manuscript (.docx) into the book, as the Manuscript panel's Word import does: each Word style becomes a Postext construct (headings, paragraph styles, callouts, quotes, verse, captions; bold, italic, chips…), lists and footnotes are kept, pictures and tables become resources placed where they were. Run it first with dryRun: true — it changes nothing and answers with the quality report of the document, every style it uses with what each would become, the chapters and resources it would make, and the start of the Markdown; then correct what a style becomes with mapping, or the options, and run it for real. destination says where the text goes: chapter replaces a chapter's text (taken back with sandbox_undo_text), append adds new chapters after a chapter, book replaces every chapter of the book, which cannot be undone. Left out, the destination is book for a document the Sandbox exported as a whole book and chapter otherwise. For Markdown text, sandbox_write_text; for a .postext book, sandbox_import_book.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "file": {
            "type": "object",
            "description": "The .docx file: where to fetch it (url) or its bytes (base64). A .doc file must be saved as .docx first.",
            "properties": {
              "url": {
                "type": "string",
                "description": "An http(s) or data: URL the page can fetch."
              },
              "base64": {
                "type": "string",
                "description": "The bytes, base64-encoded."
              },
              "mimeType": {
                "type": "string",
                "description": "Its media type. Read from the response or the file name when left out."
              },
              "fileName": {
                "type": "string",
                "description": "Its file name, with its extension."
              }
            },
            "additionalProperties": false
          },
          "dryRun": {
            "type": "boolean",
            "description": "Change nothing: answer with the report, the mapping of every style, and what the import would make."
          },
          "destination": {
            "type": "string",
            "enum": [
              "chapter",
              "append",
              "book"
            ],
            "description": "chapter: the whole document replaces one chapter's text. append: new chapters after one chapter, a new chapter at every level-1 heading, the first one shown. book: every chapter of the book is replaced, a new chapter at every level-1 heading."
          },
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "chapter, append: the chapter to replace, or the one the new chapters follow (position from 1, title or id). The chapter on screen when left out."
          },
          "template": {
            "type": [
              "string",
              "object"
            ],
            "description": "The mapping to start from: the id of a saved template (sandbox_word_templates lists them), \"embedded\" (the one a .docx exported from the Sandbox carries), \"auto\" (none: every style is guessed from its name and its Word role) or a template object { paragraphs, characters, options }. Left out, as the dialog opens: the embedded one, else the template last used, else auto."
          },
          "mapping": {
            "type": "object",
            "description": "What Word styles become, by style name, on top of the template. paragraphs: { \"<style name>\": { kind, … } } with kind one of body, heading (level 1–6, style: a heading style id), paragraphs (style: a paragraph style id), verse (style optional), callout and calloutTitle (type: a callout type id), quote, caption, chapter (starts a chapter titled with the paragraph), markup (Postext Markdown kept as written) and drop. characters: { \"<style name>\": { kind, … } } with kind one of text, bold, italic, boldItalic, smallCaps, sup, sub, chip (style: a chip style id), markup and drop. The dry run lists the names and what each becomes, in this shape.",
            "properties": {
              "paragraphs": {
                "type": "object"
              },
              "characters": {
                "type": "object"
              }
            },
            "additionalProperties": false
          },
          "lineBreaks": {
            "type": "string",
            "enum": [
              "break",
              "space",
              "paragraph"
            ],
            "description": "Soft returns (Shift+Enter) inside a paragraph: a forced line break (the default), a space, or a new paragraph."
          },
          "directFormatting": {
            "type": "string",
            "enum": [
              "keep",
              "ignore"
            ],
            "description": "Bold, italic, small caps and scripts set by hand on runs: kept (the default) or left out."
          },
          "manualHeadings": {
            "type": "integer",
            "minimum": 0,
            "maximum": 6,
            "description": "Short bold paragraphs in body text (headings typed by hand) become headings of this level; 0 (the default) keeps them as paragraphs."
          },
          "pageBreaks": {
            "type": "string",
            "enum": [
              "drop",
              "keep"
            ],
            "description": "Page breaks typed in Word: dropped (the default; the design decides where pages turn) or kept as :::pagebreak."
          },
          "images": {
            "type": "boolean",
            "description": "Pictures become resources placed where they were (default true)."
          },
          "tables": {
            "type": "boolean",
            "description": "Tables become table resources placed where they were (default true)."
          },
          "characterSpacing": {
            "type": "boolean",
            "description": "The character spacing (letter-spacing) of the Word styles in use is put, in em, on the book's paragraph styles, heading styles, heading levels and callout titles they map to, where the book sets none (what it sets itself stays). Default true when there is something to put; the dry run lists it under characterSpacing."
          },
          "saveTemplateAs": {
            "type": "string",
            "description": "Also keep the mapping used, with every style of the document written out, as a saved template of this name (the dialog's \"Save as\"); it becomes the template last used. Not on a dry run."
          },
          "previewCharacters": {
            "type": "integer",
            "minimum": 0,
            "maximum": 6000,
            "description": "dryRun: how much of the converted Markdown to answer with (default 2000)."
          },
          "wait": {
            "type": "boolean",
            "description": "Wait for the book to be laid out again and answer with the pages each chapter came to (default true). False answers at once."
          }
        },
        "required": [
          "file"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_word_templatesAction

    The Word import templates kept in this browser, the ones the import and export dialogs offer: a template says what each Word style becomes ({ name, paragraphs: { "<style name>": { kind, … } }, characters: { … }, options }) and is used by sandbox_import_word and by sandbox_export (docx). list names them and says which was used last; get answers with one whole (and, with download, saves it as a .postext-word.json file through the browser); save keeps a template — the one whose id it carries is replaced, any other is added under a new id and becomes the one last used; delete removes one and answers with it, so it can be saved back.

    View tool JSON
    {
      "name": "sandbox_word_templates",
      "kind": "act",
      "impl": "imperative",
      "description": "The Word import templates kept in this browser, the ones the import and export dialogs offer: a template says what each Word style becomes ({ name, paragraphs: { \"<style name>\": { kind, … } }, characters: { … }, options }) and is used by sandbox_import_word and by sandbox_export (docx). list names them and says which was used last; get answers with one whole (and, with download, saves it as a .postext-word.json file through the browser); save keeps a template — the one whose id it carries is replaced, any other is added under a new id and becomes the one last used; delete removes one and answers with it, so it can be saved back.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "list",
              "get",
              "save",
              "delete"
            ]
          },
          "id": {
            "type": "string",
            "description": "get, delete: the template."
          },
          "template": {
            "type": "object",
            "description": "save: the template, as get gives it or as a .postext-word.json file holds it. paragraphs maps a Word style name to { kind } with kind one of body, heading (level 1–6, style: a heading style id), paragraphs (style: a paragraph style id), verse (style optional), callout and calloutTitle (type: a callout type id), quote, caption, chapter (starts a chapter titled with the paragraph), markup (Postext Markdown kept as written) and drop; characters to { kind } with kind one of text, bold, italic, boldItalic, smallCaps, sup, sub, chip (style: a chip style id), markup and drop; options takes lineBreaks, directFormatting, manualHeadings, pageBreaks, images and tables."
          },
          "name": {
            "type": "string",
            "description": "save: the name to keep it under, when the template carries none or another is wanted."
          },
          "download": {
            "type": "boolean",
            "description": "get: also save the template as a JSON file through the browser, as the dialog's download does."
          }
        },
        "required": [
          "action"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_answerAction

    Answer the dialog the Sandbox opens when a link names a book the reader already has their own version of (sandbox_get_state reports it as question, and ready stays false until it is answered): replaceCopy: false opens the reader's version, as closing the dialog does; replaceCopy: true replaces it with the published one, which deletes their copy and its changes for good — ask the reader first. dismissNotice: true clears the message of the Books panel (notice in sandbox_get_state). Answers with the book on screen afterwards and its pages.

    View tool JSON
    {
      "name": "sandbox_answer",
      "kind": "act",
      "impl": "imperative",
      "description": "Answer the dialog the Sandbox opens when a link names a book the reader already has their own version of (sandbox_get_state reports it as question, and ready stays false until it is answered): replaceCopy: false opens the reader's version, as closing the dialog does; replaceCopy: true replaces it with the published one, which deletes their copy and its changes for good — ask the reader first. dismissNotice: true clears the message of the Books panel (notice in sandbox_get_state). Answers with the book on screen afterwards and its pages.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "replaceCopy": {
            "type": "boolean",
            "description": "The answer to the pending question: true replaces the reader's version with the published book, false keeps theirs."
          },
          "dismissNotice": {
            "type": "boolean",
            "description": "Clear the notice of the Books panel."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_get_warningsAnswer

    What the Sandbox's checks find in a chapter, or in the whole book, worded as the Checks panel words it: missing fonts and pictures, markup the engine could not read, design elements that do not fit, text too faint against its ground, typesetting faults (loose lines, widows, overflowing boxes) and print preflight. The chapter is laid out for the check itself, so the answer is the same whatever viewer and chapter are on screen, and it follows the last change. Each warning comes with its category, the chapter and the line of the source it points at (and the offsets, for sandbox_select_text), the page where it has one and, where it names one, the setting or the resource. scope "book" checks every chapter, which lays each of them out: on a long book that takes a while.

    View tool JSON
    {
      "name": "sandbox_get_warnings",
      "kind": "answer",
      "impl": "imperative",
      "description": "What the Sandbox's checks find in a chapter, or in the whole book, worded as the Checks panel words it: missing fonts and pictures, markup the engine could not read, design elements that do not fit, text too faint against its ground, typesetting faults (loose lines, widows, overflowing boxes) and print preflight. The chapter is laid out for the check itself, so the answer is the same whatever viewer and chapter are on screen, and it follows the last change. Each warning comes with its category, the chapter and the line of the source it points at (and the offsets, for sandbox_select_text), the page where it has one and, where it names one, the setting or the resource. scope \"book\" checks every chapter, which lays each of them out: on a long book that takes a while.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter to check: its position in the book (from 1), its title or its id. The chapter the reader is at when left out."
          },
          "scope": {
            "type": "string",
            "enum": [
              "chapter",
              "book"
            ],
            "description": "book checks every chapter (default chapter)."
          },
          "category": {
            "type": "string",
            "enum": [
              "fonts",
              "figures",
              "markup",
              "design",
              "contrast",
              "typesetting",
              "preflight",
              "system"
            ],
            "description": "Only this category."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "description": "Most warnings to list (default 100)."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_apply_proposalAction

    Fix a frame of a composed page with one of the fixes the layout proposes for it: the proposals of its frameOverflow, frameCovered or frameOutsideArea warning in sandbox_get_warnings, by their number there (from 1) or their kind. A frame that does not fit (frameOverflow): allowShrink lets its text shrink further (fit.minScale, and fit.shrinkText when it was off), raiseMax raises its maxHeight, lowerMin lowers the minHeight of another frame of its group, continueNextPage sets overflow.continueIn to next-page, and useTemplate sets the page with another template (the fence's template attribute in the chapter's text); shortenText changes nothing: it selects the frame's text in the Manuscript panel and answers how many characters to cut and where, for sandbox_write_text. A frame under another (frameCovered): layer paints the covering frame under it, exclude makes the covering frame push its text round it. A frame past its edge (frameOutsideArea): maxHeight holds it to the room it has, minHeight raises the frame it is anchored inside, continueNextPage lets the rest go on. move shifts the moved frame's placement.offset by the proposed millimetres (refused for a frame with no placement, or an offset in ems or percent). continueNextPage of a frame past its edge also sets the maxHeight it proposes. Both overlap checks end with allowOverlap: overlap 'allow' on the frame placed so on purpose (the covering frame of a frameCovered, the frame itself of a frameOutsideArea), which the checks then leave out. It is the one-click fix of the Checks panel and the Reflow panel, without the question they ask the reader: one step of the history that sandbox_undo takes back. A design change applies to every page set with the template. Answers what was changed and whether the check is gone, laid out again.

    View tool JSON
    {
      "name": "sandbox_apply_proposal",
      "kind": "act",
      "impl": "imperative",
      "description": "Fix a frame of a composed page with one of the fixes the layout proposes for it: the proposals of its frameOverflow, frameCovered or frameOutsideArea warning in sandbox_get_warnings, by their number there (from 1) or their kind. A frame that does not fit (frameOverflow): allowShrink lets its text shrink further (fit.minScale, and fit.shrinkText when it was off), raiseMax raises its maxHeight, lowerMin lowers the minHeight of another frame of its group, continueNextPage sets overflow.continueIn to next-page, and useTemplate sets the page with another template (the fence's template attribute in the chapter's text); shortenText changes nothing: it selects the frame's text in the Manuscript panel and answers how many characters to cut and where, for sandbox_write_text. A frame under another (frameCovered): layer paints the covering frame under it, exclude makes the covering frame push its text round it. A frame past its edge (frameOutsideArea): maxHeight holds it to the room it has, minHeight raises the frame it is anchored inside, continueNextPage lets the rest go on. move shifts the moved frame's placement.offset by the proposed millimetres (refused for a frame with no placement, or an offset in ems or percent). continueNextPage of a frame past its edge also sets the maxHeight it proposes. Both overlap checks end with allowOverlap: overlap 'allow' on the frame placed so on purpose (the covering frame of a frameCovered, the frame itself of a frameOutsideArea), which the checks then leave out. It is the one-click fix of the Checks panel and the Reflow panel, without the question they ask the reader: one step of the history that sandbox_undo takes back. A design change applies to every page set with the template. Answers what was changed and whether the check is gone, laid out again.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chapter": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The chapter of the page: its position in the book (from 1), its title or its id. The chapter the reader is at when left out."
          },
          "frame": {
            "type": "string",
            "description": "The frame the check is about, by its name in the template (the warning's frame)."
          },
          "check": {
            "type": "string",
            "enum": [
              "frameOverflow",
              "frameCovered",
              "frameOutsideArea"
            ],
            "description": "Which check of the frame to fix, when it has more than one (the warning's kind)."
          },
          "coveredBy": {
            "type": "string",
            "description": "For frameCovered: the covering frame, when the frame lies under more than one."
          },
          "page": {
            "type": "integer",
            "description": "The page number as printed, when the check is on more than one page of the chapter."
          },
          "proposal": {
            "type": [
              "integer",
              "string"
            ],
            "description": "The fix: its number in the warning's proposals (from 1) or its kind (allowShrink, raiseMax, lowerMin, continueNextPage, useTemplate, shortenText; layer, exclude, move; maxHeight, minHeight; allowOverlap)."
          }
        },
        "required": [
          "frame",
          "proposal"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    sandbox_get_composed_checksAction

    The checks of a composed book in every edition it has: frames that do not fit, slots, page fences, the contents cut between columns, figure labels and the templates themselves, listed by language, chapter, page and frame as the Checks panel lists them under "Composed pages". A preset's bundle or a local project can carry several languages (sandbox_list_books says which); sandbox_get_warnings checks only the chapter you name in the language on screen. Every edition is laid out for this call, the other languages on the layout worker at background priority, so the answer is the same whether the Checks panel is open or not, and a long multilingual book takes a while. language limits it to one edition (a locale tag such as ca, or es-ES); without it all of them are checked. Nothing is switched or changed on screen. To go to a check, open the book in that language with sandbox_open_book (language) and use the chapter and page given here.

    View tool JSON
    {
      "name": "sandbox_get_composed_checks",
      "kind": "act",
      "impl": "imperative",
      "description": "The checks of a composed book in every edition it has: frames that do not fit, slots, page fences, the contents cut between columns, figure labels and the templates themselves, listed by language, chapter, page and frame as the Checks panel lists them under \"Composed pages\". A preset's bundle or a local project can carry several languages (sandbox_list_books says which); sandbox_get_warnings checks only the chapter you name in the language on screen. Every edition is laid out for this call, the other languages on the layout worker at background priority, so the answer is the same whether the Checks panel is open or not, and a long multilingual book takes a while. language limits it to one edition (a locale tag such as ca, or es-ES); without it all of them are checked. Nothing is switched or changed on screen. To go to a check, open the book in that language with sandbox_open_book (language) and use the chapter and page given here.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "language": {
            "type": "string",
            "description": "Only this edition: a locale tag the book carries (sandbox_list_books lists them). All of them when left out."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "description": "Most checks to list (default 100)."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    site_get_contextAnswer

    The page of postext.dev on screen, its language and theme, the languages the site is in, its main sections and every page of the documentation. postext.dev documents Postext, an open-source layout engine that sets Markdown as books, magazines and textbooks in the browser; its Sandbox (/sandbox) is the editor, and offers its own tools (sandbox_*) while it is the page on screen.

    View tool JSON
    {
      "name": "site_get_context",
      "kind": "answer",
      "impl": "imperative",
      "description": "The page of postext.dev on screen, its language and theme, the languages the site is in, its main sections and every page of the documentation. postext.dev documents Postext, an open-source layout engine that sets Markdown as books, magazines and textbooks in the browser; its Sandbox (/sandbox) is the editor, and offers its own tools (sandbox_*) while it is the page on screen.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    site_searchAction

    Search the documentation and the Cookbook of postext.dev in the language on screen: sections of the docs and recipes that match the words, each with its path (to read with site_read_page or open with site_open_page) and the passage that matched. Setting names (bodyText.avoidOrphans), Markdown directives (::resource) and plain questions all work as queries.

    View tool JSON
    {
      "name": "site_search",
      "kind": "act",
      "impl": "imperative",
      "description": "Search the documentation and the Cookbook of postext.dev in the language on screen: sections of the docs and recipes that match the words, each with its path (to read with site_read_page or open with site_open_page) and the passage that matched. Setting names (bodyText.avoidOrphans), Markdown directives (::resource) and plain questions all work as queries.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "description": "What to look for."
          },
          "language": {
            "type": "string",
            "enum": [
              "en",
              "es",
              "ca",
              "de",
              "fr",
              "it",
              "pt",
              "zh",
              "ja",
              "ar"
            ],
            "description": "The language (the one on screen when left out)."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 30,
            "description": "Most results of each kind (default 8)."
          }
        },
        "required": [
          "query"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    site_read_pageAnswer

    The text of a page of postext.dev as Markdown — a documentation page (/docs/configuration-text, /docs/document-format), a recipe (/cookbook/<slug>), the glossary, the home page (/) — without leaving the page on screen. Long pages come in parts: pass the offset the answer gives to read on.

    View tool JSON
    {
      "name": "site_read_page",
      "kind": "answer",
      "impl": "imperative",
      "description": "The text of a page of postext.dev as Markdown — a documentation page (/docs/configuration-text, /docs/document-format), a recipe (/cookbook/<slug>), the glossary, the home page (/) — without leaving the page on screen. Long pages come in parts: pass the offset the answer gives to read on.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string",
            "description": "The page's path, e.g. /docs/sandbox."
          },
          "language": {
            "type": "string",
            "enum": [
              "en",
              "es",
              "ca",
              "de",
              "fr",
              "it",
              "pt",
              "zh",
              "ja",
              "ar"
            ],
            "description": "The language (the one on screen when left out)."
          },
          "offset": {
            "type": "integer",
            "minimum": 0,
            "description": "Character to start from, to read a long page on."
          },
          "length": {
            "type": "integer",
            "minimum": 500,
            "maximum": 200000,
            "description": "Most characters to give (default 40000)."
          }
        },
        "required": [
          "path"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    site_open_pageAction

    Show a page of postext.dev to the reader: the home page (/), a documentation page (/docs/<page>, with #heading to land on a section), the Cookbook (/cookbook, or /cookbook?q=words to show it filtered), a recipe (/cookbook/<slug>), the glossary (/glossary#<term>), the Sandbox (/sandbox). The tools on offer follow the page: the Sandbox's appear once it is on screen.

    View tool JSON
    {
      "name": "site_open_page",
      "kind": "act",
      "impl": "imperative",
      "description": "Show a page of postext.dev to the reader: the home page (/), a documentation page (/docs/<page>, with #heading to land on a section), the Cookbook (/cookbook, or /cookbook?q=words to show it filtered), a recipe (/cookbook/<slug>), the glossary (/glossary#<term>), the Sandbox (/sandbox). The tools on offer follow the page: the Sandbox's appear once it is on screen.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string",
            "description": "The page's path."
          },
          "language": {
            "type": "string",
            "enum": [
              "en",
              "es",
              "ca",
              "de",
              "fr",
              "it",
              "pt",
              "zh",
              "ja",
              "ar"
            ],
            "description": "The language (the one on screen when left out)."
          }
        },
        "required": [
          "path"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    site_list_recipesAction

    The recipes of the Postext Cookbook: each solves one layout problem (a drop cap, a table that breaks across pages, a bilingual page, a comic strip) and comes with its Markdown, its settings and the pages they produce. Lists them by chapter, or only those of one chapter or matching some words, with the question each one answers and its path.

    View tool JSON
    {
      "name": "site_list_recipes",
      "kind": "act",
      "impl": "imperative",
      "description": "The recipes of the Postext Cookbook: each solves one layout problem (a drop cap, a table that breaks across pages, a bilingual page, a comic strip) and comes with its Markdown, its settings and the pages they produce. Lists them by chapter, or only those of one chapter or matching some words, with the question each one answers and its path.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "description": "Words the recipe's title, question or summary must contain."
          },
          "chapter": {
            "type": "string",
            "description": "Only the recipes of this chapter (its id or number, as the answer's chapters give them)."
          },
          "language": {
            "type": "string",
            "enum": [
              "en",
              "es",
              "ca",
              "de",
              "fr",
              "it",
              "pt",
              "zh",
              "ja",
              "ar"
            ],
            "description": "The language (the one on screen when left out)."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 300,
            "description": "Most recipes to list (default 60)."
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    site_open_recipe_in_sandboxAction

    Open a Cookbook recipe in the Sandbox as a book the reader can edit — its Markdown, settings, resources and fonts — so its technique can be tried and changed. The recipe is imported as a project the first time; later the reader's copy opens, edits included.

    View tool JSON
    {
      "name": "site_open_recipe_in_sandbox",
      "kind": "act",
      "impl": "imperative",
      "description": "Open a Cookbook recipe in the Sandbox as a book the reader can edit — its Markdown, settings, resources and fonts — so its technique can be tried and changed. The recipe is imported as a project the first time; later the reader's copy opens, edits included.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "The recipe's slug, as site_list_recipes gives it."
          },
          "language": {
            "type": "string",
            "enum": [
              "en",
              "es",
              "ca",
              "de",
              "fr",
              "it",
              "pt",
              "zh",
              "ja",
              "ar"
            ],
            "description": "The language (the one on screen when left out)."
          }
        },
        "required": [
          "slug"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    site_lookup_termAction

    What a typographic or typesetting term means, from the site's glossary: widow, orphan, runt, leading, kerning, baseline grid, kinsoku, tate-chu-yoko, kashida, and the abbreviations the documentation uses. Matches the term, part of it, or its form in another of the site's languages.

    View tool JSON
    {
      "name": "site_lookup_term",
      "kind": "act",
      "impl": "imperative",
      "description": "What a typographic or typesetting term means, from the site's glossary: widow, orphan, runt, leading, kerning, baseline grid, kinsoku, tate-chu-yoko, kashida, and the abbreviations the documentation uses. Matches the term, part of it, or its form in another of the site's languages.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "term": {
            "type": "string",
            "description": "The term, or part of it."
          },
          "language": {
            "type": "string",
            "enum": [
              "en",
              "es",
              "ca",
              "de",
              "fr",
              "it",
              "pt",
              "zh",
              "ja",
              "ar"
            ],
            "description": "The language (the one on screen when left out)."
          }
        },
        "required": [
          "term"
        ],
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }
    site_set_preferencesAction

    Switch the site (the Sandbox's interface included) to another of its languages, staying on the same page, or between the light and the dark theme. The choice is remembered by the reader's browser.

    View tool JSON
    {
      "name": "site_set_preferences",
      "kind": "act",
      "impl": "imperative",
      "description": "Switch the site (the Sandbox's interface included) to another of its languages, staying on the same page, or between the light and the dark theme. The choice is remembered by the reader's browser.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "language": {
            "type": "string",
            "enum": [
              "en",
              "es",
              "ca",
              "de",
              "fr",
              "it",
              "pt",
              "zh",
              "ja",
              "ar"
            ],
            "description": "The language to switch the site to."
          },
          "theme": {
            "type": "string",
            "enum": [
              "light",
              "dark"
            ]
          }
        },
        "additionalProperties": false
      },
      "page": "/en/sandbox"
    }