Reverse Text

Eight transformations, none of them clever, and the useful distinction between them is what stays intact. Flipping line order preserves every field in a CSV; flipping characters shreds it.

Reverse Text Tool — Flip Characters, Words or Lines, and Clean Up SpacingBuildFigure

Four different things people mean by "reverse"

Reversing text is ambiguous until you say what the unit is, and the four options here cover the cases that actually come up. Reversing characters across the whole input turns abc\ndef into fed\ncba, with the line break itself carried along in the flip. Reversing characters within each line keeps the lines where they are and only flips their contents. Reversing word order leaves each word spelled correctly and reorders them within a line. Reversing line order touches nothing inside a line and flips the file top to bottom, which is the one people reach for most often — chronological logs, exports that came out oldest-first, a list that needs to read the other way.

Line-order reversal is worth pointing out for a practical reason: it is the only one of the four that is safe on structured data. If your text is CSV or TSV, flipping lines keeps every field intact, while flipping characters destroys it. Watch the header row, which ends up at the bottom.

Why the reversal is done in code points

The naive implementation of string reversal in JavaScript is s.split('').reverse().join(''), and it is broken for a large fraction of real text. JavaScript strings are sequences of UTF-16 code units, and any character above U+FFFF — every emoji, mathematical alphanumeric, and a good many CJK extension characters — is stored as two units called a surrogate pair. Splitting on units separates that pair, and reversing the halves produces an invalid sequence that renders as two replacement characters. A rocket emoji goes in and two black diamonds come out.

Everything here uses Array.from, which iterates by code point and keeps surrogate pairs together, so emoji survive. The character counts shown with the result are code point counts for the same reason, and when the two differ you get an extra line telling you how many UTF-16 units the input was — that gap is exactly the number of astral characters present, and it is the number that matters if you are checking against a database column limit or an SMS segment count.

Code points are still not quite the same as what a reader would call a character, and this is the honest limit of the approach. A base letter followed by a combining accent is two code points that display as one glyph, and reversing them puts the accent before the letter, where it will attach to whatever now precedes it. Text in normalised form NFC mostly avoids this, since é is stored as one code point there rather than two, but text pasted out of some systems is NFD and will misbehave. Devanagari, Thai and emoji sequences joined with zero-width joiners have the same issue more severely — a family emoji is several code points and one grapheme, and reversal will take it apart.

Full-width and half-width

Full-width forms are the Latin letters, digits and punctuation redrawn to occupy one full CJK character cell instead of half of one. They live at U+FF01 to U+FF5E, offset exactly 0xFEE0 above their ASCII equivalents, which is why the conversion in both directions is a single addition. The ideographic space U+3000 pairs with the ordinary space separately.

They arrive in Western data more often than you would expect: anything typed on a Japanese, Chinese or Korean input method with the wrong mode active, product codes from an Asian supplier, spreadsheet exports where a column was formatted for CJK text. The characters look almost right, so the problem shows up downstream — a part number that will not match, a lookup that silently fails, a search that returns nothing. Running a column through half-width conversion before importing it is a five-second fix for a bug that otherwise takes an afternoon to find.

Whitespace, and the traps in it

Removing all spaces takes out ordinary spaces, tabs and ideographic spaces, and it does not touch line breaks. Collapsing runs to one space also trims each line at both ends, which is the behaviour you want before comparing lines or importing them.

What neither one does is deal with the invisible characters that are not spaces. Non-breaking spaces, U+00A0, are everywhere in text pasted out of a web page or a word processor, and they look identical to a space while matching neither a literal space nor \s in some regex flavours. Zero-width spaces and zero-width joiners occur in text copied from PDFs and from some CMSs. If a line still refuses to match after collapsing whitespace, that is very often what is left, and the character count here is the fastest way to catch it: a string that counts longer than the characters you can see has something invisible in it. Which one it is takes a hex view, and the byte layout table on the text to binary converter will show you.

Questions people ask

Do emoji survive being reversed?

Single emoji do. Reversal iterates by code point rather than by UTF-16 unit, so a surrogate pair stays together instead of being split into two invalid halves — which is what the common one-line implementation of string reversal does. Composite emoji are a different matter: a family or a flag or a skin-toned figure is several code points joined by zero-width joiners or modifiers, and reversing pulls that sequence apart into its components. Nothing short of full grapheme cluster segmentation handles those, and that is beyond what this does.

Why does the character count not match what my editor says?

Different tools count different things. This counts code points. Many editors and most database column limits count UTF-16 units, where anything above U+FFFF counts as two. A byte count is different again and depends on the encoding — in UTF-8 an ASCII character is one byte and an emoji is usually four. When the input contains astral characters, this shows both the code point count and the UTF-16 unit count so you can see which number a limit elsewhere is likely to be enforcing.

Can I get upside-down or mirrored text out of this?

No, and the distinction is worth making because they are often confused. Reversing changes the order of characters. Upside-down text substitutes each letter for a different Unicode character that happens to look like it rotated — a turned e, an inverted exclamation mark, and so on. That is a lookup table of visually similar glyphs, not a transformation, and the result is text that no longer contains the letters it appears to contain. It breaks search, screen readers and anything that processes the string.

Is this safe to run on a CSV?

Only the line-order and whitespace modes. Reversing line order preserves every field and every delimiter, so it is a legitimate way to flip an export from oldest-first to newest-first — just move the header row back to the top afterwards. Collapsing whitespace is usually safe but will trim leading and trailing spaces inside unquoted fields, which occasionally matters. Reversing characters or word order will destroy the structure. There is no CSV parsing here at all; it is plain text throughout.

Related