Created
June 26, 2025 20:07
-
-
Save louis-young/959ba04a15c1ec625de1f3c8e9006583 to your computer and use it in GitHub Desktop.
Olo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { expect, test } from "vitest"; | |
| import { wordWrapString } from "."; | |
| // characterLimitPerLine = -1 / 5.5 | |
| test.each([ | |
| { | |
| stringToWordWrap: "Hello World", | |
| characterLimitPerLine: 20, | |
| expectedWordWrappedString: "Hello World", | |
| }, | |
| { | |
| stringToWordWrap: "Hello World", | |
| characterLimitPerLine: 4, | |
| expectedWordWrappedString: "Hell\no Wo\nrld", | |
| }, | |
| { | |
| stringToWordWrap: "foobarbaz", | |
| characterLimitPerLine: 3, | |
| expectedWordWrappedString: "foo\nbar\nbaz", | |
| }, | |
| { | |
| stringToWordWrap: "Hello World", | |
| characterLimitPerLine: 5, | |
| expectedWordWrappedString: "Hello\nWorld", | |
| }, | |
| { | |
| stringToWordWrap: "Hello World a b c", | |
| characterLimitPerLine: 5, | |
| expectedWordWrappedString: "Hello\nWorld\na b c", | |
| }, | |
| { | |
| stringToWordWrap: "Hello World", | |
| characterLimitPerLine: 2, | |
| expectedWordWrappedString: "He\nll\no\nWo\nrl\nd", | |
| }, | |
| ])( | |
| "returns `$expectedWordWrappedString` when called with a `stringToWordWrap` of `$stringToWordWrap` and a `characterLimitPerLine` of `$characterLimitPerLine`", | |
| ({ stringToWordWrap, characterLimitPerLine, expectedWordWrappedString }) => { | |
| const wordWrappedString = wordWrapString({ | |
| stringToWordWrap, | |
| characterLimitPerLine, | |
| }); | |
| expect(wordWrappedString).toEqual(expectedWordWrappedString); | |
| } | |
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // When placing orders through the Olo system, customers are allowed to add special instructions to their orders, for instance specifying that they don't need utensils or that they want their steak cooked a certain way. | |
| // Restaurant receipt printers have restrictions for how many characters can fit on each line. This means that in many cases special instructions must be wrapped and put on multiple lines in order for the text to fit. | |
| // Write a function 'WordWrap' that takes as input a string (the special instructions) and an integer (the character limit) and returns the special instructions wrapped onto lines with no line exceeding the character limit. | |
| /** | |
| * `utilities.ts` | |
| */ | |
| function checkIsNumberPositiveInteger(numberToCheck: number) { | |
| return numberToCheck > 0 || Number.isInteger(numberToCheck); | |
| } | |
| type ChunkStringByCharacterLimitParameters = { | |
| stringToChunk: string; | |
| characterLimitPerChunk: number; | |
| }; | |
| function chunkStringByCharacterLimit({ | |
| stringToChunk, | |
| characterLimitPerChunk, | |
| }: ChunkStringByCharacterLimitParameters) { | |
| if (!checkIsNumberPositiveInteger(characterLimitPerChunk)) { | |
| throw new Error("`characterLimitPerChunk` must be a positive integer."); | |
| } | |
| if (stringToChunk === "" || stringToChunk.length <= characterLimitPerChunk) { | |
| return [stringToChunk]; | |
| } | |
| const numberOfChunks = Math.ceil( | |
| stringToChunk.length / characterLimitPerChunk | |
| ); | |
| return Array.from({ length: numberOfChunks }, (_, chunkIndex) => { | |
| return stringToChunk.slice( | |
| chunkIndex * characterLimitPerChunk, | |
| (chunkIndex + 1) * characterLimitPerChunk | |
| ); | |
| }); | |
| } | |
| /** | |
| * `index.ts` | |
| */ | |
| const CHARACTERS = { | |
| newline: "\n", | |
| space: " ", | |
| }; | |
| type WordWrapStringParameters = { | |
| stringToWordWrap: string; | |
| characterLimitPerLine: number; | |
| }; | |
| export function wordWrapString({ | |
| stringToWordWrap, | |
| characterLimitPerLine, | |
| }: WordWrapStringParameters) { | |
| if (!checkIsNumberPositiveInteger(characterLimitPerLine)) { | |
| throw new Error("`characterLimitPerLine` must be a positive integer."); | |
| } | |
| if ( | |
| stringToWordWrap === "" || | |
| stringToWordWrap.length <= characterLimitPerLine | |
| ) { | |
| return stringToWordWrap; | |
| } | |
| const rawWords = stringToWordWrap.split(" ").filter(Boolean); | |
| const words = rawWords.flatMap((rawWord) => { | |
| if (rawWord.length <= characterLimitPerLine) { | |
| return rawWord; | |
| } | |
| return chunkStringByCharacterLimit({ | |
| stringToChunk: rawWord, | |
| characterLimitPerChunk: characterLimitPerLine, | |
| }); | |
| }); | |
| return words.reduce((wordWrappedString, word) => { | |
| if (wordWrappedString === "") { | |
| return word; | |
| } | |
| const currentLine = | |
| wordWrappedString.split(CHARACTERS.newline).at(-1) ?? wordWrappedString; | |
| const wouldWordOverflowCurrentLine = | |
| currentLine.length + word.length >= characterLimitPerLine; | |
| return wordWrappedString.concat( | |
| wouldWordOverflowCurrentLine ? CHARACTERS.newline : CHARACTERS.space, | |
| word | |
| ); | |
| }, ""); | |
| } | |
| const wordWrappedString = wordWrapString({ | |
| stringToWordWrap: "999999999", | |
| characterLimitPerLine: 3, | |
| }); | |
| console.log(wordWrappedString); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment