Documentation Index
Fetch the complete documentation index at: https://mintlify.com/smogon/pokemon-showdown-client/llms.txt
Use this file to discover all available pages before exploring further.
BattleLog (in battle-log.ts) is responsible for turning raw protocol Args tuples into human-readable, styled HTML lines displayed in the chat/log panel of every battle room and replay. It is intentionally written without jQuery, without Preact, and without ES5+ array methods that break in Internet Explorer 7 — because the exact same class powers both the modern Preact client and the legacy replay viewer that must work in IE7+.
Class overview
Constructor
scene is provided (i.e. the log is attached to a live battle), BattleLog creates a preemptElem div for messages that should appear before animations finish, and instantiates a BattleTextParser for converting protocol lines to English. Without a scene, the log acts as a plain message renderer — suitable for the standalone replay viewer.
The perspective property
perspective to 0 or 1 enables first/second-person phrasing. BattleTextParser reads this value when generating English text, so the same protocol line produces different output depending on who is watching.
- Spectator (−1)
- Player 1 (0)
- Player 2 (1)
Core methods
add
Args tuple (e.g. ['move', 'p1a: Pikachu', 'Thunderbolt', 'p2a: Eevee']) and appends the appropriate HTML to the log. When preempt is true, the message goes into preemptElem so it appears before the current animation finishes.
Messages tagged with kwArgs.silent are silently discarded.
addDiv, addNode, message
add(). External callers should generally prefer add() for protocol lines, or addDiv()/message() for custom messages that are already sanitised.
Static helpers on BattleLog
BattleLog.formatName
Message routing inside add
add() switches on args[0] to determine how to render each line. A simplified view:
BattleTextParser integration
WhenBattleLog is constructed with a scene, it creates a BattleTextParser instance (this.battleParser). Protocol lines that describe in-battle events — |move|, |switch|, |turn|, |-damage|, etc. — are parsed through battleParser.parseArgs(args, kwArgs) which returns a human-readable string that BattleLog then wraps in a <div class="battle-history"> element.
HTML sanitisation with Caja
Chat messages from other users are sanitised through Caja (thehtml4 and html globals loaded via battle-log-misc.js) before being inserted into the DOM. This prevents XSS while still allowing trusted formatting like bold, italics, and spoiler tags.
MD5 and formatText utilities
Two functions are declared inbattle-log.ts but defined in battle-log-misc.js at runtime:
| Function | Signature | Purpose |
|---|---|---|
MD5 | (input: string) => string | Computes an MD5 hash — used for generating Gravatar avatar URLs |
formatText | (input: string, isTrusted?: boolean) => string | Applies Showdown’s chat formatting (bold, italics, spoilers, links) and sanitises with Caja |
battle-log.ts so other modules can import them from a single stable location.
Why no jQuery or Preact?
The IE7 compatibility constraint
The IE7 compatibility constraint
The replay viewer at
replay.pokemonshowdown.com must render correctly in Internet Explorer 7. jQuery 2.x dropped IE6/7/8 support, and Preact is an ES6 module that won’t parse in IE7 at all. BattleLog therefore uses only DOM Level 1 APIs (document.createElement, appendChild, innerHTML) and for loops — no Array.prototype.forEach, no template literals in hot paths, no optional chaining. This constraint is explicitly documented in the file header.Performance in long replays
Performance in long replays
Using direct DOM manipulation rather than a VDOM diff is significantly faster when appending thousands of log lines during replay fast-forward. The
addSeekEarlierButton() optimisation caps rendered lines at 2 000 steps back from the current position to keep frame times below ~2 seconds even in 1 000-turn battles.Auto-scroll behaviour
BattleLog tracks whether the user has scrolled up (reading old messages) via an onscroll handler:
atBottom is true, preserving the user’s reading position when they scroll up to review earlier moves.