fix: update browser extension brand icon
|
|
@ -77,7 +77,7 @@ for the same Firefox publishing flow.
|
|||
For an explicit version check, pass the current tag after `--`:
|
||||
|
||||
```bash
|
||||
VERSTAK_BROWSER_ENV=/path/to/.env npm run publish:github -- v2.0.5
|
||||
VERSTAK_BROWSER_ENV=/path/to/.env npm run publish:github -- v2.0.6
|
||||
```
|
||||
|
||||
Release output:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"manifest_version": 3,
|
||||
"name": "Verstak Bridge",
|
||||
"version": "2.0.5",
|
||||
"version": "2.0.6",
|
||||
"description": "Send pages, selections, links, and files to the local Verstak browser inbox.",
|
||||
"author": "Verstak",
|
||||
"homepage_url": "https://github.com/mirivlad/verstak-browser-extension",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Verstak Bridge",
|
||||
"version": "2.0.5",
|
||||
"version": "2.0.6",
|
||||
"description": "Send pages, selections, links, and files to the local Verstak browser inbox.",
|
||||
"author": "Verstak",
|
||||
"homepage_url": "https://github.com/mirivlad/verstak-browser-extension",
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "verstak-browser-extension",
|
||||
"version": "2.0.5",
|
||||
"version": "2.0.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "verstak-browser-extension",
|
||||
"version": "2.0.5",
|
||||
"version": "2.0.6",
|
||||
"devDependencies": {
|
||||
"web-ext": "^8.3.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "verstak-browser-extension",
|
||||
"version": "2.0.5",
|
||||
"version": "2.0.6",
|
||||
"private": true,
|
||||
"description": "Verstak browser capture extension for Chromium and Firefox",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
"build": "node scripts/build-extension.js",
|
||||
"test": "node scripts/test-manifests.js && node scripts/test-hostname.js && node scripts/test-activity-tracker.js && node scripts/test-protocol.js && node scripts/test-i18n.js && node scripts/test-popup-settings.js && node scripts/test-popup-select-style.js && node scripts/test-popup-catalog-fallback.js && node scripts/test-background-i18n.js && node scripts/test-firefox-github-release.js",
|
||||
"test": "node scripts/test-manifests.js && node scripts/test-icons.js && node scripts/test-hostname.js && node scripts/test-activity-tracker.js && node scripts/test-protocol.js && node scripts/test-i18n.js && node scripts/test-popup-settings.js && node scripts/test-popup-select-style.js && node scripts/test-popup-catalog-fallback.js && node scripts/test-background-i18n.js && node scripts/test-firefox-github-release.js",
|
||||
"sign:firefox": "./scripts/sign-firefox-xpi.sh",
|
||||
"release:firefox": "./scripts/release-firefox-xpi.sh",
|
||||
"publish:firefox": "./scripts/publish-firefox-github-release.sh",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
## Highlights
|
||||
|
||||
- Replaced the legacy orange extension symbol with the current Verstak workbench
|
||||
icon in every browser size: 16, 48, and 128 pixels.
|
||||
- Chromium and Firefox packages now use the same icon source as the Verstak
|
||||
desktop application.
|
||||
|
||||
## Главное
|
||||
|
||||
- Старый оранжевый знак расширения заменён на актуальный фирменный значок
|
||||
Верстака во всех размерах: 16, 48 и 128 пикселей.
|
||||
- Пакеты Chromium и Firefox теперь используют тот же исходный знак, что и
|
||||
приложение Верстак.
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
MAGICK="${MAGICK_BIN:-magick}"
|
||||
SOURCE="$ROOT/shared/icons/verstak.svg"
|
||||
|
||||
if ! command -v "$MAGICK" >/dev/null; then
|
||||
echo "ImageMagick is required to generate browser extension icons: $MAGICK not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for size in 16 48 128; do
|
||||
"$MAGICK" -background none "$SOURCE" -resize "${size}x${size}" \
|
||||
"PNG32:$ROOT/shared/icons/icon${size}.png"
|
||||
done
|
||||
|
||||
echo "generated browser extension icons from $SOURCE"
|
||||
|
|
@ -6,23 +6,23 @@ const packageManifest = require('../package.json');
|
|||
const chromiumManifest = require('../chromium/manifest.json');
|
||||
const firefoxManifest = require('../firefox/manifest.json');
|
||||
|
||||
const version = '2.0.5';
|
||||
const asset = 'verstak-firefox-2.0.5.xpi';
|
||||
const version = '2.0.6';
|
||||
const asset = 'verstak-firefox-2.0.6.xpi';
|
||||
|
||||
assert.equal(packageManifest.version, version);
|
||||
assert.equal(chromiumManifest.version, version);
|
||||
assert.equal(firefoxManifest.version, version);
|
||||
assert.equal(release.releaseTag(version), 'v2.0.5');
|
||||
assert.equal(release.releaseTag(version), 'v2.0.6');
|
||||
assert.equal(
|
||||
release.releaseAssetURL(version, asset),
|
||||
'https://github.com/mirivlad/verstak-browser-extension/releases/download/v2.0.5/verstak-firefox-2.0.5.xpi',
|
||||
'https://github.com/mirivlad/verstak-browser-extension/releases/download/v2.0.6/verstak-firefox-2.0.6.xpi',
|
||||
);
|
||||
assert.deepEqual(release.updateManifest('verstak-bridge@verstak.app', version, asset), {
|
||||
addons: {
|
||||
'verstak-bridge@verstak.app': {
|
||||
updates: [{
|
||||
version: '2.0.5',
|
||||
update_link: 'https://github.com/mirivlad/verstak-browser-extension/releases/download/v2.0.5/verstak-firefox-2.0.5.xpi',
|
||||
version: '2.0.6',
|
||||
update_link: 'https://github.com/mirivlad/verstak-browser-extension/releases/download/v2.0.6/verstak-firefox-2.0.6.xpi',
|
||||
}],
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bin/env node
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const zlib = require('zlib');
|
||||
|
||||
const root = path.resolve(__dirname, '..');
|
||||
const source = fs.readFileSync(path.join(root, 'shared', 'icons', 'verstak.svg'), 'utf8');
|
||||
|
||||
assert.match(source, /fill="#1c2f4a"/i, 'icon source must define the Verstak navy');
|
||||
assert.match(source, /fill="#72d2b3"/i, 'icon source must define the Verstak mint');
|
||||
|
||||
function paeth(left, up, upperLeft) {
|
||||
const estimate = left + up - upperLeft;
|
||||
const leftDistance = Math.abs(estimate - left);
|
||||
const upDistance = Math.abs(estimate - up);
|
||||
const upperLeftDistance = Math.abs(estimate - upperLeft);
|
||||
if (leftDistance <= upDistance && leftDistance <= upperLeftDistance) return left;
|
||||
if (upDistance <= upperLeftDistance) return up;
|
||||
return upperLeft;
|
||||
}
|
||||
|
||||
function pngColors(file) {
|
||||
const png = fs.readFileSync(file);
|
||||
assert.deepStrictEqual(png.subarray(0, 8), Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]), `${file} must be PNG`);
|
||||
|
||||
let offset = 8;
|
||||
let width;
|
||||
let height;
|
||||
let bitDepth;
|
||||
let colorType;
|
||||
let palette;
|
||||
const idat = [];
|
||||
while (offset < png.length) {
|
||||
const length = png.readUInt32BE(offset);
|
||||
const type = png.toString('ascii', offset + 4, offset + 8);
|
||||
const data = png.subarray(offset + 8, offset + 8 + length);
|
||||
offset += length + 12;
|
||||
if (type === 'IHDR') {
|
||||
width = data.readUInt32BE(0);
|
||||
height = data.readUInt32BE(4);
|
||||
bitDepth = data[8];
|
||||
colorType = data[9];
|
||||
} else if (type === 'PLTE') {
|
||||
palette = data;
|
||||
} else if (type === 'IDAT') {
|
||||
idat.push(data);
|
||||
}
|
||||
}
|
||||
|
||||
assert.equal(bitDepth, 8, `${file} must use 8-bit samples`);
|
||||
assert.ok([2, 3, 6].includes(colorType), `${file} must use RGB, palette, or RGBA pixels`);
|
||||
const bytesPerPixel = colorType === 6 ? 4 : colorType === 2 ? 3 : 1;
|
||||
const rowSize = width * bytesPerPixel;
|
||||
const decoded = zlib.inflateSync(Buffer.concat(idat));
|
||||
const colors = new Set();
|
||||
let readOffset = 0;
|
||||
let previous = Buffer.alloc(rowSize);
|
||||
|
||||
for (let y = 0; y < height; y += 1) {
|
||||
const filter = decoded[readOffset++];
|
||||
const encoded = decoded.subarray(readOffset, readOffset + rowSize);
|
||||
readOffset += rowSize;
|
||||
const row = Buffer.alloc(rowSize);
|
||||
for (let x = 0; x < rowSize; x += 1) {
|
||||
const left = x >= bytesPerPixel ? row[x - bytesPerPixel] : 0;
|
||||
const up = previous[x];
|
||||
const upperLeft = x >= bytesPerPixel ? previous[x - bytesPerPixel] : 0;
|
||||
if (filter === 0) row[x] = encoded[x];
|
||||
else if (filter === 1) row[x] = (encoded[x] + left) & 255;
|
||||
else if (filter === 2) row[x] = (encoded[x] + up) & 255;
|
||||
else if (filter === 3) row[x] = (encoded[x] + Math.floor((left + up) / 2)) & 255;
|
||||
else if (filter === 4) row[x] = (encoded[x] + paeth(left, up, upperLeft)) & 255;
|
||||
else assert.fail(`${file} has unsupported PNG filter ${filter}`);
|
||||
}
|
||||
for (let x = 0; x < width; x += 1) {
|
||||
if (colorType === 3) {
|
||||
const paletteOffset = row[x] * 3;
|
||||
colors.add(palette.subarray(paletteOffset, paletteOffset + 3).toString('hex'));
|
||||
} else {
|
||||
const pixelOffset = x * bytesPerPixel;
|
||||
colors.add(row.subarray(pixelOffset, pixelOffset + 3).toString('hex'));
|
||||
}
|
||||
}
|
||||
previous = row;
|
||||
}
|
||||
return { width, height, colors };
|
||||
}
|
||||
|
||||
for (const [name, size, needsMint] of [
|
||||
['icon16.png', 16, false],
|
||||
['icon48.png', 48, true],
|
||||
['icon128.png', 128, true],
|
||||
]) {
|
||||
const icon = pngColors(path.join(root, 'shared', 'icons', name));
|
||||
assert.equal(icon.width, size, `${name} width`);
|
||||
assert.equal(icon.height, size, `${name} height`);
|
||||
assert.ok(icon.colors.has('1c2f4a'), `${name} must contain the Verstak navy`);
|
||||
if (needsMint) assert.ok(icon.colors.has('72d2b3'), `${name} must contain the Verstak mint`);
|
||||
}
|
||||
|
||||
console.log('browser extension icon tests passed');
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 765 B After Width: | Height: | Size: 642 B |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 1.2 KiB |
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<rect width="128" height="128" rx="26" fill="#1c2f4a"/>
|
||||
<path d="M28 34h72v18H28zm0 31h72v29H28z" fill="#72d2b3"/>
|
||||
<path d="M41 52v13m23-13v13m23-13v13" stroke="#1c2f4a" stroke-width="8"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 290 B |