Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 44 additions & 19 deletions .github/workflows/validate-merge-request.yml
Original file line number Diff line number Diff line change
@@ -1,35 +1,60 @@
name: Validate Merge Request
name: Validate @agape/string in monorepo context

on:
pull_request:

jobs:
test:
name: Nx Unit Tests
runs-on: ubuntu-latest

steps:
- name: Checkout Repo
- name: Checkout agape-string (this repo)
uses: actions/checkout@v4

- name: Setup Node
- name: Extract branch name
id: extract_branch
run: echo "branch=${GITHUB_HEAD_REF}" >> $GITHUB_OUTPUT

- name: Configure Git to use PAT for submodules
run: |
git config --global url."https://${{ secrets.GH_PAT }}@github.com/".insteadOf "git@github.com:"

- name: Clone AgapeToolkit monorepo (with submodules)
run: |
git clone --recurse-submodules git@github.com:AgapeToolkit/AgapeToolkit.git ../AgapeToolkit
cd ../AgapeToolkit

git submodule foreach --quiet --recursive '
echo "🔍 Checking submodule: $name"
if [ "$name" = "libs/string" ]; then
echo "⚠️ Skipping $name (current module)"
exit 0
fi
cd "$toplevel/$name"
git fetch origin
if git rev-parse --verify origin/${{ steps.extract_branch.outputs.branch }} >/dev/null 2>&1; then
echo "✅ Switching $name to branch ${{ steps.extract_branch.outputs.branch }}"
git checkout ${{ steps.extract_branch.outputs.branch }}
git pull origin ${{ steps.extract_branch.outputs.branch }}
else
echo "🛑 No matching branch in $name — leaving on default"
fi
'

- name: Replace string code in monorepo
run: |
rm -rf ../AgapeToolkit/libs/string
cp -r . ../AgapeToolkit/libs/string

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20' # use your actual Node version
node-version: '24'

- name: Install Dependencies
- name: Install monorepo dependencies
working-directory: ../AgapeToolkit
run: npm ci

- name: Cache Nx
uses: actions/cache@v4
with:
path: .nx/cache
key: ${{ runner.os }}-nx-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-nx-

- name: Run Lint (Affected)
run: npx nx affected:lint --base=origin/main --head=HEAD

- name: Run Unit Tests (Affected)
run: npx nx affected:test --base=origin/main --head=HEAD
- name: Run tests for @agape/string
working-directory: ../AgapeToolkit
run: npx nx test string
40 changes: 27 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,30 @@ import {
pascalize,
pluralize,
titalize,
verbalize
verbalize,
quantify
} from '@agape/string'

camelize('foo bar') // fooBar
camelize('user name') // userName
camelize('email-address') // emailAddress

kebabify('Foo bar') // foo-bar
kebabify('Display Name') // display-name
kebabify('userProfileId') // user-profile-id

pascalize('Foo bar') // FooBar
pascalize('user id') // UserId
pascalize('api_response_code') // ApiResponseCode

pluralize('foo') // foos
pluralize('city') // cities
pluralize('analysis') // analyses

titalize('a foo a bar') // A Foo a Bar
quantify(1, 'item') // 1 item
quantify(3, 'box') // 3 boxes

verbalize('foo-bar') // Foo bar
titalize('the lord of the rings') // The Lord of the Rings
titalize('war and peace') // War and Peace

verbalize('user-profile-id') // User profile id
verbalize('XMLHttpRequest') // XML Http Request
```

## Description
Expand All @@ -33,31 +43,35 @@ Translate strings between different representations.

## Functions

`camelize`
`camelize(input: string)`

Convert to camel case.

`kebabify`
`kebabify(input: string)`

Converted to kebab-case: lower case, word boundaries replaced with dashes.

`pascalize`
`pascalize(input: string)`

Remove all symbols and spaces, captialize words.

`pluralize`
`pluralize(input: string)`

Adds an 's' to most words. Words that end in 'y' are changed to 'ies'.
Words that end in s have 'es' appended to the word.

`titalize`
`quantify(value: number, unit: string, plural?: string)`

The value will be paired with the unit, either singular or plural form

`titalize(input: number)`

The first letter of each word is capitalized with the exception of
`a, an, and, at, be, but, by, for, if, in, of, on, the, to` which are only
capitalized if they are the first word in the string, otherwise they
are converted to lowercase.

`verbalize`
`verbalize(input: number)`

First character capitalized, word boundaries replaced with spaces.

Expand Down
7 changes: 2 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@agape/string",
"version": "2.0.0",
"version": "2.1.0",
"description": "String and token manipulation",
"main": "./cjs/index.js",
"module": "./es2020/index.js",
Expand All @@ -10,15 +10,12 @@
],
"author": "Maverik Minett",
"license": "MIT",
"es2020": "./esm2020/index.js",
"es2015": "./esm2015/index.js",
"es2020": "./es2020/index.js",
"exports": {
"./package.json": {
"default": "./package.json"
},
".": {
"es2020": "./es2020/index.js",
"es2015": "./es2015/index.js",
"node": "./cjs/index.js",
"default": "./es2020/index.js",
"require": "./cjs/index.js",
Expand Down
Loading