Skip to content

Commit ac364bd

Browse files
committed
Update new MiniMessage language specification
1 parent 483673f commit ac364bd

File tree

2 files changed

+96
-75
lines changed

2 files changed

+96
-75
lines changed

src/content/docs/adventure/minimessage/specification.md

Lines changed: 61 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,27 @@ plain text part of a MiniMessage-formatted string:
2525

2626
```mm
2727
The MiniMessage format was made to be as simple as possible.
28-
Emojies are allowed 😅. So are japanese characters, like 紙.
28+
Emojis are allowed 😅. So are Japanese characters, like 紙.
2929
```
3030

31-
MiniMessage tags are primarily used for adding markup information to plain text parts. They can, however,
31+
MiniMessage tags are primarily used for adding markup information to plain text parts. However, they can
3232
also add entirely new content into the serialized component. The way how a tag is resolved makes no
33-
difference to the MiniMessage lexer. A tag has the following structure:
33+
difference to the MiniMessage lexer.
34+
35+
There are two types of tags: sequential and named ones:
3436

3537
```mm
36-
<tagname flags named_argument=value :a sequenced argument:another one>
38+
; Note that these comments are not part of the MiniMessage specification
39+
; and are only here to explain something in-code.
40+
41+
; An example of a tag with named arguments:
42+
<named="a sequenced argument":"another one" flags named_argument=value>
43+
44+
; An example of a tag with sequential arguments:
45+
<sequential:the first value of the argument stack:the second one!>
46+
47+
; A tag can also have no arguments at all:
48+
<empty_tag>
3749
```
3850

3951
A tag consists of the following parts:
@@ -83,7 +95,7 @@ This tag is auto-closed: <tagname/>
8395
Arguments are placed between the tag name and the closing more-than symbol.
8496

8597
```mm
86-
<tagname [arguments here]>
98+
<tagname[arguments here]>
8799
```
88100

89101
### Named argument types
@@ -142,8 +154,17 @@ These two named types can be combined in any way.
142154

143155
### Sequential arguments
144156

145-
Sequential arguments are declared at the end of the tag. Each sequential argument starts with a colon `:`.
146-
Unless named arguments are present, a whitespace before the first colon `:` is not necessary.
157+
Sequential arguments can be used either exclusively or inclusively. Exclusive/inclusive here refers to whether
158+
a tag with sequential arguments present may also contain named arguments.
159+
160+
The formats are as following:
161+
162+
- Exclusive: `<tag:arg 1:arg 2:...:arg n>`.
163+
- Inclusive: `<tag=arg 1:arg 2:...:'arg n' named_args>`
164+
165+
Sequential arguments are separated using a colon `:`.
166+
In inclusive format, only the *last* sequential argument may need to be quoted to ensure
167+
extra whitespace is not treated as a separator between named arguments.
147168

