Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/site/coverpage.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

![logo](./ext/blue.svg)
![logo](ext/blue.svg)

# Ghostbird

Expand Down
7 changes: 6 additions & 1 deletion .github/site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@
<meta name="description" content="Ghostbird is a Thunderbird add-on that connects your text editor with Thunderbird's email compose window, allowing you to edit the message in the text editor.">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4.13.1/lib/themes/vue.min.css">
<link rel="icon" href="ext/blue.svg" />
<link rel="icon" href="ext/blue.svg">
<script type="module" src="index.mjs"></script>
</head>
<body>
<nav>
<a href="https://github.com/exteditor/ghostbird/">&#x1faba; GitHub</a>
<a href="#/doc/faq">&#x2753; FAQ</a>
<a href="https://translate.kagi.com/exteditor.github.io/ghostbird/">&#x1f30d; Translation</a>
</nav>
<div id="app"></div>
</body>
</html>
53 changes: 42 additions & 11 deletions .github/site/index.mjs
Original file line number Diff line number Diff line change
@@ -1,21 +1,48 @@
import mermaid from "https://cdn.jsdelivr.net/npm/mermaid@11.12.0/+esm";
import "https://cdn.jsdelivr.net/npm/docsify@4.13.1/+esm";

// @ts-check

mermaid.initialize({ startOnLoad: false });

// see https://docsify.js.org/#/configuration
/**
* Build a URL to a GitHub resource
* @param {string} type The type of resource ('blob' or 'tree')
* @param {string} path Absolute path (/ points to the repository root) to the resource
* @returns {string} The URL to the resource
*/
const urlFor = (type, path) => `https://github.com/exteditor/ghostbird/${type}/main/${encodeURIComponent(path.slice(1))}`;

/**
* Build a Markdown text that redirects to a URL
* @param {string} url The URL to redirect to
* @returns {string} a Markdown text
*/
const redirectTo = (url) => `Redirecting to ${url}...\n\n<script>\nlocation.href = "${url}"${'</'}script>`;

const footer = `____
/**
* Add a footer to the Markdown text
* @param {string} text The Markdown text
* @returns {string} Markdown text with footer added
*/
const addFooter = (text, vm) => `${text}

