Literals & Adjacency
Text you meant as literal stays literal, and two adjacent tokens never silently merge into a
different token when the output is read back. rosetta-date calls this guarantee round-trip
safety at the token boundary.
Literals
Literal (verbatim) text is preserved across dialects, even though each dialect escapes it differently:
momentbrackets[...]↔ldmlquotes'...'.- A literal apostrophe is
''inldml(e.g.'o''clock'→o'clock). - Only the letter-bearing span is escaped, so separators stay clean:
DD/MM↔dd/MM, notdd'/'MM. - A literal
]has no in-band escape inside a moment[...]run, so it is emitted between bracketed spans (e.g.a]b→[a]][b]); the text still round-trips intact.
Adjacent tokens
When a conversion would place two tokens that collide — i.e. reading the output back would lex
them as one different token — rosetta-date separates them with the target dialect’s empty
literal.
For example, date-fns PPPp (a long date next to a short time) becomes moment LL + LT. But
gluing them as LLLT would re-read as LLL (the long localized date preset) + T, a different
parse. So the converter inserts []:
import { convert } from 'rosetta-date'
import { dateFns, momentjs } from 'rosetta-date/libraries'
convert('PPPp', { from: dateFns, to: momentjs }) // 'LL[]LT' — '[]' keeps LL and LT apartWhen a dialect has no empty literal
A quote-style dialect like ldml has no empty literal — '' is a literal apostrophe, not nothing —
so it cannot express such an adjacency. There the second token is routed through
onUnsupportedToken with reason unrepresentable-adjacency:
- the default emits it anyway (matching the merged output), while
'throw'lets a mass migration catch it.
This is why adjacency is one of the four unsupported-token reasons rather than a silent fix-up: in a quote-style target the merge is genuinely unrepresentable, and you may want to know.