Search code examples
reactjsvscode-snippets

How to convert kebab-case filename to pascal-case component name in vscode-snippets


I am making custom vscode-snippets and stumbled on converting kebab-case filename to pascal-case component name. Read vscode snippets documentation several time and still don't understant how to do it. Current snippet:

"react component": {
        "prefix": [
            "rc",
            "erc"
        ],
        "body": [
            "import { type FC } from 'react'",
            "import styles from './${TM_FILENAME_BASE}.module.sass'",
            "",
            "export const ${TM_FILENAME_BASE/(\\w+)-?(\\w+)?/${1:/capitalize}${2:/capitalize}/}: FC<${TM_FILENAME_BASE/(\\w+)-?(\\w+)?/${1:/capitalize}${2:/capitalize}/}Props> = (props) => {",
            "  const {  } = props;",
            "",
            "  return (",
            "    <div>",
            "       $2",
            "    </div>",
            "  );",
            "};",
            "",
            "export type ${TM_FILENAME_BASE/(\\w+)-?(\\w+)?/${1:/capitalize}${2:/capitalize}/}Props = {",
            "  ",
            "}",
            "",
        ],
        "description": "React Component with typed props and imported styles"
    }

Current result I'm getting:

  1. filename modal.tsx => Modal (good)
  2. filename react-modal.tsx => ReactModal (good)
  3. filename one-two-three.tsx => OneTwo-three (bad, I want OneTwoThree)

It does not work for filenames seperated with more than one - (dash)


Solution

  • I think this is what you want:

    "react component": {
            "prefix": [
                "rc",
                "erc"
            ],
            "body": [
                "import { type FC } from 'react'",
                "import styles from './${TM_FILENAME_BASE}.module.sass'",
                "",
                "export const ${TM_FILENAME_BASE/(^\\w)|-(\\w)/${1:/capitalize}${2:/capitalize}/g}: FC<${TM_FILENAME_BASE/(^\\w)|-(\\w)/${1:/capitalize}${2:/capitalize}/g}Props> = (props) => {",
                "  const {  } = props;",
                "",
                "  return (",
                "    <div>",
                "       $2",
                "    </div>",
                "  );",
                "};",
                "",
                "export type ${TM_FILENAME_BASE/(^\\w)|-(\\w)/${1:/capitalize}${2:/capitalize}/g}Props = {",
                "  ",
                "}",
                "",
            ],
            "description": "React Component with typed props and imported styles"
        }
    

    The main difference is going to be in the regex to capture 2 different character groups and replacing them with the capitalized version.

    {TM_FILENAME_BASE/(^\\w)|-(\\w)/${1:/capitalize}${2:/capitalize}/g}

    • (^\\w) matches the first character of the string.
    • -(\\w) matches the first character that follows a -
    • (^\\w)|-(\\w) = matches the first character of the string OR matches the first character that follows a -

    with this we have two regex groupings, denoted by the ( ), that we can then reference.

    • ${1:/capitalize} references the first grouping and capitalizes it.
    • ${2:/capitalize} references the second grouping and capitalizes it.

    The /g at the end is also important, because this is the regex flag that tells it to match all 'global' instances and not just the first occurrence.