Skip to content

Conversation

plbstl
Copy link
Contributor

@plbstl plbstl commented Jun 29, 2023

filenames are not capitalized when overwriting

See #748

filenames are not capitalized when overwriting
@vercel
Copy link

vercel bot commented Jun 29, 2023

@plbstl is attempting to deploy a commit to the shadcn-pro Team on Vercel.

A member of the Team first needs to authorize it.

@jacob-leger
Copy link

I agree, I always capitalize my components, and I know many people also do. I would love it if this feature was implemented!

@dan5py
Copy link
Contributor

dan5py commented Jul 5, 2023

I think that we would get too many prompts in the init command. What about having it just in the component.json?
And then maybe add a section in the CLI page where the component.json can be explained better.

@plbstl
Copy link
Contributor Author

plbstl commented Jul 5, 2023

I think that we would get too many prompts in the init command. What about having it just in the component.json?

I agree with you. This implementation does not modify the init command and allows the new config option to be optional.

And then maybe add a section in the CLI page where the component.json can be explained better.

Yes. #773

@shadcn
Copy link
Collaborator

shadcn commented Sep 19, 2023

I definitely want to support casing for file names. I'll label this and get back to it. I'll think about the best to implement this so that we can support any naming convention.

Thanks for starting the work on this @plbstl

@shadcn shadcn added enhancement New feature or request area: cli labels Sep 19, 2023
@atej
Copy link

atej commented Feb 3, 2024

Dropping this here as a temporary workaround.

Usage

npm run add-component button
# will install the button component and rename file from button.tsx to Button.tsx 

Installation

npm i -D tsx @types/node
// File: package.json

scripts: {
  // ...
  "add-component": "tsx ./npm-scripts/add-component.ts"
  // ...
}
// File: npm-scripts/add-component.ts

import { exec } from 'node:child_process'
import { rename } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = import.meta.dirname ?? dirname(fileURLToPath(import.meta.url))

// modify this to match the path of your ui components folder (relative to this file)
const base = resolve(__dirname, '..', 'src', 'components', 'ui')

main()

function main() {
  const componentName = process.argv[2]
  if (!componentName) {
    console.error('Please provide a component name.')
  } else {
    createComponent(componentName)
  }
}

function createComponent(componentName: string) {
  const command = `npx shadcn-ui@latest add ${componentName}`
  exec(command, (error, stdout, stderr) => {
    if (error) {
      console.error(`Error executing command: ${error.message}`)
      return
    }
    if (stdout) console.log(`${stdout}`)
    if (stderr) console.log(`${stderr}`)

    const oldFilePath = resolve(base, `${componentName}.tsx`)
    const newFilePath = resolve(base, `${renamer(componentName)}.tsx`)
    renameFile(oldFilePath, newFilePath)
  })
}

function renamer(name: string) {
  // change from kebab-case to PascalCase
  return name
    .split('-')
    .map(part => part.charAt(0).toUpperCase() + part.slice(1))
    .join('')
}

function renameFile(oldPath: string, newPath: string) {
  rename(oldPath, newPath, err => {
    if (err) {
      console.error(`Error renaming file: ${err}`)
      return
    }
    console.log(`File renamed to ${newPath}`)
  })
}

@FelipeBodelon
Copy link

FelipeBodelon commented Feb 10, 2024

Just started incorporating shadcn recently and I'd advice a bit of care with @atej's solution, as I found cross dependencies between some components, which would remain with invalid filenames on import. They are easily fixable but it should be taken into consideration.

One example of this happening is with the Alert Dialog component, which requires buttonVariants (but not the Button component). Can't really say if this is a good approach or not, but it's not documented as a composition of other components, doesn't warn about the Button dependency and isn't self contained on automatic installation.

// src/components/alert-dialog

"use client"
 
import * as React from "react"
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
 
import { cn } from "@/lib/utils"
import { buttonVariants } from "@/components/ui/button"

...

👍 +1 to having a config option for this

@alexiuscrow
Copy link

Hello, I've created #2723.
I think my PR partially solves your task. Please check it.
I added the case property to component.json. If you set the case property to pascal and overwrite the button component, the file name describing the component will always be Button.tsx(.jsx)

@Armadillidiid
Copy link

Can someone please review and merge this PR?

@sinantalhakosar
Copy link

Here is updated version of @atej workaround with using npx shadcn@latest add ${componentName}

// // File: npm-scripts/add-component.ts

import { execSync } from 'child_process';
import fs from 'fs';
import path from 'path';

function pascalCase(str: string): string {
  return str.split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join('');
}

function addComponent(componentName: string): void {
  try {
    // Run the shadcn command
    console.log(`Adding component: ${componentName}`);
    execSync(`npx shadcn@latest add ${componentName}`, { stdio: 'inherit' });

    // Rename the generated file
    // Update uiDir based on your project structure
    const uiDir = path.join(process.cwd(), 'components', 'ui');
    const oldPath = path.join(uiDir, `${componentName}.tsx`);
    const newPath = path.join(uiDir, `${pascalCase(componentName)}.tsx`);

    if (fs.existsSync(oldPath)) {
      fs.renameSync(oldPath, newPath);
      console.log(`Renamed ${componentName}.tsx to ${pascalCase(componentName)}.tsx`);
    } else {
      console.warn(`Warning: ${componentName}.tsx not found in components/ui directory`);
    }
  } catch (error) {
    console.error('Error adding component:', error);
  }
}

// Get the component name from command-line arguments
const componentName = process.argv[2];

if (!componentName) {
  console.error('Please provide a component name');
  process.exit(1);
}

addComponent(componentName);

@HasanMothaffar
Copy link

+1 For this. Choosing a naming convention is important

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: cli enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.