Replace all n/m dashes, curly quotes with their simpler equivalents

§ Quick Take

import { strict as assert } from "assert";
import unfancy from "string-unfancy";

// U+2019
const rightSingleQuote = "\u2019";


// works with encoded HTML:
assert.equal(unfancy("someone’s"), "someone's");

§ Idea

Convert typographically-correct characters (like curly quotes or m-dashes) to their basic counterparts (like apostrophes or hyphens).

It's the opposite of detergent and string-apostrophes.

It's used in ASCII-restricted places where encoding is too unwieldy, for example, image alt attribute values in email templates.



Caveat: if the input is not a string it will throw.

Function returns a string.

§ Example - Gulp streams

If you are using Gulp to build email templates, you can tap the stream, apply a function to it, then within that function, replace opens in a new tab all instances of alt="..." with their unfancied versions.

First, you need to require gulp-tap opens in a new tab and string-unfancy:

const tap = require("gulp-tap");
const unfancy = require("string-unfancy");

Then, tap your main build task's stream, probably towards the end of the pipeline:

.pipe(tap((file) => {
file.contents = Buffer.from(unfancy(file.contents.toString()))
.pipe(gulp.dest('dist')) // that's the final write happening, yours might be different

Then, declare a function somewhere within your gulpfile.js:

function unfancy(input) {
input = input.replace(/alt="[^"]*"/g, (el) => {
return unfancy(el);
return input;

As you see above, we're running an inline function opens in a new tab upon all regex-matched characters.

And that's it! All image alt attributes will lose their HTML encoding and will have their fancy special characters converted to simple ASCII letter equivalents.

§ Can we use lodash.deburr instead?

No. It won't even convert opens in a new tab a single m-dash! It's a different tool for a different purpose.

§ Licence

MIT opens in a new tab

Copyright © 2010–2020 Roy Revelt and other contributors

Related packages:

📦 detergent 5.11.10
Extracts, cleans and encodes text
📦 html-img-alt 1.4.65
Adds missing alt attributes to img tags. Non-parsing
📦 string-convert-indexes 2.0.2
Convert between native JS string character indexes and grapheme-count-based indexes
📦 string-extract-class-names 5.9.32
Extract class (or id) name from a string
📦 string-collapse-leading-whitespace 3.0.2
Collapse the leading and trailing whitespace of a string
📦 string-match-left-right 4.0.14
Match substrings on the left or right of a given index, ignoring whitespace
📦 string-find-malformed 1.1.16
Search for a malformed string. Think of Levenshtein distance but in search