Skip to Content
  • Website
Codsen
  • Home
  • Open Source
  • Articles
  • About

prevOpen Source→string-apostrophesnext

string-apostrophes4.2.6

Comprehensive, HTML-entities-aware tool to typographically-correct the apostrophes and single/double quotes

Downloads per monthChangelogMIT Licenselibera manifesto
  • the top
  • Installation
  • Quick Take
  • Examples
  • IDEA
  • API — CONVERTALL()
  • API — CONVERTONE()
  • OPTS — OFFSETBY
  • OPTS — VALUE
  • API — DEFAULTS
  • API — VERSION
  • API — TYPES
  • COMPARED TO…
  • Changelog

No 3rd party dependencies. All dependencies and devDependencies, checked recursively, are Codsen packages.

Permalink to InstallationInstallation

Permalink to Quick TakeQuick Take

Permalink to ExamplesExamples

  • Convert one apostrophe into an entity
  • Supply the apostrophe value separately
  • Disable the apostrophe conversion
  • Convert double quotation marks
  • Convert the quotes into HTML entities
  • Convert measurement primes
  • Convert nested quotations
  • Report the index offsets through a callback

Idea

As you know, straight apostrophes are not always typographically-correct: John's should be John’s, with right single quoteopens in a new tab instead of apostropheopens in a new tab.

This program corrects apostrophes and single and double quotation marks, and recognizes measurement primesopens in a new tab. Use convertAll() for literal characters and convertOne() for a known span, including an HTML entity whose decoded value you supply.

Sources used in rules logic and unit tests:

  • Oxford A–Z of Grammar and Punctuation 2nd Ed., 2009, ISBN 978–0199564675opens in a new tab
  • Butterick’s Practical Typography 2nd Ed., “Apostrophes” chapteropens in a new tab

API — convertAll()

The main function convertAll() is imported like this:

It’s a function which takes two input arguments:

Input argumentTypeObligatoryDescription
str
Type: String
Obligatory: yes
strStringyesString to process.
opts
Type: Plain object
Obligatory: no
optsPlain objectnoOptional Options Object.

The Optional Options Object has the following shape:

KeyTypeDefaultObligatoryDescription
convertEntities
Type: Boolean
Default: false
Obligatory: no
convertEntitiesBooleanfalsenoOutput named HTML entities for typographic punctuation.
convertApostrophes
Type: Boolean
Default: true
Obligatory: no
convertApostrophesBooleantruenoUse true for typographic punctuation or false to convert curly quotes and primes back to straight quotes.

Omitted or undefined conversion flags use their defaults. Explicit convertApostrophes: false requests reverse conversion:

import { convertAll } from "string-apostrophes";

convertAll("It’s 6′2″", { convertApostrophes: false }).result;
// => "It's 6'2\""

convertAll("It’s", { convertApostrophes: undefined }).result;
// => "It’s"

Here are all defaults in one place for copying:

The function will return a plain object:

Returned object’s keyTypeDescription
result
Type: String
resultStringProcessed string, with all ranges applied
ranges
Type: Ranges: null or array of arrays
rangesRanges: null or array of arraysHalf-open UTF-16 ranges applied to produce result. An unchanged nonempty input returns []; an empty input returns null.

API — convertOne()

The main function convertOne() is imported like this:

It’s a function which takes two input arguments:

Input argumentTypeObligatoryDescription
str
Type: String
Obligatory: yes
strStringyesA string to process
opts
Type: Plain object
Obligatory: yes
optsPlain objectyesObligatory Options Object.

The Obligatory Options Object has the following shape:

KeyTypeDefaultObligatoryDescription
from
Type: Natural number, string index
Default: undefined
Obligatory: yes
fromNatural number, string indexundefinedyesInclusive UTF-16 index at which the supplied span starts.
to
Type: Natural number, string index
Default: from + 1
Obligatory: no
toNatural number, string indexfrom + 1noExclusive UTF-16 end index. An integer endpoint must satisfy from ≤ to ≤ str.length.
value
Type: String
Default: undefined
Obligatory: no
valueStringundefinednoLogical quote or prime represented by str.slice(from, to).
convertEntities
Type: Boolean
Default: false
Obligatory: no
convertEntitiesBooleanfalsenoOutput named HTML entities for typographic punctuation.
convertApostrophes
Type: Boolean
Default: true
Obligatory: no
convertApostrophesBooleantruenoUse true for typographic punctuation or false to convert curly quotes and primes back to straight quotes.
offsetBy
Type: Function
Default: undefined
Obligatory: no
offsetByFunctionundefinednoReceives the number of additional UTF-16 code units consumed beyond to when one replacement handles multiple symbols.

