Skip to content

Format and Style Standards

VUP projects adopt unified code formatting and style standards to ensure team collaboration consistency and code quality. This guide details all formatting and code quality tools used in the project and their configurations.

Tool Overview

VUP projects use the following tools to ensure code quality and formatting consistency:

  • ESLint - Code quality checking and best practices
  • Prettier - Code formatting
  • TypeScript - Type checking and compilation
  • Tailwind CSS - Styling framework
  • PostCSS - CSS post-processor
  • VSCode - Editor configuration and plugins

ESLint Configuration

Basic Configuration

The project uses @antfu/eslint-config - a modern, opinionated ESLint configuration by Anthony Fu:

javascript
// eslint.config.js
import antfu from '@antfu/eslint-config';

export default antfu({
  // Basic configuration
  typescript: true,
  vue: true,
  stylistic: false,

  // Project-specific overrides
  overrides: [
    // Vue project configuration
    {
      files: ['apps/vue-template/**/*.{js,ts,vue}'],
      rules: {
        // Vue specific rules
      },
    },

    // Nuxt project configuration
    {
      files: ['apps/nuxt-template/**/*.{js,ts,vue}'],
      rules: {
        'no-undef': 'off', // Nuxt global functions
      },
    },

    // Configuration files
    {
      files: [
        '**/*.config.{js,ts}',
        '**/vite.config.*',
        '**/nuxt.config.*',
        '**/tailwind.config.*',
      ],
      rules: {
        'no-undef': 'off',
      },
    },
  ],

  // Ignore patterns
  ignores: [
    '**/node_modules/**',
    '**/dist/**',
    '**/build/**',
    '**/.nuxt/**',
    '**/.output/**',
    '**/.nitro/**',
    '**/.vitepress/cache/**',
    '**/.wxt/**',
  ],
});

Key Features

@antfu/eslint-config provides:

  • TypeScript Support - Full TypeScript integration with strict rules
  • Vue 3 Support - Optimized for Vue 3 Composition API
  • Modern JavaScript - ES2022+ features and best practices
  • Auto-import Support - Works with unplugin-auto-import
  • Minimal Configuration - Opinionated defaults, minimal setup required
  • Performance Optimized - Fast linting with minimal overhead

Configuration Options

The configuration supports various options:

javascript
export default antfu({
  // Enable TypeScript support
  typescript: true,

  // Enable Vue support
  vue: true,

  // Disable stylistic rules (use Prettier instead)
  stylistic: false,

  // Enable formatters
  formatters: true,

  // Enable unocss support
  unocss: true,

  // Custom rules
  rules: {
    // Override specific rules
  },
});

Prettier Configuration

Basic Configuration

javascript
// prettier.config.js
export default {
  semi: true,
  singleQuote: true,
  tabWidth: 2,
  trailingComma: 'es5',
  printWidth: 100,
  endOfLine: 'lf',
  bracketSameLine: false,
  overrides: [
    {
      files: '*.md',
      options: {
        printWidth: 80,
        proseWrap: 'always',
      },
    },
  ],
};

Configuration Explanation

  • semi: true - Use semicolons
  • singleQuote: true - Use single quotes
  • tabWidth: 2 - Indentation width of 2 spaces
  • trailingComma: "es5" - Add trailing commas where valid in ES5
  • printWidth: 100 - Line width limit of 100 characters
  • endOfLine: "lf" - Use LF line endings
  • bracketSameLine: false - Place > of multi-line JSX elements on next line

Markdown Special Configuration

javascript
// Markdown file special handling
{
  files: '*.md',
  options: {
    printWidth: 80, // Line width limit of 80 characters
    proseWrap: 'always', // Always wrap
  },
}

TypeScript Configuration

Root Configuration

json
// tsconfig.json
{
  "extends": "@tsconfig/node18/tsconfig.json",
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "strict": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "removeComments": false,
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "baseUrl": "."
  },
  "exclude": [
    "node_modules",
    "dist",
    "build",
    "**/.nuxt/**",
    "**/.output/**",
    "**/.nitro/**",
    "**/.vitepress/cache/**",
    "**/.wxt/**"
  ]
}

Application Configuration

json
// apps/*/tsconfig.json
{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "outDir": "./.output",
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@shared/*": ["../../_shared/*"]
    }
  },
  "include": [
    "src/**/*",
    "src/**/*.vue",
    "src/*.vue",
    "./auto-imports.d.ts",
    "src/vue-shim.d.ts"
  ]
}

Tailwind CSS Configuration

Basic Configuration

javascript
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    './apps/**/*.{vue,js,ts,jsx,tsx,html}',
    './packages/**/*.{vue,js,ts,jsx,tsx,html}',
    './_shared/**/*.{vue,js,ts,jsx,tsx,html}',
    './apps/vitepress-template/.vitepress/theme/**/*.{vue,js,ts,jsx,tsx,html}',
    './apps/vitepress-template/src/**/*.{vue,js,ts,jsx,tsx,html,md}',
    './index.html',
  ],
  theme: {},
  plugins: [require('@tailwindcss/forms'), require('@tailwindcss/typography')],
};

Plugin Explanation

  • @tailwindcss/forms - Form style reset and enhancement
  • @tailwindcss/typography - Typography style plugin

PostCSS Configuration

javascript
// postcss.config.js
export default {
  plugins: {
    'postcss-import': {},
    tailwindcss: {},
    autoprefixer: {},
  },
};

