diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts
index 4a649ece..1a575731 100644
--- a/docs/.vitepress/config.ts
+++ b/docs/.vitepress/config.ts
@@ -8,6 +8,7 @@ import {
prepareTypedocSidebar,
} from './utils/menus';
import { meta, script } from './utils/head';
+import footnote from 'markdown-it-footnote';
import { version as wxtVersion } from '../../packages/wxt/package.json';
import { version as i18nVersion } from '../../packages/i18n/package.json';
import { version as autoIconsVersion } from '../../packages/auto-icons/package.json';
@@ -47,6 +48,12 @@ export default defineConfig({
}),
],
+ markdown: {
+ config: (md) => {
+ md.use(footnote);
+ },
+ },
+
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
logo: {
diff --git a/docs/guide/resources/compare.md b/docs/guide/resources/compare.md
index ef025f7f..88080cb6 100644
--- a/docs/guide/resources/compare.md
+++ b/docs/guide/resources/compare.md
@@ -8,50 +8,59 @@ Lets compare the features of WXT vs [Plasmo](https://docs.plasmo.com/framework)
- 🟡 - Partial support
- ❌ - No support
-| Features | WXT | Plasmo | CRXJS |
-| ------------------------------------------------------- | :--------------: | :-------------: | :--------------: |
-| Supports all browsers | ✅ | ✅ | 🟡 10 |
-| MV2 Support | ✅ | ✅ | 🟡 1 |
-| MV3 Support | ✅ | ✅ | 🟡 1 |
-| Create Extension ZIPs | ✅ | ✅ | ❌ |
-| Create Firefox Sources ZIP | ✅ | ❌ | ❌ |
-| First-class TypeScript support | ✅ | ✅ | ✅ |
-| Entrypoint discovery | ✅ 2 | ✅ 2 | ❌ |
-| Inline entrypoint config | ✅ | ✅ | ❌ 9 |
-| Auto-imports | ✅ | ❌ | ❌ |
-| Reusable module system | ✅ | ❌ | ❌ |
-| Supports all frontend frameworks | ✅ | 🟡 3 | ✅ |
-| Framework specific entrypoints (like `Popup.tsx`) | 🟡 4 | ✅ 5 | ❌ |
-| Automated publishing | ✅ | ✅ | ❌ |
-| Remote Code Bundling (Google Analytics) | ✅ | ✅ | ❌ |
-| Unlisted HTML Pages | ✅ | ✅ | ✅ |
-| Unlisted Scripts | ✅ | ❌ | ❌ |
-| ESM Content Scripts | ❌ 12 | ❌ | ✅ |
-| Dev Mode | | |
-| `.env` Files | ✅ | ✅ | ✅ |
-| Opens browser with extension installed | ✅ | ❌ | ❌ |
-| HMR for UIs | ✅ | 🟡 6 | ✅ |
-| Reload HTML Files on Change | ✅ | 🟡 7 | ✅ |
-| Reload Content Scripts on Change | ✅ | 🟡 7 | ✅ |
-| Reload Background on Change | 🟡 7 | 🟡 7 | 🟡 7 |
-| Respects Content Script `run_at` | ✅ | ✅ | ❌ 8 |
-| Built-in Wrappers | | | |
-| Storage | ✅ | ✅ | ❌ 11 |
-| Messaging | ❌ 11 | ✅ | ❌ 11 |
-| Content Script UI | ✅ | ✅ | ❌ 11 |
-| I18n | ✅ | ❌ | ❌ |
+| Features | WXT | Plasmo | CRXJS |
+| ------------------------------------------------------- | :-----: | :-----: | :-----: |
+| Supports all browsers | ✅ | ✅ | 🟡 [^j] |
+| MV2 Support | ✅ | ✅ | 🟡 [^a] |
+| MV3 Support | ✅ | ✅ | 🟡 [^a] |
+| Create Extension ZIPs | ✅ | ✅ | ❌ |
+| Create Firefox Sources ZIP | ✅ | ❌ | ❌ |
+| First-class TypeScript support | ✅ | ✅ | ✅ |
+| Entrypoint discovery | ✅ [^b] | ✅ [^b] | ❌ |
+| Inline entrypoint config | ✅ | ✅ | ❌ [^i] |
+| Auto-imports | ✅ | ❌ | ❌ |
+| Reusable module system | ✅ | ❌ | ❌ |
+| Supports all frontend frameworks | ✅ | 🟡 [^c] | ✅ |
+| Framework specific entrypoints (like `Popup.tsx`) | 🟡 [^d] | ✅ [^e] | ❌ |
+| Automated publishing | ✅ | ✅ | ❌ |
+| Remote Code Bundling (Google Analytics) | ✅ | ✅ | ❌ |
+| Unlisted HTML Pages | ✅ | ✅ | ✅ |
+| Unlisted Scripts | ✅ | ❌ | ❌ |
+| ESM Content Scripts | ❌ [^l] | ❌ | ✅ |
+| Dev Mode | | | |
+| `.env` Files | ✅ | ✅ | ✅ |
+| Opens browser with extension installed | ✅ | ❌ | ❌ |
+| HMR for UIs | ✅ | 🟡 [^f] | ✅ |
+| Reload HTML Files on Change | ✅ | 🟡 [^g] | ✅ |
+| Reload Content Scripts on Change | ✅ | 🟡 [^g] | ✅ |
+| Reload Background on Change | 🟡 [^g] | 🟡 [^g] | 🟡 [^g] |
+| Respects Content Script `run_at` | ✅ | ✅ | ❌ [^h] |
+| Built-in Wrappers | | | |
+| Storage | ✅ | ✅ | ❌ [^k] |
+| Messaging | ❌ [^k] | ✅ | ❌ [^k] |
+| Content Script UI | ✅ | ✅ | ❌ [^k] |
+| I18n | ✅ | ❌ | ❌ |
-
- 1: Either MV2 or MV3, not both.
-
2: File based.
-
3: Only React, Vue, and Svelte.
-
4: .html .ts .tsx.
-
5: .html .ts .tsx. .vue .svelte.
-
6: React only.
-
7: Reloads entire extension.
-
8: ESM-style loaders run asynchronously.
-
9: Entrypoint options all configured in manifest.json.
-
10: As of v2.0.0-beta.23, but v2 stable hasn't been released yet.
-
11: There is no built-in wrapper around this API. However, you can still access the standard APIs via chrome/browser globals or use any 3rd party NPM package.
-
12: WIP, moving very slowly. Follow wxt-dev/wxt#357 for updates.
-
+[^a]: Either MV2 or MV3, not both.
+
+[^b]: File based.
+
+[^c]: Only React, Vue, and Svelte.
+
+[^d]: `.html`, `.ts`, `.tsx`.
+
+[^e]: `.html`, `.ts`, `.tsx`, `.vue`, `.svelte`.
+
+[^f]: React only.
+
+[^g]: Reloads entire extension.
+
+[^h]: ESM-style loaders run asynchronously.
+
+[^i]: Entrypoint options all configured in `manifest.json`.
+
+[^j]: As of `v2.0.0-beta.23`, but v2 stable hasn't been released yet.
+
+[^k]: There is no built-in wrapper around this API. However, you can still access the standard APIs via `chrome`/`browser` globals or use any 3rd party NPM package.
+
+[^l]: WIP, moving very slowly. Follow [wxt-dev/wxt#357](https://github.com/wxt-dev/wxt/issues/357) for updates.
diff --git a/package.json b/package.json
index 70e7fb10..21ea5945 100644
--- a/package.json
+++ b/package.json
@@ -26,6 +26,7 @@
"fast-glob": "^3.3.2",
"fs-extra": "^11.2.0",
"lint-staged": "^15.2.10",
+ "markdown-it-footnote": "^4.0.0",
"nano-spawn": "^0.1.0",
"prettier": "^3.3.3",
"simple-git-hooks": "^2.11.1",
@@ -51,6 +52,9 @@
"@algolia/client-search",
"search-insights"
]
+ },
+ "patchedDependencies": {
+ "markdown-it-footnote": "patches/markdown-it-footnote.patch"
}
}
}
diff --git a/patches/markdown-it-footnote.md b/patches/markdown-it-footnote.md
new file mode 100644
index 00000000..dc985a62
--- /dev/null
+++ b/patches/markdown-it-footnote.md
@@ -0,0 +1 @@
+Removed sub-ids from rendered links. When you link to the same footnote multiple times, the link would look like `[3.2]` instead of just `[3]`. Didn't like how that looked, so this patch removes that function.
diff --git a/patches/markdown-it-footnote.patch b/patches/markdown-it-footnote.patch
new file mode 100644
index 00000000..2667c4ed
--- /dev/null
+++ b/patches/markdown-it-footnote.patch
@@ -0,0 +1,79 @@
+diff --git a/dist/index.cjs.js b/dist/index.cjs.js
+index 806448c967261a61288f0faa0633a91f77d35968..6812dd84bbbb7176af4115a287677454fa562883 100644
+--- a/dist/index.cjs.js
++++ b/dist/index.cjs.js
+@@ -13,14 +13,14 @@ function render_footnote_anchor_name(tokens, idx, options, env /*, slf */) {
+ }
+ function render_footnote_caption(tokens, idx /*, options, env, slf */) {
+ let n = Number(tokens[idx].meta.id + 1).toString();
+- if (tokens[idx].meta.subId > 0) n += `:${tokens[idx].meta.subId}`;
++ // if (tokens[idx].meta.subId > 0) n += `:${tokens[idx].meta.subId}`;
+ return `[${n}]`;
+ }
+ function render_footnote_ref(tokens, idx, options, env, slf) {
+ const id = slf.rules.footnote_anchor_name(tokens, idx, options, env, slf);
+ const caption = slf.rules.footnote_caption(tokens, idx, options, env, slf);
+ let refid = id;
+- if (tokens[idx].meta.subId > 0) refid += `:${tokens[idx].meta.subId}`;
++ // if (tokens[idx].meta.subId > 0) refid += `:${tokens[idx].meta.subId}`;
+ return `${caption}`;
+ }
+ function render_footnote_block_open(tokens, idx, options) {
+@@ -31,7 +31,7 @@ function render_footnote_block_close() {
+ }
+ function render_footnote_open(tokens, idx, options, env, slf) {
+ let id = slf.rules.footnote_anchor_name(tokens, idx, options, env, slf);
+- if (tokens[idx].meta.subId > 0) id += `:${tokens[idx].meta.subId}`;
++ // if (tokens[idx].meta.subId > 0) id += `:${tokens[idx].meta.subId}`;
+ return `