opts.from must be an integer from 0 to str.length - 1. opts.to defaults to from + 1; backwards or out-of-bounds integer spans throw a string-apostrophes/convertOne() error. Equal endpoints are valid for inserting a supplied value without deleting source text. Pass an options object: null receives the required-options error.

The surrounding text determines whether a mark is an apostrophe, quotation mark, or measurement prime. Measurements such as 6'2" become 6′2″, including at the end of input. Numeric-ending quotations such as Model "T2000". become Model “T2000”.. Explicit primes stay primes under forward conversion. These rules also apply to supplied logical values.

The function returns an array of ranges, or [] when no replacement is needed. Apply them with rApply() from ranges-apply. A supplied logical value that already equals the requested output can also return [], leaving decoding or encoding to the caller.

opts.offsetBy

When one replacement consumes multiple symbols, offsetBy reports the additional span after to. Your iterator must also advance across the first supplied span. For a raw quote, that first span is one code unit; for ', it is six.

For example, this tokenizer handles encoded apostrophes and literal double quotes without revisiting a consumed pair or skipping the following quotation:

import { convertOne } from "string-apostrophes";
import { rApply } from "ranges-apply";

const input = 'rock 'n'"next"';
const ranges = [];

for (let i = 0; i < input.length; i++) {
  const encoded = input.startsWith("&apos;", i);
  if (!encoded && input[i] !== '"') {
    continue;
  }
  const from = i;
  const to = from + (encoded ? 6 : 1);
  ranges.push(...convertOne(input, {
    from,
    to,
    value: encoded ? "'" : '"',
    offsetBy: (amount) => { i += amount; },
  }));
  i += to - from - 1;
}

rApply(input, ranges);
// => "rock ’n’“next”"

The first call replaces [5, 18) and reports an offset of 7: the n and the complete second &apos;. The loop’s normal increment and explicit first-span advancement move to index 18, the opening double quote.

opts.value

Consider John's with an HTML-encoded apostrophe:

John&apos;s

convertAll() does not decode entity text automatically. If your tokenizer already knows an entity or placeholder represents a quote, pass its half-open source span and decoded value to convertOne().

For example,

import { convertOne } from "string-apostrophes";
const res = convertOne(`test&apos;s`, {
  from: 4,
  to: 10,
  value: "'", // <-------- tell the program it's an apostrophe between indexes 4 and 10
  convertEntities: false,
});
console.log(JSON.stringify(res, null, 0));
// => [[4, 10, "’"]]

In the example above, the program evaluates surroundings of &apos; as if it was a “normal” apostrophe and suggests a replacement.

In practice, that’s how detergent uses this package.

API — defaults

You can import defaults:

It's a plain object:

The main function calculates the options to be used by merging the options you passed with these defaults.

These defaults are applicable for both convertOne() and convertAll() functions.

API — version

You can import version:

API — types

This package is written in TypeScript and exports the following types:

TypeDescription
Opts
Type: Opts
OptsThe Options Object of both convertAll() and convertOne(), documented above.
Range
Type: Range
RangeA single range, re-exported from ranges-apply.
Ranges
Type: Ranges
RangesZero or more Ranges, or null, re-exported from ranges-apply.
import type { Opts, Range, Ranges } from "string-apostrophes";

Compared to Others

📦 This program, string-apostrophesstraight-to-curly-quotesopens in a new tabsmartquotesopens in a new tabtypographic-quotesopens in a new tab
npm link
npm linknpm linkopens in a new tabnpm linkopens in a new tabnpm linkopens in a new tab
Returns processed string
Returns processed string✅✅✅✅
Additionally returns index ranges allowing to compose string operations
Additionally returns index ranges allowing to compose string operations✅❌❌❌
Replaces quotes in DOM, on a web page, where you put a script in
Replaces quotes in DOM, on a web page, where you put a script in❌❌✅❌
Not regex-based
Not regex-based✅❌❌❌
Can output HTML-encoded content upon request
Can output HTML-encoded content upon request✅❌❌❌
Allows to process any part of string as if it were single or double quote
Allows to process any part of string as if it were single or double quote✅❌❌❌
Serves other languages besides English
Serves other languages besides English❌❌❌✅

Permalink to changelogChangelog

Open Changelog
↑ back to top
prev next

Copyright

All rights reserved © Roy Revelt 2026
All our open source packages are under MIT licenceopens in a new tab

Activities

🐛 See a bug? Raise an issueopens in a new tab
💘 Check out the Indiewebopens in a new tab and Libera manifestoopens in a new tab