diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..80721f3e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,125 @@ +name: Build browser-extension release + +on: + release: + types: [published] + +permissions: + contents: write + +jobs: + web-extensions: + name: Chrome, Edge, and Firefox + runs-on: ubuntu-latest + steps: + - name: Check out the release tag + uses: actions/checkout@v7 + with: + ref: ${{ github.event.release.tag_name }} + + - name: Use Node.js 24 + uses: actions/setup-node@v7 + with: + node-version: 24 + cache: npm + + - name: Apply release version + id: version + env: + RELEASE_TAG: ${{ github.event.release.tag_name }} + run: | + VERSION="$(node scripts/release-version.mjs "$RELEASE_TAG")" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + npm version "$VERSION" --no-git-tag-version --allow-same-version --ignore-scripts + npm run extension:ci:version + + - name: Install dependencies + run: npm ci + + - name: Package WebExtensions + run: npm run extension:package + + - name: Attach WebExtension ZIPs to release + env: + GH_TOKEN: ${{ github.token }} + RELEASE_TAG: ${{ github.event.release.tag_name }} + run: gh release upload "$RELEASE_TAG" artifacts/release/*.zip --clobber + + # Uncomment both steps below if release versions should also be committed + # back to package.json, package-lock.json, and extension/manifest.json on + # the repository's default branch. + # - name: Check out the default branch + # uses: actions/checkout@v7 + # with: + # ref: ${{ github.event.repository.default_branch }} + # + # - name: Commit release version to the default branch + # env: + # VERSION: ${{ steps.version.outputs.version }} + # run: | + # npm version "$VERSION" --no-git-tag-version --allow-same-version --ignore-scripts + # npm run extension:ci:version + # git config user.name "github-actions[bot]" + # git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + # git add package.json package-lock.json extension/manifest.json + # git diff --cached --quiet || git commit -m "chore: set version to $VERSION" + # git push origin "HEAD:${{ github.event.repository.default_branch }}" + + safari-extension: + name: Safari + runs-on: macos-latest + steps: + - name: Check out the release tag + uses: actions/checkout@v7 + with: + ref: ${{ github.event.release.tag_name }} + + - name: Use Node.js 24 + uses: actions/setup-node@v7 + with: + node-version: 24 + cache: npm + + - name: Apply release version + id: version + env: + RELEASE_TAG: ${{ github.event.release.tag_name }} + run: | + VERSION="$(node scripts/release-version.mjs "$RELEASE_TAG")" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + npm version "$VERSION" --no-git-tag-version --allow-same-version --ignore-scripts + npm run extension:ci:version + + - name: Install dependencies + run: npm ci + + - name: Build extension assets + run: | + npm run extension:build + node scripts/package-extensions.mjs --prepare-only + cp artifacts/extensions/safari/manifest.json extension/manifest.json + + - name: Build unsigned Safari container app + env: + VERSION: ${{ steps.version.outputs.version }} + run: | + xcodebuild \ + -project VisBug/VisBug.xcodeproj \ + -scheme VisBug \ + -configuration Release \ + -destination 'generic/platform=macOS' \ + -derivedDataPath artifacts/safari-build \ + MARKETING_VERSION="$VERSION" \ + CURRENT_PROJECT_VERSION="${{ github.run_number }}" \ + CODE_SIGNING_ALLOWED=NO \ + CODE_SIGNING_REQUIRED=NO \ + build + ditto -c -k --sequesterRsrc --keepParent \ + artifacts/safari-build/Build/Products/Release/VisBug.app \ + "artifacts/release/visbug2-safari-v$VERSION.zip" + + - name: Attach Safari ZIP to release + env: + GH_TOKEN: ${{ github.token }} + RELEASE_TAG: ${{ github.event.release.tag_name }} + run: gh release upload "$RELEASE_TAG" artifacts/release/*.zip --clobber diff --git a/.gitignore b/.gitignore index eed7d5eb..8af994ab 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ extension/toolbar/bundle.css extension/toolbar/chunks/ extension/build extension/tuts +artifacts/ VisBug/VisBug.xcodeproj/project.xcworkspace/xcuserdata/argyle.xcuserdatad/UserInterfaceState.xcuserstate diff --git a/VisBug/VisBug.xcodeproj/project.pbxproj b/VisBug/VisBug.xcodeproj/project.pbxproj index 663619f4..f7dfffdf 100644 --- a/VisBug/VisBug.xcodeproj/project.pbxproj +++ b/VisBug/VisBug.xcodeproj/project.pbxproj @@ -19,7 +19,6 @@ 8EBF95AE2550B10C007B8136 /* contextmenu in Resources */ = {isa = PBXBuildFile; fileRef = 8EBF95A72550B10C007B8136 /* contextmenu */; }; 8EBF95AF2550B10C007B8136 /* icons in Resources */ = {isa = PBXBuildFile; fileRef = 8EBF95A82550B10C007B8136 /* icons */; }; 8EBF95B02550B10C007B8136 /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = 8EBF95A92550B10C007B8136 /* manifest.json */; }; - 8EBF95B12550B10C007B8136 /* build in Resources */ = {isa = PBXBuildFile; fileRef = 8EBF95AA2550B10C007B8136 /* build */; }; 8EBF95B22550B10C007B8136 /* tuts in Resources */ = {isa = PBXBuildFile; fileRef = 8EBF95AB2550B10C007B8136 /* tuts */; }; /* End PBXBuildFile section */ @@ -65,7 +64,6 @@ 8EBF95A72550B10C007B8136 /* contextmenu */ = {isa = PBXFileReference; lastKnownFileType = folder; name = contextmenu; path = ../../extension/contextmenu; sourceTree = ""; }; 8EBF95A82550B10C007B8136 /* icons */ = {isa = PBXFileReference; lastKnownFileType = folder; name = icons; path = ../../extension/icons; sourceTree = ""; }; 8EBF95A92550B10C007B8136 /* manifest.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = manifest.json; path = ../../extension/manifest.json; sourceTree = ""; }; - 8EBF95AA2550B10C007B8136 /* build */ = {isa = PBXFileReference; lastKnownFileType = folder; name = build; path = ../../extension/build; sourceTree = ""; }; 8EBF95AB2550B10C007B8136 /* tuts */ = {isa = PBXFileReference; lastKnownFileType = folder; name = tuts; path = ../../extension/tuts; sourceTree = ""; }; /* End PBXFileReference section */ @@ -149,7 +147,6 @@ 8EBF95A72550B10C007B8136 /* contextmenu */, 8EBF95A82550B10C007B8136 /* icons */, 8EBF95A92550B10C007B8136 /* manifest.json */, - 8EBF95AA2550B10C007B8136 /* build */, 8EBF95AB2550B10C007B8136 /* tuts */, ); name = Resources; @@ -249,7 +246,6 @@ 8EBF95AF2550B10C007B8136 /* icons in Resources */, 8EBF95B22550B10C007B8136 /* tuts in Resources */, 8EBF95B02550B10C007B8136 /* manifest.json in Resources */, - 8EBF95B12550B10C007B8136 /* build in Resources */, 8EBF95AD2550B10C007B8136 /* toolbar in Resources */, 8EBF95AC2550B10C007B8136 /* visbug.js in Resources */, ); diff --git a/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug1x-1.png b/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug1x-1.png index d41ab68e..39805469 100644 Binary files a/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug1x-1.png and b/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug1x-1.png differ diff --git a/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug1x-2.png b/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug1x-2.png index 7796e50c..8af75fbc 100644 Binary files a/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug1x-2.png and b/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug1x-2.png differ diff --git a/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug1x.png b/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug1x.png index ce7a27fc..aefd6fbd 100644 Binary files a/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug1x.png and b/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug1x.png differ diff --git a/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug2x-1.png b/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug2x-1.png index 529c2ffb..aefd6fbd 100644 Binary files a/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug2x-1.png and b/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug2x-1.png differ diff --git a/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug2x-4.png b/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug2x-4.png index 580a7d99..39805469 100644 Binary files a/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug2x-4.png and b/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug2x-4.png differ diff --git a/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug2x.png b/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug2x.png index e3f79f27..52010e83 100644 Binary files a/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug2x.png and b/VisBug/VisBug/Assets.xcassets/AppIcon.appiconset/VisBug2x.png differ diff --git a/app/assets/visbug.png b/app/assets/visbug.png index acd17a2e..c655c262 100644 Binary files a/app/assets/visbug.png and b/app/assets/visbug.png differ diff --git a/assets/visbug.png b/assets/visbug.png index acd17a2e..c655c262 100644 Binary files a/assets/visbug.png and b/assets/visbug.png differ diff --git a/assets/visbug.svg b/assets/visbug.svg index cfa94da3..73d54467 100644 --- a/assets/visbug.svg +++ b/assets/visbug.svg @@ -1,8 +1,8 @@ - VisBug Copy 2 - Created with Sketch. + VisBug2 logo + VisBug logo with a version 2 badge. @@ -14,11 +14,12 @@ - + + 2 diff --git a/extension/icons/visbug.png b/extension/icons/visbug.png index 29184fec..aefd6fbd 100644 Binary files a/extension/icons/visbug.png and b/extension/icons/visbug.png differ diff --git a/extension/manifest.json b/extension/manifest.json index 65e19dc8..865e210c 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,9 +1,11 @@ { "name": "VisBug2", - "version": "0.4.9", + "version": "2.0.0", "description": "Open source browser design tools", "manifest_version": 3, - "icons": { "128": "icons/visbug-dev.png" }, + "icons": { + "128": "icons/visbug.png" + }, "permissions": [ "activeTab", "contextMenus", @@ -20,14 +22,18 @@ "128": "icons/visbug.png" } }, - "web_accessible_resources": [{ - "resources": [ - "tuts/*.gif", - "toolbar/*", - "toolbar/chunks/*" - ], - "matches": [""] - }], + "web_accessible_resources": [ + { + "resources": [ + "tuts/*.gif", + "toolbar/*", + "toolbar/chunks/*" + ], + "matches": [ + "" + ] + } + ], "commands": { "_execute_action": { "suggested_key": { diff --git a/package-lock.json b/package-lock.json index 10b85dd9..828c2653 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "visbug2", - "version": "0.4.9", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "visbug2", - "version": "0.4.9", + "version": "2.0.0", "license": "Apache-2.0", "dependencies": { "@chenglou/pretext": "^0.0.8", diff --git a/package.json b/package.json index 9808ba7f..16d54fc3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "visbug2", - "version": "0.4.9", + "version": "2.0.0", "description": "Community-maintained fork of VisBug, the open source browser design tools", "author": "Adam Argyle", "license": "Apache-2.0", @@ -20,22 +20,23 @@ "bundle": "rollup -c && postcss app/index.css -o app/bundle.css", "bundle:prod": "rollup -c --environment build:prod", "bump": "npm version patch -m 'Release %s'", - "postversion": "npm run extension:ci:version", + "version": "node scripts/sync-extension-version.mjs", "dev:js": "rollup -c -w --environment build:dev", "dev:css": "postcss app/index.css -o app/bundle.css -w", "dev:server": "browser-sync start --server \"app\" --files \"app/index.html,app/bundle.css,app/bundle.js\" --no-open --no-notify --no-ui --no-ghost-mode", "dev:extension": "npm run extension:build && npm run extension:local:version", - "extension": "npm run extension:js && npm run extension:css && npm run extension:copy && npm run extension:local:version", - "extension:local:version": "sed -i '' \"s/{{NPM_VERSION}}/0.0.0/\" ./extension/manifest.json && sed -i '' \"s/VisBug2/DevBug2/\" ./extension/manifest.json && sed -i '' \"s/visbug.png/visbug-dev.png/\" ./extension/manifest.json", - "extension:ci:version": "sed -i \"s/{{NPM_VERSION}}/$npm_package_version/\" ./extension/manifest.json", + "extension": "npm run dev:extension", + "extension:local:version": "node scripts/sync-extension-version.mjs --dev", + "extension:ci:version": "node scripts/sync-extension-version.mjs", "extension:build": "npm run extension:js && npm run extension:css && npm run extension:copy", - "extension:release": "npm run test:ci && npm run bump && npm run extension:build && npm run extension:zip", + "extension:package": "npm run extension:build && node scripts/package-extensions.mjs", + "extension:release": "npm run test:ci && npm run extension:package", "extension:js": "npm run bundle:prod", "extension:css": "postcss app/extension.css -o extension/toolbar/bundle.css", - "extension:copy": "cp app/bundle.min.js extension/toolbar/ && rm -rf extension/toolbar/chunks && cp -R app/chunks extension/toolbar/ && cp -R app/tuts/ extension/tuts", - "extension:zip": "rm -rf ./extension/build/* && mkdir ./visbug2_v$npm_package_version && cp -R ./extension/* ./visbug2_v$npm_package_version/ && zip -r ./extension/build/visbug2.zip ./visbug2_v$npm_package_version/ && rm -rf ./visbug2_v$npm_package_version", - "extension:firefox": "npm run dev:extension && cd extension && web-ext run", - "extension:firefox-build": "npm run extension:build && cd extension && web-ext build", + "extension:copy": "node scripts/build-extension-assets.mjs", + "extension:zip": "node scripts/package-extensions.mjs", + "extension:firefox": "npm run extension:build && node scripts/package-extensions.mjs --prepare-only && web-ext run --source-dir artifacts/extensions/firefox", + "extension:firefox-build": "npm run extension:package", "test": "ava", "test:perf": "node tests/selection-performance.mjs", "test:dev": "ava -v -w", diff --git a/readme.md b/readme.md index 55b04d90..409b2864 100644 --- a/readme.md +++ b/readme.md @@ -110,6 +110,34 @@ The original project's [wiki](https://github.com/GoogleChromeLabs/ProjectVisBug/ and [keyboard command reference](https://github.com/GoogleChromeLabs/ProjectVisBug/wiki/Keyboard-Master-List) remain useful background documentation. +#### Release packages + +Publishing a GitHub release with a numeric tag such as `v2.1.0` starts the +browser-extension release workflow. The tag version is applied to `package.json`, +`package-lock.json`, and each generated `manifest.json` before the build, and the +following files are attached to the GitHub release automatically: + +- `visbug2-chrome-v2.1.0.zip` +- `visbug2-edge-v2.1.0.zip` +- `visbug2-firefox-v2.1.0.zip` +- `visbug2-safari-v2.1.0.zip` + +Chrome, Edge, and Firefox packages have the archive layout expected by their +respective store upload forms. The Safari ZIP contains an unsigned macOS +container app for testing; +public App Store distribution still requires Apple signing and submission +through App Store Connect. + +To build the Chrome, Edge, and Firefox ZIPs locally, run: + +```sh +npm run extension:package +``` + +The files are written to `artifacts/release/`. The workflow contains a disabled, +commented block that can later be enabled to commit the release version back to +`package.json`, `package-lock.json`, and `extension/manifest.json`. + ## Contributing Issues and pull requests are welcome in the diff --git a/scripts/build-extension-assets.mjs b/scripts/build-extension-assets.mjs new file mode 100644 index 00000000..10872d20 --- /dev/null +++ b/scripts/build-extension-assets.mjs @@ -0,0 +1,34 @@ +import {access, copyFile, cp, mkdir, rm} from 'node:fs/promises' +import path from 'node:path' +import {fileURLToPath} from 'node:url' + +const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..') +const appDirectory = path.join(repositoryRoot, 'app') +const extensionDirectory = path.join(repositoryRoot, 'extension') +const toolbarDirectory = path.join(extensionDirectory, 'toolbar') + +const requiredInputs = [ + path.join(appDirectory, 'bundle.min.js'), + path.join(appDirectory, 'chunks'), + path.join(appDirectory, 'tuts'), +] + +for (const input of requiredInputs) { + await access(input) +} + +await mkdir(toolbarDirectory, {recursive: true}) +await copyFile( + path.join(appDirectory, 'bundle.min.js'), + path.join(toolbarDirectory, 'bundle.min.js'), +) + +const toolbarChunks = path.join(toolbarDirectory, 'chunks') +await rm(toolbarChunks, {recursive: true, force: true}) +await cp(path.join(appDirectory, 'chunks'), toolbarChunks, {recursive: true}) + +const extensionTutorials = path.join(extensionDirectory, 'tuts') +await rm(extensionTutorials, {recursive: true, force: true}) +await cp(path.join(appDirectory, 'tuts'), extensionTutorials, {recursive: true}) + +console.log('Copied generated JavaScript and tutorial assets into extension/') diff --git a/scripts/package-extensions.mjs b/scripts/package-extensions.mjs new file mode 100644 index 00000000..7bbd56bd --- /dev/null +++ b/scripts/package-extensions.mjs @@ -0,0 +1,112 @@ +import {access, cp, mkdir, readFile, rm, writeFile} from 'node:fs/promises' +import path from 'node:path' +import {fileURLToPath} from 'node:url' +import {cmd as webExt} from 'web-ext' + +const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..') +const extensionDirectory = path.join(repositoryRoot, 'extension') +const artifactsDirectory = path.join(repositoryRoot, 'artifacts') +const stagingDirectory = path.join(artifactsDirectory, 'extensions') +const releaseDirectory = path.join(artifactsDirectory, 'release') +const prepareOnly = process.argv.includes('--prepare-only') + +const packageJson = JSON.parse( + await readFile(path.join(repositoryRoot, 'package.json'), 'utf8'), +) +const sourceManifest = JSON.parse( + await readFile(path.join(extensionDirectory, 'manifest.json'), 'utf8'), +) +const version = packageJson.version + +if (!/^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/.test(version)) { + throw new Error( + `package.json version "${version}" cannot be used as a browser-extension version`, + ) +} + +const sourceEntries = ['visbug.js', 'contextmenu', 'icons', 'toolbar', 'tuts'] + +for (const entry of sourceEntries) { + await access(path.join(extensionDirectory, entry)) +} + +const releaseManifest = () => { + const manifest = structuredClone(sourceManifest) + manifest.name = 'VisBug2' + manifest.version = version + delete manifest.version_name + manifest.icons = {128: 'icons/visbug.png'} + manifest.action.default_icon = {128: 'icons/visbug.png'} + delete manifest.browser_specific_settings + return manifest +} + +const manifests = { + chrome: releaseManifest(), + edge: releaseManifest(), + firefox: releaseManifest(), + safari: releaseManifest(), +} + +manifests.chrome.background = { + service_worker: 'visbug.js', + type: 'module', +} +manifests.edge.background = structuredClone(manifests.chrome.background) +manifests.firefox.background = { + scripts: ['visbug.js'], + type: 'module', +} +manifests.firefox.browser_specific_settings = { + gecko: { + id: 'visbug2@node-projects.github.io', + strict_min_version: '142.0', + data_collection_permissions: { + required: ['none'], + }, + }, +} +manifests.safari.background = { + scripts: ['visbug.js'], + service_worker: 'visbug.js', + type: 'module', +} + +await rm(stagingDirectory, {recursive: true, force: true}) +await rm(releaseDirectory, {recursive: true, force: true}) +await mkdir(releaseDirectory, {recursive: true}) + +for (const [browser, manifest] of Object.entries(manifests)) { + const browserDirectory = path.join(stagingDirectory, browser) + await mkdir(browserDirectory, {recursive: true}) + + for (const entry of sourceEntries) { + await cp( + path.join(extensionDirectory, entry), + path.join(browserDirectory, entry), + {recursive: true}, + ) + } + + await writeFile( + path.join(browserDirectory, 'manifest.json'), + `${JSON.stringify(manifest, null, 2)}\n`, + ) +} + +if (!prepareOnly) { + for (const browser of ['chrome', 'edge', 'firefox']) { + await webExt.build({ + sourceDir: path.join(stagingDirectory, browser), + artifactsDir: releaseDirectory, + overwriteDest: true, + filename: `visbug2-${browser}-v${version}.zip`, + }) + } +} + +console.log( + prepareOnly + ? `Prepared browser extension sources for ${version}` + : `Created browser release ZIPs in ${releaseDirectory}`, +) diff --git a/scripts/release-version.mjs b/scripts/release-version.mjs new file mode 100644 index 00000000..3037bbdc --- /dev/null +++ b/scripts/release-version.mjs @@ -0,0 +1,27 @@ +const tag = process.argv[2] + +if (!tag) { + console.error('Usage: node scripts/release-version.mjs ') + process.exit(1) +} + +const match = /^(?:v)?((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*))$/.exec(tag) + +if (!match) { + console.error( + `Release tag "${tag}" is invalid. Use a numeric tag such as v2.1.0 or 2.1.0.`, + ) + process.exit(1) +} + +const version = match[1] +const parts = version.split('.').map(Number) + +if (parts.some(part => part > 65535) || parts.every(part => part === 0)) { + console.error( + `Release version "${version}" is not a valid browser-extension version.`, + ) + process.exit(1) +} + +process.stdout.write(version) diff --git a/scripts/sync-extension-version.mjs b/scripts/sync-extension-version.mjs new file mode 100644 index 00000000..bb0dc29c --- /dev/null +++ b/scripts/sync-extension-version.mjs @@ -0,0 +1,29 @@ +import {readFile, writeFile} from 'node:fs/promises' +import path from 'node:path' +import {fileURLToPath} from 'node:url' + +const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..') +const packagePath = path.join(repositoryRoot, 'package.json') +const manifestPath = path.join(repositoryRoot, 'extension', 'manifest.json') +const developmentBuild = process.argv.includes('--dev') + +const packageJson = JSON.parse(await readFile(packagePath, 'utf8')) +const manifest = JSON.parse(await readFile(manifestPath, 'utf8')) + +manifest.version = packageJson.version +manifest.name = developmentBuild ? 'DevBug2' : 'VisBug2' +manifest.icons = { + 128: developmentBuild ? 'icons/visbug-dev.png' : 'icons/visbug.png', +} +manifest.action.default_icon = { + 128: developmentBuild ? 'icons/visbug-dev.png' : 'icons/visbug.png', +} + +if (developmentBuild) { + manifest.version_name = `${packageJson.version} development` +} else { + delete manifest.version_name +} + +await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`) +console.log(`Synchronized extension manifest to ${packageJson.version}`)