From 68d30db8c99d1ead7a57c19a1349d00c1d6d471b Mon Sep 17 00:00:00 2001 From: lauragreen Date: Wed, 24 Feb 2021 11:43:15 +0000 Subject: [PATCH] :sparkles: Add LoremHeading - adds ability to choose punctuation for headings, which often ought to be without punctuation, depending on style guidelines --- examples/src/app.js | 11 ++++ examples/src/heading.js | 102 +++++++++++++++++++++++++++++++++++++ src/index.d.ts | 24 ++++++++- src/index.js | 13 ++++- src/lorem-heading/index.js | 66 ++++++++++++++++++++++++ 5 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 examples/src/heading.js create mode 100644 src/lorem-heading/index.js diff --git a/examples/src/app.js b/examples/src/app.js index bc12487..26a5b34 100644 --- a/examples/src/app.js +++ b/examples/src/app.js @@ -2,6 +2,7 @@ import React, { useState } from 'react'; import Header from './header'; import Footer from './footer'; import Lipsum from './lipsum'; +import Heading from './heading'; import User from './user'; import './style.scss'; @@ -19,6 +20,13 @@ const App = () => { > Lorem Ipsum + + +
+

Component

+
+
{'import { LoremHeading } from "react-lorem-ipsum";'}
+
+
+
{`' : ''}`}
+ {componentProps.p !== defaultComponentProps.p && ( +
{`p={${componentProps.p}}`}
+ )} + {componentProps.avgWordsPerHeading !== defaultComponentProps.avgWordsPerHeading && ( +
{`avgWordsPerHeading={${componentProps.avgWordsPerHeading}}`}
+ )} + {componentProps.includeEndPunctuation !== + defaultComponentProps.includeEndPunctuation && ( +
{`includeEndPunctuation${ + componentProps.includeEndPunctuation && '="true"' + }`}
+ )} + {!areAllComponentPropsDefault &&
{'/>'}
} +
+
+ +

Output

+
+ +
+ + ); +}; + +export default Heading; diff --git a/src/index.d.ts b/src/index.d.ts index dd17389..7afc933 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -38,6 +38,26 @@ export const surname: () => string; */ export const username: () => string; +interface LoremHeadingProps { + p?: string | number; + avgWordsPerHeading?: string | number; + includeEndPunctuation?: boolean; +} + +/** + * LoremHeading (Component) generates JSX + * + * Props : + * - P = 1 - Number of paragraphs + * - avgWordsPerHeading = 3 - Average number of words per heading + * - includeEndPunctuation = true - If disabled removes end punctuation + */ +export const LoremHeading: React.FC; +/** + * loremHeading (function) returns plain text + */ +export const loremHeading: (LoremHeadingProps?: LoremHeadingProps) => string[]; + interface LoremIpsumProps { p?: string | number; avgWordsPerSentence?: string | number; @@ -51,8 +71,8 @@ interface LoremIpsumProps { * * Props : * - P = 1 - Number of paragraphs - * - avgWordsPerSentence = 8 - Avarage number of words per sentence - * - avgSentencesPerParagraph = 8 - Avarage number of sentences per paragraph + * - avgWordsPerSentence = 8 - Average number of words per sentence + * - avgSentencesPerParagraph = 8 - Average number of sentences per paragraph * - startWithLoremIpsum = true - Start with 'Lorem ipsum odor amet...' to first sentence of first paragraph * - random = true - If disabled always generates the same text. */ diff --git a/src/index.js b/src/index.js index 9593b7a..7670e18 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,16 @@ import { LoremIpsum, loremIpsum } from './lorem-ipsum'; +import { LoremHeading, loremHeading } from './lorem-heading'; import { Avatar, name, surname, fullname, username } from './user'; -export { LoremIpsum, loremIpsum, Avatar, name, surname, fullname, username }; +export { + LoremIpsum, + loremIpsum, + LoremHeading, + loremHeading, + Avatar, + name, + surname, + fullname, + username, +}; export default LoremIpsum; diff --git a/src/lorem-heading/index.js b/src/lorem-heading/index.js new file mode 100644 index 0000000..dc919f1 --- /dev/null +++ b/src/lorem-heading/index.js @@ -0,0 +1,66 @@ +import PropTypes from 'prop-types'; + +import { + randomFromRange, + randomPositiveFromRange, + getStandardDeviation, + parseIntWithDefault, +} from '../utils'; +import words from '../data/words.json'; + +// Default Props of the Component +const defaultProps = { + p: 1, + avgWordsPerHeading: 3, + includeEndPunctuation: false, +}; + +// Standard deviation percentage for words +const stDevPercentage = 0.25; + +// Get a random word from Latin word list +const getRandomWord = () => words[randomFromRange(0, words.length - 1)]; + +// Get a punctuation for end of the heading randomly +const endPunctuation = includeEndPunctuation => { + if (includeEndPunctuation) { + const random = Math.random(); + // 1% probability exclamation mark, 4% probability question mark, 95% probability dot + if (random > 0.99) return '!'; + if (random > 0.95) return '?'; + return '.'; + } + return ''; +}; + +// Create a Heading by using random words +const loremHeading = ({ avgWordsPerHeading, includeEndPunctuation }) => { + const awps = parseIntWithDefault(avgWordsPerHeading, defaultProps.avgWordsPerHeading); + const stDev = getStandardDeviation(awps, stDevPercentage); + const headingLength = randomPositiveFromRange(awps - stDev, awps + stDev); + + let heading = ''; + for (let i = 0; i < headingLength; i += 1) { + heading += `${getRandomWord()} `; + } + heading = `${heading.charAt(0).toUpperCase() + heading.substr(1).trim()}${endPunctuation( + includeEndPunctuation + )}`; + return heading; +}; + +// Component create Lorem Heading as HTML +const LoremHeading = props => { + const heading = loremHeading(props); + return heading; +}; + +LoremHeading.propTypes = { + p: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + avgWordsPerHeading: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + includeEndPunctuation: PropTypes.bool, +}; + +LoremHeading.defaultProps = defaultProps; + +export { LoremHeading, loremHeading };