Markdown and documents¶
Help pages, rules, terms of service and other text you show players can be written in markdown, the plain-text format used by GitHub, Discord and most note apps. Write it in any editor, or keep it in your repository and review it there.
SAGL shows markdown in:
- The document viewer: a scrolling panel with a title and buttons, for
whole documents. See
player.ui.showDocument. - Chat messages:
player.sendandserver.broadcastwith{ markdown: true }. - Dialogs:
player.dialogwithmarkdown: true. - Your own UI: client scripts'
setMarkdownand the<sagl-markdown src="...">element.
What's supported¶
CommonMark, the standard markdown, plus GitHub's tables, strikethrough and bare links:
# Heading, ## Subheading, ### and so on
A paragraph with **bold**, *italic*, `code`, ~~struck out~~ and [a link](https://example.com).
- A list
- of things
1. numbered
2. too
> A quote.
| Command | What it does |
|---|---|
| `/rules` | Shows these rules |
---

- Images are client files: a path relative to the markdown file
(
images/map.pngbesidedocs/rules.mdisdocs/images/map.png), orgame:<txd>/<texture>for one of the game's. Images from the web aren't shown. - Links to
https://addresses open in the player's browser, after they confirm. - HTML in markdown is shown as text, not run, so a document can't change the UI around it.
- Chat messages and dialogs keep to one line's worth of styling: bold, italic, code and links. Headings, lists and the like run together.
Keys: {key:ID}¶
{key:ID} shows the key the player has for an
action as its icon, as they've bound it in Settings →
Controls. If they rebind it, the document shows the new key.
ID is the action's id: one of yours (server.actions.register), one of
a client script's, or one of SAGL's own (chat, chat-command,
indicator-left, indicator-right, hazards). It works in every chat
message and dialog, with or without markdown.
The document viewer¶
Shows a markdown client file in a panel over the game: the title, the document (scrolling if it's long), and a row of buttons. Resolves with the index of the button pressed, or -1 if they closed it (Esc) or left.
| Option | Type | Default | Description |
|---|---|---|---|
title |
string |
none | Across the top. |
buttons |
string[] |
["Close"] |
Left to right. The last is the main one (Enter). |
requireEnd |
boolean |
false |
The last button only works once they've scrolled to the end (or it all fits). "Read to the end to continue" shows meanwhile. |
closable |
boolean |
true |
Esc (gamepad B) closes it, resolving -1. |
One shows at a time; more wait their turn. player.ui.closeDocuments()
takes down any they have showing or waiting.
Terms of service¶
The server decides what accepting means: let them play, kick them, or remember that they accepted.
server.on("playerJoin", async (player) => {
if (await accepted(player)) return;
const choice = await player.ui.showDocument("docs/terms.md", {
title: "Terms of service", buttons: ["Decline", "Accept"], requireEnd: true, closable: false,
});
if (choice === 1) await rememberAccepted(player);
else player.kick("You need to accept the terms to play here.");
});
Freeroam's /rules shows client-files/docs/rules.md this way.
Styling¶
The theme's stylesheet, /sagl/ui/theme/markdown.rcss, styles markdown
everywhere SAGL shows it. Markdown becomes elements with md- classes
(md-h1 to md-h6, md-p, md-list, md-li, md-strong, md-em,
md-code, md-code-span, md-quote, md-table, md-link, md-img
and so on). In your own documents, link that stylesheet and override
whichever classes you like: