Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .eslintignore

This file was deleted.

22 changes: 0 additions & 22 deletions .eslintrc.js

This file was deleted.

4 changes: 4 additions & 0 deletions .github/codeql/codeql-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name: "CodeQL Config"

paths-ignore:
- test-fixtures
9 changes: 4 additions & 5 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This is the official Prettier VS Code extension (`prettier.prettier-vscode`). It

- Use `pnpm` as the package manager
- Run `pnpm install` to install dependencies
- Run `pnpm webpack` to build for development
- Run `pnpm compile` to build for development
- Run `pnpm test` to run tests (no VS Code instance can be running)
- Run `pnpm lint` to check linting
- Run `pnpm prettier` to format code
Expand All @@ -23,10 +23,9 @@ Core components:
- `src/extension.ts` - Extension activation, creates ModuleResolver, PrettierEditService, and StatusBar
- `src/PrettierEditService.ts` - Registers VS Code document formatting providers, handles format requests
- `src/ModuleResolver.ts` - Resolves local/global Prettier installations, falls back to bundled Prettier
- `src/PrettierWorkerInstance.ts` - Runs Prettier v3+ in a worker thread for async formatting
- `src/PrettierMainThreadInstance.ts` - Runs Prettier v2 synchronously on main thread
- `src/PrettierInstance.ts` - Interface for Prettier loading, with `PrettierMainThreadInstance` and `PrettierWorkerInstance` implementations

Webpack produces two bundles:
esbuild produces two bundles:

- Node bundle (`dist/extension.js`) for desktop VS Code
- Web bundle (`dist/web-extension.js`) for vscode.dev/browser
Expand Down Expand Up @@ -70,7 +69,7 @@ When reviewing pull requests, focus on:
### Performance

- Avoid blocking the extension host main thread
- Prettier v3+ should use worker threads via `PrettierWorkerInstance`
- `PrettierWorkerInstance` runs Prettier in a worker thread to avoid blocking
- Module and config resolution results are cached appropriately

### Browser Compatibility
Expand Down
4 changes: 2 additions & 2 deletions .github/instructions/typescript.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ This is a VS Code extension. Follow these patterns:

## Prettier Integration

- Support both Prettier v2 (sync, main thread) and v3+ (async, worker thread)
- `PrettierMainThreadInstance` for v2, `PrettierWorkerInstance` for v3+
- Support both Prettier v2 and v3+ via `PrettierInstance` interface
- `PrettierMainThreadInstance` loads directly, `PrettierWorkerInstance` uses worker thread
- Module resolution: local install → global install → bundled Prettier
- Handle `.prettierrc`, `.prettierignore`, and `package.json` prettier config

Expand Down
1 change: 0 additions & 1 deletion .husky/.gitignore

This file was deleted.

1 change: 0 additions & 1 deletion .husky/pre-commit

This file was deleted.

1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.useFlatConfig": true,
"editor.formatOnSave": true,
"editor.defaultFormatter": "prettier.prettier-vscode",
"editor.formatOnType": false,
Expand Down
9 changes: 5 additions & 4 deletions .vscodeignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.github/
.husky/
.vscode/
.vscode-test/
.vscode-test-web/
Expand All @@ -14,10 +13,12 @@ test-fixtures/
.prettierrc
CODE_OF_CONDUCT.md
CONTRIBUTING.md
CONTRIBUTORS.md
tsconfig.json
webpack.config.js
yarn.lock
tsconfig.scripts.json
eslint.config.mjs
lefthook.yml
esbuild.mjs
pnpm-lock.yaml
dist/*.map

node_modules/
Expand Down
9 changes: 5 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,12 @@ Web tests are located in `src/test/web/suite/` and test the extension's browser
- Caches resolved modules and configurations
- Handles Workspace Trust restrictions

**Prettier Instance Wrappers**:
**Prettier Instance** (`PrettierInstance.ts`, `PrettierMainThreadInstance.ts`, `PrettierWorkerInstance.ts`):

- `PrettierWorkerInstance.ts`: Runs Prettier v3+ in a worker thread for async formatting
- `PrettierMainThreadInstance.ts`: Runs Prettier v2 synchronously on main thread
- Worker script lives in `src/worker/prettier-instance-worker.js`
- `PrettierInstance` is an interface with two implementations
- `PrettierMainThreadInstance` loads Prettier directly via `require()`
- `PrettierWorkerInstance` loads Prettier in a worker thread to avoid blocking
- Works with both Prettier v2 and v3+

### Bundling

Expand Down
12 changes: 5 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Thank you for your interest in contributing to the Prettier VS Code extension! F

3. Build the extension:
```bash
pnpm webpack
pnpm compile
```

## Development
Expand All @@ -34,9 +34,8 @@ Thank you for your interest in contributing to the Prettier VS Code extension! F

```bash
pnpm install # Install dependencies
pnpm webpack # Build for development
pnpm webpack-dev # Build and watch for changes
pnpm watch # TypeScript watch mode (without webpack)
pnpm compile # Build for development (esbuild + type checking)
pnpm watch # Build and watch for changes
pnpm lint # Run ESLint
pnpm prettier # Format code with Prettier
pnpm test # Run tests
Expand All @@ -46,7 +45,7 @@ pnpm test-compile # Compile tests only
### Running the Extension

1. Open this repository in VS Code
2. Run `pnpm webpack` to build
2. Run `pnpm compile` to build
3. Press `F5` or go to Debug sidebar → "Run Extension"
4. A new VS Code window will open with the extension loaded

Expand Down Expand Up @@ -92,8 +91,7 @@ Key components:

- `PrettierEditService.ts` - Handles document formatting
- `ModuleResolver.ts` - Resolves Prettier installations (local, global, or bundled)
- `PrettierWorkerInstance.ts` - Runs Prettier v3+ in a worker thread
- `PrettierMainThreadInstance.ts` - Runs Prettier v2 on the main thread
- `PrettierInstance.ts` - Interface for Prettier, with `PrettierMainThreadInstance` and `PrettierWorkerInstance` implementations

## Submitting Changes

Expand Down
9 changes: 0 additions & 9 deletions CONTRIBUTORS.md

This file was deleted.

64 changes: 38 additions & 26 deletions esbuild.js → esbuild.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
const esbuild = require("esbuild");
const fs = require("fs");
const path = require("path");
import esbuild from "esbuild";
import fs from "fs";
import path from "path";

const production = process.argv.includes("--production");
const watch = process.argv.includes("--watch");

const extensionPackage = require("./package.json");
const extensionPackage = JSON.parse(
fs.readFileSync(new URL("./package.json", import.meta.url), "utf-8"),
);

/**
* @type {import('esbuild').Plugin}
Expand All @@ -30,27 +32,6 @@ const esbuildProblemMatcherPlugin = {
},
};

/**
* @type {import('esbuild').Plugin}
*/
const copyWorkerPlugin = {
name: "copy-worker",
setup(build) {
build.onEnd(() => {
const srcDir = path.join(__dirname, "src/worker");
const destDir = path.join(__dirname, "dist/worker");

if (fs.existsSync(srcDir)) {
fs.mkdirSync(destDir, { recursive: true });
fs.readdirSync(srcDir).forEach((file) => {
fs.copyFileSync(path.join(srcDir, file), path.join(destDir, file));
});
console.log("[copy] worker files copied");
}
});
},
};

