Skip to content

Commit

Permalink
feat: enhance kebabCase
Browse files Browse the repository at this point in the history
  • Loading branch information
coltenkrauter committed Nov 28, 2024
1 parent 8598636 commit e7e2430
Show file tree
Hide file tree
Showing 11 changed files with 1,649 additions and 1,609 deletions.
2,210 changes: 1,080 additions & 1,130 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"name": "@krauters/utils",
"description": "A versatile TypeScript utility package packed with reusable, type-safe functions, scripts useful for all kinds of TypeScript projects, and precommit scripts to streamline your development workflow.",
"version": "1.1.0",
"version": "1.2.0",
"main": "dist/src/index.js",
"type": "commonjs",
"scripts": {
"build": "tsc",
"dev": "ts-node ./src/index.ts",
"example-1": "ts-node ./examples/1.ts",
"fix": "npm run lint -- --fix",
"lint": "npx eslint src/**",
"lint": "npx eslint src/** test/**",
"prepare": "husky || true",
"prepublishOnly": "npm run build",
"start": "nodemon --inspect -e ts -w ./src -x npm run dev",
Expand All @@ -34,23 +34,23 @@
"license": "ISC",
"devDependencies": {
"@jest/globals": "^29.7.0",
"@krauters/eslint-config": "^1.4.0",
"@krauters/eslint-config": "^1.5.0",
"@types/jest": "^29.5.14",
"husky": "^9.1.6",
"husky": "^9.1.7",
"jest": "^29.7.0",
"nodemon": "^3.1.7",
"ts-jest": "^29.2.5",
"ts-node": "^10.9.2",
"typescript": "^5.6.3"
"typescript": "^5.7.2"
},
"files": [
"dist",
"scripts"
],
"dependencies": {
"@krauters/debuggable": "^0.4.0",
"@krauters/logger": "^0.3.2",
"@krauters/logger": "^0.6.0",
"@krauters/monkey-patcher": "^0.3.0",
"@krauters/structures": "^1.0.2"
"@krauters/structures": "^1.3.0"
}
}
84 changes: 42 additions & 42 deletions src/readme-sections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,48 @@ import { execSync } from 'child_process'

import { type BadgeSectionOptions, BadgeType, BadgeURL, type Section } from './structures'

/**
* Generates a badge section in Markdown/HTML format based on the selected `BadgeType`s.
*
* @param options - Configuration containing the list of `BadgeType`s, `packageJson`, `linkedInUsername`, and `repoPath`.
* @returns The generated Markdown/HTML badge section.
*/
export function getBadgeSection(options: BadgeSectionOptions): string {
const { badgeTypes, linkedInUsername, packageJson, repoPath = getRepoPathFromGit() } = options
const { name } = packageJson
const packageName = name.startsWith('@') ? name.replace('/', '%2F') : name

if (!repoPath && badgeTypes.some((badge) => badge !== BadgeType.LinkedIn)) {
log.warn(
`Warning: One or more badges are enabled but 'repoPath' is not supplied. Badge URLs may not be generated correctly.`,
)
}

const badges = {
[BadgeType.CodeSize]: `![Code Size](${BadgeURL.Shields}github/${BadgeType.CodeSize}/${repoPath})`,
[BadgeType.CommitsPerMonth]: `![Commits per Month](${BadgeURL.Shields}github/${BadgeType.CommitsPerMonth}/${repoPath})`,
[BadgeType.Contributors]: `![Contributors](${BadgeURL.Shields}github/${BadgeType.Contributors}/${repoPath})`,
[BadgeType.Forks]: `![Forks](${BadgeURL.Shields}github/${BadgeType.Forks}/${repoPath})`,
[BadgeType.GitHubStars]: `![GitHub Stars](${BadgeURL.Shields}github/${BadgeType.GitHubStars}/${repoPath})`,
[BadgeType.InstallSize]: `![Install Size](${BadgeURL.Shields}npm/${BadgeType.InstallSize}/${packageName})`,
[BadgeType.Issues]: `![GitHub Issues](${BadgeURL.Shields}github/${BadgeType.Issues}/${repoPath})`,
[BadgeType.LastCommit]: `![Last Commit](${BadgeURL.Shields}github/${BadgeType.LastCommit}/${repoPath})`,
[BadgeType.License]: `![License](${BadgeURL.Shields}github/license/${repoPath})`,
[BadgeType.LinkedIn]: linkedInUsername
? `<a href="${BadgeURL.LinkedIn}${linkedInUsername}" target="_blank"><img src="${BadgeURL.Shields}badge/LinkedIn-%230077B5.svg?&style=flat-square&logo=linkedin&logoColor=white" alt="LinkedIn"></a>`
: '',
[BadgeType.NpmVersion]: `[![npm version](${BadgeURL.Shields}npm/v/${packageName}.svg?style=flat-square)](https://www.npmjs.org/package/${packageJson.name})`,
[BadgeType.OpenPRs]: `![Open PRs](${BadgeURL.Shields}github/${BadgeType.OpenPRs}/${repoPath})`,
[BadgeType.RepoSize]: `![Repo Size](${BadgeURL.Shields}github/${BadgeType.RepoSize}/${repoPath})`,
[BadgeType.Version]: `![Version](${BadgeURL.Shields}github/${BadgeType.Version}/${repoPath})`,
[BadgeType.Visitors]: `![visitors](${BadgeURL.Visitors}${repoPath})`,
}

const badgesSection = badgeTypes.filter((badgeType) => badges[badgeType]).map((badgeType) => badges[badgeType])

return badgesSection.length > 0 ? `<div align="center">\n\n${badgesSection.join('\n')}\n\n</div>` : ''
}

