Skip to content
Closed
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
7 changes: 7 additions & 0 deletions apps/gittensory-miner-extension/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ The extension does not request the `unlimitedStorage` permission, so a paste is
being parsed or saved once it exceeds a conservative size bound well under `chrome.storage.local`'s default 10 MiB
quota, instead of silently failing to save or leaving storage partially written.

## Icons

`icons/` holds the standard MV3 icon set (16/32/48/128) referenced from `manifest.json`'s top-level
`icons` and `action.default_icon`. Regenerate with `node icons/generate-icons.mjs` after the underlying
brand asset changes — it resizes `apps/gittensory-ui/public/favicon-512.png` via `sharp`, so the
extension's icon is always the same mark as the main site's favicon rather than a separately drawn asset.

## Host permissions

`manifest.json` grants `https://github.com/*` (for the issue-page content script) plus loopback host permissions —
Expand Down
23 changes: 23 additions & 0 deletions apps/gittensory-miner-extension/icons/generate-icons.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env node
// Regenerates the MV3 icon set (#4862) from the repo's own brand asset -- never hand-drawn/synthesized
// geometry, so the extension's icon is always the same mark as apps/gittensory-ui's favicon. Standard
// Chrome/Firefox MV3 sizes: 16 (toolbar/favicon), 32 (Windows/high-DPI toolbar), 48 (extensions page),
// 128 (Chrome Web Store listing + install dialog).
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import sharp from "sharp";

const here = dirname(fileURLToPath(import.meta.url));
const sourceIcon = resolve(here, "../../gittensory-ui/public/favicon-512.png");
const sizes = [16, 32, 48, 128];

await Promise.all(
sizes.map((size) =>
sharp(sourceIcon)
.resize(size, size)
.png()
.toFile(resolve(here, `icon-${size}.png`)),
),
);

console.log(`wrote icon-${sizes.join(".png, icon-")}.png from ${sourceIcon}`);
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/gittensory-miner-extension/icons/icon-16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/gittensory-miner-extension/icons/icon-32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 13 additions & 1 deletion apps/gittensory-miner-extension/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
"name": "LoopOver Miner Opportunity",
"description": "Contributor-facing GitHub issue opportunity signals from a locally configured miner plane.",
"version": "0.1.0",
"icons": {
"16": "icons/icon-16.png",
"32": "icons/icon-32.png",
"48": "icons/icon-48.png",
"128": "icons/icon-128.png"
},
"permissions": ["storage"],
"host_permissions": ["https://github.com/*", "http://localhost/*", "http://127.0.0.1/*"],
"background": {
Expand All @@ -19,6 +25,12 @@
],
"options_page": "options.html",
"action": {
"default_title": "LoopOver Miner"
"default_title": "LoopOver Miner",
"default_icon": {
"16": "icons/icon-16.png",
"32": "icons/icon-32.png",
"48": "icons/icon-48.png",
"128": "icons/icon-128.png"
}
}
}
5 changes: 5 additions & 0 deletions scripts/build-miner-extension.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@ const PACKAGE_FILES = [
"options.js",
"styles.css",
"toolbar-badge.js",
"icons/icon-16.png",
"icons/icon-32.png",
"icons/icon-48.png",
"icons/icon-128.png",
];

rmSync(outDir, { recursive: true, force: true });
mkdirSync(outDir, { recursive: true });
mkdirSync(resolve(outDir, "icons"), { recursive: true });

for (const file of PACKAGE_FILES) {
cpSync(resolve(source, file), resolve(outDir, file));
Expand Down
40 changes: 40 additions & 0 deletions test/unit/miner-extension-icons.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { readFileSync } from "node:fs";
import sharp from "sharp";
import { describe, expect, it } from "vitest";

const EXTENSION_DIR = "apps/gittensory-miner-extension";
const ICON_SIZES = [16, 32, 48, 128];

describe("miner extension icon set (#4862)", () => {
const manifest = JSON.parse(readFileSync(`${EXTENSION_DIR}/manifest.json`, "utf8"));

it("wires every icon size into the manifest's top-level icons and action.default_icon", () => {
for (const size of ICON_SIZES) {
const path = `icons/icon-${size}.png`;
expect(manifest.icons[String(size)]).toBe(path);
expect(manifest.action.default_icon[String(size)]).toBe(path);
}
});

it("ships a real PNG at the declared size for every icon", async () => {
for (const size of ICON_SIZES) {
const metadata = await sharp(`${EXTENSION_DIR}/icons/icon-${size}.png`).metadata();
expect(metadata.format).toBe("png");
expect(metadata.width).toBe(size);
expect(metadata.height).toBe(size);
}
});

it("packages every icon file into the built zip's PACKAGE_FILES list", () => {
const buildScript = readFileSync("scripts/build-miner-extension.mjs", "utf8");
for (const size of ICON_SIZES) {
expect(buildScript).toContain(`icons/icon-${size}.png`);
}
});

it("regenerates the icons from the repo's own brand asset, not a hand-drawn/synthesized source", () => {
const generator = readFileSync(`${EXTENSION_DIR}/icons/generate-icons.mjs`, "utf8");
expect(generator).toContain("favicon-512.png");
expect(generator).toContain("sharp");
});
});
Loading