Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
77af403
Add: A/B test framework with hub-hosted allocation config
ujiro99 Sep 13, 2026
97f5f52
Add: Onboarding variant B - welcome overlay instead of the intro step
ujiro99 Sep 13, 2026
d7b20eb
Fix: Address review findings on the onboarding welcome overlay
ujiro99 Sep 13, 2026
f5c4853
feat(pageAction): add dedicated prompt field with two-stage non-recur…
CoffeePatch Sep 15, 2026
ca6089e
feat(pageAction): add Side Panel display mode support to Page Action
CoffeePatch Sep 15, 2026
34b3583
feat: add side panel support to page actions
CoffeePatch Sep 15, 2026
b5cafa3
test: align schema tests with page action changes
CoffeePatch Sep 15, 2026
1c10b62
feat: add global icon color override
CoffeePatch Sep 15, 2026
4e7ed70
fix: address PR reviews and folder hover text color
CoffeePatch Sep 15, 2026
573ca20
refactor(extension): improve favicon detection with tldts and generic…
CoffeePatch Sep 15, 2026
7346b1c
feat(extension): update global icon color exclusion behavior and rena…
CoffeePatch Sep 15, 2026
0acf669
test(extension): add tests for custom icon recoloring and dynamic fav…
CoffeePatch Sep 15, 2026
901f829
fix(extension): handle bare IPv6 literals in getRegistrableDomain
ujiro99 Sep 16, 2026
891bdca
refactor(extension): restructure icon color preservation heuristics
ujiro99 Sep 16, 2026
565a099
refactor(extension): extract IconUrlsContext into its own module
ujiro99 Sep 16, 2026
15e926e
fix(extension): preserve folder favicon colors
ujiro99 Sep 16, 2026
73141e4
refactor(extension): split MenuImage into per-variant components
ujiro99 Sep 16, 2026
842eb47
refactor(extension): centralize user style lookups
ujiro99 Sep 16, 2026
51f6692
refactor(extension): extract the icon color toggle from IconField
ujiro99 Sep 16, 2026
0b4f022
chore(extension): drop unused originalIconUrl and tidy leftovers
ujiro99 Sep 16, 2026
4c1198a
fix(extension): translate global icon color strings into all locales
ujiro99 Sep 16, 2026
c29b289
refactor(extension): centralize icon resolution in useSettingsWithIma…
ujiro99 Sep 17, 2026
739783a
refactor(extension): extract InfoTooltip and use it for the icon colo…
ujiro99 Sep 17, 2026
5d11ea4
Update: Refine UI of IconField.
ujiro99 Sep 17, 2026
6fd1a04
feat(extension): preview the global icon color in IconField
ujiro99 Sep 17, 2026
9a469af
fix(extension): apply the same-site icon check in IconField
ujiro99 Sep 17, 2026
8bd53f9
fix(extension): keep folder properties the stored folder omits
ujiro99 Sep 17, 2026
5aed4d8
perf(extension): resolve icon colors in the service worker
ujiro99 Sep 17, 2026
aa0e9f8
Add: Start development of v1.3.0
ujiro99 Sep 17, 2026
7045bb9
fix: Follow URL changes for the command search page.
ujiro99 Sep 17, 2026
75301ce
fix: e2e
ujiro99 Sep 17, 2026
6da2cdb
Merge branch 'dev-1.3.0' into feature/global-icon-color-override
ujiro99 Sep 17, 2026
c52b8d0
Merge pull request #457 from CoffeePatch/feature/global-icon-color-ov…
ujiro99 Sep 17, 2026
e4c898e
Merge branch 'dev-1.3.0' into feat/onboarding-ab-test
ujiro99 Sep 17, 2026
3061e6d
feat(extension): オンボーディングの案内文を改善
ujiro99 Sep 17, 2026
b481990
fix(extension): オンボーディング文言の翻訳を更新
ujiro99 Sep 17, 2026
f415051
Merge remote-tracking branch 'origin/dev-1.3.0' into feat/onboarding-…
Copilot Sep 17, 2026
570586d
fix: address validation findings
Copilot Sep 17, 2026
accee7a
fix: harden icon color handling
Copilot Sep 17, 2026
e033991
fix: stabilize icon cache resolution
Copilot Sep 17, 2026
3cc897d
refactor: simplify duplicated logic in page action prompt/side panel …
ujiro99 Sep 17, 2026
f9621a1
Merge remote-tracking branch 'origin/dev-1.3.0' into feature/page-act…
ujiro99 Sep 17, 2026
7f1a950
Merge pull request #458 from CoffeePatch/feature/page-action-prompt
ujiro99 Sep 17, 2026
9659d6a
feat(pageAction): replace the prompt field with template-capable user…
ujiro99 Sep 17, 2026
7a78f11
feat(pageAction): suggest a Prompt variable when the start URL is an …
ujiro99 Sep 17, 2026
2fbe1cf
Merge pull request #456 from ujiro99/feat/onboarding-ab-test
ujiro99 Sep 18, 2026
155d69f
Merge branch 'dev-1.3.0' into feature/user-variables-integration
ujiro99 Sep 18, 2026
f6ab208
feat(pageAction): improve user variable editing
ujiro99 Sep 21, 2026
50d8603
refactor(option): improve editor controls
ujiro99 Sep 21, 2026
d392612
style(option): widen page action editor layout
ujiro99 Sep 21, 2026
d940970
refactor(pageAction): unify user variable validation
ujiro99 Sep 21, 2026
d15e6d8
feat(ui): add optional input character counter
ujiro99 Sep 21, 2026
56144b2
style(pageAction): refine user variable controls
ujiro99 Sep 21, 2026
bafb2e4
fix(extension): correct user variable insertion menu
ujiro99 Sep 21, 2026
36dfb48
test(extension): cover user variable expansion
ujiro99 Sep 21, 2026
9e0af5f
fix(pageAction): scope placeholder conversion to {{...}}
ujiro99 Sep 21, 2026
737d186
feat(option): warn before orphaning user variable references
ujiro99 Sep 21, 2026
ac32e84
refactor(extension): drop unused isValidVariableName
ujiro99 Sep 21, 2026
9d8bfde
style(extension): apply prettier to files missed by precommit
ujiro99 Sep 21, 2026
2e61af1
Merge pull request #461 from ujiro99/feature/user-variables-integration
ujiro99 Sep 21, 2026
184ec79
fix: address PR review comments
ujiro99 Sep 21, 2026
389f6d7
feat: carry the extension version on the uninstall URL
ujiro99 Sep 22, 2026
1b98ecd
Merge pull request #462 from ujiro99/feature/uninstall-event-tracking
ujiro99 Sep 22, 2026
3c2deb4
style: trim the uninstall URL comments
ujiro99 Sep 22, 2026
5fb6141
style: trim the uninstall URL comments
ujiro99 Sep 22, 2026
443df22
Merge pull request #463 from ujiro99/style/trim-uninstall-comments
ujiro99 Sep 22, 2026
c570f2f
Merge pull request #464 from ujiro99/feature/uninstall-event-tracking
ujiro99 Sep 22, 2026
110f158
fix: fall back to default icon colors when resolveIconColors fails
ujiro99 Sep 22, 2026
345a16d
refactor: split ImportExport into service, hook and view
ujiro99 Sep 22, 2026
2cbdb13
fix: hide backups without commands from restore options
ujiro99 Sep 22, 2026
dd127a9
fix: keep sync storage writes queued during an in-flight write
ujiro99 Sep 23, 2026
06ed6f0
refactor: use promise-based chrome.storage.sync.set in debouncedSyncSet
ujiro99 Sep 23, 2026
4fd69a7
fix: notify the user when the selected settings file cannot be read
ujiro99 Sep 23, 2026
159ee18
Merge pull request #466 from ujiro99/fix/import-error
ujiro99 Sep 23, 2026
41bc17e
Remove alt text from logo image
ujiro99 Sep 23, 2026
4b1608d
fix: read the clipboard for AI prompts using the query URL approach
ujiro99 Sep 23, 2026
ee0d1f5
refactor: rename useClipboard to allowClipboardFallback in command pa…
ujiro99 Sep 23, 2026
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
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ yarn dev # watch モード

