Skip to content

Commit 4c7f48a

Browse files
feat: Establish CI/CD pipelines and enhance installation documentation.
1 parent ee162dc commit 4c7f48a

File tree

7 files changed

+189
-14
lines changed

7 files changed

+189
-14
lines changed

.github/workflows/ci.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v4
16+
17+
- name: Setup Node.js
18+
uses: actions/setup-node@v4
19+
with:
20+
node-version: '20'
21+
22+
- name: Setup pnpm
23+
uses: pnpm/action-setup@v4
24+
with:
25+
version: 9
26+
27+
- name: Install dependencies
28+
run: pnpm install
29+
30+
- name: Type check
31+
run: pnpm exec tsc --noEmit
32+
33+
- name: Build Chrome extension
34+
run: pnpm build
35+
36+
- name: Build Firefox extension
37+
run: pnpm build:firefox
38+
39+
- name: Upload Chrome build artifact
40+
uses: actions/upload-artifact@v4
41+
with:
42+
name: chrome-extension
43+
path: .output/chrome-mv3/
44+
45+
- name: Upload Firefox build artifact
46+
uses: actions/upload-artifact@v4
47+
with:
48+
name: firefox-extension
49+
path: .output/firefox-mv2/

.github/workflows/release.yml

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- '*.*.*'
7+
- 'v*.*.*'
8+
9+
permissions:
10+
contents: write
11+
12+
jobs:
13+
build-and-release:
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
22+
- name: Setup Node.js
23+
uses: actions/setup-node@v4
24+
with:
25+
node-version: '20'
26+
27+
- name: Setup pnpm
28+
uses: pnpm/action-setup@v4
29+
with:
30+
version: 9
31+
32+
- name: Install dependencies
33+
run: pnpm install
34+
35+
- name: Build Chrome extension
36+
run: pnpm build
37+
38+
- name: Build Firefox extension
39+
run: pnpm build:firefox
40+
41+
- name: Create Chrome zip
42+
run: |
43+
cd .output/chrome-mv3
44+
zip -r ../../textchecker-chrome-${{ github.ref_name }}.zip .
45+
cd ../..
46+
47+
- name: Create Firefox zip
48+
run: |
49+
cd .output/firefox-mv2
50+
zip -r ../../textchecker-firefox-${{ github.ref_name }}.zip .
51+
cd ../..
52+
53+
- name: Generate changelog
54+
id: changelog
55+
run: |
56+
# Get the previous tag
57+
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
58+
59+
if [ -z "$PREV_TAG" ]; then
60+
# First release - get all commits
61+
CHANGELOG=$(git log --pretty=format:"- %s (%h)" --no-merges)
62+
else
63+
# Get commits since last tag
64+
CHANGELOG=$(git log ${PREV_TAG}..HEAD --pretty=format:"- %s (%h)" --no-merges)
65+
fi
66+
67+
# Escape for GitHub Actions
68+
CHANGELOG="${CHANGELOG//'%'/'%25'}"
69+
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
70+
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
71+
72+
echo "changelog=$CHANGELOG" >> $GITHUB_OUTPUT
73+
74+
- name: Create Release
75+
uses: softprops/action-gh-release@v2
76+
with:
77+
name: TextChecker ${{ github.ref_name }}
78+
body: |
79+
## TextChecker ${{ github.ref_name }}
80+
81+
A free, open-source alternative to LanguageTool browser extension.
82+
83+
### Installation
84+
85+
**Chrome / Edge / Brave:**
86+
1. Download `textchecker-chrome-${{ github.ref_name }}.zip`
87+
2. Extract the zip file
88+
3. Go to `chrome://extensions/`
89+
4. Enable "Developer mode"
90+
5. Click "Load unpacked" and select the extracted folder
91+
92+
**Firefox:**
93+
1. Download `textchecker-firefox-${{ github.ref_name }}.zip`
94+
2. Go to `about:debugging#/runtime/this-firefox`
95+
3. Click "Load Temporary Add-on"
96+
4. Select any file from the extracted folder
97+
98+
### Changes
99+
100+
${{ steps.changelog.outputs.changelog }}
101+
102+
---
103+
104+
**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ github.ref_name }}...HEAD
105+
files: |
106+
textchecker-chrome-${{ github.ref_name }}.zip
107+
textchecker-firefox-${{ github.ref_name }}.zip
108+
draft: false
109+
prerelease: false
110+
generate_release_notes: true