/**
* Provides custom sections to be added to the README, incorporating data from `packageJson`.
*
Expand Down Expand Up @@ -59,45 +101,3 @@ export function getRepoPathFromGit(): string | undefined {
return undefined
}
}

/**
* Generates a badge section in Markdown/HTML format based on the selected `BadgeType`s.
*
* @param options - Configuration containing the list of `BadgeType`s, `packageJson`, `linkedInUsername`, and `repoPath`.
* @returns The generated Markdown/HTML badge section.
*/
export function getBadgeSection(options: BadgeSectionOptions): string {
const { badgeTypes, linkedInUsername, packageJson, repoPath = getRepoPathFromGit() } = options
const { name } = packageJson
const packageName = name.startsWith('@') ? name.replace('/', '%2F') : name

if (!repoPath && badgeTypes.some((badge) => badge !== BadgeType.LinkedIn)) {
log.warn(
`Warning: One or more badges are enabled but 'repoPath' is not supplied. Badge URLs may not be generated correctly.`,
)
}

const badges = {
[BadgeType.CodeSize]: `![Code Size](${BadgeURL.Shields}github/${BadgeType.CodeSize}/${repoPath})`,
[BadgeType.CommitsPerMonth]: `![Commits per Month](${BadgeURL.Shields}github/${BadgeType.CommitsPerMonth}/${repoPath})`,
[BadgeType.Contributors]: `![Contributors](${BadgeURL.Shields}github/${BadgeType.Contributors}/${repoPath})`,
[BadgeType.Forks]: `![Forks](${BadgeURL.Shields}github/${BadgeType.Forks}/${repoPath})`,
[BadgeType.GitHubStars]: `![GitHub Stars](${BadgeURL.Shields}github/${BadgeType.GitHubStars}/${repoPath})`,
[BadgeType.InstallSize]: `![Install Size](${BadgeURL.Shields}npm/${BadgeType.InstallSize}/${packageName})`,
[BadgeType.Issues]: `![GitHub Issues](${BadgeURL.Shields}github/${BadgeType.Issues}/${repoPath})`,
[BadgeType.LastCommit]: `![Last Commit](${BadgeURL.Shields}github/${BadgeType.LastCommit}/${repoPath})`,
[BadgeType.License]: `![License](${BadgeURL.Shields}github/license/${repoPath})`,
[BadgeType.LinkedIn]: linkedInUsername
? `<a href="${BadgeURL.LinkedIn}${linkedInUsername}" target="_blank"><img src="${BadgeURL.Shields}badge/LinkedIn-%230077B5.svg?&style=flat-square&logo=linkedin&logoColor=white" alt="LinkedIn"></a>`
: '',
[BadgeType.NpmVersion]: `[![npm version](${BadgeURL.Shields}npm/v/${packageName}.svg?style=flat-square)](https://www.npmjs.org/package/${packageJson.name})`,
[BadgeType.OpenPRs]: `![Open PRs](${BadgeURL.Shields}github/${BadgeType.OpenPRs}/${repoPath})`,
[BadgeType.RepoSize]: `![Repo Size](${BadgeURL.Shields}github/${BadgeType.RepoSize}/${repoPath})`,
[BadgeType.Version]: `![Version](${BadgeURL.Shields}github/${BadgeType.Version}/${repoPath})`,
[BadgeType.Visitors]: `![visitors](${BadgeURL.Visitors}${repoPath})`,
}

const badgesSection = badgeTypes.filter((badgeType) => badges[badgeType]).map((badgeType) => badges[badgeType])

return badgesSection.length > 0 ? `<div align="center">\n\n${badgesSection.join('\n')}\n\n</div>` : ''
}
21 changes: 19 additions & 2 deletions src/strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,27 @@ export class Strings {
* Converts a string to kebab-case.
*
* @param text The string to convert.
* @param splitCase Optional. Whether to split PascalCase or camelCase, as well as numbers. Defaults to false.
* @returns The kebab-case string.
*/
static kebabCase(text: string): string {
return text.toLowerCase().split(/\s+/).join('-')
static kebabCase(text: string, splitCase = false): string {
text = text.trim()

// Handle PascalCase or camelCase splitting if enabled
if (splitCase) {
text = text.replace(/([a-z])([A-Z])/g, '$1 $2')

// Split letters and numbers only if splitCase is true
text = text.replace(/([a-zA-Z])([0-9])/g, '$1 $2').replace(/([0-9])([a-zA-Z])/g, '$1 $2')
}

// Replace invalid characters with spaces, normalize whitespace to dashes
text = text.replace(/[^a-zA-Z0-9\s-]/g, ' ').replace(/\s+/g, '-')

// Remove leading and trailing dashes, and normalize consecutive dashes
text = text.replace(/^-+|-+$/g, '').replace(/-{2,}/g, '-')

return text.toLowerCase()
}

/**
Expand Down
136 changes: 68 additions & 68 deletions src/structures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,6 @@
import type { PackageJson } from '@krauters/structures'
import type { MakeDirectoryOptions } from 'fs'

export interface Section {
content?: string
header: string
placeholder?: string
required: boolean
}

export interface ReadmeParserOptions {
autoCreateMissing?: boolean
updateContent?: boolean
validateOnly?: boolean
}

export interface ParsedReadme {
description: string
sections: Section[]
title: string
}

export interface Section {
content?: string
header: string
placeholder?: string
required: boolean
}

export interface ParsedReadme {
description: string
sections: Section[]
title: string
}

export interface ValidateAndUpdateReadmeOptions {
autoCreateMissing?: boolean
badgeSection?: string
packageJsonPath?: string
repoPath?: string
sections?: Section[]
updateContent?: boolean
validateOnly?: boolean
}

export enum BadgeURL {
LinkedIn = 'https://www.linkedin.com/in/',
Shields = 'https://img.shields.io/',
Visitors = 'https://visitor-badge.laobi.icu/badge?page_id=',
}

export enum BadgeType {
CodeSize = 'languages/code-size',
CommitsPerMonth = 'commit-activity/m',
Expand All @@ -69,16 +21,10 @@ export enum BadgeType {
Visitors = 'visitors',
}

export interface BadgeSectionOptions {
badgeTypes: BadgeType[]
linkedInUsername?: string
packageJson: PackageJson
repoPath?: string
}

export interface StringToArrayParsingOptions {
delimiter?: string
removeWhitespace?: boolean
export enum BadgeURL {
LinkedIn = 'https://www.linkedin.com/in/',
Shields = 'https://img.shields.io/',
Visitors = 'https://visitor-badge.laobi.icu/badge?page_id=',
}

export enum SnapType {
Expand All @@ -91,21 +37,38 @@ export enum SnapType {
Year = 'year',
}

export interface SnapDateOptions {
days?: number
months?: number
snap?: SnapType
export interface BadgeSectionOptions {
badgeTypes: BadgeType[]
linkedInUsername?: string
packageJson: PackageJson
repoPath?: string
}

export interface Batch<T> {
index: number
items: T[]
}

export interface FromQueryParamsOptions {
query: string
}

export type MakeDirectoryOptionsExtended = {
suppressLogs?: boolean
} & MakeDirectoryOptions

export interface ParsedReadme {
description: string
sections: Section[]
title: string
}

export interface ParsedReadme {
description: string
sections: Section[]
title: string
}

export interface ReadDirectoryOptions {
encoding: BufferEncoding | null
withFileTypes?: false
Expand All @@ -116,10 +79,35 @@ export interface ReadJsonFileOptions {
flag?: string
}

export interface WriteJsonFileOptions {
encoding: BufferEncoding
flag?: string
mode?: number | string
export interface ReadmeParserOptions {
autoCreateMissing?: boolean
updateContent?: boolean
validateOnly?: boolean
}

export interface Section {
content?: string
header: string
placeholder?: string
required: boolean
}

export interface Section {
content?: string
header: string
placeholder?: string
required: boolean
}

export interface SnapDateOptions {
days?: number
months?: number
snap?: SnapType
}

export interface StringToArrayParsingOptions {
delimiter?: string
removeWhitespace?: boolean
}

export interface ToQueryParamsOptions {
Expand All @@ -129,6 +117,18 @@ export interface ToQueryParamsOptions {
sortKeys?: boolean
urlEncode?: boolean
}
export interface FromQueryParamsOptions {
query: string

export interface ValidateAndUpdateReadmeOptions {
autoCreateMissing?: boolean
badgeSection?: string
packageJsonPath?: string
repoPath?: string
sections?: Section[]
updateContent?: boolean
validateOnly?: boolean
}
export interface WriteJsonFileOptions {
encoding: BufferEncoding
flag?: string
mode?: number | string
}
Loading

0 comments on commit e7e2430

Please sign in to comment.