PostCSS aims for byte-to-byte equal output, but the stringifier dropped a
leading byte order mark: `parse('a{}').toString()` returned `a{}`. The
BOM is already detected (`Input#hasBOM`) but was never re-emitted, so the
`bom.css` round-trip test had to be skipped.
Emit the BOM in `Stringifier#root` when the source had one, and re-enable the
previously skipped test.
A custom property declaration that is the last non-comment child but is
followed by comment siblings was stringified without its terminating
semicolon. Unlike a normal declaration, a custom property keeps everything
up to the next `;` or `}` as its value, so on re-parse the trailing
comments were folded into the value and the comment nodes disappeared.
Building such a tree with append()/insertAfter()/after() therefore
silently dropped the comments. Emit the semicolon when a custom property
still has following siblings so the output round-trips, mirroring the
existing handling for childless at-rules.
A childless (statement) at-rule that is the last non-comment child but is
followed by comment siblings was stringified without its terminating
semicolon. On re-parse the trailing comments were folded into the
at-rule prelude and dropped, so building such a tree with append() or
insertBefore() silently lost the comment nodes.
Emit the semicolon when a childless at-rule still has following siblings
so the output round-trips.
Cache node.raws references locally in hot methods (atrule, block, body,
comment, decl) to avoid repeated property chain resolution. In decl(),
inline the common rawValue() path when node.raws.value exists. In raw(),
cache root.rawCache in a local variable. In body(), short-circuit
raw(child, 'before') when child.raws.before is already defined. In
block() and comment(), inline the raws check to skip raw() call overhead
when the value is already present.