1. **型システム共有**: SharedパッケージでBaseCommandなどの基本型を定義し、ExtensionとHubで拡張
2. **AIサービス定義**: `packages/hub/public/data/ai-services.json` を Extension がビルド時/実行時の両方で参照
3. **e2eテスト**: `packages/hub` がデプロイする `/en/test` ページを Extension の Playwright テストが利用
3. **ABテスト配分設定**: `packages/hub/public/data/experiments.json` を Extension が実行時に参照し、オンボーディング等のABテストの配分比率を制御
4. **e2eテスト**: `packages/hub` がデプロイする `/en/test` ページを Extension の Playwright テストが利用

### Chrome拡張機能の構造 (packages/extension)

Expand Down Expand Up @@ -188,7 +189,7 @@ interface PageActionOption {
**Hub開発:**

- Hub は縮小版のため新機能は追加しない。コマンド共有プラットフォームとしての機能拡張は新リポジトリ(selection-command-hub)側で行う
- `ai-services.json` とテストページの変更時は Extension 側への影響を確認すること
- `ai-services.json` / `experiments.json` とテストページの変更時は Extension 側への影響を確認すること

**テスト:**

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "selection-command-monorepo",
"version": "1.2.0",
"version": "1.3.0",
"private": true,
"description": "Selection Command - Monorepo for Chrome Extension and Hub",
"author": "ujiro99",
Expand Down
104 changes: 104 additions & 0 deletions packages/extension/e2e/data/test-settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,110 @@
]
},
"revision": 0
},
{
"id": "cmd-test-pa-user-variable-builtins",
"title": "User Variable with Built-ins",
"openMode": "pageAction",
"parentFolderId": "0f2167ab-2e1b-4972-954c-71eec058ab14",
"pageActionOption": {
"openMode": "tab",
"startUrl": "https://ujiro99.github.io/selection-command/en/test",
"userVariables": [
{
"name": "Prompt",
"value": "Selected: {{SelectedText}} / Source: {{Url}}"
}
],
"steps": [
{
"delayMs": 0,
"id": "pa-user-builtins-s1",
"param": {
"label": "Start",
"type": "start",
"url": "https://ujiro99.github.io/selection-command/en/test"
},
"skipRenderWait": false
},
{
"delayMs": 500,
"id": "pa-user-builtins-s2",
"param": {
"label": "Text input",
"selector": "//input[@placeholder='text input']",
"selectorType": "xpath",
"type": "input",
"value": "{{Prompt}}"
},
"skipRenderWait": false
},
{
"delayMs": 0,
"id": "pa-user-builtins-s3",
"param": {
"label": "End",
"type": "end"
},
"skipRenderWait": false
}
]
},
"revision": 0
},
{
"id": "cmd-test-pa-nested-user-variables",
"title": "Nested User Variables",
"openMode": "pageAction",
"parentFolderId": "0f2167ab-2e1b-4972-954c-71eec058ab14",
"pageActionOption": {
"openMode": "tab",
"startUrl": "https://ujiro99.github.io/selection-command/en/test",
"userVariables": [
{
"name": "Topic",
"value": "Topic: {{SelectedText}}"
},
{
"name": "Prompt",
"value": "Explain {{Topic}}"
}
],
"steps": [
{
"delayMs": 0,
"id": "pa-nested-user-variables-s1",
"param": {
"label": "Start",
"type": "start",
"url": "https://ujiro99.github.io/selection-command/en/test"
},
"skipRenderWait": false
},
{
"delayMs": 500,
"id": "pa-nested-user-variables-s2",
"param": {
"label": "Text input",
"selector": "//input[@placeholder='text input']",
"selectorType": "xpath",
"type": "input",
"value": "{{Prompt}}"
},
"skipRenderWait": false
},
{
"delayMs": 0,
"id": "pa-nested-user-variables-s3",
"param": {
"label": "End",
"type": "end"
},
"skipRenderWait": false
}
]
},
"revision": 0
}
],
"folders": [
Expand Down
28 changes: 14 additions & 14 deletions packages/extension/e2e/generated-command-urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,35 @@ export const COMMAND_URLS: UrlEntry[] = [
{ title: "Netflix", locale: "en", searchUrl: "https://www.netflix.com/search?q=%s" },
{ title: "Pinterest", locale: "en", searchUrl: "https://www.pinterest.com/search/pins/?q=%s" },
{ title: "Drive", locale: "en", searchUrl: "https://drive.google.com/drive/search?q=%s" },
{ title: "Search Commands on Hub", locale: "en", searchUrl: "https://selection-command.com/en?q=%pageUrl" },
{ title: "Search Commands on Hub", locale: "en", searchUrl: "https://selection-command.com/en/commands?q=%pageUrl" },
{ title: "Amazon", locale: "ja", searchUrl: "https://www.amazon.co.jp/s?k=%s" },
{ title: "Yahoo! Japan", locale: "ja", searchUrl: "https://search.yahoo.co.jp/search?p=%s" },
{ title: "en to ja", locale: "ja", searchUrl: "https://translate.google.co.jp/?hl=ja&sl=auto&text=%s&op=translate" },
{ title: "コマンドをHubで検索", locale: "ja", searchUrl: "https://selection-command.com/ja?q=%pageUrl" },
{ title: "コマンドをHubで検索", locale: "ja", searchUrl: "https://selection-command.com/ja/commands?q=%pageUrl" },
{ title: "百度", locale: "zh", searchUrl: "https://www.baidu.com/s?wd=%s" },
{ title: "京东", locale: "zh", searchUrl: "https://search.jd.com/Search?keyword=%s" },
{ title: "哔哩哔哩", locale: "zh", searchUrl: "https://search.bilibili.com/all?keyword=%s" },
{ title: "在 Hub 中搜索命令", locale: "zh", searchUrl: "https://selection-command.com/zh-CN?q=%pageUrl" },
{ title: "在 Hub 中搜索命令", locale: "zh", searchUrl: "https://selection-command.com/zh-CN/commands?q=%pageUrl" },
{ title: "네이버", locale: "ko", searchUrl: "https://search.naver.com/search.naver?query=%s" },
{ title: "Hub에서 명령어 검색", locale: "ko", searchUrl: "https://selection-command.com/ko?q=%pageUrl" },
{ title: "Hub에서 명령어 검색", locale: "ko", searchUrl: "https://selection-command.com/ko/commands?q=%pageUrl" },
{ title: "Яндекс", locale: "ru", searchUrl: "https://yandex.ru/search/?text=%s" },
{ title: "ВКонтакте", locale: "ru", searchUrl: "https://vk.com/search?c%5Bq%5D=%s" },
{ title: "Поиск команд в Hub", locale: "ru", searchUrl: "https://selection-command.com/ru?q=%pageUrl" },
{ title: "Befehle im Hub suchen", locale: "de", searchUrl: "https://selection-command.com/de?q=%pageUrl" },
{ title: "Rechercher des commandes sur Hub", locale: "fr", searchUrl: "https://selection-command.com/fr?q=%pageUrl" },
{ title: "Поиск команд в Hub", locale: "ru", searchUrl: "https://selection-command.com/ru/commands?q=%pageUrl" },
{ title: "Befehle im Hub suchen", locale: "de", searchUrl: "https://selection-command.com/de/commands?q=%pageUrl" },
{ title: "Rechercher des commandes sur Hub", locale: "fr", searchUrl: "https://selection-command.com/fr/commands?q=%pageUrl" },
{ title: "Amazon", locale: "es", searchUrl: "https://www.amazon.es/s?k=%s" },
{ title: "El Corte Inglés", locale: "es", searchUrl: "https://www.elcorteingles.es/search-nwx/?s=%s" },
{ title: "AliExpress", locale: "es", searchUrl: "https://es.aliexpress.com/w/wholesale-%s.html" },
{ title: "Buscar comandos en Hub", locale: "es", searchUrl: "https://selection-command.com/es?q=%pageUrl" },
{ title: "Pesquisar comandos no Hub", locale: "pt-br", searchUrl: "https://selection-command.com/pt-BR?q=%pageUrl" },
{ title: "Pesquisar comandos no Hub", locale: "pt", searchUrl: "https://selection-command.com/pt-PT?q=%pageUrl" },
{ title: "Hub पर कमांड खोजें", locale: "hi", searchUrl: "https://selection-command.com/hi?q=%pageUrl" },
{ title: "Buscar comandos en Hub", locale: "es", searchUrl: "https://selection-command.com/es/commands?q=%pageUrl" },
{ title: "Pesquisar comandos no Hub", locale: "pt-br", searchUrl: "https://selection-command.com/pt-BR/commands?q=%pageUrl" },
{ title: "Pesquisar comandos no Hub", locale: "pt", searchUrl: "https://selection-command.com/pt-PT/commands?q=%pageUrl" },
{ title: "Hub पर कमांड खोजें", locale: "hi", searchUrl: "https://selection-command.com/hi/commands?q=%pageUrl" },
{ title: "Tokopedia", locale: "id", searchUrl: "https://www.tokopedia.com/search?st=product&q=%s" },
{ title: "Shopee", locale: "id", searchUrl: "https://shopee.co.id/search?keyword=%s" },
{ title: "Cari Perintah di Hub", locale: "id", searchUrl: "https://selection-command.com/id?q=%pageUrl" },
{ title: "Cari Perintah di Hub", locale: "id", searchUrl: "https://selection-command.com/id/commands?q=%pageUrl" },
{ title: "Shopee", locale: "ms", searchUrl: "https://shopee.com.my/search?keyword=%s" },
{ title: "Lazada", locale: "ms", searchUrl: "https://www.lazada.com.my/catalog/?q=%s" },
{ title: "Cari Perintah di Hub", locale: "ms", searchUrl: "https://selection-command.com/ms?q=%pageUrl" },
{ title: "Cari Perintah di Hub", locale: "ms", searchUrl: "https://selection-command.com/ms/commands?q=%pageUrl" },
{ title: "Zalando.it", locale: "it", searchUrl: "https://www.zalando.it/catalogo/?q=%s" },
{ title: "Cerca comandi su Hub", locale: "it", searchUrl: "https://selection-command.com/it?q=%pageUrl" },
{ title: "Cerca comandi su Hub", locale: "it", searchUrl: "https://selection-command.com/it/commands?q=%pageUrl" },
]
2 changes: 1 addition & 1 deletion packages/extension/e2e/hub.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ test.describe("Command Hub", () => {

// Assert: navigated to the Hub search page with the visited page's URL as the query.
const hubUrl = new URL(hubPage.url())
expect(hubUrl.origin + hubUrl.pathname).toBe(`${NEW_HUB_URL}/ja`)
expect(hubUrl.origin + hubUrl.pathname).toBe(`${NEW_HUB_URL}/ja/commands`)
expect(hubUrl.searchParams.get("q")).toBe(targetUrl)

// Assert: results are not limited to a single ("News") command — Google and
Expand Down
12 changes: 10 additions & 2 deletions packages/extension/e2e/onboarding-shots.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@ const pathToExtension = path.join(__dirname, "../dist")

type Shot = {
name: string
step: keyof typeof OnboardingStep
// Omitted for shots that should open on whichever screen the variant
// starts at (e.g. variant B's welcome overlay).
step?: keyof typeof OnboardingStep
phase?: StepPhase
variant?: "A" | "B"
}

// One shot per visually distinct screen - not one per StepPhase transition;
// e.g. Step2's WAIT_EXECUTE looks like Step1's, so only Step1 gets it.
const SHOTS: Shot[] = [
{ name: "00-intro", step: "INTRO" },
// Variant B of the onboarding A/B test (see services/experiments): no
// INTRO step, a brief welcome overlay in front of the first step instead.
{ name: "00b-welcome-variant-b", variant: "B" },
{ name: "01-search-explain", step: "SEARCH", phase: StepPhase.EXPLAIN },
{
name: "02-search-wait-execute",
Expand Down Expand Up @@ -90,8 +96,10 @@ test.describe("onboarding screenshots (design review)", () => {
fs.mkdirSync(outDir, { recursive: true })

for (const shot of SHOTS) {
const params = new URLSearchParams({ step: shot.step })
const params = new URLSearchParams()
if (shot.step) params.set("step", shot.step)
if (shot.phase) params.set("phase", shot.phase)
if (shot.variant) params.set("variant", shot.variant)
await page.goto(
`chrome-extension://${extensionId}/src/onboarding_page.html?${params}`,
)
Expand Down
61 changes: 61 additions & 0 deletions packages/extension/e2e/page-action.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,27 @@ async function openRecorder(
return { optionsPage, recorderPage, completeButton }
}

async function runActionCommand(
context: BrowserContext,
page: Page,
commandTitle: string,
): Promise<Page> {
const testPage = new TestPage(page)
await testPage.open()
await testPage.selectText("//h2[contains(text(), 'Browser')]")

const menubar = await testPage.getMenuBar()
await menubar.locator('[title="Action"]').hover()

const [actionPage] = await Promise.all([
context.waitForEvent("page", { timeout: 5000 }),
page.locator(`[role='menuitem'][aria-label='${commandTitle}']`).click(),
])
await actionPage.waitForLoadState("domcontentloaded")

return actionPage
}

test.describe("PageAction Commands", () => {
test.beforeEach(async ({ context, extensionId, getCommands }) => {
const optionsPage = new OptionsPage(context, extensionId, getCommands)
Expand Down Expand Up @@ -290,4 +311,44 @@ test.describe("PageAction Commands", () => {
waitUntil: "domcontentloaded",
})
})

/**
* E2E-47: Verify that built-in variables referenced by a user variable are
* expanded when the PageAction input step executes.
*/
test("E2E-47: PageAction expands built-in variables in a user variable", async ({
context,
page,
}) => {
const actionPage = await runActionCommand(
context,
page,
"User Variable with Built-ins",
)

await expect(
actionPage.locator('input[placeholder="text input"]'),
).toHaveValue(`Selected: Browser / Source: ${TEST_URL}`, {
timeout: 10_000,
})
})

/**
* E2E-48: Verify that a user variable can reference user variables defined
* before it and that the fully expanded value reaches the input step.
*/
test("E2E-48: PageAction expands preceding user variables", async ({
context,
page,
}) => {
const actionPage = await runActionCommand(
context,
page,
"Nested User Variables",
)

await expect(
actionPage.locator('input[placeholder="text input"]'),
).toHaveValue("Explain Topic: Browser", { timeout: 10_000 })
})
})
2 changes: 1 addition & 1 deletion packages/extension/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "__MSG_extName__",
"description": "__MSG_extDescription__",
"version": "1.2.0",
"version": "1.3.0",
"default_locale": "en",
"icons": {
"128": "icon128.png"
Expand Down
3 changes: 2 additions & 1 deletion packages/extension/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@selection-command/extension",
"version": "1.2.0",
"version": "1.3.0",
"private": true,
"author": "ujiro99",
"license": "MIT",
Expand Down Expand Up @@ -59,6 +59,7 @@
"sonner": "git+https://github.com/ujiro99/sonner.git",
"tailwind-merge": "^2.5.4",
"tailwindcss-animate": "^1.0.7",
"tldts": "^7.4.13",
"uuid": "^14.0.0",
"zod": "^3.24.1"
},
Expand Down
Loading
Loading