npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@seamusleahy/react-typography-helper

v1.0.1

Published

A React component to help with various typography needs like widow control and smart quotes

Downloads

6

Readme

React Typography Helper

A React component to help with typography by replacing characters and inserting elements to attach custom styling to.

  • Widon't (Widow Control): Prevent the last word from appearing alone on the last line with either a non-breaking space or CSS.
  • Smart Text Replacement: Replace the easy to type characters with the typographically correct characters for quotes, ellipsis and dashes.
  • Text Wrapping: Some typefaces could use extra help with special characters or they deserve special treatment. Wrap various characters in elements to add custom styles. It can wrap ordinal indicator, all-capital words, quotes, parenthesis and ampersands.

All the TypeScript definitions are included.

Installation

npm install @seamusleahy/react-typography-helper"
// or
yarn add @seamusleahy/react-typography-helper"

How-to use

import React from 'react';
import TypographyHelper from 'react-typography-helper';

export const MyArticle = ({title, body}) => (
  <article>
    <h1><TypographyHelper text={title} widontNonBreakingSpace /></h1>
    <div dangerouslySetInnerHTML={{__html: body}} />
  </article>
);

text: string (required)

The text to display and transform with the type helper.

<TypographyHelper text="The text to transform" />
// Output: The text to transform

widontNonBreakingSpace: boolean

Default value: false

Replaces the space between the last two words with a non-breaking space to prevent widowing of the last word.

<TypographyHelper text="The text to transform" widontNonBreakingSpace />
// Output: The text to&nbsp;transform

wrapWidont: boolean | ReactElement

Default value: false

  • false: disabled
  • true: will wrap in a <span class="widont">
  • A ReactElement (aka, component), will wrap in a clone of the ReactElement

Wraps the last two-words in an element for you to add CSS styles to prevent wrapping. This is useful when wanting to use Media Queries to conditionally prevent wrapping.

<TypographyHelper text="The text to transform" wrapWidont />
// Output: The text <span class="widont">to transform</span>
@media (min-width: 400px) {
  .widont {
    white-space: nowrap;
  }
}

If you use a CSS-in-JS library:

const Widont = styled.span`
@media (min-width: 400px)  {
    white-space: nowrap;
}`;

<TypographyHelper text="The text to transform" wrapWidont={Widont} />
// Output: The text <span class="css-1pybesw">to transform</span> 

widontMaxLastWordLength: number

Default value: Infinity

This allows you to set a length for when the last word is long enough that it doesn’t require widow control. This setting is for both wrapWidont and widontNonBreakingSpace.

widontMaxLastTwoWordsLength: number

Default value: Infinity

This allows you to set a length when for when the last two words are long enough that it doesn’t require widow control. This setting is for both wrapWidont and widontNonBreakingSpace.

smartQuotes: boolean

Default value: false

This replaces ' and " with right and left quo=te marks.

<TypographyHelper text={`"'Em shouted, 'free the flour!'"`} smartQuotes />
// Output: “’Em shouted, ‘free the flour!’”

| Cases | Input | Output | | ------------------------------------------------------------- | -------------------------------------------------- | ----------------------------------------- | | Double Quotes | Andrew said, "I am tired" | Andrew said, I am tired | | Single Quotes | Tawny said, 'just trying my best' | Tawny said, just trying my best | | Apostrophe | I shouldn't have more | I shouldnt have more | | Leading Apostrophe(’til, ’tis, ’tude, ’twas, ’twere, ’em) | 'Twas the night before | Twas the night before |

Note: The double quotes are always paired together when replacing with a left and right double quote marks, whereas, single quotes are determined by the characters before and after it.

smartEllipsis: boolean

Default value: false

Replaces three periods (...) with an ellipsis ().

<TypographyHelper text="Today..." smartEllipsis />
// Output: Today…

Note: This will ignore a sequence of four or more periods.

smartDashes: boolean

Default value: false

Replaces two-dashes (--) with an en-dash () and three-dashes (---) with an em-dash (—).

<TypographyHelper text="Where--what---why" smartDashes />
// Output: Where–what—why

wrapAmpersand: boolean | React.ReactElement

Default value: false

  • false: disabled
  • true: will wrap in a <span class="amp">
  • A ReactElement, will wrap in a clone of the ReactElement

Wraps ampersands (&) in an element for the purpose of custom styling.

<TypographyHelper text="Flour & Yeast" wrapAmpersand />
// Output: Flour <span class="amp">&amp;</span> Yeast
.amp {
  letter-spacing: -0.1em;
}

If you use a CSS-in-JS library:

const Amp = styled.span`
  letter-spacing: -0.1em;
`;

<TypographyHelper text="Flour & Yeast" wrapAmpersand={Amp} />
// Output: Flour <span class="css-ork2sq">&amp;</span> Yeast

wrapMultipileCapitals: boolean | React.ReactElement

Default value: false

  • false: disabled
  • true: will wrap in a <span class="caps">
  • A ReactElement, will wrap in a clone of the ReactElement

Wrap all capital-letter words in an element for the purpose of custom styling.

<TypographyHelper text="Highlights of XYZ" wrapMultipileCapitals />
// Output: Highlights of <span class="caps">XYZ</span>

If you use a CSS-in-JS library:

const Caps = styled.span`
  letter-spacing: -0.1em;
`;

