Skip to content
Open
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
34 changes: 34 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
{
"name": "Node.js & TypeScript",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/typescript-node:1-18-bookworm",
"features": {
"ghcr.io/devcontainers-extra/features/apt-packages:1": {
"clean_ppas": true,
"preserve_apt_list": true,
"packages": "xvfb,xauth",
"ppas": "ppa:deadsnakes/ppa"
},
"ghcr.io/devcontainers/features/git-lfs:1": {
"autoPull": true,
"version": "latest"
}
},

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "npm install && sudo npx playwright install-deps && npx playwright install",

// Configure tool-specific properties.
// "customizations": {},

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
48 changes: 48 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Copilot instructions (LinkHints)

## Big picture
- This is a WebExtension built from TypeScript (+ some Preact UIs). Source lives in `src/`.
- Rollup builds everything into `compiled/` (Sucrase strips TS/JSX). `tsc` is used for type-checking only.
- Build/entrypoint mapping is centralized in `project.config.ts` and consumed by `rollup.config.js`.

## Key modules
- `src/background/`: the "hub" (state machine + orchestration). See `src/background/Program.ts`.
- `src/worker/`: content script loaded in every frame; captures keypresses and finds/report elements.
- `src/renderer/`: top-frame content script; renders hints/underlines (shadow DOM container).
- `src/options/` and `src/popup/`: Preact UIs.
- `src/shared/`: shared types/helpers; message schema in `src/shared/messages.ts`.
- `docs/` → `compiled-docs/`: website sources.
- `tests/`: automated e2e tests using Playwright; configured via `playwright.config.ts`.

## Program + messaging model (core convention)
- Each subsystem has a `Program` class in `src/*/Program.ts(x)` and a tiny bootstrap in `src/*/main.ts(x)`.
- Subsystems communicate via `browser.runtime` messages; **background is the router**.
- Message types are discriminated unions in `src/shared/messages.ts` (`ToBackground`, `FromBackground`, plus nested `ToWorker`, `FromWorker`, etc.).
- Each `Program` typically defines a local `wrapMessage(...)` helper to wrap its inner message into `ToBackground`.

## Shared utilities you should use
- Listener lifecycle + error logging: `addListener`, `addEventListener`, and `Resets` in `src/shared/main.ts`.
- Logging: `log(...)` in `src/shared/main.ts` (programs update `log.level` via StateSync).
- Build-time globals are injected by Rollup and typed in `@types/globals.d.ts` (`BROWSER`, `PROD`, `META_*`, `COLOR_*`, `DEFAULT_*`). Don’t try to “import config” for these.

## Generated outputs (don’t edit)
- Do not edit `compiled/`, `compiled-docs/`, or `dist-*`.
- Template generators called by Rollup:
- `src/manifest.ts` → `compiled/manifest.json`
- `src/html.tsx` → minimal HTML shells in `compiled/`
- `src/icons.tsx` (+ `src/icons/`) → icons; update PNGs via `npm run png-icons`
- `src/css.ts` → injects colors from `project.config.ts` into CSS

## Developer workflows (exact commands)
- Install: `npm ci`
- Type-check/lint/format check/build: `npm test`
- Run e2e tests: `npm run test:playwright`
- Build once (writes `compiled/`): `npm run compile`
- Watch build: `npm run watch`
- Run extension (auto-reloads on `compiled/` changes): `npm run firefox` / `npm run chrome`
- Shortcut to run watch + both browsers: `npm start`

## Change guidance (repo-specific)
- If you add/change a cross-component action, update `src/shared/messages.ts` and both sender/receiver `Program.ts` switch handling.
- Keep message payloads JSON-serializable; prefer discriminated unions over ad-hoc objects.
- When changing extension behavior, update or add tests in `tests/` to verify the changes.
82 changes: 75 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ name: CI

on:
push:
branches:
- "main"
pull_request:

permissions:
Expand All @@ -12,7 +10,8 @@ permissions:
id-token: write

jobs:
build:
deploy:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
Expand Down Expand Up @@ -42,16 +41,85 @@ jobs:
run: npm test

- name: Setup Pages
if: github.ref == 'refs/heads/main'
uses: actions/configure-pages@v2

- name: Upload artifact
if: github.ref == 'refs/heads/main'
uses: actions/upload-pages-artifact@v1
uses: actions/upload-pages-artifact@v3
with:
path: compiled-docs

- name: Deploy to GitHub Pages
if: github.ref == 'refs/heads/main'
id: deployment
uses: actions/deploy-pages@v1

check:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18.x

- name: Cache node_modules
id: cache-node_modules
uses: actions/cache@v3
with:
path: node_modules
key: node_modules-${{ hashFiles('package.json', 'package-lock.json') }}

- name: npm ci
if: steps.cache-node_modules.outputs.cache-hit != 'true'
run: npm ci

- name: npm test
run: npm test

test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18.x

- name: Cache node_modules
id: cache-node_modules
uses: actions/cache@v3
with:
path: node_modules
key: node_modules-${{ hashFiles('package.json', 'package-lock.json') }}

- name: Cache Playwright browsers
uses: actions/cache@v3
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }}

- name: npm ci
if: steps.cache-node_modules.outputs.cache-hit != 'true'
run: npm ci

- name: Install xvfb
run: sudo apt-get update && sudo apt-get install -y xvfb

- name: Install playwright dependencies
run: sudo npx playwright install-deps

- name: Install Playwright browsers
run: npx playwright install

- name: Run Playwright tests
run: xvfb-run -a npm run test:playwright

- name: Upload test results
uses: actions/upload-artifact@v6
with:
name: test-results
path: test-results/
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
.eslintcache
custom.config.cjs
/custom.config.cjs
/node_modules/
/compiled/
/compiled*/
/compiled-docs/
/dist*/
/test-results
/.tool-versions
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
*.custom.js
/compiled/
/compiled-docs/
/test-results/
/tests/*-snapshots/
*.json
/rollup.config-*.js
10 changes: 10 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ It is recommended to set up [TypeScript], [ESLint] and [Prettier] integrations i

See `package.json` for details and additional scripts.

### Automated Testing

To run the automated end-to-end tests using Playwright:

```
npm run test:playwright
```

This will compile the extension and run tests in Firefox, verifying functionality like the tutorial workflow.

### Chrome and Firefox

Open Chrome/Firefox, with a new profile where Link Hints is pre-installed:
Expand Down
107 changes: 107 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading