Tag Reference
This page covers every non-effect span tag in ETA markup. Each section shows accepted attributes, defaults (drawn from MarkupParser.java), and a usage example. Effect tags (rainbow, wave, shake, etc.) are handled by the effects pipeline and documented in the Effects catalog.
Entry shape: tag name, one-line summary, syntax block, parameter table, example, and notes where behavior isn’t obvious.
Text style tags
Section titled “Text style tags”bold (b), italic (i), underline (u), strikethrough (s), and obfuscated (obf) apply the corresponding vanilla ChatFormatting style to their content. None of them take attributes.
| Tag | Alias | Effect |
|---|---|---|
bold | b | Bold weight |
italic | i | Italic slant |
underline | u | Underline decoration |
strikethrough | s | Strikethrough decoration |
obfuscated | obf | Vanilla obfuscation (random character cycling) |
Example
<b>Bold</b>, <i>italic</i>, <u>underline</u>, <s>struck</s>, <obf>????</obf>Notes
obfuscated is vanilla MC’s random-character cycling (equivalent to ChatFormatting.OBFUSCATED). It’s distinct from the obfuscate effect tag, which is an ETA animation with speed and mode controls. See the Effects catalog for obfuscate.
Source: MarkupParser.java
Sets a static text color. When value contains a comma or the col attribute is present, the parser treats the tag as a gradient and forwards it to GradientEffect instead.
Syntax
<color value=RRGGBB>text</color><c #FF8800>text</c>Parameters
| Name | Alias | Type | Default | Description |
|---|---|---|---|---|
value | positional first token | hex string | none (required) | Color in hex (FF8800, #FF8800, or named). When this value contains a comma the tag is forwarded to GradientEffect. |
color | — | hex string | none | Explicit named attribute; checked before value when resolving a static color. |
col | — | any | — | When present, the tag is always forwarded to GradientEffect regardless of value. Used to supply additional gradient stops. |
Example
<color value=FF8800>Orange text</color><c #FF8800>Also orange</c>Notes
The resolution order for static color is: color attribute first, then value. Gradient forwarding check happens before either: if value contains , or col is present, the tag acts as a gradient and the color attribute is not consulted for static color. See the Effects catalog for gradient usage.
Source: MarkupParser.java
Sets the rendering font for the enclosed text. When bold is active on the same span and the selected font has a registered _bold variant, the parser automatically switches to that variant.
Syntax
<font id=norse>text</font><font name=cinzel>text</font>Parameters
| Name | Alias | Type | Default | Description |
|---|---|---|---|---|
id | value, font, name | string | — | Font alias or full namespace:path resource location. |
The four attribute names are checked in order: id, value, font, name. The first non-null value wins.
Built-in aliases
| Alias | Resource location | Bold variant |
|---|---|---|
norse | emberstextapi:norse | emberstextapi:norse_bold |
norse_bold | emberstextapi:norse_bold | — |
metamorphous, meta | emberstextapi:metamorphous | none registered |
cinzel | emberstextapi:cinzel | emberstextapi:cinzel_bold |
cinzel_bold | emberstextapi:cinzel_bold | — |
almendra | emberstextapi:almendra | emberstextapi:almendra_bold |
almendra_bold | emberstextapi:almendra_bold | — |
cardo | emberstextapi:cardo | emberstextapi:cardo_bold |
cardo_bold | emberstextapi:cardo_bold | — |
Any full resource location string (mymod:myfont) is accepted directly; no alias registration required.
Example
<font id=norse>Runic inscription</font><bold><font id=cinzel>Chapter Title</font></bold>In the second example, bold is active when the span is created, so the parser replaces emberstextapi:cinzel with emberstextapi:cinzel_bold automatically.
Notes
The auto-bold switch happens in createSpanWithCurrentStyles, not in applyTagToSpan. It runs at span creation time, not at tag-push time, so the font slot on the style stack still holds the base font. Only the resolved TextSpan that carries content gets the bold variant.
metamorphous has no bold variant registered in FontAliasRegistry (it’s added to NO_BOLD_VARIANT), so the switch is skipped for it.
Source: MarkupParser.java
Translation (lang)
Section titled “Translation (lang)”Resolves a Minecraft translation key to the viewer’s locale. The substitution runs before span parsing, so the resolved text slot into the span structure but ETA tags written inside a .lang file are not re-parsed.
Syntax
<lang:item.minecraft.diamond><lang key=item.minecraft.diamond><lang key='commands.give.success.single' args='1,Diamond,Steve'>Parameters
| Name | Alias | Type | Default | Description |
|---|---|---|---|---|
key | positional first token in attribute form | string | "" | Translation key to resolve. |
args | — | comma-separated string | none | Positional substitution arguments for %s placeholders. Quote the whole value if any token contains whitespace. |
Example
You picked up <lang:item.minecraft.diamond>.<lang key='commands.give.success.single' args='1,Diamond,Steve'>Notes
Two forms are accepted by the LANG_TAG regex:
- Shorthand
<lang:KEY>: the part after:is the key directly, no attributes parsed. - Attribute form
<lang key=... args=...>: standard attribute parsing.keycan also be supplied asvalue(positional first token).
Resolution uses Language.getInstance().getOrDefault(key) for zero-arg lookups, and Component.translatable(key, args).getString() when args is supplied. Missing keys render as the key string itself, matching Component.translatable’s default. If the resolver throws, the key string is returned.
Translation values are treated as plain text by ETA. Any ETA markup that happens to appear inside a .lang file is not re-parsed.
Source: MarkupParser.java
Attaches a click event to the enclosed text.
Syntax
<click action=open_url value=https://example.com>Visit</click><click link=https://example.com>Visit</click>Parameters
| Name | Alias | Type | Default | Description |
|---|---|---|---|---|
action | — | string | — | Click action type. See accepted values below. |
value | — | string | — | Target URL, command string, page number, or clipboard text. |
link | — | string | — | Shorthand for action=open_url value=<link>. Ignored when action is also present. |
Accepted action values
| Value | Canonical form | Behavior |
|---|---|---|
open_url | open_url | Opens a URL in the system browser. |
run_command | run_command | Runs a command as the clicking player. |
suggest_command | suggest_command | Places a command in the chat input box. |
copy_to_clipboard, copy | copy_to_clipboard | Copies value to the clipboard. |
change_page | change_page | Changes the page in a book. |
Example
<click link=https://tysontheember.dev>Visit the site</click><click action=run_command value=/home>Go home</click>Notes
If both link and action are present, action takes precedence and a warning is logged. An unrecognized action value logs a warning and the click event is not applied. A missing value also logs a warning and the event is skipped.
Source: MarkupParser.java
Attaches a hover tooltip to the enclosed text.
Syntax
<hover text="Tooltip text">Hover over me</hover><hover action=show_text value="Tooltip text">Hover over me</hover>Parameters
| Name | Alias | Type | Default | Description |
|---|---|---|---|---|
action | — | string | — | Hover action type. Only show_text is currently supported. |
value | — | string | — | The tooltip text to display. |
text | — | string | — | Shorthand for action=show_text value=<text>. Ignored when action is also present. |
Example
<hover text="Forged in the nether">Netherbane</hover>Notes
In v3.0.0-beta.1, only show_text is a supported action. Any other action value logs a warning and the hover event is not applied. A missing value also logs a warning and the event is skipped.
Source: MarkupParser.java
Inline content
Section titled “Inline content”Renders an inline item icon. Accepts both wrapping and self-closing forms.
Syntax
<item value=minecraft:diamond/><item id=minecraft:diamond size=2 x=0 y=-2/><item value=minecraft:sword>Sword</item>Parameters
| Name | Alias | Type | Default | Description |
|---|---|---|---|---|
value | positional first token | resource location string | none (required) | Item registry ID. |
id | — | resource location string | none | Explicit named attribute for item ID. Checked after value. |
size | count | integer | 1 | Stack size displayed on the icon. |
offsetx | x | float | 0 | Horizontal render offset in pixels. |
offsety | y | float | 0 | Vertical render offset in pixels. |
nbt | — | SNBT string | none | NBT data for the item. |
Example
Reward: <item value=minecraft:diamond size=3/>Notes
The resolution order for the item ID is value attribute first (or the positional first token), then id. When both are present, value wins.
In wrapping form (<item ...>text</item>), the closing tag triggers the inline render at that position; the text content of the tag is not rendered as item label. The item icon is emitted as a separate TextSpan with empty content.
If size can’t be parsed as an integer, the parser logs at DEBUG and falls back to 1. Offset parse failures similarly fall back to 0.
Source: MarkupParser.java
Entity
Section titled “Entity”Renders an inline entity portrait. Accepts both wrapping and self-closing forms.
Syntax
<entity value=minecraft:zombie/><entity id=minecraft:creeper scale=1.5 yaw=30 spin=1/>Parameters
| Name | Alias | Type | Default | Description |
|---|---|---|---|---|
value | positional first token | resource location string | none (required) | Entity type registry ID. |
id | — | resource location string | none | Explicit named attribute for entity ID. |
scale | — | float | 1.0 | Render scale. |
offsetx | x | float | 0 | Horizontal render offset in pixels. |
offsety | y | float | 0 | Vertical render offset in pixels. |
yaw | — | float | 45 | Yaw rotation in degrees. |
pitch | — | float | 0 | Pitch rotation in degrees. |
roll | — | float | 0 | Roll rotation in degrees. |
lighting | light | integer | 15 | Lighting level for the entity render (0-15). |
spin | rotate | float | none | Continuous spin speed. Omit to disable. |
animation | anim | string | "idle" | Animation state to play. |
nbt | — | SNBT string | none | NBT data for the entity. |
Example
Watch out for <entity value=minecraft:creeper scale=1.2 yaw=20/>!Notes
Rotation defaults apply only when any rotation attribute is set. If none of yaw, pitch, or roll appear on the tag, span.entityRotation is called with the code defaults (yaw=45, pitch=0, roll=0).
spin/rotate is only applied when the attribute is present. When absent, no spin is set on the span (there is no always-applied default).
Source: MarkupParser.java
Duration (dur)
Section titled “Duration (dur)”Embeds a display duration in the markup string. This is extracted by a separate method (extractDuration) before any span parsing occurs.
Syntax
<dur:N>Where N is a positive number (integer or decimal float, e.g. 60, 2.5).
Example
<dur:100> <rainbow>Quest complete!</rainbow>Notes
<dur:N> is not a span tag and is not processed by TAG_PATTERN. It’s matched by its own regex <dur:(\d+(?:\.\d+)?)>. Only the first match is consumed; subsequent <dur:...> occurrences in the same string are left as literal text.
When no <dur:N> is found, extractDuration returns -1 for the duration value, signaling to the caller that no override was specified.
Callers that use parse directly instead of extractDuration will not strip this tag, and <dur:...> will appear as unmatched text (the TAG_PATTERN colon would need to be in the first character position to even try to match, but dur matches the tag name and :N> would be the attribute string; in practice the colon-form <dur:N> is handled by the dedicated regex, not the span parser).
Source: MarkupParser.java
Presets
Section titled “Presets”Any datapack-registered preset name is usable as a tag directly. When the parser encounters an unknown tag name it falls through to PresetRegistry.get(tagName). If a matching preset is found, its style overrides and effects are applied to the span.
<my_preset>Styled text</my_preset>See Presets for the preset schema and the bundled preset list.
The eta- prefix
Section titled “The eta- prefix”Inside Patchouli book entries, if a book defines a macro for an unprefixed name (for example "<b>": "$(l)"), the macro takes precedence and ETA never sees that tag. Writing <eta-bold> instead sidesteps the collision: Patchouli is unlikely to have a macro named eta-bold, so the ETA tag survives the Patchouli pipeline intact.
Because eta- names contain a hyphen they pass through ETA’s span parser unchanged. The mechanism that makes them useful in Patchouli is that Patchouli does not consume them (no matching macro), so the text containing <eta-bold> reaches ETA where, critically, ETA also cannot parse it, since the hyphen breaks the regex match.
In practice this convention is only useful when Patchouli’s own macro processing has been configured to map the raw tag string back to a form ETA can handle, or when the Patchouli pipeline leaves the full string intact for ETA to post-process at a later stage. Outside Patchouli contexts, use unprefixed tag names.
Source reference: README.md: Patchouli Compatibility