Plugin Explanation

  • postcss-import - Support @import syntax
  • tailwindcss - Tailwind CSS processor
  • autoprefixer - Automatically add browser prefixes

VSCode Configuration

Editor Settings

json
// .vscode/settings.json
{
  "editor.codeActionsOnSave": {
    "source.organizeImports": "never",
    "source.removeUnusedImports": "never",
    "source.fixAll.eslint": "never"
  },
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSaveMode": "file",
  "editor.tabSize": 2,
  "files.eol": "\n",
  "typescript.preferences.importModuleSpecifier": "relative",
  "scss.lint.unknownAtRules": "ignore",
  "eslint.enable": true,
  "eslint.validate": ["javascript", "typescript", "vue"],
  "eslint.workingDirectories": [".", "apps/*"],
  "typescript.preferences.includePackageJsonAutoImports": "auto",
  "typescript.suggest.autoImports": true,
  "typescript.updateImportsOnFileMove.enabled": "always",
  "typescript.preferences.organizeImports": {
    "enabled": false
  }
}
json
// .vscode/extensions.json
{
  "recommendations": [
    "esbenp.prettier-vscode",
    "dbaeumer.vscode-eslint",
    "ms-vscode.vscode-typescript-next",
    "ms-vscode.vscode-json",
    "bradlc.vscode-tailwindcss",
    "vue.volar",
    "pflannery.vscode-versionlens"
  ]
}

Plugin Explanation

  • esbenp.prettier-vscode - Prettier formatting plugin
  • dbaeumer.vscode-eslint - ESLint code checking plugin
  • ms-vscode.vscode-typescript-next - TypeScript support
  • ms-vscode.vscode-json - JSON file support
  • bradlc.vscode-tailwindcss - Tailwind CSS IntelliSense
  • vue.volar - Vue 3 language service
  • pflannery.vscode-versionlens - Version number display

Script Commands

Root Directory Scripts

json
// package.json
{
  "scripts": {
    "dev:all": "pnpm --filter '*' dev",
    "build:all": "pnpm --filter '*' build",
    "lint:all": "pnpm --filter '*' lint",
    "lint:fix:all": "pnpm --filter '*' lint:fix",
    "format:all": "pnpm --filter '*' format",
    "format:check:all": "pnpm --filter '*' format:check",
    "type-check:all": "pnpm --filter '*' type-check",
    "prepare": "husky",
    "changeset": "changeset",
    "version-packages": "changeset version",
    "deploy": "vercel --prod",
    "deploy:preview": "vercel"
  }
}

Application Scripts

json
// apps/*/package.json
{
  "scripts": {
    "dev": "vite",
    "build": "tsc --noEmit && vite build",
    "lint": "eslint src/ --ext .vue,.ts,.js",
    "lint:fix": "eslint src/ --ext .vue,.ts,.js --fix",
    "format": "prettier --write \"src/**/*.{js,ts,vue,json,css,scss}\"",
    "format:check": "prettier --check \"src/**/*.{js,ts,vue,json,css,scss}\""
  }
}

Usage Guide

Development Formatting

bash
# Format all files
pnpm format

# Check if formatting is correct
pnpm format:check

# Fix ESLint issues
pnpm lint:fix

Pre-commit Checks

The project is configured with Husky Git hooks that automatically run before commits:

bash
# pre-commit hook runs automatically
git add .
git commit -m "feat: add new feature"
# Automatically executes: pnpm lint-staged

Type Checking

bash
# Check TypeScript types
pnpm type-check

# Type checking also runs during build
pnpm build

Best Practices

1. Code Style

  • Use single quotes instead of double quotes
  • Use 2 spaces for indentation
  • Line width limit of 100 characters
  • Use trailing commas
  • Use semicolons

2. Import Order

javascript
// Correct import order
import { ref, computed } from 'vue'; // 1. Built-in modules
import { defineStore } from 'pinia'; // 2. External dependencies
import { useRouter } from 'vue-router'; // 3. External dependencies

import { api } from '@/utils/api'; // 4. Internal modules
import { formatDate } from '@/utils/date'; // 5. Internal modules

import type { User } from '@/types/user'; // 6. Type imports

3. Vue Components

vue
<template>
  <div class="container">
    <h1>{{ title }}</h1>
    <p>{{ description }}</p>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue';

interface Props {
  title: string;
  description?: string;
}

const props = withDefaults(defineProps<Props>(), {
  description: '',
});

const isVisible = ref(true);
const displayTitle = computed(() => props.title.toUpperCase());
</script>

<style scoped>
.container {
  @apply p-4 bg-white rounded-lg shadow-md;
}
</style>

4. TypeScript Types

typescript
// Use explicit type definitions
interface User {
  id: number;
  name: string;
  email: string;
  createdAt: Date;
}

// Use type imports
import type { User } from '@/types/user';

// Use generics
function createApi<T>(url: string): Promise<T> {
  return fetch(url).then((res) => res.json());
}

Dependencies

ESLint Dependencies

json
{
  "devDependencies": {
    "@antfu/eslint-config": "^5.4.1",
    "eslint": "^9.34.0"
  }
}

Key Dependencies

  • @antfu/eslint-config - Modern, opinionated ESLint configuration
  • eslint - JavaScript/TypeScript linter
  • prettier - Code formatter
  • typescript - TypeScript compiler
  • vue-tsc - Vue TypeScript checker