README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,26 @@ In January 2025, [LanguageTool announced](https://languagetool.org/de/webextensi
4141

4242
## Installation
4343

44-
### From Source
44+
### Download from Releases (Recommended)
45+
46+
1. Go to the [Releases page](../../releases/latest)
47+
2. Download the zip file for your browser:
48+
- `textchecker-chrome-*.zip` for Chrome, Edge, Brave, Arc
49+
- `textchecker-firefox-*.zip` for Firefox
50+
3. Extract the zip file
51+
52+
**Chrome / Edge / Brave / Arc:**
53+
1. Go to `chrome://extensions/` (or `edge://extensions/`, `brave://extensions/`)
54+
2. Enable "Developer mode" (toggle in top right)
55+
3. Click "Load unpacked"
56+
4. Select the extracted folder
57+
58+
**Firefox:**
59+
1. Go to `about:debugging#/runtime/this-firefox`
60+
2. Click "Load Temporary Add-on"
61+
3. Select any file from the extracted folder
62+
63+
### Build from Source
4564

4665
1. Clone this repository:
4766
```bash

src/entrypoints/popup/App.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useState, useEffect } from 'react';
22
import { settingsStorage, statsStorage } from '@/lib/storage';
3-
import type { Settings, AIProvider } from '@/types';
3+
import type { Settings, AIProvider, CheckMode } from '@/types';
44
import { DEFAULT_SETTINGS } from '@/types';
55
import { Settings as SettingsIcon, Power, Keyboard, Zap, AlertCircle, CheckCircle2 } from 'lucide-react';
66

@@ -40,8 +40,8 @@ export default function App() {
4040
}
4141

4242
async function toggleCheckMode() {
43-
const newMode = settings.checkMode === 'realtime' ? 'ondemand' : 'realtime';
44-
const newSettings = { ...settings, checkMode: newMode };
43+
const newMode: CheckMode = settings.checkMode === 'realtime' ? 'ondemand' : 'realtime';
44+
const newSettings: Settings = { ...settings, checkMode: newMode };
4545
setSettings(newSettings);
4646
await settingsStorage.setValue(newSettings);
4747
}

src/lib/ai/grammar-check.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ export async function checkGrammar(
4545
system: GRAMMAR_CHECK_SYSTEM_PROMPT,
4646
prompt: createGrammarCheckPrompt(text, language),
4747
temperature: 0.1, // Low temperature for consistent results
48-
maxTokens: 2048,
4948
});
5049

5150
// Parse the JSON response
@@ -110,7 +109,6 @@ export async function rewriteText(
110109
system: REWRITE_SYSTEM_PROMPT,
111110
prompt: createRewritePrompt(text, style),
112111
temperature: 0.7, // Higher temperature for creative rewriting
113-
maxTokens: 2048,
114112
});
115113

116114
return rewrittenText.trim();

src/lib/storage.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { DEFAULT_SETTINGS } from '@/types';
44
// Helper to get from sync storage
55
async function getSyncItem<T>(key: string, defaultValue: T): Promise<T> {
66
const result = await browser.storage.sync.get(key);
7-
return result[key] ?? defaultValue;
7+
return (result[key] as T) ?? defaultValue;
88
}
99

1010
// Helper to set sync storage
@@ -15,7 +15,7 @@ async function setSyncItem<T>(key: string, value: T): Promise<void> {
1515
// Helper to get from local storage
1616
async function getLocalItem<T>(key: string, defaultValue: T): Promise<T> {
1717
const result = await browser.storage.local.get(key);
18-
return result[key] ?? defaultValue;
18+
return (result[key] as T) ?? defaultValue;
1919
}
2020

2121
// Helper to set local storage
@@ -32,9 +32,9 @@ export const apiKeysStorage = {
3232
await setSyncItem('apiKeys', value);
3333
},
3434
watch(callback: (value: APIKeys) => void): () => void {
35-
const listener = (changes: { [key: string]: browser.Storage.StorageChange }, areaName: string) => {
35+
const listener = (changes: Record<string, { oldValue?: unknown; newValue?: unknown }>, areaName: string) => {
3636
if (areaName === 'sync' && changes.apiKeys) {
37-
callback(changes.apiKeys.newValue ?? {});
37+
callback((changes.apiKeys.newValue as APIKeys) ?? {});
3838
}
3939
};
4040
browser.storage.onChanged.addListener(listener);
@@ -51,9 +51,9 @@ export const settingsStorage = {
5151
await setSyncItem('settings', value);
5252
},
5353
watch(callback: (value: Settings) => void): () => void {
54-
const listener = (changes: { [key: string]: browser.Storage.StorageChange }, areaName: string) => {
54+
const listener = (changes: Record<string, { oldValue?: unknown; newValue?: unknown }>, areaName: string) => {
5555
if (areaName === 'sync' && changes.settings) {
56-
callback(changes.settings.newValue ?? DEFAULT_SETTINGS);
56+
callback((changes.settings.newValue as Settings) ?? DEFAULT_SETTINGS);
5757
}
5858
};
5959
browser.storage.onChanged.addListener(listener);

tsconfig.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,5 @@
2020
"@/*": ["./src/*"]
2121
}
2222
},
23-
"include": ["src"],
24-
"references": [{ "path": "./.wxt/tsconfig.json" }]
23+
"include": ["src", ".wxt/wxt.d.ts"]
2524
}

0 commit comments

Comments
 (0)