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

prevOpen Source→string-apostrophesnext

string-apostrophes4.2.1

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

Installation

Quick Take

Examples

  • 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 converts all cases of single and double apostrophes, plus primesopens in a new tab.

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
convertEntitiesBooleanfalsenoHTML-encode the characters?
convertApostrophes
Type: Boolean
Default: true
Obligatory: no
convertApostrophesBooleantruenoA killswitch. If it’s false, the program does nothing.

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 arraysRanges that were gathered and applied to produce the result

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 indexundefinedyesIndex at which the character to process starts.
to
Type: Natural number, string index
Default: from + 1
Obligatory: no
toNatural number, string indexfrom + 1noIndex at which the character to process ends.
value
Type: String
Default: undefined
Obligatory: no
valueStringundefinednoOverride the value of a string value, present at str.slice(from, to)
convertEntities
Type: Boolean
Default: false
Obligatory: no
convertEntitiesBooleanfalsenoHTML-encode the characters?
convertApostrophes
Type: Boolean
Default: true
Obligatory: no
convertApostrophesBooleantruenoKillswitch. If it’s false, the program does nothing.
offsetBy
Type: Function
Default: undefined
Obligatory: no
offsetByFunctionundefinednoIf you provide a function, it will be called with a natural number input argument, meaning how much characters to skip next.

opts.from is obligatory — that’s how you tell the program which characters to process.

The function returns ranges: an array of range arrays or null. Later you can use them in ranges-apply to process a string using those ranges (in other words, “to apply those ranges”).

opts.offsetBy

Offset is needed to bypass characters already fixed — it happens for example, with nested quotes: many get fixed in one go, and further processing has to be skipped; otherwise, those characters would get processed multiple times.

For example, here’s how the convertAll() index is bumped using offsetBy, in a callback-fashion:

function convertAll(str, opts) {
  let ranges = [];
  const preppedOpts = Object.assign({}, opts);
  // loop through the given string
  for (let i = 0, len = str.length; i < len; i++) {
    // define starting index:
    preppedOpts.from = i;
    // offset function:
    preppedOpts.offsetBy = (idx) => {
      i = i + idx;
    };
    // calculate the result:
    const res = convertOne(str, preppedOpts);
    if (Array.isArray(res) && res.length) {
      ranges = ranges.concat(res);
    }
  }
  return {
    result: rangesApply(str, ranges),
    ranges,
  };
}

The inner function convertOne() bumps outer’s convertAll() index.

opts.value

Consider string Your's with HTML-escaped apostrophe:

Your&apos;s

There are various other cases of apostrophes and quotes where you have a sentence, and all apostrophes/quotes are there, and you know where — just different character(s) represent them. Values are not ' and ".

We are not going to code up all those cases!

Instead, use convertOne(), process each “symbol” one-by-one and instruct the program from where (from) to where (to) is a particular character (value).

For example,

import { convertOne, convertAll } 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: 0,
});
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✅❌❌❌
A killswitch to bypass processing
A killswitch to bypass processing✅❌❌❌
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❌❌❌✅

Changelog

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