<TypographyHelper text="Flour & Yeast" wrapAmpersand={Caps} />
// Output: Highlights of <span class="css-ork2sq">XYZ</span>

wrapMultipileCapitalsMinLength: number

Default value: 2

Configure the minimum length an all capital-letter word has to be in order to be wrapped with wrapMultipileCapitals.

wrapOrdinalIndicator: boolean | React.ReactElement

Default value: false

  • false: disabled
  • true: will wrap in a <span class="ords">
  • A ReactElement, will wrap in a clone of the ReactElement

Wrap the ordinal indicator (-st, -nd, -rd, -th) in an element for the purpose of custom styling.

<TypographyHelper text="The 23rd of May" wrapOrdinalIndicator />
// Output: The 23<span class="ords">rd</span> of May

If you use a CSS-in-JS library:

const OrdinalIndicator = styled.span`
  letter-spacing: -0.1em;
`;

<TypographyHelpertext="The 23rd of May" wrapOrdinalIndicator={OrdinalIndicator} />
// Output:The 23<span class="css-ork2sq">rd</span> of May

wrapQuotes: boolean |ReactElement | WrapQuoteElements

Default value: false

  • false: disabled
  • true: will wrap in:
    {
      leftDouble: <span className="left-double-quote" />,
      rightDouble: <span className="right-double-quote" />,
      leftSingle: <span className="left-single-quote" />,
      rightSingle: <span className="right-single-quote" />,
      double: <span className="double-quote" />,
      single: <span className="single-quote" />,
      apostrophe: <span className="apostrophe" />,
    }
  • A ReactElement will wrap each quote character in a clone of the ReactElement
  • A WrapQuoteElements will wrap each corresponding quote character in a clone of the corresponding ReactElement:
    {
      leftDouble: ReactElement,
      rightDouble: ReactElement,
      leftSingle: ReactElement,
      rightSingle: ReactElement,
      double: ReactElement,
      single: ReactElement,
      apostrophe: ReactElement,
    }
<TypographyHelper text="“’Em shouted, ‘free the flour!’”" wrapQuotes />
// Output: <span class="left-double-quote">“</span><span class="apostrophe">’</span>Em shouted, <span class="left-single-quote">‘</span>free the flour!<span class="right-single-quote">’</span><span class="right-double-quote">”</span>

Using a single element:

<TypographyHelper text="“’Em shouted, ‘free the flour!’”" wrapQuotes={<i />} />
// Output: <i>“</i><i>’</i>Em shouted, <i>‘</i>free the flour!<i>’</i><i>”</i>

Using a WrapQuoteElements:

<TypographyHelper 
  text="“’Em shouted, ‘free the flour!’”" 
  wrapQuotes={{
    leftDouble: <span className="ldq" />,
    rightDouble: <span className="rdq" />,
    leftSingle:<span className="lsq" />,
    rightSingle:<span className="rsq" />,
    double: <span className="dq" />,
    single: <span className="sq" />,
    apostrophe: <span className="a" />,
  }} 
/>
// Output: <span class="ldq">“</span><span class="a">’</span>Em shouted, <span class="lsq">‘</span>free the flour!<span class="rsq">’</span><span class="rdq">”</span>

Note: apostrophe and rightSingle both match the same character so the characters around James’ around it are used to inform which of the two it is. It isn’t perfect. Words that end in an apostrophe are matched as rightSingle: James’ bicycle.

wrapParanthesis: boolean | ReactElement | WrapParanthesisElements

Default value: false

  • false: disabled
  • true: will wrap in:
    {
      leftParanthesis: <span className="left-paren" />,
      rightParanthesis: <span className="right-paren" />,
      leftSquareParanthesis: <span className="left-square-paren" />,
      rightSquareParanthesis: <span className="right-square-paren" />,
    }
  • A ReactElement will wrap each quote character in a clone of the ReactElement
  • A WrapParanthesisElements will wrap each corresponding quote character in a clone of the corresponding ReactElement:
    {
      leftParanthesis: ReactElement,
      rightParanthesis: ReactElement,
      leftSquareParanthesis: ReactElement,
      rightSquareParanthesis: ReactElement,
    }
<TypographyHelper text="(Yes) [No]" wrapParanthesis />
// Output: <span class="left-paren">(</span>Yes<span class="right-paren">)</span> <span class="left-square-paren">[</span>No<span class="right-square-paren">]</span>

Using a single element:

<TypographyHelper text="(Yes) [No]" wrapParanthesis={<b />} />
// Output: <b>(</b>Yes<b>)</b> <b>[</b>No<b>]</b>

Using a WrapParanthesisElements:

<TypographyHelper 
  text="(Yes) [No]" 
  wrapParanthesis={{
    leftParanthesis: <span className="lp" />,
    rightParanthesis: <span className="rp" />,
    leftSquareParanthesis: <span className="lsp" />,
    rightSquareParanthesis: <span className="rsp" />,
  }}
/>
// Output: <span class="lp">(</span>Yes<span class="rp">)</span> <span class="lsp">[</span>No<span class="rsp">]</span>

updateOnlyWhenTextChanges: boolean

Default value: true

When true, the component will only update the output when the text has changed - another way to put it is that it caches the results. It is leveraging React’s shouldComponentUpdate life cycle hook to accomplish this.

This assumes the formatting props are not changing during run-time. This potentially could cause issues when formatting props are being changed during development while using a hot-module-reloading; in those cases, the formatting would not change until after a hard refresh.