postext.dev
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.
First seen 2026-11-05 · Last seen 2026-11-05 · Source: webmcp.com
Answer 8 · Act 48 · Transact 5 · Score: Not yet scored
Tool inspector
sandbox_save_resource
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.
Page: /en/sandbox
Input schema
| Property | Type | Required | Description |
|---|---|---|---|
id |
string | no | 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 |
string | no | Another id for the resource named by id (letters, digits, hyphens; it is written as a slug). |
updateReferences |
boolean | no | 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 |
string | no | The resource type id (figure, table, video, or one the book defines); it decides the numbering and the caption label. |
caption |
string | no | — |
note |
string | no | A note set under the caption (a source, a credit). |
altText |
string | no | What the picture shows, for readers who cannot see it. |
image |
object | no | A picture file (PNG, JPEG, WebP, GIF or SVG): where to fetch it (url) or its bytes (base64). |
svg |
string | no | The source of an SVG drawing. On an SVG resource it is an edit of its source. |
table |
object | no | 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. |
video |
object | no | 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. |
score |
object | no | 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. |
placement |
object | no | 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. |
resolution |
number,string,null | no | 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 |
boolean | no | 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 |
object,null | no | 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. |
marks |
object | no | 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. |
fields |
object | no | 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 |
boolean | no | Wait for the book to be laid out again (default true). |
Raw JSON schema
{
"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
}
Similar websites
morphus.myles4miles.chatgpt.site
Morphus is an AI-native workspace for designing worlds and generating playable game experiences.
damnpdfs.com
Install the DamnPDFs Codex plugin, pair a browser workspace and use PDF, image and file tools from your coding agent. Includes setup and privacy limits.
insignifi4nt.github.io
broCAD/M: local-first CAD and CAM for parametric design, wire EDM planning, simulation and controller export.
cabinet.varera.studio
The Cartographer's Cabinet