Variablen & Magische Funktionen
Auf dieser Seite
Variablen & Magische Funktionen
Zwei kleine, verwandte Funktionen, um wiederkehrende Fakten und
wiederkehrende Logik aus deinem Markdown herauszuhalten: wiederverwendbare
Variablen, einmal in bxsites.yaml definiert und mit {{ }} in jede Seite
eingesetzt, und magische Funktionen, kleine BoxLang-Helfer, die du einmal
in docs/functions.bxs schreibst und auf dieselbe Weise aufrufst - überall,
ganz ohne Import, ohne Plugin, ohne Verdrahtung.
Beide teilen sich eine Syntax:
{{ dotted.path }} # a reusable variable
{{ $name(arg1, arg2) }} # a magic function call
Wiederverwendbare Variablen
Füge bxsites.yaml einen variables-Block hinzu - in beliebiger Form, flach
oder verschachtelt:
variables:
company: "Ortus Solutions"
product:
name: "BoxLang"
supportEmail: "support@example.com"
{
"variables": {
"company": "Ortus Solutions",
"product": {
"name": "BoxLang",
"supportEmail": "support@example.com"
}
}
}
Referenziere davon dann alles, per Punktpfad, von jeder Markdown-Seite aus:
# Welcome to {{ company }}
We build {{ product.name }} tools. Need help? Write us at
{{ product.supportEmail }}.
baut zu:
<h1>Welcome to Ortus Solutions</h1>
<p>We build BoxLang tools. Need help? Write us at support@example.com.</p>
Eine {{ }}-Variable wird einmal, zur Build-Zeit, gegen das aufgelöst, was
bxsites.yamls eigener variables-Block gerade dann enthält - benenne ein
Produkt um, aktualisiere eine Support-Adresse oder erhöhe ein Jahr an einer
einzigen Stelle, und jede Seite, die die Variable nutzt, übernimmt die
Änderung beim nächsten Build. Siehe
variables in der
Konfigurationsreferenz.
Magische Funktionen
Füge eine Datei docs/functions.bxs hinzu (oder src/functions.bxs, wenn
dein Projekt src/ verwendet - siehe
Erste Schritte) - ein einfaches BoxLang-Skript.
Jede Funktion, die du mit einem führenden $ benennst, wird zu einer
magischen Funktion: aufrufbar aus {{ }} in Markdown, und aufrufbar bar,
direkt, aus den eigenen theme/
.bxm-Überschreibungen eines Projekts.
function $shout( text ) {
return uCase( arguments.text ) & "!"
}
function $badge( label, kind = "info" ) {
return '<span class="badge bg-' & arguments.kind & '">' & arguments.label & '</span>'
}
{{ $shout('this is important') }}
Status: {{ $badge('Stable', 'success') }}
baut zu:
<p>THIS IS IMPORTANT!</p>
<p>Status: <span class="badge bg-success">Stable</span></p>
Eine magische Funktion kann alles toString()-Fähige zurückgeben - reinen
Text, HTML, eine Zahl - und wird direkt in das Markdown der Seite
eingesetzt, bevor es konvertiert wird, sodass die Rückgabe von echtem HTML
(wie bei $badge() oben) genau so funktioniert, wie man es erwarten würde.
Eine Funktion, die in derselben functions.bxs ohne führendes $
deklariert wird, ist nur ein privater Helfer, gedacht dafür, nur von den
eigenen $-präfixierten Funktionen in derselben Datei aufgerufen zu werden
(sie werden alle in denselben Scope geladen, sodass eine die andere bar
aufrufen kann) - {{ }} kann eine solche Funktion niemals direkt aufrufen
(nur ein $name(...)-Aufrufziel wird überhaupt erkannt), und sie ist auch
nicht Teil der dokumentierten öffentlichen Oberfläche, die ein
Theme-Override aufrufen sollte, auch wenn sie dort technisch zufällig
ebenfalls erreichbar ist:
private string function formatPrice( amount ) {
return "$" & numberFormat( arguments.amount, "9.99" )
}
function $price( amount ) {
return formatPrice( arguments.amount )
}
Eine magische Funktion aus einem Theme-Override aufrufen
Weil eine magische Funktion direkt in den Template-Scope eingebunden wird,
kann das eigene theme/page.bxm (oder layout.bxm) eines Projekts sie bar
aufrufen, ganz ohne Präfix - auf dieselbe Weise, wie es bereits
variables.page/variables.siteConfig liest:
<p class="build-banner">#$shout( 'built with boxlang' )#</p>
Kontextvariablen
Der eigene Rumpf jeder magischen Funktion kann außerdem einen festen Satz
von "unterstützenden Variablen" lesen - bar, ganz ohne benötigtes Argument -
unabhängig davon, ob sie aus {{ }} in Markdown oder bar aus einem
Theme-Override aufgerufen wird:
| Variable | Was sie ist |
|---|---|
siteConfig | Die eigene bxsites.yaml-Konfiguration der Site (bereits mit Standardwerten versehen/validiert) |
page | Die aktuelle Seite (siehe den Hinweis unten - nicht jedes Feld ist schon befüllt, wenn sie aus Markdown aufgerufen wird) |
nav | Der eigene Navigationsbaum dieses Baums |
basePath | Root-relativer Basispfad, endet mit / |
versions | Einträge des Versionsumschalters - [ { label, url } ] |
currentVersion | Welcher versions-Eintrag gerade gerendert wird |
locales | Einträge des Sprachumschalters - [ { code, label, url, dir, flag } ] |
currentLocale | Der Code welchen locales-Eintrags gerade gerendert wird |
currentLocaleDir | "ltr"/"rtl" für die aktuelle Locale |
function $sitename() {
return siteConfig.name
}
function $pagetitle() {
return page.title
}
Site: {{ $sitename() }}
Page: {{ $pagetitle() }}
page ist an beiden Stellen nicht gleich vollständig. Aus Markdown
aufgerufen, ist page das eigene Struct dieser konkreten Seite wie von der
Festplatte geladen - title/description/tags/icon/summary/
ogImage/urlPath/relativePath/body/etc. sind bereits vorhanden, aber
die Felder, die erst bekannt sind, sobald jede Seite im Baum fertig
konvertiert wurde - toc, prevPage/nextPage, breadcrumbs,
editUrl/lastUpdated, iconHtml, markdownUrl, canonicalUrl -
existieren darauf noch nicht. Bar aus page.bxm aufgerufen, ist page das
vollständig angereicherte Struct, all das eingeschlossen. Jede andere
unterstützende Variable (siteConfig, nav, basePath, versions,
currentVersion, locales, currentLocale, currentLocaleDir) ist an
beiden Stellen identisch.
Argumentsyntax
Die Argumente eines magischen Funktionsaufrufs sind einfache, durch Kommas getrennte Literale oder Variablenreferenzen - keine verschachtelten Funktionsaufrufe oder Ausdrücke in dieser ersten Version:
- Zahlen:
{{ $discount(20) }} - Zeichenketten in Anführungszeichen:
{{ $greet('World') }}oder{{ $greet("World") }} - Booleans:
{{ $badge('Beta', true) }} - Eine
{{ }}-lose Punktpfad-Variablenreferenz:{{ $greet(product.name) }}
Visualizer-Rezepte
Eine magische Funktion, die HTML zurückgibt, ist nicht auf ein
Status-Badge beschränkt - sie ist ein universeller Weg, um GitBook-artige
visuelle Zellen (eine Sternebewertung, einen farbigen Chip, einen
Fortschrittsbalken) zu bekommen, ganz ohne GitBooks eigenen
datenbankgestützten Spalten-Picker, für den die git-basierte, reine
Markdown-Quelle von bx-sites kein Äquivalent hat. Die folgenden vier
stammen aus der eigenen
docs/functions.bxs
dieser Site und werden live auf genau dieser Seite gerendert.
Bewertungen
function $stars( required numeric rating, numeric max = 5 ) {
var filled = min( max( round( arguments.rating ), 0 ), arguments.max )
var stars = repeatString( "★", filled ) & repeatString( "☆", arguments.max - filled )
return '<span title="' & arguments.rating & ' out of ' & arguments.max & '" style="color:##f5a623;letter-spacing:2px">' & stars & '</span>'
}
`{{ $stars(4) }}` rendert als: ★★★★☆
Status-Chips
function $badge( required string label, string kind = "info" ) {
var palette = {
"info" : { "bg" : "##e0edff", "fg" : "##1d4ed8" },
"success" : { "bg" : "##dcfce7", "fg" : "##15803d" },
"danger" : { "bg" : "##fee2e2", "fg" : "##b91c1c" },
"warning" : { "bg" : "##fef9c3", "fg" : "##854d0e" }
}
var pick = palette.keyExists( arguments.kind ) ? palette[ arguments.kind ] : { "bg" : "##f1f5f9", "fg" : "##475569" }
return '<span style="display:inline-block;padding:0.1em 0.6em;border-radius:999px;font-size:0.85em;font-weight:600;background:'
& pick.bg & ";color:" & pick.fg & '">' & encodeForHTML( arguments.label ) & "</span>"
}
`{{ $badge('Stable', 'success') }}` rendert als: Stable - und `{{ $badge('Beta', 'info') }}`: Beta
Fortschrittsbalken
function $progress( required numeric percent ) {
var pct = min( max( arguments.percent, 0 ), 100 )
return '<span style="display:inline-block;width:120px;height:8px;background:##e5e7eb;border-radius:999px;overflow:hidden;vertical-align:middle"><span style="display:block;height:100%;width:'
& pct & '%;background:##2563eb"></span></span> ' & pct & "%"
}
`{{ $progress(72) }}` rendert als: 72%
Trendanzeigen
function $trend( required numeric value ) {
var isUp = arguments.value >= 0
var arrow = isUp ? "â–²" : "â–¼"
var color = isUp ? "##16a34a" : "##dc2626"
var sign = isUp ? "+" : ""
return '<span style="color:' & color & ';font-weight:600">' & arrow & " " & sign & numberFormat( arguments.value, "0.0" ) & "%</span>"
}
`{{ $trend(4.2) }}` rendert als: â–² +4.2% - `{{ $trend(-1.8) }}`: â–¼ -1.8%
Innerhalb einer Tabellenzelle
{{ }} wird gegen das rohe Markdown aufgelöst, bevor
Tabellen überhaupt geparst werden, sodass jede der
obigen Funktionen innerhalb der Zellen einer Pipe-Tabelle genauso
funktioniert wie überall sonst auf der Seite - das Nächste, was es hier zu
GitBooks eigenen Select-/Rating-Tabellenspalten gibt:
| Feature | Status | Rating |
| --- | --- | --- |
| Dark mode | {{ $badge('Stable', 'success') }} | {{ $stars(5) }} |
| Table sort | {{ $badge('Beta', 'info') }} | {{ $stars(4) }} |
Was so gerendert wird:
| Feature | Status | Rating |
|---|---|---|
| Dark mode | Stable | ★★★★★ |
| Table sort | Beta | ★★★★☆ |
Die Syntax wörtlich anzeigen
Ein {{ }}, das innerhalb eines eingezäunten Codeblocks angezeigt wird (drei
oder mehr Backticks, wie jedes Beispiel auf dieser Seite), bleibt völlig
unangetastet, statt aufgelöst zu werden - dieselbe Konvention, die dieses
Modul bereits für $...$-Mathematik und === "Tab"-Content-Tabs verwendet.
Anders als bei diesen beiden ist ein {{ }} auch innerhalb von
Inline-Code geschützt (`{{ example }}`, mit einfachen oder doppelten
Backticks) - jeder Aufzählungspunkt oben, der `{{ $discount(20) }}`
inline zeigt, ist ein echtes, funktionierendes Beispiel dafür.
Ein {{ }}, dessen Inhalt weder wie ein Variablenpfad noch wie ein
$name(...)-Aufruf aussieht - etwa die eigene {{ }}-Syntax einer anderen
Templating-Engine, in Fließtext gezeigt - bleibt unangetastet, statt als
Fehler behandelt zu werden. Nur ein Token, das aussieht wie eine Variable
oder ein magischer Funktionsaufruf, aber nicht aufgelöst werden kann, lässt
den Build fehlschlagen (siehe Fehler unten) - das ist
beabsichtigt, um einen echten Tippfehler zu erkennen, ohne unbeteiligten
{{ }}-Text als defekte Syntax misszudeuten.
Geltungsbereich
functions.bxsgilt projektweit - eine Datei, einmal geladen, derselbe Satz magischer Funktionen auf jeder Seite verfügbar, über den Haupt-Baum und jeden Versions-/Locale-Baum hinweg. Du musst sie nicht nachdocs/versions/<name>/oderdocs/i18n/<code>/duplizieren.variablesist ebenso ein einzelner, projektweiterbxsites.yaml-Block - er ist selbst nicht pro Locale übersetzbar. Ein mehrsprachiges Projekt, das unterschiedlichen Variablentext pro Sprache möchte, kann stattdessen zu einer magischen Funktion greifen, die aufsiteConfig.i18n.defaultLocale.codeverzweigt (oder den Wert einfach locale-neutral halten - einen Produktnamen, eine Support-E-Mail).
Reservierte Namen
Ein theme/page.bxm/layout.bxm-Override, das eine magische Funktion bar
aufruft ($name(...)), funktioniert, weil jede geladene Funktion -
$-präfigiert oder privater Helfer gleichermaßen - direkt in denselben
eigenen Rendering-Scope dieses Templates eingebunden wird, genau neben den
eingebauten variables.page/variables.siteConfig/etc., die jedes Theme
bereits liest. Das bedeutet, dass eine Funktion aus functions.bxs, die
sich einen Namen mit einem davon teilt, bereits einen hat: vermeide page,
nav, siteConfig, themeDir, basePath, moduleAssetsDir, versions,
currentVersion, locales, currentLocale, currentLocaleDir, strings,
requiredFiles und stringsResolver als eigenen Namen für einen privaten
Helfer (eine $-präfigierte magische Funktion kann mit keinem davon je
kollidieren, da keiner von ihnen mit $ beginnt).
Fehler
BxSites.UnknownVariable- ein{{ dotted.path }}(oder ein$name(...)-Argument, das wie eine Variablenreferenz aussieht) passt zu nichts inbxsites.yamlsvariables-Block.BxSites.UnknownFunction- ein{{ $name(...) }}-Aufruf passt zu keiner$-präfigierten Funktion indocs/functions.bxs.BxSites.InvalidFunctions-docs/functions.bxskonnte nicht geladen werden (ein BoxLang-Syntaxfehler in der Datei selbst).BxSites.InvalidConfig- der Schlüsselvariablesvonbxsites.yamlist vorhanden, ist aber kein Objekt.