Skip to content

Commit

Permalink
Merge changes from v1.5.0-next.2 into main (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
trevor-anderson committed Jun 21, 2024
2 parents 0aaa540 + 4c77fe0 commit 1ca2c50
Show file tree
Hide file tree
Showing 25 changed files with 397 additions and 75 deletions.
10 changes: 0 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@ All notable changes to this project will be documented in this file.

# [1.5.0](https://github.com/Nerdware-LLC/ts-string-helpers/compare/v1.4.8...v1.5.0) (2024-06-19)


### Features

* add isValidHttpURL ([570cb33](https://github.com/Nerdware-LLC/ts-string-helpers/commit/570cb33ebf86b6d13dfd101ce0024484e4485d5c))

# [1.5.0-next.1](https://github.com/Nerdware-LLC/ts-string-helpers/compare/v1.4.8...v1.5.0-next.1) (2024-06-18)


### Features

* add isValidHttpURL ([570cb33](https://github.com/Nerdware-LLC/ts-string-helpers/commit/570cb33ebf86b6d13dfd101ce0024484e4485d5c))
Expand All @@ -26,7 +18,6 @@ All notable changes to this project will be documented in this file.

## [1.4.6](https://github.com/Nerdware-LLC/ts-string-helpers/compare/v1.4.5...v1.4.6) (2024-06-05)


### Bug Fixes

* add 'git+' prefix to 'repository.url' ([844042b](https://github.com/Nerdware-LLC/ts-string-helpers/commit/844042bc9e4ac75a13fe196a115106bdf527cf38))
Expand All @@ -39,7 +30,6 @@ All notable changes to this project will be documented in this file.

## [1.4.2](https://github.com/Nerdware-LLC/ts-string-helpers/compare/v1.4.1...v1.4.2) (2024-05-25)


### Bug Fixes

* rm trim call in getSanitizerFn ([a6b46db](https://github.com/Nerdware-LLC/ts-string-helpers/commit/a6b46db02c5c9e64653e86c8115a6540c1c26556))
Expand Down
104 changes: 64 additions & 40 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nerdware/ts-string-helpers",
"version": "1.5.0",
"version": "1.5.0-next.2",
"description": "TypeScript string utils for sanitization, validation, and formatting.",
"author": {
"name": "Trevor Anderson",
Expand Down
5 changes: 4 additions & 1 deletion src/sanitize/alphabeticWithSpaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ import { getSanitizerFn } from "./_helpers.js";
* Removes all non-alphabetic/space characters from `str`.
*
* > This function only permits [ASCII characters](https://www.asciitable.com/).
*
* **Pattern Notes:**
* - `\x20` is the ASCII hex code for a single horizontal space.
*/
export const sanitizeAlphabeticWithSpaces = getSanitizerFn(/[^a-zA-Z\s]/g);
export const sanitizeAlphabeticWithSpaces = getSanitizerFn(/[^a-zA-Z\x20]/g);
5 changes: 4 additions & 1 deletion src/sanitize/alphanumericWithSpaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ import { getSanitizerFn } from "./_helpers.js";
* Removes all non-alphanumeric/space characters from `str`.
*
* > This function only permits [ASCII characters](https://www.asciitable.com/).
*
* **Pattern Notes:**
* - `\x20` is the ASCII hex code for a single horizontal space.
*/
export const sanitizeAlphanumericWithSpaces = getSanitizerFn(/[^a-zA-Z0-9\s]/g);
export const sanitizeAlphanumericWithSpaces = getSanitizerFn(/[^a-zA-Z0-9\x20]/g);
4 changes: 3 additions & 1 deletion src/sanitize/base64URL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { getSanitizerFn } from "./_helpers.js";
* - No line breaks are used
*
* @see https://base64.guru/standards/base64url
*
* **Pattern Notes:**
* - The hyphen literal is at the end of the group to avoid unintentional range creation.
*/
export const sanitizeBase64URL = getSanitizerFn(/[^a-zA-Z0-9_-]/g);
// Note: hyphen literal is at the end of the group to avoid range creation
3 changes: 2 additions & 1 deletion src/sanitize/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ export * from "./handle.js";
export * from "./hexadecimal.js";
export * from "./id.js";
export * from "./jsonString.js";
export * from "./jwt.js";
export * from "./name.js";
export * from "./numeric.js";
export * from "./password.js";
export * from "./phone.js";
export * from "./jwt.js";
export * from "./url.js";
17 changes: 7 additions & 10 deletions src/sanitize/jsonString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ import { getSanitizerFn } from "./_helpers.js";

/**
* Removes non-JSON characters from `str`.
*
* **Pattern Notes:**
* - The pattern works by testing for characters within the ASCII printable range. The
* permitted-character range begins with the single-horizontal-space character (`\x20`),
* which is ASCII code 32, and ends with `~` (tilde), which is ASCII code 126.
* - `\x20` is the ASCII hex code for a single horizontal space.
*/
export const sanitizeJsonString = getSanitizerFn(
/**
* The pattern below works by testing for characters within the ASCII printable
* range. The permitted-character range begins with ` ` (space char), which is
* ASCII code 32, and ends with `~` (tilde), which is ASCII code 126. Note that
* for the space char, `\s` cannot be used because escape sequences are not valid
* in character ranges.
*/
/[^ -~]/g
);
export const sanitizeJsonString = getSanitizerFn(/[^\x20-~]/g);
4 changes: 3 additions & 1 deletion src/sanitize/jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { getSanitizerFn } from "./_helpers.js";

/**
* Remove characters from `str` which are not valid in a JSON Web Token.
*
* **Pattern Notes:**
* - The hyphen literal is at the end of the group to avoid unintentional range creation.
*/
export const sanitizeJWT = getSanitizerFn(/[^a-zA-Z0-9._-]/g);
// Note: hyphen literal is at the end of the group to avoid range creation
22 changes: 22 additions & 0 deletions src/sanitize/name.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { sanitizeName } from "./name.js";

describe("sanitize: name", () => {
test("removes invalid characters from the name", () => {
expect(sanitizeName("Jane Doe!@#$%^&*()_+123")).toBe("Jane Doe");
});

test("keeps valid characters in the name", () => {
const input = "José Dã'Hüman-persón";
expect(sanitizeName(input)).toBe(input);
});

test("keeps valid punctuation marks in the name", () => {
const input = "'.,-";
expect(sanitizeName(input)).toBe(input);
});

test("keeps valid whitespace characters in the name", () => {
const input = "John Doe";
expect(sanitizeName(input)).toBe(input);
});
});
26 changes: 26 additions & 0 deletions src/sanitize/name.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { getSanitizerFn } from "./_helpers.js";

/**
* Removes characters from `str` which are generally not valid in a name.
*
* **Permitted Characters:**
* - [Unicode Latin-script characters](https://en.wikipedia.org/w/index.php?title=Latin_script_in_Unicode&oldid=1210023145#Table_of_characters)
* - Single-horizontal-space characters (`\x20`)
* - Apostrophes (`'`)
* - Periods (`.`)
* - Commas (`,`)
* - Hyphens (`-`)
*
* ```ts
* // Non-ASCII latin-script characters are preserved
* sanitizeName("José São Hüman-persón"); // "José São Hüman-përsón"
* // Punctuation marks sometimes used in names are preserved
* sanitizeName("Jane Da'Human, Jr."); // "Jane Da'Human, Jr."
* ```
*
* **Pattern Notes:**
* - `\p{Script=Latin}` is used as a more i18n-friendly alternative to `[a-zA-Z]`.
* - `\x20` is the ASCII hex code for a single horizontal space.
* - The hyphen literal is at the end of the group to avoid unintentional range creation.
*/
export const sanitizeName = getSanitizerFn(/[^\p{Script=Latin}\x20'.,-]/gu);
28 changes: 28 additions & 0 deletions src/sanitize/text.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { sanitizeText } from "./text.js";

describe("sanitize: text", () => {
test("removes characters that pose security risks", () => {
expect(sanitizeText(`Hello {world}!`)).toBe("Hello world!");
expect(sanitizeText(`Hello [world]!`)).toBe("Hello world!");
expect(sanitizeText(`Hello <world>!`)).toBe("Hello world!");
});

test("keeps permitted characters", () => {
const input = `123%$#@'&.,:;"!?+=()_—-`;
expect(sanitizeText(input)).toBe(input);
});

test("keeps Latin-script characters", () => {
expect(sanitizeText(`Hello José 世界!`)).toBe(`Hello José !`);
});

test("keeps whitespace characters", () => {
const input1 = `Hello\nworld!\n`;
const input2 = `
Hello
world!`;

expect(sanitizeText(input1)).toBe(input1);
expect(sanitizeText(input2)).toBe(input2);
});
});
41 changes: 41 additions & 0 deletions src/sanitize/text.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { getSanitizerFn } from "./_helpers.js";

/**
* Removes characters from `str` which meet the following criteria:
*
* 1. The character is generally not used in everyday written text
* 2. The character poses potential security risks if not properly handled
*
* > **Examples of characters removed by this sanitizer:** `{}`, `[]`, and `<>`
*
* This function is intended for arbitrary user-provided text, like comments or forum posts.
*
* **Permitted Characters:**
* - [Unicode Latin-script characters](https://en.wikipedia.org/w/index.php?title=Latin_script_in_Unicode&oldid=1210023145#Table_of_characters)
* - Numerical digits (`\d`)
* - Whitespace characters (`\s`)
* - Percent signs (`%`)
* - Dollar signs (`$`)
* - Number signs (`#`)
* - At symbols (`@`)
* - Apostrophes (`'`)
* - Ampersands (`&`)
* - Periods (`.`)
* - Commas (`,`)
* - Colons (`:`)
* - Semicolons (`;`)
* - Double quotes (`"`)
* - Exclamation marks (`!`)
* - Question marks (`?`)
* - Plus signs (`+`)
* - Equal signs (`=`)
* - Parentheses (`()`)
* - Underscores (`_`)
* - Em dashes (`—`)
* - Hyphens (`-`)
*
* **Pattern Notes:**
* - `\p{Script=Latin}` is used as a more i18n-friendly alternative to `[a-zA-Z]`.
* - The hyphen literal is at the end of the group to avoid unintentional range creation.
*/
export const sanitizeText = getSanitizerFn(/[^\p{Script=Latin}\d\s%$#@'&.,:;"!?+=()_—-]/gu);
12 changes: 12 additions & 0 deletions src/validate/alphabeticWithSpaces.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ describe("validate: alphabeticWithSpaces", () => {
test("returns false when given a string containing numbers", () => {
expect(isValidAlphabeticWithSpaces("abc def 123")).toBe(false);
});
test("returns false when given a string containing invalid whitespace characters", () => {
expect(isValidAlphabeticWithSpaces("abc \f def")).toBe(false);
expect(isValidAlphabeticWithSpaces("abc \n def")).toBe(false);
expect(isValidAlphabeticWithSpaces("abc \r def")).toBe(false);
expect(isValidAlphabeticWithSpaces("abc \t def")).toBe(false);
expect(isValidAlphabeticWithSpaces("abc \v def")).toBe(false);
expect(
isValidAlphabeticWithSpaces(`
abc
def`)
).toBe(false);
});
test("returns false when given a string containing a null unicode character", () => {
expect(isValidAlphabeticWithSpaces("abc def \u0000")).toBe(false);
});
Expand Down
5 changes: 4 additions & 1 deletion src/validate/alphabeticWithSpaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ import { getRegexValidatorFn } from "./_helpers.js";
* Returns `true` if `value` only contains alphabetic characters and/or spaces.
*
* > This function only permits [ASCII characters](https://www.asciitable.com/).
*
* **Pattern Notes:**
* - `\x20` is the ASCII hex code for a single horizontal space.
*/
export const isValidAlphabeticWithSpaces = getRegexValidatorFn(/^[a-zA-Z\s]+$/);
export const isValidAlphabeticWithSpaces = getRegexValidatorFn(/^[a-zA-Z\x20]+$/);
14 changes: 13 additions & 1 deletion src/validate/alphanumericWithSpaces.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,19 @@ describe("validate: alphanumericWithSpaces", () => {
test("returns false when given a string containing a special character", () => {
expect(isValidAlphanumericWithSpaces("abc 123~")).toBe(false);
});
test("returns false when given a string containing invalid whitespace characters", () => {
expect(isValidAlphanumericWithSpaces("abc \f def")).toBe(false);
expect(isValidAlphanumericWithSpaces("abc \n def")).toBe(false);
expect(isValidAlphanumericWithSpaces("abc \r def")).toBe(false);
expect(isValidAlphanumericWithSpaces("abc \t def")).toBe(false);
expect(isValidAlphanumericWithSpaces("abc \v def")).toBe(false);
expect(
isValidAlphanumericWithSpaces(`
abc
def`)
).toBe(false);
});
test("returns false when given a string containing a null unicode character", () => {
expect(isValidAlphanumericWithSpaces("abc 123\u0000")).toBe(false);
expect(isValidAlphanumericWithSpaces("abc 123 \u0000")).toBe(false);
});
});
5 changes: 4 additions & 1 deletion src/validate/alphanumericWithSpaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ import { getRegexValidatorFn } from "./_helpers.js";
* Returns `true` if `value` only contains alphanumeric characters and/or spaces.
*
* > This function only permits [ASCII characters](https://www.asciitable.com/).
*
* **Pattern Notes:**
* - `\x20` is the ASCII hex code for a single horizontal space.
*/
export const isValidAlphanumericWithSpaces = getRegexValidatorFn(/^[a-zA-Z0-9\s]+$/);
export const isValidAlphanumericWithSpaces = getRegexValidatorFn(/^[a-zA-Z0-9\x20]+$/);
4 changes: 3 additions & 1 deletion src/validate/base64URL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { getRegexValidatorFn } from "./_helpers.js";
* - Must be at least 2 characters long
*
* @see https://base64.guru/standards/base64url
*
* **Pattern Notes:**
* - The hyphen literal is at the end of the group to avoid unintentional range creation.
*/
export const isValidBase64URL = getRegexValidatorFn(/^[a-zA-Z0-9_-]{2,}$/);
// Note: hyphen literal is at the end of the group to avoid range creation
1 change: 1 addition & 0 deletions src/validate/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from "./hexadecimal.js";
export * from "./id.js";
export * from "./jsonString.js";
export * from "./jwt.js";
export * from "./name.js";
export * from "./numeric.js";
export * from "./password.js";
export * from "./phone.js";
Expand Down
8 changes: 5 additions & 3 deletions src/validate/jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { getRegexValidatorFn } from "./_helpers.js";
/**
* Returns `true` if `value` is a valid JWT.
*
* JWTs contain three [Base64URL-encoded][base64url] sections separated by periods (`.`).
* JWTs contain three [Base64URL-encoded](https://base64.guru/standards/base64url) sections
* separated by periods (`.`).
*
* [base64url]: https://base64.guru/standards/base64url
* **Pattern Notes:**
* - The minimum length is 2 characters per section.
* - Hyphen literals are at the end of their groups to avoid unintentional range creation.
*/
export const isValidJWT = getRegexValidatorFn(/^([a-zA-Z0-9_-]{2,}\.){2}[a-zA-Z0-9_-]{2,}$/);
// Note: hyphen literals are at the end of their groups to avoid range creation
54 changes: 54 additions & 0 deletions src/validate/name.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { isValidName } from "./name.js";

describe("validate: name", () => {
// POSITIVE TEST CASES:

test("returns true when called with a value which contains ASCII letters", () => {
expect(isValidName("ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz")).toBe(true);
});
test("returns true when called with a value which contains non-ASCII latin-script characters", () => {
expect(isValidName("José Dã'Hüman-persón")).toBe(true);
});
test("returns true when called with a value which contains permitted punctuation characters", () => {
expect(isValidName("A'.,-")).toBe(true);
});
test("returns true when called with a value which contains several space characters", () => {
expect(isValidName("John Doe")).toBe(true);
});

// NEGATIVE TEST CASES:

test("returns false when called with a value which contains invalid special characters", () => {
expect(isValidName("Jane Doe!@#$%^&*()_+123")).toBe(false);
});
test("returns false when called with a value which contains a number", () => {
expect(isValidName("Jane Doe 123")).toBe(false);
});
test("returns false when called with a value which contains a symbol", () => {
expect(isValidName("Jane Doe #")).toBe(false);
});
test("returns false when called with a value which contains a newline character", () => {
expect(isValidName("Jane\nDoe")).toBe(false);
});
test("returns false when called with a value which contains a tab character", () => {
expect(isValidName("Jane\tDoe")).toBe(false);
});
test("returns false when called with an empty string", () => {
expect(isValidName("")).toBe(false);
});
test("returns false when called with a string containing only a space character", () => {
expect(isValidName(" ")).toBe(false);
});
test("returns false when called with a string containing only a hyphen character", () => {
expect(isValidName("-")).toBe(false);
});
test("returns false when called with a string containing only a period character", () => {
expect(isValidName(".")).toBe(false);
});
test("returns false when called with a string containing only a comma character", () => {
expect(isValidName(",")).toBe(false);
});
test("returns false when called with a string containing only an apostrophe character", () => {
expect(isValidName("'")).toBe(false);
});
});
Loading

0 comments on commit 1ca2c50

Please sign in to comment.