/**
* @type {import('esbuild').Plugin}
*/
Expand Down Expand Up @@ -84,7 +65,7 @@ const nodeConfig = {
"process.env.EXTENSION_VERSION": JSON.stringify(extensionPackage.version),
},
logLevel: "silent",
plugins: [copyWorkerPlugin, esbuildProblemMatcherPlugin],
plugins: [esbuildProblemMatcherPlugin],
};

/**
Expand Down Expand Up @@ -163,12 +144,43 @@ const webTestConfig = {
plugins: [esbuildProblemMatcherPlugin],
};

function copyWorkerFile() {
// Copy to dist (for production/esbuild bundle)
const distWorkerDir = "dist/worker";
if (!fs.existsSync(distWorkerDir)) {
fs.mkdirSync(distWorkerDir, { recursive: true });
}
fs.copyFileSync(
"src/worker/prettier-instance-worker.js",
"dist/worker/prettier-instance-worker.js",
);

// Copy to out (for tests/tsc output)
const outWorkerDir = "out/worker";
if (!fs.existsSync(outWorkerDir)) {
fs.mkdirSync(outWorkerDir, { recursive: true });
}
fs.copyFileSync(
"src/worker/prettier-instance-worker.js",
"out/worker/prettier-instance-worker.js",
);
}

async function main() {
const nodeCtx = await esbuild.context(nodeConfig);
const browserCtx = await esbuild.context(browserConfig);
const webTestCtx = await esbuild.context(webTestConfig);

// Copy worker file
copyWorkerFile();

if (watch) {
// Watch the worker file for changes
fs.watchFile("src/worker/prettier-instance-worker.js", () => {
console.log("[watch] copying worker file");
copyWorkerFile();
});

await Promise.all([
nodeCtx.watch(),
browserCtx.watch(),
Expand Down
79 changes: 79 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
import eslintConfigPrettier from "eslint-config-prettier";
import globals from "globals";

export default tseslint.config(
// Global ignores
{
ignores: [
"dist/**",
"out/**",
"test-fixtures/**",
"node_modules/**",
".vscode-test/**",
".vscode-test-web/**",
"src/worker/**",
],
},

// Base ESLint recommended rules
eslint.configs.recommended,

// TypeScript files
{
files: ["src/**/*.ts"],
extends: [...tseslint.configs.recommendedTypeChecked],
languageOptions: {
parserOptions: {
project: ["./tsconfig.json"],
tsconfigRootDir: import.meta.dirname,
},
},
rules: {
"no-console": "error",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-require-imports": "off",
// Relax stricter rules from recommendedTypeChecked
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/require-await": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/no-redundant-type-constituents": "off",
"@typescript-eslint/no-duplicate-type-constituents": "off",
"@typescript-eslint/no-unnecessary-type-assertion": "off",
"@typescript-eslint/no-misused-promises": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/prefer-promise-reject-errors": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
],
},
},

// Script files (mjs)
{
files: ["*.mjs", "scripts/*.mjs"],
languageOptions: {
globals: {
...globals.node,
},
},
rules: {
"no-console": "off",
"no-unused-vars": [
"error",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
],
},
},

// Prettier config (must be last to override other formatting rules)
eslintConfigPrettier,
);
11 changes: 11 additions & 0 deletions lefthook.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pre-commit:
parallel: true
commands:
prettier:
glob: "**/*.{ts,json,md,yml,hbs,js,mjs}"
run: pnpm prettier --write {staged_files}
stage_fixed: true
lint:
stage_fixed: true
glob: "src/**/*.ts"
run: pnpm lint
Loading