Skip to content
Open
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to the "prettier-vscode" extension will be documented in thi

<!-- Check [Keep a Changelog](https://keepachangelog.com/) for recommendations on how to structure this file. -->

## [Unreleased]

- Add support for global Prettier plugins via `prettier.plugins` setting

## [11.0.0]

- [BREAKING CHANGE] Prevent `.editorconfig` from satisfying the `requireConfig` setting (#2708) - Thanks to [@redoPop](https://github.com/redoPop)
Expand Down
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
},
"dependencies": {
"find-up": "5.0.0",
"prettier": "^2.8.8",
"prettier": "^3.6.2",
"resolve": "^1.22.8",
"semver": "^7.6.3",
"vscode-nls": "^5.2.0"
Expand All @@ -154,6 +154,11 @@
"type": "object",
"title": "%ext.config.title%",
"properties": {
"prettier.plugins": {
"type": "array",
"default": [],
"markdownDescription": "%ext.config.plugins%"
},
"prettier.disableLanguages": {
"type": "array",
"items": {
Expand Down
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"ext.command.createConfigFile.title": "Prettier: Create Configuration File",
"ext.command.forceFormatDocument.title": "Format Document (Forced)",
"ext.config.plugins": "A list of plugins to automatically install and load globally.",
"ext.config.arrowParens": "Include parentheses around a sole arrow function parameter.",
"ext.config.bracketSpacing": "Controls the printing of spaces inside object literals.",
"ext.config.configPath": "Path to the prettier configuration file.",
Expand Down
1 change: 1 addition & 0 deletions package.nls.zh-cn.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"ext.command.createConfigFile.title": "Prettier:选择配置文件",
"ext.command.forceFormatDocument.title": "格式化文件(强制)",
"ext.config.plugins": "一组插件,用于自动全局安装和加载。",
"ext.config.arrowParens": "箭头函数仅有一个参数时,参数是否添加括号。",
"ext.config.bracketSpacing": "在对象字面量的花括号内侧使用空格作为间隔。",
"ext.config.configPath": "指定 Prettier 配置文件的路径。",
Expand Down
1 change: 1 addition & 0 deletions package.nls.zh-tw.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"ext.command.createConfigFile.title": "Prettier: 建立組態檔",
"ext.command.forceFormatDocument.title": "排版文件(強制)",
"ext.config.plugins": "一組插件,用於自動全域安裝和加載。",
"ext.config.arrowParens": "箭頭函式中只有一個參數也加上括號。",
"ext.config.bracketSpacing": "控制物件字面值中兩側的留白。",
"ext.config.configPath": "Prettier 組態檔的路徑。",
Expand Down
31 changes: 20 additions & 11 deletions src/BrowserModuleResolver.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {
ModuleResolverInterface,
PrettierFileInfoOptions,
PrettierFileInfoResult,
PrettierSupportLanguage,
PrettierModule,
PrettierOptions,
ModuleResolverInterface,
PrettierSupportLanguage,
PrettierVSCodeConfig,
} from "./types";

Expand All @@ -26,10 +26,10 @@ import * as yamlPlugin from "prettier/parser-yaml";
//import * as flowPlugin from "prettier/parser-flow";
//import * as postcssPlugin from "prettier/parser-postcss";

import { Options, Plugin, ResolveConfigOptions } from "prettier";
import { TextDocument, Uri } from "vscode";
import { LoggingService } from "./LoggingService";
import { getWorkspaceRelativePath } from "./util";
import { ResolveConfigOptions, Options } from "prettier";

const plugins = [
angularPlugin,
Expand All @@ -41,21 +41,21 @@ const plugins = [
meriyahPlugin,
typescriptPlugin,
yamlPlugin,
];
] as unknown as Plugin[];

export class ModuleResolver implements ModuleResolverInterface {
constructor(private loggingService: LoggingService) {}

public async getPrettierInstance(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_fileName: string
_fileName: string,
): Promise<PrettierModule | undefined> {
return this.getGlobalPrettierInstance();
}

public async getResolvedIgnorePath(
fileName: string,
ignorePath: string
ignorePath: string,
): Promise<string | undefined> {
return getWorkspaceRelativePath(fileName, ignorePath);
}
Expand All @@ -66,7 +66,9 @@ export class ModuleResolver implements ModuleResolverInterface {
format: (source: string, options: PrettierOptions) => {
return prettierStandalone.format(source, { ...options, plugins });
},
getSupportInfo: (): { languages: PrettierSupportLanguage[] } => {
getSupportInfo: async (): Promise<{
languages: PrettierSupportLanguage[];
}> => {
return {
languages: [
{
Expand Down Expand Up @@ -167,7 +169,7 @@ export class ModuleResolver implements ModuleResolverInterface {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
filePath: string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
options?: PrettierFileInfoOptions
options?: PrettierFileInfoOptions,
): Promise<PrettierFileInfoResult> => {
// TODO: implement ignore file reading
return { ignored: false, inferredParser: null };
Expand All @@ -181,15 +183,15 @@ export class ModuleResolver implements ModuleResolverInterface {
resolveConfigFile(filePath?: string | undefined): Promise<string | null>;
resolveConfig(
fileName: string,
options?: ResolveConfigOptions | undefined
options?: ResolveConfigOptions | undefined,
): Promise<Options | null>;
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
uri: Uri,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
fileName: string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
vscodeConfig: PrettierVSCodeConfig
vscodeConfig: PrettierVSCodeConfig,
): Promise<Options | "error" | "disabled" | null> {
return null;
}
Expand All @@ -198,11 +200,18 @@ export class ModuleResolver implements ModuleResolverInterface {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_doc: TextDocument,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_vscodeConfig: PrettierVSCodeConfig
_vscodeConfig: PrettierVSCodeConfig,
): Promise<"error" | "disabled" | PrettierOptions | null> {
return null;
}

resolvePluginsGlobally(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
plugins: string[],
): string[] {
return [];
}

dispose() {
// nothing to do
}
Expand Down
70 changes: 62 additions & 8 deletions src/ModuleResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,23 @@ import {
UNTRUSTED_WORKSPACE_USING_BUNDLED_PRETTIER,
USING_BUNDLED_PRETTIER,
} from "./message";
import { loadNodeModule, resolveConfigPlugins } from "./ModuleLoader";
import { PrettierInstance } from "./PrettierInstance";
import { PrettierMainThreadInstance } from "./PrettierMainThreadInstance";
import { PrettierWorkerInstance } from "./PrettierWorkerInstance";
import {
ModuleResolverInterface,
PackageManagers,
PrettierOptions,
PrettierResolveConfigOptions,
PrettierVSCodeConfig,
} from "./types";
import { getConfig, getWorkspaceRelativePath, isAboveV3 } from "./util";
import { PrettierWorkerInstance } from "./PrettierWorkerInstance";
import { PrettierInstance } from "./PrettierInstance";
import { PrettierMainThreadInstance } from "./PrettierMainThreadInstance";
import { loadNodeModule, resolveConfigPlugins } from "./ModuleLoader";
import {
getConfig,
getPackageInfo,
getWorkspaceRelativePath,
isAboveV3,
} from "./util";

const minPrettierVersion = "1.13.0";

Expand Down Expand Up @@ -57,6 +62,8 @@ const fsStatSyncWorkaround = (
// @ts-expect-error Workaround for https://github.com/prettier/prettier-vscode/issues/3020
fs.statSync = fsStatSyncWorkaround;

declare const __non_webpack_require__: NodeRequire;

const globalPaths: {
[key: string]: { cache: string | undefined; get(): string | undefined };
} = {
Expand Down Expand Up @@ -95,6 +102,7 @@ function globalPathGet(packageManager: PackageManagers): string | undefined {
export class ModuleResolver implements ModuleResolverInterface {
private findPkgCache: Map<string, string>;
private ignorePathCache = new Map<string, string>();
private pluginsCache = new Map<string, string[]>();

private path2Module = new Map<string, PrettierInstance>();

Expand All @@ -121,7 +129,7 @@ export class ModuleResolver implements ModuleResolverInterface {
return pkgFilePath;
}
},
{ cwd }
{ cwd },
);

if (!packageJsonPath) {
Expand Down Expand Up @@ -344,6 +352,52 @@ export class ModuleResolver implements ModuleResolverInterface {
return fileName;
}

public resolvePluginsGlobally(plugins: string[]): string[] {
if (plugins.length === 0) {
return [];
}

const cacheKey = plugins.sort().join(",");

if (this.pluginsCache.has(cacheKey)) {
return this.pluginsCache.get(cacheKey)!;
}

const pluginsDirectory = path.join(__dirname, "..", "plugins");

if (!fs.existsSync(pluginsDirectory)) {
fs.mkdirSync(pluginsDirectory, { recursive: true });
}

try {
this.loggingService.logInfo(
`Installing ${plugins.length} plugins at ${pluginsDirectory}`,
);

if (!fs.existsSync(path.join(pluginsDirectory, "package.json"))) {
execSync("npm init -y", { cwd: pluginsDirectory });
}

execSync(`npm install ${plugins.join(" ")}`, { cwd: pluginsDirectory });

const resolvedPlugins = plugins.map((plugin) =>
__non_webpack_require__.resolve(getPackageInfo(plugin).name, {
paths: [path.join(pluginsDirectory, "node_modules")],
}),
);

this.loggingService.logInfo(`Plugins installed successfully.`);

this.pluginsCache.clear();
this.pluginsCache.set(cacheKey, resolvedPlugins);

return resolvedPlugins;
} catch (error) {
this.loggingService.logError(`Failed to install plugins.`, error);
return [];
}
}

public async resolveConfig(
prettierInstance: {
version: string | null;
Expand Down Expand Up @@ -382,8 +436,8 @@ export class ModuleResolver implements ModuleResolverInterface {
config: isVirtual
? undefined
: vscodeConfig.configPath
? getWorkspaceRelativePath(fileName, vscodeConfig.configPath)
: configPath,
? getWorkspaceRelativePath(fileName, vscodeConfig.configPath)
: configPath,
editorconfig: isVirtual ? undefined : vscodeConfig.useEditorConfig,
};

Expand Down
Loading