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.

§ Changelog

See it in the monorepo opens in a new tab, on Sourcehut.

§ Licence

MIT opens in a new tab

Copyright © 2010–2020 Roy Revelt and other contributors

Related packages:

📦 detergent 6.1.1
Extracts, cleans and encodes text
📦 html-img-alt 1.5.3
Adds missing alt attributes to img tags. Non-parsing
📦 string-find-heads-tails 3.17.0
Finds where are arbitrary templating marker heads and tails located
📦 string-uglify 1.3.4
Shorten sets of strings deterministically, to be git-friendly
📦 string-extract-sass-vars 1.3.0
Parse SASS variables file into a plain object of CSS key-value pairs
📦 string-range-expander 1.12.0
Expands string index ranges within whitespace boundaries until letters are met
📦 string-trim-spaces-only 2.9.0
Like String.trim() but you can choose granularly what to trim