148169
Sequential arguments may contain any UTF-16 characters. Any instances of `<`, `>`, or `:` characters
149170
must either be escaped (see [misc/escaping](#escaping)) or the argument must be wrapped in quotes
@@ -152,14 +173,19 @@ must either be escaped (see [misc/escaping](#escaping)) or the argument must be
152173
The following are valid MiniMessage tags with sequential arguments:
153174

154175
```mm
176+
; [hey there]
155177
<simpletag:hey there>
156178
179+
; [first argument,second argument]
157180
<another:first argument:second argument>
158181
182+
; [this is perfectly fine]
159183
<with_whitespace :this is perfectly fine>
160184
185+
; [<some_cool_tag and a : colon!]
161186
<nested_mm:\<some_cool_tag\> and a \: colon!>
162187
188+
; [<some_cool_tag> and a : colon, but it's quoted!]
163189
<nested_mm:"<some_cool_tag> and a : colon, but it's quoted!">
164190
```
165191

@@ -168,19 +194,17 @@ The following are valid MiniMessage tags with sequential arguments:
168194
Named and sequential arguments can be used together. The general syntax looks as follows:
169195

170196
```mm
171-
<tagname[ named_arguments ][:sequenced:arguments]>
197+
<tagname[=sequenced:arguments][ named_arguments]>
172198
```
173199

174-
All named arguments must be located between the tag name and the first non-value colon.
175-
176200
A few examples for valid tags making use of both named and sequenced arguments:
177201

178202
```mm
179-
<combined coolness=true flags :and sequenced args>
203+
<combined='and sequenced args' coolness=true flags>
180204
181-
<combined flags !over more_flags and even !more flagss :I'd call this cool:Would you?:Yeah for sure>
205+
<combined=I'd call this cool:Would you?:'Yeah for sure' flags !over more_flags and even !more flagss>
182206
183-
<combined tic=tac :time's up!>
207+
<combined="time's up!" tic=tac>
184208
```
185209

186210
## Misc
@@ -190,10 +214,11 @@ This section defines miscellaneous behavior of common parts.
190214
### Identifiers
191215

192216
All identifiers must be lowercased and contain only alphanumerical characters, `_`, or '-'. All identifiers
193-
used as named argument names should be unique.
217+
used as named argument names should be unique. Identifiers may start with a single exclamation mark `!`.
194218

195219
### Quoting
196-
Argument values can be quoted. A value counts as quoted if the first character is a `'` or `"`. The quoted
220+
221+
Argument values can be quoted. A value is treated as quoted if the first character is a `'` or `"`. The quoted
197222
value ends as soon as another unquoted quote of the same character as the starting quote is found at the
198223
end of an argument.
199224

@@ -231,50 +256,50 @@ symbol. If a backlash character had no effect, it is included literally.
231256
This segment declares the formal grammar (in a flavor of the Backus-Naur form) which specifies the MiniMessage language.
232257

233258
The specific flavor used here changes that non-terminal symbols are no longer enclosed in angle brackets `<>`
234-
and the `::=` meta symbol is replaced by ``. Curly brackets `{}` declare optional parts. Lastly, a `+` suffix
235-
declares that a symbol should appear at least once, but may appear more often, whilst a `*` suffix declares that
236-
a symbol may appear once or more often.
259+
and the `::=` meta symbol is replaced by ``. Curly brackets `{}` declare optional parts. `()` is used to
260+
group elements together. Lastly, a `+` suffix declares that a symbol must appear at least once, but may appear
261+
more often, whilst a `*` suffix declares that a symbol may appear zero or more times.
237262

238-
```bnf
263+
```bnf title="Formal Grammar"
239264
; Important notes regarding this specific grammar: due to the massive number of characters included
240265
; in the UTF-16 characterset, some special non-terminal symbols have been added:
241266
;
242267
; utf-16-char → includes all UTF-16 characters.
243268
;
244-
; utf-16-char-no-whitespace → includes all UTF-16 characters except for spaces (\s), tabs (\t), newlines (\n)
245-
; and carriage returns (\r).
269+
; utf-16-char-no-whitespace → includes all UTF-16 characters except for spaces (\s), tabs (\t),
270+
; newlines (\n) and carriage returns (\r).
246271
;
247272
; utf-16-char-no-angle-or-colon → includes all UTF-16 characters except for the
248273
; angle-bracket characters (<>) and colon (:). However
249274
; those characters are valid if an uneven number of backslash
250275
; characters is located infront of them.
251276
252-
minimessage → string {tag string}
277+
minimessage → {tag} {utf-16-char} {minimessage}
253278
254-
string → utf-16-char*
279+
; Note that the closing tag identifier should be the same as the opening one.
280+
tag → "<" identifier tag-arguments "/>"
281+
tag → "<" identifier tag-arguments ">" minimessage {"</" identifier ">"}
255282
256-
tag → "<" tag-name tag-arguments "/>"
257-
tag → "<" tag-name tag-arguments ">" minimessage {"</" tag-name ">"}
283+
tag-arguments → (":" sequential-value)+
284+
| {sequential-arguments} named-argument*
258285
259-
tag-name → identifier
286+
sequential-arguments → "=" {sequential-value ":"}* sequential-quoted
260287
261-
tag-arguments → "" | named-argument " "+ sequential-argument | named-argument | " "* sequential-argument
288+
sequential-quoted → "" | quoted | no-whitespace-string
262289
263-
named-argument → "" | " "+ {"!"} identifier {named-argument} | " "+ identifier "=" named-value {named-argument}
264-
265-
named-value → "" | quoted | no-whitespace-string
290+
sequential-value → "" | quoted | sequential-string
266291
267-
no-whitespace-string → utf-16-char-no-whitespace*
292+
named-argument → "" | " "+ identifier {"=" named-value} {named-argument}
268293
269-
sequential-argument → ":" sequential-value {sequential-argument}
294+
named-value → "" | quoted | no-whitespace-string
270295
271-
sequential-value → "" | quoted | sequential-string
296+
sequential-string → utf-16-char-no-angle-or-colon+
272297
273-
sequential-string → utf-16-char-no-angle-or-colon*
298+
no-whitespace-string → utf-16-char-no-whitespace+
274299
275-
quoted → "'" string "'" | """ string """
300+
quoted → "'" utf-16-char* "'" | '"' utf-16-char* '"'
276301
277-
identifier → alphanumeric+
302+
identifier → {"!"} alphanumeric+
278303
279304
alphanumeric → "a" | "b" | "c" | "d"
280305
| "e" | "f" | "g" | "h"

src/utils/shiki/bnf.tmLanguage.json

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
33
"name": "bnf",
44
"scopeName": "source.bnf",
5-
"patterns": [{ "include": "#comment" }, { "include": "#rule" }, { "include": "#meta" }, { "include": "#strings" }],
5+
"patterns": [
6+
{ "include": "#comment" },
7+
{ "include": "#rule" },
8+
{ "include": "#meta" },
9+
{ "include": "#strings" },
10+
{ "include": "#text" }
11+
],
12+
613
"repository": {
714
"comment": {
815
"name": "comment.line.semicolon.bnf",
@@ -11,37 +18,34 @@
1118

1219
"rule": {
1320
"name": "meta.rule.bnf",
14-
"begin": "^(\\s*)([A-Za-z0-9_-]+)(\\s*→)",
15-
"beginCaptures": {
16-
"2": { "name": "entity.name.function.nonterminal.bnf" },
17-
"3": { "name": "keyword.reserved.arrow.bnf" }
18-
},
19-
"end": "(?=^\\s*[A-Za-z0-9_-]+\\s*→|\\Z)",
20-
"patterns": [
21-
{ "include": "#tripleQuotedNonterminal" },
22-
{ "include": "#strings" },
23-
{ "include": "#meta" },
24-
{
25-
"match": "\\b[A-Za-z0-9_-]+\\b",
26-
"name": "variable.language.nonterminal.bnf"
27-
}
28-
]
21+
"match": "([A-Za-z0-9_-]+)(\\s*→)",
22+
"captures": {
23+
"0": { "name": "entity.name.function.nonterminal.bnf" },
24+
"1": { "name": "keyword.reserved.arrow.bnf" }
25+
}
2926
},
3027

31-
"tripleQuotedNonterminal": {
32-
"name": "meta.triplequoted.nonterminal.bnf",
33-
"begin": "\"{3}",
34-
"beginCaptures": {
35-
"0": { "name": "string.quoted.double.bnf" }
36-
},
37-
"end": "\"{3}",
38-
"endCaptures": {
39-
"0": { "name": "string.quoted.double.bnf" }
40-
},
28+
"meta": {
4129
"patterns": [
4230
{
43-
"match": "\\b[A-Za-z0-9_-]+\\b",
44-
"name": "variable.language.nonterminal.bnf"
31+
"match": "",
32+
"name": "keyword.reserved.arrow.bnf"
33+
},
34+
{
35+
"match": "\\|",
36+
"name": "keyword.reserved.choice.bnf"
37+
},
38+
{
39+
"match": "[{}()]",
40+
"name": "comment.punctuation.section.group.bnf"
41+
},
42+
{
43+
"match": "\\+",
44+
"name": "comment.punctuation.quantity.bnf"
45+
},
46+
{
47+
"match": "\\*",
48+
"name": "comment.punctuation.quantity.bnf"
4549
}
4650
]
4751
},
@@ -62,19 +66,11 @@
6266
]
6367
},
6468

65-
"meta": {
69+
"text": {
6670
"patterns": [
6771
{
68-
"match": "",
69-
"name": "keyword.reserved.arrow.bnf"
70-
},
71-
{
72-
"match": "\\|",
73-
"name": "keyword.reserved.choice.bnf"
74-
},
75-
{
76-
"match": "[{}()]",
77-
"name": "punctuation.section.group.bnf"
72+
"name": "variable.language.bnf",
73+
"match": "[a-z0-9-]+"
7874
}
7975
]
8076
}

0 commit comments

Comments
 (0)