diff --git a/info.json b/info.json index 7c4dfd9..be3c354 100644 --- a/info.json +++ b/info.json @@ -6,6 +6,9 @@ "name": "dprint-plugin-typescript", "description": "TypeScript/JavaScript code formatter.", "website": "https://dprint.dev/plugins/typescript/", + "npm": { + "name": "@dprint/typescript" + }, "selected": true, "configKey": "typescript", "keywords": [ @@ -33,6 +36,9 @@ "name": "dprint-plugin-json", "description": "JSON/JSONC code formatter.", "website": "https://dprint.dev/plugins/json/", + "npm": { + "name": "@dprint/json" + }, "selected": true, "configKey": "json", "keywords": [ @@ -51,6 +57,9 @@ "name": "dprint-plugin-markdown", "description": "Markdown code formatter.", "website": "https://dprint.dev/plugins/markdown/", + "npm": { + "name": "@dprint/markdown" + }, "selected": true, "configKey": "markdown", "keywords": [ @@ -72,6 +81,9 @@ "name": "dprint-plugin-toml", "description": "TOML code formatter.", "website": "https://dprint.dev/plugins/toml/", + "npm": { + "name": "@dprint/toml" + }, "selected": true, "configKey": "toml", "keywords": [ @@ -87,6 +99,9 @@ "name": "dprint-plugin-dockerfile", "description": "Dockerfile code formatter.", "website": "https://dprint.dev/plugins/dockerfile/", + "npm": { + "name": "@dprint/dockerfile" + }, "selected": false, "configKey": "dockerfile", "keywords": [ @@ -106,6 +121,9 @@ "name": "dprint-plugin-biome", "description": "Biome (JS/TS/JSON) wrapper plugin.", "website": "https://dprint.dev/plugins/biome/", + "npm": { + "name": "@dprint/biome" + }, "selected": false, "configKey": "biome", "keywords": [ @@ -135,6 +153,9 @@ "name": "dprint-plugin-oxc", "description": "Oxc (JS/TS) wrapper plugin.", "website": "https://dprint.dev/plugins/oxc/", + "npm": { + "name": "@dprint/oxc" + }, "selected": false, "configKey": "oxc", "keywords": [ @@ -161,6 +182,9 @@ "name": "dprint-plugin-mago", "description": "Mago (PHP) wrapper plugin.", "website": "https://dprint.dev/plugins/mago/", + "npm": { + "name": "@dprint/mago" + }, "selected": false, "configKey": "mago", "keywords": [ @@ -177,6 +201,9 @@ "name": "dprint-plugin-ruff", "description": "Ruff (Python) wrapper plugin.", "website": "https://dprint.dev/plugins/ruff/", + "npm": { + "name": "@dprint/ruff" + }, "selected": false, "configKey": "ruff", "keywords": [ @@ -195,6 +222,9 @@ "name": "dprint-plugin-jupyter", "description": "Jupyter notebook code block formatter.", "website": "https://dprint.dev/plugins/jupyter/", + "npm": { + "name": "@dprint/jupyter" + }, "selected": false, "configKey": "jupyter", "keywords": [ @@ -212,6 +242,9 @@ "name": "jakebailey/gofumpt", "description": "Gofumpt (Go) wrapper plugin.", "website": "https://dprint.dev/plugins/gofumpt/", + "npm": { + "name": "@jakebailey/dprint-plugin-gofumpt" + }, "selected": false, "configKey": "gofumpt", "keywords": [ @@ -229,6 +262,9 @@ "name": "g-plane/malva", "description": "CSS, SCSS, Sass and Less formatter.", "website": "https://dprint.dev/plugins/malva/", + "npm": { + "name": "dprint-plugin-malva" + }, "selected": true, "configKey": "malva", "keywords": [ @@ -252,6 +288,9 @@ "name": "g-plane/markup_fmt", "description": "HTML, Vue, Svelte, Astro, Angular, Jinja, Twig, Nunjucks, and Vento formatter.", "website": "https://dprint.dev/plugins/markup_fmt/", + "npm": { + "name": "dprint-plugin-markup" + }, "selected": true, "configKey": "markup", "keywords": [ @@ -298,6 +337,9 @@ "name": "g-plane/pretty_yaml", "description": "YAML formatter.", "website": "https://dprint.dev/plugins/pretty_yaml/", + "npm": { + "name": "dprint-plugin-yaml" + }, "selected": true, "configKey": "yaml", "keywords": [ @@ -316,6 +358,9 @@ "name": "g-plane/pretty_graphql", "description": "GraphQL formatter.", "website": "https://dprint.dev/plugins/pretty_graphql/", + "npm": { + "name": "dprint-plugin-graphql" + }, "selected": false, "configKey": "graphql", "keywords": [ @@ -332,6 +377,9 @@ { "name": "bartlomieju/lax-css", "description": "CSS, SCSS, and Less formatter that never reinterprets your styles.", + "npm": { + "name": "lax-css" + }, "selected": false, "configKey": "css", "keywords": [ @@ -352,6 +400,9 @@ { "name": "bartlomieju/lax-markup", "description": "HTML, XML, SVG, Vue, Svelte, and Astro formatter that preserves rendering-critical whitespace.", + "npm": { + "name": "lax-markup" + }, "selected": false, "configKey": "markup", "keywords": [ @@ -377,6 +428,9 @@ { "name": "bartlomieju/lax-sql", "description": "Dialect-agnostic SQL formatter.", + "npm": { + "name": "lax-sql" + }, "selected": false, "configKey": "sql", "keywords": [ @@ -438,6 +492,9 @@ "name": "dprint-plugin-prettier", "description": "Prettier wrapper plugin (consider faster dedicated plugins for JS/TS, CSS, etc.).", "website": "https://dprint.dev/plugins/prettier/", + "npm": { + "name": "@dprint/prettier" + }, "selected": false, "configKey": "prettier", "keywords": [ @@ -483,6 +540,9 @@ "name": "dprint-plugin-roslyn", "description": "C# and Visual Basic code formatter (Roslyn).", "website": "https://dprint.dev/plugins/roslyn/", + "npm": { + "name": "@dprint/roslyn" + }, "selected": false, "configKey": "roslyn", "keywords": [ @@ -504,6 +564,9 @@ "name": "dprint-plugin-exec", "description": "Formats code using formatting CLIs installed on the host machine (rustfmt, clang-format, shfmt, etc.).", "website": "https://dprint.dev/plugins/exec/", + "npm": { + "name": "@dprint/exec" + }, "selected": false, "configKey": "exec", "keywords": [ diff --git a/plugins.test.ts b/plugins.test.ts index d02952b..1511fc3 100644 --- a/plugins.test.ts +++ b/plugins.test.ts @@ -86,6 +86,7 @@ it("tryResolveUserLatestJson", async () => { url: `https://plugins.dprint.dev/typescript-${releaseInfo!.tagName}.wasm`, version: releaseInfo!.tagName, checksum: releaseInfo!.checksum, + npm: { name: "@dprint/typescript" }, }); } // dprint repo full name @@ -100,6 +101,7 @@ it("tryResolveUserLatestJson", async () => { url: `https://plugins.dprint.dev/typescript-${releaseInfo!.tagName}.wasm`, version: releaseInfo!.tagName, checksum: releaseInfo!.checksum, + npm: { name: "@dprint/typescript" }, }); } // non-dprint repo @@ -134,6 +136,19 @@ it("tryResolveUserLatestJson", async () => { url: `https://plugins.dprint.dev/prettier-${releaseInfo!.tagName}.json`, version: releaseInfo!.tagName, checksum: releaseInfo!.checksum, + npm: { name: "@dprint/prettier" }, + }); + } + // community repo published to npm + { + const result = await getValidResultForUrl("https://plugins.dprint.dev/g-plane/malva/latest.json"); + const releaseInfo = await getLatestReleaseInfo("g-plane", "malva"); + expect(result).toEqual({ + schemaVersion: 1, + url: `https://plugins.dprint.dev/g-plane/malva-${releaseInfo!.tagName}.wasm`, + version: releaseInfo!.tagName.replace(/^v/, ""), + checksum: releaseInfo!.checksum, + npm: { name: "dprint-plugin-malva" }, }); } diff --git a/plugins.ts b/plugins.ts index 47a161e..0027e33 100644 --- a/plugins.ts +++ b/plugins.ts @@ -1,3 +1,4 @@ +import infoJson from "./info.json" with { type: "json" }; import { checkGithubRepoExists, getLatestReleaseInfo } from "./utils/mod.js"; const tagPattern = "([A-Za-z0-9\._]+)"; @@ -57,6 +58,16 @@ const KNOWN_NON_PREFIXED_REPOS = new Set([ "lucacasonato/mf2-tools", ]); +/** The npm package a plugin is distributed as. */ +export interface PluginNpmInfo { + name: string; +} + +// the npm packages declared in info.json, keyed by `username/repo`. both the +// prefixed and unprefixed repo names are registered because either may be the +// resolved repo name (ex. `dprint/dprint-plugin-typescript` and `g-plane/malva`) +const npmPackagesByRepo = buildNpmPackagesByRepo(); + const APPROVED_ASSET_REPOS = new Set([ "drluckyspin/dprint-plugin-swift", ]); @@ -128,6 +139,8 @@ export async function tryResolveLatestJson(url: URL) { url: latestInfo.url, version: latestInfo.version, checksum: latestInfo.checksum, + // when set, the cli writes an npm specifier into config files instead of the url + npm: latestInfo.npm, }; } @@ -155,6 +168,8 @@ export async function getLatestInfo(username: string, repoName: string, origin: // downloads are recorded under and the tag of the latest release downloadKey: `${username}/${repoName}`, tag: releaseInfo.tagName, + // the npm package this plugin is published to, when it has one + npm: npmPackagesByRepo.get(`${username}/${repoName}`), }; } @@ -204,6 +219,21 @@ async function userRepoTagPatternMapper( return undefined; } +function buildNpmPackagesByRepo() { + const result = new Map(); + for (const plugin of infoJson.latest as { name: string; npm?: PluginNpmInfo }[]) { + if (plugin.npm == null) { + continue; + } + const slashIndex = plugin.name.indexOf("/"); + const username = slashIndex === -1 ? "dprint" : plugin.name.slice(0, slashIndex); + const shortName = plugin.name.slice(slashIndex + 1).replace(/^dprint-plugin-/, ""); + result.set(`${username}/${shortName}`, plugin.npm); + result.set(`${username}/dprint-plugin-${shortName}`, plugin.npm); + } + return result; +} + async function getFullRepoName(username: string, repoName: string) { if (repoName.startsWith("dprint-plugin-")) { return repoName;