SQLBI Whiteboard
Reference

The .wimport format

A Markdown recipe that builds image and text containers. It is not a board file. There is no export back to .wimport. After import you rearrange, draw, and save a .wboard.

This page is the public edition of the in-repo contract docs/wimport.md. Authors and agents should treat the two as the same grammar. A sample workshop lives next to that file.

The file must be valid CommonMark so it previews in VS Code and GitHub without a custom renderer. Associate the extension if the editor does not treat it as Markdown:

"files.associations": { "*.wimport": "markdown" }

Produce this

Heading grammar

LineMeaning
# TitleOptional board title. At most one. Not a container. Ignored if it appears after the first ##.
## TitleStarts a container. The heading text is the container title.
### and deeperStay inside the current container body. They do not start a new object.
---, ***, or ___ on its own lineThematic break. Starts a new row of containers. Not a container.
Any other line before the first ##Documentation for the preview. Not imported.

An empty ## heading is titled Text.

How the body becomes a container

Recognizers run in this order. The first match wins. Extra material after the match is ignored.

  1. Markdown image: ![optional alt](relative/path.png). Image container. Title is the ## heading, then the alt text, then the file name. Allowed extensions: .png, .jpg, .jpeg, .bmp, .gif, .svg. An .svg stays vector on the board, so give it a width/height or a viewBox to be sized from; anything it fetches from elsewhere is ignored.
  2. Fenced code whose info-string is a registered language. Text container. Contents of the fence. Language from the tag.
  3. Markdown link to an image extension: same as an image.
  4. Markdown link to a registered language extension: [label](relative/path.dax). Text container. File contents. Language from the extension.
  5. Any remaining text: text container. The Markdown source is stored as plain text. Whiteboard does not render Markdown.
  6. Empty body: the heading is skipped.

Do not put an image and a measure under the same ##. Use two headings.

A fenced block whose tag is unknown (for example python today) is not a language container. The whole body, fence included, becomes plain text.

Languages shipped today

LanguageFence info-stringFile extensions
DAXdax.dax
SQL Serversql, tsql.sql
KQLkql, kusto.kql

Further languages will be extra rows in this table. Do not invent fence tags Whiteboard does not list here, because they import as plain text. Linked text files larger than 1 000 000 bytes are skipped and reported as missing.

Layout

Whiteboard measures each container, then packs them left to right. If the file contains thematic breaks (---, ***, or ___), those breaks alone control the rows: containers between breaks stay together, regardless of width. Only files without thematic breaks wrap automatically at about 2400 world units.

In Preferences → Import, set Horizontal spacing between containers and Vertical spacing between rows. Both default to 32 px and range from 0 to 500 px at 100% zoom. Changes apply to future imports only.

On drop, the group’s top-left is the pointer. On Open or toolbar Import, the group’s top-left is the top-left of the visible view. Do not put coordinates in the file. There is no pos:, no YAML front matter, and no HTML comment layout.

How the file is opened

ActionResult
Drop onto an open boardContainers are added. Pointer is the group top-left. Undo is one step.
Import (toolbar)Containers are added at the visible top-left.
File → Open, or double-clickNew untitled board, then import. Save / Save As writes .wboard only. The .wimport path is used only to resolve relative links.

Missing or unreadable linked files are skipped. Whiteboard then shows a dialog listing the resolved paths, which can be copied.

Template

# Optional board title

Optional notes for the Markdown preview. Not imported.

## Container title for an image
![short alt](./images/diagram.png)

## Container title for notes
- Bullet one
- Bullet two

---

## Container title for embedded DAX
```dax
Total Sales := SUM(Sales[Amount])
```

## Container title for linked SQL
[Top customers](./sql/top-customers.sql)

Checklist

Do not