| | @@ -1,7 +1,11 @@ |
| 1 | 1 | // Builds the extension and packs it as a .vsix, the file VS Code, Cursor, Windsurf and VSCodium install. |
| 2 | 2 | // |
| 3 | | -// node apps/vscode/scripts/package.mjs [--out dir] (writes <dir>/diffinery-<version>.vsix, default apps/vscode/dist) |
| 3 | +// node apps/vscode/scripts/package.mjs [--out dir] [--marketplace] |
| 4 | 4 | // |
| 5 | +// writes <dir>/diffinery-<version>.vsix (default dir apps/vscode/dist). --marketplace writes |
| 6 | +// diffinery-<version>-marketplace.vsix instead, the build for the Visual Studio Marketplace and Open VSX: |
| 7 | +// the same extension with diffinery.checkForUpdates off by default, because the marketplace updates it. |
| 8 | +// |
| 5 | 9 | // apps/diffinery/scripts/build-docs.mjs calls packageExtension() too, so the Worker serves the build at |
| 6 | 10 | // /-/vscode/diffinery.vsix. The .vsix has the layout `vsce package` writes (extension.vsixmanifest, |
| 7 | 11 | // [Content_Types].xml, extension/…), so it can also go to the Visual Studio Marketplace and Open VSX |
| | @@ -18,13 +22,18 @@ |
| 18 | 22 | |
| 19 | 23 | const xml = (s) => String(s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """); |
| 20 | 24 | |
| 21 | | -/** The manifest as installed: the workspace package's fields, named for the editor (publisher.name = codician.diffinery). */ |
| 22 | | -function manifestFor(pkg) { |
| 23 | | - const { scripts: _s, devDependencies: _d, dependencies: _deps, private: _p, ...rest } = pkg; |
| 25 | +/** |
| 26 | + * The manifest as installed: the workspace package's fields, named for the editor (publisher.name = codician.diffinery). |
| 27 | + * A marketplace build turns the extension's own update check off by default, so it doesn't offer diffinery.com's |
| 28 | + * build next to the marketplace's updates. |
| 29 | + */ |
| 30 | +export function manifestFor(pkg, { marketplace = false } = {}) { |
| 31 | + const { scripts: _s, devDependencies: _d, dependencies: _deps, private: _p, ...rest } = structuredClone(pkg); |
| 32 | + if (marketplace) rest.contributes.configuration.properties["diffinery.checkForUpdates"].default = false; |
| 24 | 33 | return { ...rest, name: EXTENSION_NAME }; |
| 25 | 34 | } |
| 26 | 35 | |
| 27 | | -function vsixManifest(m) { |
| 36 | +export function vsixManifest(m) { |
| 28 | 37 | const props = [ |
| 29 | 38 | ["Microsoft.VisualStudio.Code.Engine", m.engines.vscode], |
| 30 | 39 | ["Microsoft.VisualStudio.Code.ExtensionDependencies", (m.extensionDependencies ?? []).join(",")], |
| | @@ -62,6 +71,7 @@ |
| 62 | 71 | <Asset Type="Microsoft.VisualStudio.Code.Manifest" Path="extension/package.json" Addressable="true" /> |
| 63 | 72 | <Asset Type="Microsoft.VisualStudio.Services.Content.Details" Path="extension/readme.md" Addressable="true" /> |
| 64 | 73 | <Asset Type="Microsoft.VisualStudio.Services.Content.Changelog" Path="extension/changelog.md" Addressable="true" /> |
| 74 | + <Asset Type="Microsoft.VisualStudio.Services.Content.License" Path="extension/LICENSE.txt" Addressable="true" /> |
| 65 | 75 | <Asset Type="Microsoft.VisualStudio.Services.Icons.Default" Path="extension/${xml(m.icon)}" Addressable="true" /> |
| 66 | 76 | </Assets> |
| 67 | 77 | </PackageManifest> |
| | @@ -69,7 +79,7 @@ |
| 69 | 79 | } |
| 70 | 80 | |
| 71 | 81 | function contentTypes(names) { |
| 72 | | - const types = { ".json": "application/json", ".js": "application/javascript", ".md": "text/markdown", ".png": "image/png", ".woff": "font/woff", ".vsixmanifest": "text/xml" }; |
| 82 | + const types = { ".json": "application/json", ".js": "application/javascript", ".md": "text/markdown", ".txt": "text/plain", ".png": "image/png", ".woff": "font/woff", ".vsixmanifest": "text/xml" }; |
| 73 | 83 | const exts = [...new Set(names.map((n) => path.extname(n).toLowerCase()).filter((e) => e && types[e]))].sort(); |
| 74 | 84 | return `<?xml version="1.0" encoding="utf-8"?> |
| 75 | 85 | <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">${exts.map((e) => `<Default Extension="${e}" ContentType="${types[e]}"/>`).join("")}</Types> |
| | @@ -146,10 +156,10 @@ |
| 146 | 156 | return Buffer.concat([...locals, ...central, end]); |
| 147 | 157 | } |
| 148 | 158 | |
| 149 | | -/** Builds and packs the extension. Returns its version and the .vsix bytes. */ |
| 150 | | -export async function packageExtension() { |
| 159 | +/** Builds and packs the extension (for a marketplace with `marketplace: true`). Returns its version and the .vsix bytes. */ |
| 160 | +export async function packageExtension({ marketplace = false } = {}) { |
| 151 | 161 | const pkg = JSON.parse(await readFile(path.join(ROOT, "package.json"), "utf8")); |
| 152 | | - const manifest = manifestFor(pkg); |
| 162 | + const manifest = manifestFor(pkg, { marketplace }); |
| 153 | 163 | const bundle = await build({ |
| 154 | 164 | entryPoints: [path.join(ROOT, "src/extension.ts")], |
| 155 | 165 | bundle: true, |
| | @@ -166,6 +176,7 @@ |
| 166 | 176 | ["extension/package.json", JSON.stringify(manifest, null, 2)], |
| 167 | 177 | ["extension/readme.md", await readFile(path.join(ROOT, "README.md"))], |
| 168 | 178 | ["extension/changelog.md", await readFile(path.join(ROOT, "CHANGELOG.md"))], |
| 179 | + ["extension/LICENSE.txt", await readFile(path.join(ROOT, "../../LICENSE"))], |
| 169 | 180 | ["extension/dist/extension.js", bundle.outputFiles[0].contents], |
| 170 | 181 | [`extension/${manifest.icon}`, await readFile(path.join(ROOT, manifest.icon))], |
| 171 | 182 | ["extension/media/diffinery-icons.woff", await readFile(path.join(ROOT, "media/diffinery-icons.woff"))], |
| | @@ -181,9 +192,10 @@ |
| 181 | 192 | if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { |
| 182 | 193 | const i = process.argv.indexOf("--out"); |
| 183 | 194 | const out = i > 0 ? path.resolve(process.argv[i + 1]) : path.join(ROOT, "dist"); |
| 184 | | - const { version, vsix } = await packageExtension(); |
| 195 | + const marketplace = process.argv.includes("--marketplace"); |
| 196 | + const { version, vsix } = await packageExtension({ marketplace }); |
| 185 | 197 | await mkdir(out, { recursive: true }); |
| 186 | | - const file = path.join(out, `${EXTENSION_NAME}-${version}.vsix`); |
| 198 | + const file = path.join(out, `${EXTENSION_NAME}-${version}${marketplace ? "-marketplace" : ""}.vsix`); |
| 187 | 199 | await writeFile(file, vsix); |
| 188 | 200 | console.log(`vscode: ${path.relative(process.cwd(), file)} (${(vsix.length / 1024).toFixed(0)} KB)`); |
| 189 | 201 | } |