Powered by [Docsify](https://docsify.js.org/)
____

[▲ Back to Top](#)
[▲ Back to Top](#top)
<div align="right">
Last Update: <a href="${urlFor('blob', vm.route.file)}">{docsify-updated}</a><br>
Powered by <a href="https://docsify.js.org/">Docsify</a>
</div>
`;

// see https://docsify.js.org/#/configuration

window.$docsify = {
name: 'Ghostbird \u{1faba}\u{1f4eb}\u{1f47b}',
repo: 'exteditor/ghostbird',
logo: 'ext/blue.svg',
formatUpdated: '{YYYY}-{MM}-{DD}',
relativePath: true,
executeScript: true,
homepage: "homepage.md",
Expand All @@ -25,12 +52,16 @@ window.$docsify = {
themeColor: '#0b9dd6',
routes: {
['/README'](route) {
let url = `https://github.com/exteditor/ghostbird/blob/main/${encodeURIComponent(route.slice(1))}.md`
return `Redirecting to ${url}...\n\n<script>\nlocation.href = "${url}"${'</'}script>`
let url = urlFor('blob', `${route}.md`)
return redirectTo(url)
},
['/[-._/a-zA-Z]*[.][a-zA-Z]+$'](route) {
let url = urlFor('blob', route)
return redirectTo(url)
},
['/[-._/a-zA-Z]*[.][a-zA-Z]+'](route) {
let url = `https://github.com/exteditor/ghostbird/blob/main/${encodeURIComponent(route.slice(1))}`
return `Redirecting to ${url}...\n\n<script>\nlocation.href = "${url}"${'</'}script>`
['/[-._/a-zA-Z]+/$'](route) {
let url = urlFor('tree', route)
return redirectTo(url)
},
},
search: [
Expand All @@ -53,8 +84,8 @@ window.$docsify = {
}
},
plugins: [
(hook, _vm) => {
hook.beforeEach(html => html + footer);
(hook, vm) => {
hook.beforeEach((text) => addFooter(text, vm));
hook.doneEach(() => mermaid.run());
},
],
Expand Down
4 changes: 2 additions & 2 deletions doc/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ js & copied_ext_files & messages & manifest --> web_ext[["web-ext"]] --> xpi["Ma
- Compiling bundled JavaScript files into `dist/ext/`.
- Running `yarn build-xpi` creates a zip archive named `dist/ghostbird-{version}.xpi`.
- [The `web-ext` tool](https://github.com/mozilla/web-ext#web-ext) does the actual work.
- The usual `yarn build` runs both of the above after running the linter and tests.
- The usual `yarn build`, which is used by the CI, runs both of the above after running the linter and tests.
- `yarn watch` is an alias for `yarn build-js --watch`, which runs the build continuously.

## Build modes
Expand Down Expand Up @@ -111,5 +111,5 @@ The build script assumes four use cases, each using a different source of versio

- Building with `ext/manifest.json` should produce identical results to one from CI in terms of file names and their contents.
- However, they will have different timestamps and file order, meaning Ghostbird builds are not strictly reproducible.
- It would be possible to wipe `mtime`s to produce strictly identical zips, but this was considered pointless as AMO repackages the zip when signing the add-on anyway.
- It would be possible to wipe `mtime`s to produce strictly identical zips, but this was considered pointless as ~~AMO repackages the zip when signing the add-on anyway.~~ **Edit:** It turns out Firefox add-ons are repackaged while Thunderbird add-ons are not, so there may be a point to this after all. PRs welcome.
- See [the issue page for the `web-ext` tool](https://github.com/mozilla/web-ext/issues/2381#issuecomment-1075667618) for details.
36 changes: 21 additions & 15 deletions doc/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ This is how user actions are handled:
* [Barrelsby](https://github.com/bencoveney/barrelsby) generates `index.ts`.
* See [building.md](./building.md) for details on build script internals.

* We rely on GitHub Actions for CI and releases.

## Structure of the code<a id="structure"></a>

The code loosely follows the [Ports and Adapters architecture](https://8thlight.com/insights/a-color-coded-guide-to-ports-and-adapters) and adheres to the [Dependency Inversion Principle](https://en.wikipedia.org/wiki/Dependency_inversion_principle).
Expand All @@ -188,21 +190,21 @@ The code loosely follows the [Ports and Adapters architecture](https://8thlight.

The source code is located in the `src/` directory. The main files are:

- `src/root/background.ts`: A background script that manages the WebSocket connection to the GhostText server and relays messages between the compose script and the server. Bundled as `background.js`.
- `src/root/compose.ts`: A compose script that adds a button to the mail compose window. Bundled as `compose.js`.
- `src/root/options.ts`: An options page for configuring settings such as the server URL and text editor to use. Bundled as `options.js` and used by `ext/options.html`.
- [`src/root/background.ts`][backgroundts]: A background script that manages the WebSocket connection to the GhostText server and relays messages between the compose script and the server. Bundled as `background.js`.
- [`src/root/compose.ts`][composets]: A compose script that adds a button to the mail compose window. Bundled as `compose.js`.
- [`src/root/options.ts`][optionsts]: An options page for configuring settings such as the server URL and text editor to use. Bundled as `options.js` and used by `ext/options.html`.

Other directories are:

- `src/app-background/`: Infrastructure of `background.ts` that handles Thunderbird events.
- `src/app-compose/`: Infrastructure of `compose.ts` that handles Thunderbird events.
- `src/app-options/`: Infrastructure of `options.ts` that handles Thunderbird events.
- `src/ghosttext-session/`: Main module of the add-on implementing the protocol.
- `src/ghosttext-runner/`: Facilitator that works together with `ghosttext-session` which feeds events into it and execute decisions made.
- `src/ghosttext-adaptor/`: Helpers of `ghosttext-runner`.
- `src/test/`: Test code.
- `src/thunderbird/`: Wrapper of the Thunderbird MailExtension API.
- `src/util/`: Utility modules used by multiple modules.
- [`src/app-background/`](../src/app-background/): Infrastructure of [`background.ts`][backgroundts] that handles Thunderbird events.
- [`src/app-compose/`](../src/app-compose/): Infrastructure of [`compose.ts`][composets] that handles Thunderbird events.
- [`src/app-options/`](../src/app-options/): Infrastructure of [`options.ts`][optionsts] that handles Thunderbird events.
- [`src/ghosttext-session/`](../src/ghosttext-session/): Main module of the add-on implementing the protocol.
- [`src/ghosttext-runner/`](../src/ghosttext-runner/): Facilitator that works together with `ghosttext-session` by feeding events into it and execute decisions made.
- [`src/ghosttext-adaptor/`](../src/ghosttext-adaptor/): Helpers of `ghosttext-runner`.
- [`src/test/`](../src/test/): Test code.
- [`src/thunderbird/`](../src/thunderbird/): Wrapper of the Thunderbird MailExtension API.
- [`src/util/`](../src/util/): Utility modules used by multiple modules.

### Module Dependencies

Expand Down Expand Up @@ -274,7 +276,7 @@ options_api & background_api & compose_api -.->|indirectly calls| thunderbird

* `api.ts` defines subsets of the Thunderbird API used by the module in the folder.
* These interfaces are implemented by `thunderbird/` modules.
* This is to isolate the impact of future Thunderbird API changes to `src/thunderbird/` modules only.
* This is to isolate the impact of future Thunderbird API changes to `thunderbird/` modules only.

```mermaid
flowchart TB
Expand All @@ -299,7 +301,7 @@ ghostbird_runner -->|uses| ghostbird_session

TL;DR: `root` module contains entry point and the [Composition Root][ploeh].

* `root/startup/startup_{background,compose,options}.ts` is used at the toplevel modules, namely `background.ts`, `compose.ts`, and `options.ts`. It initializes classes.
* [`root/startup/startup_*.ts`][startupdir] are used at the toplevel modules, namely [`background.ts`][backgroundts], [`compose.ts`][composets], and [`options.ts`][optionsts]. It initializes classes.
* All the non-root classes in the codebase are either:
* A) instantiated by `startup*()`, or
* B) instantiated directly with `new` operator by instances of (A).
Expand All @@ -317,7 +319,7 @@ TL;DR: `root` module contains entry point and the [Composition Root][ploeh].
* A class may define `static aliases: string[] | string` to have the other name.
* Name clashes will result in error at startup, except ones passed to classes with `wantArray = true`.
* Use of automatic instantiation must be restricted to `root/` to make the code easier to follow.
* `test/startup.test.ts` contains tests to verify that all classes registered can be instantiated successfully.
* [`test/startup.test.ts`](../src/test/startup.test.ts) contains tests to verify that all classes registered can be instantiated successfully.
* See [FAQ](./faq-architectural.md) for some design decisions and justification.

```mermaid
Expand Down Expand Up @@ -358,3 +360,7 @@ instantiate_class --> need_instance
[ploeh]: https://blog.ploeh.dk/2019/06/17/composition-root-location/
[wiki]: https://github.com/exteditor/ghostbird/wiki
[so]: https://stackoverflow.com/q/73206468/188256
[startupdir]: ../src/root/startup/
[backgroundts]: ../src/root/background.ts
[composets]: ../src/root/compose.ts
[optionsts]: ../src/root/options.ts
6 changes: 3 additions & 3 deletions doc/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@

### Why not use External Editor Revived as a base?

(For those who don't know: [External Editor Revived by @Frederick888](https://github.com/Frederick888/external-editor-revived) is an add-on for Thunderbird that lets you edit email text in an external text editor, which works in recent Thunderbird versions and is actively maintained)
(For those who don't know: [External Editor Revived by @Frederick888](https://github.com/Frederick888/external-editor-revived) is an add-on for Thunderbird that lets you edit email text in an external text editor, which works in recent Thunderbird versions and is well-maintained)

* I started working on Ghostbird while mostly offline. Had I known about ERR's existence, Ghostbird wouldn't exist now!
* ERR works using [Native Messaging](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging), which is the only way to launch external process in recent Thunderbird API. It requires a companion app to be installed and registered as a Native Messaging Host. See [ERR's Wiki pages](https://github.com/Frederick888/external-editor-revived/wiki) for details.
* Reasons to continue developing Ghostbird? I think GhostText's live updating functionality is pretty (for now; there is no fundamental reason ERR can't do the same).
* That said, I think you should try ERR before using Ghostbird, which is still in alpha, as ERR is more mature and already on [AMO][revived].
* That said, I think you should try ERR before using Ghostbird, which is still in beta, as ERR is more mature and already listed on [AMO][revived] as a stable extension.

[![External Editor Revived](https://raw.githubusercontent.com/thunderbird/webext-support/refs/heads/master/images/get-the-addon.svg)][revived]

Expand All @@ -106,7 +106,7 @@

### Why Yarn?

* I love cats, and Yarn has [a cat logo](https://github.com/yarnpkg/assets).
* I love cats, and Yarn has [a cat logo](https://github.com/yarnpkg/assets#yarn-assets).

### How do you build this add-on?

Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"engines": {
"thunderbird": ">= 128"
},
"homepage": "https://github.com/exteditor/ghostbird/",
"homepage": "https://exteditor.github.io/ghostbird/",
"bugs": "https://github.com/exteditor/ghostbird/issues/",
"funding": "https://give.thunderbird.net/",
"repository": {
"type": "git",
"url": "github:exteditor/ghostbird"
Expand Down