- name
- slide
- description
- Create, edit, inspect, and visually verify Slide units with the Lite Interface.
# Slide units
`execute` provides `univerAPI`, `api` (an alias of `univerAPI`), and `presentation` (the `FPresentation` bound by `--unit`). Do not redeclare them. Select pages with `presentation.getSlideByIndex(0)`, `presentation.getSlideById(id)`, or `presentation.getSlides()`. A Slide unit does not provide `workbook`; if it is undefined, verify the selected unit type.
CLI page indices are 1-based: structured inspection uses `inspect slide index:N`, while screenshot,
layout lint, and `compile-svg --page` use their documented page selectors. Inside `execute`, Facade
indexes are 0-based (`getSlideByIndex`, `getSlides()[i]`). When carrying a page from CLI output into
code, prefer `getSlideById(id)`.
Use `univer api find <query...>` to discover API symbols, then use `univer api show <symbol>` for exact signatures, enum values, documentation, and examples. Use the declared common Shape names such as `ShapeTypeEnum`, `ShapeFillEnum`, and `ShapeLineTypeEnum`.
## Presentation structure
A slide unit is one presentation: the presentation holds slides ("Deck and pages"), a slide holds elements in stacking order ("Stacking order"), and an element is a shape, an image, or a group — a text box is a shape ("Elements"). Tables and charts are elements too, and both are editable ("Tables", "Charts"). Native charts use the direct `FSlide` chart methods ("Native charts"). Imported decks can carry further element kinds (placeholders, connectors, media); address those through the generic element surface and verify their dedicated facade before editing. Master/layout pages render underneath a slide but are not edited here. A transition is a per-slide page-enter effect ("Transitions"). The facade mirrors this shape — `FPresentation` → `FSlide` → `FShape` / `FImage` / `FGroup` — and `univer api show` gives signatures.
## Task routing
- Create or redesign pages: run the four-stage workflow below — author SVG and compile it ("SVG is the generation path"); do not hand-write facade drawing code for new content.
- Edit existing content: facade through `execute` — element CRUD in "Elements", content rules in "Text", "Shapes, fill, and stroke", and "Images and textures"; block-level rework in "Editing existing pages"; tables and charts in "Tables" and "Charts".
- Insert or update data-driven charts: reserve the chart rectangle in the page SVG, then use the direct `FSlide` chart methods through `execute` ("Native charts").
- Restack or add page-enter effects: "Stacking order", "Transitions".
- Verify: "Visual verification" — structured `inspect slide`, browser-backed `lint`, then screenshots
of every page at final review.
## Multi-page deck workflow
Four stages. Stage 1 fixes the deck-level plan, stage 2 runs once **per page** as a closed loop, stage 3 reviews the whole deck, stage 4 delivers. A page must pass its own loop before the next page starts; do not batch-author pages and defer checking to the end — a layout mistake repeated across ten unchecked pages costs ten rewrites.
### 1. Write the per-page specification
Before drawing SVG, write `spec.md` precisely enough that page generation requires no fresh decisions about copy, palette, or structure. Specify what each page should be, not merely what is easy to implement. The environment includes a semantic library of about 18,000 SVG resources across icons, logos, emoji, and illustrations, so do not remove useful assets to save drawing effort. At this stage describe asset meaning, not concrete registry names; exporting happens per page in stage 2.
Fix deck-level constants once: named colors in `#RRGGBB`, font roles expressed in points (`design px × 0.75`), font families, a baseline `outline` or `filled` icon style, illustration style, and page size. Each page section must define:
1. Layout, including exact tier and card counts.
2. Structure type, chosen from forms such as process chain, hub-spoke, layered architecture, circular stages, timeline, comparison columns, card grid, or hero image. Adjacent pages should differ and a deck should use at least four structures.
3. One core message.
4. Verbatim final copy for every title, label, card, and annotation.
5. Required image and icon assets.
For reconstruction, transcribe reference text exactly. For original work, derive it from the task requirements.
### 2. Build each page in a closed loop
Run steps 2a–2e for page N and reach a clean 2d before starting page N+1.
**2a. Prepare this page's assets.** Prepare the photos, logos, QR codes, icons, emoji, illustrations, and textures this page needs as individual files, record each exported path in the spec, and reuse files already exported for earlier pages. Discover and export SVG resources by meaning:
```bash
univer resources registries
univer resources find <query> [<query>...] [--registry <id>]... [--limit <n>]
univer resources export <registry>/<resource> [<handle>...] --out ./resources/
```
Copy the canonical handle exactly. Export downloads uncached resources once and then reuses `UNIVER_HOME/cache/resources`; output files are named `<registryId>--<resourceId>.svg`. `colorEditable: true` resources can follow an authored color, while fixed logos, color emoji, and illustrations remain whole-image assets. Keep one icon registry/style baseline across the deck. Hand-draw an icon only when the library has no appropriate result. Do not clone one icon under different names, substitute Unicode glyphs, or use empty circles as placeholders. Keep exported resources as files and reference them with `<image href="./resources/<registry>--<resource>.svg">`; use `<defs><symbol>` + `<use>` for a self-authored graphic deliberately reused within a page. Never extract and copy an exported resource's path data into the page: that loses source organization, and truncated paths can still render without warnings.
**2b. Author the page SVG.** Reread the page's spec section, then hand-author the complete `page-NN.svg` with inline styles and the prepared assets, and check it against all five spec fields. Keep every SVG through delivery so review can compare exact coordinates. Do not generate or rewrite pages through scripts, shared templates, or bulk substitutions; that produces repeated layouts and propagates page-specific errors.
**2c. Compile and apply with zero warnings.** Run `univer screenshot setup` once before the first compile so real fonts can be measured. Apply the page:
```bash
univer compile-svg page-NN.svg --page N --apply deck.univer \
--worktree <id> --unit <id> --json
```
Clear every `warning` before continuing because warnings mean output was dropped or degraded. Review every `lint`; a lint is advisory and may remain only when the behavior is intentional. Errors mean the SVG construct has no Slide representation and must be redrawn.
**2d. Check structure and rendered layout (required, every page).**
```bash
univer inspect slide index:N deck.univer --unit <id> --worktree <id> --json
univer lint --file deck.univer --unit <id> --worktree <id> --pages N --json
```
Structured inspection proves stored element identity, type, transform, text, fill, stroke, and stacking
order. Browser-backed lint provides glyph geometry for three conservative rules: text off the page,
text escaping an opaque card, and overlapping text glyph bands. Treat every finding as real until its
evidence proves the overlap intentional. Check the following against lint evidence and the screenshot:
1. **Overflow** — inspect every finding against the page frame and its intended container.
2. **Unexpected wrapping** — compare the rendered screenshot with the intended line breaks.
3. **Centering** — compare text and icon centers with their containers in the screenshot.
4. **Alignment** — elements that share a role should share a left edge or center line.
5. **Indentation** — hierarchical text keeps its left-edge contract: peers indent equally, children indent deeper than their parent.
6. **Icon sizing** — icons with the same role should have the same declared size; mixed sizes across sibling cards is a common defect.
7. Deviations of ≤3px are invisible at slide scale — a reference point, not a rule to chase to zero.
Each lint finding carries geometry and the relevant text/container evidence. Discipline:
- **Every lint must end as fixed, or as an explicit "intentional" call justified against that evidence in your final report.** Never drop one silently, and never dismiss one from memory of what the page looks like — re-read the element it names. Calling a lint a false positive because you _think_ it points at a decoration, when the evidence says the container is an opaque card, is a wrong call.
- Text running **off the page** is clipped by definition — there is no legitimate design that needs it. Fix it.
- Text **escaping its card** is nearly always a CJK line that was not hand-wrapped. Shorten it, wrap it, or widen the card.
- **Overlapping text**: the finding prints both sides' colour and opacity. Read them before deciding.
Judge occlusion and contrast risks from structured facts (stacking order, fill, opacity); stage 3
confirms them visually. Do not screenshot inside this loop — screenshots belong to stage 3.
**2e. Fix and re-verify.** Fix the page by editing its `page-NN.svg` and reapplying it with `--page N` (a replacement). **Never patch a page with `--add`.** `--add` overlays: the old, broken element stays exactly where it was and the corrected one lands on top of it, so a single "fix" leaves two copies of the line — the overflow you set out to remove is still there, now with a ghost stacked over it. Seen in a real run: three pages patched this way ended with 19 duplicated texts and the original overflows intact. `--add` is for adding genuinely new content to a finished page, never for rework. After fixing, re-run 2d: the page is done when the scan is clean or every surviving finding has a written justification. If the rescan shows the same text twice, you patched with `--add` — redraw the full page and replace it.
### 3. Review the whole deck
After every page has passed its loop, screenshot every page and review in batches of no more than five pages, using independent reviewer agents when the host supports them; otherwise review the batches directly. A review must answer each checklist item with an explicit PASS or FAIL plus the observed evidence — an open-ended "does it look fine?" reliably misses defects. Check, in order: the seven items in "Visual verification", then cross-page consistency — adjacent pages should not repeat the same structure, and colors, fonts, and icon style should not drift from the spec constants. Treat each defect as a pattern: search every page SVG for the same mistake, fix the sources, reapply those pages with `--page N` (each reapplied page goes through its 2d check again), and re-screenshot them. Report anything that genuinely requires human redesign.
### 4. Deliver
After every page passes visual review, follow the core Skill's "Finish the task" steps. Provide the
artifact path together with the viewer link.
## SVG is the generation path
For new pages or generated elements, author SVG and compile it. Do not hand-write individual shape and text calls or paste generated Facade code into `execute`. The compiler owns geometry conversion, baseline conversion, page selection, and common Facade workarounds, including `textWrap=None + NoAutoFit + padding=0` for measured SVG text. **Native charts are the deliberate exception**: use SVG to establish the page layout and leave the chart rectangle empty, then insert the chart through `slide.newChart()` and `slide.insertChart()` in a follow-up `execute`. Reapplying the full page SVG clears every page element, including the chart, so finish page rework before inserting it or reinsert it afterward.
`--page` is one-based and declarative: an existing page is cleared and replaced, `pageCount + 1` appends, and a larger number fails. Add `--add` only when an SVG contains genuinely new elements to overlay onto a finished page. **`--add` is never the way to fix something**: it keeps the old element and stacks the corrected one on top, leaving both. Rework always means editing the page's SVG and reapplying it with `--page N`, which clears the page first and is idempotent. Without `--apply`, compilation is a read-only preview; `--out` writes the generated script. Reapplying the same replacement is idempotent.
Use ordinary browser-valid SVG: shapes, paths, transforms, gradients, text, bitmaps, `<use>`, style sheets, CSS units, and color functions. Open the SVG in a browser before compilation when one is available; its visible result is the baseline expectation.
`<image>` must declare width and height. Break lines with a `<tspan>` that has a scalar `x` (that line's horizontal anchor) and either absolute `y` or non-zero `dy` (line spacing); different lines may use different x values and remain one editable rich-text element. An x-only tspan after visible content resets the cursor on the same baseline and is still unsupported, as are `dx` and per-glyph coordinate lists. Center text in a badge or circle with `dominant-baseline="middle"` and `text-anchor="middle"`.
Spaces are not a layout tool. Default SVG whitespace handling collapses every run of consecutive spaces to one and strips leading spaces — in a browser and in the compiled slide alike — so layout built from spaces silently flattens: code indentation goes flush-left, the word gaps of a letter-spaced title (`P R O D U C T R O A D M A P`) vanish, and multi-column lines or icon-to-label gaps close up. The compiler reports a lint when it collapses such runs. Build the layout structurally instead: `xml:space="preserve"` on the `<text>` (or per-line `x` positions) for code indentation, one positioned `<text>` per column, and non-breaking spaces (` `) for small fixed gaps.
Draw arrowheads with an SVG `<marker>`, using `orient="auto-start-reverse"` to rotate the head onto the tangent of the line's end.
`markerWidth`/`markerHeight` are multiples of the stroke width, not pixels — keep the head sized in proportion to its line, with looks in mind; `fill="context-stroke"` follows the line's color.
Note: do not hand-place triangle vertices at a line's ends — getting the tangent direction right is hard, and the bare line end easily pokes out past the head.
Gradient coordinates are fractions of the shape's box, not pixels: `gradientUnits` defaults to `objectBoundingBox`, so a vertical gradient is `x2="0" y2="1"` — writing `y2="720"` puts the axis outside the shape and renders a near-flat color.
A few things the slide renderer cannot reproduce, so the compiler warns. Mark that subtree (usually the `<g>` around the card) `data-univer-embed="image"` and it is baked into a faithful bitmap — at the cost that the subtree is no longer editable or recolorable, so keep text and layout structure outside it:
- **Drop shadows, blur, and other filters.**
- **A translucent gradient** — a `stop-opacity` below 1, or a gradient-filled shape with element `opacity` below 1 — renders as a solid block. Illustration packs stack pale gradient shadows behind every card; that is the common case.
- **A radial gradient on a non-square shape** — the renderer draws a circle centred on the box, not an ellipse fitted to it.
SVG resources inline at compile time three ways: an exported file, `<image href="./resources/<registry>--<resource>.svg" width=".." height=".."/>` (the normal choice); a self-authored reusable page graphic, `<defs><symbol id="ic" viewBox="0 0 24 24">…</symbol></defs>` + `<use href="#ic" x=".." width=".."/>`; or an external sprite sheet, `<use href="./icons.svg#home" …/>`. Each `<use>` is one logical instance regardless of whether its target is `<symbol>`, `<g>`, or another graphical element. All three forms use the same logical lowering: one visible leaf remains one native element; multiple faithfully vectorizable single-paint leaves become one multi-path custom shape; multi-paint or text content becomes one Slide group; content that cannot be faithfully vectorized follows `data-univer-embed="auto|vector|image"` (default `auto`) and may become one image. Nested `<use>` keeps the outermost visible instance boundary. A plain `<g>` is only a transform/style/layout container and stays flat; it does not request a Slide group. These compile-time guarantees are not a reason to copy exported path data into the page.
Preserve the registry in exported filenames. A sprite sheet previews in a browser only over http — `file://` blocks the cross-file reference by same-origin policy and shows blank icons; that is browser security, not a broken page. Only resources reported as `colorEditable: true` may follow an authored color; fixed logos, color emoji, and illustrations keep their intrinsic colors and must remain whole-image assets. An `<image>` recolor can preview differently in a browser, so inspect the compiled result before relying on it.
## Visual verification
Static inspection reports facts, not verdicts — you decide what is a defect, because legitimate slide designs overlap backgrounds, decorations, and text on purpose.
`inspect presentation` gives each element's declared facts straight from the snapshot: `id`, `type`
(plus `shapeType` like `rect` or `line`), `transform`, fill/stroke, and text facts. The `elements`
array is in stacking order, bottom to top. Use explicit `index:N` or `id:ID` selectors with
`inspect slide` for page detail; CLI indices are 1-based.
Rendered glyph geometry is a separate task: run `univer lint --file <file.univer> --unit <id>
[--worktree <id>] [--pages <pages>]`. It checks text off-page, text escaping an opaque rectangular
card, and overlapping text glyph bands. `compile-svg` normally measures text with the real browser;
`--estimate-text-size` is a browserless fallback and must not replace screenshot review.
Screenshot review must check:
1. Elements clipped by or placed beyond the page.
2. Text overflowing cards or colored regions.
3. Text boxes overlapping one another.
4. Shapes hiding information they should not cover.
5. Low contrast or text placed directly on a complex image without a backing surface.
6. Missing critical elements compared with the task or reference.
7. Arrowheads lopsided, pointing off their line's direction, or mismatching its color.
## Deck and pages
A new deck contains one empty page. `compile-svg --page 1` handles it automatically. When using Facade calls directly, reuse `presentation.getSlides()[0]`; call `appendSlide()` only for page two and later. The default page is 16:9 at 960 × 540, with a top-left origin. Use `getPageSize` and `setPageSize` for dimensions.
Page backgrounds support solid colors, images, gradients, and patterns through `slide.setBackground`. `deleteSlide`, `insertSlide`, and `moveSlide` return booleans instead of throwing, so check their results. Slides have no formulas or recalculation.
## Elements
Read with `getElements()` or `getElementById(id)`; `getShapes()` narrows to shapes (`getImages()` / `getGroups()` likewise). Every element or shape exposes its id through `getId()`. Create a normal shape with `slide.insertShape({ shapeType, transform?, shapeData? })`; it returns a live `FShape` / `FConnectorShape` or `null`, so check the result and record `getId()` immediately. Change it through that live handle (`setTransform`, `setSolidFill`, `setStroke…`, `getText()`); `getShapeData()` is detached, so assigning into the returned object never persists — use `setShapeData` or a dedicated setter. `slide.insertElement(element, index?)` is the snapshot-restoration API: its complete `ISlidePageElement` carries an explicit `id`, and the returned element must have that same id. Use it only when restoring imported snapshot identity and references, not to invent ids for ordinary authoring. Images still use `newImage().…build()` → `insertImage`. Delete with `deleteElement`, which accepts the element object, not its id. Group with `slide.group(...)` / `ungroup()` (`api show FSlide.group FGroup`). Mutation methods often return booleans rather than throwing, so verify results.
## Text
`fontSize` is in points, while positions and boxes use pixels. Convert design pixels with `fontSize = px × 0.75`; passing pixel values directly makes text 1.333 times too large.
Do not rely on text-box defaults. Text added through `slide.insertShape(...).getText()` currently defaults to `Square` wrapping, `NoAutoFit`, and 4px padding on every side. A small or tightly measured box can therefore wrap or clip text silently. Set wrapping, auto-fit, and padding explicitly for every inserted Shape.
For SVG-like, measured single-line text, keep the measured box authoritative and remove the renderer inset explicitly:
```js
shape
.getText()
.setText("...")
.setTextBoxOptions({
textWrap: univerAPI.Enum.ShapeTextWrapType.None,
autoFitType: univerAPI.Enum.ShapeTextAutoFitType.NoAutoFit,
padding: { left: 0, top: 0, right: 0, bottom: 0 },
});
```
`compile-svg` emits this contract automatically after measuring the text. For intentionally wrapped text with content padding, declare that different contract explicitly:
```js
const shape = slide.insertShape({
shapeType: univerAPI.Enum.ShapeTypeEnum.Rect,
transform: { left: 60, top: 60, width: 400, height: 200 },
});
if (shape === null) throw new Error("shape insertion failed");
shape
.getText()
.setText("...")
.setTextBoxOptions({
textWrap: univerAPI.Enum.ShapeTextWrapType.Square, // wrap to the box width
autoFitType: univerAPI.Enum.ShapeTextAutoFitType.NoAutoFit, // keep the declared box
padding: { left: 8, top: 8, right: 8, bottom: 8 }, // px, optional
});
```
With wrapping on, overflow moves to the box bottom instead — still silent — so give `NoAutoFit` boxes explicit width and enough height (a useful starting point is `lines × fontSizePx × 1.4`) and let the deck lint catch escapes.
A text box is a Shape whose text is owned by `shape.getText()`. Anything beyond one uniformly styled line goes through the rich-text builder:
```js
const rich = univerAPI
.newRichText()
.paragraph({ lineHeight: 40, lineHeightRule: univerAPI.Enum.SpacingRule.EXACT })
.span("Revenue ", { fs: 14, cl: { rgb: "#374151" } })
View on GitHub