Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>necessary-templatesNew to Visual Studio Code? Get it now.

necessary-templates

Vinicius Pacheco

|
5 installs
| (0) | Free
Define templates so your project is standardized
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Necessary Templates

Necessary Templates logo

Necessary Templates is a Visual Studio Code plugin that enables users to create files faster by using templates. It works by selecting a template, writing a name, and then creating a file with the template content. If you have selected text, it will be used as the file name instead of asking the user for input.

Installation

To install Necessary Templates, follow these steps:

  1. Open Visual Studio Code
  2. Press Cmd+Shift+X (Mac) or Ctrl+Shift+X (Windows/Linux) to open the Extensions view
  3. Search for "Necessary Templates"
  4. Click "Install"

Usage

To use Necessary Templates, follow these steps:

  1. Open the Command Palette (Cmd+Shift+P or Ctrl+Shift+P)
  2. Search for "Necessary Templates: Create File"
  3. Select a template from the list
  4. Write a name for the file (if you have selected text, it will be used as the file name)
  5. Press Enter

Alternatively, you can use the keybinding Alt+Cmd+N (Mac) or Alt+Ctrl+N (Windows/Linux) to run the command directly.

The templates.js

interface TemplatesConfig {
  inputs?(ctx: TemplatesAPIContext): TemplateInputRequest[]

  getDirectories?(
    ctx: TemplatesAPIContext,
    utils: Utils,
  ): DirectoriesResponse | Promise<DirectoriesResponse>

  replaces?: ReplacesRecord

  formatName?(name: string, ctx: TemplatesAPIContext): string

  formatFileName?(
    name: string,
    ctx: TemplatesAPIContext,
    utils: TemplatesAPIUtils,
  ): string

  formatContent?(
    content: string,
    ctx: TemplatesAPIContext,
    utils: TemplatesAPIUtils,
  ): string

  onApply?(ctx: AfterContext, utils: Utils): void
}

inputs function

This function allows you to define input prompts for the user when creating a file with a specific template. For example, you could prompt the user to enter a description for a custom hook or to choose a storybook section for a component. The function receives an object with the current template and target directory and should return an array of objects with the input properties.

{
  inputs: ({ template, targetDir }) => {
    if (template.name === 'Hook') {
      return [
        {
          type: 'text',
          name: 'description',
          placeholder: 'A hook to ...',
          prompt: 'Choose a description for your hook',
        },
      ]
    }

    if (template.name === 'Component' && targetDir.includes('www/')) {
      return [
        {
          type: 'text',
          name: '__storybook_dir__',
          placeholder: 'Think like auth, group, user, etc..',
          prompt: 'Choose storybook section for this component',
        },
      ]
    }

    return []
  }
}

replaces object

This object defines the dynamic replacements that should be made in the template content before creating the file. You can define custom replacement functions that receive an object with the current inputs and target directory and return the replacement value. For example, you could replace __description__ in the template content with the value entered by the user in the description input.

{
  replaces: {
  __description__: ({ inputs }) => inputs.description,

  __verbose_name__: ({ inputs }) =>
    capitalize(inputs.selectedText.split('.').pop()),

  __procedure_name__: ({ inputs, targetDir }) =>
    `${path.basename(path.dirname(targetDir))}.${inputs.selectedText
      .split('.')
      .pop()}`,

  __storybook_dir__: ({ inputs, targetDir }) =>
    !targetDir.includes('packages/kit')
      ? inputs.__storybook_dir__?.trim() || 'UNDEFINED'
      : '@sass/ui',
  },
}

getDirectories function

This function allows you to define the list of directories where a specific template can be created. You can define custom logic based on the template and inputs to return an array of objects with the directory label and path properties. For example, you could define a list of possible directories for a component template, such as www/components and acme/kit/components, and return them based on the user input.

getDirectories: async ({ template, inputs }, { listDir }) => {
  if (template.name === 'Component') {
    return [
      {
        label: 'www',
        path: 'apps/www/components',
      },
      {
        label: 'acme/kit',
        path: 'packages/kit/components',
      },
      {
        label: 'page',
        path: 'apps/www/pages',
      },
    ]
  }

  if (template.name === 'Hook') {
    return [
      {
        label: 'www',
        path: 'apps/www/hooks',
      },
      {
        label: 'acme/kit',
        path: 'packages/kit/hooks',
      },
    ]
  }

  if (template.name === 'Query') {
    let routers = await listDir(
      path.resolve(template.workspacePath, 'apps/api/router/*'),
    )

    routers = routers
      .filter((r) => !r.includes('.'))
      .map((r) => path.basename(r))

    if (inputs.selectedText.includes('.')) {
      const [router] = inputs.selectedText.split('.')

      if (routers.includes(router)) {
        routers = [router, ...routers.filter((r) => r !== router)]
      } else {
        routers = [router, ...routers]
      }
    }

    return routers.map((router) => ({
      label: router,
      path: `apps/api/router/${router}`,
    }))
  }

  if (template.name === 'Schema') {
    return 'packages/schemas'
  }
}

formatName function

This function allows you to format the name of the file that will be created based on the user input. You can define custom logic based on the template and inputs to return the formatted name. For example, you could remove the package name prefix from a query name input before using it as the file name.

{
  formatName: (rawName, { template }) => {
    if (template.name === 'Query' || template.name === 'Mutation') {
      // ex.: app.findMany -> findMany
      return rawName.split('.').pop()
    }

    return rawName
  },
}

onApply function

This function allows you to define custom actions that should be performed after a file is created with a specific template. You can define custom logic based on the template and target directory to perform any additional actions, such as updating an index file or running a script. For example, you could update the index.ts file in a kit directory to export all kit components after creating a new component file.

{
  onApply: async ({ template, targetDir }, { listDir }) => {
    if (template.name === 'Component' && targetDir.includes('packages/kit')) {
      const kitDir = path.join(
        template.workspacePath,
        'packages',
        'kit',
        'components',
      )

      const kitFiles = await listDir(path.join(kitDir, '*'))
      const kitComponentDirectories = kitFiles
        .filter((f) => !f.includes('.'))
        .map((f) => path.basename(f))

      const content = `
// export all material ui components
export * from './material'

// export acme kit components
${kitComponentDirectories.map((name) => `export * from './${name}'`).join('\n')}
`.trim()

      await fs.promises.writeFile(
        path.resolve(kitDir, 'index.ts'),
        content,
        'utf-8',
      )
    }
  },
}

Credits

Necessary Templates was created by Vinicius Pacheco vin175pacheco@gmail.com and is licensed under the MIT license.

  • Contact us
  • Jobs
  • Privacy
  • Terms of use
  • Trademarks
© 2023 Microsoft